aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs122
-rw-r--r--OpenSim/Framework/Servers/VersionInfo.cs2
-rw-r--r--OpenSim/Framework/TaskInventoryDictionary.cs111
-rw-r--r--OpenSim/Framework/Util.cs26
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs87
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs27
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs107
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs53
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs27
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs21
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs23
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs8
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs26
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs551
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs70
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs379
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs286
-rw-r--r--OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs20
-rw-r--r--OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs6
-rw-r--r--OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs5
-rw-r--r--OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs20
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsActor.cs13
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODECharacter.cs22
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs20
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODEPrim.cs93
-rw-r--r--OpenSim/Region/Physics/POSPlugin/POSCharacter.cs21
-rw-r--r--OpenSim/Region/Physics/POSPlugin/POSPrim.cs20
-rw-r--r--OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs44
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs565
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs36
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs261
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs5
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs418
-rw-r--r--bin/OpenSim.ini.example3
38 files changed, 2337 insertions, 1171 deletions
diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
index adf7967..b22003c 100644
--- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
+++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
@@ -123,6 +123,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
123 availableMethods["admin_region_query"] = XmlRpcRegionQueryMethod; 123 availableMethods["admin_region_query"] = XmlRpcRegionQueryMethod;
124 availableMethods["admin_shutdown"] = XmlRpcShutdownMethod; 124 availableMethods["admin_shutdown"] = XmlRpcShutdownMethod;
125 availableMethods["admin_broadcast"] = XmlRpcAlertMethod; 125 availableMethods["admin_broadcast"] = XmlRpcAlertMethod;
126 availableMethods["admin_dialog"] = XmlRpcDialogMethod;
126 availableMethods["admin_restart"] = XmlRpcRestartMethod; 127 availableMethods["admin_restart"] = XmlRpcRestartMethod;
127 availableMethods["admin_load_heightmap"] = XmlRpcLoadHeightmapMethod; 128 availableMethods["admin_load_heightmap"] = XmlRpcLoadHeightmapMethod;
128 // User management 129 // User management
@@ -212,9 +213,59 @@ namespace OpenSim.ApplicationPlugins.RemoteController
212 if (!m_app.SceneManager.TryGetScene(regionID, out rebootedScene)) 213 if (!m_app.SceneManager.TryGetScene(regionID, out rebootedScene))
213 throw new Exception("region not found"); 214 throw new Exception("region not found");
214 215
216 int timeout = 30000;
217 string message;
218
219 if (requestData.ContainsKey("restart")
220 && ((string)requestData["restart"] == "delayed")
221 && requestData.ContainsKey("milliseconds"))
222 {
223 timeout = Int32.Parse(requestData["milliseconds"].ToString());
224
225 if (timeout < 15000)
226 {
227 //It must be at least 15 seconds or we'll cancel the reboot request
228 timeout = 15000;
229 }
230
231 message
232 = "Region is restarting in " + ((int)(timeout / 1000)).ToString()
233 + " second(s). Please save what you are doing and log out.";
234 }
235 else
236 {
237 message = "Region is restarting in 30 second(s). Please save what you are doing and log out.";
238 }
239
240 if (requestData.ContainsKey("noticetype")
241 && ((string)requestData["noticetype"] == "dialog"))
242 {
243 m_app.SceneManager.ForEachScene(
244 delegate(Scene scene)
245 {
246 IDialogModule dialogModule = scene.RequestModuleInterface<IDialogModule>();
247 if (dialogModule != null)
248 dialogModule.SendNotificationToUsersInRegion(UUID.Zero, "System", message);
249 });
250 }
251 else
252 {
253 if (!requestData.ContainsKey("noticetype")
254 || ((string)requestData["noticetype"] != "none"))
255 {
256 m_app.SceneManager.ForEachScene(
257 delegate(Scene scene)
258 {
259 IDialogModule dialogModule = scene.RequestModuleInterface<IDialogModule>();
260 if (dialogModule != null)
261 dialogModule.SendGeneralAlert(message);
262 });
263 }
264 }
265
215 responseData["rebooting"] = true; 266 responseData["rebooting"] = true;
216 response.Value = responseData; 267 response.Value = responseData;
217 rebootedScene.Restart(30); 268 rebootedScene.Restart(timeout / 1000,false);
218 } 269 }
219 catch (Exception e) 270 catch (Exception e)
220 { 271 {
@@ -277,6 +328,53 @@ namespace OpenSim.ApplicationPlugins.RemoteController
277 m_log.Info("[RADMIN]: Alert request complete"); 328 m_log.Info("[RADMIN]: Alert request complete");
278 return response; 329 return response;
279 } 330 }
331 public XmlRpcResponse XmlRpcDialogMethod(XmlRpcRequest request, IPEndPoint remoteClient)
332 {
333 XmlRpcResponse response = new XmlRpcResponse();
334 Hashtable responseData = new Hashtable();
335
336 m_log.Info("[RADMIN]: Dialog request started");
337
338 try
339 {
340 Hashtable requestData = (Hashtable)request.Params[0];
341
342 checkStringParameters(request, new string[] { "password", "from", "message" });
343
344 if (m_requiredPassword != String.Empty &&
345 (!requestData.Contains("password") || (string)requestData["password"] != m_requiredPassword))
346 throw new Exception("wrong password");
347
348 string message = (string)requestData["message"];
349 string fromuuid = (string)requestData["from"];
350 m_log.InfoFormat("[RADMIN]: Broadcasting: {0}", message);
351
352 responseData["accepted"] = true;
353 responseData["success"] = true;
354 response.Value = responseData;
355
356 m_app.SceneManager.ForEachScene(
357 delegate(Scene scene)
358 {
359 IDialogModule dialogModule = scene.RequestModuleInterface<IDialogModule>();
360 if (dialogModule != null)
361 dialogModule.SendNotificationToUsersInRegion(UUID.Zero, fromuuid, message);
362 });
363 }
364 catch (Exception e)
365 {
366 m_log.ErrorFormat("[RADMIN]: Broadcasting: failed: {0}", e.Message);
367 m_log.DebugFormat("[RADMIN]: Broadcasting: failed: {0}", e.ToString());
368
369 responseData["accepted"] = false;
370 responseData["success"] = false;
371 responseData["error"] = e.Message;
372 response.Value = responseData;
373 }
374
375 m_log.Info("[RADMIN]: Alert request complete");
376 return response;
377 }
280 378
281 public XmlRpcResponse XmlRpcLoadHeightmapMethod(XmlRpcRequest request, IPEndPoint remoteClient) 379 public XmlRpcResponse XmlRpcLoadHeightmapMethod(XmlRpcRequest request, IPEndPoint remoteClient)
282 { 380 {
@@ -384,13 +482,33 @@ namespace OpenSim.ApplicationPlugins.RemoteController
384 message = "Region is going down now."; 482 message = "Region is going down now.";
385 } 483 }
386 484
387 m_app.SceneManager.ForEachScene( 485 if (requestData.ContainsKey("noticetype")
486 && ((string) requestData["noticetype"] == "dialog"))
487 {
488 m_app.SceneManager.ForEachScene(
388 delegate(Scene scene) 489 delegate(Scene scene)
389 { 490 {
390 IDialogModule dialogModule = scene.RequestModuleInterface<IDialogModule>(); 491 IDialogModule dialogModule = scene.RequestModuleInterface<IDialogModule>();
391 if (dialogModule != null) 492 if (dialogModule != null)
493 dialogModule.SendNotificationToUsersInRegion(UUID.Zero, "System", message);
494 });
495 }
496 else
497 {
498 if (!requestData.ContainsKey("noticetype")
499 || ((string)requestData["noticetype"] != "none"))
500 {
501 m_app.SceneManager.ForEachScene(
502 delegate(Scene scene)
503 {
504 IDialogModule dialogModule = scene.RequestModuleInterface<IDialogModule>();
505 if (dialogModule != null)
392 dialogModule.SendGeneralAlert(message); 506 dialogModule.SendGeneralAlert(message);
393 }); 507 });
508 }
509 }
510
511
394 512
395 // Perform shutdown 513 // Perform shutdown
396 System.Timers.Timer shutdownTimer = new System.Timers.Timer(timeout); // Wait before firing 514 System.Timers.Timer shutdownTimer = new System.Timers.Timer(timeout); // Wait before firing
diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs
index ec94b2d..0d4215b 100644
--- a/OpenSim/Framework/Servers/VersionInfo.cs
+++ b/OpenSim/Framework/Servers/VersionInfo.cs
@@ -29,7 +29,7 @@ namespace OpenSim
29{ 29{
30 public class VersionInfo 30 public class VersionInfo
31 { 31 {
32 private const string VERSION_NUMBER = "0.6.9"; 32 private const string VERSION_NUMBER = "0.6.9-CM";
33 private const Flavour VERSION_FLAVOUR = Flavour.Dev; 33 private const Flavour VERSION_FLAVOUR = Flavour.Dev;
34 34
35 public enum Flavour 35 public enum Flavour
diff --git a/OpenSim/Framework/TaskInventoryDictionary.cs b/OpenSim/Framework/TaskInventoryDictionary.cs
index 25ae6b0..efe5f0c 100644
--- a/OpenSim/Framework/TaskInventoryDictionary.cs
+++ b/OpenSim/Framework/TaskInventoryDictionary.cs
@@ -27,9 +27,12 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Threading;
31using System.Reflection;
30using System.Xml; 32using System.Xml;
31using System.Xml.Schema; 33using System.Xml.Schema;
32using System.Xml.Serialization; 34using System.Xml.Serialization;
35using log4net;
33using OpenMetaverse; 36using OpenMetaverse;
34 37
35namespace OpenSim.Framework 38namespace OpenSim.Framework
@@ -45,6 +48,105 @@ namespace OpenSim.Framework
45 // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 48 // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 49
47 private static XmlSerializer tiiSerializer = new XmlSerializer(typeof (TaskInventoryItem)); 50 private static XmlSerializer tiiSerializer = new XmlSerializer(typeof (TaskInventoryItem));
51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52
53 private Thread LockedByThread;
54 /// <value>
55 /// An advanced lock for inventory data
56 /// </value>
57 private System.Threading.ReaderWriterLockSlim m_itemLock = new System.Threading.ReaderWriterLockSlim();
58
59 /// <summary>
60 /// Are we readlocked by the calling thread?
61 /// </summary>
62 public bool IsReadLockedByMe()
63 {
64 if (m_itemLock.RecursiveReadCount > 0)
65 {
66 return true;
67 }
68 else
69 {
70 return false;
71 }
72 }
73
74 /// <summary>
75 /// Lock our inventory list for reading (many can read, one can write)
76 /// </summary>
77 public void LockItemsForRead(bool locked)
78 {
79 if (locked)
80 {
81 if (m_itemLock.IsWriteLockHeld && LockedByThread != null)
82 {
83 if (!LockedByThread.IsAlive)
84 {
85 //Locked by dead thread, reset.
86 m_itemLock = new System.Threading.ReaderWriterLockSlim();
87 }
88 }
89
90 if (m_itemLock.RecursiveReadCount > 0)
91 {
92 m_log.Error("[TaskInventoryDictionary] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
93 m_itemLock.ExitReadLock();
94 }
95 if (m_itemLock.RecursiveWriteCount > 0)
96 {
97 m_log.Error("[TaskInventoryDictionary] Recursive write lock requested. This should not happen and means something needs to be fixed.");
98 m_itemLock.ExitWriteLock();
99 }
100
101 while (!m_itemLock.TryEnterReadLock(60000))
102 {
103 m_log.Error("Thread lock detected while trying to aquire READ lock in TaskInventoryDictionary. Locked by thread " + LockedByThread.Name + ". I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
104 if (m_itemLock.IsWriteLockHeld)
105 {
106 m_itemLock = new System.Threading.ReaderWriterLockSlim();
107 }
108 }
109 }
110 else
111 {
112 m_itemLock.ExitReadLock();
113 }
114 }
115
116 /// <summary>
117 /// Lock our inventory list for writing (many can read, one can write)
118 /// </summary>
119 public void LockItemsForWrite(bool locked)
120 {
121 if (locked)
122 {
123 //Enter a write lock, wait indefinately for one to open.
124 if (m_itemLock.RecursiveReadCount > 0)
125 {
126 m_log.Error("[TaskInventoryDictionary] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
127 m_itemLock.ExitReadLock();
128 }
129 if (m_itemLock.RecursiveWriteCount > 0)
130 {
131 m_log.Error("[TaskInventoryDictionary] Recursive write lock requested. This should not happen and means something needs to be fixed.");
132 m_itemLock.ExitWriteLock();
133 }
134 while (!m_itemLock.TryEnterWriteLock(60000))
135 {
136 m_log.Error("Thread lock detected while trying to aquire WRITE lock in TaskInventoryDictionary. Locked by thread " + LockedByThread.Name + ". I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
137 if (m_itemLock.IsWriteLockHeld)
138 {
139 m_itemLock = new System.Threading.ReaderWriterLockSlim();
140 }
141 }
142
143 LockedByThread = Thread.CurrentThread;
144 }
145 else
146 {
147 m_itemLock.ExitWriteLock();
148 }
149 }
48 150
49 #region ICloneable Members 151 #region ICloneable Members
50 152
@@ -52,13 +154,12 @@ namespace OpenSim.Framework
52 { 154 {
53 TaskInventoryDictionary clone = new TaskInventoryDictionary(); 155 TaskInventoryDictionary clone = new TaskInventoryDictionary();
54 156
55 lock (this) 157 m_itemLock.EnterReadLock();
158 foreach (UUID uuid in Keys)
56 { 159 {
57 foreach (UUID uuid in Keys) 160 clone.Add(uuid, (TaskInventoryItem) this[uuid].Clone());
58 {
59 clone.Add(uuid, (TaskInventoryItem) this[uuid].Clone());
60 }
61 } 161 }
162 m_itemLock.ExitReadLock();
62 163
63 return clone; 164 return clone;
64 } 165 }
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 1112497..b5e2872 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -990,19 +990,19 @@ namespace OpenSim.Framework
990 { 990 {
991 string os = String.Empty; 991 string os = String.Empty;
992 992
993 if (Environment.OSVersion.Platform != PlatformID.Unix) 993// if (Environment.OSVersion.Platform != PlatformID.Unix)
994 { 994// {
995 os = Environment.OSVersion.ToString(); 995// os = Environment.OSVersion.ToString();
996 } 996// }
997 else 997// else
998 { 998// {
999 os = ReadEtcIssue(); 999// os = ReadEtcIssue();
1000 } 1000// }
1001 1001//
1002 if (os.Length > 45) 1002// if (os.Length > 45)
1003 { 1003// {
1004 os = os.Substring(0, 45); 1004// os = os.Substring(0, 45);
1005 } 1005// }
1006 1006
1007 return os; 1007 return os;
1008 } 1008 }
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index ffe6fe9..e812945 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -785,6 +785,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
785 public virtual void SendLayerData(float[] map) 785 public virtual void SendLayerData(float[] map)
786 { 786 {
787 Util.FireAndForget(DoSendLayerData, map); 787 Util.FireAndForget(DoSendLayerData, map);
788
789 // Send it sync, and async. It's not that much data
790 // and it improves user experience just so much!
791 DoSendLayerData(map);
788 } 792 }
789 793
790 /// <summary> 794 /// <summary>
@@ -797,16 +801,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
797 801
798 try 802 try
799 { 803 {
800 //for (int y = 0; y < 16; y++) 804 for (int y = 0; y < 16; y++)
801 //{ 805 {
802 // for (int x = 0; x < 16; x++) 806 for (int x = 0; x < 16; x+=4)
803 // { 807 {
804 // SendLayerData(x, y, map); 808 SendLayerPacket(x, y, map);
805 // } 809 }
806 //} 810 }
807
808 // Send LayerData in a spiral pattern. Fun!
809 SendLayerTopRight(map, 0, 0, 15, 15);
810 } 811 }
811 catch (Exception e) 812 catch (Exception e)
812 { 813 {
@@ -814,51 +815,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
814 } 815 }
815 } 816 }
816 817
817 private void SendLayerTopRight(float[] map, int x1, int y1, int x2, int y2)
818 {
819 // Row
820 for (int i = x1; i <= x2; i++)
821 SendLayerData(i, y1, map);
822
823 // Column
824 for (int j = y1 + 1; j <= y2; j++)
825 SendLayerData(x2, j, map);
826
827 if (x2 - x1 > 0)
828 SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2);
829 }
830
831 void SendLayerBottomLeft(float[] map, int x1, int y1, int x2, int y2)
832 {
833 // Row in reverse
834 for (int i = x2; i >= x1; i--)
835 SendLayerData(i, y2, map);
836
837 // Column in reverse
838 for (int j = y2 - 1; j >= y1; j--)
839 SendLayerData(x1, j, map);
840
841 if (x2 - x1 > 0)
842 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
843 }
844
845 /// <summary> 818 /// <summary>
846 /// Sends a set of four patches (x, x+1, ..., x+3) to the client 819 /// Sends a set of four patches (x, x+1, ..., x+3) to the client
847 /// </summary> 820 /// </summary>
848 /// <param name="map">heightmap</param> 821 /// <param name="map">heightmap</param>
849 /// <param name="px">X coordinate for patches 0..12</param> 822 /// <param name="px">X coordinate for patches 0..12</param>
850 /// <param name="py">Y coordinate for patches 0..15</param> 823 /// <param name="py">Y coordinate for patches 0..15</param>
851 // private void SendLayerPacket(float[] map, int y, int x) 824 private void SendLayerPacket(int x, int y, float[] map)
852 // { 825 {
853 // int[] patches = new int[4]; 826 int[] patches = new int[4];
854 // patches[0] = x + 0 + y * 16; 827 patches[0] = x + 0 + y * 16;
855 // patches[1] = x + 1 + y * 16; 828 patches[1] = x + 1 + y * 16;
856 // patches[2] = x + 2 + y * 16; 829 patches[2] = x + 2 + y * 16;
857 // patches[3] = x + 3 + y * 16; 830 patches[3] = x + 3 + y * 16;
858 831
859 // Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); 832 float[] heightmap = (map.Length == 65536) ?
860 // OutPacket(layerpack, ThrottleOutPacketType.Land); 833 map :
861 // } 834 LLHeightFieldMoronize(map);
835
836 try
837 {
838 Packet layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
839 OutPacket(layerpack, ThrottleOutPacketType.Land);
840 }
841 catch
842 {
843 for (int px = x ; px < x + 4 ; px++)
844 SendLayerData(px, y, map);
845 }
846 }
862 847
863 /// <summary> 848 /// <summary>
864 /// Sends a specified patch to a client 849 /// Sends a specified patch to a client
@@ -3136,7 +3121,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3136 3121
3137 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; 3122 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
3138 objupdate.ObjectData[0] = CreateAvatarUpdateBlock(data); 3123 objupdate.ObjectData[0] = CreateAvatarUpdateBlock(data);
3139
3140 OutPacket(objupdate, ThrottleOutPacketType.Task); 3124 OutPacket(objupdate, ThrottleOutPacketType.Task);
3141 } 3125 }
3142 3126
@@ -3187,8 +3171,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3187 terse.ObjectData[i] = m_avatarTerseUpdates.Dequeue(); 3171 terse.ObjectData[i] = m_avatarTerseUpdates.Dequeue();
3188 } 3172 }
3189 3173
3190 // HACK: Using the task category until the tiered reprioritization code is in 3174 OutPacket(terse, ThrottleOutPacketType.State);
3191 OutPacket(terse, ThrottleOutPacketType.Task);
3192 } 3175 }
3193 3176
3194 public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations) 3177 public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index 338f2bb..85961b9 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -402,6 +402,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
402 #region Queue or Send 402 #region Queue or Send
403 403
404 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category); 404 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category);
405 outgoingPacket.Type = type;
405 406
406 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket)) 407 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket))
407 SendPacketFinal(outgoingPacket); 408 SendPacketFinal(outgoingPacket);
@@ -513,6 +514,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
513 byte flags = buffer.Data[0]; 514 byte flags = buffer.Data[0];
514 bool isResend = (flags & Helpers.MSG_RESENT) != 0; 515 bool isResend = (flags & Helpers.MSG_RESENT) != 0;
515 bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0; 516 bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0;
517 bool sendSynchronous = false;
516 LLUDPClient udpClient = outgoingPacket.Client; 518 LLUDPClient udpClient = outgoingPacket.Client;
517 519
518 if (!udpClient.IsConnected) 520 if (!udpClient.IsConnected)
@@ -568,9 +570,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
568 if (isReliable) 570 if (isReliable)
569 Interlocked.Add(ref udpClient.UnackedBytes, outgoingPacket.Buffer.DataLength); 571 Interlocked.Add(ref udpClient.UnackedBytes, outgoingPacket.Buffer.DataLength);
570 572
571 // Put the UDP payload on the wire 573 //Some packet types need to be sent synchonously.
572 AsyncBeginSend(buffer); 574 //Sorry, i know it's not optimal, but until the LL client
575 //manages packets correctly and re-orders them as required, this is necessary.
573 576
577
578 // Put the UDP payload on the wire
579 if (outgoingPacket.Type == PacketType.ImprovedTerseObjectUpdate)
580 {
581 SyncBeginPrioritySend(buffer, 2); // highest priority
582 }
583 else if (outgoingPacket.Type == PacketType.ObjectUpdate
584 || outgoingPacket.Type == PacketType.LayerData)
585 {
586 SyncBeginPrioritySend(buffer, 1); // medium priority
587 }
588 else
589 {
590 SyncBeginPrioritySend(buffer, 0); // normal priority
591 }
592
593 //AsyncBeginSend(buffer);
594
574 // Keep track of when this packet was sent out (right now) 595 // Keep track of when this packet was sent out (right now)
575 outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue; 596 outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue;
576 } 597 }
@@ -851,7 +872,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
851 872
852 Buffer.BlockCopy(packetData, 0, buffer.Data, 0, length); 873 Buffer.BlockCopy(packetData, 0, buffer.Data, 0, length);
853 874
854 AsyncBeginSend(buffer); 875 SyncBeginPrioritySend(buffer, 1); //Setting this to a medium priority should help minimise resends
855 } 876 }
856 877
857 private bool IsClientAuthorized(UseCircuitCodePacket useCircuitCode, out AuthenticateResponse sessionInfo) 878 private bool IsClientAuthorized(UseCircuitCodePacket useCircuitCode, out AuthenticateResponse sessionInfo)
diff --git a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs
index d2779ba..de2cd24 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs
@@ -29,6 +29,7 @@ using System;
29using System.Net; 29using System.Net;
30using System.Net.Sockets; 30using System.Net.Sockets;
31using System.Threading; 31using System.Threading;
32using System.Collections.Generic;
32using log4net; 33using log4net;
33 34
34namespace OpenMetaverse 35namespace OpenMetaverse
@@ -52,12 +53,30 @@ namespace OpenMetaverse
52 /// <summary>Local IP address to bind to in server mode</summary> 53 /// <summary>Local IP address to bind to in server mode</summary>
53 protected IPAddress m_localBindAddress; 54 protected IPAddress m_localBindAddress;
54 55
56 /// <summary>
57 /// Standard queue for our outgoing SyncBeginPrioritySend
58 /// </summary>
59 private List<UDPPacketBuffer> m_standardQueue = new List<UDPPacketBuffer>();
60
61 /// <summary>
62 /// Medium priority queue for our outgoing SyncBeginPrioritySend
63 /// </summary>
64 private List<UDPPacketBuffer> m_mediumPriorityQueue = new List<UDPPacketBuffer>();
65
66 /// <summary>
67 /// Prioritised queue for our outgoing SyncBeginPrioritySend
68 /// </summary>
69 private List<UDPPacketBuffer> m_priorityQueue = new List<UDPPacketBuffer>();
70
55 /// <summary>UDP socket, used in either client or server mode</summary> 71 /// <summary>UDP socket, used in either client or server mode</summary>
56 private Socket m_udpSocket; 72 private Socket m_udpSocket;
57 73
58 /// <summary>Flag to process packets asynchronously or synchronously</summary> 74 /// <summary>Flag to process packets asynchronously or synchronously</summary>
59 private bool m_asyncPacketHandling; 75 private bool m_asyncPacketHandling;
60 76
77 /// <summary>Are we currently sending data asynchronously?</summary>
78 private volatile bool m_sendingData = false;
79
61 /// <summary>The all important shutdown flag</summary> 80 /// <summary>The all important shutdown flag</summary>
62 private volatile bool m_shutdownFlag = true; 81 private volatile bool m_shutdownFlag = true;
63 82
@@ -246,7 +265,51 @@ namespace OpenMetaverse
246 } 265 }
247 } 266 }
248 267
249 public void AsyncBeginSend(UDPPacketBuffer buf) 268 public void SyncBeginPrioritySend(UDPPacketBuffer buf, int Priority)
269 {
270 if (!m_shutdownFlag)
271 {
272 if (!m_sendingData)
273 {
274 m_sendingData = true;
275 try
276 {
277 AsyncBeginSend(buf);
278 }
279 catch (SocketException) { }
280 catch (ObjectDisposedException) { }
281 }
282 else
283 {
284 if (Priority == 2)
285 {
286 lock (m_priorityQueue)
287 {
288 m_priorityQueue.Add(buf);
289 }
290 }
291 else
292 {
293 if (Priority != 0)
294 {
295 lock (m_mediumPriorityQueue)
296 {
297 m_mediumPriorityQueue.Add(buf);
298 }
299 }
300 else
301 {
302 lock (m_standardQueue)
303 {
304 m_standardQueue.Add(buf);
305 }
306 }
307 }
308 }
309 }
310 }
311
312 private void AsyncBeginSend(UDPPacketBuffer buf)
250 { 313 {
251 if (!m_shutdownFlag) 314 if (!m_shutdownFlag)
252 { 315 {
@@ -270,8 +333,48 @@ namespace OpenMetaverse
270 { 333 {
271 try 334 try
272 { 335 {
273// UDPPacketBuffer buf = (UDPPacketBuffer)result.AsyncState;
274 m_udpSocket.EndSendTo(result); 336 m_udpSocket.EndSendTo(result);
337
338 if (m_sendingData)
339 {
340 lock (m_priorityQueue)
341 {
342 if (m_priorityQueue.Count > 0)
343 {
344 UDPPacketBuffer buf = m_priorityQueue[0];
345 m_priorityQueue.RemoveAt(0);
346 AsyncBeginSend(buf);
347 }
348 else
349 {
350 lock (m_mediumPriorityQueue)
351 {
352 if (m_mediumPriorityQueue.Count > 0)
353 {
354 UDPPacketBuffer buf = m_mediumPriorityQueue[0];
355 m_mediumPriorityQueue.RemoveAt(0);
356 AsyncBeginSend(buf);
357 }
358 else
359 {
360 lock (m_standardQueue)
361 {
362 if (m_standardQueue.Count > 0)
363 {
364 UDPPacketBuffer buf = m_standardQueue[0];
365 m_standardQueue.RemoveAt(0);
366 AsyncBeginSend(buf);
367 }
368 else
369 {
370 m_sendingData = false;
371 }
372 }
373 }
374 }
375 }
376 }
377 }
275 } 378 }
276 catch (SocketException) { } 379 catch (SocketException) { }
277 catch (ObjectDisposedException) { } 380 catch (ObjectDisposedException) { }
diff --git a/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs b/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs
index 1a1a1cb..7dc42d3 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using OpenSim.Framework; 29using OpenSim.Framework;
30using OpenMetaverse; 30using OpenMetaverse;
31using OpenMetaverse.Packets;
31 32
32namespace OpenSim.Region.ClientStack.LindenUDP 33namespace OpenSim.Region.ClientStack.LindenUDP
33{ 34{
@@ -52,7 +53,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
52 public int TickCount; 53 public int TickCount;
53 /// <summary>Category this packet belongs to</summary> 54 /// <summary>Category this packet belongs to</summary>
54 public ThrottleOutPacketType Category; 55 public ThrottleOutPacketType Category;
55 56 /// <summary>The type of packet so its delivery method can be determined</summary>
57 public PacketType Type;
56 /// <summary> 58 /// <summary>
57 /// Default constructor 59 /// Default constructor
58 /// </summary> 60 /// </summary>
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
index 6dacbba..e3e8718 100644
--- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
@@ -49,7 +49,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
49 private int m_shoutdistance = 100; 49 private int m_shoutdistance = 100;
50 private int m_whisperdistance = 10; 50 private int m_whisperdistance = 10;
51 private List<Scene> m_scenes = new List<Scene>(); 51 private List<Scene> m_scenes = new List<Scene>();
52 52 private string m_adminPrefix = "";
53 internal object m_syncy = new object(); 53 internal object m_syncy = new object();
54 54
55 internal IConfig m_config; 55 internal IConfig m_config;
@@ -76,6 +76,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
76 m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance); 76 m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance);
77 m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance); 77 m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance);
78 m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance); 78 m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance);
79 m_adminPrefix = config.Configs["Chat"].GetString("admin_prefix", "");
79 } 80 }
80 81
81 public virtual void AddRegion(Scene scene) 82 public virtual void AddRegion(Scene scene)
@@ -185,6 +186,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
185 protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c) 186 protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c)
186 { 187 {
187 string fromName = c.From; 188 string fromName = c.From;
189 string fromNamePrefix = "";
188 UUID fromID = UUID.Zero; 190 UUID fromID = UUID.Zero;
189 string message = c.Message; 191 string message = c.Message;
190 IScene scene = c.Scene; 192 IScene scene = c.Scene;
@@ -207,7 +209,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
207 fromPos = avatar.AbsolutePosition; 209 fromPos = avatar.AbsolutePosition;
208 fromName = avatar.Name; 210 fromName = avatar.Name;
209 fromID = c.Sender.AgentId; 211 fromID = c.Sender.AgentId;
210 212 if (avatar.GodLevel > 200)
213 {
214 fromNamePrefix = m_adminPrefix;
215 }
211 break; 216 break;
212 217
213 case ChatSourceType.Object: 218 case ChatSourceType.Object:
@@ -227,7 +232,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
227 s.ForEachScenePresence( 232 s.ForEachScenePresence(
228 delegate(ScenePresence presence) 233 delegate(ScenePresence presence)
229 { 234 {
230 TrySendChatMessage(presence, fromPos, regionPos, fromID, fromName, c.Type, message, sourceType); 235 TrySendChatMessage(presence, fromPos, regionPos, fromID, fromNamePrefix+fromName, c.Type, message, sourceType);
231 } 236 }
232 ); 237 );
233 } 238 }
@@ -266,25 +271,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
266 } 271 }
267 272
268 // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType); 273 // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType);
269 274 if (c.Scene != null)
270 ((Scene)c.Scene).ForEachScenePresence( 275 {
271 delegate(ScenePresence presence) 276 ((Scene)c.Scene).ForEachScenePresence
272 { 277 (
273 // ignore chat from child agents 278 delegate(ScenePresence presence)
274 if (presence.IsChildAgent) return; 279 {
275 280 // ignore chat from child agents
276 IClientAPI client = presence.ControllingClient; 281 if (presence.IsChildAgent) return;
277 282
278 // don't forward SayOwner chat from objects to 283 IClientAPI client = presence.ControllingClient;
279 // non-owner agents 284
280 if ((c.Type == ChatTypeEnum.Owner) && 285 // don't forward SayOwner chat from objects to
281 (null != c.SenderObject) && 286 // non-owner agents
282 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) 287 if ((c.Type == ChatTypeEnum.Owner) &&
283 return; 288 (null != c.SenderObject) &&
284 289 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId))
285 client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, 290 return;
286 (byte)sourceType, (byte)ChatAudibleLevel.Fully); 291
287 }); 292 client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID,
293 (byte)sourceType, (byte)ChatAudibleLevel.Fully);
294 }
295 );
296 }
288 } 297 }
289 298
290 299
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
index 1614b70..7f9e5af 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
@@ -164,19 +164,22 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
164 List<GridInstantMessage>msglist = SynchronousRestObjectPoster.BeginPostObject<UUID, List<GridInstantMessage>>( 164 List<GridInstantMessage>msglist = SynchronousRestObjectPoster.BeginPostObject<UUID, List<GridInstantMessage>>(
165 "POST", m_RestURL+"/RetrieveMessages/", client.AgentId); 165 "POST", m_RestURL+"/RetrieveMessages/", client.AgentId);
166 166
167 foreach (GridInstantMessage im in msglist) 167 if (msglist != null)
168 { 168 {
169 // client.SendInstantMessage(im); 169 foreach (GridInstantMessage im in msglist)
170 170 {
171 // Send through scene event manager so all modules get a chance 171 // client.SendInstantMessage(im);
172 // to look at this message before it gets delivered. 172
173 // 173 // Send through scene event manager so all modules get a chance
174 // Needed for proper state management for stored group 174 // to look at this message before it gets delivered.
175 // invitations 175 //
176 // 176 // Needed for proper state management for stored group
177 Scene s = FindScene(client.AgentId); 177 // invitations
178 if (s != null) 178 //
179 s.EventManager.TriggerIncomingInstantMessage(im); 179 Scene s = FindScene(client.AgentId);
180 if (s != null)
181 s.EventManager.TriggerIncomingInstantMessage(im);
182 }
180 } 183 }
181 } 184 }
182 185
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
index d9a021f..b60b32b 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
@@ -389,7 +389,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
389 { 389 {
390 // Check if this is ours to handle 390 // Check if this is ours to handle
391 // 391 //
392 m_log.Info("OnFridInstantMessage"); 392 //m_log.Info("OnFridInstantMessage");
393 if (msg.dialog != (byte) InstantMessageDialog.InventoryOffered) 393 if (msg.dialog != (byte) InstantMessageDialog.InventoryOffered)
394 return; 394 return;
395 395
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index af72968..3c0997c 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -247,21 +247,20 @@ namespace OpenSim.Region.CoreModules.World.Archiver
247 // Fix ownership/creator of inventory items 247 // Fix ownership/creator of inventory items
248 // Not doing so results in inventory items 248 // Not doing so results in inventory items
249 // being no copy/no mod for everyone 249 // being no copy/no mod for everyone
250 lock (part.TaskInventory) 250 part.TaskInventory.LockItemsForRead(true);
251 TaskInventoryDictionary inv = part.TaskInventory;
252 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv)
251 { 253 {
252 TaskInventoryDictionary inv = part.TaskInventory; 254 if (!ResolveUserUuid(kvp.Value.OwnerID))
253 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv)
254 { 255 {
255 if (!ResolveUserUuid(kvp.Value.OwnerID)) 256 kvp.Value.OwnerID = masterAvatarId;
256 { 257 }
257 kvp.Value.OwnerID = masterAvatarId; 258 if (!ResolveUserUuid(kvp.Value.CreatorID))
258 } 259 {
259 if (!ResolveUserUuid(kvp.Value.CreatorID)) 260 kvp.Value.CreatorID = masterAvatarId;
260 {
261 kvp.Value.CreatorID = masterAvatarId;
262 }
263 } 261 }
264 } 262 }
263 part.TaskInventory.LockItemsForRead(false);
265 } 264 }
266 265
267 if (m_scene.AddRestoredSceneObject(sceneObject, true, false)) 266 if (m_scene.AddRestoredSceneObject(sceneObject, true, false))
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
index a459ffa..50624a1 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
@@ -53,8 +53,8 @@ namespace OpenSim.Region.Framework.Scenes.Animation
53 { 53 {
54 get { return m_movementAnimation; } 54 get { return m_movementAnimation; }
55 } 55 }
56 protected string m_movementAnimation = "DEFAULT"; 56 // protected string m_movementAnimation = "DEFAULT"; //KF: 'DEFAULT' does not exist!
57 57 protected string m_movementAnimation = "CROUCH"; //KF: CROUCH ensures reliable Av Anim. init.
58 private int m_animTickFall; 58 private int m_animTickFall;
59 private int m_animTickJump; 59 private int m_animTickJump;
60 60
@@ -123,17 +123,22 @@ namespace OpenSim.Region.Framework.Scenes.Animation
123 /// </summary> 123 /// </summary>
124 public void TrySetMovementAnimation(string anim) 124 public void TrySetMovementAnimation(string anim)
125 { 125 {
126 //m_log.DebugFormat("Updating movement animation to {0}", anim); 126//Console.WriteLine("Updating movement animation to {0}", anim);
127 127
128 if (!m_scenePresence.IsChildAgent) 128 if (!m_scenePresence.IsChildAgent)
129 { 129 {
130 if (m_animations.TrySetDefaultAnimation( 130 if (m_animations.TrySetDefaultAnimation(
131 anim, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, UUID.Zero)) 131 anim, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, UUID.Zero))
132 { 132 {
133//Console.WriteLine("TSMA {0} success.", anim);
133 // 16384 is CHANGED_ANIMATION 134 // 16384 is CHANGED_ANIMATION
134 m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { 16384 }); 135 m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { 16384 });
135 SendAnimPack(); 136 SendAnimPack();
136 } 137 }
138 else
139 {
140//Console.WriteLine("TSMA {0} fail.", anim);
141 }
137 } 142 }
138 } 143 }
139 144
@@ -156,10 +161,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
156 Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix); 161 Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix);
157 162
158 // Check control flags 163 // Check control flags
159 bool heldForward = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_AT_POS; 164 bool heldForward = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_AT_POS || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS);
160 bool heldBack = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG; 165 bool heldBack = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG);
161 bool heldLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS; 166 bool heldLeft = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS);
162 bool heldRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG; 167 bool heldRight = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG);
163 //bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT; 168 //bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT;
164 //bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT; 169 //bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT;
165 bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS; 170 bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS;
@@ -312,7 +317,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
312 public void UpdateMovementAnimations() 317 public void UpdateMovementAnimations()
313 { 318 {
314 m_movementAnimation = GetMovementAnimation(); 319 m_movementAnimation = GetMovementAnimation();
315 320//Console.WriteLine("UMA got {0}", m_movementAnimation);
316 if (m_movementAnimation == "PREJUMP" && !m_scenePresence.Scene.m_usePreJump) 321 if (m_movementAnimation == "PREJUMP" && !m_scenePresence.Scene.m_usePreJump)
317 { 322 {
318 // This was the previous behavior before PREJUMP 323 // This was the previous behavior before PREJUMP
@@ -450,4 +455,4 @@ namespace OpenSim.Region.Framework.Scenes.Animation
450 m_scenePresence = null; 455 m_scenePresence = null;
451 } 456 }
452 } 457 }
453} \ No newline at end of file 458}
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 0b0c205..7ca779a 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -840,8 +840,12 @@ namespace OpenSim.Region.Framework.Scenes
840 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID) 840 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID)
841 { 841 {
842 SceneObjectPart part = GetSceneObjectPart(localID); 842 SceneObjectPart part = GetSceneObjectPart(localID);
843 SceneObjectGroup group = part.ParentGroup; 843 SceneObjectGroup group = null;
844 if (group != null) 844 if (part != null)
845 {
846 group = part.ParentGroup;
847 }
848 if (part != null && group != null)
845 { 849 {
846 TaskInventoryItem item = group.GetInventoryItem(localID, itemID); 850 TaskInventoryItem item = group.GetInventoryItem(localID, itemID);
847 if (item == null) 851 if (item == null)
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index a22fb5f..a8bab5a 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -881,6 +881,15 @@ namespace OpenSim.Region.Framework.Scenes
881 /// <param name="seconds">float indicating duration before restart.</param> 881 /// <param name="seconds">float indicating duration before restart.</param>
882 public virtual void Restart(float seconds) 882 public virtual void Restart(float seconds)
883 { 883 {
884 Restart(seconds, true);
885 }
886
887 /// <summary>
888 /// Given float seconds, this will restart the region. showDialog will optionally alert the users.
889 /// </summary>
890 /// <param name="seconds">float indicating duration before restart.</param>
891 public virtual void Restart(float seconds, bool showDialog)
892 {
884 // notifications are done in 15 second increments 893 // notifications are done in 15 second increments
885 // so .. if the number of seconds is less then 15 seconds, it's not really a restart request 894 // so .. if the number of seconds is less then 15 seconds, it's not really a restart request
886 // It's a 'Cancel restart' request. 895 // It's a 'Cancel restart' request.
@@ -901,8 +910,11 @@ namespace OpenSim.Region.Framework.Scenes
901 m_restartTimer.Elapsed += new ElapsedEventHandler(RestartTimer_Elapsed); 910 m_restartTimer.Elapsed += new ElapsedEventHandler(RestartTimer_Elapsed);
902 m_log.Info("[REGION]: Restarting Region in " + (seconds / 60) + " minutes"); 911 m_log.Info("[REGION]: Restarting Region in " + (seconds / 60) + " minutes");
903 m_restartTimer.Start(); 912 m_restartTimer.Start();
904 m_dialogModule.SendNotificationToUsersInRegion( 913 if (showDialog)
905 UUID.Random(), String.Empty, RegionInfo.RegionName + ": Restarting in 2 Minutes"); 914 {
915 m_dialogModule.SendNotificationToUsersInRegion(
916 UUID.Random(), String.Empty, RegionInfo.RegionName + ": Restarting in " + (seconds / 60).ToString() + " Minutes");
917 }
906 } 918 }
907 } 919 }
908 920
@@ -1173,16 +1185,16 @@ namespace OpenSim.Region.Framework.Scenes
1173 // Check if any objects have reached their targets 1185 // Check if any objects have reached their targets
1174 CheckAtTargets(); 1186 CheckAtTargets();
1175 1187
1176 // Update SceneObjectGroups that have scheduled themselves for updates
1177 // Objects queue their updates onto all scene presences
1178 if (m_frame % m_update_objects == 0)
1179 m_sceneGraph.UpdateObjectGroups();
1180
1181 // Run through all ScenePresences looking for updates 1188 // Run through all ScenePresences looking for updates
1182 // Presence updates and queued object updates for each presence are sent to clients 1189 // Presence updates and queued object updates for each presence are sent to clients
1183 if (m_frame % m_update_presences == 0) 1190 if (m_frame % m_update_presences == 0)
1184 m_sceneGraph.UpdatePresences(); 1191 m_sceneGraph.UpdatePresences();
1185 1192
1193 // Update SceneObjectGroups that have scheduled themselves for updates
1194 // Objects queue their updates onto all scene presences
1195 if (m_frame % m_update_objects == 0)
1196 m_sceneGraph.UpdateObjectGroups();
1197
1186 int tmpPhysicsMS2 = Util.EnvironmentTickCount(); 1198 int tmpPhysicsMS2 = Util.EnvironmentTickCount();
1187 if ((m_frame % m_update_physics == 0) && m_physics_enabled) 1199 if ((m_frame % m_update_physics == 0) && m_physics_enabled)
1188 m_sceneGraph.UpdatePreparePhysics(); 1200 m_sceneGraph.UpdatePreparePhysics();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 6badaf5..ecda80c 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -98,6 +98,66 @@ namespace OpenSim.Region.Framework.Scenes
98 private bool m_hasGroupChanged = false; 98 private bool m_hasGroupChanged = false;
99 private long timeFirstChanged; 99 private long timeFirstChanged;
100 private long timeLastChanged; 100 private long timeLastChanged;
101 private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim();
102
103 public void lockPartsForRead(bool locked)
104 {
105 if (locked)
106 {
107 if (m_partsLock.RecursiveReadCount > 0)
108 {
109 m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
110 m_partsLock.ExitReadLock();
111 }
112 if (m_partsLock.RecursiveWriteCount > 0)
113 {
114 m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested. This should not happen and means something needs to be fixed.");
115 m_partsLock.ExitWriteLock();
116 }
117
118 while (!m_partsLock.TryEnterReadLock(60000))
119 {
120 m_log.Error("[SceneObjectGroup.m_parts] Thread lock detected while trying to aquire READ lock of m_parts in SceneObjectGroup. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
121 if (m_partsLock.IsWriteLockHeld)
122 {
123 m_partsLock = new System.Threading.ReaderWriterLockSlim();
124 }
125 }
126 }
127 else
128 {
129 m_partsLock.ExitReadLock();
130 }
131 }
132 public void lockPartsForWrite(bool locked)
133 {
134 if (locked)
135 {
136 if (m_partsLock.RecursiveReadCount > 0)
137 {
138 m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
139 m_partsLock.ExitReadLock();
140 }
141 if (m_partsLock.RecursiveWriteCount > 0)
142 {
143 m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
144 m_partsLock.ExitWriteLock();
145 }
146
147 while (!m_partsLock.TryEnterWriteLock(60000))
148 {
149 m_log.Error("[SceneObjectGroup.m_parts] Thread lock detected while trying to aquire WRITE lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
150 if (m_partsLock.IsWriteLockHeld)
151 {
152 m_partsLock = new System.Threading.ReaderWriterLockSlim();
153 }
154 }
155 }
156 else
157 {
158 m_partsLock.ExitWriteLock();
159 }
160 }
101 161
102 public bool HasGroupChanged 162 public bool HasGroupChanged
103 { 163 {
@@ -243,13 +303,16 @@ namespace OpenSim.Region.Framework.Scenes
243 set 303 set
244 { 304 {
245 m_regionHandle = value; 305 m_regionHandle = value;
246 lock (m_parts) 306 lockPartsForRead(true);
247 { 307 {
248 foreach (SceneObjectPart part in m_parts.Values) 308 foreach (SceneObjectPart part in m_parts.Values)
249 { 309 {
310
250 part.RegionHandle = m_regionHandle; 311 part.RegionHandle = m_regionHandle;
312
251 } 313 }
252 } 314 }
315 lockPartsForRead(false);
253 } 316 }
254 } 317 }
255 318
@@ -275,13 +338,16 @@ namespace OpenSim.Region.Framework.Scenes
275 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 338 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
276 } 339 }
277 340
278 lock (m_parts) 341 lockPartsForRead(true);
279 { 342 {
280 foreach (SceneObjectPart part in m_parts.Values) 343 foreach (SceneObjectPart part in m_parts.Values)
281 { 344 {
345
282 part.GroupPosition = val; 346 part.GroupPosition = val;
347
283 } 348 }
284 } 349 }
350 lockPartsForRead(false);
285 351
286 //if (m_rootPart.PhysActor != null) 352 //if (m_rootPart.PhysActor != null)
287 //{ 353 //{
@@ -432,13 +498,16 @@ namespace OpenSim.Region.Framework.Scenes
432 498
433 public void SetFromItemID(UUID AssetId) 499 public void SetFromItemID(UUID AssetId)
434 { 500 {
435 lock (m_parts) 501 lockPartsForRead(true);
436 { 502 {
437 foreach (SceneObjectPart part in m_parts.Values) 503 foreach (SceneObjectPart part in m_parts.Values)
438 { 504 {
505
439 part.FromItemID = AssetId; 506 part.FromItemID = AssetId;
507
440 } 508 }
441 } 509 }
510 lockPartsForRead(false);
442 } 511 }
443 512
444 public UUID GetFromItemID() 513 public UUID GetFromItemID()
@@ -505,10 +574,11 @@ namespace OpenSim.Region.Framework.Scenes
505 Vector3 maxScale = Vector3.Zero; 574 Vector3 maxScale = Vector3.Zero;
506 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); 575 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
507 576
508 lock (m_parts) 577 lockPartsForRead(true);
509 { 578 {
510 foreach (SceneObjectPart part in m_parts.Values) 579 foreach (SceneObjectPart part in m_parts.Values)
511 { 580 {
581
512 Vector3 partscale = part.Scale; 582 Vector3 partscale = part.Scale;
513 Vector3 partoffset = part.OffsetPosition; 583 Vector3 partoffset = part.OffsetPosition;
514 584
@@ -519,8 +589,11 @@ namespace OpenSim.Region.Framework.Scenes
519 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; 589 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X;
520 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y; 590 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y;
521 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z; 591 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
592
522 } 593 }
523 } 594 }
595 lockPartsForRead(false);
596
524 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; 597 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
525 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; 598 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
526 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; 599 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
@@ -536,10 +609,11 @@ namespace OpenSim.Region.Framework.Scenes
536 609
537 EntityIntersection result = new EntityIntersection(); 610 EntityIntersection result = new EntityIntersection();
538 611
539 lock (m_parts) 612 lockPartsForRead(true);
540 { 613 {
541 foreach (SceneObjectPart part in m_parts.Values) 614 foreach (SceneObjectPart part in m_parts.Values)
542 { 615 {
616
543 // Temporary commented to stop compiler warning 617 // Temporary commented to stop compiler warning
544 //Vector3 partPosition = 618 //Vector3 partPosition =
545 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); 619 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
@@ -567,8 +641,10 @@ namespace OpenSim.Region.Framework.Scenes
567 result.distance = inter.distance; 641 result.distance = inter.distance;
568 } 642 }
569 } 643 }
644
570 } 645 }
571 } 646 }
647 lockPartsForRead(false);
572 return result; 648 return result;
573 } 649 }
574 650
@@ -581,10 +657,11 @@ namespace OpenSim.Region.Framework.Scenes
581 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) 657 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight)
582 { 658 {
583 float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f; 659 float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f;
584 lock (m_parts) 660 lockPartsForRead(true);
585 { 661 {
586 foreach (SceneObjectPart part in m_parts.Values) 662 foreach (SceneObjectPart part in m_parts.Values)
587 { 663 {
664
588 Vector3 worldPos = part.GetWorldPosition(); 665 Vector3 worldPos = part.GetWorldPosition();
589 Vector3 offset = worldPos - AbsolutePosition; 666 Vector3 offset = worldPos - AbsolutePosition;
590 Quaternion worldRot; 667 Quaternion worldRot;
@@ -643,6 +720,8 @@ namespace OpenSim.Region.Framework.Scenes
643 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 720 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
644 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 721 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
645 722
723
724
646 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); 725 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
647 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); 726 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
648 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); 727 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
@@ -814,6 +893,7 @@ namespace OpenSim.Region.Framework.Scenes
814 minZ = backBottomLeft.Z; 893 minZ = backBottomLeft.Z;
815 } 894 }
816 } 895 }
896 lockPartsForRead(false);
817 897
818 Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ); 898 Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ);
819 899
@@ -842,17 +922,20 @@ namespace OpenSim.Region.Framework.Scenes
842 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 922 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
843 923
844 // Capture script state while holding the lock 924 // Capture script state while holding the lock
845 lock (m_parts) 925 lockPartsForRead(true);
846 { 926 {
847 foreach (SceneObjectPart part in m_parts.Values) 927 foreach (SceneObjectPart part in m_parts.Values)
848 { 928 {
929
849 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); 930 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates();
850 foreach (UUID itemid in pstates.Keys) 931 foreach (UUID itemid in pstates.Keys)
851 { 932 {
852 states.Add(itemid, pstates[itemid]); 933 states.Add(itemid, pstates[itemid]);
853 } 934 }
935
854 } 936 }
855 } 937 }
938 lockPartsForRead(false);
856 939
857 if (states.Count > 0) 940 if (states.Count > 0)
858 { 941 {
@@ -1014,13 +1097,16 @@ namespace OpenSim.Region.Framework.Scenes
1014 1097
1015 public override void UpdateMovement() 1098 public override void UpdateMovement()
1016 { 1099 {
1017 lock (m_parts) 1100 lockPartsForRead(true);
1018 { 1101 {
1019 foreach (SceneObjectPart part in m_parts.Values) 1102 foreach (SceneObjectPart part in m_parts.Values)
1020 { 1103 {
1104
1021 part.UpdateMovement(); 1105 part.UpdateMovement();
1106
1022 } 1107 }
1023 } 1108 }
1109 lockPartsForRead(false);
1024 } 1110 }
1025 1111
1026 public ushort GetTimeDilation() 1112 public ushort GetTimeDilation()
@@ -1064,7 +1150,7 @@ namespace OpenSim.Region.Framework.Scenes
1064 /// <param name="part"></param> 1150 /// <param name="part"></param>
1065 public void AddPart(SceneObjectPart part) 1151 public void AddPart(SceneObjectPart part)
1066 { 1152 {
1067 lock (m_parts) 1153 lockPartsForWrite(true);
1068 { 1154 {
1069 part.SetParent(this); 1155 part.SetParent(this);
1070 m_parts.Add(part.UUID, part); 1156 m_parts.Add(part.UUID, part);
@@ -1074,6 +1160,7 @@ namespace OpenSim.Region.Framework.Scenes
1074 if (part.LinkNum == 2 && RootPart != null) 1160 if (part.LinkNum == 2 && RootPart != null)
1075 RootPart.LinkNum = 1; 1161 RootPart.LinkNum = 1;
1076 } 1162 }
1163 lockPartsForWrite(false);
1077 } 1164 }
1078 1165
1079 /// <summary> 1166 /// <summary>
@@ -1081,28 +1168,33 @@ namespace OpenSim.Region.Framework.Scenes
1081 /// </summary> 1168 /// </summary>
1082 private void UpdateParentIDs() 1169 private void UpdateParentIDs()
1083 { 1170 {
1084 lock (m_parts) 1171 lockPartsForRead(true);
1085 { 1172 {
1086 foreach (SceneObjectPart part in m_parts.Values) 1173 foreach (SceneObjectPart part in m_parts.Values)
1087 { 1174 {
1175
1088 if (part.UUID != m_rootPart.UUID) 1176 if (part.UUID != m_rootPart.UUID)
1089 { 1177 {
1090 part.ParentID = m_rootPart.LocalId; 1178 part.ParentID = m_rootPart.LocalId;
1091 } 1179 }
1180
1092 } 1181 }
1093 } 1182 }
1183 lockPartsForRead(false);
1094 } 1184 }
1095 1185
1096 public void RegenerateFullIDs() 1186 public void RegenerateFullIDs()
1097 { 1187 {
1098 lock (m_parts) 1188 lockPartsForRead(true);
1099 { 1189 {
1100 foreach (SceneObjectPart part in m_parts.Values) 1190 foreach (SceneObjectPart part in m_parts.Values)
1101 { 1191 {
1192
1102 part.UUID = UUID.Random(); 1193 part.UUID = UUID.Random();
1103 1194
1104 } 1195 }
1105 } 1196 }
1197 lockPartsForRead(false);
1106 } 1198 }
1107 1199
1108 // helper provided for parts. 1200 // helper provided for parts.
@@ -1183,29 +1275,33 @@ namespace OpenSim.Region.Framework.Scenes
1183 1275
1184 DetachFromBackup(); 1276 DetachFromBackup();
1185 1277
1186 lock (m_parts) 1278 lockPartsForRead(true);
1279 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1280 lockPartsForRead(false);
1281
1282 foreach (SceneObjectPart part in values)
1187 { 1283 {
1188 foreach (SceneObjectPart part in m_parts.Values)
1189 {
1190// part.Inventory.RemoveScriptInstances(); 1284// part.Inventory.RemoveScriptInstances();
1191 1285
1192 ScenePresence[] avatars = Scene.GetScenePresences(); 1286 ScenePresence[] avatars = Scene.GetScenePresences();
1193 for (int i = 0; i < avatars.Length; i++) 1287 for (int i = 0; i < avatars.Length; i++)
1288 {
1289 if (avatars[i].ParentID == LocalId)
1194 { 1290 {
1195 if (avatars[i].ParentID == LocalId) 1291 avatars[i].StandUp();
1196 { 1292 }
1197 avatars[i].StandUp();
1198 }
1199 1293
1200 if (!silent) 1294 if (!silent)
1201 { 1295 {
1202 part.UpdateFlag = 0; 1296 part.UpdateFlag = 0;
1203 if (part == m_rootPart) 1297 if (part == m_rootPart)
1204 avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId); 1298 avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1205 }
1206 } 1299 }
1207 } 1300 }
1301
1208 } 1302 }
1303
1304
1209 } 1305 }
1210 1306
1211 public void AddScriptLPS(int count) 1307 public void AddScriptLPS(int count)
@@ -1230,17 +1326,20 @@ namespace OpenSim.Region.Framework.Scenes
1230 1326
1231 scriptEvents aggregateScriptEvents=0; 1327 scriptEvents aggregateScriptEvents=0;
1232 1328
1233 lock (m_parts) 1329 lockPartsForRead(true);
1234 { 1330 {
1235 foreach (SceneObjectPart part in m_parts.Values) 1331 foreach (SceneObjectPart part in m_parts.Values)
1236 { 1332 {
1333
1237 if (part == null) 1334 if (part == null)
1238 continue; 1335 continue;
1239 if (part != RootPart) 1336 if (part != RootPart)
1240 part.ObjectFlags = objectflagupdate; 1337 part.ObjectFlags = objectflagupdate;
1241 aggregateScriptEvents |= part.AggregateScriptEvents; 1338 aggregateScriptEvents |= part.AggregateScriptEvents;
1339
1242 } 1340 }
1243 } 1341 }
1342 lockPartsForRead(false);
1244 1343
1245 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); 1344 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
1246 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); 1345 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0);
@@ -1273,42 +1372,52 @@ namespace OpenSim.Region.Framework.Scenes
1273 /// <param name="m_physicalPrim"></param> 1372 /// <param name="m_physicalPrim"></param>
1274 public void ApplyPhysics(bool m_physicalPrim) 1373 public void ApplyPhysics(bool m_physicalPrim)
1275 { 1374 {
1276 lock (m_parts) 1375 lockPartsForRead(true);
1376
1377 if (m_parts.Count > 1)
1277 { 1378 {
1278 if (m_parts.Count > 1) 1379 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1380 lockPartsForRead(false);
1381 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1382 foreach (SceneObjectPart part in values)
1279 { 1383 {
1280 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); 1384
1281 foreach (SceneObjectPart part in m_parts.Values) 1385 if (part.LocalId != m_rootPart.LocalId)
1282 { 1386 {
1283 if (part.LocalId != m_rootPart.LocalId) 1387 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1284 {
1285 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1286 }
1287 } 1388 }
1288 1389
1289 // Hack to get the physics scene geometries in the right spot
1290 ResetChildPrimPhysicsPositions();
1291 }
1292 else
1293 {
1294 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1295 } 1390 }
1391 // Hack to get the physics scene geometries in the right spot
1392 ResetChildPrimPhysicsPositions();
1393 }
1394 else
1395 {
1396 lockPartsForRead(false);
1397 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1296 } 1398 }
1297 } 1399 }
1298 1400
1299 public void SetOwnerId(UUID userId) 1401 public void SetOwnerId(UUID userId)
1300 { 1402 {
1301 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1403 ForEachPart(delegate(SceneObjectPart part)
1404 {
1405
1406 part.OwnerID = userId;
1407
1408 });
1302 } 1409 }
1303 1410
1304 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1411 public void ForEachPart(Action<SceneObjectPart> whatToDo)
1305 { 1412 {
1306 lock (m_parts) 1413 lockPartsForRead(true);
1414 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1415 lockPartsForRead(false);
1416 foreach (SceneObjectPart part in values)
1307 { 1417 {
1308 foreach (SceneObjectPart part in m_parts.Values) 1418
1309 { 1419 whatToDo(part);
1310 whatToDo(part); 1420
1311 }
1312 } 1421 }
1313 } 1422 }
1314 1423
@@ -1407,14 +1516,17 @@ namespace OpenSim.Region.Framework.Scenes
1407 { 1516 {
1408 SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); 1517 SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
1409 1518
1410 lock (m_parts) 1519 lockPartsForRead(true);
1411 { 1520 {
1412 foreach (SceneObjectPart part in m_parts.Values) 1521 foreach (SceneObjectPart part in m_parts.Values)
1413 { 1522 {
1523
1414 if (part != RootPart) 1524 if (part != RootPart)
1415 SendPartFullUpdate(remoteClient, part, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); 1525 SendPartFullUpdate(remoteClient, part, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
1526
1416 } 1527 }
1417 } 1528 }
1529 lockPartsForRead(false);
1418 } 1530 }
1419 1531
1420 /// <summary> 1532 /// <summary>
@@ -1509,10 +1621,11 @@ namespace OpenSim.Region.Framework.Scenes
1509 1621
1510 List<SceneObjectPart> partList; 1622 List<SceneObjectPart> partList;
1511 1623
1512 lock (m_parts) 1624 lockPartsForRead(true);
1513 { 1625
1514 partList = new List<SceneObjectPart>(m_parts.Values); 1626 partList = new List<SceneObjectPart>(m_parts.Values);
1515 } 1627
1628 lockPartsForRead(false);
1516 1629
1517 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1630 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1518 { 1631 {
@@ -1735,6 +1848,45 @@ namespace OpenSim.Region.Framework.Scenes
1735 } 1848 }
1736 } 1849 }
1737 1850
1851 public void rotLookAt(Quaternion target, float strength, float damping)
1852 {
1853 SceneObjectPart rootpart = m_rootPart;
1854 if (rootpart != null)
1855 {
1856 if (IsAttachment)
1857 {
1858 /*
1859 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1860 if (avatar != null)
1861 {
1862 Rotate the Av?
1863 } */
1864 }
1865 else
1866 {
1867 if (rootpart.PhysActor != null)
1868 {
1869 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
1870 rootpart.PhysActor.APIDStrength = strength;
1871 rootpart.PhysActor.APIDDamping = damping;
1872 rootpart.PhysActor.APIDActive = true;
1873 }
1874 }
1875 }
1876 }
1877 public void stopLookAt()
1878 {
1879 SceneObjectPart rootpart = m_rootPart;
1880 if (rootpart != null)
1881 {
1882 if (rootpart.PhysActor != null)
1883 {
1884 rootpart.PhysActor.APIDActive = false;
1885 }
1886 }
1887
1888 }
1889
1738 /// <summary> 1890 /// <summary>
1739 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds. 1891 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds.
1740 /// </summary> 1892 /// </summary>
@@ -1796,10 +1948,11 @@ namespace OpenSim.Region.Framework.Scenes
1796 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 1948 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1797 newPart.SetParent(this); 1949 newPart.SetParent(this);
1798 1950
1799 lock (m_parts) 1951 lockPartsForWrite(true);
1800 { 1952 {
1801 m_parts.Add(newPart.UUID, newPart); 1953 m_parts.Add(newPart.UUID, newPart);
1802 } 1954 }
1955 lockPartsForWrite(false);
1803 1956
1804 SetPartAsNonRoot(newPart); 1957 SetPartAsNonRoot(newPart);
1805 1958
@@ -1862,7 +2015,7 @@ namespace OpenSim.Region.Framework.Scenes
1862 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2015 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1863 // return; 2016 // return;
1864 2017
1865 lock (m_parts) 2018 lockPartsForRead(true);
1866 { 2019 {
1867 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2020 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1868 2021
@@ -1880,34 +2033,43 @@ namespace OpenSim.Region.Framework.Scenes
1880 2033
1881 foreach (SceneObjectPart part in m_parts.Values) 2034 foreach (SceneObjectPart part in m_parts.Values)
1882 { 2035 {
2036
1883 part.SendScheduledUpdates(); 2037 part.SendScheduledUpdates();
2038
1884 } 2039 }
1885 } 2040 }
2041 lockPartsForRead(false);
1886 } 2042 }
1887 2043
1888 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2044 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
1889 { 2045 {
1890 RootPart.AddFullUpdateToAvatar(presence); 2046 RootPart.AddFullUpdateToAvatar(presence);
1891 2047
1892 lock (m_parts) 2048 lockPartsForRead(true);
1893 { 2049 {
1894 foreach (SceneObjectPart part in m_parts.Values) 2050 foreach (SceneObjectPart part in m_parts.Values)
1895 { 2051 {
2052
1896 if (part != RootPart) 2053 if (part != RootPart)
1897 part.AddFullUpdateToAvatar(presence); 2054 part.AddFullUpdateToAvatar(presence);
2055
1898 } 2056 }
1899 } 2057 }
2058 lockPartsForRead(false);
1900 } 2059 }
1901 2060
1902 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2061 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
1903 { 2062 {
1904 lock (m_parts) 2063 lockPartsForRead(true);
1905 { 2064 {
1906 foreach (SceneObjectPart part in m_parts.Values) 2065 foreach (SceneObjectPart part in m_parts.Values)
1907 { 2066 {
2067
1908 part.AddTerseUpdateToAvatar(presence); 2068 part.AddTerseUpdateToAvatar(presence);
2069
1909 } 2070 }
1910 } 2071 }
2072 lockPartsForRead(false);
1911 } 2073 }
1912 2074
1913 /// <summary> 2075 /// <summary>
@@ -1918,14 +2080,17 @@ namespace OpenSim.Region.Framework.Scenes
1918 checkAtTargets(); 2080 checkAtTargets();
1919 RootPart.ScheduleFullUpdate(); 2081 RootPart.ScheduleFullUpdate();
1920 2082
1921 lock (m_parts) 2083 lockPartsForRead(true);
1922 { 2084 {
1923 foreach (SceneObjectPart part in m_parts.Values) 2085 foreach (SceneObjectPart part in m_parts.Values)
1924 { 2086 {
2087
1925 if (part != RootPart) 2088 if (part != RootPart)
1926 part.ScheduleFullUpdate(); 2089 part.ScheduleFullUpdate();
2090
1927 } 2091 }
1928 } 2092 }
2093 lockPartsForRead(false);
1929 } 2094 }
1930 2095
1931 /// <summary> 2096 /// <summary>
@@ -1933,13 +2098,16 @@ namespace OpenSim.Region.Framework.Scenes
1933 /// </summary> 2098 /// </summary>
1934 public void ScheduleGroupForTerseUpdate() 2099 public void ScheduleGroupForTerseUpdate()
1935 { 2100 {
1936 lock (m_parts) 2101 lockPartsForRead(true);
1937 { 2102 {
1938 foreach (SceneObjectPart part in m_parts.Values) 2103 foreach (SceneObjectPart part in m_parts.Values)
1939 { 2104 {
2105
1940 part.ScheduleTerseUpdate(); 2106 part.ScheduleTerseUpdate();
2107
1941 } 2108 }
1942 } 2109 }
2110 lockPartsForRead(false);
1943 } 2111 }
1944 2112
1945 /// <summary> 2113 /// <summary>
@@ -1952,14 +2120,17 @@ namespace OpenSim.Region.Framework.Scenes
1952 2120
1953 RootPart.SendFullUpdateToAllClients(); 2121 RootPart.SendFullUpdateToAllClients();
1954 2122
1955 lock (m_parts) 2123 lockPartsForRead(true);
1956 { 2124 {
1957 foreach (SceneObjectPart part in m_parts.Values) 2125 foreach (SceneObjectPart part in m_parts.Values)
1958 { 2126 {
2127
1959 if (part != RootPart) 2128 if (part != RootPart)
1960 part.SendFullUpdateToAllClients(); 2129 part.SendFullUpdateToAllClients();
2130
1961 } 2131 }
1962 } 2132 }
2133 lockPartsForRead(false);
1963 } 2134 }
1964 2135
1965 /// <summary> 2136 /// <summary>
@@ -1990,14 +2161,15 @@ namespace OpenSim.Region.Framework.Scenes
1990 { 2161 {
1991 if (IsDeleted) 2162 if (IsDeleted)
1992 return; 2163 return;
1993 2164
1994 lock (m_parts) 2165 lockPartsForRead(true);
1995 { 2166 {
1996 foreach (SceneObjectPart part in m_parts.Values) 2167 foreach (SceneObjectPart part in m_parts.Values)
1997 { 2168 {
1998 part.SendTerseUpdateToAllClients(); 2169 part.SendTerseUpdateToAllClients();
1999 } 2170 }
2000 } 2171 }
2172 lockPartsForRead(false);
2001 } 2173 }
2002 2174
2003 #endregion 2175 #endregion
@@ -2011,16 +2183,18 @@ namespace OpenSim.Region.Framework.Scenes
2011 /// <returns>null if no child part with that linknum or child part</returns> 2183 /// <returns>null if no child part with that linknum or child part</returns>
2012 public SceneObjectPart GetLinkNumPart(int linknum) 2184 public SceneObjectPart GetLinkNumPart(int linknum)
2013 { 2185 {
2014 lock (m_parts) 2186 lockPartsForRead(true);
2015 { 2187 {
2016 foreach (SceneObjectPart part in m_parts.Values) 2188 foreach (SceneObjectPart part in m_parts.Values)
2017 { 2189 {
2018 if (part.LinkNum == linknum) 2190 if (part.LinkNum == linknum)
2019 { 2191 {
2192 lockPartsForRead(false);
2020 return part; 2193 return part;
2021 } 2194 }
2022 } 2195 }
2023 } 2196 }
2197 lockPartsForRead(false);
2024 2198
2025 return null; 2199 return null;
2026 } 2200 }
@@ -2048,17 +2222,19 @@ namespace OpenSim.Region.Framework.Scenes
2048 public SceneObjectPart GetChildPart(uint localID) 2222 public SceneObjectPart GetChildPart(uint localID)
2049 { 2223 {
2050 //m_log.DebugFormat("Entered looking for {0}", localID); 2224 //m_log.DebugFormat("Entered looking for {0}", localID);
2051 lock (m_parts) 2225 lockPartsForRead(true);
2052 { 2226 {
2053 foreach (SceneObjectPart part in m_parts.Values) 2227 foreach (SceneObjectPart part in m_parts.Values)
2054 { 2228 {
2055 //m_log.DebugFormat("Found {0}", part.LocalId); 2229 //m_log.DebugFormat("Found {0}", part.LocalId);
2056 if (part.LocalId == localID) 2230 if (part.LocalId == localID)
2057 { 2231 {
2232 lockPartsForRead(false);
2058 return part; 2233 return part;
2059 } 2234 }
2060 } 2235 }
2061 } 2236 }
2237 lockPartsForRead(false);
2062 2238
2063 return null; 2239 return null;
2064 } 2240 }
@@ -2088,17 +2264,19 @@ namespace OpenSim.Region.Framework.Scenes
2088 public bool HasChildPrim(uint localID) 2264 public bool HasChildPrim(uint localID)
2089 { 2265 {
2090 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2266 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2091 lock (m_parts) 2267 lockPartsForRead(true);
2092 { 2268 {
2093 foreach (SceneObjectPart part in m_parts.Values) 2269 foreach (SceneObjectPart part in m_parts.Values)
2094 { 2270 {
2095 //m_log.DebugFormat("Found {0}", part.LocalId); 2271 //m_log.DebugFormat("Found {0}", part.LocalId);
2096 if (part.LocalId == localID) 2272 if (part.LocalId == localID)
2097 { 2273 {
2274 lockPartsForRead(false);
2098 return true; 2275 return true;
2099 } 2276 }
2100 } 2277 }
2101 } 2278 }
2279 lockPartsForRead(false);
2102 2280
2103 return false; 2281 return false;
2104 } 2282 }
@@ -2148,53 +2326,57 @@ namespace OpenSim.Region.Framework.Scenes
2148 if (m_rootPart.LinkNum == 0) 2326 if (m_rootPart.LinkNum == 0)
2149 m_rootPart.LinkNum = 1; 2327 m_rootPart.LinkNum = 1;
2150 2328
2151 lock (m_parts) 2329 lockPartsForWrite(true);
2152 { 2330
2153 m_parts.Add(linkPart.UUID, linkPart); 2331 m_parts.Add(linkPart.UUID, linkPart);
2332
2333 lockPartsForWrite(false);
2154 2334
2155 // Insert in terms of link numbers, the new links 2335 // Insert in terms of link numbers, the new links
2156 // before the current ones (with the exception of 2336 // before the current ones (with the exception of
2157 // the root prim. Shuffle the old ones up 2337 // the root prim. Shuffle the old ones up
2158 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2338 lockPartsForRead(true);
2339 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2340 {
2341 if (kvp.Value.LinkNum != 1)
2159 { 2342 {
2160 if (kvp.Value.LinkNum != 1) 2343 // Don't update root prim link number
2161 { 2344 kvp.Value.LinkNum += objectGroup.PrimCount;
2162 // Don't update root prim link number
2163 kvp.Value.LinkNum += objectGroup.PrimCount;
2164 }
2165 } 2345 }
2346 }
2347 lockPartsForRead(false);
2166 2348
2167 linkPart.LinkNum = 2; 2349 linkPart.LinkNum = 2;
2168 2350
2169 linkPart.SetParent(this); 2351 linkPart.SetParent(this);
2170 linkPart.AddFlag(PrimFlags.CreateSelected); 2352 linkPart.AddFlag(PrimFlags.CreateSelected);
2171 2353
2172 //if (linkPart.PhysActor != null) 2354 //if (linkPart.PhysActor != null)
2173 //{ 2355 //{
2174 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2356 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2175 2357
2176 //linkPart.PhysActor = null; 2358 //linkPart.PhysActor = null;
2177 //} 2359 //}
2178 2360
2179 //TODO: rest of parts 2361 //TODO: rest of parts
2180 int linkNum = 3; 2362 int linkNum = 3;
2181 foreach (SceneObjectPart part in objectGroup.Children.Values) 2363 foreach (SceneObjectPart part in objectGroup.Children.Values)
2364 {
2365 if (part.UUID != objectGroup.m_rootPart.UUID)
2182 { 2366 {
2183 if (part.UUID != objectGroup.m_rootPart.UUID) 2367 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2184 {
2185 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2186 }
2187 part.ClearUndoState();
2188 } 2368 }
2369 part.ClearUndoState();
2189 } 2370 }
2190 2371
2191 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2372 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2192 objectGroup.m_isDeleted = true; 2373 objectGroup.m_isDeleted = true;
2374
2375 objectGroup.lockPartsForWrite(true);
2193 2376
2194 lock (objectGroup.m_parts) 2377 objectGroup.m_parts.Clear();
2195 { 2378
2196 objectGroup.m_parts.Clear(); 2379 objectGroup.lockPartsForWrite(false);
2197 }
2198 2380
2199 // Can't do this yet since backup still makes use of the root part without any synchronization 2381 // Can't do this yet since backup still makes use of the root part without any synchronization
2200// objectGroup.m_rootPart = null; 2382// objectGroup.m_rootPart = null;
@@ -2253,11 +2435,12 @@ namespace OpenSim.Region.Framework.Scenes
2253 Quaternion worldRot = linkPart.GetWorldRotation(); 2435 Quaternion worldRot = linkPart.GetWorldRotation();
2254 2436
2255 // Remove the part from this object 2437 // Remove the part from this object
2256 lock (m_parts) 2438 lockPartsForWrite(true);
2257 { 2439 {
2258 m_parts.Remove(linkPart.UUID); 2440 m_parts.Remove(linkPart.UUID);
2259 } 2441 }
2260 2442 lockPartsForWrite(false);
2443 lockPartsForRead(true);
2261 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2444 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2262 RootPart.LinkNum = 0; 2445 RootPart.LinkNum = 0;
2263 else 2446 else
@@ -2268,6 +2451,7 @@ namespace OpenSim.Region.Framework.Scenes
2268 p.LinkNum--; 2451 p.LinkNum--;
2269 } 2452 }
2270 } 2453 }
2454 lockPartsForRead(false);
2271 2455
2272 linkPart.ParentID = 0; 2456 linkPart.ParentID = 0;
2273 linkPart.LinkNum = 0; 2457 linkPart.LinkNum = 0;
@@ -2585,9 +2769,12 @@ namespace OpenSim.Region.Framework.Scenes
2585 2769
2586 if (selectionPart != null) 2770 if (selectionPart != null)
2587 { 2771 {
2588 lock (m_parts) 2772 lockPartsForRead(true);
2773 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
2774 lockPartsForRead(false);
2775 foreach (SceneObjectPart part in parts)
2589 { 2776 {
2590 foreach (SceneObjectPart part in m_parts.Values) 2777 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2591 { 2778 {
2592 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 2779 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2593 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 2780 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
@@ -2597,12 +2784,13 @@ namespace OpenSim.Region.Framework.Scenes
2597 break; 2784 break;
2598 } 2785 }
2599 } 2786 }
2787 }
2600 2788
2601 foreach (SceneObjectPart part in m_parts.Values) 2789 foreach (SceneObjectPart part in parts)
2602 { 2790 {
2603 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2791 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2604 }
2605 } 2792 }
2793
2606 } 2794 }
2607 } 2795 }
2608 2796
@@ -2688,11 +2876,9 @@ namespace OpenSim.Region.Framework.Scenes
2688 scale.Y = m_scene.m_maxNonphys; 2876 scale.Y = m_scene.m_maxNonphys;
2689 if (scale.Z > m_scene.m_maxNonphys) 2877 if (scale.Z > m_scene.m_maxNonphys)
2690 scale.Z = m_scene.m_maxNonphys; 2878 scale.Z = m_scene.m_maxNonphys;
2691
2692 SceneObjectPart part = GetChildPart(localID); 2879 SceneObjectPart part = GetChildPart(localID);
2693 if (part != null) 2880 if (part != null)
2694 { 2881 {
2695 part.Resize(scale);
2696 if (part.PhysActor != null) 2882 if (part.PhysActor != null)
2697 { 2883 {
2698 if (part.PhysActor.IsPhysical) 2884 if (part.PhysActor.IsPhysical)
@@ -2707,7 +2893,7 @@ namespace OpenSim.Region.Framework.Scenes
2707 part.PhysActor.Size = scale; 2893 part.PhysActor.Size = scale;
2708 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 2894 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2709 } 2895 }
2710 //if (part.UUID != m_rootPart.UUID) 2896 part.Resize(scale);
2711 2897
2712 HasGroupChanged = true; 2898 HasGroupChanged = true;
2713 ScheduleGroupForFullUpdate(); 2899 ScheduleGroupForFullUpdate();
@@ -2748,77 +2934,76 @@ namespace OpenSim.Region.Framework.Scenes
2748 float y = (scale.Y / part.Scale.Y); 2934 float y = (scale.Y / part.Scale.Y);
2749 float z = (scale.Z / part.Scale.Z); 2935 float z = (scale.Z / part.Scale.Z);
2750 2936
2751 lock (m_parts) 2937 lockPartsForRead(true);
2938 if (x > 1.0f || y > 1.0f || z > 1.0f)
2752 { 2939 {
2753 if (x > 1.0f || y > 1.0f || z > 1.0f) 2940 foreach (SceneObjectPart obPart in m_parts.Values)
2754 { 2941 {
2755 foreach (SceneObjectPart obPart in m_parts.Values) 2942 if (obPart.UUID != m_rootPart.UUID)
2756 { 2943 {
2757 if (obPart.UUID != m_rootPart.UUID) 2944 Vector3 oldSize = new Vector3(obPart.Scale);
2758 {
2759 Vector3 oldSize = new Vector3(obPart.Scale);
2760 2945
2761 float f = 1.0f; 2946 float f = 1.0f;
2762 float a = 1.0f; 2947 float a = 1.0f;
2763 2948
2764 if (part.PhysActor != null && part.PhysActor.IsPhysical) 2949 if (part.PhysActor != null && part.PhysActor.IsPhysical)
2950 {
2951 if (oldSize.X*x > m_scene.m_maxPhys)
2765 { 2952 {
2766 if (oldSize.X*x > m_scene.m_maxPhys) 2953 f = m_scene.m_maxPhys / oldSize.X;
2767 { 2954 a = f / x;
2768 f = m_scene.m_maxPhys / oldSize.X; 2955 x *= a;
2769 a = f / x; 2956 y *= a;
2770 x *= a; 2957 z *= a;
2771 y *= a;
2772 z *= a;
2773 }
2774 if (oldSize.Y*y > m_scene.m_maxPhys)
2775 {
2776 f = m_scene.m_maxPhys / oldSize.Y;
2777 a = f / y;
2778 x *= a;
2779 y *= a;
2780 z *= a;
2781 }
2782 if (oldSize.Z*z > m_scene.m_maxPhys)
2783 {
2784 f = m_scene.m_maxPhys / oldSize.Z;
2785 a = f / z;
2786 x *= a;
2787 y *= a;
2788 z *= a;
2789 }
2790 } 2958 }
2791 else 2959 if (oldSize.Y*y > m_scene.m_maxPhys)
2960 {
2961 f = m_scene.m_maxPhys / oldSize.Y;
2962 a = f / y;
2963 x *= a;
2964 y *= a;
2965 z *= a;
2966 }
2967 if (oldSize.Z*z > m_scene.m_maxPhys)
2792 { 2968 {
2793 if (oldSize.X*x > m_scene.m_maxNonphys) 2969 f = m_scene.m_maxPhys / oldSize.Z;
2794 { 2970 a = f / z;
2795 f = m_scene.m_maxNonphys / oldSize.X; 2971 x *= a;
2796 a = f / x; 2972 y *= a;
2797 x *= a; 2973 z *= a;
2798 y *= a; 2974 }
2799 z *= a; 2975 }
2800 } 2976 else
2801 if (oldSize.Y*y > m_scene.m_maxNonphys) 2977 {
2802 { 2978 if (oldSize.X*x > m_scene.m_maxNonphys)
2803 f = m_scene.m_maxNonphys / oldSize.Y; 2979 {
2804 a = f / y; 2980 f = m_scene.m_maxNonphys / oldSize.X;
2805 x *= a; 2981 a = f / x;
2806 y *= a; 2982 x *= a;
2807 z *= a; 2983 y *= a;
2808 } 2984 z *= a;
2809 if (oldSize.Z*z > m_scene.m_maxNonphys) 2985 }
2810 { 2986 if (oldSize.Y*y > m_scene.m_maxNonphys)
2811 f = m_scene.m_maxNonphys / oldSize.Z; 2987 {
2812 a = f / z; 2988 f = m_scene.m_maxNonphys / oldSize.Y;
2813 x *= a; 2989 a = f / y;
2814 y *= a; 2990 x *= a;
2815 z *= a; 2991 y *= a;
2816 } 2992 z *= a;
2993 }
2994 if (oldSize.Z*z > m_scene.m_maxNonphys)
2995 {
2996 f = m_scene.m_maxNonphys / oldSize.Z;
2997 a = f / z;
2998 x *= a;
2999 y *= a;
3000 z *= a;
2817 } 3001 }
2818 } 3002 }
2819 } 3003 }
2820 } 3004 }
2821 } 3005 }
3006 lockPartsForRead(false);
2822 3007
2823 Vector3 prevScale = part.Scale; 3008 Vector3 prevScale = part.Scale;
2824 prevScale.X *= x; 3009 prevScale.X *= x;
@@ -2826,7 +3011,7 @@ namespace OpenSim.Region.Framework.Scenes
2826 prevScale.Z *= z; 3011 prevScale.Z *= z;
2827 part.Resize(prevScale); 3012 part.Resize(prevScale);
2828 3013
2829 lock (m_parts) 3014 lockPartsForRead(true);
2830 { 3015 {
2831 foreach (SceneObjectPart obPart in m_parts.Values) 3016 foreach (SceneObjectPart obPart in m_parts.Values)
2832 { 3017 {
@@ -2845,6 +3030,7 @@ namespace OpenSim.Region.Framework.Scenes
2845 } 3030 }
2846 } 3031 }
2847 } 3032 }
3033 lockPartsForRead(false);
2848 3034
2849 if (part.PhysActor != null) 3035 if (part.PhysActor != null)
2850 { 3036 {
@@ -2925,7 +3111,7 @@ namespace OpenSim.Region.Framework.Scenes
2925 axDiff *= Quaternion.Inverse(partRotation); 3111 axDiff *= Quaternion.Inverse(partRotation);
2926 diff = axDiff; 3112 diff = axDiff;
2927 3113
2928 lock (m_parts) 3114 lockPartsForRead(true);
2929 { 3115 {
2930 foreach (SceneObjectPart obPart in m_parts.Values) 3116 foreach (SceneObjectPart obPart in m_parts.Values)
2931 { 3117 {
@@ -2935,6 +3121,7 @@ namespace OpenSim.Region.Framework.Scenes
2935 } 3121 }
2936 } 3122 }
2937 } 3123 }
3124 lockPartsForRead(false);
2938 3125
2939 AbsolutePosition = newPos; 3126 AbsolutePosition = newPos;
2940 3127
@@ -3052,7 +3239,7 @@ namespace OpenSim.Region.Framework.Scenes
3052 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3239 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3053 } 3240 }
3054 3241
3055 lock (m_parts) 3242 lockPartsForRead(true);
3056 { 3243 {
3057 foreach (SceneObjectPart prim in m_parts.Values) 3244 foreach (SceneObjectPart prim in m_parts.Values)
3058 { 3245 {
@@ -3070,6 +3257,7 @@ namespace OpenSim.Region.Framework.Scenes
3070 } 3257 }
3071 } 3258 }
3072 } 3259 }
3260 lockPartsForRead(false);
3073 3261
3074 m_rootPart.ScheduleTerseUpdate(); 3262 m_rootPart.ScheduleTerseUpdate();
3075 } 3263 }
@@ -3168,7 +3356,7 @@ namespace OpenSim.Region.Framework.Scenes
3168 if (atTargets.Count > 0) 3356 if (atTargets.Count > 0)
3169 { 3357 {
3170 uint[] localids = new uint[0]; 3358 uint[] localids = new uint[0];
3171 lock (m_parts) 3359 lockPartsForRead(true);
3172 { 3360 {
3173 localids = new uint[m_parts.Count]; 3361 localids = new uint[m_parts.Count];
3174 int cntr = 0; 3362 int cntr = 0;
@@ -3178,6 +3366,7 @@ namespace OpenSim.Region.Framework.Scenes
3178 cntr++; 3366 cntr++;
3179 } 3367 }
3180 } 3368 }
3369 lockPartsForRead(false);
3181 3370
3182 for (int ctr = 0; ctr < localids.Length; ctr++) 3371 for (int ctr = 0; ctr < localids.Length; ctr++)
3183 { 3372 {
@@ -3196,7 +3385,7 @@ namespace OpenSim.Region.Framework.Scenes
3196 { 3385 {
3197 //trigger not_at_target 3386 //trigger not_at_target
3198 uint[] localids = new uint[0]; 3387 uint[] localids = new uint[0];
3199 lock (m_parts) 3388 lockPartsForRead(true);
3200 { 3389 {
3201 localids = new uint[m_parts.Count]; 3390 localids = new uint[m_parts.Count];
3202 int cntr = 0; 3391 int cntr = 0;
@@ -3206,7 +3395,8 @@ namespace OpenSim.Region.Framework.Scenes
3206 cntr++; 3395 cntr++;
3207 } 3396 }
3208 } 3397 }
3209 3398 lockPartsForRead(false);
3399
3210 for (int ctr = 0; ctr < localids.Length; ctr++) 3400 for (int ctr = 0; ctr < localids.Length; ctr++)
3211 { 3401 {
3212 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3402 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3219,19 +3409,20 @@ namespace OpenSim.Region.Framework.Scenes
3219 public float GetMass() 3409 public float GetMass()
3220 { 3410 {
3221 float retmass = 0f; 3411 float retmass = 0f;
3222 lock (m_parts) 3412 lockPartsForRead(true);
3223 { 3413 {
3224 foreach (SceneObjectPart part in m_parts.Values) 3414 foreach (SceneObjectPart part in m_parts.Values)
3225 { 3415 {
3226 retmass += part.GetMass(); 3416 retmass += part.GetMass();
3227 } 3417 }
3228 } 3418 }
3419 lockPartsForRead(false);
3229 return retmass; 3420 return retmass;
3230 } 3421 }
3231 3422
3232 public void CheckSculptAndLoad() 3423 public void CheckSculptAndLoad()
3233 { 3424 {
3234 lock (m_parts) 3425 lockPartsForRead(true);
3235 { 3426 {
3236 if (!IsDeleted) 3427 if (!IsDeleted)
3237 { 3428 {
@@ -3256,6 +3447,7 @@ namespace OpenSim.Region.Framework.Scenes
3256 } 3447 }
3257 } 3448 }
3258 } 3449 }
3450 lockPartsForRead(false);
3259 } 3451 }
3260 3452
3261 protected void AssetReceived(string id, Object sender, AssetBase asset) 3453 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3276,7 +3468,7 @@ namespace OpenSim.Region.Framework.Scenes
3276 /// <param name="client"></param> 3468 /// <param name="client"></param>
3277 public void SetGroup(UUID GroupID, IClientAPI client) 3469 public void SetGroup(UUID GroupID, IClientAPI client)
3278 { 3470 {
3279 lock (m_parts) 3471 lockPartsForRead(true);
3280 { 3472 {
3281 foreach (SceneObjectPart part in m_parts.Values) 3473 foreach (SceneObjectPart part in m_parts.Values)
3282 { 3474 {
@@ -3286,7 +3478,7 @@ namespace OpenSim.Region.Framework.Scenes
3286 3478
3287 HasGroupChanged = true; 3479 HasGroupChanged = true;
3288 } 3480 }
3289 3481 lockPartsForRead(false);
3290 ScheduleGroupForFullUpdate(); 3482 ScheduleGroupForFullUpdate();
3291 } 3483 }
3292 3484
@@ -3305,11 +3497,12 @@ namespace OpenSim.Region.Framework.Scenes
3305 3497
3306 public void SetAttachmentPoint(byte point) 3498 public void SetAttachmentPoint(byte point)
3307 { 3499 {
3308 lock (m_parts) 3500 lockPartsForRead(true);
3309 { 3501 {
3310 foreach (SceneObjectPart part in m_parts.Values) 3502 foreach (SceneObjectPart part in m_parts.Values)
3311 part.SetAttachmentPoint(point); 3503 part.SetAttachmentPoint(point);
3312 } 3504 }
3505 lockPartsForRead(false);
3313 } 3506 }
3314 3507
3315 #region ISceneObject 3508 #region ISceneObject
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index b6916f2..19e3023 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -389,12 +389,16 @@ namespace OpenSim.Region.Framework.Scenes
389 } 389 }
390 390
391 /// <value> 391 /// <value>
392 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 392 /// Get the inventory list
393 /// </value> 393 /// </value>
394 public TaskInventoryDictionary TaskInventory 394 public TaskInventoryDictionary TaskInventory
395 { 395 {
396 get { return m_inventory.Items; } 396 get {
397 set { m_inventory.Items = value; } 397 return m_inventory.Items;
398 }
399 set {
400 m_inventory.Items = value;
401 }
398 } 402 }
399 403
400 public uint ObjectFlags 404 public uint ObjectFlags
@@ -1064,14 +1068,6 @@ namespace OpenSim.Region.Framework.Scenes
1064 } 1068 }
1065 } 1069 }
1066 1070
1067 /// <summary>
1068 /// Clear all pending updates of parts to clients
1069 /// </summary>
1070 private void ClearUpdateSchedule()
1071 {
1072 m_updateFlag = 0;
1073 }
1074
1075 private void SendObjectPropertiesToClient(UUID AgentID) 1071 private void SendObjectPropertiesToClient(UUID AgentID)
1076 { 1072 {
1077 ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences(); 1073 ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences();
@@ -2109,17 +2105,18 @@ namespace OpenSim.Region.Framework.Scenes
2109 //Trys to fetch sound id from prim's inventory. 2105 //Trys to fetch sound id from prim's inventory.
2110 //Prim's inventory doesn't support non script items yet 2106 //Prim's inventory doesn't support non script items yet
2111 2107
2112 lock (TaskInventory) 2108 TaskInventory.LockItemsForRead(true);
2109
2110 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2113 { 2111 {
2114 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2112 if (item.Value.Name == sound)
2115 { 2113 {
2116 if (item.Value.Name == sound) 2114 soundID = item.Value.ItemID;
2117 { 2115 break;
2118 soundID = item.Value.ItemID;
2119 break;
2120 }
2121 } 2116 }
2122 } 2117 }
2118
2119 TaskInventory.LockItemsForRead(false);
2123 } 2120 }
2124 2121
2125 List<ScenePresence> avatarts = m_parentGroup.Scene.GetAvatars(); 2122 List<ScenePresence> avatarts = m_parentGroup.Scene.GetAvatars();
@@ -2185,6 +2182,11 @@ namespace OpenSim.Region.Framework.Scenes
2185 ParentGroup.HasGroupChanged = true; 2182 ParentGroup.HasGroupChanged = true;
2186 ScheduleFullUpdate(); 2183 ScheduleFullUpdate();
2187 } 2184 }
2185
2186 public void RotLookAt(Quaternion target, float strength, float damping)
2187 {
2188 m_parentGroup.rotLookAt(target, strength, damping);
2189 }
2188 2190
2189 /// <summary> 2191 /// <summary>
2190 /// Schedules this prim for a full update 2192 /// Schedules this prim for a full update
@@ -2389,8 +2391,8 @@ namespace OpenSim.Region.Framework.Scenes
2389 { 2391 {
2390 const float ROTATION_TOLERANCE = 0.01f; 2392 const float ROTATION_TOLERANCE = 0.01f;
2391 const float VELOCITY_TOLERANCE = 0.001f; 2393 const float VELOCITY_TOLERANCE = 0.001f;
2392 const float POSITION_TOLERANCE = 0.05f; 2394 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2393 const int TIME_MS_TOLERANCE = 3000; 2395 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2394 2396
2395 if (m_updateFlag == 1) 2397 if (m_updateFlag == 1)
2396 { 2398 {
@@ -2404,7 +2406,7 @@ namespace OpenSim.Region.Framework.Scenes
2404 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 2406 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
2405 { 2407 {
2406 AddTerseUpdateToAllAvatars(); 2408 AddTerseUpdateToAllAvatars();
2407 ClearUpdateSchedule(); 2409
2408 2410
2409 // This causes the Scene to 'poll' physical objects every couple of frames 2411 // This causes the Scene to 'poll' physical objects every couple of frames
2410 // bad, so it's been replaced by an event driven method. 2412 // bad, so it's been replaced by an event driven method.
@@ -2422,16 +2424,18 @@ namespace OpenSim.Region.Framework.Scenes
2422 m_lastAngularVelocity = AngularVelocity; 2424 m_lastAngularVelocity = AngularVelocity;
2423 m_lastTerseSent = Environment.TickCount; 2425 m_lastTerseSent = Environment.TickCount;
2424 } 2426 }
2427 //Moved this outside of the if clause so updates don't get blocked.. *sigh*
2428 m_updateFlag = 0; //Why were we calling a function to do this? Inefficient! *screams*
2425 } 2429 }
2426 else 2430 else
2427 { 2431 {
2428 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes 2432 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes
2429 { 2433 {
2430 AddFullUpdateToAllAvatars(); 2434 AddFullUpdateToAllAvatars();
2431 ClearUpdateSchedule(); 2435 m_updateFlag = 0; //Same here
2432 } 2436 }
2433 } 2437 }
2434 ClearUpdateSchedule(); 2438 m_updateFlag = 0;
2435 } 2439 }
2436 2440
2437 /// <summary> 2441 /// <summary>
@@ -2458,17 +2462,16 @@ namespace OpenSim.Region.Framework.Scenes
2458 if (!UUID.TryParse(sound, out soundID)) 2462 if (!UUID.TryParse(sound, out soundID))
2459 { 2463 {
2460 // search sound file from inventory 2464 // search sound file from inventory
2461 lock (TaskInventory) 2465 TaskInventory.LockItemsForRead(true);
2466 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2462 { 2467 {
2463 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2468 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
2464 { 2469 {
2465 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 2470 soundID = item.Value.ItemID;
2466 { 2471 break;
2467 soundID = item.Value.ItemID;
2468 break;
2469 }
2470 } 2472 }
2471 } 2473 }
2474 TaskInventory.LockItemsForRead(false);
2472 } 2475 }
2473 2476
2474 if (soundID == UUID.Zero) 2477 if (soundID == UUID.Zero)
@@ -2684,6 +2687,13 @@ namespace OpenSim.Region.Framework.Scenes
2684 SetText(text); 2687 SetText(text);
2685 } 2688 }
2686 2689
2690 public void StopLookAt()
2691 {
2692 m_parentGroup.stopLookAt();
2693
2694 m_parentGroup.ScheduleGroupForTerseUpdate();
2695 }
2696
2687 public void StopMoveToTarget() 2697 public void StopMoveToTarget()
2688 { 2698 {
2689 m_parentGroup.stopMoveToTarget(); 2699 m_parentGroup.stopMoveToTarget();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 22eedba..4780ff2 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -80,7 +80,9 @@ namespace OpenSim.Region.Framework.Scenes
80 /// </value> 80 /// </value>
81 protected internal TaskInventoryDictionary Items 81 protected internal TaskInventoryDictionary Items
82 { 82 {
83 get { return m_items; } 83 get {
84 return m_items;
85 }
84 set 86 set
85 { 87 {
86 m_items = value; 88 m_items = value;
@@ -116,22 +118,25 @@ namespace OpenSim.Region.Framework.Scenes
116 /// <param name="linkNum">Link number for the part</param> 118 /// <param name="linkNum">Link number for the part</param>
117 public void ResetInventoryIDs() 119 public void ResetInventoryIDs()
118 { 120 {
119 lock (Items) 121 m_items.LockItemsForWrite(true);
122
123 if (0 == Items.Count)
120 { 124 {
121 if (0 == Items.Count) 125 m_items.LockItemsForWrite(false);
122 return; 126 return;
127 }
123 128
124 HasInventoryChanged = true; 129 HasInventoryChanged = true;
125 m_part.ParentGroup.HasGroupChanged = true; 130 m_part.ParentGroup.HasGroupChanged = true;
126 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 131 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
127 Items.Clear(); 132 Items.Clear();
128 133
129 foreach (TaskInventoryItem item in items) 134 foreach (TaskInventoryItem item in items)
130 { 135 {
131 item.ResetIDs(m_part.UUID); 136 item.ResetIDs(m_part.UUID);
132 Items.Add(item.ItemID, item); 137 Items.Add(item.ItemID, item);
133 }
134 } 138 }
139 m_items.LockItemsForWrite(false);
135 } 140 }
136 141
137 /// <summary> 142 /// <summary>
@@ -140,25 +145,25 @@ namespace OpenSim.Region.Framework.Scenes
140 /// <param name="ownerId"></param> 145 /// <param name="ownerId"></param>
141 public void ChangeInventoryOwner(UUID ownerId) 146 public void ChangeInventoryOwner(UUID ownerId)
142 { 147 {
143 lock (Items) 148 m_items.LockItemsForWrite(true);
149 if (0 == Items.Count)
144 { 150 {
145 if (0 == Items.Count) 151 m_items.LockItemsForWrite(false);
146 { 152 return;
147 return; 153 }
148 }
149 154
150 HasInventoryChanged = true; 155 HasInventoryChanged = true;
151 m_part.ParentGroup.HasGroupChanged = true; 156 m_part.ParentGroup.HasGroupChanged = true;
152 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 157 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
153 foreach (TaskInventoryItem item in items) 158 foreach (TaskInventoryItem item in items)
159 {
160 if (ownerId != item.OwnerID)
154 { 161 {
155 if (ownerId != item.OwnerID) 162 item.LastOwnerID = item.OwnerID;
156 { 163 item.OwnerID = ownerId;
157 item.LastOwnerID = item.OwnerID;
158 item.OwnerID = ownerId;
159 }
160 } 164 }
161 } 165 }
166 m_items.LockItemsForWrite(false);
162 } 167 }
163 168
164 /// <summary> 169 /// <summary>
@@ -167,24 +172,24 @@ namespace OpenSim.Region.Framework.Scenes
167 /// <param name="groupID"></param> 172 /// <param name="groupID"></param>
168 public void ChangeInventoryGroup(UUID groupID) 173 public void ChangeInventoryGroup(UUID groupID)
169 { 174 {
170 lock (Items) 175 m_items.LockItemsForWrite(true);
176 if (0 == Items.Count)
171 { 177 {
172 if (0 == Items.Count) 178 m_items.LockItemsForWrite(false);
173 { 179 return;
174 return; 180 }
175 }
176 181
177 HasInventoryChanged = true; 182 HasInventoryChanged = true;
178 m_part.ParentGroup.HasGroupChanged = true; 183 m_part.ParentGroup.HasGroupChanged = true;
179 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 184 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
180 foreach (TaskInventoryItem item in items) 185 foreach (TaskInventoryItem item in items)
186 {
187 if (groupID != item.GroupID)
181 { 188 {
182 if (groupID != item.GroupID) 189 item.GroupID = groupID;
183 {
184 item.GroupID = groupID;
185 }
186 } 190 }
187 } 191 }
192 m_items.LockItemsForWrite(false);
188 } 193 }
189 194
190 /// <summary> 195 /// <summary>
@@ -192,14 +197,14 @@ namespace OpenSim.Region.Framework.Scenes
192 /// </summary> 197 /// </summary>
193 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) 198 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
194 { 199 {
195 lock (m_items) 200 Items.LockItemsForRead(true);
201 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
202 Items.LockItemsForRead(false);
203 foreach (TaskInventoryItem item in items)
196 { 204 {
197 foreach (TaskInventoryItem item in Items.Values) 205 if ((int)InventoryType.LSL == item.InvType)
198 { 206 {
199 if ((int)InventoryType.LSL == item.InvType) 207 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
200 {
201 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
202 }
203 } 208 }
204 } 209 }
205 } 210 }
@@ -209,17 +214,20 @@ namespace OpenSim.Region.Framework.Scenes
209 /// </summary> 214 /// </summary>
210 public void RemoveScriptInstances() 215 public void RemoveScriptInstances()
211 { 216 {
212 lock (Items) 217 Items.LockItemsForRead(true);
218 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
219 Items.LockItemsForRead(false);
220
221 foreach (TaskInventoryItem item in items)
213 { 222 {
214 foreach (TaskInventoryItem item in Items.Values) 223 if ((int)InventoryType.LSL == item.InvType)
215 { 224 {
216 if ((int)InventoryType.LSL == item.InvType) 225 RemoveScriptInstance(item.ItemID);
217 { 226 m_part.RemoveScriptEvents(item.ItemID);
218 RemoveScriptInstance(item.ItemID);
219 m_part.RemoveScriptEvents(item.ItemID);
220 }
221 } 227 }
222 } 228 }
229
230
223 } 231 }
224 232
225 /// <summary> 233 /// <summary>
@@ -244,8 +252,10 @@ namespace OpenSim.Region.Framework.Scenes
244 if (stateSource == 1 && // Prim crossing 252 if (stateSource == 1 && // Prim crossing
245 m_part.ParentGroup.Scene.m_trustBinaries) 253 m_part.ParentGroup.Scene.m_trustBinaries)
246 { 254 {
255 m_items.LockItemsForWrite(true);
247 m_items[item.ItemID].PermsMask = 0; 256 m_items[item.ItemID].PermsMask = 0;
248 m_items[item.ItemID].PermsGranter = UUID.Zero; 257 m_items[item.ItemID].PermsGranter = UUID.Zero;
258 m_items.LockItemsForWrite(false);
249 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 259 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
250 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 260 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
251 m_part.ParentGroup.AddActiveScriptCount(1); 261 m_part.ParentGroup.AddActiveScriptCount(1);
@@ -267,8 +277,10 @@ namespace OpenSim.Region.Framework.Scenes
267 { 277 {
268 if (m_part.ParentGroup.m_savedScriptState != null) 278 if (m_part.ParentGroup.m_savedScriptState != null)
269 RestoreSavedScriptState(item.OldItemID, item.ItemID); 279 RestoreSavedScriptState(item.OldItemID, item.ItemID);
280 m_items.LockItemsForWrite(true);
270 m_items[item.ItemID].PermsMask = 0; 281 m_items[item.ItemID].PermsMask = 0;
271 m_items[item.ItemID].PermsGranter = UUID.Zero; 282 m_items[item.ItemID].PermsGranter = UUID.Zero;
283 m_items.LockItemsForWrite(false);
272 string script = Utils.BytesToString(asset.Data); 284 string script = Utils.BytesToString(asset.Data);
273 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 285 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
274 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 286 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
@@ -303,7 +315,8 @@ namespace OpenSim.Region.Framework.Scenes
303 /// </param> 315 /// </param>
304 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 316 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
305 { 317 {
306 lock (m_items) 318 m_items.LockItemsForRead(true);
319 if (m_items.ContainsKey(itemId))
307 { 320 {
308 if (m_items.ContainsKey(itemId)) 321 if (m_items.ContainsKey(itemId))
309 { 322 {
@@ -317,7 +330,17 @@ namespace OpenSim.Region.Framework.Scenes
317 itemId, m_part.Name, m_part.UUID, 330 itemId, m_part.Name, m_part.UUID,
318 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 331 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
319 } 332 }
333 m_items.LockItemsForRead(false);
334 }
335 else
336 {
337 m_items.LockItemsForRead(false);
338 m_log.ErrorFormat(
339 "[PRIM INVENTORY]: " +
340 "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2}",
341 itemId, m_part.Name, m_part.UUID);
320 } 342 }
343
321 } 344 }
322 345
323 /// <summary> 346 /// <summary>
@@ -349,11 +372,16 @@ namespace OpenSim.Region.Framework.Scenes
349 /// <returns></returns> 372 /// <returns></returns>
350 private bool InventoryContainsName(string name) 373 private bool InventoryContainsName(string name)
351 { 374 {
352 foreach (TaskInventoryItem item in Items.Values) 375 m_items.LockItemsForRead(true);
376 foreach (TaskInventoryItem item in m_items.Values)
353 { 377 {
354 if (item.Name == name) 378 if (item.Name == name)
379 {
380 m_items.LockItemsForRead(false);
355 return true; 381 return true;
382 }
356 } 383 }
384 m_items.LockItemsForRead(false);
357 return false; 385 return false;
358 } 386 }
359 387
@@ -395,7 +423,9 @@ namespace OpenSim.Region.Framework.Scenes
395 /// <param name="item"></param> 423 /// <param name="item"></param>
396 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 424 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
397 { 425 {
426 m_items.LockItemsForRead(true);
398 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values); 427 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
428 m_items.LockItemsForRead(false);
399 foreach (TaskInventoryItem i in il) 429 foreach (TaskInventoryItem i in il)
400 { 430 {
401 if (i.Name == item.Name) 431 if (i.Name == item.Name)
@@ -432,15 +462,14 @@ namespace OpenSim.Region.Framework.Scenes
432 item.ParentPartID = m_part.UUID; 462 item.ParentPartID = m_part.UUID;
433 item.Name = name; 463 item.Name = name;
434 464
435 lock (m_items) 465 m_items.LockItemsForWrite(true);
436 { 466 m_items.Add(item.ItemID, item);
437 m_items.Add(item.ItemID, item); 467 m_items.LockItemsForWrite(false);
438
439 if (allowedDrop) 468 if (allowedDrop)
440 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 469 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
441 else 470 else
442 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 471 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
443 } 472
444 473
445 m_inventorySerial++; 474 m_inventorySerial++;
446 //m_inventorySerial += 2; 475 //m_inventorySerial += 2;
@@ -457,14 +486,13 @@ namespace OpenSim.Region.Framework.Scenes
457 /// <param name="items"></param> 486 /// <param name="items"></param>
458 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 487 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
459 { 488 {
460 lock (m_items) 489 m_items.LockItemsForWrite(true);
490 foreach (TaskInventoryItem item in items)
461 { 491 {
462 foreach (TaskInventoryItem item in items) 492 m_items.Add(item.ItemID, item);
463 { 493 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
464 m_items.Add(item.ItemID, item);
465 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
466 }
467 } 494 }
495 m_items.LockItemsForWrite(false);
468 496
469 m_inventorySerial++; 497 m_inventorySerial++;
470 } 498 }
@@ -477,8 +505,9 @@ namespace OpenSim.Region.Framework.Scenes
477 public TaskInventoryItem GetInventoryItem(UUID itemId) 505 public TaskInventoryItem GetInventoryItem(UUID itemId)
478 { 506 {
479 TaskInventoryItem item; 507 TaskInventoryItem item;
508 m_items.LockItemsForRead(true);
480 m_items.TryGetValue(itemId, out item); 509 m_items.TryGetValue(itemId, out item);
481 510 m_items.LockItemsForRead(false);
482 return item; 511 return item;
483 } 512 }
484 513
@@ -490,46 +519,46 @@ namespace OpenSim.Region.Framework.Scenes
490 /// <returns>false if the item did not exist, true if the update occurred successfully</returns> 519 /// <returns>false if the item did not exist, true if the update occurred successfully</returns>
491 public bool UpdateInventoryItem(TaskInventoryItem item) 520 public bool UpdateInventoryItem(TaskInventoryItem item)
492 { 521 {
493 lock (m_items) 522 m_items.LockItemsForWrite(true);
523
524 if (m_items.ContainsKey(item.ItemID))
494 { 525 {
495 if (m_items.ContainsKey(item.ItemID)) 526 item.ParentID = m_part.UUID;
527 item.ParentPartID = m_part.UUID;
528 item.Flags = m_items[item.ItemID].Flags;
529 if (item.AssetID == UUID.Zero)
496 { 530 {
497 item.ParentID = m_part.UUID; 531 item.AssetID = m_items[item.ItemID].AssetID;
498 item.ParentPartID = m_part.UUID; 532 }
499 item.Flags = m_items[item.ItemID].Flags; 533 else if ((InventoryType)item.Type == InventoryType.Notecard)
500 if (item.AssetID == UUID.Zero) 534 {
501 { 535 ScenePresence presence = m_part.ParentGroup.Scene.GetScenePresence(item.OwnerID);
502 item.AssetID = m_items[item.ItemID].AssetID;
503 }
504 else if ((InventoryType)item.Type == InventoryType.Notecard)
505 {
506 ScenePresence presence = m_part.ParentGroup.Scene.GetScenePresence(item.OwnerID);
507 536
508 if (presence != null) 537 if (presence != null)
509 { 538 {
510 presence.ControllingClient.SendAgentAlertMessage( 539 presence.ControllingClient.SendAgentAlertMessage(
511 "Notecard saved", false); 540 "Notecard saved", false);
512 }
513 } 541 }
542 }
514 543
515 m_items[item.ItemID] = item; 544 m_items[item.ItemID] = item;
516 m_inventorySerial++; 545 m_inventorySerial++;
517 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 546 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
518
519 HasInventoryChanged = true;
520 m_part.ParentGroup.HasGroupChanged = true;
521 547
522 return true; 548 HasInventoryChanged = true;
523 } 549 m_part.ParentGroup.HasGroupChanged = true;
524 else 550 m_items.LockItemsForWrite(false);
525 { 551 return true;
526 m_log.ErrorFormat( 552 }
527 "[PRIM INVENTORY]: " + 553 else
528 "Tried to retrieve item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", 554 {
529 item.ItemID, m_part.Name, m_part.UUID, 555 m_log.ErrorFormat(
530 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 556 "[PRIM INVENTORY]: " +
531 } 557 "Tried to retrieve item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory",
558 item.ItemID, m_part.Name, m_part.UUID,
559 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
532 } 560 }
561 m_items.LockItemsForWrite(false);
533 562
534 return false; 563 return false;
535 } 564 }
@@ -542,52 +571,54 @@ namespace OpenSim.Region.Framework.Scenes
542 /// in this prim's inventory.</returns> 571 /// in this prim's inventory.</returns>
543 public int RemoveInventoryItem(UUID itemID) 572 public int RemoveInventoryItem(UUID itemID)
544 { 573 {
545 lock (m_items) 574 m_items.LockItemsForRead(true);
575
576 if (m_items.ContainsKey(itemID))
546 { 577 {
547 if (m_items.ContainsKey(itemID)) 578 int type = m_items[itemID].InvType;
579 m_items.LockItemsForRead(false);
580 if (type == 10) // Script
548 { 581 {
549 int type = m_items[itemID].InvType; 582 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
550 if (type == 10) // Script 583 }
551 { 584 m_items.LockItemsForWrite(true);
552 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 585 m_items.Remove(itemID);
553 } 586 m_items.LockItemsForWrite(false);
554 m_items.Remove(itemID); 587 m_inventorySerial++;
555 m_inventorySerial++; 588 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
556 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
557
558 HasInventoryChanged = true;
559 m_part.ParentGroup.HasGroupChanged = true;
560 589
561 int scriptcount = 0; 590 HasInventoryChanged = true;
562 lock (m_items) 591 m_part.ParentGroup.HasGroupChanged = true;
563 {
564 foreach (TaskInventoryItem item in m_items.Values)
565 {
566 if (item.Type == 10)
567 {
568 scriptcount++;
569 }
570 }
571 }
572 592
573 if (scriptcount <= 0) 593 int scriptcount = 0;
594 m_items.LockItemsForRead(true);
595 foreach (TaskInventoryItem item in m_items.Values)
596 {
597 if (item.Type == 10)
574 { 598 {
575 m_part.RemFlag(PrimFlags.Scripted); 599 scriptcount++;
576 } 600 }
577
578 m_part.ScheduleFullUpdate();
579
580 return type;
581 } 601 }
582 else 602 m_items.LockItemsForRead(false);
603
604
605 if (scriptcount <= 0)
583 { 606 {
584 m_log.ErrorFormat( 607 m_part.RemFlag(PrimFlags.Scripted);
585 "[PRIM INVENTORY]: " +
586 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory",
587 itemID, m_part.Name, m_part.UUID,
588 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
589 } 608 }
609
610 m_part.ScheduleFullUpdate();
611
612 return type;
613 }
614 else
615 {
616 m_log.ErrorFormat(
617 "[PRIM INVENTORY]: " +
618 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
619 itemID, m_part.Name, m_part.UUID);
590 } 620 }
621 m_items.LockItemsForWrite(false);
591 622
592 return -1; 623 return -1;
593 } 624 }
@@ -640,52 +671,53 @@ namespace OpenSim.Region.Framework.Scenes
640 // isn't available (such as drag from prim inventory to agent inventory) 671 // isn't available (such as drag from prim inventory to agent inventory)
641 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); 672 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
642 673
643 lock (m_items) 674 m_items.LockItemsForRead(true);
675
676 foreach (TaskInventoryItem item in m_items.Values)
644 { 677 {
645 foreach (TaskInventoryItem item in m_items.Values) 678 UUID ownerID = item.OwnerID;
646 { 679 uint everyoneMask = 0;
647 UUID ownerID = item.OwnerID; 680 uint baseMask = item.BasePermissions;
648 uint everyoneMask = 0; 681 uint ownerMask = item.CurrentPermissions;
649 uint baseMask = item.BasePermissions;
650 uint ownerMask = item.CurrentPermissions;
651 682
652 invString.AddItemStart(); 683 invString.AddItemStart();
653 invString.AddNameValueLine("item_id", item.ItemID.ToString()); 684 invString.AddNameValueLine("item_id", item.ItemID.ToString());
654 invString.AddNameValueLine("parent_id", m_part.UUID.ToString()); 685 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
655 686
656 invString.AddPermissionsStart(); 687 invString.AddPermissionsStart();
657 688
658 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); 689 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
659 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); 690 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
660 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(0)); 691 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(0));
661 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask)); 692 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
662 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions)); 693 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
663 694
664 invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); 695 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
665 invString.AddNameValueLine("owner_id", ownerID.ToString()); 696 invString.AddNameValueLine("owner_id", ownerID.ToString());
666 697
667 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); 698 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
668 699
669 invString.AddNameValueLine("group_id", item.GroupID.ToString()); 700 invString.AddNameValueLine("group_id", item.GroupID.ToString());
670 invString.AddSectionEnd(); 701 invString.AddSectionEnd();
671 702
672 invString.AddNameValueLine("asset_id", item.AssetID.ToString()); 703 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
673 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]); 704 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]);
674 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]); 705 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]);
675 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags)); 706 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
676 707
677 invString.AddSaleStart(); 708 invString.AddSaleStart();
678 invString.AddNameValueLine("sale_type", "not"); 709 invString.AddNameValueLine("sale_type", "not");
679 invString.AddNameValueLine("sale_price", "0"); 710 invString.AddNameValueLine("sale_price", "0");
680 invString.AddSectionEnd(); 711 invString.AddSectionEnd();
681 712
682 invString.AddNameValueLine("name", item.Name + "|"); 713 invString.AddNameValueLine("name", item.Name + "|");
683 invString.AddNameValueLine("desc", item.Description + "|"); 714 invString.AddNameValueLine("desc", item.Description + "|");
684 715
685 invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); 716 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
686 invString.AddSectionEnd(); 717 invString.AddSectionEnd();
687 }
688 } 718 }
719 int count = m_items.Count;
720 m_items.LockItemsForRead(false);
689 721
690 fileData = Utils.StringToBytes(invString.BuildString); 722 fileData = Utils.StringToBytes(invString.BuildString);
691 723
@@ -706,10 +738,9 @@ namespace OpenSim.Region.Framework.Scenes
706 { 738 {
707 if (HasInventoryChanged) 739 if (HasInventoryChanged)
708 { 740 {
709 lock (Items) 741 Items.LockItemsForRead(true);
710 { 742 datastore.StorePrimInventory(m_part.UUID, Items.Values);
711 datastore.StorePrimInventory(m_part.UUID, Items.Values); 743 Items.LockItemsForRead(false);
712 }
713 744
714 HasInventoryChanged = false; 745 HasInventoryChanged = false;
715 } 746 }
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index a3ceecb..cd28434 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -73,7 +73,7 @@ namespace OpenSim.Region.Framework.Scenes
73// { 73// {
74// m_log.Debug("[ScenePresence] Destructor called"); 74// m_log.Debug("[ScenePresence] Destructor called");
75// } 75// }
76 76
77 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 77 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
78 78
79 private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 }; 79 private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 };
@@ -89,7 +89,9 @@ namespace OpenSim.Region.Framework.Scenes
89 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis 89 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis
90 /// issue #1716 90 /// issue #1716
91 /// </summary> 91 /// </summary>
92 private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f); 92// private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f);
93 // Value revised by KF 091121 by comparison with SL.
94 private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f);
93 95
94 public UUID currentParcelUUID = UUID.Zero; 96 public UUID currentParcelUUID = UUID.Zero;
95 97
@@ -113,7 +115,9 @@ namespace OpenSim.Region.Framework.Scenes
113 public Vector3 lastKnownAllowedPosition; 115 public Vector3 lastKnownAllowedPosition;
114 public bool sentMessageAboutRestrictedParcelFlyingDown; 116 public bool sentMessageAboutRestrictedParcelFlyingDown;
115 public Vector4 CollisionPlane = Vector4.UnitW; 117 public Vector4 CollisionPlane = Vector4.UnitW;
116 118
119 private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation
120 private Vector3 m_avUnscriptedSitPos; // for non-scripted prims
117 private Vector3 m_lastPosition; 121 private Vector3 m_lastPosition;
118 private Quaternion m_lastRotation; 122 private Quaternion m_lastRotation;
119 private Vector3 m_lastVelocity; 123 private Vector3 m_lastVelocity;
@@ -144,7 +148,6 @@ namespace OpenSim.Region.Framework.Scenes
144 private int m_perfMonMS; 148 private int m_perfMonMS;
145 149
146 private bool m_setAlwaysRun; 150 private bool m_setAlwaysRun;
147
148 private bool m_forceFly; 151 private bool m_forceFly;
149 private bool m_flyDisabled; 152 private bool m_flyDisabled;
150 153
@@ -168,7 +171,8 @@ namespace OpenSim.Region.Framework.Scenes
168 protected RegionInfo m_regionInfo; 171 protected RegionInfo m_regionInfo;
169 protected ulong crossingFromRegion; 172 protected ulong crossingFromRegion;
170 173
171 private readonly Vector3[] Dir_Vectors = new Vector3[6]; 174 private readonly Vector3[] Dir_Vectors = new Vector3[11];
175 private bool m_isNudging = false;
172 176
173 // Position of agent's camera in world (region cordinates) 177 // Position of agent's camera in world (region cordinates)
174 protected Vector3 m_CameraCenter; 178 protected Vector3 m_CameraCenter;
@@ -203,6 +207,9 @@ namespace OpenSim.Region.Framework.Scenes
203 private bool m_followCamAuto; 207 private bool m_followCamAuto;
204 208
205 private int m_movementUpdateCount; 209 private int m_movementUpdateCount;
210 private int m_lastColCount = -1; //KF: Look for Collision chnages
211 private int m_updateCount = 0; //KF: Update Anims for a while
212 private static readonly int UPDATE_COUNT = 10; // how many frames to update for
206 213
207 private const int NumMovementsBetweenRayCast = 5; 214 private const int NumMovementsBetweenRayCast = 5;
208 215
@@ -232,6 +239,10 @@ namespace OpenSim.Region.Framework.Scenes
232 DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG, 239 DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG,
233 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, 240 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
234 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, 241 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
242 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS,
243 DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
244 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
245 DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
235 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG 246 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
236 } 247 }
237 248
@@ -658,9 +669,7 @@ namespace OpenSim.Region.Framework.Scenes
658 669
659 AdjustKnownSeeds(); 670 AdjustKnownSeeds();
660 671
661 // TODO: I think, this won't send anything, as we are still a child here... 672 Animator.TrySetMovementAnimation("STAND");
662 Animator.TrySetMovementAnimation("STAND");
663
664 // we created a new ScenePresence (a new child agent) in a fresh region. 673 // we created a new ScenePresence (a new child agent) in a fresh region.
665 // Request info about all the (root) agents in this region 674 // Request info about all the (root) agents in this region
666 // Note: This won't send data *to* other clients in that region (children don't send) 675 // Note: This won't send data *to* other clients in that region (children don't send)
@@ -716,21 +725,47 @@ namespace OpenSim.Region.Framework.Scenes
716 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT 725 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT
717 Dir_Vectors[4] = Vector3.UnitZ; //UP 726 Dir_Vectors[4] = Vector3.UnitZ; //UP
718 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN 727 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN
719 Dir_Vectors[5] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge 728 Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE
729 Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE
730 Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE
731 Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE
732 Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
720 } 733 }
721 734
722 private Vector3[] GetWalkDirectionVectors() 735 private Vector3[] GetWalkDirectionVectors()
723 { 736 {
724 Vector3[] vector = new Vector3[6]; 737 Vector3[] vector = new Vector3[11];
725 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD 738 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD
726 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK 739 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK
727 vector[2] = Vector3.UnitY; //LEFT 740 vector[2] = Vector3.UnitY; //LEFT
728 vector[3] = -Vector3.UnitY; //RIGHT 741 vector[3] = -Vector3.UnitY; //RIGHT
729 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP 742 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP
730 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN 743 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN
731 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge 744 vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE
745 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE
746 vector[8] = Vector3.UnitY; //LEFT_NUDGE
747 vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
748 vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE
732 return vector; 749 return vector;
733 } 750 }
751
752 private bool[] GetDirectionIsNudge()
753 {
754 bool[] isNudge = new bool[11];
755 isNudge[0] = false; //FORWARD
756 isNudge[1] = false; //BACK
757 isNudge[2] = false; //LEFT
758 isNudge[3] = false; //RIGHT
759 isNudge[4] = false; //UP
760 isNudge[5] = false; //DOWN
761 isNudge[6] = true; //FORWARD_NUDGE
762 isNudge[7] = true; //BACK_NUDGE
763 isNudge[8] = true; //LEFT_NUDGE
764 isNudge[9] = true; //RIGHT_NUDGE
765 isNudge[10] = true; //DOWN_Nudge
766 return isNudge;
767 }
768
734 769
735 #endregion 770 #endregion
736 771
@@ -994,7 +1029,9 @@ namespace OpenSim.Region.Framework.Scenes
994 { 1029 {
995 AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f)); 1030 AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f));
996 } 1031 }
997 1032
1033 m_updateCount = UPDATE_COUNT; //KF: Trigger Anim updates to catch falling anim.
1034
998 ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId, 1035 ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId,
999 AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient))); 1036 AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient)));
1000 } 1037 }
@@ -1229,7 +1266,6 @@ namespace OpenSim.Region.Framework.Scenes
1229 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback); 1266 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback);
1230 } 1267 }
1231 } 1268 }
1232
1233 lock (scriptedcontrols) 1269 lock (scriptedcontrols)
1234 { 1270 {
1235 if (scriptedcontrols.Count > 0) 1271 if (scriptedcontrols.Count > 0)
@@ -1244,9 +1280,7 @@ namespace OpenSim.Region.Framework.Scenes
1244 1280
1245 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) 1281 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
1246 { 1282 {
1247 // TODO: This doesn't prevent the user from walking yet. 1283 m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.
1248 // Setting parent ID would fix this, if we knew what value
1249 // to use. Or we could add a m_isSitting variable.
1250 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); 1284 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
1251 } 1285 }
1252 1286
@@ -1261,7 +1295,6 @@ namespace OpenSim.Region.Framework.Scenes
1261 { 1295 {
1262 return; 1296 return;
1263 } 1297 }
1264
1265 if (m_allowMovement) 1298 if (m_allowMovement)
1266 { 1299 {
1267 int i = 0; 1300 int i = 0;
@@ -1289,6 +1322,11 @@ namespace OpenSim.Region.Framework.Scenes
1289 update_rotation = true; 1322 update_rotation = true;
1290 } 1323 }
1291 1324
1325 //guilty until proven innocent..
1326 bool Nudging = true;
1327 //Basically, if there is at least one non-nudge control then we don't need
1328 //to worry about stopping the avatar
1329
1292 if (m_parentID == 0) 1330 if (m_parentID == 0)
1293 { 1331 {
1294 bool bAllowUpdateMoveToPosition = false; 1332 bool bAllowUpdateMoveToPosition = false;
@@ -1303,6 +1341,12 @@ namespace OpenSim.Region.Framework.Scenes
1303 else 1341 else
1304 dirVectors = Dir_Vectors; 1342 dirVectors = Dir_Vectors;
1305 1343
1344 bool[] isNudge = GetDirectionIsNudge();
1345
1346
1347
1348
1349
1306 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) 1350 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
1307 { 1351 {
1308 if (((uint)flags & (uint)DCF) != 0) 1352 if (((uint)flags & (uint)DCF) != 0)
@@ -1312,6 +1356,10 @@ namespace OpenSim.Region.Framework.Scenes
1312 try 1356 try
1313 { 1357 {
1314 agent_control_v3 += dirVectors[i]; 1358 agent_control_v3 += dirVectors[i];
1359 if (isNudge[i] == false)
1360 {
1361 Nudging = false;
1362 }
1315 } 1363 }
1316 catch (IndexOutOfRangeException) 1364 catch (IndexOutOfRangeException)
1317 { 1365 {
@@ -1373,6 +1421,9 @@ namespace OpenSim.Region.Framework.Scenes
1373 // Ignore z component of vector 1421 // Ignore z component of vector
1374 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); 1422 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
1375 LocalVectorToTarget2D.Normalize(); 1423 LocalVectorToTarget2D.Normalize();
1424
1425 //We're not nudging
1426 Nudging = false;
1376 agent_control_v3 += LocalVectorToTarget2D; 1427 agent_control_v3 += LocalVectorToTarget2D;
1377 1428
1378 // update avatar movement flags. the avatar coordinate system is as follows: 1429 // update avatar movement flags. the avatar coordinate system is as follows:
@@ -1455,7 +1506,7 @@ namespace OpenSim.Region.Framework.Scenes
1455 // m_log.DebugFormat( 1506 // m_log.DebugFormat(
1456 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3); 1507 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
1457 1508
1458 AddNewMovement(agent_control_v3, q); 1509 AddNewMovement(agent_control_v3, q, Nudging);
1459 1510
1460 if (update_movementflag) 1511 if (update_movementflag)
1461 Animator.UpdateMovementAnimations(); 1512 Animator.UpdateMovementAnimations();
@@ -1538,7 +1589,7 @@ namespace OpenSim.Region.Framework.Scenes
1538 Velocity = Vector3.Zero; 1589 Velocity = Vector3.Zero;
1539 SendFullUpdateToAllClients(); 1590 SendFullUpdateToAllClients();
1540 1591
1541 //HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); 1592 HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ??
1542 } 1593 }
1543 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false); 1594 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false);
1544 m_requestedSitTargetUUID = UUID.Zero; 1595 m_requestedSitTargetUUID = UUID.Zero;
@@ -1576,21 +1627,19 @@ namespace OpenSim.Region.Framework.Scenes
1576 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); 1627 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
1577 if (part != null) 1628 if (part != null)
1578 { 1629 {
1630 part.TaskInventory.LockItemsForRead(true);
1579 TaskInventoryDictionary taskIDict = part.TaskInventory; 1631 TaskInventoryDictionary taskIDict = part.TaskInventory;
1580 if (taskIDict != null) 1632 if (taskIDict != null)
1581 { 1633 {
1582 lock (taskIDict) 1634 foreach (UUID taskID in taskIDict.Keys)
1583 { 1635 {
1584 foreach (UUID taskID in taskIDict.Keys) 1636 UnRegisterControlEventsToScript(LocalId, taskID);
1585 { 1637 taskIDict[taskID].PermsMask &= ~(
1586 UnRegisterControlEventsToScript(LocalId, taskID); 1638 2048 | //PERMISSION_CONTROL_CAMERA
1587 taskIDict[taskID].PermsMask &= ~( 1639 4); // PERMISSION_TAKE_CONTROLS
1588 2048 | //PERMISSION_CONTROL_CAMERA
1589 4); // PERMISSION_TAKE_CONTROLS
1590 }
1591 } 1640 }
1592
1593 } 1641 }
1642 part.TaskInventory.LockItemsForRead(false);
1594 // Reset sit target. 1643 // Reset sit target.
1595 if (part.GetAvatarOnSitTarget() == UUID) 1644 if (part.GetAvatarOnSitTarget() == UUID)
1596 part.SetAvatarOnSitTarget(UUID.Zero); 1645 part.SetAvatarOnSitTarget(UUID.Zero);
@@ -1603,9 +1652,9 @@ namespace OpenSim.Region.Framework.Scenes
1603 { 1652 {
1604 AddToPhysicalScene(false); 1653 AddToPhysicalScene(false);
1605 } 1654 }
1606
1607 m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight); 1655 m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight);
1608 m_parentPosition = Vector3.Zero; 1656 m_parentPosition = Vector3.Zero;
1657//Console.WriteLine("Stand Pos {0}", m_pos);
1609 1658
1610 m_parentID = 0; 1659 m_parentID = 0;
1611 SendFullUpdateToAllClients(); 1660 SendFullUpdateToAllClients();
@@ -1651,7 +1700,7 @@ namespace OpenSim.Region.Framework.Scenes
1651 bool SitTargetisSet = 1700 bool SitTargetisSet =
1652 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 1f && 1701 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 1f &&
1653 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f)); 1702 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f));
1654 1703 // this test is probably failing
1655 if (SitTargetisSet && SitTargetUnOccupied) 1704 if (SitTargetisSet && SitTargetUnOccupied)
1656 { 1705 {
1657 //switch the target to this prim 1706 //switch the target to this prim
@@ -1678,31 +1727,58 @@ namespace OpenSim.Region.Framework.Scenes
1678 { 1727 {
1679 // TODO: determine position to sit at based on scene geometry; don't trust offset from client 1728 // TODO: determine position to sit at based on scene geometry; don't trust offset from client
1680 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it 1729 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
1681 1730
1731 // part is the prim to sit on
1732 // offset is the vector distance from that prim center to the click-spot
1733 // UUID is the UUID of the Avatar doing the clicking
1734
1735 m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation
1736
1682 // Is a sit target available? 1737 // Is a sit target available?
1683 Vector3 avSitOffSet = part.SitTargetPosition; 1738 Vector3 avSitOffSet = part.SitTargetPosition;
1684 Quaternion avSitOrientation = part.SitTargetOrientation; 1739 Quaternion avSitOrientation = part.SitTargetOrientation;
1685 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1740 UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
1686 1741
1687 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1742 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero));
1688 bool SitTargetisSet = 1743// bool SitTargetisSet =
1689 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 0f && 1744// (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 0f &&
1690 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f)); 1745// avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f));
1691 1746
1692 if (SitTargetisSet && SitTargetUnOccupied) 1747 bool SitTargetisSet = ((Vector3.Zero != avSitOffSet) || (Quaternion.Identity != avSitOrientation));
1693 { 1748
1694 part.SetAvatarOnSitTarget(UUID); 1749//Console.WriteLine("SendSitResponse offset=" + offset + " UnOccup=" + SitTargetUnOccupied +
1695 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); 1750// " TargSet=" + SitTargetisSet);
1696 sitOrientation = avSitOrientation; 1751 // Sit analysis rewritten by KF 091125
1697 autopilot = false; 1752 if (SitTargetisSet) // scipted sit
1698 } 1753 {
1754 if (SitTargetUnOccupied)
1755 {
1756 part.SetAvatarOnSitTarget(UUID); // set that Av will be on it
1757 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
1758 sitOrientation = avSitOrientation; // Change rotatione to the scripted one
1759 autopilot = false; // Jump direct to scripted llSitPos()
1760 }
1761 else return;
1762 }
1763 else // Not Scripted
1764 {
1765 if ( (Math.Abs(offset.X) > 0.5f) || (Math.Abs(offset.Y) > 0.5f) ) // large prim
1766 {
1767 Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
1768 m_avUnscriptedSitPos = offset * partIRot; // sit where clicked
1769 pos = part.AbsolutePosition + (offset * partIRot);
1770 }
1771 else // small prim
1772 {
1773 if (SitTargetUnOccupied)
1774 {
1775 m_avUnscriptedSitPos = Vector3.Zero; // Sit on unoccupied small prim center
1776 pos = part.AbsolutePosition;
1777 }
1778 else return; // occupied small
1779 } // end large/small
1780 } // end Scripted/not
1699 1781
1700 pos = part.AbsolutePosition + offset;
1701 //if (Math.Abs(part.AbsolutePosition.Z - AbsolutePosition.Z) > 1)
1702 //{
1703 // offset = pos;
1704 //autopilot = false;
1705 //}
1706 if (m_physicsActor != null) 1782 if (m_physicsActor != null)
1707 { 1783 {
1708 // If we're not using the client autopilot, we're immediately warping the avatar to the location 1784 // If we're not using the client autopilot, we're immediately warping the avatar to the location
@@ -1710,17 +1786,17 @@ namespace OpenSim.Region.Framework.Scenes
1710 m_sitAvatarHeight = m_physicsActor.Size.Z; 1786 m_sitAvatarHeight = m_physicsActor.Size.Z;
1711 1787
1712 if (autopilot) 1788 if (autopilot)
1713 { 1789 { // its not a scripted sit
1714 if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5) 1790 if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5)
1715 { 1791 {
1716 autopilot = false; 1792 autopilot = false; // close enough
1717 1793
1718 RemoveFromPhysicalScene(); 1794 RemoveFromPhysicalScene();
1719 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); 1795 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to Prim
1720 } 1796 } // else the autopilot will get us close
1721 } 1797 }
1722 else 1798 else
1723 { 1799 { // its a scripted sit
1724 RemoveFromPhysicalScene(); 1800 RemoveFromPhysicalScene();
1725 } 1801 }
1726 } 1802 }
@@ -1823,29 +1899,52 @@ namespace OpenSim.Region.Framework.Scenes
1823 { 1899 {
1824 if (part.GetAvatarOnSitTarget() == UUID) 1900 if (part.GetAvatarOnSitTarget() == UUID)
1825 { 1901 {
1902 // Scripted sit
1826 Vector3 sitTargetPos = part.SitTargetPosition; 1903 Vector3 sitTargetPos = part.SitTargetPosition;
1827 Quaternion sitTargetOrient = part.SitTargetOrientation; 1904 Quaternion sitTargetOrient = part.SitTargetOrientation;
1828
1829 //Quaternion vq = new Quaternion(sitTargetPos.X, sitTargetPos.Y+0.2f, sitTargetPos.Z+0.2f, 0);
1830 //Quaternion nq = new Quaternion(-sitTargetOrient.X, -sitTargetOrient.Y, -sitTargetOrient.Z, sitTargetOrient.w);
1831
1832 //Quaternion result = (sitTargetOrient * vq) * nq;
1833
1834 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z); 1905 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
1835 m_pos += SIT_TARGET_ADJUSTMENT; 1906 m_pos += SIT_TARGET_ADJUSTMENT;
1836 m_bodyRot = sitTargetOrient; 1907 m_bodyRot = sitTargetOrient;
1837 //Rotation = sitTargetOrient;
1838 m_parentPosition = part.AbsolutePosition; 1908 m_parentPosition = part.AbsolutePosition;
1839
1840 //SendTerseUpdateToAllClients();
1841 } 1909 }
1842 else 1910 else
1843 { 1911 {
1844 m_pos -= part.AbsolutePosition; 1912 // Non-scripted sit by Kitto Flora 21Nov09
1913 // Calculate angle of line from prim to Av
1914 Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos;
1915 float y_diff = (m_avInitialPos.Y - sitTargetPos.Y);
1916 float x_diff = ( m_avInitialPos.X - sitTargetPos.X);
1917 if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0
1918 if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0
1919 float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff);
1920 Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
1921 // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'.
1922 // Av sits at world euler <0,0, z>, translated by part rotation
1923 m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click
1845 m_parentPosition = part.AbsolutePosition; 1924 m_parentPosition = part.AbsolutePosition;
1846 } 1925 if(m_avUnscriptedSitPos != Vector3.Zero)
1847 } 1926 { // sit where clicked on big prim
1848 else 1927 m_pos = m_avUnscriptedSitPos + (new Vector3(0.0f, 0f, 0.625f) * partIRot);
1928 }
1929 else
1930 { // sit at center of small prim
1931 m_pos = new Vector3(0f, 0f, 0.05f) +
1932 (new Vector3(0.0f, 0f, 0.625f) * partIRot) +
1933 (new Vector3(0.25f, 0f, 0.0f) * m_bodyRot);
1934 //Set up raytrace to find top surface of prim
1935 Vector3 size = part.Scale;
1936 float mag = 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
1937 Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
1938 Vector3 down = new Vector3(0f, 0f, -1f);
1939 m_scene.PhysicsScene.RaycastWorld(
1940 start, // Vector3 position,
1941 down, // Vector3 direction,
1942 mag, // float length,
1943 SitAltitudeCallback); // retMethod
1944 } // end small/big
1945 } // end scripted/not
1946 }
1947 else // no Av
1849 { 1948 {
1850 return; 1949 return;
1851 } 1950 }
@@ -1857,11 +1956,21 @@ namespace OpenSim.Region.Framework.Scenes
1857 1956
1858 Animator.TrySetMovementAnimation(sitAnimation); 1957 Animator.TrySetMovementAnimation(sitAnimation);
1859 SendFullUpdateToAllClients(); 1958 SendFullUpdateToAllClients();
1860 // This may seem stupid, but Our Full updates don't send avatar rotation :P
1861 // So we're also sending a terse update (which has avatar rotation)
1862 // [Update] We do now.
1863 //SendTerseUpdateToAllClients();
1864 } 1959 }
1960
1961 public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance)
1962 {
1963 if(hitYN)
1964 {
1965 // m_pos = Av offset from prim center to make look like on center
1966 // m_parentPosition = Actual center pos of prim
1967 // collisionPoint = spot on prim where we want to sit
1968 SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
1969 Vector3 offset = (collisionPoint - m_parentPosition) * Quaternion.Inverse(part.RotationOffset);
1970 m_pos += offset;
1971// Console.WriteLine("m_pos={0}, offset={1} newsit={2}", m_pos, offset, newsit);
1972 }
1973 }
1865 1974
1866 /// <summary> 1975 /// <summary>
1867 /// Event handler for the 'Always run' setting on the client 1976 /// Event handler for the 'Always run' setting on the client
@@ -1891,7 +2000,7 @@ namespace OpenSim.Region.Framework.Scenes
1891 /// </summary> 2000 /// </summary>
1892 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 2001 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
1893 /// <param name="rotation">The direction in which this avatar should now face. 2002 /// <param name="rotation">The direction in which this avatar should now face.
1894 public void AddNewMovement(Vector3 vec, Quaternion rotation) 2003 public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging)
1895 { 2004 {
1896 if (m_isChildAgent) 2005 if (m_isChildAgent)
1897 { 2006 {
@@ -1965,7 +2074,7 @@ namespace OpenSim.Region.Framework.Scenes
1965 2074
1966 // TODO: Add the force instead of only setting it to support multiple forces per frame? 2075 // TODO: Add the force instead of only setting it to support multiple forces per frame?
1967 m_forceToApply = direc; 2076 m_forceToApply = direc;
1968 2077 m_isNudging = Nudging;
1969 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); 2078 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
1970 } 2079 }
1971 2080
@@ -1980,7 +2089,7 @@ namespace OpenSim.Region.Framework.Scenes
1980 const float POSITION_TOLERANCE = 0.05f; 2089 const float POSITION_TOLERANCE = 0.05f;
1981 //const int TIME_MS_TOLERANCE = 3000; 2090 //const int TIME_MS_TOLERANCE = 3000;
1982 2091
1983 SendPrimUpdates(); 2092
1984 2093
1985 if (m_newCoarseLocations) 2094 if (m_newCoarseLocations)
1986 { 2095 {
@@ -2016,6 +2125,9 @@ namespace OpenSim.Region.Framework.Scenes
2016 CheckForBorderCrossing(); 2125 CheckForBorderCrossing();
2017 CheckForSignificantMovement(); // sends update to the modules. 2126 CheckForSignificantMovement(); // sends update to the modules.
2018 } 2127 }
2128
2129 //Sending prim updates AFTER the avatar terse updates are sent
2130 SendPrimUpdates();
2019 } 2131 }
2020 2132
2021 #endregion 2133 #endregion
@@ -2869,14 +2981,25 @@ namespace OpenSim.Region.Framework.Scenes
2869 { 2981 {
2870 if (m_forceToApply.HasValue) 2982 if (m_forceToApply.HasValue)
2871 { 2983 {
2872 Vector3 force = m_forceToApply.Value;
2873 2984
2985 Vector3 force = m_forceToApply.Value;
2874 m_updateflag = true; 2986 m_updateflag = true;
2875// movementvector = force;
2876 Velocity = force; 2987 Velocity = force;
2877 2988
2878 m_forceToApply = null; 2989 m_forceToApply = null;
2879 } 2990 }
2991 else
2992 {
2993 if (m_isNudging)
2994 {
2995 Vector3 force = Vector3.Zero;
2996
2997 m_updateflag = true;
2998 Velocity = force;
2999 m_isNudging = false;
3000 m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND"
3001 }
3002 }
2880 } 3003 }
2881 3004
2882 public override void SetText(string text, Vector3 color, double alpha) 3005 public override void SetText(string text, Vector3 color, double alpha)
@@ -2926,10 +3049,15 @@ namespace OpenSim.Region.Framework.Scenes
2926 // Event called by the physics plugin to tell the avatar about a collision. 3049 // Event called by the physics plugin to tell the avatar about a collision.
2927 private void PhysicsCollisionUpdate(EventArgs e) 3050 private void PhysicsCollisionUpdate(EventArgs e)
2928 { 3051 {
3052 if (m_updateCount > 0) //KF: Update Anims for a short period. Many Anim
3053 { // changes are very asynchronous.
3054 Animator.UpdateMovementAnimations();
3055 m_updateCount--;
3056 }
3057
2929 if (e == null) 3058 if (e == null)
2930 return; 3059 return;
2931 3060
2932 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f))
2933 // The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents( 3061 // The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents(
2934 // as of this comment the interval is set in AddToPhysicalScene 3062 // as of this comment the interval is set in AddToPhysicalScene
2935 if (Animator!=null) 3063 if (Animator!=null)
@@ -2940,6 +3068,12 @@ namespace OpenSim.Region.Framework.Scenes
2940 3068
2941 CollisionPlane = Vector4.UnitW; 3069 CollisionPlane = Vector4.UnitW;
2942 3070
3071 if (m_lastColCount != coldata.Count)
3072 {
3073 m_updateCount = 10;
3074 m_lastColCount = coldata.Count;
3075 }
3076
2943 if (coldata.Count != 0 && Animator != null) 3077 if (coldata.Count != 0 && Animator != null)
2944 { 3078 {
2945 switch (Animator.CurrentMovementAnimation) 3079 switch (Animator.CurrentMovementAnimation)
@@ -3588,4 +3722,4 @@ namespace OpenSim.Region.Framework.Scenes
3588 } 3722 }
3589 } 3723 }
3590 } 3724 }
3591} \ No newline at end of file 3725}
diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs
index 8df997e..f411dd7 100644
--- a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs
+++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs
@@ -303,6 +303,26 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
303 set { return; } 303 set { return; }
304 } 304 }
305 305
306 public override Quaternion APIDTarget
307 {
308 set { return; }
309 }
310
311 public override bool APIDActive
312 {
313 set { return; }
314 }
315
316 public override float APIDStrength
317 {
318 set { return; }
319 }
320
321 public override float APIDDamping
322 {
323 set { return; }
324 }
325
306 public override void SubscribeEvents(int ms) 326 public override void SubscribeEvents(int ms)
307 { 327 {
308 } 328 }
diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs
index 5ed3b14..98681d6 100644
--- a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs
+++ b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs
@@ -619,6 +619,12 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin
619 { 619 {
620 set { return; } 620 set { return; }
621 } 621 }
622
623 public override Quaternion APIDTarget { set { return; } }
624 public override bool APIDActive { set { return; } }
625 public override float APIDStrength { set { return; } }
626 public override float APIDDamping { set { return; } }
627
622 628
623 /// <summary> 629 /// <summary>
624 /// Adds the force supplied to the Target Velocity 630 /// Adds the force supplied to the Target Velocity
diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs
index 5b542db..d931f126 100644
--- a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs
+++ b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs
@@ -565,6 +565,11 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin
565 public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } } 565 public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } }
566 public override float PIDHoverTau { set { m_PIDHoverTau = value; } } 566 public override float PIDHoverTau { set { m_PIDHoverTau = value; } }
567 567
568 public override Quaternion APIDTarget { set { return; } }
569 public override bool APIDActive { set { return; } }
570 public override float APIDStrength { set { return; } }
571 public override float APIDDamping { set { return; } }
572
568 573
569 public override void AddForce(Vector3 force, bool pushforce) 574 public override void AddForce(Vector3 force, bool pushforce)
570 { 575 {
diff --git a/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs b/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs
index 1e94ee2..d5d146e 100644
--- a/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs
+++ b/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs
@@ -1238,6 +1238,26 @@ namespace OpenSim.Region.Physics.BulletXPlugin
1238 public override PIDHoverType PIDHoverType { set { return; } } 1238 public override PIDHoverType PIDHoverType { set { return; } }
1239 public override float PIDHoverTau { set { return; } } 1239 public override float PIDHoverTau { set { return; } }
1240 1240
1241 public override OpenMetaverse.Quaternion APIDTarget
1242 {
1243 set { return; }
1244 }
1245
1246 public override bool APIDActive
1247 {
1248 set { return; }
1249 }
1250
1251 public override float APIDStrength
1252 {
1253 set { return; }
1254 }
1255
1256 public override float APIDDamping
1257 {
1258 set { return; }
1259 }
1260
1241 1261
1242 public override void SubscribeEvents(int ms) 1262 public override void SubscribeEvents(int ms)
1243 { 1263 {
diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs
index f58129d..b82586f 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs
@@ -243,7 +243,12 @@ namespace OpenSim.Region.Physics.Manager
243 public abstract PIDHoverType PIDHoverType { set;} 243 public abstract PIDHoverType PIDHoverType { set;}
244 public abstract float PIDHoverTau { set;} 244 public abstract float PIDHoverTau { set;}
245 245
246 246 // For RotLookAt
247 public abstract Quaternion APIDTarget { set;}
248 public abstract bool APIDActive { set;}
249 public abstract float APIDStrength { set;}
250 public abstract float APIDDamping { set;}
251
247 public abstract void AddForce(Vector3 force, bool pushforce); 252 public abstract void AddForce(Vector3 force, bool pushforce);
248 public abstract void AddAngularForce(Vector3 force, bool pushforce); 253 public abstract void AddAngularForce(Vector3 force, bool pushforce);
249 public abstract void SetMomentum(Vector3 momentum); 254 public abstract void SetMomentum(Vector3 momentum);
@@ -476,6 +481,12 @@ namespace OpenSim.Region.Physics.Manager
476 public override bool PIDHoverActive { set { return; } } 481 public override bool PIDHoverActive { set { return; } }
477 public override PIDHoverType PIDHoverType { set { return; } } 482 public override PIDHoverType PIDHoverType { set { return; } }
478 public override float PIDHoverTau { set { return; } } 483 public override float PIDHoverTau { set { return; } }
484
485 public override Quaternion APIDTarget { set { return; } }
486 public override bool APIDActive { set { return; } }
487 public override float APIDStrength { set { return; } }
488 public override float APIDDamping { set { return; } }
489
479 490
480 public override void SetMomentum(Vector3 momentum) 491 public override void SetMomentum(Vector3 momentum)
481 { 492 {
diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
index 40fbde1..b99baa2 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
@@ -1196,6 +1196,28 @@ namespace OpenSim.Region.Physics.OdePlugin
1196 public override bool PIDHoverActive { set { return; } } 1196 public override bool PIDHoverActive { set { return; } }
1197 public override PIDHoverType PIDHoverType { set { return; } } 1197 public override PIDHoverType PIDHoverType { set { return; } }
1198 public override float PIDHoverTau { set { return; } } 1198 public override float PIDHoverTau { set { return; } }
1199
1200 public override Quaternion APIDTarget
1201 {
1202 set { return; }
1203 }
1204
1205 public override bool APIDActive
1206 {
1207 set { return; }
1208 }
1209
1210 public override float APIDStrength
1211 {
1212 set { return; }
1213 }
1214
1215 public override float APIDDamping
1216 {
1217 set { return; }
1218 }
1219
1220
1199 1221
1200 public override void SubscribeEvents(int ms) 1222 public override void SubscribeEvents(int ms)
1201 { 1223 {
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs b/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs
index 39cdc0f..78b15be 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs
@@ -23,6 +23,19 @@
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 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 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. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 * Revised Aug, Sept 2009 by Kitto Flora. ODEDynamics.cs replaces
28 * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised:
29 * ODEPrim.cs contains methods dealing with Prim editing, Prim
30 * characteristics and Kinetic motion.
31 * ODEDynamics.cs contains methods dealing with Prim Physical motion
32 * (dynamics) and the associated settings. Old Linear and angular
33 * motors for dynamic motion have been replace with MoveLinear()
34 * and MoveAngular(); 'Physical' is used only to switch ODE dynamic
35 * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_<other> is to
36 * switch between 'VEHICLE' parameter use and general dynamics
37 * settings use.
38 *
26 */ 39 */
27 40
28/* Revised Aug, Sept 2009 by Kitto Flora. ODEDynamics.cs replaces 41/* Revised Aug, Sept 2009 by Kitto Flora. ODEDynamics.cs replaces
@@ -120,7 +133,7 @@ namespace OpenSim.Region.Physics.OdePlugin
120// private float m_VhoverEfficiency = 0f; 133// private float m_VhoverEfficiency = 0f;
121 private float m_VhoverTimescale = 0f; 134 private float m_VhoverTimescale = 0f;
122 private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height 135 private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height
123 private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle. 136 private float m_VehicleBuoyancy = 0f; // Set by VEHICLE_BUOYANCY, for a vehicle.
124 // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity) 137 // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity)
125 // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity. 138 // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity.
126 // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity. 139 // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity.
@@ -479,7 +492,7 @@ namespace OpenSim.Region.Physics.OdePlugin
479 Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object 492 Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object
480 m_dir *= rotq; // apply obj rotation to velocity vector 493 m_dir *= rotq; // apply obj rotation to velocity vector
481 494
482 // add Gravity andBuoyancy 495 // add Gravity and Buoyancy
483 // KF: So far I have found no good method to combine a script-requested 496 // KF: So far I have found no good method to combine a script-requested
484 // .Z velocity and gravity. Therefore only 0g will used script-requested 497 // .Z velocity and gravity. Therefore only 0g will used script-requested
485 // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only. 498 // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only.
@@ -561,6 +574,7 @@ namespace OpenSim.Region.Physics.OdePlugin
561 private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate 574 private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate
562 private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body 575 private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body
563 */ 576 */
577//if(frcount == 0) Console.WriteLine("MoveAngular ");
564 578
565 // Get what the body is doing, this includes 'external' influences 579 // Get what the body is doing, this includes 'external' influences
566 d.Vector3 angularVelocity = d.BodyGetAngularVel(Body); 580 d.Vector3 angularVelocity = d.BodyGetAngularVel(Body);
@@ -636,7 +650,7 @@ namespace OpenSim.Region.Physics.OdePlugin
636 // Deflection section tba 650 // Deflection section tba
637 651
638 // Sum velocities 652 // Sum velocities
639 m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // + bank + deflection 653 m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // tba: + bank + deflection
640 654
641 if (!m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) 655 if (!m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f))
642 { 656 {
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
index d241574..c27c420 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
@@ -21,6 +21,18 @@
21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 * Revised August 26 2009 by Kitto Flora. ODEDynamics.cs replaces
26 * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised:
27 * ODEPrim.cs contains methods dealing with Prim editing, Prim
28 * characteristics and Kinetic motion.
29 * ODEDynamics.cs contains methods dealing with Prim Physical motion
30 * (dynamics) and the associated settings. Old Linear and angular
31 * motors for dynamic motion have been replace with MoveLinear()
32 * and MoveAngular(); 'Physical' is used only to switch ODE dynamic
33 * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_<other> is to
34 * switch between 'VEHICLE' parameter use and general dynamics
35 * settings use.
24 */ 36 */
25 37
26/* 38/*
@@ -81,7 +93,12 @@ namespace OpenSim.Region.Physics.OdePlugin
81 private float m_PIDTau; 93 private float m_PIDTau;
82 private float PID_D = 35f; 94 private float PID_D = 35f;
83 private float PID_G = 25f; 95 private float PID_G = 25f;
84 private bool m_usePID; 96 private bool m_usePID = false;
97
98 private Quaternion m_APIDTarget = new Quaternion();
99 private float m_APIDStrength = 0.5f;
100 private float m_APIDDamping = 0.5f;
101 private bool m_useAPID = false;
85 102
86 // KF: These next 7 params apply to llSetHoverHeight(float height, integer water, float tau), 103 // KF: These next 7 params apply to llSetHoverHeight(float height, integer water, float tau),
87 // and are for non-VEHICLES only. 104 // and are for non-VEHICLES only.
@@ -182,6 +199,9 @@ namespace OpenSim.Region.Physics.OdePlugin
182 private ODEDynamics m_vehicle; 199 private ODEDynamics m_vehicle;
183 200
184 internal int m_material = (int)Material.Wood; 201 internal int m_material = (int)Material.Wood;
202
203 private int frcount = 0; // Used to limit dynamics debug output to
204
185 205
186 public OdePrim(String primName, OdeScene parent_scene, Vector3 pos, Vector3 size, 206 public OdePrim(String primName, OdeScene parent_scene, Vector3 pos, Vector3 size,
187 Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical, CollisionLocker dode) 207 Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical, CollisionLocker dode)
@@ -1561,9 +1581,14 @@ Console.WriteLine(" JointCreateFixed");
1561 float fy = 0; 1581 float fy = 0;
1562 float fz = 0; 1582 float fz = 0;
1563 1583
1584 frcount++; // used to limit debug comment output
1585 if (frcount > 100)
1586 frcount = 0;
1564 1587
1565 if (IsPhysical && (Body != IntPtr.Zero) && !m_isSelected && !childPrim) // KF: Only move root prims. 1588 if (IsPhysical && (Body != IntPtr.Zero) && !m_isSelected && !childPrim) // KF: Only move root prims.
1566 { 1589 {
1590//if(frcount == 0) Console.WriteLine("Move " + m_primName + " VTyp " + m_vehicle.Type +
1591 // " usePID=" + m_usePID + " seHover=" + m_useHoverPID + " useAPID=" + m_useAPID);
1567 if (m_vehicle.Type != Vehicle.TYPE_NONE) 1592 if (m_vehicle.Type != Vehicle.TYPE_NONE)
1568 { 1593 {
1569 // 'VEHICLES' are dealt with in ODEDynamics.cs 1594 // 'VEHICLES' are dealt with in ODEDynamics.cs
@@ -1571,7 +1596,6 @@ Console.WriteLine(" JointCreateFixed");
1571 } 1596 }
1572 else 1597 else
1573 { 1598 {
1574//Console.WriteLine("Move " + m_primName);
1575 if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); // KF add 161009 1599 if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); // KF add 161009
1576 // NON-'VEHICLES' are dealt with here 1600 // NON-'VEHICLES' are dealt with here
1577 if (d.BodyIsEnabled(Body) && !m_angularlock.ApproxEquals(Vector3.Zero, 0.003f)) 1601 if (d.BodyIsEnabled(Body) && !m_angularlock.ApproxEquals(Vector3.Zero, 0.003f))
@@ -1593,21 +1617,18 @@ Console.WriteLine(" JointCreateFixed");
1593 //m_log.Info(m_collisionFlags.ToString()); 1617 //m_log.Info(m_collisionFlags.ToString());
1594 1618
1595 1619
1596 //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle. 1620 //KF: m_buoyancy is set by llSetBuoyancy() and is for non-vehicle.
1597 // would come from SceneObjectPart.cs, public void SetBuoyancy(float fvalue) , PhysActor.Buoyancy = fvalue; ??
1598 // m_buoyancy: (unlimited value) <0=Falls fast; 0=1g; 1=0g; >1 = floats up 1621 // m_buoyancy: (unlimited value) <0=Falls fast; 0=1g; 1=0g; >1 = floats up
1599 // gravityz multiplier = 1 - m_buoyancy 1622 // NB Prims in ODE are no subject to global gravity
1600 fz = _parent_scene.gravityz * (1.0f - m_buoyancy) * m_mass; 1623 fz = _parent_scene.gravityz * (1.0f - m_buoyancy) * m_mass; // force = acceleration * mass
1601 1624
1602 if (m_usePID) 1625 if (m_usePID)
1603 { 1626 {
1604//Console.WriteLine("PID " + m_primName); 1627//if(frcount == 0) Console.WriteLine("PID " + m_primName);
1605 // KF - this is for object move? eg. llSetPos() ? 1628 // KF - this is for object MoveToTarget.
1629
1606 //if (!d.BodyIsEnabled(Body)) 1630 //if (!d.BodyIsEnabled(Body))
1607 //d.BodySetForce(Body, 0f, 0f, 0f); 1631 //d.BodySetForce(Body, 0f, 0f, 0f);
1608 // If we're using the PID controller, then we have no gravity
1609 //fz = (-1 * _parent_scene.gravityz) * m_mass; //KF: ?? Prims have no global gravity,so simply...
1610 fz = 0f;
1611 1632
1612 // no lock; for now it's only called from within Simulate() 1633 // no lock; for now it's only called from within Simulate()
1613 1634
@@ -1742,7 +1763,7 @@ Console.WriteLine(" JointCreateFixed");
1742 d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight); 1763 d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight);
1743 d.BodySetLinearVel(Body, vel.X, vel.Y, 0); 1764 d.BodySetLinearVel(Body, vel.X, vel.Y, 0);
1744 d.BodyAddForce(Body, 0, 0, fz); 1765 d.BodyAddForce(Body, 0, 0, fz);
1745 return; 1766 //KF this prevents furthur motions return;
1746 } 1767 }
1747 else 1768 else
1748 { 1769 {
@@ -1751,8 +1772,46 @@ Console.WriteLine(" JointCreateFixed");
1751 // We're flying and colliding with something 1772 // We're flying and colliding with something
1752 fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass); 1773 fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass);
1753 } 1774 }
1754 } 1775 } // end m_useHoverPID && !m_usePID
1755 1776
1777 if (m_useAPID)
1778 {
1779 // RotLookAt, apparently overrides all other rotation sources. Inputs:
1780 // Quaternion m_APIDTarget
1781 // float m_APIDStrength // From SL experiments, this is the time to get there
1782 // float m_APIDDamping // From SL experiments, this is damping, 1.0 = damped, 0.1 = wobbly
1783 // Also in SL the mass of the object has no effect on time to get there.
1784 // Factors:
1785//if(frcount == 0) Console.WriteLine("APID ");
1786 // get present body rotation
1787 float limit = 1.0f;
1788 float scaler = 50f; // adjusts damping time
1789 float RLAservo = 0f;
1790
1791 d.Quaternion rot = d.BodyGetQuaternion(Body);
1792 Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W);
1793 Quaternion rot_diff = Quaternion.Inverse(rotq) * m_APIDTarget;
1794 float diff_angle;
1795 Vector3 diff_axis;
1796 rot_diff.GetAxisAngle(out diff_axis, out diff_angle);
1797 diff_axis.Normalize();
1798 if(diff_angle > 0.01f) // diff_angle is always +ve
1799 {
1800// PhysicsVector rotforce = new PhysicsVector(diff_axis.X, diff_axis.Y, diff_axis.Z);
1801 Vector3 rotforce = new Vector3(diff_axis.X, diff_axis.Y, diff_axis.Z);
1802 rotforce = rotforce * rotq;
1803 if(diff_angle > limit) diff_angle = limit; // cap the rotate rate
1804// RLAservo = timestep / m_APIDStrength * m_mass * scaler;
1805 // rotforce = rotforce * RLAservo * diff_angle ;
1806 // d.BodyAddRelTorque(Body, rotforce.X, rotforce.Y, rotforce.Z);
1807 RLAservo = timestep / m_APIDStrength * scaler;
1808 rotforce = rotforce * RLAservo * diff_angle ;
1809 d.BodySetAngularVel (Body, rotforce.X, rotforce.Y, rotforce.Z);
1810//Console.WriteLine("axis= " + diff_axis + " angle= " + diff_angle + "servo= " + RLAservo);
1811 }
1812//if(frcount == 0) Console.WriteLine("mass= " + m_mass + " servo= " + RLAservo + " angle= " + diff_angle);
1813 } // end m_useAPID
1814
1756 fx *= m_mass; 1815 fx *= m_mass;
1757 fy *= m_mass; 1816 fy *= m_mass;
1758 //fz *= m_mass; 1817 //fz *= m_mass;
@@ -2822,6 +2881,12 @@ Console.WriteLine(" JointCreateFixed");
2822 } 2881 }
2823 public override bool PIDActive { set { m_usePID = value; } } 2882 public override bool PIDActive { set { m_usePID = value; } }
2824 public override float PIDTau { set { m_PIDTau = value; } } 2883 public override float PIDTau { set { m_PIDTau = value; } }
2884
2885 // For RotLookAt
2886 public override Quaternion APIDTarget { set { m_APIDTarget = value; } }
2887 public override bool APIDActive { set { m_useAPID = value; } }
2888 public override float APIDStrength { set { m_APIDStrength = value; } }
2889 public override float APIDDamping { set { m_APIDDamping = value; } }
2825 2890
2826 public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } } 2891 public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } }
2827 public override bool PIDHoverActive { set { m_useHoverPID = value; } } 2892 public override bool PIDHoverActive { set { m_useHoverPID = value; } }
diff --git a/OpenSim/Region/Physics/POSPlugin/POSCharacter.cs b/OpenSim/Region/Physics/POSPlugin/POSCharacter.cs
index 26cd1dd..566b4e7 100644
--- a/OpenSim/Region/Physics/POSPlugin/POSCharacter.cs
+++ b/OpenSim/Region/Physics/POSPlugin/POSCharacter.cs
@@ -304,6 +304,27 @@ namespace OpenSim.Region.Physics.POSPlugin
304 { 304 {
305 set { return; } 305 set { return; }
306 } 306 }
307
308 public override Quaternion APIDTarget
309 {
310 set { return; }
311 }
312
313 public override bool APIDActive
314 {
315 set { return; }
316 }
317
318 public override float APIDStrength
319 {
320 set { return; }
321 }
322
323 public override float APIDDamping
324 {
325 set { return; }
326 }
327
307 328
308 public override void SubscribeEvents(int ms) 329 public override void SubscribeEvents(int ms)
309 { 330 {
diff --git a/OpenSim/Region/Physics/POSPlugin/POSPrim.cs b/OpenSim/Region/Physics/POSPlugin/POSPrim.cs
index 96c3e26..847b634 100644
--- a/OpenSim/Region/Physics/POSPlugin/POSPrim.cs
+++ b/OpenSim/Region/Physics/POSPlugin/POSPrim.cs
@@ -299,6 +299,26 @@ namespace OpenSim.Region.Physics.POSPlugin
299 { 299 {
300 set { return; } 300 set { return; }
301 } 301 }
302 public override Quaternion APIDTarget
303 {
304 set { return; }
305 }
306
307 public override bool APIDActive
308 {
309 set { return; }
310 }
311
312 public override float APIDStrength
313 {
314 set { return; }
315 }
316
317 public override float APIDDamping
318 {
319 set { return; }
320 }
321
302 322
303 public override void SubscribeEvents(int ms) 323 public override void SubscribeEvents(int ms)
304 { 324 {
diff --git a/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs b/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs
index 8bdb18d..24eb6b1 100644
--- a/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs
+++ b/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs
@@ -498,6 +498,28 @@ namespace OpenSim.Region.Physics.PhysXPlugin
498 public override bool PIDHoverActive { set { return; } } 498 public override bool PIDHoverActive { set { return; } }
499 public override PIDHoverType PIDHoverType { set { return; } } 499 public override PIDHoverType PIDHoverType { set { return; } }
500 public override float PIDHoverTau { set { return; } } 500 public override float PIDHoverTau { set { return; } }
501
502 public override Quaternion APIDTarget
503 {
504 set { return; }
505 }
506
507 public override bool APIDActive
508 {
509 set { return; }
510 }
511
512 public override float APIDStrength
513 {
514 set { return; }
515 }
516
517 public override float APIDDamping
518 {
519 set { return; }
520 }
521
522
501 523
502 public override void SubscribeEvents(int ms) 524 public override void SubscribeEvents(int ms)
503 { 525 {
@@ -780,6 +802,28 @@ namespace OpenSim.Region.Physics.PhysXPlugin
780 public override bool PIDHoverActive { set { return; } } 802 public override bool PIDHoverActive { set { return; } }
781 public override PIDHoverType PIDHoverType { set { return; } } 803 public override PIDHoverType PIDHoverType { set { return; } }
782 public override float PIDHoverTau { set { return; } } 804 public override float PIDHoverTau { set { return; } }
805
806 public override Quaternion APIDTarget
807 {
808 set { return; }
809 }
810
811 public override bool APIDActive
812 {
813 set { return; }
814 }
815
816 public override float APIDStrength
817 {
818 set { return; }
819 }
820
821 public override float APIDDamping
822 {
823 set { return; }
824 }
825
826
783 827
784 public override void SubscribeEvents(int ms) 828 public override void SubscribeEvents(int ms)
785 { 829 {
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index d235bac..267928b 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Diagnostics; //for [DebuggerNonUserCode]
31using System.Runtime.Remoting.Lifetime; 32using System.Runtime.Remoting.Lifetime;
32using System.Text; 33using System.Text;
33using System.Threading; 34using System.Threading;
@@ -151,6 +152,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
151 get { return m_ScriptEngine.World; } 152 get { return m_ScriptEngine.World; }
152 } 153 }
153 154
155 [DebuggerNonUserCode]
154 public void state(string newState) 156 public void state(string newState)
155 { 157 {
156 m_ScriptEngine.SetState(m_itemID, newState); 158 m_ScriptEngine.SetState(m_itemID, newState);
@@ -160,6 +162,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
160 /// Reset the named script. The script must be present 162 /// Reset the named script. The script must be present
161 /// in the same prim. 163 /// in the same prim.
162 /// </summary> 164 /// </summary>
165 [DebuggerNonUserCode]
163 public void llResetScript() 166 public void llResetScript()
164 { 167 {
165 m_host.AddScriptLPS(1); 168 m_host.AddScriptLPS(1);
@@ -272,40 +275,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
272 protected UUID InventorySelf() 275 protected UUID InventorySelf()
273 { 276 {
274 UUID invItemID = new UUID(); 277 UUID invItemID = new UUID();
275 278 bool unlock = false;
276 lock (m_host.TaskInventory) 279 if (!m_host.TaskInventory.IsReadLockedByMe())
280 {
281 m_host.TaskInventory.LockItemsForRead(true);
282 unlock = true;
283 }
284 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
277 { 285 {
278 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 286 if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID)
279 { 287 {
280 if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID) 288 invItemID = inv.Key;
281 { 289 break;
282 invItemID = inv.Key;
283 break;
284 }
285 } 290 }
286 } 291 }
287 292 if (unlock)
293 {
294 m_host.TaskInventory.LockItemsForRead(false);
295 }
288 return invItemID; 296 return invItemID;
289 } 297 }
290 298
291 protected UUID InventoryKey(string name, int type) 299 protected UUID InventoryKey(string name, int type)
292 { 300 {
293 m_host.AddScriptLPS(1); 301 m_host.AddScriptLPS(1);
294 302 m_host.TaskInventory.LockItemsForRead(true);
295 lock (m_host.TaskInventory) 303
304 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
296 { 305 {
297 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 306 if (inv.Value.Name == name)
298 { 307 {
299 if (inv.Value.Name == name) 308 m_host.TaskInventory.LockItemsForRead(false);
309
310 if (inv.Value.Type != type)
300 { 311 {
301 if (inv.Value.Type != type) 312 return UUID.Zero;
302 return UUID.Zero;
303
304 return inv.Value.AssetID;
305 } 313 }
314
315 return inv.Value.AssetID;
306 } 316 }
307 } 317 }
308 318
319 m_host.TaskInventory.LockItemsForRead(false);
309 return UUID.Zero; 320 return UUID.Zero;
310 } 321 }
311 322
@@ -313,17 +324,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
313 { 324 {
314 m_host.AddScriptLPS(1); 325 m_host.AddScriptLPS(1);
315 326
316 lock (m_host.TaskInventory) 327
328 m_host.TaskInventory.LockItemsForRead(true);
329
330 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
317 { 331 {
318 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 332 if (inv.Value.Name == name)
319 { 333 {
320 if (inv.Value.Name == name) 334 m_host.TaskInventory.LockItemsForRead(false);
321 { 335 return inv.Value.AssetID;
322 return inv.Value.AssetID;
323 }
324 } 336 }
325 } 337 }
326 338
339 m_host.TaskInventory.LockItemsForRead(false);
340
341
327 return UUID.Zero; 342 return UUID.Zero;
328 } 343 }
329 344
@@ -2555,12 +2570,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2555 2570
2556 m_host.AddScriptLPS(1); 2571 m_host.AddScriptLPS(1);
2557 2572
2573 m_host.TaskInventory.LockItemsForRead(true);
2558 TaskInventoryItem item = m_host.TaskInventory[invItemID]; 2574 TaskInventoryItem item = m_host.TaskInventory[invItemID];
2559 2575 m_host.TaskInventory.LockItemsForRead(false);
2560 lock (m_host.TaskInventory)
2561 {
2562 item = m_host.TaskInventory[invItemID];
2563 }
2564 2576
2565 if (item.PermsGranter == UUID.Zero) 2577 if (item.PermsGranter == UUID.Zero)
2566 return 0; 2578 return 0;
@@ -2635,6 +2647,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2635 if (dist > m_ScriptDistanceFactor * 10.0f) 2647 if (dist > m_ScriptDistanceFactor * 10.0f)
2636 return; 2648 return;
2637 2649
2650 //Clone is thread-safe
2638 TaskInventoryDictionary partInventory = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 2651 TaskInventoryDictionary partInventory = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
2639 2652
2640 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in partInventory) 2653 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in partInventory)
@@ -2720,11 +2733,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2720 // Orient the object to the angle calculated 2733 // Orient the object to the angle calculated
2721 llSetRot(rot); 2734 llSetRot(rot);
2722 } 2735 }
2736
2737 public void llRotLookAt(LSL_Rotation target, double strength, double damping)
2738 {
2739 m_host.AddScriptLPS(1);
2740// NotImplemented("llRotLookAt");
2741 m_host.RotLookAt(Rot2Quaternion(target), (float)strength, (float)damping);
2742
2743 }
2744
2723 2745
2724 public void llStopLookAt() 2746 public void llStopLookAt()
2725 { 2747 {
2726 m_host.AddScriptLPS(1); 2748 m_host.AddScriptLPS(1);
2727 NotImplemented("llStopLookAt"); 2749// NotImplemented("llStopLookAt");
2750 m_host.StopLookAt();
2728 } 2751 }
2729 2752
2730 public void llSetTimerEvent(double sec) 2753 public void llSetTimerEvent(double sec)
@@ -2758,13 +2781,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2758 { 2781 {
2759 TaskInventoryItem item; 2782 TaskInventoryItem item;
2760 2783
2761 lock (m_host.TaskInventory) 2784 m_host.TaskInventory.LockItemsForRead(true);
2785 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2762 { 2786 {
2763 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 2787 m_host.TaskInventory.LockItemsForRead(false);
2764 return; 2788 return;
2765 else 2789 }
2766 item = m_host.TaskInventory[InventorySelf()]; 2790 else
2791 {
2792 item = m_host.TaskInventory[InventorySelf()];
2767 } 2793 }
2794 m_host.TaskInventory.LockItemsForRead(false);
2768 2795
2769 if (item.PermsGranter != UUID.Zero) 2796 if (item.PermsGranter != UUID.Zero)
2770 { 2797 {
@@ -2786,13 +2813,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2786 { 2813 {
2787 TaskInventoryItem item; 2814 TaskInventoryItem item;
2788 2815
2816 m_host.TaskInventory.LockItemsForRead(true);
2789 lock (m_host.TaskInventory) 2817 lock (m_host.TaskInventory)
2790 { 2818 {
2819
2791 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 2820 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2821 {
2822 m_host.TaskInventory.LockItemsForRead(false);
2792 return; 2823 return;
2824 }
2793 else 2825 else
2826 {
2794 item = m_host.TaskInventory[InventorySelf()]; 2827 item = m_host.TaskInventory[InventorySelf()];
2828 }
2795 } 2829 }
2830 m_host.TaskInventory.LockItemsForRead(false);
2796 2831
2797 m_host.AddScriptLPS(1); 2832 m_host.AddScriptLPS(1);
2798 2833
@@ -2829,14 +2864,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2829 2864
2830 TaskInventoryItem item; 2865 TaskInventoryItem item;
2831 2866
2832 lock (m_host.TaskInventory) 2867 m_host.TaskInventory.LockItemsForRead(true);
2868
2869 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2833 { 2870 {
2834 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 2871 m_host.TaskInventory.LockItemsForRead(false);
2835 return; 2872 return;
2836 else 2873 }
2837 item = m_host.TaskInventory[InventorySelf()]; 2874 else
2875 {
2876 item = m_host.TaskInventory[InventorySelf()];
2838 } 2877 }
2839 2878
2879 m_host.TaskInventory.LockItemsForRead(false);
2880
2840 if (item.PermsGranter != m_host.OwnerID) 2881 if (item.PermsGranter != m_host.OwnerID)
2841 return; 2882 return;
2842 2883
@@ -2861,13 +2902,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2861 2902
2862 TaskInventoryItem item; 2903 TaskInventoryItem item;
2863 2904
2864 lock (m_host.TaskInventory) 2905 m_host.TaskInventory.LockItemsForRead(true);
2906
2907 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2865 { 2908 {
2866 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 2909 m_host.TaskInventory.LockItemsForRead(false);
2867 return; 2910 return;
2868 else
2869 item = m_host.TaskInventory[InventorySelf()];
2870 } 2911 }
2912 else
2913 {
2914 item = m_host.TaskInventory[InventorySelf()];
2915 }
2916 m_host.TaskInventory.LockItemsForRead(false);
2917
2871 2918
2872 if (item.PermsGranter != m_host.OwnerID) 2919 if (item.PermsGranter != m_host.OwnerID)
2873 return; 2920 return;
@@ -2903,8 +2950,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2903 return m_host.OwnerID.ToString(); 2950 return m_host.OwnerID.ToString();
2904 } 2951 }
2905 2952
2953 [DebuggerNonUserCode]
2906 public void llInstantMessage(string user, string message) 2954 public void llInstantMessage(string user, string message)
2907 { 2955 {
2956 UUID result;
2957 if (!UUID.TryParse(user, out result))
2958 {
2959 throw new Exception(String.Format("An invalid key of '{0} was passed to llInstantMessage", user));
2960 return;
2961 }
2962
2963
2908 m_host.AddScriptLPS(1); 2964 m_host.AddScriptLPS(1);
2909 2965
2910 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. 2966 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
@@ -2919,7 +2975,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2919 UUID friendTransactionID = UUID.Random(); 2975 UUID friendTransactionID = UUID.Random();
2920 2976
2921 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); 2977 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
2922 2978
2923 GridInstantMessage msg = new GridInstantMessage(); 2979 GridInstantMessage msg = new GridInstantMessage();
2924 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; 2980 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid;
2925 msg.toAgentID = new Guid(user); // toAgentID.Guid; 2981 msg.toAgentID = new Guid(user); // toAgentID.Guid;
@@ -3068,12 +3124,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3068 m_host.AddScriptLPS(1); 3124 m_host.AddScriptLPS(1);
3069 } 3125 }
3070 3126
3071 public void llRotLookAt(LSL_Rotation target, double strength, double damping)
3072 {
3073 m_host.AddScriptLPS(1);
3074 NotImplemented("llRotLookAt");
3075 }
3076
3077 public LSL_Integer llStringLength(string str) 3127 public LSL_Integer llStringLength(string str)
3078 { 3128 {
3079 m_host.AddScriptLPS(1); 3129 m_host.AddScriptLPS(1);
@@ -3097,14 +3147,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3097 3147
3098 TaskInventoryItem item; 3148 TaskInventoryItem item;
3099 3149
3100 lock (m_host.TaskInventory) 3150 m_host.TaskInventory.LockItemsForRead(true);
3151 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3101 { 3152 {
3102 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3153 m_host.TaskInventory.LockItemsForRead(false);
3103 return; 3154 return;
3104 else
3105 item = m_host.TaskInventory[InventorySelf()];
3106 } 3155 }
3107 3156 else
3157 {
3158 item = m_host.TaskInventory[InventorySelf()];
3159 }
3160 m_host.TaskInventory.LockItemsForRead(false);
3108 if (item.PermsGranter == UUID.Zero) 3161 if (item.PermsGranter == UUID.Zero)
3109 return; 3162 return;
3110 3163
@@ -3134,13 +3187,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3134 3187
3135 TaskInventoryItem item; 3188 TaskInventoryItem item;
3136 3189
3137 lock (m_host.TaskInventory) 3190 m_host.TaskInventory.LockItemsForRead(true);
3191 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3138 { 3192 {
3139 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3193 m_host.TaskInventory.LockItemsForRead(false);
3140 return; 3194 return;
3141 else
3142 item = m_host.TaskInventory[InventorySelf()];
3143 } 3195 }
3196 else
3197 {
3198 item = m_host.TaskInventory[InventorySelf()];
3199 }
3200 m_host.TaskInventory.LockItemsForRead(false);
3201
3144 3202
3145 if (item.PermsGranter == UUID.Zero) 3203 if (item.PermsGranter == UUID.Zero)
3146 return; 3204 return;
@@ -3213,10 +3271,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3213 3271
3214 TaskInventoryItem item; 3272 TaskInventoryItem item;
3215 3273
3216 lock (m_host.TaskInventory) 3274
3275 m_host.TaskInventory.LockItemsForRead(true);
3276 if (!m_host.TaskInventory.ContainsKey(invItemID))
3277 {
3278 m_host.TaskInventory.LockItemsForRead(false);
3279 return;
3280 }
3281 else
3217 { 3282 {
3218 item = m_host.TaskInventory[invItemID]; 3283 item = m_host.TaskInventory[invItemID];
3219 } 3284 }
3285 m_host.TaskInventory.LockItemsForRead(false);
3220 3286
3221 if (agentID == UUID.Zero || perm == 0) // Releasing permissions 3287 if (agentID == UUID.Zero || perm == 0) // Releasing permissions
3222 { 3288 {
@@ -3248,11 +3314,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3248 3314
3249 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3315 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3250 { 3316 {
3251 lock (m_host.TaskInventory) 3317 m_host.TaskInventory.LockItemsForWrite(true);
3252 { 3318 m_host.TaskInventory[invItemID].PermsGranter = agentID;
3253 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3319 m_host.TaskInventory[invItemID].PermsMask = perm;
3254 m_host.TaskInventory[invItemID].PermsMask = perm; 3320 m_host.TaskInventory.LockItemsForWrite(false);
3255 }
3256 3321
3257 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3322 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3258 "run_time_permissions", new Object[] { 3323 "run_time_permissions", new Object[] {
@@ -3272,11 +3337,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3272 3337
3273 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3338 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3274 { 3339 {
3275 lock (m_host.TaskInventory) 3340 m_host.TaskInventory.LockItemsForWrite(true);
3276 { 3341 m_host.TaskInventory[invItemID].PermsGranter = agentID;
3277 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3342 m_host.TaskInventory[invItemID].PermsMask = perm;
3278 m_host.TaskInventory[invItemID].PermsMask = perm; 3343 m_host.TaskInventory.LockItemsForWrite(false);
3279 }
3280 3344
3281 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3345 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3282 "run_time_permissions", new Object[] { 3346 "run_time_permissions", new Object[] {
@@ -3297,11 +3361,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3297 3361
3298 if (!m_waitingForScriptAnswer) 3362 if (!m_waitingForScriptAnswer)
3299 { 3363 {
3300 lock (m_host.TaskInventory) 3364 m_host.TaskInventory.LockItemsForWrite(true);
3301 { 3365 m_host.TaskInventory[invItemID].PermsGranter = agentID;
3302 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3366 m_host.TaskInventory[invItemID].PermsMask = 0;
3303 m_host.TaskInventory[invItemID].PermsMask = 0; 3367 m_host.TaskInventory.LockItemsForWrite(false);
3304 }
3305 3368
3306 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; 3369 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
3307 m_waitingForScriptAnswer=true; 3370 m_waitingForScriptAnswer=true;
@@ -3336,10 +3399,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3336 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) 3399 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
3337 llReleaseControls(); 3400 llReleaseControls();
3338 3401
3339 lock (m_host.TaskInventory) 3402
3340 { 3403 m_host.TaskInventory.LockItemsForWrite(true);
3341 m_host.TaskInventory[invItemID].PermsMask = answer; 3404 m_host.TaskInventory[invItemID].PermsMask = answer;
3342 } 3405 m_host.TaskInventory.LockItemsForWrite(false);
3406
3343 3407
3344 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3408 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3345 "run_time_permissions", new Object[] { 3409 "run_time_permissions", new Object[] {
@@ -3351,16 +3415,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3351 { 3415 {
3352 m_host.AddScriptLPS(1); 3416 m_host.AddScriptLPS(1);
3353 3417
3354 lock (m_host.TaskInventory) 3418 m_host.TaskInventory.LockItemsForRead(true);
3419
3420 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3355 { 3421 {
3356 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 3422 if (item.Type == 10 && item.ItemID == m_itemID)
3357 { 3423 {
3358 if (item.Type == 10 && item.ItemID == m_itemID) 3424 m_host.TaskInventory.LockItemsForRead(false);
3359 { 3425 return item.PermsGranter.ToString();
3360 return item.PermsGranter.ToString();
3361 }
3362 } 3426 }
3363 } 3427 }
3428 m_host.TaskInventory.LockItemsForRead(false);
3364 3429
3365 return UUID.Zero.ToString(); 3430 return UUID.Zero.ToString();
3366 } 3431 }
@@ -3369,19 +3434,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3369 { 3434 {
3370 m_host.AddScriptLPS(1); 3435 m_host.AddScriptLPS(1);
3371 3436
3372 lock (m_host.TaskInventory) 3437 m_host.TaskInventory.LockItemsForRead(true);
3438
3439 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3373 { 3440 {
3374 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 3441 if (item.Type == 10 && item.ItemID == m_itemID)
3375 { 3442 {
3376 if (item.Type == 10 && item.ItemID == m_itemID) 3443 int perms = item.PermsMask;
3377 { 3444 if (m_automaticLinkPermission)
3378 int perms = item.PermsMask; 3445 perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS;
3379 if (m_automaticLinkPermission) 3446 m_host.TaskInventory.LockItemsForRead(false);
3380 perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS; 3447 return perms;
3381 return perms;
3382 }
3383 } 3448 }
3384 } 3449 }
3450 m_host.TaskInventory.LockItemsForRead(false);
3385 3451
3386 return 0; 3452 return 0;
3387 } 3453 }
@@ -3414,11 +3480,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3414 UUID invItemID = InventorySelf(); 3480 UUID invItemID = InventorySelf();
3415 3481
3416 TaskInventoryItem item; 3482 TaskInventoryItem item;
3417 lock (m_host.TaskInventory) 3483 m_host.TaskInventory.LockItemsForRead(true);
3418 { 3484 item = m_host.TaskInventory[invItemID];
3419 item = m_host.TaskInventory[invItemID]; 3485 m_host.TaskInventory.LockItemsForRead(false);
3420 } 3486
3421
3422 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 3487 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
3423 && !m_automaticLinkPermission) 3488 && !m_automaticLinkPermission)
3424 { 3489 {
@@ -3471,16 +3536,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3471 m_host.AddScriptLPS(1); 3536 m_host.AddScriptLPS(1);
3472 UUID invItemID = InventorySelf(); 3537 UUID invItemID = InventorySelf();
3473 3538
3474 lock (m_host.TaskInventory) 3539 m_host.TaskInventory.LockItemsForRead(true);
3475 {
3476 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 3540 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
3477 && !m_automaticLinkPermission) 3541 && !m_automaticLinkPermission)
3478 { 3542 {
3479 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!"); 3543 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
3544 m_host.TaskInventory.LockItemsForRead(false);
3480 return; 3545 return;
3481 } 3546 }
3482 } 3547 m_host.TaskInventory.LockItemsForRead(false);
3483 3548
3484 if (linknum < ScriptBaseClass.LINK_THIS) 3549 if (linknum < ScriptBaseClass.LINK_THIS)
3485 return; 3550 return;
3486 3551
@@ -3649,17 +3714,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3649 m_host.AddScriptLPS(1); 3714 m_host.AddScriptLPS(1);
3650 int count = 0; 3715 int count = 0;
3651 3716
3652 lock (m_host.TaskInventory) 3717 m_host.TaskInventory.LockItemsForRead(true);
3718 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3653 { 3719 {
3654 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 3720 if (inv.Value.Type == type || type == -1)
3655 { 3721 {
3656 if (inv.Value.Type == type || type == -1) 3722 count = count + 1;
3657 {
3658 count = count + 1;
3659 }
3660 } 3723 }
3661 } 3724 }
3662 3725
3726 m_host.TaskInventory.LockItemsForRead(false);
3663 return count; 3727 return count;
3664 } 3728 }
3665 3729
@@ -3668,16 +3732,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3668 m_host.AddScriptLPS(1); 3732 m_host.AddScriptLPS(1);
3669 ArrayList keys = new ArrayList(); 3733 ArrayList keys = new ArrayList();
3670 3734
3671 lock (m_host.TaskInventory) 3735 m_host.TaskInventory.LockItemsForRead(true);
3736 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3672 { 3737 {
3673 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 3738 if (inv.Value.Type == type || type == -1)
3674 { 3739 {
3675 if (inv.Value.Type == type || type == -1) 3740 keys.Add(inv.Value.Name);
3676 {
3677 keys.Add(inv.Value.Name);
3678 }
3679 } 3741 }
3680 } 3742 }
3743 m_host.TaskInventory.LockItemsForRead(false);
3681 3744
3682 if (keys.Count == 0) 3745 if (keys.Count == 0)
3683 { 3746 {
@@ -3714,20 +3777,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3714 } 3777 }
3715 3778
3716 // move the first object found with this inventory name 3779 // move the first object found with this inventory name
3717 lock (m_host.TaskInventory) 3780 m_host.TaskInventory.LockItemsForRead(true);
3781 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3718 { 3782 {
3719 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 3783 if (inv.Value.Name == inventory)
3720 { 3784 {
3721 if (inv.Value.Name == inventory) 3785 found = true;
3722 { 3786 objId = inv.Key;
3723 found = true; 3787 assetType = inv.Value.Type;
3724 objId = inv.Key; 3788 objName = inv.Value.Name;
3725 assetType = inv.Value.Type; 3789 break;
3726 objName = inv.Value.Name;
3727 break;
3728 }
3729 } 3790 }
3730 } 3791 }
3792 m_host.TaskInventory.LockItemsForRead(false);
3731 3793
3732 if (!found) 3794 if (!found)
3733 { 3795 {
@@ -3772,24 +3834,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3772 ScriptSleep(3000); 3834 ScriptSleep(3000);
3773 } 3835 }
3774 3836
3837 [DebuggerNonUserCode]
3775 public void llRemoveInventory(string name) 3838 public void llRemoveInventory(string name)
3776 { 3839 {
3777 m_host.AddScriptLPS(1); 3840 m_host.AddScriptLPS(1);
3778 3841
3779 lock (m_host.TaskInventory) 3842 m_host.TaskInventory.LockItemsForRead(true);
3843 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3780 { 3844 {
3781 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 3845 if (item.Name == name)
3782 { 3846 {
3783 if (item.Name == name) 3847 if (item.ItemID == m_itemID)
3784 { 3848 throw new ScriptDeleteException();
3785 if (item.ItemID == m_itemID) 3849 else
3786 throw new ScriptDeleteException(); 3850 m_host.Inventory.RemoveInventoryItem(item.ItemID);
3787 else 3851
3788 m_host.Inventory.RemoveInventoryItem(item.ItemID); 3852 m_host.TaskInventory.LockItemsForRead(false);
3789 return; 3853 return;
3790 }
3791 } 3854 }
3792 } 3855 }
3856 m_host.TaskInventory.LockItemsForRead(false);
3793 } 3857 }
3794 3858
3795 public void llSetText(string text, LSL_Vector color, double alpha) 3859 public void llSetText(string text, LSL_Vector color, double alpha)
@@ -3878,6 +3942,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3878 { 3942 {
3879 m_host.AddScriptLPS(1); 3943 m_host.AddScriptLPS(1);
3880 3944
3945 //Clone is thread safe
3881 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 3946 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
3882 3947
3883 foreach (TaskInventoryItem item in itemDictionary.Values) 3948 foreach (TaskInventoryItem item in itemDictionary.Values)
@@ -3968,17 +4033,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3968 UUID soundId = UUID.Zero; 4033 UUID soundId = UUID.Zero;
3969 if (!UUID.TryParse(impact_sound, out soundId)) 4034 if (!UUID.TryParse(impact_sound, out soundId))
3970 { 4035 {
3971 lock (m_host.TaskInventory) 4036 m_host.TaskInventory.LockItemsForRead(true);
4037 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3972 { 4038 {
3973 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4039 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound)
3974 { 4040 {
3975 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound) 4041 soundId = item.AssetID;
3976 { 4042 break;
3977 soundId = item.AssetID;
3978 break;
3979 }
3980 } 4043 }
3981 } 4044 }
4045 m_host.TaskInventory.LockItemsForRead(false);
3982 } 4046 }
3983 m_host.CollisionSound = soundId; 4047 m_host.CollisionSound = soundId;
3984 m_host.CollisionSoundVolume = (float)impact_volume; 4048 m_host.CollisionSoundVolume = (float)impact_volume;
@@ -4024,6 +4088,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4024 UUID partItemID; 4088 UUID partItemID;
4025 foreach (SceneObjectPart part in parts) 4089 foreach (SceneObjectPart part in parts)
4026 { 4090 {
4091 //Clone is thread safe
4027 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); 4092 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
4028 4093
4029 foreach (TaskInventoryItem item in itemsDictionary.Values) 4094 foreach (TaskInventoryItem item in itemsDictionary.Values)
@@ -4231,17 +4296,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4231 4296
4232 m_host.AddScriptLPS(1); 4297 m_host.AddScriptLPS(1);
4233 4298
4234 lock (m_host.TaskInventory) 4299 m_host.TaskInventory.LockItemsForRead(true);
4300 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
4235 { 4301 {
4236 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4302 if (item.Type == 10 && item.ItemID == m_itemID)
4237 { 4303 {
4238 if (item.Type == 10 && item.ItemID == m_itemID) 4304 result = item.Name!=null?item.Name:String.Empty;
4239 { 4305 break;
4240 result = item.Name!=null?item.Name:String.Empty;
4241 break;
4242 }
4243 } 4306 }
4244 } 4307 }
4308 m_host.TaskInventory.LockItemsForRead(false);
4245 4309
4246 return result; 4310 return result;
4247 } 4311 }
@@ -4499,23 +4563,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4499 { 4563 {
4500 m_host.AddScriptLPS(1); 4564 m_host.AddScriptLPS(1);
4501 4565
4502 lock (m_host.TaskInventory) 4566 m_host.TaskInventory.LockItemsForRead(true);
4567 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
4503 { 4568 {
4504 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4569 if (inv.Value.Name == name)
4505 { 4570 {
4506 if (inv.Value.Name == name) 4571 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
4507 { 4572 {
4508 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) 4573 m_host.TaskInventory.LockItemsForRead(false);
4509 { 4574 return inv.Value.AssetID.ToString();
4510 return inv.Value.AssetID.ToString(); 4575 }
4511 } 4576 else
4512 else 4577 {
4513 { 4578 m_host.TaskInventory.LockItemsForRead(false);
4514 return UUID.Zero.ToString(); 4579 return UUID.Zero.ToString();
4515 }
4516 } 4580 }
4517 } 4581 }
4518 } 4582 }
4583 m_host.TaskInventory.LockItemsForRead(false);
4519 4584
4520 return UUID.Zero.ToString(); 4585 return UUID.Zero.ToString();
4521 } 4586 }
@@ -6011,14 +6076,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6011 6076
6012 protected UUID GetTaskInventoryItem(string name) 6077 protected UUID GetTaskInventoryItem(string name)
6013 { 6078 {
6014 lock (m_host.TaskInventory) 6079 m_host.TaskInventory.LockItemsForRead(true);
6080 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6015 { 6081 {
6016 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 6082 if (inv.Value.Name == name)
6017 { 6083 {
6018 if (inv.Value.Name == name) 6084 m_host.TaskInventory.LockItemsForRead(false);
6019 return inv.Key; 6085 return inv.Key;
6020 } 6086 }
6021 } 6087 }
6088 m_host.TaskInventory.LockItemsForRead(false);
6022 6089
6023 return UUID.Zero; 6090 return UUID.Zero;
6024 } 6091 }
@@ -6329,22 +6396,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6329 } 6396 }
6330 6397
6331 // copy the first script found with this inventory name 6398 // copy the first script found with this inventory name
6332 lock (m_host.TaskInventory) 6399 m_host.TaskInventory.LockItemsForRead(true);
6400 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6333 { 6401 {
6334 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 6402 if (inv.Value.Name == name)
6335 { 6403 {
6336 if (inv.Value.Name == name) 6404 // make sure the object is a script
6405 if (10 == inv.Value.Type)
6337 { 6406 {
6338 // make sure the object is a script 6407 found = true;
6339 if (10 == inv.Value.Type) 6408 srcId = inv.Key;
6340 { 6409 break;
6341 found = true;
6342 srcId = inv.Key;
6343 break;
6344 }
6345 } 6410 }
6346 } 6411 }
6347 } 6412 }
6413 m_host.TaskInventory.LockItemsForRead(false);
6348 6414
6349 if (!found) 6415 if (!found)
6350 { 6416 {
@@ -8147,28 +8213,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8147 { 8213 {
8148 m_host.AddScriptLPS(1); 8214 m_host.AddScriptLPS(1);
8149 8215
8150 lock (m_host.TaskInventory) 8216 m_host.TaskInventory.LockItemsForRead(true);
8217 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
8151 { 8218 {
8152 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 8219 if (inv.Value.Name == item)
8153 { 8220 {
8154 if (inv.Value.Name == item) 8221 m_host.TaskInventory.LockItemsForRead(false);
8222 switch (mask)
8155 { 8223 {
8156 switch (mask) 8224 case 0:
8157 { 8225 return (int)inv.Value.BasePermissions;
8158 case 0: 8226 case 1:
8159 return (int)inv.Value.BasePermissions; 8227 return (int)inv.Value.CurrentPermissions;
8160 case 1: 8228 case 2:
8161 return (int)inv.Value.CurrentPermissions; 8229 return (int)inv.Value.GroupPermissions;
8162 case 2: 8230 case 3:
8163 return (int)inv.Value.GroupPermissions; 8231 return (int)inv.Value.EveryonePermissions;
8164 case 3: 8232 case 4:
8165 return (int)inv.Value.EveryonePermissions; 8233 return (int)inv.Value.NextPermissions;
8166 case 4:
8167 return (int)inv.Value.NextPermissions;
8168 }
8169 } 8234 }
8170 } 8235 }
8171 } 8236 }
8237 m_host.TaskInventory.LockItemsForRead(false);
8172 8238
8173 return -1; 8239 return -1;
8174 } 8240 }
@@ -8183,16 +8249,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8183 { 8249 {
8184 m_host.AddScriptLPS(1); 8250 m_host.AddScriptLPS(1);
8185 8251
8186 lock (m_host.TaskInventory) 8252 m_host.TaskInventory.LockItemsForRead(true);
8253 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
8187 { 8254 {
8188 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 8255 if (inv.Value.Name == item)
8189 { 8256 {
8190 if (inv.Value.Name == item) 8257 m_host.TaskInventory.LockItemsForRead(false);
8191 { 8258 return inv.Value.CreatorID.ToString();
8192 return inv.Value.CreatorID.ToString();
8193 }
8194 } 8259 }
8195 } 8260 }
8261 m_host.TaskInventory.LockItemsForRead(false);
8196 8262
8197 llSay(0, "No item name '" + item + "'"); 8263 llSay(0, "No item name '" + item + "'");
8198 8264
@@ -8716,16 +8782,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8716 { 8782 {
8717 m_host.AddScriptLPS(1); 8783 m_host.AddScriptLPS(1);
8718 8784
8719 lock (m_host.TaskInventory) 8785 m_host.TaskInventory.LockItemsForRead(true);
8786 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
8720 { 8787 {
8721 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 8788 if (inv.Value.Name == name)
8722 { 8789 {
8723 if (inv.Value.Name == name) 8790 m_host.TaskInventory.LockItemsForRead(false);
8724 { 8791 return inv.Value.Type;
8725 return inv.Value.Type;
8726 }
8727 } 8792 }
8728 } 8793 }
8794 m_host.TaskInventory.LockItemsForRead(false);
8729 8795
8730 return -1; 8796 return -1;
8731 } 8797 }
@@ -8756,17 +8822,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8756 if (invItemID == UUID.Zero) 8822 if (invItemID == UUID.Zero)
8757 return new LSL_Vector(); 8823 return new LSL_Vector();
8758 8824
8759 lock (m_host.TaskInventory) 8825 m_host.TaskInventory.LockItemsForRead(true);
8826 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
8760 { 8827 {
8761 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) 8828 m_host.TaskInventory.LockItemsForRead(false);
8762 return new LSL_Vector(); 8829 return new LSL_Vector();
8830 }
8763 8831
8764 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) 8832 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
8765 { 8833 {
8766 ShoutError("No permissions to track the camera"); 8834 ShoutError("No permissions to track the camera");
8767 return new LSL_Vector(); 8835 m_host.TaskInventory.LockItemsForRead(false);
8768 } 8836 return new LSL_Vector();
8769 } 8837 }
8838 m_host.TaskInventory.LockItemsForRead(false);
8770 8839
8771 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 8840 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
8772 if (presence != null) 8841 if (presence != null)
@@ -8784,17 +8853,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8784 if (invItemID == UUID.Zero) 8853 if (invItemID == UUID.Zero)
8785 return new LSL_Rotation(); 8854 return new LSL_Rotation();
8786 8855
8787 lock (m_host.TaskInventory) 8856 m_host.TaskInventory.LockItemsForRead(true);
8857 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
8788 { 8858 {
8789 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) 8859 m_host.TaskInventory.LockItemsForRead(false);
8790 return new LSL_Rotation(); 8860 return new LSL_Rotation();
8791
8792 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
8793 {
8794 ShoutError("No permissions to track the camera");
8795 return new LSL_Rotation();
8796 }
8797 } 8861 }
8862 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
8863 {
8864 ShoutError("No permissions to track the camera");
8865 m_host.TaskInventory.LockItemsForRead(false);
8866 return new LSL_Rotation();
8867 }
8868 m_host.TaskInventory.LockItemsForRead(false);
8798 8869
8799 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 8870 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
8800 if (presence != null) 8871 if (presence != null)
@@ -8944,14 +9015,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8944 if (objectID == UUID.Zero) return; 9015 if (objectID == UUID.Zero) return;
8945 9016
8946 UUID agentID; 9017 UUID agentID;
8947 lock (m_host.TaskInventory) 9018 m_host.TaskInventory.LockItemsForRead(true);
8948 { 9019 // we need the permission first, to know which avatar we want to set the camera for
8949 // we need the permission first, to know which avatar we want to set the camera for 9020 agentID = m_host.TaskInventory[invItemID].PermsGranter;
8950 agentID = m_host.TaskInventory[invItemID].PermsGranter;
8951 9021
8952 if (agentID == UUID.Zero) return; 9022 if (agentID == UUID.Zero)
8953 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return; 9023 {
9024 m_host.TaskInventory.LockItemsForRead(false);
9025 return;
8954 } 9026 }
9027 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0)
9028 {
9029 m_host.TaskInventory.LockItemsForRead(false);
9030 return;
9031 }
9032 m_host.TaskInventory.LockItemsForRead(false);
8955 9033
8956 ScenePresence presence = World.GetScenePresence(agentID); 9034 ScenePresence presence = World.GetScenePresence(agentID);
8957 9035
@@ -9001,12 +9079,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9001 9079
9002 // we need the permission first, to know which avatar we want to clear the camera for 9080 // we need the permission first, to know which avatar we want to clear the camera for
9003 UUID agentID; 9081 UUID agentID;
9004 lock (m_host.TaskInventory) 9082 m_host.TaskInventory.LockItemsForRead(true);
9083 agentID = m_host.TaskInventory[invItemID].PermsGranter;
9084 if (agentID == UUID.Zero)
9085 {
9086 m_host.TaskInventory.LockItemsForRead(false);
9087 return;
9088 }
9089 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0)
9005 { 9090 {
9006 agentID = m_host.TaskInventory[invItemID].PermsGranter; 9091 m_host.TaskInventory.LockItemsForRead(false);
9007 if (agentID == UUID.Zero) return; 9092 return;
9008 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return;
9009 } 9093 }
9094 m_host.TaskInventory.LockItemsForRead(false);
9010 9095
9011 ScenePresence presence = World.GetScenePresence(agentID); 9096 ScenePresence presence = World.GetScenePresence(agentID);
9012 9097
@@ -9463,15 +9548,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9463 9548
9464 internal UUID ScriptByName(string name) 9549 internal UUID ScriptByName(string name)
9465 { 9550 {
9466 lock (m_host.TaskInventory) 9551 m_host.TaskInventory.LockItemsForRead(true);
9552
9553 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
9467 { 9554 {
9468 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 9555 if (item.Type == 10 && item.Name == name)
9469 { 9556 {
9470 if (item.Type == 10 && item.Name == name) 9557 m_host.TaskInventory.LockItemsForRead(false);
9471 return item.ItemID; 9558 return item.ItemID;
9472 } 9559 }
9473 } 9560 }
9474 9561
9562 m_host.TaskInventory.LockItemsForRead(false);
9563
9475 return UUID.Zero; 9564 return UUID.Zero;
9476 } 9565 }
9477 9566
@@ -9512,6 +9601,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9512 { 9601 {
9513 m_host.AddScriptLPS(1); 9602 m_host.AddScriptLPS(1);
9514 9603
9604 //Clone is thread safe
9515 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 9605 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
9516 9606
9517 UUID assetID = UUID.Zero; 9607 UUID assetID = UUID.Zero;
@@ -9574,6 +9664,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9574 { 9664 {
9575 m_host.AddScriptLPS(1); 9665 m_host.AddScriptLPS(1);
9576 9666
9667 //Clone is thread safe
9577 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 9668 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
9578 9669
9579 UUID assetID = UUID.Zero; 9670 UUID assetID = UUID.Zero;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 5501679..7f739b1 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -728,18 +728,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
728 if (target != null) 728 if (target != null)
729 { 729 {
730 UUID animID=UUID.Zero; 730 UUID animID=UUID.Zero;
731 lock (m_host.TaskInventory) 731 m_host.TaskInventory.LockItemsForRead(true);
732 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
732 { 733 {
733 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 734 if (inv.Value.Name == animation)
734 { 735 {
735 if (inv.Value.Name == animation) 736 if (inv.Value.Type == (int)AssetType.Animation)
736 { 737 animID = inv.Value.AssetID;
737 if (inv.Value.Type == (int)AssetType.Animation) 738 continue;
738 animID = inv.Value.AssetID;
739 continue;
740 }
741 } 739 }
742 } 740 }
741 m_host.TaskInventory.LockItemsForRead(false);
743 if (animID == UUID.Zero) 742 if (animID == UUID.Zero)
744 target.Animator.AddAnimation(animation, m_host.UUID); 743 target.Animator.AddAnimation(animation, m_host.UUID);
745 else 744 else
@@ -761,18 +760,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
761 if (target != null) 760 if (target != null)
762 { 761 {
763 UUID animID=UUID.Zero; 762 UUID animID=UUID.Zero;
764 lock (m_host.TaskInventory) 763 m_host.TaskInventory.LockItemsForRead(true);
764 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
765 { 765 {
766 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 766 if (inv.Value.Name == animation)
767 { 767 {
768 if (inv.Value.Name == animation) 768 if (inv.Value.Type == (int)AssetType.Animation)
769 { 769 animID = inv.Value.AssetID;
770 if (inv.Value.Type == (int)AssetType.Animation) 770 continue;
771 animID = inv.Value.AssetID;
772 continue;
773 }
774 } 771 }
775 } 772 }
773 m_host.TaskInventory.LockItemsForRead(false);
776 774
777 if (animID == UUID.Zero) 775 if (animID == UUID.Zero)
778 target.Animator.RemoveAnimation(animation); 776 target.Animator.RemoveAnimation(animation);
@@ -1541,6 +1539,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1541 1539
1542 if (!UUID.TryParse(name, out assetID)) 1540 if (!UUID.TryParse(name, out assetID))
1543 { 1541 {
1542 m_host.TaskInventory.LockItemsForRead(true);
1544 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 1543 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
1545 { 1544 {
1546 if (item.Type == 7 && item.Name == name) 1545 if (item.Type == 7 && item.Name == name)
@@ -1548,6 +1547,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1548 assetID = item.AssetID; 1547 assetID = item.AssetID;
1549 } 1548 }
1550 } 1549 }
1550 m_host.TaskInventory.LockItemsForRead(false);
1551 } 1551 }
1552 1552
1553 if (assetID == UUID.Zero) 1553 if (assetID == UUID.Zero)
@@ -1594,6 +1594,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1594 1594
1595 if (!UUID.TryParse(name, out assetID)) 1595 if (!UUID.TryParse(name, out assetID))
1596 { 1596 {
1597 m_host.TaskInventory.LockItemsForRead(true);
1597 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 1598 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
1598 { 1599 {
1599 if (item.Type == 7 && item.Name == name) 1600 if (item.Type == 7 && item.Name == name)
@@ -1601,6 +1602,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1601 assetID = item.AssetID; 1602 assetID = item.AssetID;
1602 } 1603 }
1603 } 1604 }
1605 m_host.TaskInventory.LockItemsForRead(false);
1604 } 1606 }
1605 1607
1606 if (assetID == UUID.Zero) 1608 if (assetID == UUID.Zero)
@@ -1651,6 +1653,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1651 1653
1652 if (!UUID.TryParse(name, out assetID)) 1654 if (!UUID.TryParse(name, out assetID))
1653 { 1655 {
1656 m_host.TaskInventory.LockItemsForRead(true);
1654 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 1657 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
1655 { 1658 {
1656 if (item.Type == 7 && item.Name == name) 1659 if (item.Type == 7 && item.Name == name)
@@ -1658,6 +1661,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1658 assetID = item.AssetID; 1661 assetID = item.AssetID;
1659 } 1662 }
1660 } 1663 }
1664 m_host.TaskInventory.LockItemsForRead(false);
1661 } 1665 }
1662 1666
1663 if (assetID == UUID.Zero) 1667 if (assetID == UUID.Zero)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs
index 7f67599..15e0408 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics; //for [DebuggerNonUserCode]
30using System.Reflection; 31using System.Reflection;
31using System.Runtime.Remoting.Lifetime; 32using System.Runtime.Remoting.Lifetime;
32using OpenSim.Region.ScriptEngine.Shared; 33using OpenSim.Region.ScriptEngine.Shared;
@@ -131,6 +132,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
131 return (eventFlags); 132 return (eventFlags);
132 } 133 }
133 134
135 [DebuggerNonUserCode]
134 public void ExecuteEvent(string state, string FunctionName, object[] args) 136 public void ExecuteEvent(string state, string FunctionName, object[] args)
135 { 137 {
136 // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory. 138 // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory.
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs
index 121159c..a44abb0 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs
@@ -33,6 +33,7 @@ using System.Threading;
33using System.Reflection; 33using System.Reflection;
34using System.Collections; 34using System.Collections;
35using System.Collections.Generic; 35using System.Collections.Generic;
36using System.Diagnostics; //for [DebuggerNonUserCode]
36using OpenSim.Region.ScriptEngine.Interfaces; 37using OpenSim.Region.ScriptEngine.Interfaces;
37using OpenSim.Region.ScriptEngine.Shared; 38using OpenSim.Region.ScriptEngine.Shared;
38using OpenSim.Region.ScriptEngine.Shared.Api.Runtime; 39using OpenSim.Region.ScriptEngine.Shared.Api.Runtime;
@@ -90,6 +91,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
90 return (int)m_Executor.GetStateEventFlags(state); 91 return (int)m_Executor.GetStateEventFlags(state);
91 } 92 }
92 93
94 [DebuggerNonUserCode]
93 public void ExecuteEvent(string state, string FunctionName, object[] args) 95 public void ExecuteEvent(string state, string FunctionName, object[] args)
94 { 96 {
95 m_Executor.ExecuteEvent(state, FunctionName, args); 97 m_Executor.ExecuteEvent(state, FunctionName, args);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index 5c5d57e..8333a27 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.IO; 29using System.IO;
30using System.Diagnostics; //for [DebuggerNonUserCode]
30using System.Runtime.Remoting; 31using System.Runtime.Remoting;
31using System.Runtime.Remoting.Lifetime; 32using System.Runtime.Remoting.Lifetime;
32using System.Threading; 33using System.Threading;
@@ -237,13 +238,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
237 238
238 if (part != null) 239 if (part != null)
239 { 240 {
240 lock (part.TaskInventory) 241 part.TaskInventory.LockItemsForRead(true);
242 if (part.TaskInventory.ContainsKey(m_ItemID))
241 { 243 {
242 if (part.TaskInventory.ContainsKey(m_ItemID)) 244 m_thisScriptTask = part.TaskInventory[m_ItemID];
243 {
244 m_thisScriptTask = part.TaskInventory[m_ItemID];
245 }
246 } 245 }
246 part.TaskInventory.LockItemsForRead(false);
247 } 247 }
248 248
249 ApiManager am = new ApiManager(); 249 ApiManager am = new ApiManager();
@@ -428,14 +428,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
428 { 428 {
429 int permsMask; 429 int permsMask;
430 UUID permsGranter; 430 UUID permsGranter;
431 lock (part.TaskInventory) 431 part.TaskInventory.LockItemsForRead(true);
432 if (!part.TaskInventory.ContainsKey(m_ItemID))
432 { 433 {
433 if (!part.TaskInventory.ContainsKey(m_ItemID)) 434 part.TaskInventory.LockItemsForRead(false);
434 return; 435 return;
435
436 permsGranter = part.TaskInventory[m_ItemID].PermsGranter;
437 permsMask = part.TaskInventory[m_ItemID].PermsMask;
438 } 436 }
437 permsGranter = part.TaskInventory[m_ItemID].PermsGranter;
438 permsMask = part.TaskInventory[m_ItemID].PermsMask;
439 part.TaskInventory.LockItemsForRead(false);
439 440
440 if ((permsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0) 441 if ((permsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)
441 { 442 {
@@ -544,6 +545,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
544 return true; 545 return true;
545 } 546 }
546 547
548 [DebuggerNonUserCode] //Prevents the debugger from farting in this function
547 public void SetState(string state) 549 public void SetState(string state)
548 { 550 {
549 if (state == State) 551 if (state == State)
@@ -555,7 +557,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
555 new DetectParams[0])); 557 new DetectParams[0]));
556 PostEvent(new EventParams("state_entry", new Object[0], 558 PostEvent(new EventParams("state_entry", new Object[0],
557 new DetectParams[0])); 559 new DetectParams[0]));
558 560
559 throw new EventAbortException(); 561 throw new EventAbortException();
560 } 562 }
561 563
@@ -638,154 +640,158 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
638 /// <returns></returns> 640 /// <returns></returns>
639 public object EventProcessor() 641 public object EventProcessor()
640 { 642 {
643
644 EventParams data = null;
645
646 lock (m_EventQueue)
647 {
641 lock (m_Script) 648 lock (m_Script)
642 { 649 {
643 EventParams data = null; 650 data = (EventParams) m_EventQueue.Dequeue();
644 651 if (data == null) // Shouldn't happen
645 lock (m_EventQueue)
646 { 652 {
647 data = (EventParams) m_EventQueue.Dequeue(); 653 if ((m_EventQueue.Count > 0) && m_RunEvents && (!m_ShuttingDown))
648 if (data == null) // Shouldn't happen
649 { 654 {
650 if ((m_EventQueue.Count > 0) && m_RunEvents && (!m_ShuttingDown)) 655 m_CurrentResult = m_Engine.QueueEventHandler(this);
651 {
652 m_CurrentResult = m_Engine.QueueEventHandler(this);
653 }
654 else
655 {
656 m_CurrentResult = null;
657 }
658 return 0;
659 } 656 }
660 657 else
661 if (data.EventName == "timer")
662 m_TimerQueued = false;
663 if (data.EventName == "control")
664 { 658 {
665 if (m_ControlEventsInQueue > 0) 659 m_CurrentResult = null;
666 m_ControlEventsInQueue--;
667 } 660 }
668 if (data.EventName == "collision") 661 return 0;
669 m_CollisionInQueue = false;
670 } 662 }
671
672 //m_log.DebugFormat("[XENGINE]: Processing event {0} for {1}", data.EventName, this);
673 663
674 m_DetectParams = data.DetectParams; 664 if (data.EventName == "timer")
675 665 m_TimerQueued = false;
676 if (data.EventName == "state") // Hardcoded state change 666 if (data.EventName == "control")
677 { 667 {
678 // m_log.DebugFormat("[Script] Script {0}.{1} state set to {2}", 668 if (m_ControlEventsInQueue > 0)
679 // m_PrimName, m_ScriptName, data.Params[0].ToString()); 669 m_ControlEventsInQueue--;
680 m_State=data.Params[0].ToString(); 670 }
681 AsyncCommandManager.RemoveScript(m_Engine, 671 if (data.EventName == "collision")
682 m_LocalID, m_ItemID); 672 m_CollisionInQueue = false;
673 }
674 }
675 lock(m_Script)
676 {
677
678 //m_log.DebugFormat("[XENGINE]: Processing event {0} for {1}", data.EventName, this);
683 679
684 SceneObjectPart part = m_Engine.World.GetSceneObjectPart( 680 m_DetectParams = data.DetectParams;
685 m_LocalID); 681
686 if (part != null) 682 if (data.EventName == "state") // Hardcoded state change
687 { 683 {
688 part.SetScriptEvents(m_ItemID, 684// m_log.DebugFormat("[Script] Script {0}.{1} state set to {2}",
689 (int)m_Script.GetStateEventFlags(State)); 685// m_PrimName, m_ScriptName, data.Params[0].ToString());
690 } 686 m_State=data.Params[0].ToString();
687 AsyncCommandManager.RemoveScript(m_Engine,
688 m_LocalID, m_ItemID);
689
690 SceneObjectPart part = m_Engine.World.GetSceneObjectPart(
691 m_LocalID);
692 if (part != null)
693 {
694 part.SetScriptEvents(m_ItemID,
695 (int)m_Script.GetStateEventFlags(State));
691 } 696 }
692 else 697 }
698 else
699 {
700 if (m_Engine.World.PipeEventsForScript(m_LocalID) ||
701 data.EventName == "control") // Don't freeze avies!
693 { 702 {
694 if (m_Engine.World.PipeEventsForScript(m_LocalID) || 703 SceneObjectPart part = m_Engine.World.GetSceneObjectPart(
695 data.EventName == "control") // Don't freeze avies! 704 m_LocalID);
696 { 705 // m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}",
697 SceneObjectPart part = m_Engine.World.GetSceneObjectPart( 706 // m_PrimName, m_ScriptName, data.EventName, m_State);
698 m_LocalID);
699 // m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}",
700 // m_PrimName, m_ScriptName, data.EventName, m_State);
701 707
702 try 708 try
703 { 709 {
704 m_CurrentEvent = data.EventName; 710 m_CurrentEvent = data.EventName;
705 m_EventStart = DateTime.Now; 711 m_EventStart = DateTime.Now;
706 m_InEvent = true; 712 m_InEvent = true;
707 713
708 m_Script.ExecuteEvent(State, data.EventName, data.Params); 714 m_Script.ExecuteEvent(State, data.EventName, data.Params);
709 715
710 m_InEvent = false; 716 m_InEvent = false;
711 m_CurrentEvent = String.Empty; 717 m_CurrentEvent = String.Empty;
712 718
713 if (m_SaveState) 719 if (m_SaveState)
714 { 720 {
715 // This will be the very first event we deliver 721 // This will be the very first event we deliver
716 // (state_entry) in default state 722 // (state_entry) in default state
717 // 723 //
718 724
719 SaveState(m_Assembly); 725 SaveState(m_Assembly);
720 726
721 m_SaveState = false; 727 m_SaveState = false;
722 }
723 } 728 }
724 catch (Exception e) 729 }
725 { 730 catch (Exception e)
726 // m_log.DebugFormat("[SCRIPT] Exception: {0}", e.Message); 731 {
727 m_InEvent = false; 732 // m_log.DebugFormat("[SCRIPT] Exception: {0}", e.Message);
728 m_CurrentEvent = String.Empty; 733 m_InEvent = false;
734 m_CurrentEvent = String.Empty;
729 735
730 if ((!(e is TargetInvocationException) || (!(e.InnerException is SelfDeleteException) && !(e.InnerException is ScriptDeleteException))) && !(e is ThreadAbortException)) 736 if ((!(e is TargetInvocationException) || (!(e.InnerException is SelfDeleteException) && !(e.InnerException is ScriptDeleteException))) && !(e is ThreadAbortException))
731 { 737 {
732 try 738 try
733 {
734 // DISPLAY ERROR INWORLD
735 string text = FormatException(e);
736
737 if (text.Length > 1000)
738 text = text.Substring(0, 1000);
739 m_Engine.World.SimChat(Utils.StringToBytes(text),
740 ChatTypeEnum.DebugChannel, 2147483647,
741 part.AbsolutePosition,
742 part.Name, part.UUID, false);
743 }
744 catch (Exception)
745 {
746 }
747 // catch (Exception e2) // LEGIT: User Scripting
748 // {
749 // m_log.Error("[SCRIPT]: "+
750 // "Error displaying error in-world: " +
751 // e2.ToString());
752 // m_log.Error("[SCRIPT]: " +
753 // "Errormessage: Error compiling script:\r\n" +
754 // e.ToString());
755 // }
756 }
757 else if ((e is TargetInvocationException) && (e.InnerException is SelfDeleteException))
758 { 739 {
759 m_InSelfDelete = true; 740 // DISPLAY ERROR INWORLD
760 if (part != null && part.ParentGroup != null) 741 string text = FormatException(e);
761 m_Engine.World.DeleteSceneObject(part.ParentGroup, false); 742
743 if (text.Length > 1000)
744 text = text.Substring(0, 1000);
745 m_Engine.World.SimChat(Utils.StringToBytes(text),
746 ChatTypeEnum.DebugChannel, 2147483647,
747 part.AbsolutePosition,
748 part.Name, part.UUID, false);
762 } 749 }
763 else if ((e is TargetInvocationException) && (e.InnerException is ScriptDeleteException)) 750 catch (Exception)
764 { 751 {
765 m_InSelfDelete = true;
766 if (part != null && part.ParentGroup != null)
767 part.Inventory.RemoveInventoryItem(m_ItemID);
768 } 752 }
753 // catch (Exception e2) // LEGIT: User Scripting
754 // {
755 // m_log.Error("[SCRIPT]: "+
756 // "Error displaying error in-world: " +
757 // e2.ToString());
758 // m_log.Error("[SCRIPT]: " +
759 // "Errormessage: Error compiling script:\r\n" +
760 // e.ToString());
761 // }
762 }
763 else if ((e is TargetInvocationException) && (e.InnerException is SelfDeleteException))
764 {
765 m_InSelfDelete = true;
766 if (part != null && part.ParentGroup != null)
767 m_Engine.World.DeleteSceneObject(part.ParentGroup, false);
768 }
769 else if ((e is TargetInvocationException) && (e.InnerException is ScriptDeleteException))
770 {
771 m_InSelfDelete = true;
772 if (part != null && part.ParentGroup != null)
773 part.Inventory.RemoveInventoryItem(m_ItemID);
769 } 774 }
770 } 775 }
771 } 776 }
777 }
772 778
773 lock (m_EventQueue) 779 lock (m_EventQueue)
780 {
781 if ((m_EventQueue.Count > 0) && m_RunEvents && (!m_ShuttingDown))
774 { 782 {
775 if ((m_EventQueue.Count > 0) && m_RunEvents && (!m_ShuttingDown)) 783 m_CurrentResult = m_Engine.QueueEventHandler(this);
776 { 784 }
777 m_CurrentResult = m_Engine.QueueEventHandler(this); 785 else
778 } 786 {
779 else 787 m_CurrentResult = null;
780 {
781 m_CurrentResult = null;
782 }
783 } 788 }
789 }
784 790
785 m_DetectParams = null; 791 m_DetectParams = null;
786 792
787 return 0; 793 return 0;
788 } 794 }
789 } 795 }
790 796
791 public int EventTime() 797 public int EventTime()
@@ -824,6 +830,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
824 new Object[0], new DetectParams[0])); 830 new Object[0], new DetectParams[0]));
825 } 831 }
826 832
833 [DebuggerNonUserCode] //Stops the VS debugger from farting in this function
827 public void ApiResetScript() 834 public void ApiResetScript()
828 { 835 {
829 // bool running = Running; 836 // bool running = Running;
diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
index 3f38bb6..1fc31c5 100644
--- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
@@ -429,6 +429,11 @@ namespace OpenSim.Region.ScriptEngine.Shared
429 } 429 }
430 } 430 }
431 431
432 public int Size
433 {
434 get { return 0; }
435 }
436
432 public object[] Data 437 public object[] Data
433 { 438 {
434 get { 439 get {
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 9030a5c..49c69ab 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -30,6 +30,7 @@ using System.IO;
30using System.Threading; 30using System.Threading;
31using System.Collections; 31using System.Collections;
32using System.Collections.Generic; 32using System.Collections.Generic;
33using System.Diagnostics; //for [DebuggerNonUserCode]
33using System.Security; 34using System.Security;
34using System.Security.Policy; 35using System.Security.Policy;
35using System.Reflection; 36using System.Reflection;
@@ -100,6 +101,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
100 private Dictionary<UUID, IScriptInstance> m_Scripts = 101 private Dictionary<UUID, IScriptInstance> m_Scripts =
101 new Dictionary<UUID, IScriptInstance>(); 102 new Dictionary<UUID, IScriptInstance>();
102 103
104 private OpenMetaverse.ReaderWriterLockSlim m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
105
103 // Maps the asset ID to the assembly 106 // Maps the asset ID to the assembly
104 107
105 private Dictionary<UUID, string> m_Assemblies = 108 private Dictionary<UUID, string> m_Assemblies =
@@ -121,6 +124,65 @@ namespace OpenSim.Region.ScriptEngine.XEngine
121 private ScriptCompileQueue m_CompileQueue = new ScriptCompileQueue(); 124 private ScriptCompileQueue m_CompileQueue = new ScriptCompileQueue();
122 IWorkItemResult m_CurrentCompile = null; 125 IWorkItemResult m_CurrentCompile = null;
123 126
127 private void lockScriptsForRead(bool locked)
128 {
129 if (locked)
130 {
131 if (m_scriptsLock.RecursiveReadCount > 0)
132 {
133 m_log.Error("[XEngine.m_Scripts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
134 m_scriptsLock.ExitReadLock();
135 }
136 if (m_scriptsLock.RecursiveWriteCount > 0)
137 {
138 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
139 m_scriptsLock.ExitWriteLock();
140 }
141
142 while (!m_scriptsLock.TryEnterReadLock(60000))
143 {
144 m_log.Error("[XEngine.m_Scripts] Thread lock detected while trying to aquire READ lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
145 if (m_scriptsLock.IsWriteLockHeld)
146 {
147 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
148 }
149 }
150 }
151 else
152 {
153 m_scriptsLock.ExitReadLock();
154 }
155 }
156 private void lockScriptsForWrite(bool locked)
157 {
158 if (locked)
159 {
160 if (m_scriptsLock.RecursiveReadCount > 0)
161 {
162 m_log.Error("[XEngine.m_Scripts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
163 m_scriptsLock.ExitReadLock();
164 }
165 if (m_scriptsLock.RecursiveWriteCount > 0)
166 {
167 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
168 m_scriptsLock.ExitWriteLock();
169 }
170
171 while (!m_scriptsLock.TryEnterWriteLock(60000))
172 {
173 m_log.Error("[XEngine.m_Scripts] Thread lock detected while trying to aquire WRITE lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
174 if (m_scriptsLock.IsWriteLockHeld)
175 {
176 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
177 }
178 }
179 }
180 else
181 {
182 m_scriptsLock.ExitWriteLock();
183 }
184 }
185
124 public string ScriptEngineName 186 public string ScriptEngineName
125 { 187 {
126 get { return "XEngine"; } 188 get { return "XEngine"; }
@@ -260,43 +322,45 @@ namespace OpenSim.Region.ScriptEngine.XEngine
260 322
261 public void RemoveRegion(Scene scene) 323 public void RemoveRegion(Scene scene)
262 { 324 {
263 lock (m_Scripts) 325 lockScriptsForRead(true);
326 foreach (IScriptInstance instance in m_Scripts.Values)
264 { 327 {
265 foreach (IScriptInstance instance in m_Scripts.Values) 328 // Force a final state save
329 //
330 if (m_Assemblies.ContainsKey(instance.AssetID))
266 { 331 {
267 // Force a final state save 332 string assembly = m_Assemblies[instance.AssetID];
268 // 333 instance.SaveState(assembly);
269 if (m_Assemblies.ContainsKey(instance.AssetID)) 334 }
270 {
271 string assembly = m_Assemblies[instance.AssetID];
272 instance.SaveState(assembly);
273 }
274 335
275 // Clear the event queue and abort the instance thread 336 // Clear the event queue and abort the instance thread
276 // 337 //
277 instance.ClearQueue(); 338 instance.ClearQueue();
278 instance.Stop(0); 339 instance.Stop(0);
279 340
280 // Release events, timer, etc 341 // Release events, timer, etc
281 // 342 //
282 instance.DestroyScriptInstance(); 343 instance.DestroyScriptInstance();
283 344
284 // Unload scripts and app domains 345 // Unload scripts and app domains
285 // Must be done explicitly because they have infinite 346 // Must be done explicitly because they have infinite
286 // lifetime 347 // lifetime
287 // 348 //
288 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 349 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
289 if (m_DomainScripts[instance.AppDomain].Count == 0) 350 if (m_DomainScripts[instance.AppDomain].Count == 0)
290 { 351 {
291 m_DomainScripts.Remove(instance.AppDomain); 352 m_DomainScripts.Remove(instance.AppDomain);
292 UnloadAppDomain(instance.AppDomain); 353 UnloadAppDomain(instance.AppDomain);
293 }
294 } 354 }
295 m_Scripts.Clear();
296 m_PrimObjects.Clear();
297 m_Assemblies.Clear();
298 m_DomainScripts.Clear();
299 } 355 }
356 lockScriptsForRead(false);
357 lockScriptsForWrite(true);
358 m_Scripts.Clear();
359 lockScriptsForWrite(false);
360 m_PrimObjects.Clear();
361 m_Assemblies.Clear();
362 m_DomainScripts.Clear();
363
300 lock (m_ScriptEngines) 364 lock (m_ScriptEngines)
301 { 365 {
302 m_ScriptEngines.Remove(this); 366 m_ScriptEngines.Remove(this);
@@ -355,22 +419,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
355 419
356 List<IScriptInstance> instances = new List<IScriptInstance>(); 420 List<IScriptInstance> instances = new List<IScriptInstance>();
357 421
358 lock (m_Scripts) 422 lockScriptsForRead(true);
359 { 423 foreach (IScriptInstance instance in m_Scripts.Values)
360 foreach (IScriptInstance instance in m_Scripts.Values)
361 instances.Add(instance); 424 instances.Add(instance);
362 } 425 lockScriptsForRead(false);
363 426
364 foreach (IScriptInstance i in instances) 427 foreach (IScriptInstance i in instances)
365 { 428 {
366 string assembly = String.Empty; 429 string assembly = String.Empty;
367 430
368 lock (m_Scripts) 431
369 {
370 if (!m_Assemblies.ContainsKey(i.AssetID)) 432 if (!m_Assemblies.ContainsKey(i.AssetID))
371 continue; 433 continue;
372 assembly = m_Assemblies[i.AssetID]; 434 assembly = m_Assemblies[i.AssetID];
373 } 435
374 436
375 i.SaveState(assembly); 437 i.SaveState(assembly);
376 } 438 }
@@ -672,172 +734,183 @@ namespace OpenSim.Region.ScriptEngine.XEngine
672 return false; 734 return false;
673 } 735 }
674 736
675 lock (m_Scripts) 737
738
739 ScriptInstance instance = null;
740 // Create the object record
741 lockScriptsForRead(true);
742 if ((!m_Scripts.ContainsKey(itemID)) ||
743 (m_Scripts[itemID].AssetID != assetID))
676 { 744 {
677 ScriptInstance instance = null; 745 lockScriptsForRead(false);
678 // Create the object record
679 746
680 if ((!m_Scripts.ContainsKey(itemID)) || 747 UUID appDomain = assetID;
681 (m_Scripts[itemID].AssetID != assetID))
682 {
683 UUID appDomain = assetID;
684 748
685 if (part.ParentGroup.IsAttachment) 749 if (part.ParentGroup.IsAttachment)
686 appDomain = part.ParentGroup.RootPart.UUID; 750 appDomain = part.ParentGroup.RootPart.UUID;
687 751
688 if (!m_AppDomains.ContainsKey(appDomain)) 752 if (!m_AppDomains.ContainsKey(appDomain))
753 {
754 try
689 { 755 {
690 try 756 AppDomainSetup appSetup = new AppDomainSetup();
691 { 757 // appSetup.ApplicationBase = Path.Combine(
692 AppDomainSetup appSetup = new AppDomainSetup(); 758 // "ScriptEngines",
693// appSetup.ApplicationBase = Path.Combine( 759 // m_Scene.RegionInfo.RegionID.ToString());
694// "ScriptEngines", 760
695// m_Scene.RegionInfo.RegionID.ToString()); 761 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
696 762 Evidence evidence = new Evidence(baseEvidence);
697 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 763
698 Evidence evidence = new Evidence(baseEvidence); 764 AppDomain sandbox;
699 765 if (m_AppDomainLoading)
700 AppDomain sandbox; 766 sandbox = AppDomain.CreateDomain(
701 if (m_AppDomainLoading) 767 m_Scene.RegionInfo.RegionID.ToString(),
702 sandbox = AppDomain.CreateDomain( 768 evidence, appSetup);
703 m_Scene.RegionInfo.RegionID.ToString(), 769 else
704 evidence, appSetup); 770 sandbox = AppDomain.CurrentDomain;
705 else 771
706 sandbox = AppDomain.CurrentDomain; 772 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
707 773 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
708 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); 774 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
709 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); 775 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
710 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet"); 776 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
711 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet); 777 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
712 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement); 778 //sandbox.SetAppDomainPolicy(sandboxPolicy);
713 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup; 779
714 //sandbox.SetAppDomainPolicy(sandboxPolicy); 780 m_AppDomains[appDomain] = sandbox;
715 781
716 m_AppDomains[appDomain] = sandbox; 782 m_AppDomains[appDomain].AssemblyResolve +=
717 783 new ResolveEventHandler(
718 m_AppDomains[appDomain].AssemblyResolve += 784 AssemblyResolver.OnAssemblyResolve);
719 new ResolveEventHandler( 785 m_DomainScripts[appDomain] = new List<UUID>();
720 AssemblyResolver.OnAssemblyResolve);
721 m_DomainScripts[appDomain] = new List<UUID>();
722 }
723 catch (Exception e)
724 {
725 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
726 m_ScriptErrorMessage += "Exception creating app domain:\n";
727 m_ScriptFailCount++;
728 lock (m_AddingAssemblies)
729 {
730 m_AddingAssemblies[assembly]--;
731 }
732 return false;
733 }
734 } 786 }
735 m_DomainScripts[appDomain].Add(itemID); 787 catch (Exception e)
736
737 instance = new ScriptInstance(this, part,
738 itemID, assetID, assembly,
739 m_AppDomains[appDomain],
740 part.ParentGroup.RootPart.Name,
741 item.Name, startParam, postOnRez,
742 stateSource, m_MaxScriptQueue);
743
744 m_log.DebugFormat("[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}",
745 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, part.ParentGroup.RootPart.AbsolutePosition.ToString());
746
747 if (presence != null)
748 { 788 {
749 ShowScriptSaveResponse(item.OwnerID, 789 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
750 assetID, "Compile successful", true); 790 m_ScriptErrorMessage += "Exception creating app domain:\n";
791 m_ScriptFailCount++;
792 lock (m_AddingAssemblies)
793 {
794 m_AddingAssemblies[assembly]--;
795 }
796 return false;
751 } 797 }
798 }
799 m_DomainScripts[appDomain].Add(itemID);
752 800
753 instance.AppDomain = appDomain; 801 instance = new ScriptInstance(this, part,
754 instance.LineMap = linemap; 802 itemID, assetID, assembly,
803 m_AppDomains[appDomain],
804 part.ParentGroup.RootPart.Name,
805 item.Name, startParam, postOnRez,
806 stateSource, m_MaxScriptQueue);
755 807
756 m_Scripts[itemID] = instance; 808 m_log.DebugFormat("[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}",
757 } 809 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, part.ParentGroup.RootPart.AbsolutePosition.ToString());
758 810
759 lock (m_PrimObjects) 811 if (presence != null)
760 { 812 {
761 if (!m_PrimObjects.ContainsKey(localID)) 813 ShowScriptSaveResponse(item.OwnerID,
762 m_PrimObjects[localID] = new List<UUID>(); 814 assetID, "Compile successful", true);
815 }
763 816
764 if (!m_PrimObjects[localID].Contains(itemID)) 817 instance.AppDomain = appDomain;
765 m_PrimObjects[localID].Add(itemID); 818 instance.LineMap = linemap;
819 lockScriptsForWrite(true);
820 m_Scripts[itemID] = instance;
821 lockScriptsForWrite(false);
822 }
823 else
824 {
825 lockScriptsForRead(false);
826 }
827 lock (m_PrimObjects)
828 {
829 if (!m_PrimObjects.ContainsKey(localID))
830 m_PrimObjects[localID] = new List<UUID>();
766 831
767 } 832 if (!m_PrimObjects[localID].Contains(itemID))
833 m_PrimObjects[localID].Add(itemID);
768 834
769 if (!m_Assemblies.ContainsKey(assetID)) 835 }
770 m_Assemblies[assetID] = assembly;
771 836
772 lock (m_AddingAssemblies) 837 if (!m_Assemblies.ContainsKey(assetID))
773 { 838 m_Assemblies[assetID] = assembly;
774 m_AddingAssemblies[assembly]--;
775 }
776 839
777 if (instance!=null) 840 lock (m_AddingAssemblies)
778 instance.Init(); 841 {
842 m_AddingAssemblies[assembly]--;
779 } 843 }
844
845 if (instance!=null)
846 instance.Init();
847
780 return true; 848 return true;
781 } 849 }
782 850
783 public void OnRemoveScript(uint localID, UUID itemID) 851 public void OnRemoveScript(uint localID, UUID itemID)
784 { 852 {
785 lock (m_Scripts) 853 lockScriptsForRead(true);
854 // Do we even have it?
855 if (!m_Scripts.ContainsKey(itemID))
786 { 856 {
787 // Do we even have it? 857 lockScriptsForRead(false);
788 if (!m_Scripts.ContainsKey(itemID)) 858 return;
789 return; 859 }
860
790 861
791 IScriptInstance instance=m_Scripts[itemID]; 862 IScriptInstance instance=m_Scripts[itemID];
792 m_Scripts.Remove(itemID); 863 lockScriptsForRead(false);
864 lockScriptsForWrite(true);
865 m_Scripts.Remove(itemID);
866 lockScriptsForWrite(false);
867 instance.ClearQueue();
868 instance.Stop(0);
793 869
794 instance.ClearQueue(); 870 SceneObjectPart part =
795 instance.Stop(0); 871 m_Scene.GetSceneObjectPart(localID);
796 872
797 SceneObjectPart part = 873 if (part != null)
798 m_Scene.GetSceneObjectPart(localID); 874 part.RemoveScriptEvents(itemID);
799
800 if (part != null)
801 part.RemoveScriptEvents(itemID);
802 875
803// bool objectRemoved = false; 876// bool objectRemoved = false;
804 877
805 lock (m_PrimObjects) 878 lock (m_PrimObjects)
879 {
880 // Remove the script from it's prim
881 if (m_PrimObjects.ContainsKey(localID))
806 { 882 {
807 // Remove the script from it's prim 883 // Remove inventory item record
808 if (m_PrimObjects.ContainsKey(localID)) 884 if (m_PrimObjects[localID].Contains(itemID))
809 { 885 m_PrimObjects[localID].Remove(itemID);
810 // Remove inventory item record
811 if (m_PrimObjects[localID].Contains(itemID))
812 m_PrimObjects[localID].Remove(itemID);
813 886
814 // If there are no more scripts, remove prim 887 // If there are no more scripts, remove prim
815 if (m_PrimObjects[localID].Count == 0) 888 if (m_PrimObjects[localID].Count == 0)
816 { 889 {
817 m_PrimObjects.Remove(localID); 890 m_PrimObjects.Remove(localID);
818// objectRemoved = true; 891// objectRemoved = true;
819 }
820 } 892 }
821 } 893 }
894 }
822 895
823 instance.RemoveState(); 896 instance.RemoveState();
824 instance.DestroyScriptInstance(); 897 instance.DestroyScriptInstance();
825 898
826 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 899 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
827 if (m_DomainScripts[instance.AppDomain].Count == 0) 900 if (m_DomainScripts[instance.AppDomain].Count == 0)
828 { 901 {
829 m_DomainScripts.Remove(instance.AppDomain); 902 m_DomainScripts.Remove(instance.AppDomain);
830 UnloadAppDomain(instance.AppDomain); 903 UnloadAppDomain(instance.AppDomain);
831 } 904 }
832 905
833 instance = null; 906 instance = null;
834 907
835 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 908 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
836 if (handlerObjectRemoved != null) 909 if (handlerObjectRemoved != null)
837 handlerObjectRemoved(part.UUID); 910 handlerObjectRemoved(part.UUID);
838 911
839 CleanAssemblies(); 912 CleanAssemblies();
840 } 913
841 914
842 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 915 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
843 if (handlerScriptRemoved != null) 916 if (handlerScriptRemoved != null)
@@ -1090,12 +1163,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1090 private IScriptInstance GetInstance(UUID itemID) 1163 private IScriptInstance GetInstance(UUID itemID)
1091 { 1164 {
1092 IScriptInstance instance; 1165 IScriptInstance instance;
1093 lock (m_Scripts) 1166 lockScriptsForRead(true);
1167 if (!m_Scripts.ContainsKey(itemID))
1094 { 1168 {
1095 if (!m_Scripts.ContainsKey(itemID)) 1169 lockScriptsForRead(false);
1096 return null; 1170 return null;
1097 instance = m_Scripts[itemID];
1098 } 1171 }
1172 instance = m_Scripts[itemID];
1173 lockScriptsForRead(false);
1099 return instance; 1174 return instance;
1100 } 1175 }
1101 1176
@@ -1119,6 +1194,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1119 return false; 1194 return false;
1120 } 1195 }
1121 1196
1197 [DebuggerNonUserCode]
1122 public void ApiResetScript(UUID itemID) 1198 public void ApiResetScript(UUID itemID)
1123 { 1199 {
1124 IScriptInstance instance = GetInstance(itemID); 1200 IScriptInstance instance = GetInstance(itemID);
@@ -1170,6 +1246,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1170 return UUID.Zero; 1246 return UUID.Zero;
1171 } 1247 }
1172 1248
1249 [DebuggerNonUserCode]
1173 public void SetState(UUID itemID, string newState) 1250 public void SetState(UUID itemID, string newState)
1174 { 1251 {
1175 IScriptInstance instance = GetInstance(itemID); 1252 IScriptInstance instance = GetInstance(itemID);
@@ -1197,11 +1274,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1197 { 1274 {
1198 List<IScriptInstance> instances = new List<IScriptInstance>(); 1275 List<IScriptInstance> instances = new List<IScriptInstance>();
1199 1276
1200 lock (m_Scripts) 1277 lockScriptsForRead(true);
1201 { 1278 foreach (IScriptInstance instance in m_Scripts.Values)
1202 foreach (IScriptInstance instance in m_Scripts.Values)
1203 instances.Add(instance); 1279 instances.Add(instance);
1204 } 1280 lockScriptsForRead(false);
1205 1281
1206 foreach (IScriptInstance i in instances) 1282 foreach (IScriptInstance i in instances)
1207 { 1283 {
diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example
index 4351b3f..62aceb1 100644
--- a/bin/OpenSim.ini.example
+++ b/bin/OpenSim.ini.example
@@ -454,6 +454,9 @@
454 454
455 ; Distance in meters that shouts should travel. Default is 100m 455 ; Distance in meters that shouts should travel. Default is 100m
456 shout_distance = 100 456 shout_distance = 100
457
458 ; Append a prefix to the god avatar names appearing in chat whilst in god mode
459 ; admin_prefix = "@"
457 460
458 461
459[Messaging] 462[Messaging]