aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Application/OpenSimBase.cs49
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs148
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs5
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs31
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs102
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs51
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs11
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs17
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs15
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs330
-rw-r--r--OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs9
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs7
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityInventory.cs3
-rw-r--r--OpenSim/Region/Framework/Interfaces/IInterregionComms.cs8
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISnmpModule.cs27
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs26
-rw-r--r--OpenSim/Region/Framework/Scenes/EntityManager.cs79
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs71
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs75
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs47
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs26
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs685
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs145
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs722
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs688
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneViewer.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs9
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs9
-rw-r--r--OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs3
-rw-r--r--OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs2
-rw-r--r--OpenSim/Region/Physics/ChOdePlugin/AssemblyInfo.cs58
-rw-r--r--OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs1369
-rw-r--r--OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs3788
-rw-r--r--OpenSim/Region/Physics/ChOdePlugin/ODERayCastRequestManager.cs375
-rw-r--r--OpenSim/Region/Physics/ChOdePlugin/OdePhysicsJoint.cs (renamed from OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs)46
-rw-r--r--OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs3853
-rw-r--r--OpenSim/Region/Physics/ChOdePlugin/Tests/ODETestClass.cs122
-rw-r--r--OpenSim/Region/Physics/ChOdePlugin/drawstuff.cs98
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODECharacter.cs1
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODEPrim.cs2
-rw-r--r--OpenSim/Region/Physics/POSPlugin/POSPrim.cs2
-rw-r--r--OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs82
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs22
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs949
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs36
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs13
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs32
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs1
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs1
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs40
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs422
59 files changed, 13153 insertions, 1587 deletions
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index 83be61e..f053911 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -343,10 +343,26 @@ namespace OpenSim
343 else m_log.Error("[MODULES]: The new RegionModulesController is missing..."); 343 else m_log.Error("[MODULES]: The new RegionModulesController is missing...");
344 344
345 scene.SetModuleInterfaces(); 345 scene.SetModuleInterfaces();
346// First Step of bootreport sequence
347 if (scene.SnmpService != null)
348 {
349 scene.SnmpService.ColdStart(1,scene);
350 scene.SnmpService.LinkDown(scene);
351 }
352
353 if (scene.SnmpService != null)
354 {
355 scene.SnmpService.BootInfo("Loading prins", scene);
356 }
346 357
347 // Prims have to be loaded after module configuration since some modules may be invoked during the load 358 // Prims have to be loaded after module configuration since some modules may be invoked during the load
348 scene.LoadPrimsFromStorage(regionInfo.originRegionID); 359 scene.LoadPrimsFromStorage(regionInfo.originRegionID);
349 360
361 if (scene.SnmpService != null)
362 {
363 scene.SnmpService.BootInfo("Creating region texture", scene);
364 }
365
350 // moved these here as the terrain texture has to be created after the modules are initialized 366 // moved these here as the terrain texture has to be created after the modules are initialized
351 // and has to happen before the region is registered with the grid. 367 // and has to happen before the region is registered with the grid.
352 scene.CreateTerrainTexture(); 368 scene.CreateTerrainTexture();
@@ -354,6 +370,10 @@ namespace OpenSim
354 // TODO : Try setting resource for region xstats here on scene 370 // TODO : Try setting resource for region xstats here on scene
355 MainServer.Instance.AddStreamHandler(new Region.Framework.Scenes.RegionStatsHandler(regionInfo)); 371 MainServer.Instance.AddStreamHandler(new Region.Framework.Scenes.RegionStatsHandler(regionInfo));
356 372
373 if (scene.SnmpService != null)
374 {
375 scene.SnmpService.BootInfo("Grid Registration in progress", scene);
376 }
357 try 377 try
358 { 378 {
359 scene.RegisterRegionWithGrid(); 379 scene.RegisterRegionWithGrid();
@@ -362,11 +382,20 @@ namespace OpenSim
362 { 382 {
363 m_log.ErrorFormat("[STARTUP]: Registration of region with grid failed, aborting startup - {0}", e.StackTrace); 383 m_log.ErrorFormat("[STARTUP]: Registration of region with grid failed, aborting startup - {0}", e.StackTrace);
364 384
385 if (scene.SnmpService != null)
386 {
387 scene.SnmpService.Critical("Grid registration failed. Startup aborted.", scene);
388 }
365 // Carrying on now causes a lot of confusion down the 389 // Carrying on now causes a lot of confusion down the
366 // line - we need to get the user's attention 390 // line - we need to get the user's attention
367 Environment.Exit(1); 391 Environment.Exit(1);
368 } 392 }
369 393
394 if (scene.SnmpService != null)
395 {
396 scene.SnmpService.BootInfo("Grid Registration done", scene);
397 }
398
370 // We need to do this after we've initialized the 399 // We need to do this after we've initialized the
371 // scripting engines. 400 // scripting engines.
372 scene.CreateScriptInstances(); 401 scene.CreateScriptInstances();
@@ -374,6 +403,11 @@ namespace OpenSim
374 scene.loadAllLandObjectsFromStorage(regionInfo.originRegionID); 403 scene.loadAllLandObjectsFromStorage(regionInfo.originRegionID);
375 scene.EventManager.TriggerParcelPrimCountUpdate(); 404 scene.EventManager.TriggerParcelPrimCountUpdate();
376 405
406 if (scene.SnmpService != null)
407 {
408 scene.SnmpService.BootInfo("ScriptEngine started", scene);
409 }
410
377 m_sceneManager.Add(scene); 411 m_sceneManager.Add(scene);
378 412
379 if (m_autoCreateClientStack) 413 if (m_autoCreateClientStack)
@@ -382,6 +416,10 @@ namespace OpenSim
382 clientServer.Start(); 416 clientServer.Start();
383 } 417 }
384 418
419 if (scene.SnmpService != null)
420 {
421 scene.SnmpService.BootInfo("Initializing region modules", scene);
422 }
385 if (do_post_init) 423 if (do_post_init)
386 { 424 {
387 foreach (IRegionModule module in modules) 425 foreach (IRegionModule module in modules)
@@ -393,6 +431,12 @@ namespace OpenSim
393 431
394 mscene = scene; 432 mscene = scene;
395 433
434 if (scene.SnmpService != null)
435 {
436 scene.SnmpService.BootInfo("The region is operational", scene);
437 scene.SnmpService.LinkUp(scene);
438 }
439
396 scene.StartTimer(); 440 scene.StartTimer();
397 441
398 return clientServer; 442 return clientServer;
@@ -401,6 +445,11 @@ namespace OpenSim
401 private void ShutdownRegion(Scene scene) 445 private void ShutdownRegion(Scene scene)
402 { 446 {
403 m_log.DebugFormat("[SHUTDOWN]: Shutting down region {0}", scene.RegionInfo.RegionName); 447 m_log.DebugFormat("[SHUTDOWN]: Shutting down region {0}", scene.RegionInfo.RegionName);
448 if (scene.SnmpService != null)
449 {
450 scene.SnmpService.BootInfo("The region is shutting down", scene);
451 scene.SnmpService.LinkDown(scene);
452 }
404 IRegionModulesController controller; 453 IRegionModulesController controller;
405 if (ApplicationRegistry.TryGet<IRegionModulesController>(out controller)) 454 if (ApplicationRegistry.TryGet<IRegionModulesController>(out controller))
406 { 455 {
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 07c3a6a..e29ae2a 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -348,6 +348,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
348 private AgentUpdateArgs lastarg; 348 private AgentUpdateArgs lastarg;
349 private bool m_IsActive = true; 349 private bool m_IsActive = true;
350 private bool m_IsLoggingOut = false; 350 private bool m_IsLoggingOut = false;
351 private bool m_IsPresenceReady = false;
351 352
352 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>(); 353 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>();
353 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers 354 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
@@ -371,6 +372,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
371 372
372 private Timer m_propertiesPacketTimer; 373 private Timer m_propertiesPacketTimer;
373 private List<ObjectPropertiesPacket.ObjectDataBlock> m_propertiesBlocks = new List<ObjectPropertiesPacket.ObjectDataBlock>(); 374 private List<ObjectPropertiesPacket.ObjectDataBlock> m_propertiesBlocks = new List<ObjectPropertiesPacket.ObjectDataBlock>();
375 private List<Packet> m_pendingPackets;
374 376
375 #endregion Class Members 377 #endregion Class Members
376 378
@@ -411,6 +413,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
411 get { return m_IsActive; } 413 get { return m_IsActive; }
412 set { m_IsActive = value; } 414 set { m_IsActive = value; }
413 } 415 }
416
414 public bool IsLoggingOut 417 public bool IsLoggingOut
415 { 418 {
416 get { return m_IsLoggingOut; } 419 get { return m_IsLoggingOut; }
@@ -472,18 +475,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
472 475
473 #region Client Methods 476 #region Client Methods
474 477
478
475 /// <summary> 479 /// <summary>
476 /// Shut down the client view 480 /// Shut down the client view
477 /// </summary> 481 /// </summary>
478 public void Close() 482 public void Close()
479 { 483 {
484 Close(true);
485 }
486
487 /// <summary>
488 /// Shut down the client view
489 /// </summary>
490 public void Close(bool sendStop)
491 {
480 m_log.DebugFormat( 492 m_log.DebugFormat(
481 "[CLIENT]: Close has been called for {0} attached to scene {1}", 493 "[CLIENT]: Close has been called for {0} attached to scene {1}",
482 Name, m_scene.RegionInfo.RegionName); 494 Name, m_scene.RegionInfo.RegionName);
483 495
484 // Send the STOP packet 496 if (sendStop)
485 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator); 497 {
486 OutPacket(disable, ThrottleOutPacketType.Unknown); 498 // Send the STOP packet
499 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
500 OutPacket(disable, ThrottleOutPacketType.Unknown);
501 }
487 502
488 IsActive = false; 503 IsActive = false;
489 504
@@ -1034,6 +1049,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1034 public virtual void SendLayerData(float[] map) 1049 public virtual void SendLayerData(float[] map)
1035 { 1050 {
1036 Util.FireAndForget(DoSendLayerData, map); 1051 Util.FireAndForget(DoSendLayerData, map);
1052
1053 // Send it sync, and async. It's not that much data
1054 // and it improves user experience just so much!
1055 DoSendLayerData(map);
1037 } 1056 }
1038 1057
1039 /// <summary> 1058 /// <summary>
@@ -1046,16 +1065,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1046 1065
1047 try 1066 try
1048 { 1067 {
1049 //for (int y = 0; y < 16; y++) 1068 for (int y = 0; y < 16; y++)
1050 //{ 1069 {
1051 // for (int x = 0; x < 16; x++) 1070 for (int x = 0; x < 16; x+=4)
1052 // { 1071 {
1053 // SendLayerData(x, y, map); 1072 SendLayerPacket(x, y, map);
1054 // } 1073 }
1055 //} 1074 }
1056
1057 // Send LayerData in a spiral pattern. Fun!
1058 SendLayerTopRight(map, 0, 0, 15, 15);
1059 } 1075 }
1060 catch (Exception e) 1076 catch (Exception e)
1061 { 1077 {
@@ -1063,51 +1079,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1063 } 1079 }
1064 } 1080 }
1065 1081
1066 private void SendLayerTopRight(float[] map, int x1, int y1, int x2, int y2)
1067 {
1068 // Row
1069 for (int i = x1; i <= x2; i++)
1070 SendLayerData(i, y1, map);
1071
1072 // Column
1073 for (int j = y1 + 1; j <= y2; j++)
1074 SendLayerData(x2, j, map);
1075
1076 if (x2 - x1 > 0)
1077 SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2);
1078 }
1079
1080 void SendLayerBottomLeft(float[] map, int x1, int y1, int x2, int y2)
1081 {
1082 // Row in reverse
1083 for (int i = x2; i >= x1; i--)
1084 SendLayerData(i, y2, map);
1085
1086 // Column in reverse
1087 for (int j = y2 - 1; j >= y1; j--)
1088 SendLayerData(x1, j, map);
1089
1090 if (x2 - x1 > 0)
1091 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
1092 }
1093
1094 /// <summary> 1082 /// <summary>
1095 /// Sends a set of four patches (x, x+1, ..., x+3) to the client 1083 /// Sends a set of four patches (x, x+1, ..., x+3) to the client
1096 /// </summary> 1084 /// </summary>
1097 /// <param name="map">heightmap</param> 1085 /// <param name="map">heightmap</param>
1098 /// <param name="px">X coordinate for patches 0..12</param> 1086 /// <param name="px">X coordinate for patches 0..12</param>
1099 /// <param name="py">Y coordinate for patches 0..15</param> 1087 /// <param name="py">Y coordinate for patches 0..15</param>
1100 // private void SendLayerPacket(float[] map, int y, int x) 1088 private void SendLayerPacket(int x, int y, float[] map)
1101 // { 1089 {
1102 // int[] patches = new int[4]; 1090 int[] patches = new int[4];
1103 // patches[0] = x + 0 + y * 16; 1091 patches[0] = x + 0 + y * 16;
1104 // patches[1] = x + 1 + y * 16; 1092 patches[1] = x + 1 + y * 16;
1105 // patches[2] = x + 2 + y * 16; 1093 patches[2] = x + 2 + y * 16;
1106 // patches[3] = x + 3 + y * 16; 1094 patches[3] = x + 3 + y * 16;
1107 1095
1108 // Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); 1096 float[] heightmap = (map.Length == 65536) ?
1109 // OutPacket(layerpack, ThrottleOutPacketType.Land); 1097 map :
1110 // } 1098 LLHeightFieldMoronize(map);
1099
1100 try
1101 {
1102 Packet layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1103 OutPacket(layerpack, ThrottleOutPacketType.Land);
1104 }
1105 catch
1106 {
1107 for (int px = x ; px < x + 4 ; px++)
1108 SendLayerData(px, y, map);
1109 }
1110 }
1111 1111
1112 /// <summary> 1112 /// <summary>
1113 /// Sends a specified patch to a client 1113 /// Sends a specified patch to a client
@@ -1127,7 +1127,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1127 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); 1127 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1128 layerpack.Header.Reliable = true; 1128 layerpack.Header.Reliable = true;
1129 1129
1130 OutPacket(layerpack, ThrottleOutPacketType.Land); 1130 OutPacket(layerpack, ThrottleOutPacketType.Task);
1131 } 1131 }
1132 catch (Exception e) 1132 catch (Exception e)
1133 { 1133 {
@@ -3891,6 +3891,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3891 { 3891 {
3892 m_propertiesPacketTimer.Stop(); 3892 m_propertiesPacketTimer.Stop();
3893 3893
3894 if (m_propertiesBlocks.Count == 0)
3895 return;
3896
3894 proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[m_propertiesBlocks.Count]; 3897 proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[m_propertiesBlocks.Count];
3895 3898
3896 int index = 0; 3899 int index = 0;
@@ -4882,6 +4885,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4882 (x.CameraLeftAxis != lastarg.CameraLeftAxis) || 4885 (x.CameraLeftAxis != lastarg.CameraLeftAxis) ||
4883 (x.CameraUpAxis != lastarg.CameraUpAxis) || 4886 (x.CameraUpAxis != lastarg.CameraUpAxis) ||
4884 (x.ControlFlags != lastarg.ControlFlags) || 4887 (x.ControlFlags != lastarg.ControlFlags) ||
4888 (x.ControlFlags != 0) ||
4885 (x.Far != lastarg.Far) || 4889 (x.Far != lastarg.Far) ||
4886 (x.Flags != lastarg.Flags) || 4890 (x.Flags != lastarg.Flags) ||
4887 (x.State != lastarg.State) || 4891 (x.State != lastarg.State) ||
@@ -5252,7 +5256,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5252 args.Channel = ch; 5256 args.Channel = ch;
5253 args.From = String.Empty; 5257 args.From = String.Empty;
5254 args.Message = Utils.BytesToString(msg); 5258 args.Message = Utils.BytesToString(msg);
5255 args.Type = ChatTypeEnum.Shout; 5259 args.Type = ChatTypeEnum.Region; //Behaviour in SL is that the response can be heard from any distance
5256 args.Position = new Vector3(); 5260 args.Position = new Vector3();
5257 args.Scene = Scene; 5261 args.Scene = Scene;
5258 args.Sender = this; 5262 args.Sender = this;
@@ -11170,18 +11174,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11170 } 11174 }
11171 11175
11172 /// <summary> 11176 /// <summary>
11177 /// This processes packets which have accumulated while the presence was still in the process of initialising.
11178 /// </summary>
11179 public void ProcessPendingPackets()
11180 {
11181 m_IsPresenceReady = true;
11182 if (m_pendingPackets == null)
11183 return;
11184 foreach (Packet p in m_pendingPackets)
11185 {
11186 ProcessInPacket(p);
11187 }
11188 m_pendingPackets.Clear();
11189 }
11190
11191 /// <summary>
11173 /// Entryway from the client to the simulator. All UDP packets from the client will end up here 11192 /// Entryway from the client to the simulator. All UDP packets from the client will end up here
11174 /// </summary> 11193 /// </summary>
11175 /// <param name="Pack">OpenMetaverse.packet</param> 11194 /// <param name="Pack">OpenMetaverse.packet</param>
11176 public void ProcessInPacket(Packet Pack) 11195 public void ProcessInPacket(Packet Pack)
11177 { 11196 {
11178 if (m_debugPacketLevel >= 255) 11197 if (!m_IsPresenceReady)
11179 m_log.DebugFormat("[CLIENT]: Packet IN {0}", Pack.Type); 11198 {
11199 if (m_pendingPackets == null)
11200 {
11201 m_pendingPackets = new List<Packet>();
11202 }
11203 m_pendingPackets.Add(Pack);
11204 }
11205 else
11206 {
11207 if (m_debugPacketLevel >= 255)
11208 m_log.DebugFormat("[CLIENT]: Packet IN {0}", Pack.Type);
11180 11209
11181 if (!ProcessPacketMethod(Pack)) 11210 if (!ProcessPacketMethod(Pack))
11182 m_log.Warn("[CLIENT]: unhandled packet " + Pack.Type); 11211 m_log.Warn("[CLIENT]: unhandled packet " + Pack.Type);
11183 11212
11184 PacketPool.Instance.ReturnPacket(Pack); 11213 PacketPool.Instance.ReturnPacket(Pack);
11214 }
11185 } 11215 }
11186 11216
11187 private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) 11217 private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket)
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index 1b81105..cda461c 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -899,7 +899,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
899 client.OnLogout += LogoutHandler; 899 client.OnLogout += LogoutHandler;
900 900
901 // Start the IClientAPI 901 // Start the IClientAPI
902 client.Start(); 902 // Spin it off so that it doesn't clog up the LLUDPServer
903 Util.FireAndForget(delegate(object o) { client.Start(); });
903 } 904 }
904 else 905 else
905 { 906 {
@@ -915,7 +916,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
915 if (m_scene.TryGetClient(udpClient.AgentID, out client)) 916 if (m_scene.TryGetClient(udpClient.AgentID, out client))
916 { 917 {
917 client.IsLoggingOut = true; 918 client.IsLoggingOut = true;
918 client.Close(); 919 client.Close(false);
919 } 920 }
920 } 921 }
921 922
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index f050dcf..4fac01f 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -27,6 +27,7 @@
27 27
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.Reflection; 29using System.Reflection;
30using System.Xml;
30using log4net; 31using log4net;
31using Nini.Config; 32using Nini.Config;
32using OpenMetaverse; 33using OpenMetaverse;
@@ -35,6 +36,7 @@ using OpenSim.Framework;
35using OpenSim.Region.Framework; 36using OpenSim.Region.Framework;
36using OpenSim.Region.Framework.Interfaces; 37using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes; 38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Region.Framework.Scenes.Serialization;
38 40
39namespace OpenSim.Region.CoreModules.Avatar.Attachments 41namespace OpenSim.Region.CoreModules.Avatar.Attachments
40{ 42{
@@ -190,8 +192,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
190 192
191 public UUID RezSingleAttachmentFromInventory( 193 public UUID RezSingleAttachmentFromInventory(
192 IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus) 194 IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus)
195 {
196 return RezSingleAttachmentFromInventory(remoteClient, itemID, AttachmentPt, true, null);
197 }
198
199 public UUID RezSingleAttachmentFromInventory(
200 IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus, XmlDocument doc)
193 { 201 {
194 SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(remoteClient, itemID, AttachmentPt); 202 SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(remoteClient, itemID, AttachmentPt, doc);
195 203
196 if (updateInventoryStatus) 204 if (updateInventoryStatus)
197 { 205 {
@@ -210,7 +218,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
210 } 218 }
211 219
212 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal( 220 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal(
213 IClientAPI remoteClient, UUID itemID, uint AttachmentPt) 221 IClientAPI remoteClient, UUID itemID, uint AttachmentPt, XmlDocument doc)
214 { 222 {
215 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>(); 223 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>();
216 if (invAccess != null) 224 if (invAccess != null)
@@ -236,13 +244,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
236 if (tainted) 244 if (tainted)
237 objatt.HasGroupChanged = true; 245 objatt.HasGroupChanged = true;
238 246
247 if (doc != null)
248 {
249 objatt.LoadScriptState(doc);
250 objatt.ResetOwnerChangeFlag();
251 }
252
239 // Fire after attach, so we don't get messy perms dialogs 253 // Fire after attach, so we don't get messy perms dialogs
240 // 3 == AttachedRez 254 // 3 == AttachedRez
241 objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 3); 255 objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 3);
242 objatt.ResumeScripts(); 256 objatt.ResumeScripts();
243 257
244 // Do this last so that event listeners have access to all the effects of the attachment 258 // Do this last so that event listeners have access to all the effects of the attachment
245 m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, remoteClient.AgentId); 259 //m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, remoteClient.AgentId);
246 } 260 }
247 else 261 else
248 { 262 {
@@ -271,7 +285,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
271 if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) 285 if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence))
272 { 286 {
273 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); 287 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId);
274 item = m_scene.InventoryService.GetItem(item); 288 if (m_scene.InventoryService != null)
289 item = m_scene.InventoryService.GetItem(item);
275 290
276 presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /*att.UUID*/); 291 presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /*att.UUID*/);
277 } 292 }
@@ -316,6 +331,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
316 { 331 {
317 // XXYY!! 332 // XXYY!!
318 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); 333 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId);
334 if (item == null)
335 m_log.Error("[ATTACHMENT]: item == null");
336 if (m_scene == null)
337 m_log.Error("[ATTACHMENT]: m_scene == null");
338 if (m_scene.InventoryService == null)
339 m_log.Error("[ATTACHMENT]: m_scene.InventoryService == null");
319 item = m_scene.InventoryService.GetItem(item); 340 item = m_scene.InventoryService.GetItem(item);
320 presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /* att.UUID */); 341 presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /* att.UUID */);
321 342
@@ -404,6 +425,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
404 if (group.GetFromItemID() == itemID) 425 if (group.GetFromItemID() == itemID)
405 { 426 {
406 m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero); 427 m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero);
428 // CM / XMREngine!!!! Needed to conclude attach event
429 SceneObjectSerializer.ToOriginalXmlFormat(group);
407 group.DetachToInventoryPrep(); 430 group.DetachToInventoryPrep();
408 m_log.Debug("[ATTACHMENTS MODULE]: Saving attachpoint: " + ((uint)group.GetAttachmentPoint()).ToString()); 431 m_log.Debug("[ATTACHMENTS MODULE]: Saving attachpoint: " + ((uint)group.GetAttachmentPoint()).ToString());
409 m_scene.UpdateKnownItem(remoteClient, group,group.GetFromItemID(), group.OwnerID); 432 m_scene.UpdateKnownItem(remoteClient, group,group.GetFromItemID(), group.OwnerID);
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
index 02f0968..9c8cbc6 100644
--- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
@@ -49,7 +49,8 @@ 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 List<string> FreezeCache = new List<string>();
53 private string m_adminPrefix = "";
53 internal object m_syncy = new object(); 54 internal object m_syncy = new object();
54 55
55 internal IConfig m_config; 56 internal IConfig m_config;
@@ -76,6 +77,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
76 m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance); 77 m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance);
77 m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance); 78 m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance);
78 m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance); 79 m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance);
80 m_adminPrefix = config.Configs["Chat"].GetString("admin_prefix", "");
79 } 81 }
80 82
81 public virtual void AddRegion(Scene scene) 83 public virtual void AddRegion(Scene scene)
@@ -171,7 +173,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
171 return; 173 return;
172 } 174 }
173 175
174 DeliverChatToAvatars(ChatSourceType.Agent, c); 176 if (FreezeCache.Contains(c.Sender.AgentId.ToString()))
177 {
178 if (c.Type != ChatTypeEnum.StartTyping || c.Type != ChatTypeEnum.StopTyping)
179 c.Sender.SendAgentAlertMessage("You may not talk as you are frozen.", false);
180 }
181 else
182 {
183 DeliverChatToAvatars(ChatSourceType.Agent, c);
184 }
175 } 185 }
176 186
177 public virtual void OnChatFromWorld(Object sender, OSChatMessage c) 187 public virtual void OnChatFromWorld(Object sender, OSChatMessage c)
@@ -185,6 +195,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
185 protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c) 195 protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c)
186 { 196 {
187 string fromName = c.From; 197 string fromName = c.From;
198 string fromNamePrefix = "";
188 UUID fromID = UUID.Zero; 199 UUID fromID = UUID.Zero;
189 string message = c.Message; 200 string message = c.Message;
190 IScene scene = c.Scene; 201 IScene scene = c.Scene;
@@ -207,7 +218,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
207 fromPos = avatar.AbsolutePosition; 218 fromPos = avatar.AbsolutePosition;
208 fromName = avatar.Name; 219 fromName = avatar.Name;
209 fromID = c.Sender.AgentId; 220 fromID = c.Sender.AgentId;
210 221 if (avatar.GodLevel > 200)
222 {
223 fromNamePrefix = m_adminPrefix;
224 }
211 break; 225 break;
212 226
213 case ChatSourceType.Object: 227 case ChatSourceType.Object:
@@ -227,7 +241,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
227 s.ForEachScenePresence( 241 s.ForEachScenePresence(
228 delegate(ScenePresence presence) 242 delegate(ScenePresence presence)
229 { 243 {
230 TrySendChatMessage(presence, fromPos, regionPos, fromID, fromName, c.Type, message, sourceType); 244 ILandObject Presencecheck = s.LandChannel.GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y);
245 if (Presencecheck != null)
246 {
247 if (Presencecheck.IsEitherBannedOrRestricted(c.SenderUUID) != true)
248 {
249 TrySendChatMessage(presence, fromPos, regionPos, fromID, fromNamePrefix+fromName, c.Type, message, sourceType);
250 }
251 }
252
231 } 253 }
232 ); 254 );
233 } 255 }
@@ -270,25 +292,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
270 } 292 }
271 293
272 // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType); 294 // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType);
273 295 if (c.Scene != null)
274 ((Scene)c.Scene).ForEachScenePresence( 296 {
275 delegate(ScenePresence presence) 297 ((Scene)c.Scene).ForEachScenePresence
276 { 298 (
277 // ignore chat from child agents 299 delegate(ScenePresence presence)
278 if (presence.IsChildAgent) return; 300 {
279 301 // ignore chat from child agents
280 IClientAPI client = presence.ControllingClient; 302 if (presence.IsChildAgent) return;
281 303
282 // don't forward SayOwner chat from objects to 304 IClientAPI client = presence.ControllingClient;
283 // non-owner agents 305
284 if ((c.Type == ChatTypeEnum.Owner) && 306 // don't forward SayOwner chat from objects to
285 (null != c.SenderObject) && 307 // non-owner agents
286 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) 308 if ((c.Type == ChatTypeEnum.Owner) &&
287 return; 309 (null != c.SenderObject) &&
288 310 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId))
289 client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, 311 return;
290 (byte)sourceType, (byte)ChatAudibleLevel.Fully); 312
291 }); 313 client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID,
314 (byte)sourceType, (byte)ChatAudibleLevel.Fully);
315 }
316 );
317 }
292 } 318 }
293 319
294 320
@@ -317,5 +343,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
317 presence.ControllingClient.SendChatMessage(message, (byte) type, fromPos, fromName, 343 presence.ControllingClient.SendChatMessage(message, (byte) type, fromPos, fromName,
318 fromAgentID,(byte)src,(byte)ChatAudibleLevel.Fully); 344 fromAgentID,(byte)src,(byte)ChatAudibleLevel.Fully);
319 } 345 }
346
347 Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>();
348 public void ParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
349 {
350 System.Threading.Timer Timer;
351 if (flags == 0)
352 {
353 FreezeCache.Add(target.ToString());
354 System.Threading.TimerCallback timeCB = new System.Threading.TimerCallback(OnEndParcelFrozen);
355 Timer = new System.Threading.Timer(timeCB, target, 30000, 0);
356 Timers.Add(target, Timer);
357 }
358 else
359 {
360 FreezeCache.Remove(target.ToString());
361 Timers.TryGetValue(target, out Timer);
362 Timers.Remove(target);
363 Timer.Dispose();
364 }
365 }
366
367 private void OnEndParcelFrozen(object avatar)
368 {
369 UUID target = (UUID)avatar;
370 FreezeCache.Remove(target.ToString());
371 System.Threading.Timer Timer;
372 Timers.TryGetValue(target, out Timer);
373 Timers.Remove(target);
374 Timer.Dispose();
375 }
320 } 376 }
321} 377}
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index 0c81f44..30eb9b8 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -67,7 +67,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
67 return false; 67 return false;
68 } 68 }
69 } 69 }
70 70
71 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 71 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
72 72
73 protected List<Scene> m_Scenes = new List<Scene>(); 73 protected List<Scene> m_Scenes = new List<Scene>();
@@ -201,9 +201,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
201 201
202 UserFriendData data = m_Friends[principalID]; 202 UserFriendData data = m_Friends[principalID];
203 203
204 string searchFor = friendID.ToString();
204 foreach (FriendInfo fi in data.Friends) 205 foreach (FriendInfo fi in data.Friends)
205 { 206 {
206 if (fi.Friend == friendID.ToString()) 207 if (fi.Friend == searchFor)
207 return (uint)fi.TheirFlags; 208 return (uint)fi.TheirFlags;
208 } 209 }
209 return 0; 210 return 0;
@@ -234,7 +235,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
234 newFriends.RegionID = UUID.Zero; 235 newFriends.RegionID = UUID.Zero;
235 236
236 m_Friends.Add(client.AgentId, newFriends); 237 m_Friends.Add(client.AgentId, newFriends);
237 238
238 //StatusChange(client.AgentId, true); 239 //StatusChange(client.AgentId, true);
239 } 240 }
240 241
@@ -289,7 +290,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
289 290
290 // Inform the friends that this user is online 291 // Inform the friends that this user is online
291 StatusChange(agentID, true); 292 StatusChange(agentID, true);
292 293
293 // Register that we need to send the list of online friends to this user 294 // Register that we need to send the list of online friends to this user
294 lock (m_NeedsListOfFriends) 295 lock (m_NeedsListOfFriends)
295 if (!m_NeedsListOfFriends.Contains(agentID)) 296 if (!m_NeedsListOfFriends.Contains(agentID))
@@ -439,11 +440,47 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
439 if (((fi.MyFlags & 1) != 0) && (fi.TheirFlags != -1)) 440 if (((fi.MyFlags & 1) != 0) && (fi.TheirFlags != -1))
440 friendList.Add(fi); 441 friendList.Add(fi);
441 } 442 }
443 /*
442 foreach (FriendInfo fi in friendList) 444 foreach (FriendInfo fi in friendList)
443 { 445 {
444 // Notify about this user status 446 // Notify about this user status
445 StatusNotify(fi, agentID, online); 447 StatusNotify(fi, agentID, online);
446 } 448 }
449 */
450
451 StatusNotifyMass(friendList, agentID, online);
452 }
453 }
454
455 private void StatusNotifyMass(List<FriendInfo> friendList, UUID userID, bool online)
456 {
457 int fct = friendList.Count;
458 string[] friendIDs = new string[fct];
459 int notlocal = 0;
460 for (int x = 0 ; x < fct ; x++)
461 {
462 UUID friendID = UUID.Zero;
463 if (UUID.TryParse(friendList[x].Friend, out friendID))
464 {
465 if (!LocalStatusNotification(userID, friendID, online))
466 {
467 friendIDs[notlocal++] = friendID.ToString();
468 }
469 }
470 }
471
472 PresenceInfo[] friendSessions = PresenceService.GetAgents(friendIDs);
473
474 for (int x = 0; x < friendSessions.GetLength(0); x++)
475 {
476 if (friendIDs.Length <= x)
477 continue;
478 PresenceInfo friendSession = friendSessions[x];
479 if (friendSession != null)
480 {
481 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
482 m_FriendsSimConnector.StatusNotify(region, userID, new UUID(friendIDs[x]), online);
483 }
447 } 484 }
448 } 485 }
449 486
@@ -456,7 +493,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
456 // Try local 493 // Try local
457 if (LocalStatusNotification(userID, friendID, online)) 494 if (LocalStatusNotification(userID, friendID, online))
458 return; 495 return;
459 496
460 // The friend is not here [as root]. Let's forward. 497 // The friend is not here [as root]. Let's forward.
461 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); 498 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() });
462 if (friendSessions != null && friendSessions.Length > 0) 499 if (friendSessions != null && friendSessions.Length > 0)
@@ -476,7 +513,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
476 private void OnInstantMessage(IClientAPI client, GridInstantMessage im) 513 private void OnInstantMessage(IClientAPI client, GridInstantMessage im)
477 { 514 {
478 if (im.dialog == (byte)OpenMetaverse.InstantMessageDialog.FriendshipOffered) 515 if (im.dialog == (byte)OpenMetaverse.InstantMessageDialog.FriendshipOffered)
479 { 516 {
480 // we got a friendship offer 517 // we got a friendship offer
481 UUID principalID = new UUID(im.fromAgentID); 518 UUID principalID = new UUID(im.fromAgentID);
482 UUID friendID = new UUID(im.toAgentID); 519 UUID friendID = new UUID(im.toAgentID);
@@ -701,7 +738,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
701 // we're done 738 // we're done
702 return true; 739 return true;
703 } 740 }
704 741
705 return false; 742 return false;
706 } 743 }
707 744
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
index fdfcd10..9412735 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
@@ -172,13 +172,16 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
172 172
173 private void RetrieveInstantMessages(IClientAPI client) 173 private void RetrieveInstantMessages(IClientAPI client)
174 { 174 {
175 if (m_RestURL != "") 175 if (m_RestURL == String.Empty)
176 { 176 return;
177 m_log.DebugFormat("[OFFLINE MESSAGING] Retrieving stored messages for {0}", client.AgentId);
178 177
179 List<GridInstantMessage> msglist = SynchronousRestObjectPoster.BeginPostObject<UUID, List<GridInstantMessage>>( 178 m_log.DebugFormat("[OFFLINE MESSAGING] Retrieving stored messages for {0}", client.AgentId);
179
180 List<GridInstantMessage> msglist = SynchronousRestObjectPoster.BeginPostObject<UUID, List<GridInstantMessage>>(
180 "POST", m_RestURL + "/RetrieveMessages/", client.AgentId); 181 "POST", m_RestURL + "/RetrieveMessages/", client.AgentId);
181 182
183 if (msglist != null)
184 {
182 foreach (GridInstantMessage im in msglist) 185 foreach (GridInstantMessage im in msglist)
183 { 186 {
184 // client.SendInstantMessage(im); 187 // client.SendInstantMessage(im);
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
index be89740..7142442 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
@@ -417,7 +417,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
417 { 417 {
418 // Check if this is ours to handle 418 // Check if this is ours to handle
419 // 419 //
420 m_log.Info("OnFridInstantMessage"); 420 //m_log.Info("OnFridInstantMessage");
421 if (msg.dialog != (byte) InstantMessageDialog.InventoryOffered) 421 if (msg.dialog != (byte) InstantMessageDialog.InventoryOffered)
422 return; 422 return;
423 423
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
index e32dbb3..329a259 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
@@ -290,6 +290,23 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
290 return false; 290 return false;
291 } 291 }
292 292
293 public bool CloseChildAgent(GridRegion destination, UUID id)
294 {
295 if (destination == null)
296 return false;
297
298 foreach (Scene s in m_sceneList)
299 {
300 if (s.RegionInfo.RegionID == destination.RegionID)
301 {
302 //m_log.Debug("[LOCAL COMMS]: Found region to SendCloseAgent");
303 return s.IncomingCloseChildAgent(id);
304 }
305 }
306 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent");
307 return false;
308 }
309
293 /** 310 /**
294 * Object-related communications 311 * Object-related communications
295 */ 312 */
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
index 9e8454f..377c868 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
@@ -253,6 +253,21 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
253 return false; 253 return false;
254 } 254 }
255 255
256 public bool CloseChildAgent(GridRegion destination, UUID id)
257 {
258 if (destination == null)
259 return false;
260
261 // Try local first
262 if (m_localBackend.CloseChildAgent(destination, id))
263 return true;
264
265 // else do the remote thing
266 if (!m_localBackend.IsLocalRegion(destination.RegionHandle))
267 return m_remoteConnector.CloseChildAgent(destination, id);
268
269 return false;
270 }
256 271
257 public bool CloseAgent(GridRegion destination, UUID id) 272 public bool CloseAgent(GridRegion destination, UUID id)
258 { 273 {
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index c52f029..b37beab 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -263,10 +263,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver
263 // Fix ownership/creator of inventory items 263 // Fix ownership/creator of inventory items
264 // Not doing so results in inventory items 264 // Not doing so results in inventory items
265 // being no copy/no mod for everyone 265 // being no copy/no mod for everyone
266 lock (part.TaskInventory) 266 part.TaskInventory.LockItemsForRead(true);
267 TaskInventoryDictionary inv = part.TaskInventory;
268 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv)
267 { 269 {
268 TaskInventoryDictionary inv = part.TaskInventory; 270 if (!ResolveUserUuid(kvp.Value.OwnerID))
269 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv)
270 { 271 {
271 if (!ResolveUserUuid(kvp.Value.OwnerID)) 272 if (!ResolveUserUuid(kvp.Value.OwnerID))
272 { 273 {
@@ -278,6 +279,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
278 } 279 }
279 } 280 }
280 } 281 }
282 part.TaskInventory.LockItemsForRead(false);
281 } 283 }
282 284
283 if (m_scene.AddRestoredSceneObject(sceneObject, true, false)) 285 if (m_scene.AddRestoredSceneObject(sceneObject, true, false))
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index 4ccd0f0..9d6c9a9 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
@@ -82,6 +82,8 @@ namespace OpenSim.Region.CoreModules.World.Land
82 private int m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1; 82 private int m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1;
83 83
84 private bool m_allowedForcefulBans = true; 84 private bool m_allowedForcefulBans = true;
85 private UUID DefaultGodParcelGroup;
86 private string DefaultGodParcelName;
85 87
86 // caches ExtendedLandData 88 // caches ExtendedLandData
87 private Cache parcelInfoCache; 89 private Cache parcelInfoCache;
@@ -96,6 +98,12 @@ namespace OpenSim.Region.CoreModules.World.Land
96 98
97 public void Initialise(IConfigSource source) 99 public void Initialise(IConfigSource source)
98 { 100 {
101 IConfig cnf = source.Configs["LandManagement"];
102 if (cnf != null)
103 {
104 DefaultGodParcelGroup = new UUID(cnf.GetString("DefaultAdministratorGroupUUID", UUID.Zero.ToString()));
105 DefaultGodParcelName = cnf.GetString("DefaultAdministratorParcelName", "Default Parcel");
106 }
99 } 107 }
100 108
101 public void AddRegion(Scene scene) 109 public void AddRegion(Scene scene)
@@ -351,7 +359,7 @@ namespace OpenSim.Region.CoreModules.World.Land
351 { 359 {
352 if (avatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT) 360 if (avatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT)
353 { 361 {
354 if (parcelAvatarIsEntering.IsBannedFromLand(avatar.UUID)) 362 if (parcelAvatarIsEntering.IsEitherBannedOrRestricted(avatar.UUID))
355 { 363 {
356 SendYouAreBannedNotice(avatar); 364 SendYouAreBannedNotice(avatar);
357 ForceAvatarToPosition(avatar, m_scene.GetNearestAllowedPosition(avatar)); 365 ForceAvatarToPosition(avatar, m_scene.GetNearestAllowedPosition(avatar));
@@ -991,6 +999,10 @@ namespace OpenSim.Region.CoreModules.World.Land
991 //Owner Flag 999 //Owner Flag
992 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER); 1000 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER);
993 } 1001 }
1002 else if (currentParcelBlock.LandData.IsGroupOwned && remote_client.IsGroupMember(currentParcelBlock.LandData.GroupID))
1003 {
1004 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_GROUP);
1005 }
994 else if (currentParcelBlock.LandData.SalePrice > 0 && 1006 else if (currentParcelBlock.LandData.SalePrice > 0 &&
995 (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero || 1007 (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero ||
996 currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId)) 1008 currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId))
@@ -1520,5 +1532,321 @@ namespace OpenSim.Region.CoreModules.World.Land
1520 1532
1521 UpdateLandObject(localID, land.LandData); 1533 UpdateLandObject(localID, land.LandData);
1522 } 1534 }
1535
1536 public void ClientOnParcelGodMark(IClientAPI client, UUID god, int landID)
1537 {
1538 ILandObject land = null;
1539 List<ILandObject> Land = ((Scene)client.Scene).LandChannel.AllParcels();
1540 foreach (ILandObject landObject in Land)
1541 {
1542 if (landObject.LandData.LocalID == landID)
1543 {
1544 land = landObject;
1545 }
1546 }
1547 land.DeedToGroup(DefaultGodParcelGroup);
1548 land.LandData.Name = DefaultGodParcelName;
1549 land.SendLandUpdateToAvatarsOverMe();
1550 }
1551
1552 private void ClientOnSimWideDeletes(IClientAPI client, UUID agentID, int flags, UUID targetID)
1553 {
1554 ScenePresence SP;
1555 ((Scene)client.Scene).TryGetScenePresence(client.AgentId, out SP);
1556 List<SceneObjectGroup> returns = new List<SceneObjectGroup>();
1557 if (SP.GodLevel != 0)
1558 {
1559 if (flags == 0) //All parcels, scripted or not
1560 {
1561 ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e)
1562 {
1563 if (e.OwnerID == targetID)
1564 {
1565 returns.Add(e);
1566 }
1567 }
1568 );
1569 }
1570 if (flags == 4) //All parcels, scripted object
1571 {
1572 ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e)
1573 {
1574 if (e.OwnerID == targetID)
1575 {
1576 if (e.scriptScore >= 0.01)
1577 {
1578 returns.Add(e);
1579 }
1580 }
1581 }
1582 );
1583 }
1584 if (flags == 4) //not target parcel, scripted object
1585 {
1586 ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e)
1587 {
1588 if (e.OwnerID == targetID)
1589 {
1590 ILandObject landobject = ((Scene)client.Scene).LandChannel.GetLandObject(e.AbsolutePosition.X, e.AbsolutePosition.Y);
1591 if (landobject.LandData.OwnerID != e.OwnerID)
1592 {
1593 if (e.scriptScore >= 0.01)
1594 {
1595 returns.Add(e);
1596 }
1597 }
1598 }
1599 }
1600 );
1601 }
1602 foreach (SceneObjectGroup ol in returns)
1603 {
1604 ReturnObject(ol, client);
1605 }
1606 }
1607 }
1608 public void ReturnObject(SceneObjectGroup obj, IClientAPI client)
1609 {
1610 SceneObjectGroup[] objs = new SceneObjectGroup[1];
1611 objs[0] = obj;
1612 ((Scene)client.Scene).returnObjects(objs, client.AgentId);
1613 }
1614
1615 Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>();
1616
1617 public void ClientOnParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
1618 {
1619 ScenePresence targetAvatar = null;
1620 ((Scene)client.Scene).TryGetScenePresence(target, out targetAvatar);
1621 ScenePresence parcelManager = null;
1622 ((Scene)client.Scene).TryGetScenePresence(client.AgentId, out parcelManager);
1623 System.Threading.Timer Timer;
1624
1625 if (targetAvatar.GodLevel == 0)
1626 {
1627 ILandObject land = ((Scene)client.Scene).LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y);
1628 if (!((Scene)client.Scene).Permissions.CanEditParcel(client.AgentId, land))
1629 return;
1630 if (flags == 0)
1631 {
1632 targetAvatar.AllowMovement = false;
1633 targetAvatar.ControllingClient.SendAlertMessage(parcelManager.Firstname + " " + parcelManager.Lastname + " has frozen you for 30 seconds. You cannot move or interact with the world.");
1634 parcelManager.ControllingClient.SendAlertMessage("Avatar Frozen.");
1635 System.Threading.TimerCallback timeCB = new System.Threading.TimerCallback(OnEndParcelFrozen);
1636 Timer = new System.Threading.Timer(timeCB, targetAvatar, 30000, 0);
1637 Timers.Add(targetAvatar.UUID, Timer);
1638 }
1639 else
1640 {
1641 targetAvatar.AllowMovement = true;
1642 targetAvatar.ControllingClient.SendAlertMessage(parcelManager.Firstname + " " + parcelManager.Lastname + " has unfrozen you.");
1643 parcelManager.ControllingClient.SendAlertMessage("Avatar Unfrozen.");
1644 Timers.TryGetValue(targetAvatar.UUID, out Timer);
1645 Timers.Remove(targetAvatar.UUID);
1646 Timer.Dispose();
1647 }
1648 }
1649 }
1650 private void OnEndParcelFrozen(object avatar)
1651 {
1652 ScenePresence targetAvatar = (ScenePresence)avatar;
1653 targetAvatar.AllowMovement = true;
1654 System.Threading.Timer Timer;
1655 Timers.TryGetValue(targetAvatar.UUID, out Timer);
1656 Timers.Remove(targetAvatar.UUID);
1657 targetAvatar.ControllingClient.SendAgentAlertMessage("The freeze has worn off; you may go about your business.", false);
1658 }
1659
1660
1661 public void ClientOnParcelEjectUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
1662 {
1663 ScenePresence targetAvatar = null;
1664 ((Scene)client.Scene).TryGetScenePresence(target, out targetAvatar);
1665 ScenePresence parcelManager = null;
1666 ((Scene)client.Scene).TryGetScenePresence(client.AgentId, out parcelManager);
1667 //Just eject
1668 if (flags == 0)
1669 {
1670 if (targetAvatar.GodLevel == 0)
1671 {
1672 ILandObject land = ((Scene)client.Scene).LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y);
1673 if (!((Scene)client.Scene).Permissions.CanEditParcel(client.AgentId, land))
1674 return;
1675
1676 Vector3 position = new Vector3(0, 0, 0);
1677 List<ILandObject> allParcels = new List<ILandObject>();
1678 allParcels = AllParcels();
1679 if (allParcels.Count != 1)
1680 {
1681 foreach (ILandObject parcel in allParcels)
1682 {
1683 if (parcel.LandData.GlobalID != land.LandData.GlobalID)
1684 {
1685 if (parcel.IsEitherBannedOrRestricted(targetAvatar.UUID) != true)
1686 {
1687 for (int x = 1; x <= Constants.RegionSize; x += 2)
1688 {
1689 for (int y = 1; y <= Constants.RegionSize; y += 2)
1690 {
1691 if (parcel.ContainsPoint(x, y))
1692 {
1693 position = new Vector3(x, y, targetAvatar.AbsolutePosition.Z);
1694 targetAvatar.TeleportWithMomentum(position);
1695 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1696 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected.");
1697 return;
1698 }
1699 }
1700 }
1701 }
1702 }
1703 }
1704 }
1705 Vector3 targetVector;
1706 if (targetAvatar.AbsolutePosition.X > targetAvatar.AbsolutePosition.Y)
1707 {
1708 if (targetAvatar.AbsolutePosition.X > .5 * Constants.RegionSize)
1709 {
1710 targetVector = new Vector3(Constants.RegionSize, targetAvatar.AbsolutePosition.Y, targetAvatar.AbsolutePosition.Z); ;
1711 targetAvatar.TeleportWithMomentum(targetVector);
1712 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1713 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected.");
1714 return;
1715 }
1716 else
1717 {
1718 targetVector = new Vector3(0, targetAvatar.AbsolutePosition.Y, targetAvatar.AbsolutePosition.Z); ;
1719 targetAvatar.TeleportWithMomentum(targetVector);
1720 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1721 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected.");
1722 return;
1723 }
1724 }
1725 else
1726 {
1727 if (targetAvatar.AbsolutePosition.Y > .5 * Constants.RegionSize)
1728 {
1729 targetVector = new Vector3(targetAvatar.AbsolutePosition.X, Constants.RegionSize, targetAvatar.AbsolutePosition.Z); ;
1730 targetAvatar.TeleportWithMomentum(targetVector);
1731 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1732 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected.");
1733 return;
1734 }
1735 else
1736 {
1737 targetVector = new Vector3(targetAvatar.AbsolutePosition.X, 0, targetAvatar.AbsolutePosition.Z); ;
1738 targetAvatar.TeleportWithMomentum(targetVector);
1739 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1740 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected.");
1741 return;
1742 }
1743 }
1744 }
1745 }
1746 //Eject and ban
1747 if (flags == 1)
1748 {
1749 if (targetAvatar.GodLevel == 0)
1750 {
1751 ILandObject land = ((Scene)client.Scene).LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y);
1752 if (!((Scene)client.Scene).Permissions.CanEditParcel(client.AgentId, land))
1753 return;
1754
1755 Vector3 position = new Vector3(0, 0, 0);
1756 List<ILandObject> allParcels = new List<ILandObject>();
1757 allParcels = AllParcels();
1758 if (allParcels.Count != 1)
1759 {
1760 foreach (ILandObject parcel in allParcels)
1761 {
1762 if (parcel.LandData.GlobalID != land.LandData.GlobalID)
1763 {
1764 if (parcel.IsEitherBannedOrRestricted(targetAvatar.UUID) != true)
1765 {
1766 for (int x = 1; x <= Constants.RegionSize; x += 2)
1767 {
1768 for (int y = 1; y <= Constants.RegionSize; y += 2)
1769 {
1770 if (parcel.ContainsPoint(x, y))
1771 {
1772 position = new Vector3(x, y, targetAvatar.AbsolutePosition.Z);
1773 targetAvatar.TeleportWithMomentum(position);
1774 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected and banned by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1775 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected and Banned.");
1776 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
1777 entry.AgentID = targetAvatar.UUID;
1778 entry.Flags = AccessList.Ban;
1779 entry.Time = new DateTime();
1780 land.LandData.ParcelAccessList.Add(entry);
1781 return;
1782 }
1783 }
1784 }
1785 }
1786 }
1787 }
1788 }
1789 Vector3 targetVector;
1790 if (targetAvatar.AbsolutePosition.X > targetAvatar.AbsolutePosition.Y)
1791 {
1792 if (targetAvatar.AbsolutePosition.X > .5 * Constants.RegionSize)
1793 {
1794 targetVector = new Vector3(Constants.RegionSize, targetAvatar.AbsolutePosition.Y, targetAvatar.AbsolutePosition.Z); ;
1795 targetAvatar.TeleportWithMomentum(targetVector);
1796 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected and banned by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1797 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected and Banned.");
1798 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
1799 entry.AgentID = targetAvatar.UUID;
1800 entry.Flags = AccessList.Ban;
1801 entry.Time = new DateTime();
1802 land.LandData.ParcelAccessList.Add(entry);
1803 return;
1804 }
1805 else
1806 {
1807 targetVector = new Vector3(0, targetAvatar.AbsolutePosition.Y, targetAvatar.AbsolutePosition.Z); ;
1808 targetAvatar.TeleportWithMomentum(targetVector);
1809 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected and banned by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1810 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected and Banned.");
1811 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
1812 entry.AgentID = targetAvatar.UUID;
1813 entry.Flags = AccessList.Ban;
1814 entry.Time = new DateTime();
1815 land.LandData.ParcelAccessList.Add(entry);
1816 return;
1817 }
1818 }
1819 else
1820 {
1821 if (targetAvatar.AbsolutePosition.Y > .5 * Constants.RegionSize)
1822 {
1823 targetVector = new Vector3(targetAvatar.AbsolutePosition.X, Constants.RegionSize, targetAvatar.AbsolutePosition.Z); ;
1824 targetAvatar.TeleportWithMomentum(targetVector);
1825 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected and banned by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1826 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected and Banned.");
1827 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
1828 entry.AgentID = targetAvatar.UUID;
1829 entry.Flags = AccessList.Ban;
1830 entry.Time = new DateTime();
1831 land.LandData.ParcelAccessList.Add(entry);
1832 return;
1833 }
1834 else
1835 {
1836 targetVector = new Vector3(targetAvatar.AbsolutePosition.X, 0, targetAvatar.AbsolutePosition.Z); ;
1837 targetAvatar.TeleportWithMomentum(targetVector);
1838 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected and banned by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1839 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected and Banned.");
1840 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
1841 entry.AgentID = targetAvatar.UUID;
1842 entry.Flags = AccessList.Ban;
1843 entry.Time = new DateTime();
1844 land.LandData.ParcelAccessList.Add(entry);
1845 return;
1846 }
1847 }
1848 }
1849 }
1850 }
1523 } 1851 }
1524} 1852}
diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
index aac47d1..b6b25ea 100644
--- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
+++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
@@ -817,12 +817,21 @@ namespace OpenSim.Region.Examples.SimpleModule
817 { 817 {
818 } 818 }
819 819
820 public void ProcessPendingPackets()
821 {
822 }
823
820 public void ProcessInPacket(Packet NewPack) 824 public void ProcessInPacket(Packet NewPack)
821 { 825 {
822 } 826 }
823 827
824 public void Close() 828 public void Close()
825 { 829 {
830 Close(true);
831 }
832
833 public void Close(bool sendStop)
834 {
826 } 835 }
827 836
828 public void Start() 837 public void Start()
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index f8af367..958847b 100644
--- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Xml;
29using OpenMetaverse; 30using OpenMetaverse;
30using OpenMetaverse.Packets; 31using OpenMetaverse.Packets;
31using OpenSim.Framework; 32using OpenSim.Framework;
@@ -82,6 +83,10 @@ namespace OpenSim.Region.Framework.Interfaces
82 UUID RezSingleAttachmentFromInventory( 83 UUID RezSingleAttachmentFromInventory(
83 IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus); 84 IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus);
84 85
86 // Same as above, but also load script states from a separate doc
87 UUID RezSingleAttachmentFromInventory(
88 IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus, XmlDocument doc);
89
85 /// <summary> 90 /// <summary>
86 /// Rez multiple attachments from a user's inventory 91 /// Rez multiple attachments from a user's inventory
87 /// </summary> 92 /// </summary>
@@ -132,4 +137,4 @@ namespace OpenSim.Region.Framework.Interfaces
132 /// </param> 137 /// </param>
133 void ShowDetachInUserInventory(UUID itemID, IClientAPI remoteClient); 138 void ShowDetachInUserInventory(UUID itemID, IClientAPI remoteClient);
134 } 139 }
135} \ No newline at end of file 140}
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
index fd43923..1e2f60b 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
@@ -105,6 +105,8 @@ namespace OpenSim.Region.Framework.Interfaces
105 /// <param name="stateSource"></param> 105 /// <param name="stateSource"></param>
106 void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource); 106 void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
107 107
108 ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
109
108 /// <summary> 110 /// <summary>
109 /// Stop a script which is in this prim's inventory. 111 /// Stop a script which is in this prim's inventory.
110 /// </summary> 112 /// </summary>
@@ -214,5 +216,6 @@ namespace OpenSim.Region.Framework.Interfaces
214 /// A <see cref="Dictionary`2"/> 216 /// A <see cref="Dictionary`2"/>
215 /// </returns> 217 /// </returns>
216 Dictionary<UUID, string> GetScriptStates(); 218 Dictionary<UUID, string> GetScriptStates();
219 Dictionary<UUID, string> GetScriptStates(bool oldIDs);
217 } 220 }
218} 221}
diff --git a/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs b/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
index 2d6287f..67a500f 100644
--- a/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
+++ b/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
@@ -68,6 +68,14 @@ namespace OpenSim.Region.Framework.Interfaces
68 bool SendReleaseAgent(ulong regionHandle, UUID id, string uri); 68 bool SendReleaseAgent(ulong regionHandle, UUID id, string uri);
69 69
70 /// <summary> 70 /// <summary>
71 /// Close chid agent.
72 /// </summary>
73 /// <param name="regionHandle"></param>
74 /// <param name="id"></param>
75 /// <returns></returns>
76 bool SendCloseChildAgent(ulong regionHandle, UUID id);
77
78 /// <summary>
71 /// Close agent. 79 /// Close agent.
72 /// </summary> 80 /// </summary>
73 /// <param name="regionHandle"></param> 81 /// <param name="regionHandle"></param>
diff --git a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs
new file mode 100644
index 0000000..e01f649
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs
@@ -0,0 +1,27 @@
1///////////////////////////////////////////////////////////////////
2//
3// (c) Careminster LImited, Melanie Thielker and the Meta7 Team
4//
5// This file is not open source. All rights reserved
6// Mod 2
7
8using OpenSim.Region.Framework.Scenes;
9
10public interface ISnmpModule
11{
12 void Trap(int code, string Message, Scene scene);
13 void Critical(string Message, Scene scene);
14 void Warning(string Message, Scene scene);
15 void Major(string Message, Scene scene);
16 void ColdStart(int step , Scene scene);
17 void Shutdown(int step , Scene scene);
18 //
19 // Node Start/stop events
20 //
21 void LinkUp(Scene scene);
22 void LinkDown(Scene scene);
23 void BootInfo(string data, Scene scene);
24 void trapDebug(string Module,string data, Scene scene);
25 void trapXMRE(int data, string Message, Scene scene);
26
27}
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
index de4c5fb..702a1e2 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
@@ -53,10 +53,11 @@ 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 public int m_animTickJump; // ScenePresence has to see this to control +Z force
60 61
61 /// <value> 62 /// <value>
62 /// The scene presence that this animator applies to 63 /// The scene presence that this animator applies to
@@ -123,8 +124,6 @@ namespace OpenSim.Region.Framework.Scenes.Animation
123 /// </summary> 124 /// </summary>
124 public void TrySetMovementAnimation(string anim) 125 public void TrySetMovementAnimation(string anim)
125 { 126 {
126 //m_log.DebugFormat("Updating movement animation to {0}", anim);
127
128 if (!m_scenePresence.IsChildAgent) 127 if (!m_scenePresence.IsChildAgent)
129 { 128 {
130 if (m_animations.TrySetDefaultAnimation( 129 if (m_animations.TrySetDefaultAnimation(
@@ -146,10 +145,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
146 const float PREJUMP_DELAY = 0.25f; 145 const float PREJUMP_DELAY = 0.25f;
147 146
148 #region Inputs 147 #region Inputs
149 if (m_scenePresence.SitGround) 148
150 {
151 return "SIT_GROUND_CONSTRAINED";
152 }
153 AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags; 149 AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags;
154 PhysicsActor actor = m_scenePresence.PhysicsActor; 150 PhysicsActor actor = m_scenePresence.PhysicsActor;
155 151
@@ -159,11 +155,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
159 Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix); 155 Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix);
160 156
161 // Check control flags 157 // Check control flags
162 bool heldForward = 158 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);
163 (((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)); 159 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);
164 bool heldBack = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG; 160 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);
165 bool heldLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS; 161 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);
166 bool heldRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG;
167 //bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT; 162 //bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT;
168 //bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT; 163 //bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT;
169 bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS; 164 bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS;
@@ -266,7 +261,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
266 m_animTickJump = Environment.TickCount; 261 m_animTickJump = Environment.TickCount;
267 return "PREJUMP"; 262 return "PREJUMP";
268 } 263 }
269 else if (Environment.TickCount - m_animTickJump > PREJUMP_DELAY * 1000.0f) 264 else if (Environment.TickCount - m_animTickJump > PREJUMP_DELAY * 800.0f)
270 { 265 {
271 // Start actual jump 266 // Start actual jump
272 if (m_animTickJump == -1) 267 if (m_animTickJump == -1)
@@ -316,7 +311,6 @@ namespace OpenSim.Region.Framework.Scenes.Animation
316 public void UpdateMovementAnimations() 311 public void UpdateMovementAnimations()
317 { 312 {
318 m_movementAnimation = GetMovementAnimation(); 313 m_movementAnimation = GetMovementAnimation();
319
320 if (m_movementAnimation == "PREJUMP" && !m_scenePresence.Scene.m_usePreJump) 314 if (m_movementAnimation == "PREJUMP" && !m_scenePresence.Scene.m_usePreJump)
321 { 315 {
322 // This was the previous behavior before PREJUMP 316 // This was the previous behavior before PREJUMP
diff --git a/OpenSim/Region/Framework/Scenes/EntityManager.cs b/OpenSim/Region/Framework/Scenes/EntityManager.cs
index 099fcce..c246e32 100644
--- a/OpenSim/Region/Framework/Scenes/EntityManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EntityManager.cs
@@ -40,7 +40,7 @@ namespace OpenSim.Region.Framework.Scenes
40 private readonly Dictionary<UUID,EntityBase> m_eb_uuid = new Dictionary<UUID, EntityBase>(); 40 private readonly Dictionary<UUID,EntityBase> m_eb_uuid = new Dictionary<UUID, EntityBase>();
41 private readonly Dictionary<uint, EntityBase> m_eb_localID = new Dictionary<uint, EntityBase>(); 41 private readonly Dictionary<uint, EntityBase> m_eb_localID = new Dictionary<uint, EntityBase>();
42 //private readonly Dictionary<UUID, ScenePresence> m_pres_uuid = new Dictionary<UUID, ScenePresence>(); 42 //private readonly Dictionary<UUID, ScenePresence> m_pres_uuid = new Dictionary<UUID, ScenePresence>();
43 private readonly Object m_lock = new Object(); 43 private System.Threading.ReaderWriterLockSlim m_lock = new System.Threading.ReaderWriterLockSlim();
44 44
45 [Obsolete("Use Add() instead.")] 45 [Obsolete("Use Add() instead.")]
46 public void Add(UUID id, EntityBase eb) 46 public void Add(UUID id, EntityBase eb)
@@ -50,7 +50,8 @@ namespace OpenSim.Region.Framework.Scenes
50 50
51 public void Add(EntityBase entity) 51 public void Add(EntityBase entity)
52 { 52 {
53 lock (m_lock) 53 m_lock.EnterWriteLock();
54 try
54 { 55 {
55 try 56 try
56 { 57 {
@@ -62,11 +63,16 @@ namespace OpenSim.Region.Framework.Scenes
62 m_log.ErrorFormat("Add Entity failed: {0}", e.Message); 63 m_log.ErrorFormat("Add Entity failed: {0}", e.Message);
63 } 64 }
64 } 65 }
66 finally
67 {
68 m_lock.ExitWriteLock();
69 }
65 } 70 }
66 71
67 public void InsertOrReplace(EntityBase entity) 72 public void InsertOrReplace(EntityBase entity)
68 { 73 {
69 lock (m_lock) 74 m_lock.EnterWriteLock();
75 try
70 { 76 {
71 try 77 try
72 { 78 {
@@ -78,15 +84,24 @@ namespace OpenSim.Region.Framework.Scenes
78 m_log.ErrorFormat("Insert or Replace Entity failed: {0}", e.Message); 84 m_log.ErrorFormat("Insert or Replace Entity failed: {0}", e.Message);
79 } 85 }
80 } 86 }
87 finally
88 {
89 m_lock.ExitWriteLock();
90 }
81 } 91 }
82 92
83 public void Clear() 93 public void Clear()
84 { 94 {
85 lock (m_lock) 95 m_lock.EnterWriteLock();
96 try
86 { 97 {
87 m_eb_uuid.Clear(); 98 m_eb_uuid.Clear();
88 m_eb_localID.Clear(); 99 m_eb_localID.Clear();
89 } 100 }
101 finally
102 {
103 m_lock.ExitWriteLock();
104 }
90 } 105 }
91 106
92 public int Count 107 public int Count
@@ -123,7 +138,8 @@ namespace OpenSim.Region.Framework.Scenes
123 138
124 public bool Remove(uint localID) 139 public bool Remove(uint localID)
125 { 140 {
126 lock (m_lock) 141 m_lock.EnterWriteLock();
142 try
127 { 143 {
128 try 144 try
129 { 145 {
@@ -141,11 +157,16 @@ namespace OpenSim.Region.Framework.Scenes
141 return false; 157 return false;
142 } 158 }
143 } 159 }
160 finally
161 {
162 m_lock.ExitWriteLock();
163 }
144 } 164 }
145 165
146 public bool Remove(UUID id) 166 public bool Remove(UUID id)
147 { 167 {
148 lock (m_lock) 168 m_lock.EnterWriteLock();
169 try
149 { 170 {
150 try 171 try
151 { 172 {
@@ -163,13 +184,18 @@ namespace OpenSim.Region.Framework.Scenes
163 return false; 184 return false;
164 } 185 }
165 } 186 }
187 finally
188 {
189 m_lock.ExitWriteLock();
190 }
166 } 191 }
167 192
168 public List<EntityBase> GetAllByType<T>() 193 public List<EntityBase> GetAllByType<T>()
169 { 194 {
170 List<EntityBase> tmp = new List<EntityBase>(); 195 List<EntityBase> tmp = new List<EntityBase>();
171 196
172 lock (m_lock) 197 m_lock.EnterReadLock();
198 try
173 { 199 {
174 try 200 try
175 { 201 {
@@ -187,23 +213,33 @@ namespace OpenSim.Region.Framework.Scenes
187 tmp = null; 213 tmp = null;
188 } 214 }
189 } 215 }
216 finally
217 {
218 m_lock.ExitReadLock();
219 }
190 220
191 return tmp; 221 return tmp;
192 } 222 }
193 223
194 public List<EntityBase> GetEntities() 224 public List<EntityBase> GetEntities()
195 { 225 {
196 lock (m_lock) 226 m_lock.EnterReadLock();
227 try
197 { 228 {
198 return new List<EntityBase>(m_eb_uuid.Values); 229 return new List<EntityBase>(m_eb_uuid.Values);
199 } 230 }
231 finally
232 {
233 m_lock.ExitReadLock();
234 }
200 } 235 }
201 236
202 public EntityBase this[UUID id] 237 public EntityBase this[UUID id]
203 { 238 {
204 get 239 get
205 { 240 {
206 lock (m_lock) 241 m_lock.EnterReadLock();
242 try
207 { 243 {
208 EntityBase entity; 244 EntityBase entity;
209 if (m_eb_uuid.TryGetValue(id, out entity)) 245 if (m_eb_uuid.TryGetValue(id, out entity))
@@ -211,6 +247,10 @@ namespace OpenSim.Region.Framework.Scenes
211 else 247 else
212 return null; 248 return null;
213 } 249 }
250 finally
251 {
252 m_lock.ExitReadLock();
253 }
214 } 254 }
215 set 255 set
216 { 256 {
@@ -222,7 +262,8 @@ namespace OpenSim.Region.Framework.Scenes
222 { 262 {
223 get 263 get
224 { 264 {
225 lock (m_lock) 265 m_lock.EnterReadLock();
266 try
226 { 267 {
227 EntityBase entity; 268 EntityBase entity;
228 if (m_eb_localID.TryGetValue(localID, out entity)) 269 if (m_eb_localID.TryGetValue(localID, out entity))
@@ -230,6 +271,10 @@ namespace OpenSim.Region.Framework.Scenes
230 else 271 else
231 return null; 272 return null;
232 } 273 }
274 finally
275 {
276 m_lock.ExitReadLock();
277 }
233 } 278 }
234 set 279 set
235 { 280 {
@@ -239,18 +284,28 @@ namespace OpenSim.Region.Framework.Scenes
239 284
240 public bool TryGetValue(UUID key, out EntityBase obj) 285 public bool TryGetValue(UUID key, out EntityBase obj)
241 { 286 {
242 lock (m_lock) 287 m_lock.EnterReadLock();
288 try
243 { 289 {
244 return m_eb_uuid.TryGetValue(key, out obj); 290 return m_eb_uuid.TryGetValue(key, out obj);
245 } 291 }
292 finally
293 {
294 m_lock.ExitReadLock();
295 }
246 } 296 }
247 297
248 public bool TryGetValue(uint key, out EntityBase obj) 298 public bool TryGetValue(uint key, out EntityBase obj)
249 { 299 {
250 lock (m_lock) 300 m_lock.EnterReadLock();
301 try
251 { 302 {
252 return m_eb_localID.TryGetValue(key, out obj); 303 return m_eb_localID.TryGetValue(key, out obj);
253 } 304 }
305 finally
306 {
307 m_lock.ExitReadLock();
308 }
254 } 309 }
255 310
256 /// <summary> 311 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 60f730d..cbe3456 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -94,6 +94,22 @@ namespace OpenSim.Region.Framework.Scenes
94 94
95 public void AddInventoryItem(UUID AgentID, InventoryItemBase item) 95 public void AddInventoryItem(UUID AgentID, InventoryItemBase item)
96 { 96 {
97 InventoryFolderBase folder;
98
99 if (item.Folder == UUID.Zero)
100 {
101 folder = InventoryService.GetFolderForType(AgentID, (AssetType)item.AssetType);
102 if (folder == null)
103 {
104 folder = InventoryService.GetRootFolder(AgentID);
105
106 if (folder == null)
107 return;
108 }
109
110 item.Folder = folder.ID;
111 }
112
97 if (InventoryService.AddItem(item)) 113 if (InventoryService.AddItem(item))
98 { 114 {
99 int userlevel = 0; 115 int userlevel = 0;
@@ -214,8 +230,7 @@ namespace OpenSim.Region.Framework.Scenes
214 { 230 {
215 // Needs to determine which engine was running it and use that 231 // Needs to determine which engine was running it and use that
216 // 232 //
217 part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0); 233 errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 0);
218 errors = part.Inventory.GetScriptErrors(item.ItemID);
219 } 234 }
220 else 235 else
221 { 236 {
@@ -382,29 +397,31 @@ namespace OpenSim.Region.Framework.Scenes
382 itemCopy.InvType = item.InvType; 397 itemCopy.InvType = item.InvType;
383 itemCopy.Folder = recipientFolderId; 398 itemCopy.Folder = recipientFolderId;
384 399
385 if (Permissions.PropagatePermissions()) 400 if (Permissions.PropagatePermissions() && recipient != senderId)
386 { 401 {
402 // First, make sore base is limited to the next perms
403 itemCopy.BasePermissions = item.BasePermissions & item.NextPermissions;
404 // By default, current equals base
405 itemCopy.CurrentPermissions = itemCopy.BasePermissions;
406
407 // If this is an object, replace current perms
408 // with folded perms
387 if (item.InvType == (int)InventoryType.Object) 409 if (item.InvType == (int)InventoryType.Object)
388 { 410 {
389 itemCopy.BasePermissions &= ~(uint)(PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer); 411 itemCopy.CurrentPermissions &= ~(uint)(PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer);
390 itemCopy.BasePermissions |= (item.CurrentPermissions & 7) << 13; 412 itemCopy.CurrentPermissions |= (item.CurrentPermissions & 7) << 13;
391 }
392 else
393 {
394 itemCopy.BasePermissions = item.BasePermissions & item.NextPermissions;
395 } 413 }
396 414
397 itemCopy.CurrentPermissions = itemCopy.BasePermissions; 415 // Ensure there is no escalation
398 if ((item.CurrentPermissions & 8) != 0) // Propagate slam bit 416 itemCopy.CurrentPermissions &= item.NextPermissions;
399 { 417
400 itemCopy.BasePermissions &= item.NextPermissions; 418 // Need slam bit on xfer
401 itemCopy.CurrentPermissions = itemCopy.BasePermissions; 419 itemCopy.CurrentPermissions |= 8;
402 itemCopy.CurrentPermissions |= 8;
403 }
404 420
405 itemCopy.NextPermissions = item.NextPermissions; 421 itemCopy.NextPermissions = item.NextPermissions;
406 itemCopy.EveryOnePermissions = item.EveryOnePermissions & item.NextPermissions; 422
407 itemCopy.GroupPermissions = item.GroupPermissions & item.NextPermissions; 423 itemCopy.EveryOnePermissions = 0;
424 itemCopy.GroupPermissions = 0;
408 } 425 }
409 else 426 else
410 { 427 {
@@ -834,8 +851,12 @@ namespace OpenSim.Region.Framework.Scenes
834 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID) 851 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID)
835 { 852 {
836 SceneObjectPart part = GetSceneObjectPart(localID); 853 SceneObjectPart part = GetSceneObjectPart(localID);
837 SceneObjectGroup group = part.ParentGroup; 854 SceneObjectGroup group = null;
838 if (group != null) 855 if (part != null)
856 {
857 group = part.ParentGroup;
858 }
859 if (part != null && group != null)
839 { 860 {
840 TaskInventoryItem item = group.GetInventoryItem(localID, itemID); 861 TaskInventoryItem item = group.GetInventoryItem(localID, itemID);
841 if (item == null) 862 if (item == null)
@@ -895,12 +916,12 @@ namespace OpenSim.Region.Framework.Scenes
895 916
896 if ((part.OwnerID != destAgent) && Permissions.PropagatePermissions()) 917 if ((part.OwnerID != destAgent) && Permissions.PropagatePermissions())
897 { 918 {
919 agentItem.BasePermissions = taskItem.BasePermissions & taskItem.NextPermissions;
898 if (taskItem.InvType == (int)InventoryType.Object) 920 if (taskItem.InvType == (int)InventoryType.Object)
899 agentItem.BasePermissions = taskItem.BasePermissions & ((taskItem.CurrentPermissions & 7) << 13); 921 agentItem.CurrentPermissions = agentItem.BasePermissions & ((taskItem.CurrentPermissions & 7) << 13);
900 else 922 agentItem.CurrentPermissions = agentItem.BasePermissions ;
901 agentItem.BasePermissions = taskItem.BasePermissions; 923
902 agentItem.BasePermissions &= taskItem.NextPermissions; 924 agentItem.CurrentPermissions |= 8;
903 agentItem.CurrentPermissions = agentItem.BasePermissions | 8;
904 agentItem.NextPermissions = taskItem.NextPermissions; 925 agentItem.NextPermissions = taskItem.NextPermissions;
905 agentItem.EveryOnePermissions = taskItem.EveryonePermissions & taskItem.NextPermissions; 926 agentItem.EveryOnePermissions = taskItem.EveryonePermissions & taskItem.NextPermissions;
906 agentItem.GroupPermissions = taskItem.GroupPermissions & taskItem.NextPermissions; 927 agentItem.GroupPermissions = taskItem.GroupPermissions & taskItem.NextPermissions;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index de8ecc2..377abe3 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -156,6 +156,20 @@ namespace OpenSim.Region.Framework.Scenes
156 156
157 public IXfer XferManager; 157 public IXfer XferManager;
158 158
159 protected ISnmpModule m_snmpService = null;
160 public ISnmpModule SnmpService
161 {
162 get
163 {
164 if (m_snmpService == null)
165 {
166 m_snmpService = RequestModuleInterface<ISnmpModule>();
167 }
168
169 return m_snmpService;
170 }
171 }
172
159 protected IAssetService m_AssetService; 173 protected IAssetService m_AssetService;
160 protected IAuthorizationService m_AuthorizationService; 174 protected IAuthorizationService m_AuthorizationService;
161 175
@@ -613,6 +627,8 @@ namespace OpenSim.Region.Framework.Scenes
613 627
614 // Load region settings 628 // Load region settings
615 m_regInfo.RegionSettings = m_storageManager.DataStore.LoadRegionSettings(m_regInfo.RegionID); 629 m_regInfo.RegionSettings = m_storageManager.DataStore.LoadRegionSettings(m_regInfo.RegionID);
630 m_regInfo.WindlightSettings = m_storageManager.DataStore.LoadRegionWindlightSettings(m_regInfo.RegionID);
631
616 if (m_storageManager.EstateDataStore != null) 632 if (m_storageManager.EstateDataStore != null)
617 { 633 {
618 m_regInfo.EstateSettings = m_storageManager.EstateDataStore.LoadEstateSettings(m_regInfo.RegionID, false); 634 m_regInfo.EstateSettings = m_storageManager.EstateDataStore.LoadEstateSettings(m_regInfo.RegionID, false);
@@ -711,7 +727,7 @@ namespace OpenSim.Region.Framework.Scenes
711 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); 727 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
712 // TODO: Change default to true once the feature is supported 728 // TODO: Change default to true once the feature is supported
713 m_usePreJump = startupConfig.GetBoolean("enableprejump", false); 729 m_usePreJump = startupConfig.GetBoolean("enableprejump", false);
714 730 m_usePreJump = true; // Above line fails!?
715 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); 731 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys);
716 if (RegionInfo.NonphysPrimMax > 0) 732 if (RegionInfo.NonphysPrimMax > 0)
717 { 733 {
@@ -1031,6 +1047,15 @@ namespace OpenSim.Region.Framework.Scenes
1031 /// <param name="seconds">float indicating duration before restart.</param> 1047 /// <param name="seconds">float indicating duration before restart.</param>
1032 public virtual void Restart(float seconds) 1048 public virtual void Restart(float seconds)
1033 { 1049 {
1050 Restart(seconds, true);
1051 }
1052
1053 /// <summary>
1054 /// Given float seconds, this will restart the region. showDialog will optionally alert the users.
1055 /// </summary>
1056 /// <param name="seconds">float indicating duration before restart.</param>
1057 public virtual void Restart(float seconds, bool showDialog)
1058 {
1034 // notifications are done in 15 second increments 1059 // notifications are done in 15 second increments
1035 // so .. if the number of seconds is less then 15 seconds, it's not really a restart request 1060 // so .. if the number of seconds is less then 15 seconds, it's not really a restart request
1036 // It's a 'Cancel restart' request. 1061 // It's a 'Cancel restart' request.
@@ -1051,8 +1076,11 @@ namespace OpenSim.Region.Framework.Scenes
1051 m_restartTimer.Elapsed += new ElapsedEventHandler(RestartTimer_Elapsed); 1076 m_restartTimer.Elapsed += new ElapsedEventHandler(RestartTimer_Elapsed);
1052 m_log.Info("[REGION]: Restarting Region in " + (seconds / 60) + " minutes"); 1077 m_log.Info("[REGION]: Restarting Region in " + (seconds / 60) + " minutes");
1053 m_restartTimer.Start(); 1078 m_restartTimer.Start();
1054 m_dialogModule.SendNotificationToUsersInRegion( 1079 if (showDialog)
1080 {
1081 m_dialogModule.SendNotificationToUsersInRegion(
1055 UUID.Random(), String.Empty, RegionInfo.RegionName + String.Format(": Restarting in {0} Minutes", (int)(seconds / 60.0))); 1082 UUID.Random(), String.Empty, RegionInfo.RegionName + String.Format(": Restarting in {0} Minutes", (int)(seconds / 60.0)));
1083 }
1056 } 1084 }
1057 } 1085 }
1058 1086
@@ -1408,16 +1436,16 @@ namespace OpenSim.Region.Framework.Scenes
1408 // Check if any objects have reached their targets 1436 // Check if any objects have reached their targets
1409 CheckAtTargets(); 1437 CheckAtTargets();
1410 1438
1411 // Update SceneObjectGroups that have scheduled themselves for updates
1412 // Objects queue their updates onto all scene presences
1413 if (m_frame % m_update_objects == 0)
1414 m_sceneGraph.UpdateObjectGroups();
1415
1416 // Run through all ScenePresences looking for updates 1439 // Run through all ScenePresences looking for updates
1417 // Presence updates and queued object updates for each presence are sent to clients 1440 // Presence updates and queued object updates for each presence are sent to clients
1418 if (m_frame % m_update_presences == 0) 1441 if (m_frame % m_update_presences == 0)
1419 m_sceneGraph.UpdatePresences(); 1442 m_sceneGraph.UpdatePresences();
1420 1443
1444 // Update SceneObjectGroups that have scheduled themselves for updates
1445 // Objects queue their updates onto all scene presences
1446 if (m_frame % m_update_objects == 0)
1447 m_sceneGraph.UpdateObjectGroups();
1448
1421 int tmpPhysicsMS2 = Util.EnvironmentTickCount(); 1449 int tmpPhysicsMS2 = Util.EnvironmentTickCount();
1422 if ((m_frame % m_update_physics == 0) && m_physics_enabled) 1450 if ((m_frame % m_update_physics == 0) && m_physics_enabled)
1423 m_sceneGraph.UpdatePreparePhysics(); 1451 m_sceneGraph.UpdatePreparePhysics();
@@ -2119,7 +2147,7 @@ namespace OpenSim.Region.Framework.Scenes
2119 public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 2147 public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
2120 { 2148 {
2121 return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates); 2149 return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates);
2122 } 2150 }
2123 2151
2124 /// <summary> 2152 /// <summary>
2125 /// Delete every object from the scene 2153 /// Delete every object from the scene
@@ -3461,12 +3489,15 @@ namespace OpenSim.Region.Framework.Scenes
3461 { 3489 {
3462 // We have a zombie from a crashed session. Kill it. 3490 // We have a zombie from a crashed session. Kill it.
3463 m_log.DebugFormat("[SCENE]: Zombie scene presence detected for {0} in {1}", agent.AgentID, RegionInfo.RegionName); 3491 m_log.DebugFormat("[SCENE]: Zombie scene presence detected for {0} in {1}", agent.AgentID, RegionInfo.RegionName);
3464 sp.ControllingClient.Close(); 3492 sp.ControllingClient.Close(false);
3465 } 3493 }
3466 } 3494 }
3467 3495
3468 CapsModule.AddCapsHandler(agent.AgentID); 3496 CapsModule.AddCapsHandler(agent.AgentID);
3469 3497
3498 if ((teleportFlags & ((uint)TeleportFlags.ViaLandmark | (uint)TeleportFlags.ViaLocation | (uint)TeleportFlags.ViaLandmark | (uint)TeleportFlags.Default)) != 0)
3499 System.Threading.Thread.Sleep(2000);
3500
3470 if (!agent.child) 3501 if (!agent.child)
3471 { 3502 {
3472 if (TestBorderCross(agent.startpos,Cardinals.E)) 3503 if (TestBorderCross(agent.startpos,Cardinals.E))
@@ -3525,6 +3556,8 @@ namespace OpenSim.Region.Framework.Scenes
3525 } 3556 }
3526 } 3557 }
3527 // Honor parcel landing type and position. 3558 // Honor parcel landing type and position.
3559 /*
3560 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3528 if (land != null) 3561 if (land != null)
3529 { 3562 {
3530 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3563 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3532,6 +3565,7 @@ namespace OpenSim.Region.Framework.Scenes
3532 agent.startpos = land.LandData.UserLocation; 3565 agent.startpos = land.LandData.UserLocation;
3533 } 3566 }
3534 } 3567 }
3568 */// This is now handled properly in ScenePresence.MakeRootAgent
3535 } 3569 }
3536 3570
3537 agent.teleportFlags = teleportFlags; 3571 agent.teleportFlags = teleportFlags;
@@ -3880,12 +3914,22 @@ namespace OpenSim.Region.Framework.Scenes
3880 return false; 3914 return false;
3881 } 3915 }
3882 3916
3917 public bool IncomingCloseAgent(UUID agentID)
3918 {
3919 return IncomingCloseAgent(agentID, false);
3920 }
3921
3922 public bool IncomingCloseChildAgent(UUID agentID)
3923 {
3924 return IncomingCloseAgent(agentID, true);
3925 }
3926
3883 /// <summary> 3927 /// <summary>
3884 /// Tell a single agent to disconnect from the region. 3928 /// Tell a single agent to disconnect from the region.
3885 /// </summary> 3929 /// </summary>
3886 /// <param name="regionHandle"></param>
3887 /// <param name="agentID"></param> 3930 /// <param name="agentID"></param>
3888 public bool IncomingCloseAgent(UUID agentID) 3931 /// <param name="childOnly"></param>
3932 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
3889 { 3933 {
3890 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 3934 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
3891 3935
@@ -3897,7 +3941,7 @@ namespace OpenSim.Region.Framework.Scenes
3897 { 3941 {
3898 m_sceneGraph.removeUserCount(false); 3942 m_sceneGraph.removeUserCount(false);
3899 } 3943 }
3900 else 3944 else if (!childOnly)
3901 { 3945 {
3902 m_sceneGraph.removeUserCount(true); 3946 m_sceneGraph.removeUserCount(true);
3903 } 3947 }
@@ -3913,9 +3957,12 @@ namespace OpenSim.Region.Framework.Scenes
3913 } 3957 }
3914 else 3958 else
3915 presence.ControllingClient.SendShutdownConnectionNotice(); 3959 presence.ControllingClient.SendShutdownConnectionNotice();
3960 presence.ControllingClient.Close(false);
3961 }
3962 else if (!childOnly)
3963 {
3964 presence.ControllingClient.Close(true);
3916 } 3965 }
3917
3918 presence.ControllingClient.Close();
3919 return true; 3966 return true;
3920 } 3967 }
3921 3968
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index bd8ccce..6309cd9 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -281,7 +281,7 @@ namespace OpenSim.Region.Framework.Scenes
281 uint x = 0, y = 0; 281 uint x = 0, y = 0;
282 Utils.LongToUInts(regionHandle, out x, out y); 282 Utils.LongToUInts(regionHandle, out x, out y);
283 GridRegion destination = m_scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y); 283 GridRegion destination = m_scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y);
284 m_scene.SimulationService.CloseAgent(destination, agentID); 284 m_scene.SimulationService.CloseChildAgent(destination, agentID);
285 } 285 }
286 286
287 private void SendCloseChildAgentCompleted(IAsyncResult iar) 287 private void SendCloseChildAgentCompleted(IAsyncResult iar)
@@ -300,7 +300,7 @@ namespace OpenSim.Region.Framework.Scenes
300 d); 300 d);
301 } 301 }
302 } 302 }
303 303
304 public List<GridRegion> RequestNamedRegions(string name, int maxNumber) 304 public List<GridRegion> RequestNamedRegions(string name, int maxNumber)
305 { 305 {
306 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber); 306 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber);
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index ef13c98..3c2203c 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -68,7 +68,7 @@ namespace OpenSim.Region.Framework.Scenes
68 68
69 #region Fields 69 #region Fields
70 70
71 protected object m_presenceLock = new object(); 71 protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim();
72 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>(); 72 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>();
73 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>(); 73 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>();
74 74
@@ -133,13 +133,18 @@ namespace OpenSim.Region.Framework.Scenes
133 133
134 protected internal void Close() 134 protected internal void Close()
135 { 135 {
136 lock (m_presenceLock) 136 m_scenePresencesLock.EnterWriteLock();
137 try
137 { 138 {
138 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 139 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
139 List<ScenePresence> newlist = new List<ScenePresence>(); 140 List<ScenePresence> newlist = new List<ScenePresence>();
140 m_scenePresenceMap = newmap; 141 m_scenePresenceMap = newmap;
141 m_scenePresenceArray = newlist; 142 m_scenePresenceArray = newlist;
142 } 143 }
144 finally
145 {
146 m_scenePresencesLock.ExitWriteLock();
147 }
143 148
144 lock (m_dictionary_lock) 149 lock (m_dictionary_lock)
145 { 150 {
@@ -228,6 +233,30 @@ namespace OpenSim.Region.Framework.Scenes
228 protected internal bool AddRestoredSceneObject( 233 protected internal bool AddRestoredSceneObject(
229 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted) 234 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted)
230 { 235 {
236 // KF: Check for out-of-region, move inside and make static.
237 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
238 sceneObject.RootPart.GroupPosition.Y,
239 sceneObject.RootPart.GroupPosition.Z);
240 if (!(((sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) && (sceneObject.RootPart.Shape.State != 0))) && (npos.X < 0.0 || npos.Y < 0.0 || npos.Z < 0.0 ||
241 npos.X > Constants.RegionSize ||
242 npos.Y > Constants.RegionSize))
243 {
244 if (npos.X < 0.0) npos.X = 1.0f;
245 if (npos.Y < 0.0) npos.Y = 1.0f;
246 if (npos.Z < 0.0) npos.Z = 0.0f;
247 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
248 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
249
250 foreach (SceneObjectPart part in sceneObject.Children.Values)
251 {
252 part.GroupPosition = npos;
253 }
254 sceneObject.RootPart.Velocity = Vector3.Zero;
255 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
256 sceneObject.RootPart.Acceleration = Vector3.Zero;
257 sceneObject.RootPart.Velocity = Vector3.Zero;
258 }
259
231 if (!alreadyPersisted) 260 if (!alreadyPersisted)
232 { 261 {
233 sceneObject.ForceInventoryPersistence(); 262 sceneObject.ForceInventoryPersistence();
@@ -521,7 +550,8 @@ namespace OpenSim.Region.Framework.Scenes
521 550
522 Entities[presence.UUID] = presence; 551 Entities[presence.UUID] = presence;
523 552
524 lock (m_presenceLock) 553 m_scenePresencesLock.EnterWriteLock();
554 try
525 { 555 {
526 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 556 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
527 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 557 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -545,6 +575,10 @@ namespace OpenSim.Region.Framework.Scenes
545 m_scenePresenceMap = newmap; 575 m_scenePresenceMap = newmap;
546 m_scenePresenceArray = newlist; 576 m_scenePresenceArray = newlist;
547 } 577 }
578 finally
579 {
580 m_scenePresencesLock.ExitWriteLock();
581 }
548 } 582 }
549 583
550 /// <summary> 584 /// <summary>
@@ -559,7 +593,8 @@ namespace OpenSim.Region.Framework.Scenes
559 agentID); 593 agentID);
560 } 594 }
561 595
562 lock (m_presenceLock) 596 m_scenePresencesLock.EnterWriteLock();
597 try
563 { 598 {
564 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 599 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
565 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 600 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -580,6 +615,10 @@ namespace OpenSim.Region.Framework.Scenes
580 m_log.WarnFormat("[SCENE] Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 615 m_log.WarnFormat("[SCENE] Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
581 } 616 }
582 } 617 }
618 finally
619 {
620 m_scenePresencesLock.ExitWriteLock();
621 }
583 } 622 }
584 623
585 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 624 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index f7e46af..1149a20 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -46,12 +46,12 @@ namespace OpenSim.Region.Framework.Scenes
46 /// </summary> 46 /// </summary>
47 public void ForceInventoryPersistence() 47 public void ForceInventoryPersistence()
48 { 48 {
49 lock (m_parts) 49 lockPartsForRead(true);
50 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
51 lockPartsForRead(false);
52 foreach (SceneObjectPart part in values)
50 { 53 {
51 foreach (SceneObjectPart part in m_parts.Values) 54 part.Inventory.ForceInventoryPersistence();
52 {
53 part.Inventory.ForceInventoryPersistence();
54 }
55 } 55 }
56 } 56 }
57 57
@@ -74,19 +74,17 @@ namespace OpenSim.Region.Framework.Scenes
74 /// <summary> 74 /// <summary>
75 /// Stop the scripts contained in all the prims in this group 75 /// Stop the scripts contained in all the prims in this group
76 /// </summary> 76 /// </summary>
77 /// <param name="sceneObjectBeingDeleted">
78 /// Should be true if these scripts are being removed because the scene
79 /// object is being deleted. This will prevent spurious updates to the client.
80 /// </param>
81 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 77 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
82 { 78 {
83 lock (m_parts) 79 lockPartsForRead(true);
80 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
81 lockPartsForRead(false);
82
83 foreach (SceneObjectPart part in values)
84 { 84 {
85 foreach (SceneObjectPart part in m_parts.Values) 85 part.Inventory.RemoveScriptInstances(sceneObjectBeingDeleted);
86 {
87 part.Inventory.RemoveScriptInstances(sceneObjectBeingDeleted);
88 }
89 } 86 }
87
90 } 88 }
91 89
92 /// <summary> 90 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 8aefd50..a4b8944 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -104,8 +104,78 @@ namespace OpenSim.Region.Framework.Scenes
104 /// since the group's last persistent backup 104 /// since the group's last persistent backup
105 /// </summary> 105 /// </summary>
106 private bool m_hasGroupChanged = false; 106 private bool m_hasGroupChanged = false;
107 private long timeFirstChanged; 107 private long timeFirstChanged = 0;
108 private long timeLastChanged; 108 private long timeLastChanged = 0;
109 private long m_maxPersistTime = 0;
110 private long m_minPersistTime = 0;
111 private Random m_rand;
112
113 private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim();
114
115 public void lockPartsForRead(bool locked)
116 {
117 if (locked)
118 {
119 if (m_partsLock.RecursiveReadCount > 0)
120 {
121 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.");
122 m_partsLock.ExitReadLock();
123 }
124 if (m_partsLock.RecursiveWriteCount > 0)
125 {
126 m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested (write lock exists on this thread). This should not happen and means something needs to be fixed.");
127 m_partsLock.ExitWriteLock();
128 }
129
130 while (!m_partsLock.TryEnterReadLock(60000))
131 {
132 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.");
133 if (m_partsLock.IsWriteLockHeld)
134 {
135 m_partsLock = new System.Threading.ReaderWriterLockSlim();
136 }
137 }
138 }
139 else
140 {
141 if (m_partsLock.RecursiveReadCount > 0)
142 {
143 m_partsLock.ExitReadLock();
144 }
145 }
146 }
147 public void lockPartsForWrite(bool locked)
148 {
149 if (locked)
150 {
151 if (m_partsLock.RecursiveReadCount > 0)
152 {
153 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.");
154 m_partsLock.ExitReadLock();
155 }
156 if (m_partsLock.RecursiveWriteCount > 0)
157 {
158 m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
159 m_partsLock.ExitWriteLock();
160 }
161
162 while (!m_partsLock.TryEnterWriteLock(60000))
163 {
164 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.");
165 if (m_partsLock.IsWriteLockHeld)
166 {
167 m_partsLock = new System.Threading.ReaderWriterLockSlim();
168 }
169 }
170 }
171 else
172 {
173 if (m_partsLock.RecursiveWriteCount > 0)
174 {
175 m_partsLock.ExitWriteLock();
176 }
177 }
178 }
109 179
110 public bool HasGroupChanged 180 public bool HasGroupChanged
111 { 181 {
@@ -116,6 +186,32 @@ namespace OpenSim.Region.Framework.Scenes
116 timeLastChanged = DateTime.Now.Ticks; 186 timeLastChanged = DateTime.Now.Ticks;
117 if (!m_hasGroupChanged) 187 if (!m_hasGroupChanged)
118 timeFirstChanged = DateTime.Now.Ticks; 188 timeFirstChanged = DateTime.Now.Ticks;
189 if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null)
190 {
191 if (m_rand == null)
192 {
193 byte[] val = new byte[16];
194 m_rootPart.UUID.ToBytes(val, 0);
195 m_rand = new Random(BitConverter.ToInt32(val, 0));
196 }
197
198 if (m_scene.GetRootAgentCount() == 0)
199 {
200 //If the region is empty, this change has been made by an automated process
201 //and thus we delay the persist time by a random amount between 1.5 and 2.5.
202
203 float factor = 1.5f + (float)(m_rand.NextDouble());
204 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor);
205 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor);
206 }
207 else
208 {
209 //If the region is not empty, we want to obey the minimum and maximum persist times
210 //but add a random factor so we stagger the object persistance a little
211 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5
212 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0
213 }
214 }
119 } 215 }
120 m_hasGroupChanged = value; 216 m_hasGroupChanged = value;
121 } 217 }
@@ -131,8 +227,19 @@ namespace OpenSim.Region.Framework.Scenes
131 return false; 227 return false;
132 if (m_scene.ShuttingDown) 228 if (m_scene.ShuttingDown)
133 return true; 229 return true;
230
231 if (m_minPersistTime == 0 || m_maxPersistTime == 0)
232 {
233 m_maxPersistTime = m_scene.m_persistAfter;
234 m_minPersistTime = m_scene.m_dontPersistBefore;
235 }
236
134 long currentTime = DateTime.Now.Ticks; 237 long currentTime = DateTime.Now.Ticks;
135 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) 238
239 if (timeLastChanged == 0) timeLastChanged = currentTime;
240 if (timeFirstChanged == 0) timeFirstChanged = currentTime;
241
242 if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime)
136 return true; 243 return true;
137 return false; 244 return false;
138 } 245 }
@@ -258,13 +365,16 @@ namespace OpenSim.Region.Framework.Scenes
258 set 365 set
259 { 366 {
260 m_regionHandle = value; 367 m_regionHandle = value;
261 lock (m_parts) 368 lockPartsForRead(true);
262 { 369 {
263 foreach (SceneObjectPart part in m_parts.Values) 370 foreach (SceneObjectPart part in m_parts.Values)
264 { 371 {
372
265 part.RegionHandle = m_regionHandle; 373 part.RegionHandle = m_regionHandle;
374
266 } 375 }
267 } 376 }
377 lockPartsForRead(false);
268 } 378 }
269 } 379 }
270 380
@@ -298,6 +408,9 @@ namespace OpenSim.Region.Framework.Scenes
298 { 408 {
299 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 409 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
300 } 410 }
411
412 lockPartsForRead(true);
413
301 if (RootPart.GetStatusSandbox()) 414 if (RootPart.GetStatusSandbox())
302 { 415 {
303 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 416 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -305,17 +418,18 @@ namespace OpenSim.Region.Framework.Scenes
305 RootPart.ScriptSetPhysicsStatus(false); 418 RootPart.ScriptSetPhysicsStatus(false);
306 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), 419 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
307 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); 420 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
421 lockPartsForRead(false);
308 return; 422 return;
309 } 423 }
310 } 424 }
311 lock (m_parts) 425
426 foreach (SceneObjectPart part in m_parts.Values)
312 { 427 {
313 foreach (SceneObjectPart part in m_parts.Values) 428 part.GroupPosition = val;
314 {
315 part.GroupPosition = val;
316 }
317 } 429 }
318 430
431 lockPartsForRead(false);
432
319 //if (m_rootPart.PhysActor != null) 433 //if (m_rootPart.PhysActor != null)
320 //{ 434 //{
321 //m_rootPart.PhysActor.Position = 435 //m_rootPart.PhysActor.Position =
@@ -457,6 +571,7 @@ namespace OpenSim.Region.Framework.Scenes
457 /// </summary> 571 /// </summary>
458 public SceneObjectGroup() 572 public SceneObjectGroup()
459 { 573 {
574
460 } 575 }
461 576
462 /// <summary> 577 /// <summary>
@@ -473,7 +588,7 @@ namespace OpenSim.Region.Framework.Scenes
473 /// Constructor. This object is added to the scene later via AttachToScene() 588 /// Constructor. This object is added to the scene later via AttachToScene()
474 /// </summary> 589 /// </summary>
475 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 590 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
476 { 591 {
477 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 592 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
478 } 593 }
479 594
@@ -504,13 +619,16 @@ namespace OpenSim.Region.Framework.Scenes
504 619
505 public void SetFromItemID(UUID AssetId) 620 public void SetFromItemID(UUID AssetId)
506 { 621 {
507 lock (m_parts) 622 lockPartsForRead(true);
508 { 623 {
509 foreach (SceneObjectPart part in m_parts.Values) 624 foreach (SceneObjectPart part in m_parts.Values)
510 { 625 {
626
511 part.FromItemID = AssetId; 627 part.FromItemID = AssetId;
628
512 } 629 }
513 } 630 }
631 lockPartsForRead(false);
514 } 632 }
515 633
516 public UUID GetFromItemID() 634 public UUID GetFromItemID()
@@ -579,10 +697,11 @@ namespace OpenSim.Region.Framework.Scenes
579 Vector3 maxScale = Vector3.Zero; 697 Vector3 maxScale = Vector3.Zero;
580 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); 698 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
581 699
582 lock (m_parts) 700 lockPartsForRead(true);
583 { 701 {
584 foreach (SceneObjectPart part in m_parts.Values) 702 foreach (SceneObjectPart part in m_parts.Values)
585 { 703 {
704
586 Vector3 partscale = part.Scale; 705 Vector3 partscale = part.Scale;
587 Vector3 partoffset = part.OffsetPosition; 706 Vector3 partoffset = part.OffsetPosition;
588 707
@@ -593,8 +712,11 @@ namespace OpenSim.Region.Framework.Scenes
593 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; 712 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X;
594 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y; 713 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y;
595 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z; 714 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
715
596 } 716 }
597 } 717 }
718 lockPartsForRead(false);
719
598 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; 720 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
599 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; 721 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
600 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; 722 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
@@ -610,10 +732,11 @@ namespace OpenSim.Region.Framework.Scenes
610 732
611 EntityIntersection result = new EntityIntersection(); 733 EntityIntersection result = new EntityIntersection();
612 734
613 lock (m_parts) 735 lockPartsForRead(true);
614 { 736 {
615 foreach (SceneObjectPart part in m_parts.Values) 737 foreach (SceneObjectPart part in m_parts.Values)
616 { 738 {
739
617 // Temporary commented to stop compiler warning 740 // Temporary commented to stop compiler warning
618 //Vector3 partPosition = 741 //Vector3 partPosition =
619 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); 742 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
@@ -641,8 +764,10 @@ namespace OpenSim.Region.Framework.Scenes
641 result.distance = inter.distance; 764 result.distance = inter.distance;
642 } 765 }
643 } 766 }
767
644 } 768 }
645 } 769 }
770 lockPartsForRead(false);
646 return result; 771 return result;
647 } 772 }
648 773
@@ -655,10 +780,11 @@ namespace OpenSim.Region.Framework.Scenes
655 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) 780 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight)
656 { 781 {
657 float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f; 782 float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f;
658 lock (m_parts) 783 lockPartsForRead(true);
659 { 784 {
660 foreach (SceneObjectPart part in m_parts.Values) 785 foreach (SceneObjectPart part in m_parts.Values)
661 { 786 {
787
662 Vector3 worldPos = part.GetWorldPosition(); 788 Vector3 worldPos = part.GetWorldPosition();
663 Vector3 offset = worldPos - AbsolutePosition; 789 Vector3 offset = worldPos - AbsolutePosition;
664 Quaternion worldRot; 790 Quaternion worldRot;
@@ -717,6 +843,8 @@ namespace OpenSim.Region.Framework.Scenes
717 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 843 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
718 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 844 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
719 845
846
847
720 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); 848 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
721 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); 849 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
722 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); 850 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
@@ -888,6 +1016,7 @@ namespace OpenSim.Region.Framework.Scenes
888 minZ = backBottomLeft.Z; 1016 minZ = backBottomLeft.Z;
889 } 1017 }
890 } 1018 }
1019 lockPartsForRead(false);
891 1020
892 Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ); 1021 Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ);
893 1022
@@ -912,21 +1041,29 @@ namespace OpenSim.Region.Framework.Scenes
912 1041
913 public void SaveScriptedState(XmlTextWriter writer) 1042 public void SaveScriptedState(XmlTextWriter writer)
914 { 1043 {
1044 SaveScriptedState(writer, false);
1045 }
1046
1047 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1048 {
915 XmlDocument doc = new XmlDocument(); 1049 XmlDocument doc = new XmlDocument();
916 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1050 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
917 1051
918 // Capture script state while holding the lock 1052 // Capture script state while holding the lock
919 lock (m_parts) 1053 lockPartsForRead(true);
920 { 1054 {
921 foreach (SceneObjectPart part in m_parts.Values) 1055 foreach (SceneObjectPart part in m_parts.Values)
922 { 1056 {
923 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); 1057
1058 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(oldIDs);
924 foreach (UUID itemid in pstates.Keys) 1059 foreach (UUID itemid in pstates.Keys)
925 { 1060 {
926 states.Add(itemid, pstates[itemid]); 1061 states.Add(itemid, pstates[itemid]);
927 } 1062 }
1063
928 } 1064 }
929 } 1065 }
1066 lockPartsForRead(false);
930 1067
931 if (states.Count > 0) 1068 if (states.Count > 0)
932 { 1069 {
@@ -1094,13 +1231,16 @@ namespace OpenSim.Region.Framework.Scenes
1094 1231
1095 public override void UpdateMovement() 1232 public override void UpdateMovement()
1096 { 1233 {
1097 lock (m_parts) 1234 lockPartsForRead(true);
1098 { 1235 {
1099 foreach (SceneObjectPart part in m_parts.Values) 1236 foreach (SceneObjectPart part in m_parts.Values)
1100 { 1237 {
1238
1101 part.UpdateMovement(); 1239 part.UpdateMovement();
1240
1102 } 1241 }
1103 } 1242 }
1243 lockPartsForRead(false);
1104 } 1244 }
1105 1245
1106 public ushort GetTimeDilation() 1246 public ushort GetTimeDilation()
@@ -1144,7 +1284,7 @@ namespace OpenSim.Region.Framework.Scenes
1144 /// <param name="part"></param> 1284 /// <param name="part"></param>
1145 public void AddPart(SceneObjectPart part) 1285 public void AddPart(SceneObjectPart part)
1146 { 1286 {
1147 lock (m_parts) 1287 lockPartsForWrite(true);
1148 { 1288 {
1149 part.SetParent(this); 1289 part.SetParent(this);
1150 m_parts.Add(part.UUID, part); 1290 m_parts.Add(part.UUID, part);
@@ -1154,6 +1294,7 @@ namespace OpenSim.Region.Framework.Scenes
1154 if (part.LinkNum == 2 && RootPart != null) 1294 if (part.LinkNum == 2 && RootPart != null)
1155 RootPart.LinkNum = 1; 1295 RootPart.LinkNum = 1;
1156 } 1296 }
1297 lockPartsForWrite(false);
1157 } 1298 }
1158 1299
1159 /// <summary> 1300 /// <summary>
@@ -1161,28 +1302,33 @@ namespace OpenSim.Region.Framework.Scenes
1161 /// </summary> 1302 /// </summary>
1162 private void UpdateParentIDs() 1303 private void UpdateParentIDs()
1163 { 1304 {
1164 lock (m_parts) 1305 lockPartsForRead(true);
1165 { 1306 {
1166 foreach (SceneObjectPart part in m_parts.Values) 1307 foreach (SceneObjectPart part in m_parts.Values)
1167 { 1308 {
1309
1168 if (part.UUID != m_rootPart.UUID) 1310 if (part.UUID != m_rootPart.UUID)
1169 { 1311 {
1170 part.ParentID = m_rootPart.LocalId; 1312 part.ParentID = m_rootPart.LocalId;
1171 } 1313 }
1314
1172 } 1315 }
1173 } 1316 }
1317 lockPartsForRead(false);
1174 } 1318 }
1175 1319
1176 public void RegenerateFullIDs() 1320 public void RegenerateFullIDs()
1177 { 1321 {
1178 lock (m_parts) 1322 lockPartsForRead(true);
1179 { 1323 {
1180 foreach (SceneObjectPart part in m_parts.Values) 1324 foreach (SceneObjectPart part in m_parts.Values)
1181 { 1325 {
1326
1182 part.UUID = UUID.Random(); 1327 part.UUID = UUID.Random();
1183 1328
1184 } 1329 }
1185 } 1330 }
1331 lockPartsForRead(false);
1186 } 1332 }
1187 1333
1188 // helper provided for parts. 1334 // helper provided for parts.
@@ -1263,27 +1409,32 @@ namespace OpenSim.Region.Framework.Scenes
1263 1409
1264 DetachFromBackup(); 1410 DetachFromBackup();
1265 1411
1266 lock (m_parts) 1412 lockPartsForRead(true);
1413 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1414 lockPartsForRead(false);
1415
1416 foreach (SceneObjectPart part in values)
1267 { 1417 {
1268 foreach (SceneObjectPart part in m_parts.Values)
1269 {
1270// part.Inventory.RemoveScriptInstances(); 1418// part.Inventory.RemoveScriptInstances();
1271 Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1419
1420 Scene.ForEachScenePresence(delegate (ScenePresence sp)
1421 {
1422 if (sp.ParentID == LocalId)
1272 { 1423 {
1273 if (avatar.ParentID == LocalId) 1424 sp.StandUp();
1274 { 1425 }
1275 avatar.StandUp();
1276 }
1277 1426
1278 if (!silent) 1427 if (!silent)
1279 { 1428 {
1280 part.UpdateFlag = 0; 1429 part.UpdateFlag = 0;
1281 if (part == m_rootPart) 1430 if (part == m_rootPart)
1282 avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId); 1431 sp.ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1283 } 1432 }
1284 }); 1433 });
1285 } 1434
1286 } 1435 }
1436
1437
1287 } 1438 }
1288 1439
1289 public void AddScriptLPS(int count) 1440 public void AddScriptLPS(int count)
@@ -1308,17 +1459,20 @@ namespace OpenSim.Region.Framework.Scenes
1308 1459
1309 scriptEvents aggregateScriptEvents=0; 1460 scriptEvents aggregateScriptEvents=0;
1310 1461
1311 lock (m_parts) 1462 lockPartsForRead(true);
1312 { 1463 {
1313 foreach (SceneObjectPart part in m_parts.Values) 1464 foreach (SceneObjectPart part in m_parts.Values)
1314 { 1465 {
1466
1315 if (part == null) 1467 if (part == null)
1316 continue; 1468 continue;
1317 if (part != RootPart) 1469 if (part != RootPart)
1318 part.ObjectFlags = objectflagupdate; 1470 part.ObjectFlags = objectflagupdate;
1319 aggregateScriptEvents |= part.AggregateScriptEvents; 1471 aggregateScriptEvents |= part.AggregateScriptEvents;
1472
1320 } 1473 }
1321 } 1474 }
1475 lockPartsForRead(false);
1322 1476
1323 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); 1477 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
1324 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); 1478 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0);
@@ -1360,42 +1514,52 @@ namespace OpenSim.Region.Framework.Scenes
1360 /// <param name="m_physicalPrim"></param> 1514 /// <param name="m_physicalPrim"></param>
1361 public void ApplyPhysics(bool m_physicalPrim) 1515 public void ApplyPhysics(bool m_physicalPrim)
1362 { 1516 {
1363 lock (m_parts) 1517 lockPartsForRead(true);
1518
1519 if (m_parts.Count > 1)
1364 { 1520 {
1365 if (m_parts.Count > 1) 1521 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1522 lockPartsForRead(false);
1523 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1524 foreach (SceneObjectPart part in values)
1366 { 1525 {
1367 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); 1526
1368 foreach (SceneObjectPart part in m_parts.Values) 1527 if (part.LocalId != m_rootPart.LocalId)
1369 { 1528 {
1370 if (part.LocalId != m_rootPart.LocalId) 1529 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1371 {
1372 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1373 }
1374 } 1530 }
1375 1531
1376 // Hack to get the physics scene geometries in the right spot
1377 ResetChildPrimPhysicsPositions();
1378 }
1379 else
1380 {
1381 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1382 } 1532 }
1533 // Hack to get the physics scene geometries in the right spot
1534 ResetChildPrimPhysicsPositions();
1535 }
1536 else
1537 {
1538 lockPartsForRead(false);
1539 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1383 } 1540 }
1384 } 1541 }
1385 1542
1386 public void SetOwnerId(UUID userId) 1543 public void SetOwnerId(UUID userId)
1387 { 1544 {
1388 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1545 ForEachPart(delegate(SceneObjectPart part)
1546 {
1547
1548 part.OwnerID = userId;
1549
1550 });
1389 } 1551 }
1390 1552
1391 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1553 public void ForEachPart(Action<SceneObjectPart> whatToDo)
1392 { 1554 {
1393 lock (m_parts) 1555 lockPartsForRead(true);
1556 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1557 lockPartsForRead(false);
1558 foreach (SceneObjectPart part in values)
1394 { 1559 {
1395 foreach (SceneObjectPart part in m_parts.Values) 1560
1396 { 1561 whatToDo(part);
1397 whatToDo(part); 1562
1398 }
1399 } 1563 }
1400 } 1564 }
1401 1565
@@ -1493,15 +1657,17 @@ namespace OpenSim.Region.Framework.Scenes
1493 RootPart.SendFullUpdate( 1657 RootPart.SendFullUpdate(
1494 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); 1658 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
1495 1659
1496 lock (m_parts) 1660 lockPartsForRead(true);
1497 { 1661 {
1498 foreach (SceneObjectPart part in m_parts.Values) 1662 foreach (SceneObjectPart part in m_parts.Values)
1499 { 1663 {
1664
1500 if (part != RootPart) 1665 if (part != RootPart)
1501 part.SendFullUpdate( 1666 part.SendFullUpdate(
1502 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); 1667 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
1503 } 1668 }
1504 } 1669 }
1670 lockPartsForRead(false);
1505 } 1671 }
1506 1672
1507 #region Copying 1673 #region Copying
@@ -1570,10 +1736,11 @@ namespace OpenSim.Region.Framework.Scenes
1570 1736
1571 List<SceneObjectPart> partList; 1737 List<SceneObjectPart> partList;
1572 1738
1573 lock (m_parts) 1739 lockPartsForRead(true);
1574 { 1740
1575 partList = new List<SceneObjectPart>(m_parts.Values); 1741 partList = new List<SceneObjectPart>(m_parts.Values);
1576 } 1742
1743 lockPartsForRead(false);
1577 1744
1578 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1745 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1579 { 1746 {
@@ -1796,13 +1963,40 @@ namespace OpenSim.Region.Framework.Scenes
1796 } 1963 }
1797 } 1964 }
1798 1965
1966 public void rotLookAt(Quaternion target, float strength, float damping)
1967 {
1968 SceneObjectPart rootpart = m_rootPart;
1969 if (rootpart != null)
1970 {
1971 if (IsAttachment)
1972 {
1973 /*
1974 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1975 if (avatar != null)
1976 {
1977 Rotate the Av?
1978 } */
1979 }
1980 else
1981 {
1982 if (rootpart.PhysActor != null)
1983 { // APID must be implemented in your physics system for this to function.
1984 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
1985 rootpart.PhysActor.APIDStrength = strength;
1986 rootpart.PhysActor.APIDDamping = damping;
1987 rootpart.PhysActor.APIDActive = true;
1988 }
1989 }
1990 }
1991 }
1992
1799 public void stopLookAt() 1993 public void stopLookAt()
1800 { 1994 {
1801 SceneObjectPart rootpart = m_rootPart; 1995 SceneObjectPart rootpart = m_rootPart;
1802 if (rootpart != null) 1996 if (rootpart != null)
1803 { 1997 {
1804 if (rootpart.PhysActor != null) 1998 if (rootpart.PhysActor != null)
1805 { 1999 { // APID must be implemented in your physics system for this to function.
1806 rootpart.PhysActor.APIDActive = false; 2000 rootpart.PhysActor.APIDActive = false;
1807 } 2001 }
1808 } 2002 }
@@ -1870,10 +2064,11 @@ namespace OpenSim.Region.Framework.Scenes
1870 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2064 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1871 newPart.SetParent(this); 2065 newPart.SetParent(this);
1872 2066
1873 lock (m_parts) 2067 lockPartsForWrite(true);
1874 { 2068 {
1875 m_parts.Add(newPart.UUID, newPart); 2069 m_parts.Add(newPart.UUID, newPart);
1876 } 2070 }
2071 lockPartsForWrite(false);
1877 2072
1878 SetPartAsNonRoot(newPart); 2073 SetPartAsNonRoot(newPart);
1879 2074
@@ -1936,7 +2131,7 @@ namespace OpenSim.Region.Framework.Scenes
1936 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2131 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1937 // return; 2132 // return;
1938 2133
1939 lock (m_parts) 2134 lockPartsForRead(true);
1940 { 2135 {
1941 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2136 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1942 2137
@@ -1956,9 +2151,12 @@ namespace OpenSim.Region.Framework.Scenes
1956 { 2151 {
1957 if (!IsSelected) 2152 if (!IsSelected)
1958 part.UpdateLookAt(); 2153 part.UpdateLookAt();
2154
1959 part.SendScheduledUpdates(); 2155 part.SendScheduledUpdates();
2156
1960 } 2157 }
1961 } 2158 }
2159 lockPartsForRead(false);
1962 } 2160 }
1963 2161
1964 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2162 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
@@ -1967,27 +2165,29 @@ namespace OpenSim.Region.Framework.Scenes
1967 2165
1968 RootPart.AddFullUpdateToAvatar(presence); 2166 RootPart.AddFullUpdateToAvatar(presence);
1969 2167
1970 lock (m_parts) 2168 lockPartsForRead(true);
1971 { 2169 {
1972 foreach (SceneObjectPart part in m_parts.Values) 2170 foreach (SceneObjectPart part in m_parts.Values)
1973 { 2171 {
2172
1974 if (part != RootPart) 2173 if (part != RootPart)
1975 part.AddFullUpdateToAvatar(presence); 2174 part.AddFullUpdateToAvatar(presence);
2175
1976 } 2176 }
1977 } 2177 }
2178 lockPartsForRead(false);
1978 } 2179 }
1979 2180
1980 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2181 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
1981 { 2182 {
1982// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); 2183 lockPartsForRead(true);
1983 2184
1984 lock (m_parts) 2185 foreach (SceneObjectPart part in m_parts.Values)
1985 { 2186 {
1986 foreach (SceneObjectPart part in m_parts.Values) 2187 part.AddTerseUpdateToAvatar(presence);
1987 {
1988 part.AddTerseUpdateToAvatar(presence);
1989 }
1990 } 2188 }
2189
2190 lockPartsForRead(false);
1991 } 2191 }
1992 2192
1993 /// <summary> 2193 /// <summary>
@@ -2000,14 +2200,17 @@ namespace OpenSim.Region.Framework.Scenes
2000 checkAtTargets(); 2200 checkAtTargets();
2001 RootPart.ScheduleFullUpdate(); 2201 RootPart.ScheduleFullUpdate();
2002 2202
2003 lock (m_parts) 2203 lockPartsForRead(true);
2004 { 2204 {
2005 foreach (SceneObjectPart part in m_parts.Values) 2205 foreach (SceneObjectPart part in m_parts.Values)
2006 { 2206 {
2207
2007 if (part != RootPart) 2208 if (part != RootPart)
2008 part.ScheduleFullUpdate(); 2209 part.ScheduleFullUpdate();
2210
2009 } 2211 }
2010 } 2212 }
2213 lockPartsForRead(false);
2011 } 2214 }
2012 2215
2013 /// <summary> 2216 /// <summary>
@@ -2015,37 +2218,38 @@ namespace OpenSim.Region.Framework.Scenes
2015 /// </summary> 2218 /// </summary>
2016 public void ScheduleGroupForTerseUpdate() 2219 public void ScheduleGroupForTerseUpdate()
2017 { 2220 {
2018// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); 2221 lockPartsForRead(true);
2019 2222 foreach (SceneObjectPart part in m_parts.Values)
2020 lock (m_parts)
2021 { 2223 {
2022 foreach (SceneObjectPart part in m_parts.Values) 2224 part.ScheduleTerseUpdate();
2023 {
2024 part.ScheduleTerseUpdate();
2025 }
2026 } 2225 }
2226
2227 lockPartsForRead(false);
2027 } 2228 }
2028 2229
2029 /// <summary> 2230 /// <summary>
2030 /// Immediately send a full update for this scene object. 2231 /// Immediately send a full update for this scene object.
2031 /// </summary> 2232 /// </summary>
2032 public void SendGroupFullUpdate() 2233 public void SendGroupFullUpdate()
2033 { 2234 {
2034 if (IsDeleted) 2235 if (IsDeleted)
2035 return; 2236 return;
2036 2237
2037// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2238// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
2038 2239
2039 RootPart.SendFullUpdateToAllClients(); 2240 RootPart.SendFullUpdateToAllClients();
2040 2241
2041 lock (m_parts) 2242 lockPartsForRead(true);
2042 { 2243 {
2043 foreach (SceneObjectPart part in m_parts.Values) 2244 foreach (SceneObjectPart part in m_parts.Values)
2044 { 2245 {
2246
2045 if (part != RootPart) 2247 if (part != RootPart)
2046 part.SendFullUpdateToAllClients(); 2248 part.SendFullUpdateToAllClients();
2249
2047 } 2250 }
2048 } 2251 }
2252 lockPartsForRead(false);
2049 } 2253 }
2050 2254
2051 /// <summary> 2255 /// <summary>
@@ -2077,14 +2281,15 @@ namespace OpenSim.Region.Framework.Scenes
2077 { 2281 {
2078 if (IsDeleted) 2282 if (IsDeleted)
2079 return; 2283 return;
2080 2284
2081 lock (m_parts) 2285 lockPartsForRead(true);
2082 { 2286 {
2083 foreach (SceneObjectPart part in m_parts.Values) 2287 foreach (SceneObjectPart part in m_parts.Values)
2084 { 2288 {
2085 part.SendTerseUpdateToAllClients(); 2289 part.SendTerseUpdateToAllClients();
2086 } 2290 }
2087 } 2291 }
2292 lockPartsForRead(false);
2088 } 2293 }
2089 2294
2090 #endregion 2295 #endregion
@@ -2098,16 +2303,18 @@ namespace OpenSim.Region.Framework.Scenes
2098 /// <returns>null if no child part with that linknum or child part</returns> 2303 /// <returns>null if no child part with that linknum or child part</returns>
2099 public SceneObjectPart GetLinkNumPart(int linknum) 2304 public SceneObjectPart GetLinkNumPart(int linknum)
2100 { 2305 {
2101 lock (m_parts) 2306 lockPartsForRead(true);
2102 { 2307 {
2103 foreach (SceneObjectPart part in m_parts.Values) 2308 foreach (SceneObjectPart part in m_parts.Values)
2104 { 2309 {
2105 if (part.LinkNum == linknum) 2310 if (part.LinkNum == linknum)
2106 { 2311 {
2312 lockPartsForRead(false);
2107 return part; 2313 return part;
2108 } 2314 }
2109 } 2315 }
2110 } 2316 }
2317 lockPartsForRead(false);
2111 2318
2112 return null; 2319 return null;
2113 } 2320 }
@@ -2135,17 +2342,19 @@ namespace OpenSim.Region.Framework.Scenes
2135 public SceneObjectPart GetChildPart(uint localID) 2342 public SceneObjectPart GetChildPart(uint localID)
2136 { 2343 {
2137 //m_log.DebugFormat("Entered looking for {0}", localID); 2344 //m_log.DebugFormat("Entered looking for {0}", localID);
2138 lock (m_parts) 2345 lockPartsForRead(true);
2139 { 2346 {
2140 foreach (SceneObjectPart part in m_parts.Values) 2347 foreach (SceneObjectPart part in m_parts.Values)
2141 { 2348 {
2142 //m_log.DebugFormat("Found {0}", part.LocalId); 2349 //m_log.DebugFormat("Found {0}", part.LocalId);
2143 if (part.LocalId == localID) 2350 if (part.LocalId == localID)
2144 { 2351 {
2352 lockPartsForRead(false);
2145 return part; 2353 return part;
2146 } 2354 }
2147 } 2355 }
2148 } 2356 }
2357 lockPartsForRead(false);
2149 2358
2150 return null; 2359 return null;
2151 } 2360 }
@@ -2175,17 +2384,19 @@ namespace OpenSim.Region.Framework.Scenes
2175 public bool HasChildPrim(uint localID) 2384 public bool HasChildPrim(uint localID)
2176 { 2385 {
2177 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2386 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2178 lock (m_parts) 2387 lockPartsForRead(true);
2179 { 2388 {
2180 foreach (SceneObjectPart part in m_parts.Values) 2389 foreach (SceneObjectPart part in m_parts.Values)
2181 { 2390 {
2182 //m_log.DebugFormat("Found {0}", part.LocalId); 2391 //m_log.DebugFormat("Found {0}", part.LocalId);
2183 if (part.LocalId == localID) 2392 if (part.LocalId == localID)
2184 { 2393 {
2394 lockPartsForRead(false);
2185 return true; 2395 return true;
2186 } 2396 }
2187 } 2397 }
2188 } 2398 }
2399 lockPartsForRead(false);
2189 2400
2190 return false; 2401 return false;
2191 } 2402 }
@@ -2235,53 +2446,57 @@ namespace OpenSim.Region.Framework.Scenes
2235 if (m_rootPart.LinkNum == 0) 2446 if (m_rootPart.LinkNum == 0)
2236 m_rootPart.LinkNum = 1; 2447 m_rootPart.LinkNum = 1;
2237 2448
2238 lock (m_parts) 2449 lockPartsForWrite(true);
2239 { 2450
2240 m_parts.Add(linkPart.UUID, linkPart); 2451 m_parts.Add(linkPart.UUID, linkPart);
2452
2453 lockPartsForWrite(false);
2241 2454
2242 // Insert in terms of link numbers, the new links 2455 // Insert in terms of link numbers, the new links
2243 // before the current ones (with the exception of 2456 // before the current ones (with the exception of
2244 // the root prim. Shuffle the old ones up 2457 // the root prim. Shuffle the old ones up
2245 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2458 lockPartsForRead(true);
2459 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2460 {
2461 if (kvp.Value.LinkNum != 1)
2246 { 2462 {
2247 if (kvp.Value.LinkNum != 1) 2463 // Don't update root prim link number
2248 { 2464 kvp.Value.LinkNum += objectGroup.PrimCount;
2249 // Don't update root prim link number
2250 kvp.Value.LinkNum += objectGroup.PrimCount;
2251 }
2252 } 2465 }
2466 }
2467 lockPartsForRead(false);
2253 2468
2254 linkPart.LinkNum = 2; 2469 linkPart.LinkNum = 2;
2255 2470
2256 linkPart.SetParent(this); 2471 linkPart.SetParent(this);
2257 linkPart.AddFlag(PrimFlags.CreateSelected); 2472 linkPart.AddFlag(PrimFlags.CreateSelected);
2258 2473
2259 //if (linkPart.PhysActor != null) 2474 //if (linkPart.PhysActor != null)
2260 //{ 2475 //{
2261 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2476 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2262 2477
2263 //linkPart.PhysActor = null; 2478 //linkPart.PhysActor = null;
2264 //} 2479 //}
2265 2480
2266 //TODO: rest of parts 2481 //TODO: rest of parts
2267 int linkNum = 3; 2482 int linkNum = 3;
2268 foreach (SceneObjectPart part in objectGroup.Children.Values) 2483 foreach (SceneObjectPart part in objectGroup.Children.Values)
2484 {
2485 if (part.UUID != objectGroup.m_rootPart.UUID)
2269 { 2486 {
2270 if (part.UUID != objectGroup.m_rootPart.UUID) 2487 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2271 {
2272 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2273 }
2274 part.ClearUndoState();
2275 } 2488 }
2489 part.ClearUndoState();
2276 } 2490 }
2277 2491
2278 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2492 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2279 objectGroup.m_isDeleted = true; 2493 objectGroup.m_isDeleted = true;
2494
2495 objectGroup.lockPartsForWrite(true);
2280 2496
2281 lock (objectGroup.m_parts) 2497 objectGroup.m_parts.Clear();
2282 { 2498
2283 objectGroup.m_parts.Clear(); 2499 objectGroup.lockPartsForWrite(false);
2284 }
2285 2500
2286 // Can't do this yet since backup still makes use of the root part without any synchronization 2501 // Can't do this yet since backup still makes use of the root part without any synchronization
2287// objectGroup.m_rootPart = null; 2502// objectGroup.m_rootPart = null;
@@ -2351,11 +2566,12 @@ namespace OpenSim.Region.Framework.Scenes
2351 Quaternion worldRot = linkPart.GetWorldRotation(); 2566 Quaternion worldRot = linkPart.GetWorldRotation();
2352 2567
2353 // Remove the part from this object 2568 // Remove the part from this object
2354 lock (m_parts) 2569 lockPartsForWrite(true);
2355 { 2570 {
2356 m_parts.Remove(linkPart.UUID); 2571 m_parts.Remove(linkPart.UUID);
2357 } 2572 }
2358 2573 lockPartsForWrite(false);
2574 lockPartsForRead(true);
2359 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2575 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2360 RootPart.LinkNum = 0; 2576 RootPart.LinkNum = 0;
2361 else 2577 else
@@ -2366,6 +2582,7 @@ namespace OpenSim.Region.Framework.Scenes
2366 p.LinkNum--; 2582 p.LinkNum--;
2367 } 2583 }
2368 } 2584 }
2585 lockPartsForRead(false);
2369 2586
2370 linkPart.ParentID = 0; 2587 linkPart.ParentID = 0;
2371 linkPart.LinkNum = 0; 2588 linkPart.LinkNum = 0;
@@ -2687,9 +2904,12 @@ namespace OpenSim.Region.Framework.Scenes
2687 2904
2688 if (selectionPart != null) 2905 if (selectionPart != null)
2689 { 2906 {
2690 lock (m_parts) 2907 lockPartsForRead(true);
2908 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
2909 lockPartsForRead(false);
2910 foreach (SceneObjectPart part in parts)
2691 { 2911 {
2692 foreach (SceneObjectPart part in m_parts.Values) 2912 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2693 { 2913 {
2694 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 2914 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2695 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 2915 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
@@ -2699,12 +2919,13 @@ namespace OpenSim.Region.Framework.Scenes
2699 break; 2919 break;
2700 } 2920 }
2701 } 2921 }
2922 }
2702 2923
2703 foreach (SceneObjectPart part in m_parts.Values) 2924 foreach (SceneObjectPart part in parts)
2704 { 2925 {
2705 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2926 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2706 }
2707 } 2927 }
2928
2708 } 2929 }
2709 } 2930 }
2710 2931
@@ -2790,11 +3011,9 @@ namespace OpenSim.Region.Framework.Scenes
2790 scale.Y = m_scene.m_maxNonphys; 3011 scale.Y = m_scene.m_maxNonphys;
2791 if (scale.Z > m_scene.m_maxNonphys) 3012 if (scale.Z > m_scene.m_maxNonphys)
2792 scale.Z = m_scene.m_maxNonphys; 3013 scale.Z = m_scene.m_maxNonphys;
2793
2794 SceneObjectPart part = GetChildPart(localID); 3014 SceneObjectPart part = GetChildPart(localID);
2795 if (part != null) 3015 if (part != null)
2796 { 3016 {
2797 part.Resize(scale);
2798 if (part.PhysActor != null) 3017 if (part.PhysActor != null)
2799 { 3018 {
2800 if (part.PhysActor.IsPhysical) 3019 if (part.PhysActor.IsPhysical)
@@ -2809,7 +3028,7 @@ namespace OpenSim.Region.Framework.Scenes
2809 part.PhysActor.Size = scale; 3028 part.PhysActor.Size = scale;
2810 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 3029 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2811 } 3030 }
2812 //if (part.UUID != m_rootPart.UUID) 3031 part.Resize(scale);
2813 3032
2814 HasGroupChanged = true; 3033 HasGroupChanged = true;
2815 ScheduleGroupForFullUpdate(); 3034 ScheduleGroupForFullUpdate();
@@ -2851,73 +3070,71 @@ namespace OpenSim.Region.Framework.Scenes
2851 float y = (scale.Y / part.Scale.Y); 3070 float y = (scale.Y / part.Scale.Y);
2852 float z = (scale.Z / part.Scale.Z); 3071 float z = (scale.Z / part.Scale.Z);
2853 3072
2854 lock (m_parts) 3073 lockPartsForRead(true);
3074 if (x > 1.0f || y > 1.0f || z > 1.0f)
2855 { 3075 {
2856 if (x > 1.0f || y > 1.0f || z > 1.0f) 3076 foreach (SceneObjectPart obPart in m_parts.Values)
2857 { 3077 {
2858 foreach (SceneObjectPart obPart in m_parts.Values) 3078 if (obPart.UUID != m_rootPart.UUID)
2859 { 3079 {
2860 if (obPart.UUID != m_rootPart.UUID) 3080 Vector3 oldSize = new Vector3(obPart.Scale);
2861 { 3081 obPart.IgnoreUndoUpdate = true;
2862 obPart.IgnoreUndoUpdate = true;
2863 Vector3 oldSize = new Vector3(obPart.Scale);
2864 3082
2865 float f = 1.0f; 3083 float f = 1.0f;
2866 float a = 1.0f; 3084 float a = 1.0f;
2867 3085
2868 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3086 if (part.PhysActor != null && part.PhysActor.IsPhysical)
3087 {
3088 if (oldSize.X*x > m_scene.m_maxPhys)
2869 { 3089 {
2870 if (oldSize.X*x > m_scene.m_maxPhys) 3090 f = m_scene.m_maxPhys / oldSize.X;
2871 { 3091 a = f / x;
2872 f = m_scene.m_maxPhys / oldSize.X; 3092 x *= a;
2873 a = f / x; 3093 y *= a;
2874 x *= a; 3094 z *= a;
2875 y *= a;
2876 z *= a;
2877 }
2878 if (oldSize.Y*y > m_scene.m_maxPhys)
2879 {
2880 f = m_scene.m_maxPhys / oldSize.Y;
2881 a = f / y;
2882 x *= a;
2883 y *= a;
2884 z *= a;
2885 }
2886 if (oldSize.Z*z > m_scene.m_maxPhys)
2887 {
2888 f = m_scene.m_maxPhys / oldSize.Z;
2889 a = f / z;
2890 x *= a;
2891 y *= a;
2892 z *= a;
2893 }
2894 } 3095 }
2895 else 3096 if (oldSize.Y*y > m_scene.m_maxPhys)
3097 {
3098 f = m_scene.m_maxPhys / oldSize.Y;
3099 a = f / y;
3100 x *= a;
3101 y *= a;
3102 z *= a;
3103 }
3104 if (oldSize.Z*z > m_scene.m_maxPhys)
2896 { 3105 {
2897 if (oldSize.X*x > m_scene.m_maxNonphys) 3106 f = m_scene.m_maxPhys / oldSize.Z;
2898 { 3107 a = f / z;
2899 f = m_scene.m_maxNonphys / oldSize.X; 3108 x *= a;
2900 a = f / x; 3109 y *= a;
2901 x *= a; 3110 z *= a;
2902 y *= a; 3111 }
2903 z *= a; 3112 }
2904 } 3113 else
2905 if (oldSize.Y*y > m_scene.m_maxNonphys) 3114 {
2906 { 3115 if (oldSize.X*x > m_scene.m_maxNonphys)
2907 f = m_scene.m_maxNonphys / oldSize.Y; 3116 {
2908 a = f / y; 3117 f = m_scene.m_maxNonphys / oldSize.X;
2909 x *= a; 3118 a = f / x;
2910 y *= a; 3119 x *= a;
2911 z *= a; 3120 y *= a;
2912 } 3121 z *= a;
2913 if (oldSize.Z*z > m_scene.m_maxNonphys) 3122 }
2914 { 3123 if (oldSize.Y*y > m_scene.m_maxNonphys)
2915 f = m_scene.m_maxNonphys / oldSize.Z; 3124 {
2916 a = f / z; 3125 f = m_scene.m_maxNonphys / oldSize.Y;
2917 x *= a; 3126 a = f / y;
2918 y *= a; 3127 x *= a;
2919 z *= a; 3128 y *= a;
2920 } 3129 z *= a;
3130 }
3131 if (oldSize.Z*z > m_scene.m_maxNonphys)
3132 {
3133 f = m_scene.m_maxNonphys / oldSize.Z;
3134 a = f / z;
3135 x *= a;
3136 y *= a;
3137 z *= a;
2921 } 3138 }
2922 obPart.IgnoreUndoUpdate = false; 3139 obPart.IgnoreUndoUpdate = false;
2923 obPart.StoreUndoState(); 3140 obPart.StoreUndoState();
@@ -2925,6 +3142,7 @@ namespace OpenSim.Region.Framework.Scenes
2925 } 3142 }
2926 } 3143 }
2927 } 3144 }
3145 lockPartsForRead(false);
2928 3146
2929 Vector3 prevScale = part.Scale; 3147 Vector3 prevScale = part.Scale;
2930 prevScale.X *= x; 3148 prevScale.X *= x;
@@ -2932,7 +3150,7 @@ namespace OpenSim.Region.Framework.Scenes
2932 prevScale.Z *= z; 3150 prevScale.Z *= z;
2933 part.Resize(prevScale); 3151 part.Resize(prevScale);
2934 3152
2935 lock (m_parts) 3153 lockPartsForRead(true);
2936 { 3154 {
2937 foreach (SceneObjectPart obPart in m_parts.Values) 3155 foreach (SceneObjectPart obPart in m_parts.Values)
2938 { 3156 {
@@ -2954,6 +3172,7 @@ namespace OpenSim.Region.Framework.Scenes
2954 obPart.StoreUndoState(); 3172 obPart.StoreUndoState();
2955 } 3173 }
2956 } 3174 }
3175 lockPartsForRead(false);
2957 3176
2958 if (part.PhysActor != null) 3177 if (part.PhysActor != null)
2959 { 3178 {
@@ -3056,7 +3275,7 @@ namespace OpenSim.Region.Framework.Scenes
3056 axDiff *= Quaternion.Inverse(partRotation); 3275 axDiff *= Quaternion.Inverse(partRotation);
3057 diff = axDiff; 3276 diff = axDiff;
3058 3277
3059 lock (m_parts) 3278 lockPartsForRead(true);
3060 { 3279 {
3061 foreach (SceneObjectPart obPart in m_parts.Values) 3280 foreach (SceneObjectPart obPart in m_parts.Values)
3062 { 3281 {
@@ -3066,6 +3285,7 @@ namespace OpenSim.Region.Framework.Scenes
3066 } 3285 }
3067 } 3286 }
3068 } 3287 }
3288 lockPartsForRead(false);
3069 3289
3070 AbsolutePosition = newPos; 3290 AbsolutePosition = newPos;
3071 3291
@@ -3199,25 +3419,25 @@ namespace OpenSim.Region.Framework.Scenes
3199 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3419 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3200 } 3420 }
3201 3421
3202 lock (m_parts) 3422 lockPartsForRead(true);
3423
3424 foreach (SceneObjectPart prim in m_parts.Values)
3203 { 3425 {
3204 foreach (SceneObjectPart prim in m_parts.Values) 3426 if (prim.UUID != m_rootPart.UUID)
3205 { 3427 {
3206 if (prim.UUID != m_rootPart.UUID) 3428 prim.IgnoreUndoUpdate = true;
3207 { 3429 Vector3 axPos = prim.OffsetPosition;
3208 prim.IgnoreUndoUpdate = true; 3430 axPos *= oldParentRot;
3209 Vector3 axPos = prim.OffsetPosition; 3431 axPos *= Quaternion.Inverse(axRot);
3210 axPos *= oldParentRot; 3432 prim.OffsetPosition = axPos;
3211 axPos *= Quaternion.Inverse(axRot); 3433 Quaternion primsRot = prim.RotationOffset;
3212 prim.OffsetPosition = axPos; 3434 Quaternion newRot = primsRot * oldParentRot;
3213 Quaternion primsRot = prim.RotationOffset; 3435 newRot *= Quaternion.Inverse(axRot);
3214 Quaternion newRot = primsRot * oldParentRot; 3436 prim.RotationOffset = newRot;
3215 newRot *= Quaternion.Inverse(axRot); 3437 prim.ScheduleTerseUpdate();
3216 prim.RotationOffset = newRot;
3217 prim.ScheduleTerseUpdate();
3218 }
3219 } 3438 }
3220 } 3439 }
3440
3221 foreach (SceneObjectPart childpart in Children.Values) 3441 foreach (SceneObjectPart childpart in Children.Values)
3222 { 3442 {
3223 if (childpart != m_rootPart) 3443 if (childpart != m_rootPart)
@@ -3226,6 +3446,9 @@ namespace OpenSim.Region.Framework.Scenes
3226 childpart.StoreUndoState(); 3446 childpart.StoreUndoState();
3227 } 3447 }
3228 } 3448 }
3449
3450 lockPartsForRead(false);
3451
3229 m_rootPart.ScheduleTerseUpdate(); 3452 m_rootPart.ScheduleTerseUpdate();
3230 } 3453 }
3231 3454
@@ -3347,7 +3570,7 @@ namespace OpenSim.Region.Framework.Scenes
3347 if (atTargets.Count > 0) 3570 if (atTargets.Count > 0)
3348 { 3571 {
3349 uint[] localids = new uint[0]; 3572 uint[] localids = new uint[0];
3350 lock (m_parts) 3573 lockPartsForRead(true);
3351 { 3574 {
3352 localids = new uint[m_parts.Count]; 3575 localids = new uint[m_parts.Count];
3353 int cntr = 0; 3576 int cntr = 0;
@@ -3357,6 +3580,7 @@ namespace OpenSim.Region.Framework.Scenes
3357 cntr++; 3580 cntr++;
3358 } 3581 }
3359 } 3582 }
3583 lockPartsForRead(false);
3360 3584
3361 for (int ctr = 0; ctr < localids.Length; ctr++) 3585 for (int ctr = 0; ctr < localids.Length; ctr++)
3362 { 3586 {
@@ -3375,7 +3599,7 @@ namespace OpenSim.Region.Framework.Scenes
3375 { 3599 {
3376 //trigger not_at_target 3600 //trigger not_at_target
3377 uint[] localids = new uint[0]; 3601 uint[] localids = new uint[0];
3378 lock (m_parts) 3602 lockPartsForRead(true);
3379 { 3603 {
3380 localids = new uint[m_parts.Count]; 3604 localids = new uint[m_parts.Count];
3381 int cntr = 0; 3605 int cntr = 0;
@@ -3385,7 +3609,8 @@ namespace OpenSim.Region.Framework.Scenes
3385 cntr++; 3609 cntr++;
3386 } 3610 }
3387 } 3611 }
3388 3612 lockPartsForRead(false);
3613
3389 for (int ctr = 0; ctr < localids.Length; ctr++) 3614 for (int ctr = 0; ctr < localids.Length; ctr++)
3390 { 3615 {
3391 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3616 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3426,7 +3651,8 @@ namespace OpenSim.Region.Framework.Scenes
3426 if (atRotTargets.Count > 0) 3651 if (atRotTargets.Count > 0)
3427 { 3652 {
3428 uint[] localids = new uint[0]; 3653 uint[] localids = new uint[0];
3429 lock (m_parts) 3654 lockPartsForRead(true);
3655 try
3430 { 3656 {
3431 localids = new uint[m_parts.Count]; 3657 localids = new uint[m_parts.Count];
3432 int cntr = 0; 3658 int cntr = 0;
@@ -3436,6 +3662,10 @@ namespace OpenSim.Region.Framework.Scenes
3436 cntr++; 3662 cntr++;
3437 } 3663 }
3438 } 3664 }
3665 finally
3666 {
3667 lockPartsForRead(false);
3668 }
3439 3669
3440 for (int ctr = 0; ctr < localids.Length; ctr++) 3670 for (int ctr = 0; ctr < localids.Length; ctr++)
3441 { 3671 {
@@ -3454,7 +3684,8 @@ namespace OpenSim.Region.Framework.Scenes
3454 { 3684 {
3455 //trigger not_at_target 3685 //trigger not_at_target
3456 uint[] localids = new uint[0]; 3686 uint[] localids = new uint[0];
3457 lock (m_parts) 3687 lockPartsForRead(true);
3688 try
3458 { 3689 {
3459 localids = new uint[m_parts.Count]; 3690 localids = new uint[m_parts.Count];
3460 int cntr = 0; 3691 int cntr = 0;
@@ -3464,6 +3695,10 @@ namespace OpenSim.Region.Framework.Scenes
3464 cntr++; 3695 cntr++;
3465 } 3696 }
3466 } 3697 }
3698 finally
3699 {
3700 lockPartsForRead(false);
3701 }
3467 3702
3468 for (int ctr = 0; ctr < localids.Length; ctr++) 3703 for (int ctr = 0; ctr < localids.Length; ctr++)
3469 { 3704 {
@@ -3477,19 +3712,20 @@ namespace OpenSim.Region.Framework.Scenes
3477 public float GetMass() 3712 public float GetMass()
3478 { 3713 {
3479 float retmass = 0f; 3714 float retmass = 0f;
3480 lock (m_parts) 3715 lockPartsForRead(true);
3481 { 3716 {
3482 foreach (SceneObjectPart part in m_parts.Values) 3717 foreach (SceneObjectPart part in m_parts.Values)
3483 { 3718 {
3484 retmass += part.GetMass(); 3719 retmass += part.GetMass();
3485 } 3720 }
3486 } 3721 }
3722 lockPartsForRead(false);
3487 return retmass; 3723 return retmass;
3488 } 3724 }
3489 3725
3490 public void CheckSculptAndLoad() 3726 public void CheckSculptAndLoad()
3491 { 3727 {
3492 lock (m_parts) 3728 lockPartsForRead(true);
3493 { 3729 {
3494 if (!IsDeleted) 3730 if (!IsDeleted)
3495 { 3731 {
@@ -3514,6 +3750,7 @@ namespace OpenSim.Region.Framework.Scenes
3514 } 3750 }
3515 } 3751 }
3516 } 3752 }
3753 lockPartsForRead(false);
3517 } 3754 }
3518 3755
3519 protected void AssetReceived(string id, Object sender, AssetBase asset) 3756 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3534,7 +3771,7 @@ namespace OpenSim.Region.Framework.Scenes
3534 /// <param name="client"></param> 3771 /// <param name="client"></param>
3535 public void SetGroup(UUID GroupID, IClientAPI client) 3772 public void SetGroup(UUID GroupID, IClientAPI client)
3536 { 3773 {
3537 lock (m_parts) 3774 lockPartsForRead(true);
3538 { 3775 {
3539 foreach (SceneObjectPart part in m_parts.Values) 3776 foreach (SceneObjectPart part in m_parts.Values)
3540 { 3777 {
@@ -3544,6 +3781,7 @@ namespace OpenSim.Region.Framework.Scenes
3544 3781
3545 HasGroupChanged = true; 3782 HasGroupChanged = true;
3546 } 3783 }
3784 lockPartsForRead(false);
3547 3785
3548 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 3786 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
3549 // for the same object with very different properties. The caller must schedule the update. 3787 // for the same object with very different properties. The caller must schedule the update.
@@ -3565,11 +3803,12 @@ namespace OpenSim.Region.Framework.Scenes
3565 3803
3566 public void SetAttachmentPoint(byte point) 3804 public void SetAttachmentPoint(byte point)
3567 { 3805 {
3568 lock (m_parts) 3806 lockPartsForRead(true);
3569 { 3807 {
3570 foreach (SceneObjectPart part in m_parts.Values) 3808 foreach (SceneObjectPart part in m_parts.Values)
3571 part.SetAttachmentPoint(point); 3809 part.SetAttachmentPoint(point);
3572 } 3810 }
3811 lockPartsForRead(false);
3573 } 3812 }
3574 3813
3575 #region ISceneObject 3814 #region ISceneObject
@@ -3703,5 +3942,13 @@ namespace OpenSim.Region.Framework.Scenes
3703 3942
3704 return priority; 3943 return priority;
3705 } 3944 }
3945
3946 public void ResetOwnerChangeFlag()
3947 {
3948 ForEachPart(delegate(SceneObjectPart part)
3949 {
3950 part.ResetOwnerChangeFlag();
3951 });
3952 }
3706 } 3953 }
3707} 3954}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 71c8018..d174d04 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -147,7 +147,7 @@ namespace OpenSim.Region.Framework.Scenes
147 147
148 // TODO: This needs to be persisted in next XML version update! 148 // TODO: This needs to be persisted in next XML version update!
149 [XmlIgnore] 149 [XmlIgnore]
150 public readonly int[] PayPrice = {-2,-2,-2,-2,-2}; 150 public int[] PayPrice = {-2,-2,-2,-2,-2};
151 [XmlIgnore] 151 [XmlIgnore]
152 public PhysicsActor PhysActor; 152 public PhysicsActor PhysActor;
153 153
@@ -274,6 +274,7 @@ namespace OpenSim.Region.Framework.Scenes
274 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 274 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
275 private Vector3 m_sitTargetPosition; 275 private Vector3 m_sitTargetPosition;
276 private string m_sitAnimation = "SIT"; 276 private string m_sitAnimation = "SIT";
277 private bool m_occupied; // KF if any av is sitting on this prim
277 private string m_text = String.Empty; 278 private string m_text = String.Empty;
278 private string m_touchName = String.Empty; 279 private string m_touchName = String.Empty;
279 private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5); 280 private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5);
@@ -452,12 +453,16 @@ namespace OpenSim.Region.Framework.Scenes
452 } 453 }
453 454
454 /// <value> 455 /// <value>
455 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 456 /// Get the inventory list
456 /// </value> 457 /// </value>
457 public TaskInventoryDictionary TaskInventory 458 public TaskInventoryDictionary TaskInventory
458 { 459 {
459 get { return m_inventory.Items; } 460 get {
460 set { m_inventory.Items = value; } 461 return m_inventory.Items;
462 }
463 set {
464 m_inventory.Items = value;
465 }
461 } 466 }
462 467
463 public uint ObjectFlags 468 public uint ObjectFlags
@@ -586,14 +591,12 @@ namespace OpenSim.Region.Framework.Scenes
586 set { m_LoopSoundSlavePrims = value; } 591 set { m_LoopSoundSlavePrims = value; }
587 } 592 }
588 593
589 [XmlIgnore]
590 public Byte[] TextureAnimation 594 public Byte[] TextureAnimation
591 { 595 {
592 get { return m_TextureAnimation; } 596 get { return m_TextureAnimation; }
593 set { m_TextureAnimation = value; } 597 set { m_TextureAnimation = value; }
594 } 598 }
595 599
596 [XmlIgnore]
597 public Byte[] ParticleSystem 600 public Byte[] ParticleSystem
598 { 601 {
599 get { return m_particleSystem; } 602 get { return m_particleSystem; }
@@ -647,7 +650,6 @@ namespace OpenSim.Region.Framework.Scenes
647 set 650 set
648 { 651 {
649 m_groupPosition = value; 652 m_groupPosition = value;
650
651 PhysicsActor actor = PhysActor; 653 PhysicsActor actor = PhysActor;
652 if (actor != null) 654 if (actor != null)
653 { 655 {
@@ -834,7 +836,16 @@ namespace OpenSim.Region.Framework.Scenes
834 /// <summary></summary> 836 /// <summary></summary>
835 public Vector3 Acceleration 837 public Vector3 Acceleration
836 { 838 {
837 get { return m_acceleration; } 839 get
840 {
841 PhysicsActor actor = PhysActor;
842 if (actor != null)
843 {
844 m_acceleration = actor.Acceleration;
845 }
846 return m_acceleration;
847 }
848
838 set { m_acceleration = value; } 849 set { m_acceleration = value; }
839 } 850 }
840 851
@@ -978,7 +989,8 @@ namespace OpenSim.Region.Framework.Scenes
978 if (IsAttachment) 989 if (IsAttachment)
979 return GroupPosition; 990 return GroupPosition;
980 991
981 return m_offsetPosition + m_groupPosition; } 992// return m_offsetPosition + m_groupPosition; }
993 return m_groupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset) ; } //KF: Rotation was ignored!
982 } 994 }
983 995
984 public SceneObjectGroup ParentGroup 996 public SceneObjectGroup ParentGroup
@@ -1129,6 +1141,13 @@ namespace OpenSim.Region.Framework.Scenes
1129 get { return _flags; } 1141 get { return _flags; }
1130 set { _flags = value; } 1142 set { _flags = value; }
1131 } 1143 }
1144
1145 [XmlIgnore]
1146 public bool IsOccupied // KF If an av is sittingon this prim
1147 {
1148 get { return m_occupied; }
1149 set { m_occupied = value; }
1150 }
1132 1151
1133 [XmlIgnore] 1152 [XmlIgnore]
1134 public UUID SitTargetAvatar 1153 public UUID SitTargetAvatar
@@ -1204,14 +1223,6 @@ namespace OpenSim.Region.Framework.Scenes
1204 } 1223 }
1205 } 1224 }
1206 1225
1207 /// <summary>
1208 /// Clear all pending updates of parts to clients
1209 /// </summary>
1210 private void ClearUpdateSchedule()
1211 {
1212 m_updateFlag = 0;
1213 }
1214
1215 private void SendObjectPropertiesToClient(UUID AgentID) 1226 private void SendObjectPropertiesToClient(UUID AgentID)
1216 { 1227 {
1217 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1228 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
@@ -1951,12 +1962,17 @@ namespace OpenSim.Region.Framework.Scenes
1951 public Vector3 GetWorldPosition() 1962 public Vector3 GetWorldPosition()
1952 { 1963 {
1953 Quaternion parentRot = ParentGroup.RootPart.RotationOffset; 1964 Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
1954
1955 Vector3 axPos = OffsetPosition; 1965 Vector3 axPos = OffsetPosition;
1956
1957 axPos *= parentRot; 1966 axPos *= parentRot;
1958 Vector3 translationOffsetPosition = axPos; 1967 Vector3 translationOffsetPosition = axPos;
1959 return GroupPosition + translationOffsetPosition; 1968 if(_parentID == 0)
1969 {
1970 return GroupPosition;
1971 }
1972 else
1973 {
1974 return ParentGroup.AbsolutePosition + translationOffsetPosition; //KF: Fix child prim position
1975 }
1960 } 1976 }
1961 1977
1962 /// <summary> 1978 /// <summary>
@@ -1967,7 +1983,7 @@ namespace OpenSim.Region.Framework.Scenes
1967 { 1983 {
1968 Quaternion newRot; 1984 Quaternion newRot;
1969 1985
1970 if (this.LinkNum == 0) 1986 if (this.LinkNum < 2) //KF Single or root prim
1971 { 1987 {
1972 newRot = RotationOffset; 1988 newRot = RotationOffset;
1973 } 1989 }
@@ -2613,17 +2629,18 @@ namespace OpenSim.Region.Framework.Scenes
2613 //Trys to fetch sound id from prim's inventory. 2629 //Trys to fetch sound id from prim's inventory.
2614 //Prim's inventory doesn't support non script items yet 2630 //Prim's inventory doesn't support non script items yet
2615 2631
2616 lock (TaskInventory) 2632 TaskInventory.LockItemsForRead(true);
2633
2634 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2617 { 2635 {
2618 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2636 if (item.Value.Name == sound)
2619 { 2637 {
2620 if (item.Value.Name == sound) 2638 soundID = item.Value.ItemID;
2621 { 2639 break;
2622 soundID = item.Value.ItemID;
2623 break;
2624 }
2625 } 2640 }
2626 } 2641 }
2642
2643 TaskInventory.LockItemsForRead(false);
2627 } 2644 }
2628 2645
2629 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp) 2646 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp)
@@ -2692,38 +2709,7 @@ namespace OpenSim.Region.Framework.Scenes
2692 2709
2693 public void RotLookAt(Quaternion target, float strength, float damping) 2710 public void RotLookAt(Quaternion target, float strength, float damping)
2694 { 2711 {
2695 rotLookAt(target, strength, damping); 2712 m_parentGroup.rotLookAt(target, strength, damping); // This calls method in SceneObjectGroup.
2696 }
2697
2698 public void rotLookAt(Quaternion target, float strength, float damping)
2699 {
2700 if (IsAttachment)
2701 {
2702 /*
2703 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2704 if (avatar != null)
2705 {
2706 Rotate the Av?
2707 } */
2708 }
2709 else
2710 {
2711 APIDDamp = damping;
2712 APIDStrength = strength;
2713 APIDTarget = target;
2714 }
2715 }
2716
2717 public void startLookAt(Quaternion rot, float damp, float strength)
2718 {
2719 APIDDamp = damp;
2720 APIDStrength = strength;
2721 APIDTarget = rot;
2722 }
2723
2724 public void stopLookAt()
2725 {
2726 APIDTarget = Quaternion.Identity;
2727 } 2713 }
2728 2714
2729 /// <summary> 2715 /// <summary>
@@ -2952,8 +2938,8 @@ namespace OpenSim.Region.Framework.Scenes
2952 { 2938 {
2953 const float ROTATION_TOLERANCE = 0.01f; 2939 const float ROTATION_TOLERANCE = 0.01f;
2954 const float VELOCITY_TOLERANCE = 0.001f; 2940 const float VELOCITY_TOLERANCE = 0.001f;
2955 const float POSITION_TOLERANCE = 0.05f; 2941 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2956 const int TIME_MS_TOLERANCE = 3000; 2942 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2957 2943
2958 if (m_updateFlag == 1) 2944 if (m_updateFlag == 1)
2959 { 2945 {
@@ -2967,7 +2953,7 @@ namespace OpenSim.Region.Framework.Scenes
2967 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 2953 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
2968 { 2954 {
2969 AddTerseUpdateToAllAvatars(); 2955 AddTerseUpdateToAllAvatars();
2970 ClearUpdateSchedule(); 2956
2971 2957
2972 // This causes the Scene to 'poll' physical objects every couple of frames 2958 // This causes the Scene to 'poll' physical objects every couple of frames
2973 // bad, so it's been replaced by an event driven method. 2959 // bad, so it's been replaced by an event driven method.
@@ -2985,16 +2971,18 @@ namespace OpenSim.Region.Framework.Scenes
2985 m_lastAngularVelocity = AngularVelocity; 2971 m_lastAngularVelocity = AngularVelocity;
2986 m_lastTerseSent = Environment.TickCount; 2972 m_lastTerseSent = Environment.TickCount;
2987 } 2973 }
2974 //Moved this outside of the if clause so updates don't get blocked.. *sigh*
2975 m_updateFlag = 0; //Why were we calling a function to do this? Inefficient! *screams*
2988 } 2976 }
2989 else 2977 else
2990 { 2978 {
2991 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes 2979 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes
2992 { 2980 {
2993 AddFullUpdateToAllAvatars(); 2981 AddFullUpdateToAllAvatars();
2994 ClearUpdateSchedule(); 2982 m_updateFlag = 0; //Same here
2995 } 2983 }
2996 } 2984 }
2997 ClearUpdateSchedule(); 2985 m_updateFlag = 0;
2998 } 2986 }
2999 2987
3000 /// <summary> 2988 /// <summary>
@@ -3021,17 +3009,16 @@ namespace OpenSim.Region.Framework.Scenes
3021 if (!UUID.TryParse(sound, out soundID)) 3009 if (!UUID.TryParse(sound, out soundID))
3022 { 3010 {
3023 // search sound file from inventory 3011 // search sound file from inventory
3024 lock (TaskInventory) 3012 TaskInventory.LockItemsForRead(true);
3013 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
3025 { 3014 {
3026 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3015 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
3027 { 3016 {
3028 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3017 soundID = item.Value.ItemID;
3029 { 3018 break;
3030 soundID = item.Value.ItemID;
3031 break;
3032 }
3033 } 3019 }
3034 } 3020 }
3021 TaskInventory.LockItemsForRead(false);
3035 } 3022 }
3036 3023
3037 if (soundID == UUID.Zero) 3024 if (soundID == UUID.Zero)
@@ -3466,7 +3453,7 @@ namespace OpenSim.Region.Framework.Scenes
3466 3453
3467 public void StopLookAt() 3454 public void StopLookAt()
3468 { 3455 {
3469 m_parentGroup.stopLookAt(); 3456 m_parentGroup.stopLookAt(); // This calls method in SceneObjectGroup.
3470 3457
3471 m_parentGroup.ScheduleGroupForTerseUpdate(); 3458 m_parentGroup.ScheduleGroupForTerseUpdate();
3472 } 3459 }
@@ -4706,5 +4693,17 @@ namespace OpenSim.Region.Framework.Scenes
4706 Color color = Color; 4693 Color color = Color;
4707 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 4694 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4708 } 4695 }
4696
4697 public void ResetOwnerChangeFlag()
4698 {
4699 List<UUID> inv = Inventory.GetInventoryList();
4700
4701 foreach (UUID itemID in inv)
4702 {
4703 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
4704 item.OwnerChanged = false;
4705 Inventory.UpdateInventoryItem(item);
4706 }
4707 }
4709 } 4708 }
4710} 4709}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 8b83b06..c4cff12 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -45,6 +45,8 @@ namespace OpenSim.Region.Framework.Scenes
45 45
46 private string m_inventoryFileName = String.Empty; 46 private string m_inventoryFileName = String.Empty;
47 private int m_inventoryFileNameSerial = 0; 47 private int m_inventoryFileNameSerial = 0;
48
49 private Dictionary<UUID, ArrayList> m_scriptErrors = new Dictionary<UUID, ArrayList>();
48 50
49 /// <value> 51 /// <value>
50 /// The part to which the inventory belongs. 52 /// The part to which the inventory belongs.
@@ -81,7 +83,9 @@ namespace OpenSim.Region.Framework.Scenes
81 /// </value> 83 /// </value>
82 protected internal TaskInventoryDictionary Items 84 protected internal TaskInventoryDictionary Items
83 { 85 {
84 get { return m_items; } 86 get {
87 return m_items;
88 }
85 set 89 set
86 { 90 {
87 m_items = value; 91 m_items = value;
@@ -117,22 +121,25 @@ namespace OpenSim.Region.Framework.Scenes
117 /// <param name="linkNum">Link number for the part</param> 121 /// <param name="linkNum">Link number for the part</param>
118 public void ResetInventoryIDs() 122 public void ResetInventoryIDs()
119 { 123 {
120 lock (Items) 124 m_items.LockItemsForWrite(true);
125
126 if (0 == Items.Count)
121 { 127 {
122 if (0 == Items.Count) 128 m_items.LockItemsForWrite(false);
123 return; 129 return;
130 }
124 131
125 HasInventoryChanged = true; 132 HasInventoryChanged = true;
126 m_part.ParentGroup.HasGroupChanged = true; 133 m_part.ParentGroup.HasGroupChanged = true;
127 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 134 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
128 Items.Clear(); 135 Items.Clear();
129 136
130 foreach (TaskInventoryItem item in items) 137 foreach (TaskInventoryItem item in items)
131 { 138 {
132 item.ResetIDs(m_part.UUID); 139 item.ResetIDs(m_part.UUID);
133 Items.Add(item.ItemID, item); 140 Items.Add(item.ItemID, item);
134 }
135 } 141 }
142 m_items.LockItemsForWrite(false);
136 } 143 }
137 144
138 /// <summary> 145 /// <summary>
@@ -141,25 +148,25 @@ namespace OpenSim.Region.Framework.Scenes
141 /// <param name="ownerId"></param> 148 /// <param name="ownerId"></param>
142 public void ChangeInventoryOwner(UUID ownerId) 149 public void ChangeInventoryOwner(UUID ownerId)
143 { 150 {
144 lock (Items) 151 m_items.LockItemsForWrite(true);
152 if (0 == Items.Count)
145 { 153 {
146 if (0 == Items.Count) 154 m_items.LockItemsForWrite(false);
147 { 155 return;
148 return; 156 }
149 }
150 157
151 HasInventoryChanged = true; 158 HasInventoryChanged = true;
152 m_part.ParentGroup.HasGroupChanged = true; 159 m_part.ParentGroup.HasGroupChanged = true;
153 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 160 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
154 foreach (TaskInventoryItem item in items) 161 foreach (TaskInventoryItem item in items)
162 {
163 if (ownerId != item.OwnerID)
155 { 164 {
156 if (ownerId != item.OwnerID) 165 item.LastOwnerID = item.OwnerID;
157 { 166 item.OwnerID = ownerId;
158 item.LastOwnerID = item.OwnerID;
159 item.OwnerID = ownerId;
160 }
161 } 167 }
162 } 168 }
169 m_items.LockItemsForWrite(false);
163 } 170 }
164 171
165 /// <summary> 172 /// <summary>
@@ -168,24 +175,24 @@ namespace OpenSim.Region.Framework.Scenes
168 /// <param name="groupID"></param> 175 /// <param name="groupID"></param>
169 public void ChangeInventoryGroup(UUID groupID) 176 public void ChangeInventoryGroup(UUID groupID)
170 { 177 {
171 lock (Items) 178 m_items.LockItemsForWrite(true);
179 if (0 == Items.Count)
172 { 180 {
173 if (0 == Items.Count) 181 m_items.LockItemsForWrite(false);
174 { 182 return;
175 return; 183 }
176 }
177 184
178 HasInventoryChanged = true; 185 HasInventoryChanged = true;
179 m_part.ParentGroup.HasGroupChanged = true; 186 m_part.ParentGroup.HasGroupChanged = true;
180 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 187 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
181 foreach (TaskInventoryItem item in items) 188 foreach (TaskInventoryItem item in items)
189 {
190 if (groupID != item.GroupID)
182 { 191 {
183 if (groupID != item.GroupID) 192 item.GroupID = groupID;
184 {
185 item.GroupID = groupID;
186 }
187 } 193 }
188 } 194 }
195 m_items.LockItemsForWrite(false);
189 } 196 }
190 197
191 /// <summary> 198 /// <summary>
@@ -193,14 +200,14 @@ namespace OpenSim.Region.Framework.Scenes
193 /// </summary> 200 /// </summary>
194 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) 201 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
195 { 202 {
196 lock (m_items) 203 Items.LockItemsForRead(true);
204 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
205 Items.LockItemsForRead(false);
206 foreach (TaskInventoryItem item in items)
197 { 207 {
198 foreach (TaskInventoryItem item in Items.Values) 208 if ((int)InventoryType.LSL == item.InvType)
199 { 209 {
200 if ((int)InventoryType.LSL == item.InvType) 210 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
201 {
202 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
203 }
204 } 211 }
205 } 212 }
206 } 213 }
@@ -235,16 +242,20 @@ namespace OpenSim.Region.Framework.Scenes
235 /// </param> 242 /// </param>
236 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 243 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
237 { 244 {
238 lock (Items) 245 Items.LockItemsForRead(true);
246 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
247 Items.LockItemsForRead(false);
248
249 foreach (TaskInventoryItem item in items)
239 { 250 {
240 foreach (TaskInventoryItem item in Items.Values) 251 if ((int)InventoryType.LSL == item.InvType)
241 { 252 {
242 if ((int)InventoryType.LSL == item.InvType) 253 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
243 { 254 m_part.RemoveScriptEvents(item.ItemID);
244 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
245 }
246 } 255 }
247 } 256 }
257
258
248 } 259 }
249 260
250 /// <summary> 261 /// <summary>
@@ -260,7 +271,10 @@ namespace OpenSim.Region.Framework.Scenes
260 // item.Name, item.ItemID, Name, UUID); 271 // item.Name, item.ItemID, Name, UUID);
261 272
262 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) 273 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID))
274 {
275 StoreScriptError(item.ItemID, "no permission");
263 return; 276 return;
277 }
264 278
265 m_part.AddFlag(PrimFlags.Scripted); 279 m_part.AddFlag(PrimFlags.Scripted);
266 280
@@ -269,14 +283,13 @@ namespace OpenSim.Region.Framework.Scenes
269 if (stateSource == 1 && // Prim crossing 283 if (stateSource == 1 && // Prim crossing
270 m_part.ParentGroup.Scene.m_trustBinaries) 284 m_part.ParentGroup.Scene.m_trustBinaries)
271 { 285 {
272 lock (m_items) 286 m_items.LockItemsForWrite(true);
273 { 287 m_items[item.ItemID].PermsMask = 0;
274 m_items[item.ItemID].PermsMask = 0; 288 m_items[item.ItemID].PermsGranter = UUID.Zero;
275 m_items[item.ItemID].PermsGranter = UUID.Zero; 289 m_items.LockItemsForWrite(false);
276 }
277
278 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 290 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
279 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 291 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
292 StoreScriptErrors(item.ItemID, null);
280 m_part.ParentGroup.AddActiveScriptCount(1); 293 m_part.ParentGroup.AddActiveScriptCount(1);
281 m_part.ScheduleFullUpdate(); 294 m_part.ScheduleFullUpdate();
282 return; 295 return;
@@ -285,6 +298,8 @@ namespace OpenSim.Region.Framework.Scenes
285 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 298 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
286 if (null == asset) 299 if (null == asset)
287 { 300 {
301 string msg = String.Format("asset ID {0} could not be found", item.AssetID);
302 StoreScriptError(item.ItemID, msg);
288 m_log.ErrorFormat( 303 m_log.ErrorFormat(
289 "[PRIM INVENTORY]: " + 304 "[PRIM INVENTORY]: " +
290 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", 305 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
@@ -296,15 +311,17 @@ namespace OpenSim.Region.Framework.Scenes
296 if (m_part.ParentGroup.m_savedScriptState != null) 311 if (m_part.ParentGroup.m_savedScriptState != null)
297 RestoreSavedScriptState(item.OldItemID, item.ItemID); 312 RestoreSavedScriptState(item.OldItemID, item.ItemID);
298 313
299 lock (m_items) 314 m_items.LockItemsForWrite(true);
300 { 315
301 m_items[item.ItemID].PermsMask = 0; 316 m_items[item.ItemID].PermsMask = 0;
302 m_items[item.ItemID].PermsGranter = UUID.Zero; 317 m_items[item.ItemID].PermsGranter = UUID.Zero;
303 } 318
319 m_items.LockItemsForWrite(false);
304 320
305 string script = Utils.BytesToString(asset.Data); 321 string script = Utils.BytesToString(asset.Data);
306 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 322 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
307 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 323 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
324 StoreScriptErrors(item.ItemID, null);
308 m_part.ParentGroup.AddActiveScriptCount(1); 325 m_part.ParentGroup.AddActiveScriptCount(1);
309 m_part.ScheduleFullUpdate(); 326 m_part.ScheduleFullUpdate();
310 } 327 }
@@ -368,27 +385,145 @@ namespace OpenSim.Region.Framework.Scenes
368 385
369 /// <summary> 386 /// <summary>
370 /// Start a script which is in this prim's inventory. 387 /// Start a script which is in this prim's inventory.
388 /// Some processing may occur in the background, but this routine returns asap.
371 /// </summary> 389 /// </summary>
372 /// <param name="itemId"> 390 /// <param name="itemId">
373 /// A <see cref="UUID"/> 391 /// A <see cref="UUID"/>
374 /// </param> 392 /// </param>
375 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 393 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
376 { 394 {
377 lock (m_items) 395 lock (m_scriptErrors)
396 {
397 // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion
398 m_scriptErrors.Remove(itemId);
399 }
400 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
401 }
402
403 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
404 {
405 m_items.LockItemsForRead(true);
406 if (m_items.ContainsKey(itemId))
378 { 407 {
379 if (m_items.ContainsKey(itemId)) 408 if (m_items.ContainsKey(itemId))
380 { 409 {
410 m_items.LockItemsForRead(false);
381 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource); 411 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource);
382 } 412 }
383 else 413 else
384 { 414 {
415 m_items.LockItemsForRead(false);
416 string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID,
417 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
418 StoreScriptError(itemId, msg);
385 m_log.ErrorFormat( 419 m_log.ErrorFormat(
386 "[PRIM INVENTORY]: " + 420 "[PRIM INVENTORY]: " +
387 "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 421 "Couldn't start script with ID {0} since it {1}", itemId, msg);
388 itemId, m_part.Name, m_part.UUID,
389 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
390 } 422 }
391 } 423 }
424 else
425 {
426 m_items.LockItemsForRead(false);
427 string msg = String.Format("couldn't be found for prim {0}, {1}", m_part.Name, m_part.UUID);
428 StoreScriptError(itemId, msg);
429 m_log.ErrorFormat(
430 "[PRIM INVENTORY]: " +
431 "Couldn't start script with ID {0} since it {1}", itemId, msg);
432 }
433
434 }
435
436 /// <summary>
437 /// Start a script which is in this prim's inventory and return any compilation error messages.
438 /// </summary>
439 /// <param name="itemId">
440 /// A <see cref="UUID"/>
441 /// </param>
442 public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
443 {
444 ArrayList errors;
445
446 // Indicate to CreateScriptInstanceInternal() we want it to
447 // post any compilation/loading error messages
448 lock (m_scriptErrors)
449 {
450 m_scriptErrors[itemId] = null;
451 }
452
453 // Perform compilation/loading
454 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
455
456 // Wait for and retrieve any errors
457 lock (m_scriptErrors)
458 {
459 while ((errors = m_scriptErrors[itemId]) == null)
460 {
461 if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000))
462 {
463 m_log.ErrorFormat(
464 "[PRIM INVENTORY]: " +
465 "timedout waiting for script {0} errors", itemId);
466 errors = m_scriptErrors[itemId];
467 if (errors == null)
468 {
469 errors = new ArrayList(1);
470 errors.Add("timedout waiting for errors");
471 }
472 break;
473 }
474 }
475 m_scriptErrors.Remove(itemId);
476 }
477 return errors;
478 }
479
480 // Signal to CreateScriptInstanceEr() that compilation/loading is complete
481 private void StoreScriptErrors(UUID itemId, ArrayList errors)
482 {
483 lock (m_scriptErrors)
484 {
485 // If compilation/loading initiated via CreateScriptInstance(),
486 // it does not want the errors, so just get out
487 if (!m_scriptErrors.ContainsKey(itemId))
488 {
489 return;
490 }
491
492 // Initiated via CreateScriptInstanceEr(), if we know what the
493 // errors are, save them and wake CreateScriptInstanceEr().
494 if (errors != null)
495 {
496 m_scriptErrors[itemId] = errors;
497 System.Threading.Monitor.PulseAll(m_scriptErrors);
498 return;
499 }
500 }
501
502 // Initiated via CreateScriptInstanceEr() but we don't know what
503 // the errors are yet, so retrieve them from the script engine.
504 // This may involve some waiting internal to GetScriptErrors().
505 errors = GetScriptErrors(itemId);
506
507 // Get a default non-null value to indicate success.
508 if (errors == null)
509 {
510 errors = new ArrayList();
511 }
512
513 // Post to CreateScriptInstanceEr() and wake it up
514 lock (m_scriptErrors)
515 {
516 m_scriptErrors[itemId] = errors;
517 System.Threading.Monitor.PulseAll(m_scriptErrors);
518 }
519 }
520
521 // Like StoreScriptErrors(), but just posts a single string message
522 private void StoreScriptError(UUID itemId, string message)
523 {
524 ArrayList errors = new ArrayList(1);
525 errors.Add(message);
526 StoreScriptErrors(itemId, errors);
392 } 527 }
393 528
394 /// <summary> 529 /// <summary>
@@ -401,15 +536,7 @@ namespace OpenSim.Region.Framework.Scenes
401 /// </param> 536 /// </param>
402 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted) 537 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
403 { 538 {
404 bool scriptPresent = false; 539 if (m_items.ContainsKey(itemId))
405
406 lock (m_items)
407 {
408 if (m_items.ContainsKey(itemId))
409 scriptPresent = true;
410 }
411
412 if (scriptPresent)
413 { 540 {
414 if (!sceneObjectBeingDeleted) 541 if (!sceneObjectBeingDeleted)
415 m_part.RemoveScriptEvents(itemId); 542 m_part.RemoveScriptEvents(itemId);
@@ -435,11 +562,16 @@ namespace OpenSim.Region.Framework.Scenes
435 /// <returns></returns> 562 /// <returns></returns>
436 private bool InventoryContainsName(string name) 563 private bool InventoryContainsName(string name)
437 { 564 {
438 foreach (TaskInventoryItem item in Items.Values) 565 m_items.LockItemsForRead(true);
566 foreach (TaskInventoryItem item in m_items.Values)
439 { 567 {
440 if (item.Name == name) 568 if (item.Name == name)
569 {
570 m_items.LockItemsForRead(false);
441 return true; 571 return true;
572 }
442 } 573 }
574 m_items.LockItemsForRead(false);
443 return false; 575 return false;
444 } 576 }
445 577
@@ -481,13 +613,9 @@ namespace OpenSim.Region.Framework.Scenes
481 /// <param name="item"></param> 613 /// <param name="item"></param>
482 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 614 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
483 { 615 {
484 List<TaskInventoryItem> il; 616 m_items.LockItemsForRead(true);
485 617 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
486 lock (m_items) 618 m_items.LockItemsForRead(false);
487 {
488 il = new List<TaskInventoryItem>(m_items.Values);
489 }
490
491 foreach (TaskInventoryItem i in il) 619 foreach (TaskInventoryItem i in il)
492 { 620 {
493 if (i.Name == item.Name) 621 if (i.Name == item.Name)
@@ -525,15 +653,14 @@ namespace OpenSim.Region.Framework.Scenes
525 item.Name = name; 653 item.Name = name;
526 item.GroupID = m_part.GroupID; 654 item.GroupID = m_part.GroupID;
527 655
528 lock (m_items) 656 m_items.LockItemsForWrite(true);
529 { 657 m_items.Add(item.ItemID, item);
530 m_items.Add(item.ItemID, item); 658 m_items.LockItemsForWrite(false);
531
532 if (allowedDrop) 659 if (allowedDrop)
533 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 660 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
534 else 661 else
535 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 662 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
536 } 663
537 664
538 m_inventorySerial++; 665 m_inventorySerial++;
539 //m_inventorySerial += 2; 666 //m_inventorySerial += 2;
@@ -550,14 +677,13 @@ namespace OpenSim.Region.Framework.Scenes
550 /// <param name="items"></param> 677 /// <param name="items"></param>
551 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 678 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
552 { 679 {
553 lock (m_items) 680 m_items.LockItemsForWrite(true);
681 foreach (TaskInventoryItem item in items)
554 { 682 {
555 foreach (TaskInventoryItem item in items) 683 m_items.Add(item.ItemID, item);
556 { 684 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
557 m_items.Add(item.ItemID, item);
558 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
559 }
560 } 685 }
686 m_items.LockItemsForWrite(false);
561 687
562 m_inventorySerial++; 688 m_inventorySerial++;
563 } 689 }
@@ -570,10 +696,9 @@ namespace OpenSim.Region.Framework.Scenes
570 public TaskInventoryItem GetInventoryItem(UUID itemId) 696 public TaskInventoryItem GetInventoryItem(UUID itemId)
571 { 697 {
572 TaskInventoryItem item; 698 TaskInventoryItem item;
573 699 m_items.LockItemsForRead(true);
574 lock (m_items) 700 m_items.TryGetValue(itemId, out item);
575 m_items.TryGetValue(itemId, out item); 701 m_items.LockItemsForRead(false);
576
577 return item; 702 return item;
578 } 703 }
579 704
@@ -589,15 +714,16 @@ namespace OpenSim.Region.Framework.Scenes
589 { 714 {
590 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(); 715 IList<TaskInventoryItem> items = new List<TaskInventoryItem>();
591 716
592 lock (m_items) 717 m_items.LockItemsForRead(true);
718
719 foreach (TaskInventoryItem item in m_items.Values)
593 { 720 {
594 foreach (TaskInventoryItem item in m_items.Values) 721 if (item.Name == name)
595 { 722 items.Add(item);
596 if (item.Name == name)
597 items.Add(item);
598 }
599 } 723 }
600 724
725 m_items.LockItemsForRead(false);
726
601 return items; 727 return items;
602 } 728 }
603 729
@@ -614,45 +740,54 @@ namespace OpenSim.Region.Framework.Scenes
614 740
615 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents) 741 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents)
616 { 742 {
617 lock(m_items) 743 m_items.LockItemsForWrite(true);
744
745 if (m_items.ContainsKey(item.ItemID))
618 { 746 {
619 if (m_items.ContainsKey(item.ItemID)) 747 item.ParentID = m_part.UUID;
748 item.ParentPartID = m_part.UUID;
749 item.Flags = m_items[item.ItemID].Flags;
750
751 // If group permissions have been set on, check that the groupID is up to date in case it has
752 // changed since permissions were last set.
753 if (item.GroupPermissions != (uint)PermissionMask.None)
754 item.GroupID = m_part.GroupID;
755
756 if (item.AssetID == UUID.Zero)
620 { 757 {
621 if (m_items.ContainsKey(item.ItemID)) 758 item.AssetID = m_items[item.ItemID].AssetID;
622 { 759 }
623 item.ParentID = m_part.UUID; 760 else if ((InventoryType)item.Type == InventoryType.Notecard)
624 item.ParentPartID = m_part.UUID; 761 {
625 item.Flags = m_items[item.ItemID].Flags; 762 ScenePresence presence = m_part.ParentGroup.Scene.GetScenePresence(item.OwnerID);
626 763
627 // If group permissions have been set on, check that the groupID is up to date in case it has 764 if (presence != null)
628 // changed since permissions were last set.
629 if (item.GroupPermissions != (uint)PermissionMask.None)
630 item.GroupID = m_part.GroupID;
631
632 if (item.AssetID == UUID.Zero)
633 {
634 item.AssetID = m_items[item.ItemID].AssetID;
635 }
636 m_items[item.ItemID] = item;
637 m_inventorySerial++;
638 if (fireScriptEvents)
639 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
640 HasInventoryChanged = true;
641 m_part.ParentGroup.HasGroupChanged = true;
642 return true;
643 }
644 else
645 { 765 {
646 m_log.ErrorFormat( 766 presence.ControllingClient.SendAgentAlertMessage(
647 "[PRIM INVENTORY]: " + 767 "Notecard saved", false);
648 "Tried to retrieve item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory",
649 item.ItemID, m_part.Name, m_part.UUID,
650 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
651 } 768 }
652
653 } 769 }
654 return false; 770
771 m_items[item.ItemID] = item;
772 m_inventorySerial++;
773 if (fireScriptEvents)
774 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
775 HasInventoryChanged = true;
776 m_part.ParentGroup.HasGroupChanged = true;
777 m_items.LockItemsForWrite(false);
778 return true;
655 } 779 }
780 else
781 {
782 m_log.ErrorFormat(
783 "[PRIM INVENTORY]: " +
784 "Tried to retrieve item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory",
785 item.ItemID, m_part.Name, m_part.UUID,
786 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
787 }
788 m_items.LockItemsForWrite(false);
789
790 return false;
656 } 791 }
657 792
658 /// <summary> 793 /// <summary>
@@ -663,52 +798,53 @@ namespace OpenSim.Region.Framework.Scenes
663 /// in this prim's inventory.</returns> 798 /// in this prim's inventory.</returns>
664 public int RemoveInventoryItem(UUID itemID) 799 public int RemoveInventoryItem(UUID itemID)
665 { 800 {
666 lock (m_items) 801 m_items.LockItemsForRead(true);
802
803 if (m_items.ContainsKey(itemID))
667 { 804 {
668 if (m_items.ContainsKey(itemID)) 805 int type = m_items[itemID].InvType;
806 m_items.LockItemsForRead(false);
807 if (type == 10) // Script
669 { 808 {
670 int type = m_items[itemID].InvType; 809 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
671 if (type == 10) // Script 810 }
672 { 811 m_items.LockItemsForWrite(true);
673 m_part.RemoveScriptEvents(itemID); 812 m_items.Remove(itemID);
674 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 813 m_items.LockItemsForWrite(false);
675 } 814 m_inventorySerial++;
676 m_items.Remove(itemID); 815 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
677 m_inventorySerial++;
678 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
679
680 HasInventoryChanged = true;
681 m_part.ParentGroup.HasGroupChanged = true;
682 816
683 int scriptcount = 0; 817 HasInventoryChanged = true;
684 lock (m_items) 818 m_part.ParentGroup.HasGroupChanged = true;
685 {
686 foreach (TaskInventoryItem item in m_items.Values)
687 {
688 if (item.Type == 10)
689 {
690 scriptcount++;
691 }
692 }
693 }
694 819
695 if (scriptcount <= 0) 820 int scriptcount = 0;
821 m_items.LockItemsForRead(true);
822 foreach (TaskInventoryItem item in m_items.Values)
823 {
824 if (item.Type == 10)
696 { 825 {
697 m_part.RemFlag(PrimFlags.Scripted); 826 scriptcount++;
698 } 827 }
699
700 m_part.ScheduleFullUpdate();
701
702 return type;
703 } 828 }
704 else 829 m_items.LockItemsForRead(false);
830
831
832 if (scriptcount <= 0)
705 { 833 {
706 m_log.ErrorFormat( 834 m_part.RemFlag(PrimFlags.Scripted);
707 "[PRIM INVENTORY]: " +
708 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory",
709 itemID, m_part.Name, m_part.UUID,
710 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
711 } 835 }
836
837 m_part.ScheduleFullUpdate();
838
839 return type;
840 }
841 else
842 {
843 m_items.LockItemsForRead(false);
844 m_log.ErrorFormat(
845 "[PRIM INVENTORY]: " +
846 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
847 itemID, m_part.Name, m_part.UUID);
712 } 848 }
713 849
714 return -1; 850 return -1;
@@ -762,53 +898,54 @@ namespace OpenSim.Region.Framework.Scenes
762 // isn't available (such as drag from prim inventory to agent inventory) 898 // isn't available (such as drag from prim inventory to agent inventory)
763 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); 899 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
764 900
765 lock (m_items) 901 m_items.LockItemsForRead(true);
902
903 foreach (TaskInventoryItem item in m_items.Values)
766 { 904 {
767 foreach (TaskInventoryItem item in m_items.Values) 905 UUID ownerID = item.OwnerID;
768 { 906 uint everyoneMask = 0;
769 UUID ownerID = item.OwnerID; 907 uint baseMask = item.BasePermissions;
770 uint everyoneMask = 0; 908 uint ownerMask = item.CurrentPermissions;
771 uint baseMask = item.BasePermissions; 909 uint groupMask = item.GroupPermissions;
772 uint ownerMask = item.CurrentPermissions;
773 uint groupMask = item.GroupPermissions;
774 910
775 invString.AddItemStart(); 911 invString.AddItemStart();
776 invString.AddNameValueLine("item_id", item.ItemID.ToString()); 912 invString.AddNameValueLine("item_id", item.ItemID.ToString());
777 invString.AddNameValueLine("parent_id", m_part.UUID.ToString()); 913 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
778 914
779 invString.AddPermissionsStart(); 915 invString.AddPermissionsStart();
780 916
781 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); 917 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
782 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); 918 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
783 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask)); 919 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
784 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask)); 920 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
785 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions)); 921 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
786 922
787 invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); 923 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
788 invString.AddNameValueLine("owner_id", ownerID.ToString()); 924 invString.AddNameValueLine("owner_id", ownerID.ToString());
789 925
790 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); 926 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
791 927
792 invString.AddNameValueLine("group_id", item.GroupID.ToString()); 928 invString.AddNameValueLine("group_id", item.GroupID.ToString());
793 invString.AddSectionEnd(); 929 invString.AddSectionEnd();
794 930
795 invString.AddNameValueLine("asset_id", item.AssetID.ToString()); 931 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
796 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]); 932 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]);
797 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]); 933 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]);
798 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags)); 934 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
799 935
800 invString.AddSaleStart(); 936 invString.AddSaleStart();
801 invString.AddNameValueLine("sale_type", "not"); 937 invString.AddNameValueLine("sale_type", "not");
802 invString.AddNameValueLine("sale_price", "0"); 938 invString.AddNameValueLine("sale_price", "0");
803 invString.AddSectionEnd(); 939 invString.AddSectionEnd();
804 940
805 invString.AddNameValueLine("name", item.Name + "|"); 941 invString.AddNameValueLine("name", item.Name + "|");
806 invString.AddNameValueLine("desc", item.Description + "|"); 942 invString.AddNameValueLine("desc", item.Description + "|");
807 943
808 invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); 944 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
809 invString.AddSectionEnd(); 945 invString.AddSectionEnd();
810 }
811 } 946 }
947 int count = m_items.Count;
948 m_items.LockItemsForRead(false);
812 949
813 fileData = Utils.StringToBytes(invString.BuildString); 950 fileData = Utils.StringToBytes(invString.BuildString);
814 951
@@ -829,10 +966,9 @@ namespace OpenSim.Region.Framework.Scenes
829 { 966 {
830 if (HasInventoryChanged) 967 if (HasInventoryChanged)
831 { 968 {
832 lock (Items) 969 Items.LockItemsForRead(true);
833 { 970 datastore.StorePrimInventory(m_part.UUID, Items.Values);
834 datastore.StorePrimInventory(m_part.UUID, Items.Values); 971 Items.LockItemsForRead(false);
835 }
836 972
837 HasInventoryChanged = false; 973 HasInventoryChanged = false;
838 } 974 }
@@ -901,90 +1037,76 @@ namespace OpenSim.Region.Framework.Scenes
901 { 1037 {
902 uint mask=0x7fffffff; 1038 uint mask=0x7fffffff;
903 1039
904 lock (m_items) 1040 foreach (TaskInventoryItem item in m_items.Values)
905 { 1041 {
906 foreach (TaskInventoryItem item in m_items.Values) 1042 if (item.InvType != (int)InventoryType.Object)
907 { 1043 {
908 if (item.InvType != (int)InventoryType.Object) 1044 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
909 { 1045 mask &= ~((uint)PermissionMask.Copy >> 13);
910 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1046 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
911 mask &= ~((uint)PermissionMask.Copy >> 13); 1047 mask &= ~((uint)PermissionMask.Transfer >> 13);
912 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1048 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
913 mask &= ~((uint)PermissionMask.Transfer >> 13); 1049 mask &= ~((uint)PermissionMask.Modify >> 13);
914 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) 1050 }
915 mask &= ~((uint)PermissionMask.Modify >> 13); 1051 else
916 } 1052 {
917 else 1053 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
918 { 1054 mask &= ~((uint)PermissionMask.Copy >> 13);
919 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) 1055 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
920 mask &= ~((uint)PermissionMask.Copy >> 13); 1056 mask &= ~((uint)PermissionMask.Transfer >> 13);
921 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) 1057 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
922 mask &= ~((uint)PermissionMask.Transfer >> 13); 1058 mask &= ~((uint)PermissionMask.Modify >> 13);
923 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
924 mask &= ~((uint)PermissionMask.Modify >> 13);
925 }
926
927 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
928 mask &= ~(uint)PermissionMask.Copy;
929 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
930 mask &= ~(uint)PermissionMask.Transfer;
931 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
932 mask &= ~(uint)PermissionMask.Modify;
933 } 1059 }
1060
1061 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1062 mask &= ~(uint)PermissionMask.Copy;
1063 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1064 mask &= ~(uint)PermissionMask.Transfer;
1065 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1066 mask &= ~(uint)PermissionMask.Modify;
934 } 1067 }
935
936 return mask; 1068 return mask;
937 } 1069 }
938 1070
939 public void ApplyNextOwnerPermissions() 1071 public void ApplyNextOwnerPermissions()
940 { 1072 {
941 lock (m_items) 1073 foreach (TaskInventoryItem item in m_items.Values)
942 { 1074 {
943 foreach (TaskInventoryItem item in m_items.Values) 1075 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
944 { 1076 {
945 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) 1077 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
946 { 1078 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
947 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) 1079 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
948 item.CurrentPermissions &= ~(uint)PermissionMask.Copy; 1080 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
949 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) 1081 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
950 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; 1082 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
951 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0) 1083 item.CurrentPermissions |= 8;
952 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
953 item.CurrentPermissions |= 8;
954 }
955 item.CurrentPermissions &= item.NextPermissions;
956 item.BasePermissions &= item.NextPermissions;
957 item.EveryonePermissions &= item.NextPermissions;
958 item.OwnerChanged = true;
959 } 1084 }
1085 item.OwnerChanged = true;
1086 item.CurrentPermissions &= item.NextPermissions;
1087 item.BasePermissions &= item.NextPermissions;
1088 item.EveryonePermissions &= item.NextPermissions;
960 } 1089 }
961 } 1090 }
962 1091
963 public void ApplyGodPermissions(uint perms) 1092 public void ApplyGodPermissions(uint perms)
964 { 1093 {
965 lock (m_items) 1094 foreach (TaskInventoryItem item in m_items.Values)
966 { 1095 {
967 foreach (TaskInventoryItem item in m_items.Values) 1096 item.CurrentPermissions = perms;
968 { 1097 item.BasePermissions = perms;
969 item.CurrentPermissions = perms;
970 item.BasePermissions = perms;
971 }
972 } 1098 }
973 } 1099 }
974 1100
975 public bool ContainsScripts() 1101 public bool ContainsScripts()
976 { 1102 {
977 lock (m_items) 1103 foreach (TaskInventoryItem item in m_items.Values)
978 { 1104 {
979 foreach (TaskInventoryItem item in m_items.Values) 1105 if (item.InvType == (int)InventoryType.LSL)
980 { 1106 {
981 if (item.InvType == (int)InventoryType.LSL) 1107 return true;
982 {
983 return true;
984 }
985 } 1108 }
986 } 1109 }
987
988 return false; 1110 return false;
989 } 1111 }
990 1112
@@ -992,46 +1114,52 @@ namespace OpenSim.Region.Framework.Scenes
992 { 1114 {
993 List<UUID> ret = new List<UUID>(); 1115 List<UUID> ret = new List<UUID>();
994 1116
995 lock (m_items) 1117 foreach (TaskInventoryItem item in m_items.Values)
996 { 1118 ret.Add(item.ItemID);
997 foreach (TaskInventoryItem item in m_items.Values)
998 ret.Add(item.ItemID);
999 }
1000 1119
1001 return ret; 1120 return ret;
1002 } 1121 }
1003 1122
1004 public Dictionary<UUID, string> GetScriptStates() 1123 public Dictionary<UUID, string> GetScriptStates()
1005 { 1124 {
1125 return GetScriptStates(false);
1126 }
1127
1128 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1129 {
1006 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>(); 1130 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
1007 1131
1008 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1132 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1009 if (engines == null) // No engine at all 1133 if (engines == null) // No engine at all
1010 return ret; 1134 return ret;
1011 1135
1012 lock (m_items) 1136 foreach (TaskInventoryItem item in m_items.Values)
1013 { 1137 {
1014 foreach (TaskInventoryItem item in m_items.Values) 1138 if (item.InvType == (int)InventoryType.LSL)
1015 { 1139 {
1016 if (item.InvType == (int)InventoryType.LSL) 1140 foreach (IScriptModule e in engines)
1017 { 1141 {
1018 foreach (IScriptModule e in engines) 1142 if (e != null)
1019 { 1143 {
1020 if (e != null) 1144 string n = e.GetXMLState(item.ItemID);
1145 if (n != String.Empty)
1021 { 1146 {
1022 string n = e.GetXMLState(item.ItemID); 1147 if (oldIDs)
1023 if (n != String.Empty) 1148 {
1149 if (!ret.ContainsKey(item.OldItemID))
1150 ret[item.OldItemID] = n;
1151 }
1152 else
1024 { 1153 {
1025 if (!ret.ContainsKey(item.ItemID)) 1154 if (!ret.ContainsKey(item.ItemID))
1026 ret[item.ItemID] = n; 1155 ret[item.ItemID] = n;
1027 break;
1028 } 1156 }
1157 break;
1029 } 1158 }
1030 } 1159 }
1031 } 1160 }
1032 } 1161 }
1033 } 1162 }
1034
1035 return ret; 1163 return ret;
1036 } 1164 }
1037 1165
@@ -1041,25 +1169,27 @@ namespace OpenSim.Region.Framework.Scenes
1041 if (engines == null) 1169 if (engines == null)
1042 return; 1170 return;
1043 1171
1044 lock (m_items) 1172
1173 Items.LockItemsForRead(true);
1174
1175 foreach (TaskInventoryItem item in m_items.Values)
1045 { 1176 {
1046 foreach (TaskInventoryItem item in m_items.Values) 1177 if (item.InvType == (int)InventoryType.LSL)
1047 { 1178 {
1048 if (item.InvType == (int)InventoryType.LSL) 1179 foreach (IScriptModule engine in engines)
1049 { 1180 {
1050 foreach (IScriptModule engine in engines) 1181 if (engine != null)
1051 { 1182 {
1052 if (engine != null) 1183 if (item.OwnerChanged)
1053 { 1184 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER });
1054 if (item.OwnerChanged) 1185 item.OwnerChanged = false;
1055 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER }); 1186 engine.ResumeScript(item.ItemID);
1056 item.OwnerChanged = false;
1057 engine.ResumeScript(item.ItemID);
1058 }
1059 } 1187 }
1060 } 1188 }
1061 } 1189 }
1062 } 1190 }
1191
1192 Items.LockItemsForRead(false);
1063 } 1193 }
1064 } 1194 }
1065} 1195}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index ee0eb07..179ecdc 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Xml;
29using System.Collections.Generic; 30using System.Collections.Generic;
30using System.Reflection; 31using System.Reflection;
31using System.Timers; 32using System.Timers;
@@ -73,7 +74,7 @@ namespace OpenSim.Region.Framework.Scenes
73// { 74// {
74// m_log.Debug("[ScenePresence] Destructor called"); 75// m_log.Debug("[ScenePresence] Destructor called");
75// } 76// }
76 77
77 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 78 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
78 79
79 private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 }; 80 private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 };
@@ -89,7 +90,9 @@ namespace OpenSim.Region.Framework.Scenes
89 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis 90 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis
90 /// issue #1716 91 /// issue #1716
91 /// </summary> 92 /// </summary>
92 private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f); 93// private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f);
94 // Value revised by KF 091121 by comparison with SL.
95 private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f);
93 96
94 public UUID currentParcelUUID = UUID.Zero; 97 public UUID currentParcelUUID = UUID.Zero;
95 98
@@ -123,8 +126,11 @@ namespace OpenSim.Region.Framework.Scenes
123 public Vector3 lastKnownAllowedPosition; 126 public Vector3 lastKnownAllowedPosition;
124 public bool sentMessageAboutRestrictedParcelFlyingDown; 127 public bool sentMessageAboutRestrictedParcelFlyingDown;
125 public Vector4 CollisionPlane = Vector4.UnitW; 128 public Vector4 CollisionPlane = Vector4.UnitW;
126 129
130 private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation
131 private Vector3 m_avUnscriptedSitPos; // for non-scripted prims
127 private Vector3 m_lastPosition; 132 private Vector3 m_lastPosition;
133 private Vector3 m_lastWorldPosition;
128 private Quaternion m_lastRotation; 134 private Quaternion m_lastRotation;
129 private Vector3 m_lastVelocity; 135 private Vector3 m_lastVelocity;
130 //private int m_lastTerseSent; 136 //private int m_lastTerseSent;
@@ -134,7 +140,6 @@ namespace OpenSim.Region.Framework.Scenes
134 private Vector3? m_forceToApply; 140 private Vector3? m_forceToApply;
135 private uint m_requestedSitTargetID; 141 private uint m_requestedSitTargetID;
136 private UUID m_requestedSitTargetUUID; 142 private UUID m_requestedSitTargetUUID;
137 public bool SitGround = false;
138 143
139 private SendCourseLocationsMethod m_sendCourseLocationsMethod; 144 private SendCourseLocationsMethod m_sendCourseLocationsMethod;
140 145
@@ -157,7 +162,6 @@ namespace OpenSim.Region.Framework.Scenes
157 private int m_perfMonMS; 162 private int m_perfMonMS;
158 163
159 private bool m_setAlwaysRun; 164 private bool m_setAlwaysRun;
160
161 private bool m_forceFly; 165 private bool m_forceFly;
162 private bool m_flyDisabled; 166 private bool m_flyDisabled;
163 167
@@ -183,7 +187,8 @@ namespace OpenSim.Region.Framework.Scenes
183 protected RegionInfo m_regionInfo; 187 protected RegionInfo m_regionInfo;
184 protected ulong crossingFromRegion; 188 protected ulong crossingFromRegion;
185 189
186 private readonly Vector3[] Dir_Vectors = new Vector3[9]; 190 private readonly Vector3[] Dir_Vectors = new Vector3[11];
191 private bool m_isNudging = false;
187 192
188 // Position of agent's camera in world (region cordinates) 193 // Position of agent's camera in world (region cordinates)
189 protected Vector3 m_CameraCenter; 194 protected Vector3 m_CameraCenter;
@@ -208,6 +213,7 @@ namespace OpenSim.Region.Framework.Scenes
208 private bool m_autopilotMoving; 213 private bool m_autopilotMoving;
209 private Vector3 m_autoPilotTarget; 214 private Vector3 m_autoPilotTarget;
210 private bool m_sitAtAutoTarget; 215 private bool m_sitAtAutoTarget;
216 private Vector3 m_initialSitTarget = Vector3.Zero; //KF: First estimate of where to sit
211 217
212 private string m_nextSitAnimation = String.Empty; 218 private string m_nextSitAnimation = String.Empty;
213 219
@@ -218,6 +224,9 @@ namespace OpenSim.Region.Framework.Scenes
218 private bool m_followCamAuto; 224 private bool m_followCamAuto;
219 225
220 private int m_movementUpdateCount; 226 private int m_movementUpdateCount;
227 private int m_lastColCount = -1; //KF: Look for Collision chnages
228 private int m_updateCount = 0; //KF: Update Anims for a while
229 private static readonly int UPDATE_COUNT = 10; // how many frames to update for
221 private const int NumMovementsBetweenRayCast = 5; 230 private const int NumMovementsBetweenRayCast = 5;
222 231
223 private bool CameraConstraintActive; 232 private bool CameraConstraintActive;
@@ -245,7 +254,9 @@ namespace OpenSim.Region.Framework.Scenes
245 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, 254 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
246 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, 255 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
247 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS, 256 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS,
248 DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, 257 DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
258 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
259 DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
249 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG 260 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
250 } 261 }
251 262
@@ -452,7 +463,8 @@ namespace OpenSim.Region.Framework.Scenes
452 get 463 get
453 { 464 {
454 PhysicsActor actor = m_physicsActor; 465 PhysicsActor actor = m_physicsActor;
455 if (actor != null) 466// if (actor != null)
467 if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting!
456 m_pos = actor.Position; 468 m_pos = actor.Position;
457 469
458 return m_parentPosition + m_pos; 470 return m_parentPosition + m_pos;
@@ -473,7 +485,8 @@ namespace OpenSim.Region.Framework.Scenes
473 } 485 }
474 } 486 }
475 487
476 m_pos = value; 488 if (m_parentID == 0) // KF Do NOT update m_pos here if Av is sitting!
489 m_pos = value;
477 m_parentPosition = Vector3.Zero; 490 m_parentPosition = Vector3.Zero;
478 } 491 }
479 } 492 }
@@ -671,7 +684,7 @@ namespace OpenSim.Region.Framework.Scenes
671 CreateSceneViewer(); 684 CreateSceneViewer();
672 m_animator = new ScenePresenceAnimator(this); 685 m_animator = new ScenePresenceAnimator(this);
673 } 686 }
674 687
675 private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this() 688 private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this()
676 { 689 {
677 m_rootRegionHandle = reginfo.RegionHandle; 690 m_rootRegionHandle = reginfo.RegionHandle;
@@ -703,16 +716,16 @@ namespace OpenSim.Region.Framework.Scenes
703 m_reprioritization_timer.AutoReset = false; 716 m_reprioritization_timer.AutoReset = false;
704 717
705 AdjustKnownSeeds(); 718 AdjustKnownSeeds();
706
707 // TODO: I think, this won't send anything, as we are still a child here...
708 Animator.TrySetMovementAnimation("STAND"); 719 Animator.TrySetMovementAnimation("STAND");
709
710 // we created a new ScenePresence (a new child agent) in a fresh region. 720 // we created a new ScenePresence (a new child agent) in a fresh region.
711 // Request info about all the (root) agents in this region 721 // Request info about all the (root) agents in this region
712 // Note: This won't send data *to* other clients in that region (children don't send) 722 // Note: This won't send data *to* other clients in that region (children don't send)
713 SendInitialFullUpdateToAllClients(); 723 SendInitialFullUpdateToAllClients();
714
715 RegisterToEvents(); 724 RegisterToEvents();
725 if (m_controllingClient != null)
726 {
727 m_controllingClient.ProcessPendingPackets();
728 }
716 SetDirectionVectors(); 729 SetDirectionVectors();
717 } 730 }
718 731
@@ -762,25 +775,47 @@ namespace OpenSim.Region.Framework.Scenes
762 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT 775 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT
763 Dir_Vectors[4] = Vector3.UnitZ; //UP 776 Dir_Vectors[4] = Vector3.UnitZ; //UP
764 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN 777 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN
765 Dir_Vectors[8] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge 778 Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE
766 Dir_Vectors[6] = Vector3.UnitX*2; //FORWARD 779 Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE
767 Dir_Vectors[7] = -Vector3.UnitX; //BACK 780 Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE
781 Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE
782 Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
768 } 783 }
769 784
770 private Vector3[] GetWalkDirectionVectors() 785 private Vector3[] GetWalkDirectionVectors()
771 { 786 {
772 Vector3[] vector = new Vector3[9]; 787 Vector3[] vector = new Vector3[11];
773 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD 788 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD
774 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK 789 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK
775 vector[2] = Vector3.UnitY; //LEFT 790 vector[2] = Vector3.UnitY; //LEFT
776 vector[3] = -Vector3.UnitY; //RIGHT 791 vector[3] = -Vector3.UnitY; //RIGHT
777 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP 792 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP
778 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN 793 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN
779 vector[8] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge 794 vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE
780 vector[6] = (new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z) * 2); //FORWARD Nudge 795 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE
781 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK Nudge 796 vector[8] = Vector3.UnitY; //LEFT_NUDGE
797 vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
798 vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE
782 return vector; 799 return vector;
783 } 800 }
801
802 private bool[] GetDirectionIsNudge()
803 {
804 bool[] isNudge = new bool[11];
805 isNudge[0] = false; //FORWARD
806 isNudge[1] = false; //BACK
807 isNudge[2] = false; //LEFT
808 isNudge[3] = false; //RIGHT
809 isNudge[4] = false; //UP
810 isNudge[5] = false; //DOWN
811 isNudge[6] = true; //FORWARD_NUDGE
812 isNudge[7] = true; //BACK_NUDGE
813 isNudge[8] = true; //LEFT_NUDGE
814 isNudge[9] = true; //RIGHT_NUDGE
815 isNudge[10] = true; //DOWN_Nudge
816 return isNudge;
817 }
818
784 819
785 #endregion 820 #endregion
786 821
@@ -832,7 +867,6 @@ namespace OpenSim.Region.Framework.Scenes
832 m_grouptitle = gm.GetGroupTitle(m_uuid); 867 m_grouptitle = gm.GetGroupTitle(m_uuid);
833 868
834 m_rootRegionHandle = m_scene.RegionInfo.RegionHandle; 869 m_rootRegionHandle = m_scene.RegionInfo.RegionHandle;
835
836 m_scene.SetRootAgentScene(m_uuid); 870 m_scene.SetRootAgentScene(m_uuid);
837 871
838 // Moved this from SendInitialData to ensure that m_appearance is initialized 872 // Moved this from SendInitialData to ensure that m_appearance is initialized
@@ -851,6 +885,52 @@ namespace OpenSim.Region.Framework.Scenes
851 pos.Y = crossedBorder.BorderLine.Z - 1; 885 pos.Y = crossedBorder.BorderLine.Z - 1;
852 } 886 }
853 887
888 //If they're TP'ing in or logging in, we haven't had time to add any known child regions yet.
889 //This has the unfortunate consequence that if somebody is TP'ing who is already a child agent,
890 //they'll bypass the landing point. But I can't think of any decent way of fixing this.
891 if (KnownChildRegionHandles.Count == 0)
892 {
893 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
894 if (land != null)
895 {
896 //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni.
897 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && UserLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid)
898 {
899 pos = land.LandData.UserLocation;
900 }
901 }
902 }
903
904 if (pos.X < 0 || pos.Y < 0 || pos.Z < 0)
905 {
906 Vector3 emergencyPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 128);
907
908 if (pos.X < 0)
909 {
910 emergencyPos.X = (int)Constants.RegionSize + pos.X;
911 if (!(pos.Y < 0))
912 emergencyPos.Y = pos.Y;
913 if (!(pos.Z < 0))
914 emergencyPos.Z = pos.Z;
915 }
916 if (pos.Y < 0)
917 {
918 emergencyPos.Y = (int)Constants.RegionSize + pos.Y;
919 if (!(pos.X < 0))
920 emergencyPos.X = pos.X;
921 if (!(pos.Z < 0))
922 emergencyPos.Z = pos.Z;
923 }
924 if (pos.Z < 0)
925 {
926 emergencyPos.Z = 128;
927 if (!(pos.Y < 0))
928 emergencyPos.Y = pos.Y;
929 if (!(pos.X < 0))
930 emergencyPos.X = pos.X;
931 }
932 }
933
854 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 934 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
855 { 935 {
856 m_log.WarnFormat( 936 m_log.WarnFormat(
@@ -983,9 +1063,10 @@ namespace OpenSim.Region.Framework.Scenes
983 public void Teleport(Vector3 pos) 1063 public void Teleport(Vector3 pos)
984 { 1064 {
985 bool isFlying = false; 1065 bool isFlying = false;
1066
986 if (m_physicsActor != null) 1067 if (m_physicsActor != null)
987 isFlying = m_physicsActor.Flying; 1068 isFlying = m_physicsActor.Flying;
988 1069
989 RemoveFromPhysicalScene(); 1070 RemoveFromPhysicalScene();
990 Velocity = Vector3.Zero; 1071 Velocity = Vector3.Zero;
991 AbsolutePosition = pos; 1072 AbsolutePosition = pos;
@@ -997,6 +1078,7 @@ namespace OpenSim.Region.Framework.Scenes
997 } 1078 }
998 1079
999 SendTerseUpdateToAllClients(); 1080 SendTerseUpdateToAllClients();
1081
1000 } 1082 }
1001 1083
1002 public void TeleportWithMomentum(Vector3 pos) 1084 public void TeleportWithMomentum(Vector3 pos)
@@ -1041,7 +1123,9 @@ namespace OpenSim.Region.Framework.Scenes
1041 { 1123 {
1042 AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f)); 1124 AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f));
1043 } 1125 }
1044 1126
1127 m_updateCount = UPDATE_COUNT; //KF: Trigger Anim updates to catch falling anim.
1128
1045 ControllingClient.SendPrimUpdate(this, PrimUpdateFlags.Position); 1129 ControllingClient.SendPrimUpdate(this, PrimUpdateFlags.Position);
1046 //ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId, 1130 //ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId,
1047 // AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient))); 1131 // AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient)));
@@ -1128,7 +1212,6 @@ namespace OpenSim.Region.Framework.Scenes
1128 pos.Z = ground + 1.5f; 1212 pos.Z = ground + 1.5f;
1129 AbsolutePosition = pos; 1213 AbsolutePosition = pos;
1130 } 1214 }
1131
1132 m_isChildAgent = false; 1215 m_isChildAgent = false;
1133 bool m_flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); 1216 bool m_flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
1134 MakeRootAgent(AbsolutePosition, m_flying); 1217 MakeRootAgent(AbsolutePosition, m_flying);
@@ -1227,6 +1310,7 @@ namespace OpenSim.Region.Framework.Scenes
1227 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); 1310 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902");
1228 1311
1229 m_pos = m_LastFinitePos; 1312 m_pos = m_LastFinitePos;
1313
1230 if (!m_pos.IsFinite()) 1314 if (!m_pos.IsFinite())
1231 { 1315 {
1232 m_pos.X = 127f; 1316 m_pos.X = 127f;
@@ -1293,7 +1377,6 @@ namespace OpenSim.Region.Framework.Scenes
1293 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback); 1377 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback);
1294 } 1378 }
1295 } 1379 }
1296
1297 lock (scriptedcontrols) 1380 lock (scriptedcontrols)
1298 { 1381 {
1299 if (scriptedcontrols.Count > 0) 1382 if (scriptedcontrols.Count > 0)
@@ -1308,12 +1391,8 @@ namespace OpenSim.Region.Framework.Scenes
1308 1391
1309 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) 1392 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
1310 { 1393 {
1311 // TODO: This doesn't prevent the user from walking yet. 1394 m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.
1312 // Setting parent ID would fix this, if we knew what value 1395 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
1313 // to use. Or we could add a m_isSitting variable.
1314 //Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
1315 SitGround = true;
1316
1317 } 1396 }
1318 1397
1319 // In the future, these values might need to go global. 1398 // In the future, these values might need to go global.
@@ -1363,6 +1442,11 @@ namespace OpenSim.Region.Framework.Scenes
1363 update_rotation = true; 1442 update_rotation = true;
1364 } 1443 }
1365 1444
1445 //guilty until proven innocent..
1446 bool Nudging = true;
1447 //Basically, if there is at least one non-nudge control then we don't need
1448 //to worry about stopping the avatar
1449
1366 if (m_parentID == 0) 1450 if (m_parentID == 0)
1367 { 1451 {
1368 bool bAllowUpdateMoveToPosition = false; 1452 bool bAllowUpdateMoveToPosition = false;
@@ -1377,9 +1461,12 @@ namespace OpenSim.Region.Framework.Scenes
1377 else 1461 else
1378 dirVectors = Dir_Vectors; 1462 dirVectors = Dir_Vectors;
1379 1463
1380 // The fact that m_movementflag is a byte needs to be fixed 1464 bool[] isNudge = GetDirectionIsNudge();
1381 // it really should be a uint 1465
1382 uint nudgehack = 250; 1466
1467
1468
1469
1383 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) 1470 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
1384 { 1471 {
1385 if (((uint)flags & (uint)DCF) != 0) 1472 if (((uint)flags & (uint)DCF) != 0)
@@ -1389,40 +1476,28 @@ namespace OpenSim.Region.Framework.Scenes
1389 try 1476 try
1390 { 1477 {
1391 agent_control_v3 += dirVectors[i]; 1478 agent_control_v3 += dirVectors[i];
1392 //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]); 1479 if (isNudge[i] == false)
1480 {
1481 Nudging = false;
1482 }
1393 } 1483 }
1394 catch (IndexOutOfRangeException) 1484 catch (IndexOutOfRangeException)
1395 { 1485 {
1396 // Why did I get this? 1486 // Why did I get this?
1397 } 1487 }
1398 1488
1399 if ((m_movementflag & (byte)(uint)DCF) == 0) 1489 if ((m_movementflag & (uint)DCF) == 0)
1400 { 1490 {
1401 if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1402 {
1403 m_movementflag |= (byte)nudgehack;
1404 }
1405 m_movementflag += (byte)(uint)DCF; 1491 m_movementflag += (byte)(uint)DCF;
1406 update_movementflag = true; 1492 update_movementflag = true;
1407 } 1493 }
1408 } 1494 }
1409 else 1495 else
1410 { 1496 {
1411 if ((m_movementflag & (byte)(uint)DCF) != 0 || 1497 if ((m_movementflag & (uint)DCF) != 0)
1412 ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1413 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1414 ) // This or is for Nudge forward
1415 { 1498 {
1416 m_movementflag -= ((byte)(uint)DCF); 1499 m_movementflag -= (byte)(uint)DCF;
1417
1418 update_movementflag = true; 1500 update_movementflag = true;
1419 /*
1420 if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1421 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1422 {
1423 m_log.Debug("Removed Hack flag");
1424 }
1425 */
1426 } 1501 }
1427 else 1502 else
1428 { 1503 {
@@ -1431,7 +1506,6 @@ namespace OpenSim.Region.Framework.Scenes
1431 } 1506 }
1432 i++; 1507 i++;
1433 } 1508 }
1434
1435 //Paupaw:Do Proper PID for Autopilot here 1509 //Paupaw:Do Proper PID for Autopilot here
1436 if (bResetMoveToPosition) 1510 if (bResetMoveToPosition)
1437 { 1511 {
@@ -1466,6 +1540,9 @@ namespace OpenSim.Region.Framework.Scenes
1466 // Ignore z component of vector 1540 // Ignore z component of vector
1467 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); 1541 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
1468 LocalVectorToTarget2D.Normalize(); 1542 LocalVectorToTarget2D.Normalize();
1543
1544 //We're not nudging
1545 Nudging = false;
1469 agent_control_v3 += LocalVectorToTarget2D; 1546 agent_control_v3 += LocalVectorToTarget2D;
1470 1547
1471 // update avatar movement flags. the avatar coordinate system is as follows: 1548 // update avatar movement flags. the avatar coordinate system is as follows:
@@ -1554,13 +1631,13 @@ namespace OpenSim.Region.Framework.Scenes
1554 // m_log.DebugFormat( 1631 // m_log.DebugFormat(
1555 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3); 1632 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
1556 1633
1557 AddNewMovement(agent_control_v3, q); 1634 AddNewMovement(agent_control_v3, q, Nudging);
1558 1635
1559 1636
1560 } 1637 }
1561 } 1638 }
1562 1639
1563 if (update_movementflag && ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) == 0) && (m_parentID == 0) && !SitGround) 1640 if (update_movementflag)
1564 Animator.UpdateMovementAnimations(); 1641 Animator.UpdateMovementAnimations();
1565 1642
1566 m_scene.EventManager.TriggerOnClientMovement(this); 1643 m_scene.EventManager.TriggerOnClientMovement(this);
@@ -1575,7 +1652,6 @@ namespace OpenSim.Region.Framework.Scenes
1575 m_sitAtAutoTarget = false; 1652 m_sitAtAutoTarget = false;
1576 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default; 1653 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
1577 //proxy.PCode = (byte)PCode.ParticleSystem; 1654 //proxy.PCode = (byte)PCode.ParticleSystem;
1578
1579 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy); 1655 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy);
1580 proxyObjectGroup.AttachToScene(m_scene); 1656 proxyObjectGroup.AttachToScene(m_scene);
1581 1657
@@ -1617,7 +1693,7 @@ namespace OpenSim.Region.Framework.Scenes
1617 } 1693 }
1618 m_moveToPositionInProgress = true; 1694 m_moveToPositionInProgress = true;
1619 m_moveToPositionTarget = new Vector3(locx, locy, locz); 1695 m_moveToPositionTarget = new Vector3(locx, locy, locz);
1620 } 1696 }
1621 catch (Exception ex) 1697 catch (Exception ex)
1622 { 1698 {
1623 //Why did I get this error? 1699 //Why did I get this error?
@@ -1639,7 +1715,7 @@ namespace OpenSim.Region.Framework.Scenes
1639 Velocity = Vector3.Zero; 1715 Velocity = Vector3.Zero;
1640 SendFullUpdateToAllClients(); 1716 SendFullUpdateToAllClients();
1641 1717
1642 //HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); 1718 HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ??
1643 } 1719 }
1644 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false); 1720 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false);
1645 m_requestedSitTargetUUID = UUID.Zero; 1721 m_requestedSitTargetUUID = UUID.Zero;
@@ -1672,55 +1748,84 @@ namespace OpenSim.Region.Framework.Scenes
1672 /// </summary> 1748 /// </summary>
1673 public void StandUp() 1749 public void StandUp()
1674 { 1750 {
1675 if (SitGround)
1676 SitGround = false;
1677
1678 if (m_parentID != 0) 1751 if (m_parentID != 0)
1679 { 1752 {
1680 m_log.Debug("StandupCode Executed");
1681 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); 1753 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
1682 if (part != null) 1754 if (part != null)
1683 { 1755 {
1756 part.TaskInventory.LockItemsForRead(true);
1684 TaskInventoryDictionary taskIDict = part.TaskInventory; 1757 TaskInventoryDictionary taskIDict = part.TaskInventory;
1685 if (taskIDict != null) 1758 if (taskIDict != null)
1686 { 1759 {
1687 lock (taskIDict) 1760 foreach (UUID taskID in taskIDict.Keys)
1688 { 1761 {
1689 foreach (UUID taskID in taskIDict.Keys) 1762 UnRegisterControlEventsToScript(LocalId, taskID);
1690 { 1763 taskIDict[taskID].PermsMask &= ~(
1691 UnRegisterControlEventsToScript(LocalId, taskID); 1764 2048 | //PERMISSION_CONTROL_CAMERA
1692 taskIDict[taskID].PermsMask &= ~( 1765 4); // PERMISSION_TAKE_CONTROLS
1693 2048 | //PERMISSION_CONTROL_CAMERA
1694 4); // PERMISSION_TAKE_CONTROLS
1695 }
1696 } 1766 }
1697
1698 } 1767 }
1768 part.TaskInventory.LockItemsForRead(false);
1699 // Reset sit target. 1769 // Reset sit target.
1700 if (part.GetAvatarOnSitTarget() == UUID) 1770 if (part.GetAvatarOnSitTarget() == UUID)
1701 part.SetAvatarOnSitTarget(UUID.Zero); 1771 part.SetAvatarOnSitTarget(UUID.Zero);
1702
1703 m_parentPosition = part.GetWorldPosition(); 1772 m_parentPosition = part.GetWorldPosition();
1704 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1773 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1705 } 1774 }
1775 // part.GetWorldRotation() is the rotation of the object being sat on
1776 // Rotation is the sittiing Av's rotation
1777
1778 Quaternion partRot;
1779// if (part.LinkNum == 1)
1780// { // Root prim of linkset
1781// partRot = part.ParentGroup.RootPart.RotationOffset;
1782// }
1783// else
1784// { // single or child prim
1785
1786// }
1787 if (part == null) //CW: Part may be gone. llDie() for example.
1788 {
1789 partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
1790 }
1791 else
1792 {
1793 partRot = part.GetWorldRotation();
1794 }
1795
1796 Quaternion partIRot = Quaternion.Inverse(partRot);
1797
1798 Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
1799 Vector3 avStandUp = new Vector3(1.0f, 0f, 0f) * avatarRot; // 1M infront of av
1706 1800
1801
1707 if (m_physicsActor == null) 1802 if (m_physicsActor == null)
1708 { 1803 {
1709 AddToPhysicalScene(false); 1804 AddToPhysicalScene(false);
1710 } 1805 }
1711 1806 //CW: If the part isn't null then we can set the current position
1712 m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight); 1807 if (part != null)
1713 m_parentPosition = Vector3.Zero; 1808 {
1714 1809 Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + (m_pos * partRot); // + av sit offset!
1715 m_parentID = 0; 1810 AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
1811 part.IsOccupied = false;
1812 }
1813 else
1814 {
1815 //CW: Since the part doesn't exist, a coarse standup position isn't an issue
1816 AbsolutePosition = m_lastWorldPosition;
1817 }
1818
1819 m_parentPosition = Vector3.Zero;
1820 m_parentID = 0;
1716 SendFullUpdateToAllClients(); 1821 SendFullUpdateToAllClients();
1717 m_requestedSitTargetID = 0; 1822 m_requestedSitTargetID = 0;
1823
1718 if ((m_physicsActor != null) && (m_avHeight > 0)) 1824 if ((m_physicsActor != null) && (m_avHeight > 0))
1719 { 1825 {
1720 SetHeight(m_avHeight); 1826 SetHeight(m_avHeight);
1721 } 1827 }
1722 } 1828 }
1723
1724 Animator.TrySetMovementAnimation("STAND"); 1829 Animator.TrySetMovementAnimation("STAND");
1725 } 1830 }
1726 1831
@@ -1751,13 +1856,9 @@ namespace OpenSim.Region.Framework.Scenes
1751 Vector3 avSitOffSet = part.SitTargetPosition; 1856 Vector3 avSitOffSet = part.SitTargetPosition;
1752 Quaternion avSitOrientation = part.SitTargetOrientation; 1857 Quaternion avSitOrientation = part.SitTargetOrientation;
1753 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1858 UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
1754 1859 bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero);
1755 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1860 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1756 bool SitTargetisSet = 1861 if (SitTargetisSet && !SitTargetOccupied)
1757 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 1f &&
1758 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f));
1759
1760 if (SitTargetisSet && SitTargetUnOccupied)
1761 { 1862 {
1762 //switch the target to this prim 1863 //switch the target to this prim
1763 return part; 1864 return part;
@@ -1771,84 +1872,153 @@ namespace OpenSim.Region.Framework.Scenes
1771 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation) 1872 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation)
1772 { 1873 {
1773 bool autopilot = true; 1874 bool autopilot = true;
1875 Vector3 autopilotTarget = new Vector3();
1876 Quaternion sitOrientation = Quaternion.Identity;
1774 Vector3 pos = new Vector3(); 1877 Vector3 pos = new Vector3();
1775 Quaternion sitOrientation = pSitOrientation;
1776 Vector3 cameraEyeOffset = Vector3.Zero; 1878 Vector3 cameraEyeOffset = Vector3.Zero;
1777 Vector3 cameraAtOffset = Vector3.Zero; 1879 Vector3 cameraAtOffset = Vector3.Zero;
1778 bool forceMouselook = false; 1880 bool forceMouselook = false;
1779 1881
1780 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); 1882 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
1781 SceneObjectPart part = FindNextAvailableSitTarget(targetID); 1883 SceneObjectPart part = FindNextAvailableSitTarget(targetID);
1782 if (part != null) 1884 if (part == null) return;
1783 { 1885
1784 // TODO: determine position to sit at based on scene geometry; don't trust offset from client 1886 // TODO: determine position to sit at based on scene geometry; don't trust offset from client
1785 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it 1887 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
1786 1888
1787 // Is a sit target available? 1889 // part is the prim to sit on
1788 Vector3 avSitOffSet = part.SitTargetPosition; 1890 // offset is the world-ref vector distance from that prim center to the click-spot
1789 Quaternion avSitOrientation = part.SitTargetOrientation; 1891 // UUID is the UUID of the Avatar doing the clicking
1790 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1892
1791 1893 m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation
1792 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1894
1793 bool SitTargetisSet = 1895 // Is a sit target available?
1794 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && 1896 Vector3 avSitOffSet = part.SitTargetPosition;
1795 ( 1897 Quaternion avSitOrientation = part.SitTargetOrientation;
1796 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 1f // Valid Zero Rotation quaternion 1898
1797 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f && avSitOrientation.W == 0f // W-Z Mapping was invalid at one point 1899 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1798 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 0f // Invalid Quaternion 1900 // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
1799 ) 1901 Quaternion partRot;
1800 )); 1902// if (part.LinkNum == 1)
1801 1903// { // Root prim of linkset
1802 if (SitTargetisSet && SitTargetUnOccupied) 1904// partRot = part.ParentGroup.RootPart.RotationOffset;
1803 { 1905// }
1804 part.SetAvatarOnSitTarget(UUID); 1906// else
1805 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); 1907// { // single or child prim
1806 sitOrientation = avSitOrientation; 1908 partRot = part.GetWorldRotation();
1807 autopilot = false; 1909// }
1808 } 1910 Quaternion partIRot = Quaternion.Inverse(partRot);
1809 1911//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet);
1810 pos = part.AbsolutePosition + offset; 1912 // Sit analysis rewritten by KF 091125
1811 //if (Math.Abs(part.AbsolutePosition.Z - AbsolutePosition.Z) > 1) 1913 if (SitTargetisSet) // scipted sit
1812 //{ 1914 {
1813 // offset = pos; 1915 if (!part.IsOccupied)
1814 //autopilot = false; 1916 {
1815 //} 1917//Console.WriteLine("Scripted, unoccupied");
1816 if (m_physicsActor != null) 1918 part.SetAvatarOnSitTarget(UUID); // set that Av will be on it
1817 { 1919 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
1818 // If we're not using the client autopilot, we're immediately warping the avatar to the location 1920 sitOrientation = avSitOrientation; // Change rotatione to the scripted one
1819 // We can remove the physicsActor until they stand up. 1921 autopilot = false; // Jump direct to scripted llSitPos()
1820 m_sitAvatarHeight = m_physicsActor.Size.Z; 1922 }
1821 1923 else
1822 if (autopilot) 1924 {
1823 { 1925//Console.WriteLine("Scripted, occupied");
1824 if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5) 1926 return;
1825 { 1927 }
1826 autopilot = false; 1928 }
1929 else // Not Scripted
1930 {
1931 if ( (Math.Abs(offset.X) > 0.5f) || (Math.Abs(offset.Y) > 0.5f) )
1932 {
1933 // large prim & offset, ignore if other Avs sitting
1934// offset.Z -= 0.05f;
1935 m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked
1936 autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point
1937
1938//Console.WriteLine(" offset ={0}", offset);
1939//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos);
1940//Console.WriteLine(" autopilotTarget={0}", autopilotTarget);
1941
1942 }
1943 else // small offset
1944 {
1945//Console.WriteLine("Small offset");
1946 if (!part.IsOccupied)
1947 {
1948 m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center
1949 autopilotTarget = part.AbsolutePosition;
1950//Console.WriteLine("UsSmall autopilotTarget={0}", autopilotTarget);
1951 }
1952 else return; // occupied small
1953 } // end large/small
1954 } // end Scripted/not
1955 cameraAtOffset = part.GetCameraAtOffset();
1956 cameraEyeOffset = part.GetCameraEyeOffset();
1957 forceMouselook = part.GetForceMouselook();
1958 if(cameraAtOffset == Vector3.Zero) cameraAtOffset = new Vector3(0f, 0f, 0.1f); //
1959 if(cameraEyeOffset == Vector3.Zero) cameraEyeOffset = new Vector3(0f, 0f, 0.1f); //
1827 1960
1828 RemoveFromPhysicalScene(); 1961 if (m_physicsActor != null)
1829 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); 1962 {
1830 } 1963 // If we're not using the client autopilot, we're immediately warping the avatar to the location
1831 } 1964 // We can remove the physicsActor until they stand up.
1832 else 1965 m_sitAvatarHeight = m_physicsActor.Size.Z;
1966 if (autopilot)
1967 { // its not a scripted sit
1968// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
1969 if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 2.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 2.0f) )
1833 { 1970 {
1971 autopilot = false; // close enough
1972 m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup.
1973 Not using the part's position because returning the AV to the last known standing
1974 position is likely to be more friendly, isn't it? */
1834 RemoveFromPhysicalScene(); 1975 RemoveFromPhysicalScene();
1835 } 1976 AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target
1977 } // else the autopilot will get us close
1978 }
1979 else
1980 { // its a scripted sit
1981 m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup.
1982 I *am* using the part's position this time because we have no real idea how far away
1983 the avatar is from the sit target. */
1984 RemoveFromPhysicalScene();
1836 } 1985 }
1837
1838 cameraAtOffset = part.GetCameraAtOffset();
1839 cameraEyeOffset = part.GetCameraEyeOffset();
1840 forceMouselook = part.GetForceMouselook();
1841 } 1986 }
1842 1987 else return; // physactor is null!
1843 ControllingClient.SendSitResponse(targetID, offset, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); 1988
1844 m_requestedSitTargetUUID = targetID; 1989 Vector3 offsetr; // = offset * partIRot;
1990 // KF: In a linkset, offsetr needs to be relative to the group root! 091208
1991 // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot);
1992 // if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error.
1993 // { // Single, or Root prim of linkset, target is ClickOffset * RootRot
1994 offsetr = offset * partIRot;
1995//
1996 // else
1997 // { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot)
1998 // offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) +
1999 // (offset * partRot);
2000 // }
2001
2002//Console.WriteLine(" ");
2003//Console.WriteLine("link number ={0}", part.LinkNum);
2004//Console.WriteLine("Prim offset ={0}", part.OffsetPosition );
2005//Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset);
2006//Console.WriteLine("Click offst ={0}", offset);
2007//Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation());
2008//Console.WriteLine("offsetr ={0}", offsetr);
2009//Console.WriteLine("Camera At ={0}", cameraAtOffset);
2010//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
2011
2012 ControllingClient.SendSitResponse(part.UUID, offsetr, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
2013 m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
1845 // This calls HandleAgentSit twice, once from here, and the client calls 2014 // This calls HandleAgentSit twice, once from here, and the client calls
1846 // HandleAgentSit itself after it gets to the location 2015 // HandleAgentSit itself after it gets to the location
1847 // It doesn't get to the location until we've moved them there though 2016 // It doesn't get to the location until we've moved them there though
1848 // which happens in HandleAgentSit :P 2017 // which happens in HandleAgentSit :P
1849 m_autopilotMoving = autopilot; 2018 m_autopilotMoving = autopilot;
1850 m_autoPilotTarget = pos; 2019 m_autoPilotTarget = autopilotTarget;
1851 m_sitAtAutoTarget = autopilot; 2020 m_sitAtAutoTarget = autopilot;
2021 m_initialSitTarget = autopilotTarget;
1852 if (!autopilot) 2022 if (!autopilot)
1853 HandleAgentSit(remoteClient, UUID); 2023 HandleAgentSit(remoteClient, UUID);
1854 } 2024 }
@@ -2143,31 +2313,66 @@ namespace OpenSim.Region.Framework.Scenes
2143 { 2313 {
2144 if (part != null) 2314 if (part != null)
2145 { 2315 {
2316//Console.WriteLine("Link #{0}, Rot {1}", part.LinkNum, part.GetWorldRotation());
2146 if (part.GetAvatarOnSitTarget() == UUID) 2317 if (part.GetAvatarOnSitTarget() == UUID)
2147 { 2318 {
2319//Console.WriteLine("Scripted Sit");
2320 // Scripted sit
2148 Vector3 sitTargetPos = part.SitTargetPosition; 2321 Vector3 sitTargetPos = part.SitTargetPosition;
2149 Quaternion sitTargetOrient = part.SitTargetOrientation; 2322 Quaternion sitTargetOrient = part.SitTargetOrientation;
2150
2151 //Quaternion vq = new Quaternion(sitTargetPos.X, sitTargetPos.Y+0.2f, sitTargetPos.Z+0.2f, 0);
2152 //Quaternion nq = new Quaternion(-sitTargetOrient.X, -sitTargetOrient.Y, -sitTargetOrient.Z, sitTargetOrient.w);
2153
2154 //Quaternion result = (sitTargetOrient * vq) * nq;
2155
2156 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z); 2323 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
2157 m_pos += SIT_TARGET_ADJUSTMENT; 2324 m_pos += SIT_TARGET_ADJUSTMENT;
2158 m_bodyRot = sitTargetOrient; 2325 m_bodyRot = sitTargetOrient;
2159 //Rotation = sitTargetOrient;
2160 m_parentPosition = part.AbsolutePosition; 2326 m_parentPosition = part.AbsolutePosition;
2161 2327 part.IsOccupied = true;
2162 //SendTerseUpdateToAllClients(); 2328Console.WriteLine("Scripted Sit ofset {0}", m_pos);
2163 } 2329 }
2164 else 2330 else
2165 { 2331 {
2166 m_pos -= part.AbsolutePosition; 2332 // if m_avUnscriptedSitPos is zero then Av sits above center
2333 // Else Av sits at m_avUnscriptedSitPos
2334
2335 // Non-scripted sit by Kitto Flora 21Nov09
2336 // Calculate angle of line from prim to Av
2337 Quaternion partIRot;
2338// if (part.LinkNum == 1)
2339// { // Root prim of linkset
2340// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2341// }
2342// else
2343// { // single or child prim
2344 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2345// }
2346 Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos;
2347 float y_diff = (m_avInitialPos.Y - sitTargetPos.Y);
2348 float x_diff = ( m_avInitialPos.X - sitTargetPos.X);
2349 if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0
2350 if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0
2351 float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff);
2352 // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'.
2353 // Av sits at world euler <0,0, z>, translated by part rotation
2354 m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click
2355
2167 m_parentPosition = part.AbsolutePosition; 2356 m_parentPosition = part.AbsolutePosition;
2168 } 2357 part.IsOccupied = true;
2358 m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation
2359 (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center
2360 (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) +
2361 m_avUnscriptedSitPos; // adds click offset, if any
2362 //Set up raytrace to find top surface of prim
2363 Vector3 size = part.Scale;
2364 float mag = 2.0f; // 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
2365 Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
2366 Vector3 down = new Vector3(0f, 0f, -1f);
2367//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag);
2368 m_scene.PhysicsScene.RaycastWorld(
2369 start, // Vector3 position,
2370 down, // Vector3 direction,
2371 mag, // float length,
2372 SitAltitudeCallback); // retMethod
2373 } // end scripted/not
2169 } 2374 }
2170 else 2375 else // no Av
2171 { 2376 {
2172 return; 2377 return;
2173 } 2378 }
@@ -2179,11 +2384,39 @@ namespace OpenSim.Region.Framework.Scenes
2179 2384
2180 Animator.TrySetMovementAnimation(sitAnimation); 2385 Animator.TrySetMovementAnimation(sitAnimation);
2181 SendFullUpdateToAllClients(); 2386 SendFullUpdateToAllClients();
2182 // This may seem stupid, but Our Full updates don't send avatar rotation :P
2183 // So we're also sending a terse update (which has avatar rotation)
2184 // [Update] We do now.
2185 //SendTerseUpdateToAllClients();
2186 } 2387 }
2388
2389 public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal)
2390 {
2391 // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer
2392 // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height.
2393 if(hitYN)
2394 {
2395 // m_pos = Av offset from prim center to make look like on center
2396 // m_parentPosition = Actual center pos of prim
2397 // collisionPoint = spot on prim where we want to sit
2398 // collisionPoint.Z = global sit surface height
2399 SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
2400 Quaternion partIRot;
2401// if (part.LinkNum == 1)
2402/// { // Root prim of linkset
2403// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2404// }
2405// else
2406// { // single or child prim
2407 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2408// }
2409 if (m_initialSitTarget != null)
2410 {
2411 float offZ = collisionPoint.Z - m_initialSitTarget.Z;
2412 Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
2413 //Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
2414 m_pos += offset;
2415 // ControllingClient.SendClearFollowCamProperties(part.UUID);
2416 }
2417
2418 }
2419 } // End SitAltitudeCallback KF.
2187 2420
2188 /// <summary> 2421 /// <summary>
2189 /// Event handler for the 'Always run' setting on the client 2422 /// Event handler for the 'Always run' setting on the client
@@ -2213,7 +2446,7 @@ namespace OpenSim.Region.Framework.Scenes
2213 /// </summary> 2446 /// </summary>
2214 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 2447 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
2215 /// <param name="rotation">The direction in which this avatar should now face. 2448 /// <param name="rotation">The direction in which this avatar should now face.
2216 public void AddNewMovement(Vector3 vec, Quaternion rotation) 2449 public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging)
2217 { 2450 {
2218 if (m_isChildAgent) 2451 if (m_isChildAgent)
2219 { 2452 {
@@ -2254,10 +2487,11 @@ namespace OpenSim.Region.Framework.Scenes
2254 Rotation = rotation; 2487 Rotation = rotation;
2255 Vector3 direc = vec * rotation; 2488 Vector3 direc = vec * rotation;
2256 direc.Normalize(); 2489 direc.Normalize();
2490 PhysicsActor actor = m_physicsActor;
2491 if ((vec.Z == 0f) && !actor.Flying) direc.Z = 0f; // Prevent camera WASD up.
2257 2492
2258 direc *= 0.03f * 128f * m_speedModifier; 2493 direc *= 0.03f * 128f * m_speedModifier;
2259 2494
2260 PhysicsActor actor = m_physicsActor;
2261 if (actor != null) 2495 if (actor != null)
2262 { 2496 {
2263 if (actor.Flying) 2497 if (actor.Flying)
@@ -2279,18 +2513,25 @@ namespace OpenSim.Region.Framework.Scenes
2279 { 2513 {
2280 if (direc.Z > 2.0f) 2514 if (direc.Z > 2.0f)
2281 { 2515 {
2282 direc.Z *= 3.0f; 2516 if(m_animator.m_animTickJump == -1)
2283 2517 {
2284 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored. 2518 direc.Z *= 3.0f; // jump
2285 Animator.TrySetMovementAnimation("PREJUMP"); 2519 }
2286 Animator.TrySetMovementAnimation("JUMP"); 2520 else
2521 {
2522 direc.Z *= 0.1f; // prejump
2523 }
2524 /* Animations are controlled via GetMovementAnimation() in ScenePresenceAnimator.cs
2525 Animator.TrySetMovementAnimation("PREJUMP");
2526 Animator.TrySetMovementAnimation("JUMP");
2527 */
2287 } 2528 }
2288 } 2529 }
2289 } 2530 }
2290 2531
2291 // TODO: Add the force instead of only setting it to support multiple forces per frame? 2532 // TODO: Add the force instead of only setting it to support multiple forces per frame?
2292 m_forceToApply = direc; 2533 m_forceToApply = direc;
2293 2534 m_isNudging = Nudging;
2294 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); 2535 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
2295 } 2536 }
2296 2537
@@ -2305,7 +2546,7 @@ namespace OpenSim.Region.Framework.Scenes
2305 const float POSITION_TOLERANCE = 0.05f; 2546 const float POSITION_TOLERANCE = 0.05f;
2306 //const int TIME_MS_TOLERANCE = 3000; 2547 //const int TIME_MS_TOLERANCE = 3000;
2307 2548
2308 SendPrimUpdates(); 2549
2309 2550
2310 if (m_newCoarseLocations) 2551 if (m_newCoarseLocations)
2311 { 2552 {
@@ -2341,6 +2582,9 @@ namespace OpenSim.Region.Framework.Scenes
2341 CheckForBorderCrossing(); 2582 CheckForBorderCrossing();
2342 CheckForSignificantMovement(); // sends update to the modules. 2583 CheckForSignificantMovement(); // sends update to the modules.
2343 } 2584 }
2585
2586 //Sending prim updates AFTER the avatar terse updates are sent
2587 SendPrimUpdates();
2344 } 2588 }
2345 2589
2346 #endregion 2590 #endregion
@@ -3151,6 +3395,7 @@ namespace OpenSim.Region.Framework.Scenes
3151 m_callbackURI = cAgent.CallbackURI; 3395 m_callbackURI = cAgent.CallbackURI;
3152 3396
3153 m_pos = cAgent.Position; 3397 m_pos = cAgent.Position;
3398
3154 m_velocity = cAgent.Velocity; 3399 m_velocity = cAgent.Velocity;
3155 m_CameraCenter = cAgent.Center; 3400 m_CameraCenter = cAgent.Center;
3156 //m_avHeight = cAgent.Size.Z; 3401 //m_avHeight = cAgent.Size.Z;
@@ -3239,14 +3484,25 @@ namespace OpenSim.Region.Framework.Scenes
3239 { 3484 {
3240 if (m_forceToApply.HasValue) 3485 if (m_forceToApply.HasValue)
3241 { 3486 {
3242 Vector3 force = m_forceToApply.Value;
3243 3487
3488 Vector3 force = m_forceToApply.Value;
3244 m_updateflag = true; 3489 m_updateflag = true;
3245// movementvector = force;
3246 Velocity = force; 3490 Velocity = force;
3247 3491
3248 m_forceToApply = null; 3492 m_forceToApply = null;
3249 } 3493 }
3494 else
3495 {
3496 if (m_isNudging)
3497 {
3498 Vector3 force = Vector3.Zero;
3499
3500 m_updateflag = true;
3501 Velocity = force;
3502 m_isNudging = false;
3503 m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND"
3504 }
3505 }
3250 } 3506 }
3251 3507
3252 public override void SetText(string text, Vector3 color, double alpha) 3508 public override void SetText(string text, Vector3 color, double alpha)
@@ -3297,18 +3553,29 @@ namespace OpenSim.Region.Framework.Scenes
3297 { 3553 {
3298 if (e == null) 3554 if (e == null)
3299 return; 3555 return;
3300 3556
3301 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 3557 // The Physics Scene will send (spam!) updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3302 // The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3303 // as of this comment the interval is set in AddToPhysicalScene 3558 // as of this comment the interval is set in AddToPhysicalScene
3304 if (Animator!=null) 3559 if (Animator!=null)
3305 Animator.UpdateMovementAnimations(); 3560 {
3561 if (m_updateCount > 0) //KF: DO NOT call UpdateMovementAnimations outside of the m_updateCount wrapper,
3562 { // else its will lock out other animation changes, like ground sit.
3563 Animator.UpdateMovementAnimations();
3564 m_updateCount--;
3565 }
3566 }
3306 3567
3307 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 3568 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
3308 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 3569 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
3309 3570
3310 CollisionPlane = Vector4.UnitW; 3571 CollisionPlane = Vector4.UnitW;
3311 3572
3573 if (m_lastColCount != coldata.Count)
3574 {
3575 m_updateCount = UPDATE_COUNT;
3576 m_lastColCount = coldata.Count;
3577 }
3578
3312 if (coldata.Count != 0 && Animator != null) 3579 if (coldata.Count != 0 && Animator != null)
3313 { 3580 {
3314 switch (Animator.CurrentMovementAnimation) 3581 switch (Animator.CurrentMovementAnimation)
@@ -3512,7 +3779,10 @@ namespace OpenSim.Region.Framework.Scenes
3512 m_scene = scene; 3779 m_scene = scene;
3513 3780
3514 RegisterToEvents(); 3781 RegisterToEvents();
3515 3782 if (m_controllingClient != null)
3783 {
3784 m_controllingClient.ProcessPendingPackets();
3785 }
3516 /* 3786 /*
3517 AbsolutePosition = client.StartPos; 3787 AbsolutePosition = client.StartPos;
3518 3788
@@ -3743,6 +4013,32 @@ namespace OpenSim.Region.Framework.Scenes
3743 return; 4013 return;
3744 } 4014 }
3745 4015
4016 XmlDocument doc = new XmlDocument();
4017 string stateData = String.Empty;
4018
4019 IAttachmentsService attServ = m_scene.RequestModuleInterface<IAttachmentsService>();
4020 if (attServ != null)
4021 {
4022 m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service");
4023 stateData = attServ.Get(ControllingClient.AgentId.ToString());
4024 doc.LoadXml(stateData);
4025 }
4026
4027 Dictionary<UUID, string> itemData = new Dictionary<UUID, string>();
4028
4029 XmlNodeList nodes = doc.GetElementsByTagName("Attachment");
4030 if (nodes.Count > 0)
4031 {
4032 foreach (XmlNode n in nodes)
4033 {
4034 XmlElement elem = (XmlElement)n;
4035 string itemID = elem.GetAttribute("ItemID");
4036 string xml = elem.InnerXml;
4037
4038 itemData[new UUID(itemID)] = xml;
4039 }
4040 }
4041
3746 List<int> attPoints = m_appearance.GetAttachedPoints(); 4042 List<int> attPoints = m_appearance.GetAttachedPoints();
3747 foreach (int p in attPoints) 4043 foreach (int p in attPoints)
3748 { 4044 {
@@ -3762,9 +4058,26 @@ namespace OpenSim.Region.Framework.Scenes
3762 4058
3763 try 4059 try
3764 { 4060 {
3765 // Rez from inventory 4061 string xmlData;
3766 UUID asset 4062 XmlDocument d = new XmlDocument();
3767 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p); 4063 UUID asset;
4064 if (itemData.TryGetValue(itemID, out xmlData))
4065 {
4066 d.LoadXml(xmlData);
4067 m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", itemID);
4068
4069 // Rez from inventory
4070 asset
4071 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, d);
4072
4073 }
4074 else
4075 {
4076 // Rez from inventory (with a null doc to let
4077 // CHANGED_OWNER happen)
4078 asset
4079 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, null);
4080 }
3768 4081
3769 m_log.InfoFormat( 4082 m_log.InfoFormat(
3770 "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2} ({3})", 4083 "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2} ({3})",
@@ -3915,5 +4228,16 @@ namespace OpenSim.Region.Framework.Scenes
3915 m_reprioritization_called = false; 4228 m_reprioritization_called = false;
3916 } 4229 }
3917 } 4230 }
4231
4232 private Vector3 Quat2Euler(Quaternion rot){
4233 float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) ,
4234 (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z)));
4235 float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W)));
4236 float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) ,
4237 (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z)));
4238 return(new Vector3(x,y,z));
4239 }
4240
4241
3918 } 4242 }
3919} 4243}
diff --git a/OpenSim/Region/Framework/Scenes/SceneViewer.cs b/OpenSim/Region/Framework/Scenes/SceneViewer.cs
index c6cf4cc..4ba4fab 100644
--- a/OpenSim/Region/Framework/Scenes/SceneViewer.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneViewer.cs
@@ -75,7 +75,7 @@ namespace OpenSim.Region.Framework.Scenes
75 75
76 foreach (EntityBase e in m_presence.Scene.Entities) 76 foreach (EntityBase e in m_presence.Scene.Entities)
77 { 77 {
78 if (e is SceneObjectGroup) 78 if (e != null && e is SceneObjectGroup)
79 m_pendingObjects.Enqueue((SceneObjectGroup)e); 79 m_pendingObjects.Enqueue((SceneObjectGroup)e);
80 } 80 }
81 } 81 }
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index 84faac0..fb8543b 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -878,6 +878,10 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
878 878
879 } 879 }
880 880
881 public void ProcessPendingPackets()
882 {
883 }
884
881 public void ProcessInPacket(Packet NewPack) 885 public void ProcessInPacket(Packet NewPack)
882 { 886 {
883 887
@@ -885,6 +889,11 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
885 889
886 public void Close() 890 public void Close()
887 { 891 {
892 Close(true);
893 }
894
895 public void Close(bool sendStop)
896 {
888 Disconnect(); 897 Disconnect();
889 } 898 }
890 899
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index 9066691..3cbc538 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
@@ -831,12 +831,21 @@ namespace OpenSim.Region.OptionalModules.World.NPC
831 { 831 {
832 } 832 }
833 833
834 public void ProcessPendingPackets()
835 {
836 }
837
834 public void ProcessInPacket(Packet NewPack) 838 public void ProcessInPacket(Packet NewPack)
835 { 839 {
836 } 840 }
837 841
838 public void Close() 842 public void Close()
839 { 843 {
844 Close(true);
845 }
846
847 public void Close(bool sendStop)
848 {
840 } 849 }
841 850
842 public void Start() 851 public void Start()
diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs
index ac4e2b9..f13c323 100644
--- a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs
+++ b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs
@@ -624,8 +624,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin
624 { 624 {
625 set { return; } 625 set { return; }
626 } 626 }
627 627
628
629 public override Quaternion APIDTarget 628 public override Quaternion APIDTarget
630 { 629 {
631 set { return; } 630 set { return; }
diff --git a/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs b/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs
index e2a6a2e..f4245b6 100644
--- a/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs
+++ b/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs
@@ -996,7 +996,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin
996 { 996 {
997 997
998 } 998 }
999 999
1000 public override void VehicleFlags(int param, bool remove) 1000 public override void VehicleFlags(int param, bool remove)
1001 { 1001 {
1002 1002
diff --git a/OpenSim/Region/Physics/ChOdePlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/ChOdePlugin/AssemblyInfo.cs
new file mode 100644
index 0000000..d65929a
--- /dev/null
+++ b/OpenSim/Region/Physics/ChOdePlugin/AssemblyInfo.cs
@@ -0,0 +1,58 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System.Reflection;
29using System.Runtime.InteropServices;
30
31// Information about this assembly is defined by the following
32// attributes.
33//
34// change them to the information which is associated with the assembly
35// you compile.
36
37[assembly : AssemblyTitle("OdePlugin")]
38[assembly : AssemblyDescription("")]
39[assembly : AssemblyConfiguration("")]
40[assembly : AssemblyCompany("http://opensimulator.org")]
41[assembly : AssemblyProduct("OdePlugin")]
42[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers 2007-2009")]
43[assembly : AssemblyTrademark("")]
44[assembly : AssemblyCulture("")]
45
46// This sets the default COM visibility of types in the assembly to invisible.
47// If you need to expose a type to COM, use [ComVisible(true)] on that type.
48
49[assembly : ComVisible(false)]
50
51// The assembly version has following format :
52//
53// Major.Minor.Build.Revision
54//
55// You can specify all values by your own or you can build default build and revision
56// numbers with the '*' character (the default):
57
58[assembly : AssemblyVersion("0.6.5.*")]
diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs
new file mode 100644
index 0000000..38c38b6
--- /dev/null
+++ b/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs
@@ -0,0 +1,1369 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using OpenMetaverse;
32using Ode.NET;
33using OpenSim.Framework;
34using OpenSim.Region.Physics.Manager;
35using log4net;
36
37namespace OpenSim.Region.Physics.OdePlugin
38{
39 /// <summary>
40 /// Various properties that ODE uses for AMotors but isn't exposed in ODE.NET so we must define them ourselves.
41 /// </summary>
42
43 public enum dParam : int
44 {
45 LowStop = 0,
46 HiStop = 1,
47 Vel = 2,
48 FMax = 3,
49 FudgeFactor = 4,
50 Bounce = 5,
51 CFM = 6,
52 StopERP = 7,
53 StopCFM = 8,
54 LoStop2 = 256,
55 HiStop2 = 257,
56 Vel2 = 258,
57 FMax2 = 259,
58 StopERP2 = 7 + 256,
59 StopCFM2 = 8 + 256,
60 LoStop3 = 512,
61 HiStop3 = 513,
62 Vel3 = 514,
63 FMax3 = 515,
64 StopERP3 = 7 + 512,
65 StopCFM3 = 8 + 512
66 }
67 public class OdeCharacter : PhysicsActor
68 {
69 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
70
71 private Vector3 _position;
72 private d.Vector3 _zeroPosition;
73 // private d.Matrix3 m_StandUpRotation;
74 private bool _zeroFlag = false;
75 private bool m_lastUpdateSent = false;
76 private Vector3 _velocity;
77 private Vector3 _target_velocity;
78 private Vector3 _acceleration;
79 private Vector3 m_rotationalVelocity;
80 private float m_mass = 80f;
81 public float m_density = 60f;
82 private bool m_pidControllerActive = true;
83 public float PID_D = 800.0f;
84 public float PID_P = 900.0f;
85 //private static float POSTURE_SERVO = 10000.0f;
86 public float CAPSULE_RADIUS = 0.37f;
87 public float CAPSULE_LENGTH = 2.140599f;
88 public float m_tensor = 3800000f;
89 public float heightFudgeFactor = 0.52f;
90 public float walkDivisor = 1.3f;
91 public float runDivisor = 0.8f;
92 private bool flying = false;
93 private bool m_iscolliding = false;
94 private bool m_iscollidingGround = false;
95 private bool m_wascolliding = false;
96 private bool m_wascollidingGround = false;
97 private bool m_iscollidingObj = false;
98 private bool m_alwaysRun = false;
99 private bool m_hackSentFall = false;
100 private bool m_hackSentFly = false;
101 private int m_requestedUpdateFrequency = 0;
102 private Vector3 m_taintPosition = Vector3.Zero;
103 public uint m_localID = 0;
104 public bool m_returnCollisions = false;
105 // taints and their non-tainted counterparts
106 public bool m_isPhysical = false; // the current physical status
107 public bool m_tainted_isPhysical = false; // set when the physical status is tainted (false=not existing in physics engine, true=existing)
108 public float MinimumGroundFlightOffset = 3f;
109
110 private float m_tainted_CAPSULE_LENGTH; // set when the capsule length changes.
111 private float m_tiltMagnitudeWhenProjectedOnXYPlane = 0.1131371f; // used to introduce a fixed tilt because a straight-up capsule falls through terrain, probably a bug in terrain collider
112
113
114 private float m_buoyancy = 0f;
115
116 // private CollisionLocker ode;
117
118 private string m_name = String.Empty;
119
120 private bool[] m_colliderarr = new bool[11];
121 private bool[] m_colliderGroundarr = new bool[11];
122
123 // Default we're a Character
124 private CollisionCategories m_collisionCategories = (CollisionCategories.Character);
125
126 // Default, Collide with Other Geometries, spaces, bodies and characters.
127 private CollisionCategories m_collisionFlags = (CollisionCategories.Geom
128 | CollisionCategories.Space
129 | CollisionCategories.Body
130 | CollisionCategories.Character
131 | CollisionCategories.Land);
132 public IntPtr Body = IntPtr.Zero;
133 private OdeScene _parent_scene;
134 public IntPtr Shell = IntPtr.Zero;
135 public IntPtr Amotor = IntPtr.Zero;
136 public d.Mass ShellMass;
137 public bool collidelock = false;
138
139 public int m_eventsubscription = 0;
140 private CollisionEventUpdate CollisionEventsThisFrame = new CollisionEventUpdate();
141
142 // unique UUID of this character object
143 public UUID m_uuid;
144 public bool bad = false;
145
146 public OdeCharacter(String avName, OdeScene parent_scene, Vector3 pos, CollisionLocker dode, Vector3 size, float pid_d, float pid_p, float capsule_radius, float tensor, float density, float height_fudge_factor, float walk_divisor, float rundivisor)
147 {
148 m_uuid = UUID.Random();
149
150 if (pos.IsFinite())
151 {
152 if (pos.Z > 9999999f)
153 {
154 pos.Z = parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
155 }
156 if (pos.Z < -90000f)
157 {
158 pos.Z = parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
159 }
160 _position = pos;
161 m_taintPosition.X = pos.X;
162 m_taintPosition.Y = pos.Y;
163 m_taintPosition.Z = pos.Z;
164 }
165 else
166 {
167 _position = new Vector3(((float)_parent_scene.WorldExtents.X * 0.5f), ((float)_parent_scene.WorldExtents.Y * 0.5f), parent_scene.GetTerrainHeightAtXY(128f, 128f) + 10f);
168 m_taintPosition.X = _position.X;
169 m_taintPosition.Y = _position.Y;
170 m_taintPosition.Z = _position.Z;
171 m_log.Warn("[PHYSICS]: Got NaN Position on Character Create");
172 }
173
174 _parent_scene = parent_scene;
175
176 PID_D = pid_d;
177 PID_P = pid_p;
178 CAPSULE_RADIUS = capsule_radius;
179 m_tensor = tensor;
180 m_density = density;
181 heightFudgeFactor = height_fudge_factor;
182 walkDivisor = walk_divisor;
183 runDivisor = rundivisor;
184
185 // m_StandUpRotation =
186 // new d.Matrix3(0.5f, 0.7071068f, 0.5f, -0.7071068f, 0f, 0.7071068f, 0.5f, -0.7071068f,
187 // 0.5f);
188
189 for (int i = 0; i < 11; i++)
190 {
191 m_colliderarr[i] = false;
192 }
193 CAPSULE_LENGTH = (size.Z * 1.15f) - CAPSULE_RADIUS * 2.0f;
194 //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
195 m_tainted_CAPSULE_LENGTH = CAPSULE_LENGTH;
196
197 m_isPhysical = false; // current status: no ODE information exists
198 m_tainted_isPhysical = true; // new tainted status: need to create ODE information
199
200 _parent_scene.AddPhysicsActorTaint(this);
201
202 m_name = avName;
203 }
204
205 public override int PhysicsActorType
206 {
207 get { return (int) ActorTypes.Agent; }
208 set { return; }
209 }
210
211 /// <summary>
212 /// If this is set, the avatar will move faster
213 /// </summary>
214 public override bool SetAlwaysRun
215 {
216 get { return m_alwaysRun; }
217 set { m_alwaysRun = value; }
218 }
219
220 public override uint LocalID
221 {
222 set { m_localID = value; }
223 }
224
225 public override bool Grabbed
226 {
227 set { return; }
228 }
229
230 public override bool Selected
231 {
232 set { return; }
233 }
234
235 public override float Buoyancy
236 {
237 get { return m_buoyancy; }
238 set { m_buoyancy = value; }
239 }
240
241 public override bool FloatOnWater
242 {
243 set { return; }
244 }
245
246 public override bool IsPhysical
247 {
248 get { return false; }
249 set { return; }
250 }
251
252 public override bool ThrottleUpdates
253 {
254 get { return false; }
255 set { return; }
256 }
257
258 public override bool Flying
259 {
260 get { return flying; }
261 set { flying = value; }
262 }
263
264 /// <summary>
265 /// Returns if the avatar is colliding in general.
266 /// This includes the ground and objects and avatar.
267 /// </summary>
268 public override bool IsColliding
269 {
270 get { return m_iscolliding; }
271 set
272 {
273 int i;
274 int truecount = 0;
275 int falsecount = 0;
276
277 if (m_colliderarr.Length >= 10)
278 {
279 for (i = 0; i < 10; i++)
280 {
281 m_colliderarr[i] = m_colliderarr[i + 1];
282 }
283 }
284 m_colliderarr[10] = value;
285
286 for (i = 0; i < 11; i++)
287 {
288 if (m_colliderarr[i])
289 {
290 truecount++;
291 }
292 else
293 {
294 falsecount++;
295 }
296 }
297
298 // Equal truecounts and false counts means we're colliding with something.
299
300 if (falsecount > 1.2*truecount)
301 {
302 m_iscolliding = false;
303 }
304 else
305 {
306 m_iscolliding = true;
307 }
308 if (m_wascolliding != m_iscolliding)
309 {
310 //base.SendCollisionUpdate(new CollisionEventUpdate());
311 }
312 m_wascolliding = m_iscolliding;
313 }
314 }
315
316 /// <summary>
317 /// Returns if an avatar is colliding with the ground
318 /// </summary>
319 public override bool CollidingGround
320 {
321 get { return m_iscollidingGround; }
322 set
323 {
324 // Collisions against the ground are not really reliable
325 // So, to get a consistant value we have to average the current result over time
326 // Currently we use 1 second = 10 calls to this.
327 int i;
328 int truecount = 0;
329 int falsecount = 0;
330
331 if (m_colliderGroundarr.Length >= 10)
332 {
333 for (i = 0; i < 10; i++)
334 {
335 m_colliderGroundarr[i] = m_colliderGroundarr[i + 1];
336 }
337 }
338 m_colliderGroundarr[10] = value;
339
340 for (i = 0; i < 11; i++)
341 {
342 if (m_colliderGroundarr[i])
343 {
344 truecount++;
345 }
346 else
347 {
348 falsecount++;
349 }
350 }
351
352 // Equal truecounts and false counts means we're colliding with something.
353
354 if (falsecount > 1.2*truecount)
355 {
356 m_iscollidingGround = false;
357 }
358 else
359 {
360 m_iscollidingGround = true;
361 }
362 if (m_wascollidingGround != m_iscollidingGround)
363 {
364 //base.SendCollisionUpdate(new CollisionEventUpdate());
365 }
366 m_wascollidingGround = m_iscollidingGround;
367 }
368 }
369
370 /// <summary>
371 /// Returns if the avatar is colliding with an object
372 /// </summary>
373 public override bool CollidingObj
374 {
375 get { return m_iscollidingObj; }
376 set
377 {
378 m_iscollidingObj = value;
379 if (value)
380 m_pidControllerActive = false;
381 else
382 m_pidControllerActive = true;
383 }
384 }
385
386 /// <summary>
387 /// turn the PID controller on or off.
388 /// The PID Controller will turn on all by itself in many situations
389 /// </summary>
390 /// <param name="status"></param>
391 public void SetPidStatus(bool status)
392 {
393 m_pidControllerActive = status;
394 }
395
396 public override bool Stopped
397 {
398 get { return _zeroFlag; }
399 }
400
401 /// <summary>
402 /// This 'puts' an avatar somewhere in the physics space.
403 /// Not really a good choice unless you 'know' it's a good
404 /// spot otherwise you're likely to orbit the avatar.
405 /// </summary>
406 public override Vector3 Position
407 {
408 get { return _position; }
409 set
410 {
411 if (Body == IntPtr.Zero || Shell == IntPtr.Zero)
412 {
413 if (value.IsFinite())
414 {
415 if (value.Z > 9999999f)
416 {
417 value.Z = _parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
418 }
419 if (value.Z < -90000f)
420 {
421 value.Z = _parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
422 }
423
424 _position.X = value.X;
425 _position.Y = value.Y;
426 _position.Z = value.Z;
427
428 m_taintPosition.X = value.X;
429 m_taintPosition.Y = value.Y;
430 m_taintPosition.Z = value.Z;
431 _parent_scene.AddPhysicsActorTaint(this);
432 }
433 else
434 {
435 m_log.Warn("[PHYSICS]: Got a NaN Position from Scene on a Character");
436 }
437 }
438 }
439 }
440
441 public override Vector3 RotationalVelocity
442 {
443 get { return m_rotationalVelocity; }
444 set { m_rotationalVelocity = value; }
445 }
446
447 /// <summary>
448 /// This property sets the height of the avatar only. We use the height to make sure the avatar stands up straight
449 /// and use it to offset landings properly
450 /// </summary>
451 public override Vector3 Size
452 {
453 get { return new Vector3(CAPSULE_RADIUS * 2, CAPSULE_RADIUS * 2, CAPSULE_LENGTH); }
454 set
455 {
456 if (value.IsFinite())
457 {
458 m_pidControllerActive = true;
459
460 Vector3 SetSize = value;
461 m_tainted_CAPSULE_LENGTH = (SetSize.Z*1.15f) - CAPSULE_RADIUS*2.0f;
462 //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
463
464 Velocity = Vector3.Zero;
465
466 _parent_scene.AddPhysicsActorTaint(this);
467 }
468 else
469 {
470 m_log.Warn("[PHYSICS]: Got a NaN Size from Scene on a Character");
471 }
472 }
473 }
474
475 private void AlignAvatarTiltWithCurrentDirectionOfMovement(Vector3 movementVector)
476 {
477 movementVector.Z = 0f;
478 float magnitude = (float)Math.Sqrt((double)(movementVector.X * movementVector.X + movementVector.Y * movementVector.Y));
479 if (magnitude < 0.1f) return;
480
481 // normalize the velocity vector
482 float invMagnitude = 1.0f / magnitude;
483 movementVector.X *= invMagnitude;
484 movementVector.Y *= invMagnitude;
485
486 // if we change the capsule heading too often, the capsule can fall down
487 // therefore we snap movement vector to just 1 of 4 predefined directions (ne, nw, se, sw),
488 // meaning only 4 possible capsule tilt orientations
489 if (movementVector.X > 0)
490 {
491 // east
492 if (movementVector.Y > 0)
493 {
494 // northeast
495 movementVector.X = (float)Math.Sqrt(2.0);
496 movementVector.Y = (float)Math.Sqrt(2.0);
497 }
498 else
499 {
500 // southeast
501 movementVector.X = (float)Math.Sqrt(2.0);
502 movementVector.Y = -(float)Math.Sqrt(2.0);
503 }
504 }
505 else
506 {
507 // west
508 if (movementVector.Y > 0)
509 {
510 // northwest
511 movementVector.X = -(float)Math.Sqrt(2.0);
512 movementVector.Y = (float)Math.Sqrt(2.0);
513 }
514 else
515 {
516 // southwest
517 movementVector.X = -(float)Math.Sqrt(2.0);
518 movementVector.Y = -(float)Math.Sqrt(2.0);
519 }
520 }
521
522
523 // movementVector.Z is zero
524
525 // calculate tilt components based on desired amount of tilt and current (snapped) heading.
526 // the "-" sign is to force the tilt to be OPPOSITE the direction of movement.
527 float xTiltComponent = -movementVector.X * m_tiltMagnitudeWhenProjectedOnXYPlane;
528 float yTiltComponent = -movementVector.Y * m_tiltMagnitudeWhenProjectedOnXYPlane;
529
530 //m_log.Debug("[PHYSICS] changing avatar tilt");
531 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, xTiltComponent);
532 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, xTiltComponent); // must be same as lowstop, else a different, spurious tilt is introduced
533 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, yTiltComponent);
534 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, yTiltComponent); // same as lowstop
535 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, 0f);
536 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0f); // same as lowstop
537 }
538
539 /// <summary>
540 /// This creates the Avatar's physical Surrogate at the position supplied
541 /// </summary>
542 /// <param name="npositionX"></param>
543 /// <param name="npositionY"></param>
544 /// <param name="npositionZ"></param>
545
546 // WARNING: This MUST NOT be called outside of ProcessTaints, else we can have unsynchronized access
547 // to ODE internals. ProcessTaints is called from within thread-locked Simulate(), so it is the only
548 // place that is safe to call this routine AvatarGeomAndBodyCreation.
549 private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ, float tensor)
550 {
551 //CAPSULE_LENGTH = -5;
552 //CAPSULE_RADIUS = -5;
553 int dAMotorEuler = 1;
554 _parent_scene.waitForSpaceUnlock(_parent_scene.space);
555 if (CAPSULE_LENGTH <= 0)
556 {
557 m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
558 CAPSULE_LENGTH = 0.01f;
559
560 }
561
562 if (CAPSULE_RADIUS <= 0)
563 {
564 m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
565 CAPSULE_RADIUS = 0.01f;
566
567 }
568 Shell = d.CreateCapsule(_parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH);
569
570 d.GeomSetCategoryBits(Shell, (int)m_collisionCategories);
571 d.GeomSetCollideBits(Shell, (int)m_collisionFlags);
572
573 d.MassSetCapsuleTotal(out ShellMass, m_mass, 2, CAPSULE_RADIUS, CAPSULE_LENGTH);
574 Body = d.BodyCreate(_parent_scene.world);
575 d.BodySetPosition(Body, npositionX, npositionY, npositionZ);
576
577 _position.X = npositionX;
578 _position.Y = npositionY;
579 _position.Z = npositionZ;
580
581
582 m_taintPosition.X = npositionX;
583 m_taintPosition.Y = npositionY;
584 m_taintPosition.Z = npositionZ;
585
586 d.BodySetMass(Body, ref ShellMass);
587 d.Matrix3 m_caprot;
588 // 90 Stand up on the cap of the capped cyllinder
589 if (_parent_scene.IsAvCapsuleTilted)
590 {
591 d.RFromAxisAndAngle(out m_caprot, 1, 0, 1, (float)(Math.PI / 2));
592 }
593 else
594 {
595 d.RFromAxisAndAngle(out m_caprot, 0, 0, 1, (float)(Math.PI / 2));
596 }
597
598
599 d.GeomSetRotation(Shell, ref m_caprot);
600 d.BodySetRotation(Body, ref m_caprot);
601
602 d.GeomSetBody(Shell, Body);
603
604
605 // The purpose of the AMotor here is to keep the avatar's physical
606 // surrogate from rotating while moving
607 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero);
608 d.JointAttach(Amotor, Body, IntPtr.Zero);
609 d.JointSetAMotorMode(Amotor, dAMotorEuler);
610 d.JointSetAMotorNumAxes(Amotor, 3);
611 d.JointSetAMotorAxis(Amotor, 0, 0, 1, 0, 0);
612 d.JointSetAMotorAxis(Amotor, 1, 0, 0, 1, 0);
613 d.JointSetAMotorAxis(Amotor, 2, 0, 0, 0, 1);
614 d.JointSetAMotorAngle(Amotor, 0, 0);
615 d.JointSetAMotorAngle(Amotor, 1, 0);
616 d.JointSetAMotorAngle(Amotor, 2, 0);
617
618 // These lowstops and high stops are effectively (no wiggle room)
619 if (_parent_scene.IsAvCapsuleTilted)
620 {
621 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, -0.000000000001f);
622 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0.000000000001f);
623 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, -0.000000000001f);
624 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0.000000000001f);
625 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0.000000000001f);
626 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0.000000000001f);
627 }
628 else
629 {
630 #region Documentation of capsule motor LowStop and HighStop parameters
631 // Intentionally introduce some tilt into the capsule by setting
632 // the motor stops to small epsilon values. This small tilt prevents
633 // the capsule from falling into the terrain; a straight-up capsule
634 // (with -0..0 motor stops) falls into the terrain for reasons yet
635 // to be comprehended in their entirety.
636 #endregion
637 AlignAvatarTiltWithCurrentDirectionOfMovement(Vector3.Zero);
638 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, 0.08f);
639 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0f);
640 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, 0.08f);
641 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0.08f); // must be same as lowstop, else a different, spurious tilt is introduced
642 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0f); // same as lowstop
643 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0.08f); // same as lowstop
644 }
645
646 // Fudge factor is 1f by default, we're setting it to 0. We don't want it to Fudge or the
647 // capped cyllinder will fall over
648 d.JointSetAMotorParam(Amotor, (int)dParam.FudgeFactor, 0f);
649 d.JointSetAMotorParam(Amotor, (int)dParam.FMax, tensor);
650
651 //d.Matrix3 bodyrotation = d.BodyGetRotation(Body);
652 //d.QfromR(
653 //d.Matrix3 checkrotation = new d.Matrix3(0.7071068,0.5, -0.7071068,
654 //
655 //m_log.Info("[PHYSICSAV]: Rotation: " + bodyrotation.M00 + " : " + bodyrotation.M01 + " : " + bodyrotation.M02 + " : " + bodyrotation.M10 + " : " + bodyrotation.M11 + " : " + bodyrotation.M12 + " : " + bodyrotation.M20 + " : " + bodyrotation.M21 + " : " + bodyrotation.M22);
656 //standupStraight();
657 }
658
659 //
660 /// <summary>
661 /// Uses the capped cyllinder volume formula to calculate the avatar's mass.
662 /// This may be used in calculations in the scene/scenepresence
663 /// </summary>
664 public override float Mass
665 {
666 get
667 {
668 float AVvolume = (float) (Math.PI*Math.Pow(CAPSULE_RADIUS, 2)*CAPSULE_LENGTH);
669 return m_density*AVvolume;
670 }
671 }
672 public override void link(PhysicsActor obj)
673 {
674
675 }
676
677 public override void delink()
678 {
679
680 }
681
682 public override void LockAngularMotion(Vector3 axis)
683 {
684
685 }
686
687// This code is very useful. Written by DanX0r. We're just not using it right now.
688// Commented out to prevent a warning.
689//
690// private void standupStraight()
691// {
692// // The purpose of this routine here is to quickly stabilize the Body while it's popped up in the air.
693// // The amotor needs a few seconds to stabilize so without it, the avatar shoots up sky high when you
694// // change appearance and when you enter the simulator
695// // After this routine is done, the amotor stabilizes much quicker
696// d.Vector3 feet;
697// d.Vector3 head;
698// d.BodyGetRelPointPos(Body, 0.0f, 0.0f, -1.0f, out feet);
699// d.BodyGetRelPointPos(Body, 0.0f, 0.0f, 1.0f, out head);
700// float posture = head.Z - feet.Z;
701
702// // restoring force proportional to lack of posture:
703// float servo = (2.5f - posture) * POSTURE_SERVO;
704// d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, servo, 0.0f, 0.0f, 1.0f);
705// d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, -servo, 0.0f, 0.0f, -1.0f);
706// //d.Matrix3 bodyrotation = d.BodyGetRotation(Body);
707// //m_log.Info("[PHYSICSAV]: Rotation: " + bodyrotation.M00 + " : " + bodyrotation.M01 + " : " + bodyrotation.M02 + " : " + bodyrotation.M10 + " : " + bodyrotation.M11 + " : " + bodyrotation.M12 + " : " + bodyrotation.M20 + " : " + bodyrotation.M21 + " : " + bodyrotation.M22);
708// }
709
710 public override Vector3 Force
711 {
712 get { return _target_velocity; }
713 set { return; }
714 }
715
716 public override int VehicleType
717 {
718 get { return 0; }
719 set { return; }
720 }
721
722 public override void VehicleFloatParam(int param, float value)
723 {
724
725 }
726
727 public override void VehicleVectorParam(int param, Vector3 value)
728 {
729
730 }
731
732 public override void VehicleRotationParam(int param, Quaternion rotation)
733 {
734
735 }
736
737 public override void VehicleFlags(int flags, bool remove)
738 {
739 }
740
741 public override void SetVolumeDetect(int param)
742 {
743
744 }
745
746 public override Vector3 CenterOfMass
747 {
748 get { return Vector3.Zero; }
749 }
750
751 public override Vector3 GeometricCenter
752 {
753 get { return Vector3.Zero; }
754 }
755
756 public override PrimitiveBaseShape Shape
757 {
758 set { return; }
759 }
760
761 public override Vector3 Velocity
762 {
763 get {
764 // There's a problem with Vector3.Zero! Don't Use it Here!
765 if (_zeroFlag)
766 return Vector3.Zero;
767 m_lastUpdateSent = false;
768 return _velocity;
769 }
770 set
771 {
772 if (value.IsFinite())
773 {
774 m_pidControllerActive = true;
775 _target_velocity = value;
776 }
777 else
778 {
779 m_log.Warn("[PHYSICS]: Got a NaN velocity from Scene in a Character");
780 }
781 }
782 }
783
784 public override Vector3 Torque
785 {
786 get { return Vector3.Zero; }
787 set { return; }
788 }
789
790 public override float CollisionScore
791 {
792 get { return 0f; }
793 set { }
794 }
795
796 public override bool Kinematic
797 {
798 get { return false; }
799 set { }
800 }
801
802 public override Quaternion Orientation
803 {
804 get { return Quaternion.Identity; }
805 set {
806 //Matrix3 or = Orientation.ToRotationMatrix();
807 //d.Matrix3 ord = new d.Matrix3(or.m00, or.m10, or.m20, or.m01, or.m11, or.m21, or.m02, or.m12, or.m22);
808 //d.BodySetRotation(Body, ref ord);
809 }
810 }
811
812 public override Vector3 Acceleration
813 {
814 get { return _acceleration; }
815 }
816
817 public void SetAcceleration(Vector3 accel)
818 {
819 m_pidControllerActive = true;
820 _acceleration = accel;
821 }
822
823 /// <summary>
824 /// Adds the force supplied to the Target Velocity
825 /// The PID controller takes this target velocity and tries to make it a reality
826 /// </summary>
827 /// <param name="force"></param>
828 public override void AddForce(Vector3 force, bool pushforce)
829 {
830 if (force.IsFinite())
831 {
832 if (pushforce)
833 {
834 m_pidControllerActive = false;
835 force *= 100f;
836 doForce(force);
837 // If uncommented, things get pushed off world
838 //
839 // m_log.Debug("Push!");
840 // _target_velocity.X += force.X;
841 // _target_velocity.Y += force.Y;
842 // _target_velocity.Z += force.Z;
843 }
844 else
845 {
846 m_pidControllerActive = true;
847 _target_velocity.X += force.X;
848 _target_velocity.Y += force.Y;
849 _target_velocity.Z += force.Z;
850 }
851 }
852 else
853 {
854 m_log.Warn("[PHYSICS]: Got a NaN force applied to a Character");
855 }
856 //m_lastUpdateSent = false;
857 }
858
859 public override void AddAngularForce(Vector3 force, bool pushforce)
860 {
861
862 }
863
864 /// <summary>
865 /// After all of the forces add up with 'add force' we apply them with doForce
866 /// </summary>
867 /// <param name="force"></param>
868 public void doForce(Vector3 force)
869 {
870 if (!collidelock)
871 {
872 d.BodyAddForce(Body, force.X, force.Y, force.Z);
873 //d.BodySetRotation(Body, ref m_StandUpRotation);
874 //standupStraight();
875
876 }
877 }
878
879 public override void SetMomentum(Vector3 momentum)
880 {
881 }
882
883
884 /// <summary>
885 /// Called from Simulate
886 /// This is the avatar's movement control + PID Controller
887 /// </summary>
888 /// <param name="timeStep"></param>
889 public void Move(float timeStep, List<OdeCharacter> defects)
890 {
891 // no lock; for now it's only called from within Simulate()
892
893 // If the PID Controller isn't active then we set our force
894 // calculating base velocity to the current position
895
896 if (Body == IntPtr.Zero)
897 return;
898
899 if (m_pidControllerActive == false)
900 {
901 _zeroPosition = d.BodyGetPosition(Body);
902 }
903 //PidStatus = true;
904
905 d.Vector3 localpos = d.BodyGetPosition(Body);
906 Vector3 localPos = new Vector3(localpos.X, localpos.Y, localpos.Z);
907
908 if (!localPos.IsFinite())
909 {
910
911 m_log.Warn("[PHYSICS]: Avatar Position is non-finite!");
912 defects.Add(this);
913 // _parent_scene.RemoveCharacter(this);
914
915 // destroy avatar capsule and related ODE data
916 if (Amotor != IntPtr.Zero)
917 {
918 // Kill the Amotor
919 d.JointDestroy(Amotor);
920 Amotor = IntPtr.Zero;
921 }
922
923 //kill the Geometry
924 _parent_scene.waitForSpaceUnlock(_parent_scene.space);
925
926 if (Body != IntPtr.Zero)
927 {
928 //kill the body
929 d.BodyDestroy(Body);
930
931 Body = IntPtr.Zero;
932 }
933
934 if (Shell != IntPtr.Zero)
935 {
936 d.GeomDestroy(Shell);
937 _parent_scene.geom_name_map.Remove(Shell);
938 Shell = IntPtr.Zero;
939 }
940
941 return;
942 }
943
944 Vector3 vec = Vector3.Zero;
945 d.Vector3 vel = d.BodyGetLinearVel(Body);
946
947 float movementdivisor = 1f;
948
949 if (!m_alwaysRun)
950 {
951 movementdivisor = walkDivisor;
952 }
953 else
954 {
955 movementdivisor = runDivisor;
956 }
957
958 // if velocity is zero, use position control; otherwise, velocity control
959 if (_target_velocity.X == 0.0f && _target_velocity.Y == 0.0f && _target_velocity.Z == 0.0f && m_iscolliding)
960 {
961 // keep track of where we stopped. No more slippin' & slidin'
962 if (!_zeroFlag)
963 {
964 _zeroFlag = true;
965 _zeroPosition = d.BodyGetPosition(Body);
966 }
967 if (m_pidControllerActive)
968 {
969 // We only want to deactivate the PID Controller if we think we want to have our surrogate
970 // react to the physics scene by moving it's position.
971 // Avatar to Avatar collisions
972 // Prim to avatar collisions
973
974 d.Vector3 pos = d.BodyGetPosition(Body);
975 float errX = _zeroPosition.X - pos.X;
976 float errY = _zeroPosition.Y - pos.Y;
977 if( (Math.Abs(errX) > 0.1f) || (Math.Abs(errY) > 0.1f) )
978 {
979 vec.X = (_target_velocity.X - vel.X) * (PID_D) + (errX) * (PID_P * 2);
980 vec.Y = (_target_velocity.Y - vel.Y) * (PID_D) + (errY) * (PID_P * 2);
981 }
982 else
983 { // close, jump to lateral destination
984 d.BodySetPosition(Body, _zeroPosition.X, _zeroPosition.Y, pos.Z);
985 }
986 if (flying)
987 {
988 vec.Z = (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P;
989 }
990 }
991 //PidStatus = true;
992 }
993 else
994 {
995 m_pidControllerActive = true;
996 _zeroFlag = false;
997 if (m_iscolliding && !flying)
998 {
999 // We're standing on something
1000 vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D);
1001 vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D);
1002 }
1003 else if (m_iscolliding && flying)
1004 {
1005 // We're flying and colliding with something
1006 vec.X = ((_target_velocity.X/movementdivisor) - vel.X)*(PID_D / 16);
1007 vec.Y = ((_target_velocity.Y/movementdivisor) - vel.Y)*(PID_D / 16);
1008 }
1009 else if (!m_iscolliding && flying)
1010 {
1011 // we're in mid air suspended
1012 vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D/6);
1013 vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D/6);
1014 }
1015
1016 if (m_iscolliding && !flying && _target_velocity.Z > 0.0f)
1017 {
1018 // We're colliding with something and we're not flying but we're moving
1019 // This means we're walking or running.
1020 d.Vector3 pos = d.BodyGetPosition(Body);
1021 vec.Z = (_target_velocity.Z - vel.Z)*PID_D + (_zeroPosition.Z - pos.Z)*PID_P;
1022 if (_target_velocity.X > 0)
1023 {
1024 vec.X = ((_target_velocity.X - vel.X)/1.2f)*PID_D;
1025 }
1026 if (_target_velocity.Y > 0)
1027 {
1028 vec.Y = ((_target_velocity.Y - vel.Y)/1.2f)*PID_D;
1029 }
1030 }
1031 else if (!m_iscolliding && !flying)
1032 {
1033 // we're not colliding and we're not flying so that means we're falling!
1034 // m_iscolliding includes collisions with the ground.
1035
1036 // d.Vector3 pos = d.BodyGetPosition(Body);
1037 if (Math.Abs(_target_velocity.X) > 0)
1038 {
1039 vec.X = ((_target_velocity.X - vel.X)/1.2f)*PID_D;
1040 }
1041 if (Math.Abs(_target_velocity.Y) > 0)
1042 {
1043 vec.Y = ((_target_velocity.Y - vel.Y)/1.2f)*PID_D;
1044 }
1045 }
1046
1047 if (flying)
1048 {
1049 vec.Z = (_target_velocity.Z - vel.Z) * (PID_D);
1050 }
1051 }
1052 if (flying)
1053 {
1054 vec.Z += ((-1 * _parent_scene.gravityz)*m_mass);
1055
1056 //Added for auto fly height. Kitto Flora
1057 //d.Vector3 pos = d.BodyGetPosition(Body);
1058 float target_altitude = _parent_scene.GetTerrainHeightAtXY(_position.X, _position.Y) + MinimumGroundFlightOffset;
1059
1060 if (_position.Z < target_altitude)
1061 {
1062 vec.Z += (target_altitude - _position.Z) * PID_P * 5.0f;
1063 }
1064 // end add Kitto Flora
1065 }
1066 if (vec.IsFinite())
1067 {
1068 if (!vec.ApproxEquals(Vector3.Zero, 0.01f))
1069 {
1070 doForce(vec);
1071 if (!_zeroFlag)
1072 {
1073 AlignAvatarTiltWithCurrentDirectionOfMovement(vec);
1074 }
1075 }
1076 }
1077 else
1078 {
1079 m_log.Warn("[PHYSICS]: Got a NaN force vector in Move()");
1080 m_log.Warn("[PHYSICS]: Avatar Position is non-finite!");
1081 defects.Add(this);
1082 // _parent_scene.RemoveCharacter(this);
1083 // destroy avatar capsule and related ODE data
1084 if (Amotor != IntPtr.Zero)
1085 {
1086 // Kill the Amotor
1087 d.JointDestroy(Amotor);
1088 Amotor = IntPtr.Zero;
1089 }
1090 //kill the Geometry
1091 _parent_scene.waitForSpaceUnlock(_parent_scene.space);
1092
1093 if (Body != IntPtr.Zero)
1094 {
1095 //kill the body
1096 d.BodyDestroy(Body);
1097
1098 Body = IntPtr.Zero;
1099 }
1100
1101 if (Shell != IntPtr.Zero)
1102 {
1103 d.GeomDestroy(Shell);
1104 _parent_scene.geom_name_map.Remove(Shell);
1105 Shell = IntPtr.Zero;
1106 }
1107 }
1108 }
1109
1110 /// <summary>
1111 /// Updates the reported position and velocity. This essentially sends the data up to ScenePresence.
1112 /// </summary>
1113 public void UpdatePositionAndVelocity()
1114 {
1115 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
1116 d.Vector3 vec;
1117 try
1118 {
1119 vec = d.BodyGetPosition(Body);
1120 }
1121 catch (NullReferenceException)
1122 {
1123 bad = true;
1124 _parent_scene.BadCharacter(this);
1125 vec = new d.Vector3(_position.X, _position.Y, _position.Z);
1126 base.RaiseOutOfBounds(_position); // Tells ScenePresence that there's a problem!
1127 m_log.WarnFormat("[ODEPLUGIN]: Avatar Null reference for Avatar {0}, physical actor {1}", m_name, m_uuid);
1128 }
1129
1130
1131 // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!)
1132 if (vec.X < 0.0f) vec.X = 0.0f;
1133 if (vec.Y < 0.0f) vec.Y = 0.0f;
1134 if (vec.X > (int)_parent_scene.WorldExtents.X - 0.05f) vec.X = (int)_parent_scene.WorldExtents.X - 0.05f;
1135 if (vec.Y > (int)_parent_scene.WorldExtents.Y - 0.05f) vec.Y = (int)_parent_scene.WorldExtents.Y - 0.05f;
1136
1137 _position.X = vec.X;
1138 _position.Y = vec.Y;
1139 _position.Z = vec.Z;
1140
1141 // Did we move last? = zeroflag
1142 // This helps keep us from sliding all over
1143
1144 if (_zeroFlag)
1145 {
1146 _velocity.X = 0.0f;
1147 _velocity.Y = 0.0f;
1148 _velocity.Z = 0.0f;
1149
1150 // Did we send out the 'stopped' message?
1151 if (!m_lastUpdateSent)
1152 {
1153 m_lastUpdateSent = true;
1154 //base.RequestPhysicsterseUpdate();
1155
1156 }
1157 }
1158 else
1159 {
1160 m_lastUpdateSent = false;
1161 try
1162 {
1163 vec = d.BodyGetLinearVel(Body);
1164 }
1165 catch (NullReferenceException)
1166 {
1167 vec.X = _velocity.X;
1168 vec.Y = _velocity.Y;
1169 vec.Z = _velocity.Z;
1170 }
1171 _velocity.X = (vec.X);
1172 _velocity.Y = (vec.Y);
1173
1174 _velocity.Z = (vec.Z);
1175
1176 if (_velocity.Z < -6 && !m_hackSentFall)
1177 {
1178 m_hackSentFall = true;
1179 m_pidControllerActive = false;
1180 }
1181 else if (flying && !m_hackSentFly)
1182 {
1183 //m_hackSentFly = true;
1184 //base.SendCollisionUpdate(new CollisionEventUpdate());
1185 }
1186 else
1187 {
1188 m_hackSentFly = false;
1189 m_hackSentFall = false;
1190 }
1191 }
1192 }
1193
1194 /// <summary>
1195 /// Cleanup the things we use in the scene.
1196 /// </summary>
1197 public void Destroy()
1198 {
1199 m_tainted_isPhysical = false;
1200 _parent_scene.AddPhysicsActorTaint(this);
1201 }
1202
1203 public override void CrossingFailure()
1204 {
1205 }
1206
1207 public override Vector3 PIDTarget { set { return; } }
1208 public override bool PIDActive { set { return; } }
1209 public override float PIDTau { set { return; } }
1210
1211 public override float PIDHoverHeight { set { return; } }
1212 public override bool PIDHoverActive { set { return; } }
1213 public override PIDHoverType PIDHoverType { set { return; } }
1214 public override float PIDHoverTau { set { return; } }
1215
1216 public override Quaternion APIDTarget{ set { return; } }
1217
1218 public override bool APIDActive{ set { return; } }
1219
1220 public override float APIDStrength{ set { return; } }
1221
1222 public override float APIDDamping{ set { return; } }
1223
1224
1225 public override void SubscribeEvents(int ms)
1226 {
1227 m_requestedUpdateFrequency = ms;
1228 m_eventsubscription = ms;
1229 _parent_scene.addCollisionEventReporting(this);
1230 }
1231 public override void UnSubscribeEvents()
1232 {
1233 _parent_scene.remCollisionEventReporting(this);
1234 m_requestedUpdateFrequency = 0;
1235 m_eventsubscription = 0;
1236 }
1237 public void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
1238 {
1239 if (m_eventsubscription > 0)
1240 {
1241 CollisionEventsThisFrame.addCollider(CollidedWith, contact);
1242 }
1243 }
1244
1245 public void SendCollisions()
1246 {
1247 if (m_eventsubscription > m_requestedUpdateFrequency)
1248 {
1249 if (CollisionEventsThisFrame != null)
1250 {
1251 base.SendCollisionUpdate(CollisionEventsThisFrame);
1252 }
1253 CollisionEventsThisFrame = new CollisionEventUpdate();
1254 m_eventsubscription = 0;
1255 }
1256 }
1257 public override bool SubscribedEvents()
1258 {
1259 if (m_eventsubscription > 0)
1260 return true;
1261 return false;
1262 }
1263
1264 public void ProcessTaints(float timestep)
1265 {
1266
1267 if (m_tainted_isPhysical != m_isPhysical)
1268 {
1269 if (m_tainted_isPhysical)
1270 {
1271 // Create avatar capsule and related ODE data
1272 if (!(Shell == IntPtr.Zero && Body == IntPtr.Zero && Amotor == IntPtr.Zero))
1273 {
1274 m_log.Warn("[PHYSICS]: re-creating the following avatar ODE data, even though it already exists - "
1275 + (Shell!=IntPtr.Zero ? "Shell ":"")
1276 + (Body!=IntPtr.Zero ? "Body ":"")
1277 + (Amotor!=IntPtr.Zero ? "Amotor ":""));
1278 }
1279 AvatarGeomAndBodyCreation(_position.X, _position.Y, _position.Z, m_tensor);
1280
1281 _parent_scene.geom_name_map[Shell] = m_name;
1282 _parent_scene.actor_name_map[Shell] = (PhysicsActor)this;
1283 _parent_scene.AddCharacter(this);
1284 }
1285 else
1286 {
1287 _parent_scene.RemoveCharacter(this);
1288 // destroy avatar capsule and related ODE data
1289 if (Amotor != IntPtr.Zero)
1290 {
1291 // Kill the Amotor
1292 d.JointDestroy(Amotor);
1293 Amotor = IntPtr.Zero;
1294 }
1295 //kill the Geometry
1296 _parent_scene.waitForSpaceUnlock(_parent_scene.space);
1297
1298 if (Body != IntPtr.Zero)
1299 {
1300 //kill the body
1301 d.BodyDestroy(Body);
1302
1303 Body = IntPtr.Zero;
1304 }
1305
1306 if (Shell != IntPtr.Zero)
1307 {
1308 d.GeomDestroy(Shell);
1309 _parent_scene.geom_name_map.Remove(Shell);
1310 Shell = IntPtr.Zero;
1311 }
1312
1313 }
1314
1315 m_isPhysical = m_tainted_isPhysical;
1316 }
1317
1318 if (m_tainted_CAPSULE_LENGTH != CAPSULE_LENGTH)
1319 {
1320 if (Shell != IntPtr.Zero && Body != IntPtr.Zero && Amotor != IntPtr.Zero)
1321 {
1322
1323 m_pidControllerActive = true;
1324 // no lock needed on _parent_scene.OdeLock because we are called from within the thread lock in OdePlugin's simulate()
1325 d.JointDestroy(Amotor);
1326 float prevCapsule = CAPSULE_LENGTH;
1327 CAPSULE_LENGTH = m_tainted_CAPSULE_LENGTH;
1328 //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
1329 d.BodyDestroy(Body);
1330 d.GeomDestroy(Shell);
1331 AvatarGeomAndBodyCreation(_position.X, _position.Y,
1332 _position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2), m_tensor);
1333 Velocity = Vector3.Zero;
1334
1335 _parent_scene.geom_name_map[Shell] = m_name;
1336 _parent_scene.actor_name_map[Shell] = (PhysicsActor)this;
1337 }
1338 else
1339 {
1340 m_log.Warn("[PHYSICS]: trying to change capsule size, but the following ODE data is missing - "
1341 + (Shell==IntPtr.Zero ? "Shell ":"")
1342 + (Body==IntPtr.Zero ? "Body ":"")
1343 + (Amotor==IntPtr.Zero ? "Amotor ":""));
1344 }
1345 }
1346
1347 if (!m_taintPosition.ApproxEquals(_position, 0.05f))
1348 {
1349 if (Body != IntPtr.Zero)
1350 {
1351 d.BodySetPosition(Body, m_taintPosition.X, m_taintPosition.Y, m_taintPosition.Z);
1352
1353 _position.X = m_taintPosition.X;
1354 _position.Y = m_taintPosition.Y;
1355 _position.Z = m_taintPosition.Z;
1356 }
1357 }
1358
1359 }
1360
1361 internal void AddCollisionFrameTime(int p)
1362 {
1363 // protect it from overflow crashing
1364 if (m_eventsubscription + p >= int.MaxValue)
1365 m_eventsubscription = 0;
1366 m_eventsubscription += p;
1367 }
1368 }
1369}
diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs
new file mode 100644
index 0000000..fbe52c8
--- /dev/null
+++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs
@@ -0,0 +1,3788 @@
1/* Copyright (c) Contributors, http://opensimulator.org/
2 * See CONTRIBUTORS.TXT for a full list of copyright holders.
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are met:
5 * * Redistributions of source code must retain the above copyright
6 * notice, this list of conditions and the following disclaimer.
7 * * Redistributions in binary form must reproduce the above copyright
8 * notice, this list of conditions and the following disclaimer in the
9 * documentation and/or other materials provided with the distribution.
10 * * Neither the name of the OpenSimulator Project nor the
11 * names of its contributors may be used to endorse or promote products
12 * derived from this software without specific prior written permission.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
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
23 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 * Revised March 5th 2010 by Kitto Flora. ODEDynamics.cs
26 * rolled into ODEPrim.cs
27 */
28
29using System;
30using System.Collections.Generic;
31using System.Reflection;
32using System.Runtime.InteropServices;
33using System.Threading;
34using log4net;
35using OpenMetaverse;
36using Ode.NET;
37using OpenSim.Framework;
38using OpenSim.Region.Physics.Manager;
39
40
41namespace OpenSim.Region.Physics.OdePlugin
42{
43 /// <summary>
44 /// Various properties that ODE uses for AMotors but isn't exposed in ODE.NET so we must define them ourselves.
45 /// </summary>
46
47 public class OdePrim : PhysicsActor
48 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50
51 private Vector3 _position;
52 private Vector3 _velocity;
53 private Vector3 _torque;
54 private Vector3 m_lastVelocity;
55 private Vector3 m_lastposition;
56 private Quaternion m_lastorientation = new Quaternion();
57 private Vector3 m_rotationalVelocity;
58 private Vector3 _size;
59 private Vector3 _acceleration;
60 // private d.Vector3 _zeroPosition = new d.Vector3(0.0f, 0.0f, 0.0f);
61 private Quaternion _orientation;
62 private Vector3 m_taintposition;
63 private Vector3 m_taintsize;
64 private Vector3 m_taintVelocity;
65 private Vector3 m_taintTorque;
66 private Quaternion m_taintrot;
67 private Vector3 m_angularEnable = Vector3.One; // Current setting
68 private Vector3 m_taintAngularLock = Vector3.One; // Request from LSL
69
70
71 private IntPtr Amotor = IntPtr.Zero;
72
73 private Vector3 m_PIDTarget;
74 private float m_PIDTau;
75 private float PID_D = 35f;
76 private float PID_G = 25f;
77 private bool m_usePID = false;
78
79 private Quaternion m_APIDTarget = new Quaternion();
80 private float m_APIDStrength = 0.5f;
81 private float m_APIDDamping = 0.5f;
82 private bool m_useAPID = false;
83
84 // These next 7 params apply to llSetHoverHeight(float height, integer water, float tau),
85 // do not confuse with VEHICLE HOVER
86
87 private float m_PIDHoverHeight;
88 private float m_PIDHoverTau;
89 private bool m_useHoverPID;
90 private PIDHoverType m_PIDHoverType = PIDHoverType.Ground;
91 private float m_targetHoverHeight;
92 private float m_groundHeight;
93 private float m_waterHeight;
94 private float m_buoyancy; //m_buoyancy set by llSetBuoyancy()
95
96 // private float m_tensor = 5f;
97 private int body_autodisable_frames = 20;
98
99
100 private const CollisionCategories m_default_collisionFlags = (CollisionCategories.Geom
101 | CollisionCategories.Space
102 | CollisionCategories.Body
103 | CollisionCategories.Character
104 );
105 private bool m_taintshape;
106 private bool m_taintPhysics;
107 private bool m_collidesLand = true;
108 private bool m_collidesWater;
109 public bool m_returnCollisions;
110
111 // Default we're a Geometry
112 private CollisionCategories m_collisionCategories = (CollisionCategories.Geom);
113
114 // Default, Collide with Other Geometries, spaces and Bodies
115 private CollisionCategories m_collisionFlags = m_default_collisionFlags;
116
117 public bool m_taintremove;
118 public bool m_taintdisable;
119 public bool m_disabled;
120 public bool m_taintadd;
121 public bool m_taintselected;
122 public bool m_taintCollidesWater;
123
124 public uint m_localID;
125
126 //public GCHandle gc;
127 private CollisionLocker ode;
128
129 private bool m_taintforce = false;
130 private bool m_taintaddangularforce = false;
131 private Vector3 m_force;
132 private List<Vector3> m_forcelist = new List<Vector3>();
133 private List<Vector3> m_angularforcelist = new List<Vector3>();
134
135 private IMesh _mesh;
136 private PrimitiveBaseShape _pbs;
137 private OdeScene _parent_scene;
138 public IntPtr m_targetSpace = IntPtr.Zero;
139 public IntPtr prim_geom;
140 public IntPtr prev_geom;
141 public IntPtr _triMeshData;
142
143 private IntPtr _linkJointGroup = IntPtr.Zero;
144 private PhysicsActor _parent;
145 private PhysicsActor m_taintparent;
146
147 private List<OdePrim> childrenPrim = new List<OdePrim>();
148
149 private bool iscolliding;
150 private bool m_isphysical;
151 private bool m_isSelected;
152
153 internal bool m_isVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively
154
155 private bool m_throttleUpdates;
156 private int throttleCounter;
157 public int m_interpenetrationcount;
158 public float m_collisionscore;
159 public int m_roundsUnderMotionThreshold;
160 private int m_crossingfailures;
161
162 public bool outofBounds;
163 private float m_density = 10.000006836f; // Aluminum g/cm3;
164
165 public bool _zeroFlag; // if body has been stopped
166 private bool m_lastUpdateSent;
167
168 public IntPtr Body = IntPtr.Zero;
169 public String m_primName;
170 private Vector3 _target_velocity;
171 public d.Mass pMass;
172
173 public int m_eventsubscription;
174 private CollisionEventUpdate CollisionEventsThisFrame;
175
176 private IntPtr m_linkJoint = IntPtr.Zero;
177
178 public volatile bool childPrim;
179
180 internal int m_material = (int)Material.Wood;
181
182 private int frcount = 0; // Used to limit dynamics debug output to
183 private int revcount = 0; // Reverse motion while > 0
184
185 private IntPtr m_body = IntPtr.Zero;
186
187 // Vehicle properties ============================================================================================
188 private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind
189 // private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier
190 private VehicleFlag m_flags = (VehicleFlag) 0; // Bit settings:
191 // HOVER_TERRAIN_ONLY
192 // HOVER_GLOBAL_HEIGHT
193 // NO_DEFLECTION_UP
194 // HOVER_WATER_ONLY
195 // HOVER_UP_ONLY
196 // LIMIT_MOTOR_UP
197 // LIMIT_ROLL_ONLY
198
199 // Linear properties
200 private Vector3 m_linearMotorDirection = Vector3.Zero; // (was m_linearMotorDirectionLASTSET) the (local) Velocity
201 //requested by LSL
202 private float m_linearMotorTimescale = 0; // Motor Attack rate set by LSL
203 private float m_linearMotorDecayTimescale = 0; // Motor Decay rate set by LSL
204 private Vector3 m_linearFrictionTimescale = Vector3.Zero; // General Friction set by LSL
205
206 private Vector3 m_lLinMotorDVel = Vector3.Zero; // decayed motor
207 private Vector3 m_lLinObjectVel = Vector3.Zero; // local frame object velocity
208 private Vector3 m_wLinObjectVel = Vector3.Zero; // world frame object velocity
209
210 //Angular properties
211 private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor
212
213 private float m_angularMotorTimescale = 0; // motor angular Attack rate set by LSL
214 private float m_angularMotorDecayTimescale = 0; // motor angular Decay rate set by LSL
215 private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular Friction set by LSL
216
217 private Vector3 m_angularMotorDVel = Vector3.Zero; // decayed angular motor
218// private Vector3 m_angObjectVel = Vector3.Zero; // current body angular velocity
219 private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body
220
221 //Deflection properties
222 // private float m_angularDeflectionEfficiency = 0;
223 // private float m_angularDeflectionTimescale = 0;
224 // private float m_linearDeflectionEfficiency = 0;
225 // private float m_linearDeflectionTimescale = 0;
226
227 //Banking properties
228 // private float m_bankingEfficiency = 0;
229 // private float m_bankingMix = 0;
230 // private float m_bankingTimescale = 0;
231
232 //Hover and Buoyancy properties
233 private float m_VhoverHeight = 0f;
234// private float m_VhoverEfficiency = 0f;
235 private float m_VhoverTimescale = 0f;
236 private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height
237 private float m_VehicleBuoyancy = 0f; // Set by VEHICLE_BUOYANCY, for a vehicle.
238 // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity)
239 // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity.
240 // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity.
241
242 //Attractor properties
243 private float m_verticalAttractionEfficiency = 1.0f; // damped
244 private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor.
245
246
247
248
249
250
251 public OdePrim(String primName, OdeScene parent_scene, Vector3 pos, Vector3 size,
252 Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical, CollisionLocker dode)
253 {
254 ode = dode;
255 if (!pos.IsFinite())
256 {
257 pos = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f),
258 parent_scene.GetTerrainHeightAtXY(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f)) + 0.5f);
259 m_log.Warn("[PHYSICS]: Got nonFinite Object create Position");
260 }
261
262 _position = pos;
263 m_taintposition = pos;
264 PID_D = parent_scene.bodyPIDD;
265 PID_G = parent_scene.bodyPIDG;
266 m_density = parent_scene.geomDefaultDensity;
267 // m_tensor = parent_scene.bodyMotorJointMaxforceTensor;
268 body_autodisable_frames = parent_scene.bodyFramesAutoDisable;
269
270
271 prim_geom = IntPtr.Zero;
272 prev_geom = IntPtr.Zero;
273
274 if (!pos.IsFinite())
275 {
276 size = new Vector3(0.5f, 0.5f, 0.5f);
277 m_log.Warn("[PHYSICS]: Got nonFinite Object create Size");
278 }
279
280 if (size.X <= 0) size.X = 0.01f;
281 if (size.Y <= 0) size.Y = 0.01f;
282 if (size.Z <= 0) size.Z = 0.01f;
283
284 _size = size;
285 m_taintsize = _size;
286
287 if (!QuaternionIsFinite(rotation))
288 {
289 rotation = Quaternion.Identity;
290 m_log.Warn("[PHYSICS]: Got nonFinite Object create Rotation");
291 }
292
293 _orientation = rotation;
294 m_taintrot = _orientation;
295 _mesh = mesh;
296 _pbs = pbs;
297
298 _parent_scene = parent_scene;
299 m_targetSpace = (IntPtr)0;
300
301// if (pos.Z < 0)
302 if (pos.Z < parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y))
303 m_isphysical = false;
304 else
305 {
306 m_isphysical = pisPhysical;
307 // If we're physical, we need to be in the master space for now.
308 // linksets *should* be in a space together.. but are not currently
309 if (m_isphysical)
310 m_targetSpace = _parent_scene.space;
311 }
312 m_primName = primName;
313 m_taintadd = true;
314 _parent_scene.AddPhysicsActorTaint(this);
315 // don't do .add() here; old geoms get recycled with the same hash
316 }
317
318 public override int PhysicsActorType
319 {
320 get { return (int) ActorTypes.Prim; }
321 set { return; }
322 }
323
324 public override bool SetAlwaysRun
325 {
326 get { return false; }
327 set { return; }
328 }
329
330 public override uint LocalID
331 {
332 set {
333 //m_log.Info("[PHYSICS]: Setting TrackerID: " + value);
334 m_localID = value; }
335 }
336
337 public override bool Grabbed
338 {
339 set { return; }
340 }
341
342 public override bool Selected
343 {
344 set {
345
346//Console.WriteLine("Sel {0} {1} {2}", m_primName, value, m_isphysical);
347 // This only makes the object not collidable if the object
348 // is physical or the object is modified somehow *IN THE FUTURE*
349 // without this, if an avatar selects prim, they can walk right
350 // through it while it's selected
351 m_collisionscore = 0;
352 if ((m_isphysical && !_zeroFlag) || !value)
353 {
354 m_taintselected = value;
355 _parent_scene.AddPhysicsActorTaint(this);
356 }
357 else
358 {
359 m_taintselected = value;
360 m_isSelected = value;
361 }
362 if(m_isSelected) disableBodySoft();
363 }
364 }
365
366 public override bool IsPhysical
367 {
368 get { return m_isphysical; }
369 set
370 {
371 m_isphysical = value;
372 if (!m_isphysical)
373 { // Zero the remembered last velocity
374 m_lastVelocity = Vector3.Zero;
375 if (m_type != Vehicle.TYPE_NONE) Halt();
376 }
377 }
378 }
379
380 public void setPrimForRemoval()
381 {
382 m_taintremove = true;
383 }
384
385 public override bool Flying
386 {
387 // no flying prims for you
388 get { return false; }
389 set { }
390 }
391
392 public override bool IsColliding
393 {
394 get { return iscolliding; }
395 set { iscolliding = value; }
396 }
397
398 public override bool CollidingGround
399 {
400 get { return false; }
401 set { return; }
402 }
403
404 public override bool CollidingObj
405 {
406 get { return false; }
407 set { return; }
408 }
409
410 public override bool ThrottleUpdates
411 {
412 get { return m_throttleUpdates; }
413 set { m_throttleUpdates = value; }
414 }
415
416 public override bool Stopped
417 {
418 get { return _zeroFlag; }
419 }
420
421 public override Vector3 Position
422 {
423 get { return _position; }
424
425 set { _position = value;
426 //m_log.Info("[PHYSICS]: " + _position.ToString());
427 }
428 }
429
430 public override Vector3 Size
431 {
432 get { return _size; }
433 set
434 {
435 if (value.IsFinite())
436 {
437 _size = value;
438 }
439 else
440 {
441 m_log.Warn("[PHYSICS]: Got NaN Size on object");
442 }
443 }
444 }
445
446 public override float Mass
447 {
448 get { return CalculateMass(); }
449 }
450
451 public override Vector3 Force
452 {
453 //get { return Vector3.Zero; }
454 get { return m_force; }
455 set
456 {
457 if (value.IsFinite())
458 {
459 m_force = value;
460 }
461 else
462 {
463 m_log.Warn("[PHYSICS]: NaN in Force Applied to an Object");
464 }
465 }
466 }
467
468 public override int VehicleType
469 {
470 get { return (int)m_type; }
471 set { ProcessTypeChange((Vehicle)value); }
472 }
473
474 public override void VehicleFloatParam(int param, float value)
475 {
476 ProcessFloatVehicleParam((Vehicle) param, value);
477 }
478
479 public override void VehicleVectorParam(int param, Vector3 value)
480 {
481 ProcessVectorVehicleParam((Vehicle) param, value);
482 }
483
484 public override void VehicleRotationParam(int param, Quaternion rotation)
485 {
486 ProcessRotationVehicleParam((Vehicle) param, rotation);
487 }
488
489 public override void VehicleFlags(int param, bool remove)
490 {
491 ProcessVehicleFlags(param, remove);
492 }
493
494 public override void SetVolumeDetect(int param)
495 {
496 lock (_parent_scene.OdeLock)
497 {
498 m_isVolumeDetect = (param!=0);
499 }
500 }
501
502 public override Vector3 CenterOfMass
503 {
504 get { return Vector3.Zero; }
505 }
506
507 public override Vector3 GeometricCenter
508 {
509 get { return Vector3.Zero; }
510 }
511
512 public override PrimitiveBaseShape Shape
513 {
514 set
515 {
516 _pbs = value;
517 m_taintshape = true;
518 }
519 }
520
521 public override Vector3 Velocity
522 {
523 get
524 {
525 // Averate previous velocity with the new one so
526 // client object interpolation works a 'little' better
527 if (_zeroFlag)
528 return Vector3.Zero;
529
530 Vector3 returnVelocity = Vector3.Zero;
531 returnVelocity.X = (m_lastVelocity.X + _velocity.X)/2;
532 returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y)/2;
533 returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z)/2;
534 return returnVelocity;
535 }
536 set
537 {
538 if (value.IsFinite())
539 {
540 _velocity = value;
541
542 m_taintVelocity = value;
543 _parent_scene.AddPhysicsActorTaint(this);
544 }
545 else
546 {
547 m_log.Warn("[PHYSICS]: Got NaN Velocity in Object");
548 }
549
550 }
551 }
552
553 public override Vector3 Torque
554 {
555 get
556 {
557 if (!m_isphysical || Body == IntPtr.Zero)
558 return Vector3.Zero;
559
560 return _torque;
561 }
562
563 set
564 {
565 if (value.IsFinite())
566 {
567 m_taintTorque = value;
568 _parent_scene.AddPhysicsActorTaint(this);
569 }
570 else
571 {
572 m_log.Warn("[PHYSICS]: Got NaN Torque in Object");
573 }
574 }
575 }
576
577 public override float CollisionScore
578 {
579 get { return m_collisionscore; }
580 set { m_collisionscore = value; }
581 }
582
583 public override bool Kinematic
584 {
585 get { return false; }
586 set { }
587 }
588
589 public override Quaternion Orientation
590 {
591 get { return _orientation; }
592 set
593 {
594 if (QuaternionIsFinite(value))
595 {
596 _orientation = value;
597 }
598 else
599 m_log.Warn("[PHYSICS]: Got NaN quaternion Orientation from Scene in Object");
600
601 }
602 }
603
604
605 public override bool FloatOnWater
606 {
607 set {
608 m_taintCollidesWater = value;
609 _parent_scene.AddPhysicsActorTaint(this);
610 }
611 }
612
613 public override void SetMomentum(Vector3 momentum)
614 {
615 }
616
617 public override Vector3 PIDTarget
618 {
619 set
620 {
621 if (value.IsFinite())
622 {
623 m_PIDTarget = value;
624 }
625 else
626 m_log.Warn("[PHYSICS]: Got NaN PIDTarget from Scene on Object");
627 }
628 }
629 public override bool PIDActive { set { m_usePID = value; } }
630 public override float PIDTau { set { m_PIDTau = value; } }
631
632 // For RotLookAt
633 public override Quaternion APIDTarget { set { m_APIDTarget = value; } }
634 public override bool APIDActive { set { m_useAPID = value; } }
635 public override float APIDStrength { set { m_APIDStrength = value; } }
636 public override float APIDDamping { set { m_APIDDamping = value; } }
637
638 public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } }
639 public override bool PIDHoverActive { set { m_useHoverPID = value; } }
640 public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } }
641 public override float PIDHoverTau { set { m_PIDHoverTau = value; } }
642
643 internal static bool QuaternionIsFinite(Quaternion q)
644 {
645 if (Single.IsNaN(q.X) || Single.IsInfinity(q.X))
646 return false;
647 if (Single.IsNaN(q.Y) || Single.IsInfinity(q.Y))
648 return false;
649 if (Single.IsNaN(q.Z) || Single.IsInfinity(q.Z))
650 return false;
651 if (Single.IsNaN(q.W) || Single.IsInfinity(q.W))
652 return false;
653 return true;
654 }
655
656 public override Vector3 Acceleration // client updates read data via here
657 {
658 get { return _acceleration; }
659 }
660
661
662 public void SetAcceleration(Vector3 accel) // No one calls this, and it would not do anything.
663 {
664 _acceleration = accel;
665 }
666
667 public override void AddForce(Vector3 force, bool pushforce)
668 {
669 if (force.IsFinite())
670 {
671 lock (m_forcelist)
672 m_forcelist.Add(force);
673
674 m_taintforce = true;
675 }
676 else
677 {
678 m_log.Warn("[PHYSICS]: Got Invalid linear force vector from Scene in Object");
679 }
680 //m_log.Info("[PHYSICS]: Added Force:" + force.ToString() + " to prim at " + Position.ToString());
681 }
682
683 public override void AddAngularForce(Vector3 force, bool pushforce)
684 {
685 if (force.IsFinite())
686 {
687 m_angularforcelist.Add(force);
688 m_taintaddangularforce = true;
689 }
690 else
691 {
692 m_log.Warn("[PHYSICS]: Got Invalid Angular force vector from Scene in Object");
693 }
694 }
695
696 public override Vector3 RotationalVelocity
697 {
698 get
699 {
700 return m_rotationalVelocity;
701 }
702 set
703 {
704 if (value.IsFinite())
705 {
706 m_rotationalVelocity = value;
707 }
708 else
709 {
710 m_log.Warn("[PHYSICS]: Got NaN RotationalVelocity in Object");
711 }
712 }
713 }
714
715 public override void CrossingFailure()
716 {
717 m_crossingfailures++;
718 if (m_crossingfailures > _parent_scene.geomCrossingFailuresBeforeOutofbounds)
719 {
720 base.RaiseOutOfBounds(_position);
721 return;
722 }
723 else if (m_crossingfailures == _parent_scene.geomCrossingFailuresBeforeOutofbounds)
724 {
725 m_log.Warn("[PHYSICS]: Too many crossing failures for: " + m_primName);
726 }
727 }
728
729 public override float Buoyancy
730 {
731 get { return m_buoyancy; }
732 set { m_buoyancy = value; }
733 }
734
735 public override void link(PhysicsActor obj)
736 {
737 m_taintparent = obj;
738 }
739
740 public override void delink()
741 {
742 m_taintparent = null;
743 }
744
745 public override void LockAngularMotion(Vector3 axis)
746 {
747 // reverse the zero/non zero values for ODE.
748 if (axis.IsFinite())
749 {
750 axis.X = (axis.X > 0) ? 1f : 0f;
751 axis.Y = (axis.Y > 0) ? 1f : 0f;
752 axis.Z = (axis.Z > 0) ? 1f : 0f;
753 m_log.DebugFormat("[axislock]: <{0},{1},{2}>", axis.X, axis.Y, axis.Z);
754 m_taintAngularLock = axis;
755 }
756 else
757 {
758 m_log.Warn("[PHYSICS]: Got NaN locking axis from Scene on Object");
759 }
760 }
761
762
763 public void SetGeom(IntPtr geom)
764 {
765 prev_geom = prim_geom;
766 prim_geom = geom;
767//Console.WriteLine("SetGeom to " + prim_geom + " for " + m_primName);
768 if (prim_geom != IntPtr.Zero)
769 {
770 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
771 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
772 }
773
774 if (childPrim)
775 {
776 if (_parent != null && _parent is OdePrim)
777 {
778 OdePrim parent = (OdePrim)_parent;
779//Console.WriteLine("SetGeom calls ChildSetGeom");
780 parent.ChildSetGeom(this);
781 }
782 }
783 //m_log.Warn("Setting Geom to: " + prim_geom);
784 }
785
786 public void enableBodySoft()
787 {
788 if (!childPrim)
789 {
790 if (m_isphysical && Body != IntPtr.Zero)
791 {
792 d.BodyEnable(Body);
793 if (m_type != Vehicle.TYPE_NONE)
794 Enable(Body, _parent_scene);
795 }
796
797 m_disabled = false;
798 }
799 }
800
801 public void disableBodySoft()
802 {
803 m_disabled = true;
804
805 if (m_isphysical && Body != IntPtr.Zero)
806 {
807 d.BodyDisable(Body);
808 Halt();
809 }
810 }
811
812 public void enableBody()
813 {
814 // Don't enable this body if we're a child prim
815 // this should be taken care of in the parent function not here
816 if (!childPrim)
817 {
818 // Sets the geom to a body
819 Body = d.BodyCreate(_parent_scene.world);
820
821 setMass();
822 d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
823 d.Quaternion myrot = new d.Quaternion();
824 myrot.X = _orientation.X;
825 myrot.Y = _orientation.Y;
826 myrot.Z = _orientation.Z;
827 myrot.W = _orientation.W;
828 d.BodySetQuaternion(Body, ref myrot);
829 d.GeomSetBody(prim_geom, Body);
830 m_collisionCategories |= CollisionCategories.Body;
831 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
832
833 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
834 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
835
836 d.BodySetAutoDisableFlag(Body, true);
837 d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
838
839 // disconnect from world gravity so we can apply buoyancy
840 d.BodySetGravityMode (Body, false);
841
842 m_interpenetrationcount = 0;
843 m_collisionscore = 0;
844 m_disabled = false;
845
846 if (m_type != Vehicle.TYPE_NONE)
847 {
848 Enable(Body, _parent_scene);
849 }
850
851 _parent_scene.addActivePrim(this);
852 }
853 }
854
855 #region Mass Calculation
856
857 private float CalculateMass()
858 {
859 float volume = 0;
860
861 // No material is passed to the physics engines yet.. soo..
862 // we're using the m_density constant in the class definition
863
864 float returnMass = 0;
865
866 switch (_pbs.ProfileShape)
867 {
868 case ProfileShape.Square:
869 // Profile Volume
870
871 volume = _size.X*_size.Y*_size.Z;
872
873 // If the user has 'hollowed out'
874 // ProfileHollow is one of those 0 to 50000 values :P
875 // we like percentages better.. so turning into a percentage
876
877 if (((float) _pbs.ProfileHollow/50000f) > 0.0)
878 {
879 float hollowAmount = (float) _pbs.ProfileHollow/50000f;
880
881 // calculate the hollow volume by it's shape compared to the prim shape
882 float hollowVolume = 0;
883 switch (_pbs.HollowShape)
884 {
885 case HollowShape.Square:
886 case HollowShape.Same:
887 // Cube Hollow volume calculation
888 float hollowsizex = _size.X*hollowAmount;
889 float hollowsizey = _size.Y*hollowAmount;
890 float hollowsizez = _size.Z*hollowAmount;
891 hollowVolume = hollowsizex*hollowsizey*hollowsizez;
892 break;
893
894 case HollowShape.Circle:
895 // Hollow shape is a perfect cyllinder in respect to the cube's scale
896 // Cyllinder hollow volume calculation
897 float hRadius = _size.X/2;
898 float hLength = _size.Z;
899
900 // pi * r2 * h
901 hollowVolume = ((float) (Math.PI*Math.Pow(hRadius, 2)*hLength)*hollowAmount);
902 break;
903
904 case HollowShape.Triangle:
905 // Equilateral Triangular Prism volume hollow calculation
906 // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y
907
908 float aLength = _size.Y;
909 // 1/2 abh
910 hollowVolume = (float) ((0.5*aLength*_size.X*_size.Z)*hollowAmount);
911 break;
912
913 default:
914 hollowVolume = 0;
915 break;
916 }
917 volume = volume - hollowVolume;
918 }
919
920 break;
921 case ProfileShape.Circle:
922 if (_pbs.PathCurve == (byte)Extrusion.Straight)
923 {
924 // Cylinder
925 float volume1 = (float)(Math.PI * Math.Pow(_size.X/2, 2) * _size.Z);
926 float volume2 = (float)(Math.PI * Math.Pow(_size.Y/2, 2) * _size.Z);
927
928 // Approximating the cylinder's irregularity.
929 if (volume1 > volume2)
930 {
931 volume = (float)volume1 - (volume1 - volume2);
932 }
933 else if (volume2 > volume1)
934 {
935 volume = (float)volume2 - (volume2 - volume1);
936 }
937 else
938 {
939 // Regular cylinder
940 volume = volume1;
941 }
942 }
943 else
944 {
945 // We don't know what the shape is yet, so use default
946 volume = _size.X * _size.Y * _size.Z;
947 }
948 // If the user has 'hollowed out'
949 // ProfileHollow is one of those 0 to 50000 values :P
950 // we like percentages better.. so turning into a percentage
951
952 if (((float)_pbs.ProfileHollow / 50000f) > 0.0)
953 {
954 float hollowAmount = (float)_pbs.ProfileHollow / 50000f;
955
956 // calculate the hollow volume by it's shape compared to the prim shape
957 float hollowVolume = 0;
958 switch (_pbs.HollowShape)
959 {
960 case HollowShape.Same:
961 case HollowShape.Circle:
962 // Hollow shape is a perfect cyllinder in respect to the cube's scale
963 // Cyllinder hollow volume calculation
964 float hRadius = _size.X / 2;
965 float hLength = _size.Z;
966
967 // pi * r2 * h
968 hollowVolume = ((float)(Math.PI * Math.Pow(hRadius, 2) * hLength) * hollowAmount);
969 break;
970
971 case HollowShape.Square:
972 // Cube Hollow volume calculation
973 float hollowsizex = _size.X * hollowAmount;
974 float hollowsizey = _size.Y * hollowAmount;
975 float hollowsizez = _size.Z * hollowAmount;
976 hollowVolume = hollowsizex * hollowsizey * hollowsizez;
977 break;
978
979 case HollowShape.Triangle:
980 // Equilateral Triangular Prism volume hollow calculation
981 // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y
982
983 float aLength = _size.Y;
984 // 1/2 abh
985 hollowVolume = (float)((0.5 * aLength * _size.X * _size.Z) * hollowAmount);
986 break;
987
988 default:
989 hollowVolume = 0;
990 break;
991 }
992 volume = volume - hollowVolume;
993 }
994 break;
995
996 case ProfileShape.HalfCircle:
997 if (_pbs.PathCurve == (byte)Extrusion.Curve1)
998 {
999 if (_size.X == _size.Y && _size.Y == _size.Z)
1000 {
1001 // regular sphere
1002 // v = 4/3 * pi * r^3
1003 float sradius3 = (float)Math.Pow((_size.X / 2), 3);
1004 volume = (float)((4f / 3f) * Math.PI * sradius3);
1005 }
1006 else
1007 {
1008 // we treat this as a box currently
1009 volume = _size.X * _size.Y * _size.Z;
1010 }
1011 }
1012 else
1013 {
1014 // We don't know what the shape is yet, so use default
1015 volume = _size.X * _size.Y * _size.Z;
1016 }
1017 break;
1018
1019 case ProfileShape.EquilateralTriangle:
1020 /*
1021 v = (abs((xB*yA-xA*yB)+(xC*yB-xB*yC)+(xA*yC-xC*yA))/2) * h
1022
1023 // seed mesh
1024 Vertex MM = new Vertex(-0.25f, -0.45f, 0.0f);
1025 Vertex PM = new Vertex(+0.5f, 0f, 0.0f);
1026 Vertex PP = new Vertex(-0.25f, +0.45f, 0.0f);
1027 */
1028 float xA = -0.25f * _size.X;
1029 float yA = -0.45f * _size.Y;
1030
1031 float xB = 0.5f * _size.X;
1032 float yB = 0;
1033
1034 float xC = -0.25f * _size.X;
1035 float yC = 0.45f * _size.Y;
1036
1037 volume = (float)((Math.Abs((xB * yA - xA * yB) + (xC * yB - xB * yC) + (xA * yC - xC * yA)) / 2) * _size.Z);
1038
1039 // If the user has 'hollowed out'
1040 // ProfileHollow is one of those 0 to 50000 values :P
1041 // we like percentages better.. so turning into a percentage
1042 float fhollowFactor = ((float)_pbs.ProfileHollow / 1.9f);
1043 if (((float)fhollowFactor / 50000f) > 0.0)
1044 {
1045 float hollowAmount = (float)fhollowFactor / 50000f;
1046
1047 // calculate the hollow volume by it's shape compared to the prim shape
1048 float hollowVolume = 0;
1049 switch (_pbs.HollowShape)
1050 {
1051 case HollowShape.Same:
1052 case HollowShape.Triangle:
1053 // Equilateral Triangular Prism volume hollow calculation
1054 // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y
1055
1056 float aLength = _size.Y;
1057 // 1/2 abh
1058 hollowVolume = (float)((0.5 * aLength * _size.X * _size.Z) * hollowAmount);
1059 break;
1060
1061 case HollowShape.Square:
1062 // Cube Hollow volume calculation
1063 float hollowsizex = _size.X * hollowAmount;
1064 float hollowsizey = _size.Y * hollowAmount;
1065 float hollowsizez = _size.Z * hollowAmount;
1066 hollowVolume = hollowsizex * hollowsizey * hollowsizez;
1067 break;
1068
1069 case HollowShape.Circle:
1070 // Hollow shape is a perfect cyllinder in respect to the cube's scale
1071 // Cyllinder hollow volume calculation
1072 float hRadius = _size.X / 2;
1073 float hLength = _size.Z;
1074
1075 // pi * r2 * h
1076 hollowVolume = ((float)((Math.PI * Math.Pow(hRadius, 2) * hLength)/2) * hollowAmount);
1077 break;
1078
1079 default:
1080 hollowVolume = 0;
1081 break;
1082 }
1083 volume = volume - hollowVolume;
1084 }
1085 break;
1086
1087 default:
1088 // we don't have all of the volume formulas yet so
1089 // use the common volume formula for all
1090 volume = _size.X*_size.Y*_size.Z;
1091 break;
1092 }
1093
1094 // Calculate Path cut effect on volume
1095 // Not exact, in the triangle hollow example
1096 // They should never be zero or less then zero..
1097 // we'll ignore it if it's less then zero
1098
1099 // ProfileEnd and ProfileBegin are values
1100 // from 0 to 50000
1101
1102 // Turning them back into percentages so that I can cut that percentage off the volume
1103
1104 float PathCutEndAmount = _pbs.ProfileEnd;
1105 float PathCutStartAmount = _pbs.ProfileBegin;
1106 if (((PathCutStartAmount + PathCutEndAmount)/50000f) > 0.0f)
1107 {
1108 float pathCutAmount = ((PathCutStartAmount + PathCutEndAmount)/50000f);
1109
1110 // Check the return amount for sanity
1111 if (pathCutAmount >= 0.99f)
1112 pathCutAmount = 0.99f;
1113
1114 volume = volume - (volume*pathCutAmount);
1115 }
1116 UInt16 taperX = _pbs.PathScaleX;
1117 UInt16 taperY = _pbs.PathScaleY;
1118 float taperFactorX = 0;
1119 float taperFactorY = 0;
1120
1121 // Mass = density * volume
1122 if (taperX != 100)
1123 {
1124 if (taperX > 100)
1125 {
1126 taperFactorX = 1.0f - ((float)taperX / 200);
1127 //m_log.Warn("taperTopFactorX: " + extr.taperTopFactorX.ToString());
1128 }
1129 else
1130 {
1131 taperFactorX = 1.0f - ((100 - (float)taperX) / 100);
1132 //m_log.Warn("taperBotFactorX: " + extr.taperBotFactorX.ToString());
1133 }
1134 volume = (float)volume * ((taperFactorX / 3f) + 0.001f);
1135 }
1136
1137 if (taperY != 100)
1138 {
1139 if (taperY > 100)
1140 {
1141 taperFactorY = 1.0f - ((float)taperY / 200);
1142 //m_log.Warn("taperTopFactorY: " + extr.taperTopFactorY.ToString());
1143 }
1144 else
1145 {
1146 taperFactorY = 1.0f - ((100 - (float)taperY) / 100);
1147 //m_log.Warn("taperBotFactorY: " + extr.taperBotFactorY.ToString());
1148 }
1149 volume = (float)volume * ((taperFactorY / 3f) + 0.001f);
1150 }
1151 returnMass = m_density*volume;
1152 if (returnMass <= 0) returnMass = 0.0001f;//ckrinke: Mass must be greater then zero.
1153
1154
1155
1156 // Recursively calculate mass
1157 bool HasChildPrim = false;
1158 lock (childrenPrim)
1159 {
1160 if (childrenPrim.Count > 0)
1161 {
1162 HasChildPrim = true;
1163 }
1164
1165 }
1166 if (HasChildPrim)
1167 {
1168 OdePrim[] childPrimArr = new OdePrim[0];
1169
1170 lock (childrenPrim)
1171 childPrimArr = childrenPrim.ToArray();
1172
1173 for (int i = 0; i < childPrimArr.Length; i++)
1174 {
1175 if (childPrimArr[i] != null && !childPrimArr[i].m_taintremove)
1176 returnMass += childPrimArr[i].CalculateMass();
1177 // failsafe, this shouldn't happen but with OpenSim, you never know :)
1178 if (i > 256)
1179 break;
1180 }
1181 }
1182 if (returnMass > _parent_scene.maximumMassObject)
1183 returnMass = _parent_scene.maximumMassObject;
1184 return returnMass;
1185 }// end CalculateMass
1186
1187 #endregion
1188
1189 public void setMass()
1190 {
1191 if (Body != (IntPtr) 0)
1192 {
1193 float newmass = CalculateMass();
1194
1195 //m_log.Info("[PHYSICS]: New Mass: " + newmass.ToString());
1196
1197 d.MassSetBoxTotal(out pMass, newmass, _size.X, _size.Y, _size.Z);
1198 d.BodySetMass(Body, ref pMass);
1199 }
1200 }
1201
1202 public void disableBody()
1203 {
1204 //this kills the body so things like 'mesh' can re-create it.
1205 lock (this)
1206 {
1207 if (!childPrim)
1208 {
1209 if (Body != IntPtr.Zero)
1210 {
1211 _parent_scene.remActivePrim(this);
1212 m_collisionCategories &= ~CollisionCategories.Body;
1213 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
1214
1215 if (prim_geom != IntPtr.Zero)
1216 {
1217 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1218 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1219 }
1220
1221
1222 d.BodyDestroy(Body);
1223 lock (childrenPrim)
1224 {
1225 if (childrenPrim.Count > 0)
1226 {
1227 foreach (OdePrim prm in childrenPrim)
1228 {
1229 _parent_scene.remActivePrim(prm);
1230 prm.Body = IntPtr.Zero;
1231 }
1232 }
1233 }
1234 Body = IntPtr.Zero;
1235 }
1236 }
1237 else
1238 {
1239 _parent_scene.remActivePrim(this);
1240
1241 m_collisionCategories &= ~CollisionCategories.Body;
1242 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
1243
1244 if (prim_geom != IntPtr.Zero)
1245 {
1246 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1247 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1248 }
1249
1250
1251 Body = IntPtr.Zero;
1252 }
1253 }
1254 m_disabled = true;
1255 m_collisionscore = 0;
1256 }
1257
1258 private static Dictionary<IMesh, IntPtr> m_MeshToTriMeshMap = new Dictionary<IMesh, IntPtr>();
1259
1260 public void setMesh(OdeScene parent_scene, IMesh mesh)
1261 {
1262 // This sleeper is there to moderate how long it takes between
1263 // setting up the mesh and pre-processing it when we get rapid fire mesh requests on a single object
1264
1265 //Thread.Sleep(10);
1266
1267 //Kill Body so that mesh can re-make the geom
1268 if (IsPhysical && Body != IntPtr.Zero)
1269 {
1270 if (childPrim)
1271 {
1272 if (_parent != null)
1273 {
1274 OdePrim parent = (OdePrim)_parent;
1275 parent.ChildDelink(this);
1276 }
1277 }
1278 else
1279 {
1280 disableBody();
1281 }
1282 }
1283
1284 IntPtr vertices, indices;
1285 int vertexCount, indexCount;
1286 int vertexStride, triStride;
1287 mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap
1288 mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage
1289
1290 mesh.releaseSourceMeshData(); // free up the original mesh data to save memory
1291 if (m_MeshToTriMeshMap.ContainsKey(mesh))
1292 {
1293 _triMeshData = m_MeshToTriMeshMap[mesh];
1294 }
1295 else
1296 {
1297 _triMeshData = d.GeomTriMeshDataCreate();
1298
1299 d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride);
1300 d.GeomTriMeshDataPreprocess(_triMeshData);
1301 m_MeshToTriMeshMap[mesh] = _triMeshData;
1302 }
1303
1304 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1305 try
1306 {
1307 if (prim_geom == IntPtr.Zero)
1308 {
1309 SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null));
1310 }
1311 }
1312 catch (AccessViolationException)
1313 {
1314 m_log.Error("[PHYSICS]: MESH LOCKED");
1315 return;
1316 }
1317
1318
1319 // if (IsPhysical && Body == (IntPtr) 0)
1320 // {
1321 // Recreate the body
1322 // m_interpenetrationcount = 0;
1323 // m_collisionscore = 0;
1324
1325 // enableBody();
1326 // }
1327 }
1328
1329 public void ProcessTaints(float timestep) //=============================================================================
1330 {
1331 if (m_taintadd)
1332 {
1333 changeadd(timestep);
1334 }
1335
1336 if (prim_geom != IntPtr.Zero)
1337 {
1338 if (!_position.ApproxEquals(m_taintposition, 0f))
1339 changemove(timestep);
1340
1341 if (m_taintrot != _orientation)
1342 {
1343 if(childPrim && IsPhysical) // For physical child prim...
1344 {
1345 rotate(timestep);
1346 // KF: ODE will also rotate the parent prim!
1347 // so rotate the root back to where it was
1348 OdePrim parent = (OdePrim)_parent;
1349 parent.rotate(timestep);
1350 }
1351 else
1352 {
1353 //Just rotate the prim
1354 rotate(timestep);
1355 }
1356 }
1357 //
1358
1359 if (m_taintPhysics != m_isphysical && !(m_taintparent != _parent))
1360 changePhysicsStatus(timestep);
1361 //
1362
1363 if (!_size.ApproxEquals(m_taintsize,0f))
1364 changesize(timestep);
1365 //
1366
1367 if (m_taintshape)
1368 changeshape(timestep);
1369 //
1370
1371 if (m_taintforce)
1372 changeAddForce(timestep);
1373
1374 if (m_taintaddangularforce)
1375 changeAddAngularForce(timestep);
1376
1377 if (!m_taintTorque.ApproxEquals(Vector3.Zero, 0.001f))
1378 changeSetTorque(timestep);
1379
1380 if (m_taintdisable)
1381 changedisable(timestep);
1382
1383 if (m_taintselected != m_isSelected)
1384 changeSelectedStatus(timestep);
1385
1386 if (!m_taintVelocity.ApproxEquals(Vector3.Zero, 0.001f))
1387 changevelocity(timestep);
1388
1389 if (m_taintparent != _parent)
1390 changelink(timestep);
1391
1392 if (m_taintCollidesWater != m_collidesWater)
1393 changefloatonwater(timestep);
1394
1395 if (!m_angularEnable.ApproxEquals(m_taintAngularLock,0f))
1396 changeAngularLock(timestep);
1397
1398 }
1399 else
1400 {
1401 m_log.Error("[PHYSICS]: The scene reused a disposed PhysActor! *waves finger*, Don't be evil. A couple of things can cause this. An improper prim breakdown(be sure to set prim_geom to zero after d.GeomDestroy! An improper buildup (creating the geom failed). Or, the Scene Reused a physics actor after disposing it.)");
1402 }
1403 }
1404
1405
1406 private void changeAngularLock(float timestep)
1407 {
1408 if (_parent == null)
1409 {
1410 m_angularEnable = m_taintAngularLock;
1411 }
1412 }
1413
1414 private void changelink(float timestep)
1415 {
1416 // If the newly set parent is not null
1417 // create link
1418 if (_parent == null && m_taintparent != null)
1419 {
1420 if (m_taintparent.PhysicsActorType == (int)ActorTypes.Prim)
1421 {
1422 OdePrim obj = (OdePrim)m_taintparent;
1423 //obj.disableBody();
1424 obj.ParentPrim(this);
1425
1426 /*
1427 if (obj.Body != (IntPtr)0 && Body != (IntPtr)0 && obj.Body != Body)
1428 {
1429 _linkJointGroup = d.JointGroupCreate(0);
1430 m_linkJoint = d.JointCreateFixed(_parent_scene.world, _linkJointGroup);
1431 d.JointAttach(m_linkJoint, obj.Body, Body);
1432 d.JointSetFixed(m_linkJoint);
1433 }
1434 */
1435 }
1436 }
1437 // If the newly set parent is null
1438 // destroy link
1439 else if (_parent != null && m_taintparent == null)
1440 {
1441 if (_parent is OdePrim)
1442 {
1443 OdePrim obj = (OdePrim)_parent;
1444 obj.ChildDelink(this);
1445 childPrim = false;
1446 //_parent = null;
1447 }
1448
1449 /*
1450 if (Body != (IntPtr)0 && _linkJointGroup != (IntPtr)0)
1451 d.JointGroupDestroy(_linkJointGroup);
1452
1453 _linkJointGroup = (IntPtr)0;
1454 m_linkJoint = (IntPtr)0;
1455 */
1456 }
1457
1458 _parent = m_taintparent;
1459 m_taintPhysics = m_isphysical;
1460 }
1461
1462 // I'm the parent
1463 // prim is the child
1464 public void ParentPrim(OdePrim prim)
1465 {
1466 if (this.m_localID != prim.m_localID)
1467 {
1468 if (Body == IntPtr.Zero)
1469 {
1470 Body = d.BodyCreate(_parent_scene.world);
1471 setMass();
1472 }
1473 if (Body != IntPtr.Zero)
1474 {
1475 lock (childrenPrim)
1476 {
1477 if (!childrenPrim.Contains(prim))
1478 {
1479 childrenPrim.Add(prim);
1480
1481 foreach (OdePrim prm in childrenPrim)
1482 {
1483 d.Mass m2;
1484 d.MassSetZero(out m2);
1485 d.MassSetBoxTotal(out m2, prim.CalculateMass(), prm._size.X, prm._size.Y, prm._size.Z);
1486
1487
1488 d.Quaternion quat = new d.Quaternion();
1489 quat.W = prm._orientation.W;
1490 quat.X = prm._orientation.X;
1491 quat.Y = prm._orientation.Y;
1492 quat.Z = prm._orientation.Z;
1493
1494 d.Matrix3 mat = new d.Matrix3();
1495 d.RfromQ(out mat, ref quat);
1496 d.MassRotate(ref m2, ref mat);
1497 d.MassTranslate(ref m2, Position.X - prm.Position.X, Position.Y - prm.Position.Y, Position.Z - prm.Position.Z);
1498 d.MassAdd(ref pMass, ref m2);
1499 }
1500 foreach (OdePrim prm in childrenPrim)
1501 {
1502
1503 prm.m_collisionCategories |= CollisionCategories.Body;
1504 prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1505
1506 if (prm.prim_geom == IntPtr.Zero)
1507 {
1508 m_log.Warn("[PHYSICS]: Unable to link one of the linkset elements. No geom yet");
1509 continue;
1510 }
1511//Console.WriteLine(" GeomSetCategoryBits 1: " + prm.prim_geom + " - " + (int)prm.m_collisionCategories + " for " + m_primName);
1512 d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories);
1513 d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags);
1514
1515
1516 d.Quaternion quat = new d.Quaternion();
1517 quat.W = prm._orientation.W;
1518 quat.X = prm._orientation.X;
1519 quat.Y = prm._orientation.Y;
1520 quat.Z = prm._orientation.Z;
1521
1522 d.Matrix3 mat = new d.Matrix3();
1523 d.RfromQ(out mat, ref quat);
1524 if (Body != IntPtr.Zero)
1525 {
1526 d.GeomSetBody(prm.prim_geom, Body);
1527 prm.childPrim = true;
1528 d.GeomSetOffsetWorldPosition(prm.prim_geom, prm.Position.X , prm.Position.Y, prm.Position.Z);
1529 //d.GeomSetOffsetPosition(prim.prim_geom,
1530 // (Position.X - prm.Position.X) - pMass.c.X,
1531 // (Position.Y - prm.Position.Y) - pMass.c.Y,
1532 // (Position.Z - prm.Position.Z) - pMass.c.Z);
1533 d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat);
1534 //d.GeomSetOffsetRotation(prm.prim_geom, ref mat);
1535 d.MassTranslate(ref pMass, -pMass.c.X, -pMass.c.Y, -pMass.c.Z);
1536 d.BodySetMass(Body, ref pMass);
1537 }
1538 else
1539 {
1540 m_log.Debug("[PHYSICS]:I ain't got no boooooooooddy, no body");
1541 }
1542
1543
1544 prm.m_interpenetrationcount = 0;
1545 prm.m_collisionscore = 0;
1546 prm.m_disabled = false;
1547
1548 prm.Body = Body;
1549 _parent_scene.addActivePrim(prm);
1550 }
1551 m_collisionCategories |= CollisionCategories.Body;
1552 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1553
1554//Console.WriteLine("GeomSetCategoryBits 2: " + prim_geom + " - " + (int)m_collisionCategories + " for " + m_primName);
1555 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1556//Console.WriteLine(" Post GeomSetCategoryBits 2");
1557 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1558
1559
1560 d.Quaternion quat2 = new d.Quaternion();
1561 quat2.W = _orientation.W;
1562 quat2.X = _orientation.X;
1563 quat2.Y = _orientation.Y;
1564 quat2.Z = _orientation.Z;
1565
1566 d.Matrix3 mat2 = new d.Matrix3();
1567 d.RfromQ(out mat2, ref quat2);
1568 d.GeomSetBody(prim_geom, Body);
1569 d.GeomSetOffsetWorldPosition(prim_geom, Position.X - pMass.c.X, Position.Y - pMass.c.Y, Position.Z - pMass.c.Z);
1570 //d.GeomSetOffsetPosition(prim.prim_geom,
1571 // (Position.X - prm.Position.X) - pMass.c.X,
1572 // (Position.Y - prm.Position.Y) - pMass.c.Y,
1573 // (Position.Z - prm.Position.Z) - pMass.c.Z);
1574 //d.GeomSetOffsetRotation(prim_geom, ref mat2);
1575 d.MassTranslate(ref pMass, -pMass.c.X, -pMass.c.Y, -pMass.c.Z);
1576 d.BodySetMass(Body, ref pMass);
1577
1578 d.BodySetAutoDisableFlag(Body, true);
1579 d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
1580
1581
1582 m_interpenetrationcount = 0;
1583 m_collisionscore = 0;
1584 m_disabled = false;
1585
1586 d.BodySetPosition(Body, Position.X, Position.Y, Position.Z);
1587 if (m_type != Vehicle.TYPE_NONE) Enable(Body, _parent_scene);
1588 _parent_scene.addActivePrim(this);
1589 }
1590 }
1591 }
1592 }
1593
1594 }
1595
1596 private void ChildSetGeom(OdePrim odePrim)
1597 {
1598 //if (m_isphysical && Body != IntPtr.Zero)
1599 lock (childrenPrim)
1600 {
1601 foreach (OdePrim prm in childrenPrim)
1602 {
1603 //prm.childPrim = true;
1604 prm.disableBody();
1605 //prm.m_taintparent = null;
1606 //prm._parent = null;
1607 //prm.m_taintPhysics = false;
1608 //prm.m_disabled = true;
1609 //prm.childPrim = false;
1610 }
1611 }
1612 disableBody();
1613
1614
1615 if (Body != IntPtr.Zero)
1616 {
1617 _parent_scene.remActivePrim(this);
1618 }
1619
1620 lock (childrenPrim)
1621 {
1622 foreach (OdePrim prm in childrenPrim)
1623 {
1624 ParentPrim(prm);
1625 }
1626 }
1627
1628 }
1629
1630 private void ChildDelink(OdePrim odePrim)
1631 {
1632 // Okay, we have a delinked child.. need to rebuild the body.
1633 lock (childrenPrim)
1634 {
1635 foreach (OdePrim prm in childrenPrim)
1636 {
1637 prm.childPrim = true;
1638 prm.disableBody();
1639 //prm.m_taintparent = null;
1640 //prm._parent = null;
1641 //prm.m_taintPhysics = false;
1642 //prm.m_disabled = true;
1643 //prm.childPrim = false;
1644 }
1645 }
1646 disableBody();
1647
1648 lock (childrenPrim)
1649 {
1650 childrenPrim.Remove(odePrim);
1651 }
1652
1653 if (Body != IntPtr.Zero)
1654 {
1655 _parent_scene.remActivePrim(this);
1656 }
1657
1658 lock (childrenPrim)
1659 {
1660 foreach (OdePrim prm in childrenPrim)
1661 {
1662 ParentPrim(prm);
1663 }
1664 }
1665 }
1666
1667 private void changeSelectedStatus(float timestep)
1668 {
1669 if (m_taintselected)
1670 {
1671 m_collisionCategories = CollisionCategories.Selected;
1672 m_collisionFlags = (CollisionCategories.Sensor | CollisionCategories.Space);
1673
1674 // We do the body disable soft twice because 'in theory' a collision could have happened
1675 // in between the disabling and the collision properties setting
1676 // which would wake the physical body up from a soft disabling and potentially cause it to fall
1677 // through the ground.
1678
1679 // NOTE FOR JOINTS: this doesn't always work for jointed assemblies because if you select
1680 // just one part of the assembly, the rest of the assembly is non-selected and still simulating,
1681 // so that causes the selected part to wake up and continue moving.
1682
1683 // even if you select all parts of a jointed assembly, it is not guaranteed that the entire
1684 // assembly will stop simulating during the selection, because of the lack of atomicity
1685 // of select operations (their processing could be interrupted by a thread switch, causing
1686 // simulation to continue before all of the selected object notifications trickle down to
1687 // the physics engine).
1688
1689 // e.g. we select 100 prims that are connected by joints. non-atomically, the first 50 are
1690 // selected and disabled. then, due to a thread switch, the selection processing is
1691 // interrupted and the physics engine continues to simulate, so the last 50 items, whose
1692 // selection was not yet processed, continues to simulate. this wakes up ALL of the
1693 // first 50 again. then the last 50 are disabled. then the first 50, which were just woken
1694 // up, start simulating again, which in turn wakes up the last 50.
1695
1696 if (m_isphysical)
1697 {
1698 disableBodySoft();
1699 }
1700
1701 if (prim_geom != IntPtr.Zero)
1702 {
1703 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1704 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1705 }
1706
1707 if (m_isphysical)
1708 {
1709 disableBodySoft();
1710 }
1711 }
1712 else
1713 {
1714 m_collisionCategories = CollisionCategories.Geom;
1715
1716 if (m_isphysical)
1717 m_collisionCategories |= CollisionCategories.Body;
1718
1719 m_collisionFlags = m_default_collisionFlags;
1720
1721 if (m_collidesLand)
1722 m_collisionFlags |= CollisionCategories.Land;
1723 if (m_collidesWater)
1724 m_collisionFlags |= CollisionCategories.Water;
1725
1726 if (prim_geom != IntPtr.Zero)
1727 {
1728 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1729 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1730 }
1731 if (m_isphysical)
1732 {
1733 if (Body != IntPtr.Zero)
1734 {
1735 d.BodySetLinearVel(Body, 0f, 0f, 0f);
1736 d.BodySetForce(Body, 0, 0, 0);
1737 enableBodySoft();
1738 }
1739 }
1740 }
1741
1742 resetCollisionAccounting();
1743 m_isSelected = m_taintselected;
1744 }//end changeSelectedStatus
1745
1746 public void ResetTaints()
1747 {
1748 m_taintposition = _position;
1749 m_taintrot = _orientation;
1750 m_taintPhysics = m_isphysical;
1751 m_taintselected = m_isSelected;
1752 m_taintsize = _size;
1753 m_taintshape = false;
1754 m_taintforce = false;
1755 m_taintdisable = false;
1756 m_taintVelocity = Vector3.Zero;
1757 }
1758
1759 public void CreateGeom(IntPtr m_targetSpace, IMesh _mesh)
1760 {
1761//Console.WriteLine("CreateGeom:");
1762 if (_mesh != null)
1763 {
1764 setMesh(_parent_scene, _mesh);
1765 }
1766 else
1767 {
1768 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
1769 {
1770 if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
1771 {
1772 if (((_size.X / 2f) > 0f))
1773 {
1774 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1775 try
1776 {
1777//Console.WriteLine(" CreateGeom 1");
1778 SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2));
1779 }
1780 catch (AccessViolationException)
1781 {
1782 m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
1783 ode.dunlock(_parent_scene.world);
1784 return;
1785 }
1786 }
1787 else
1788 {
1789 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1790 try
1791 {
1792//Console.WriteLine(" CreateGeom 2");
1793 SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
1794 }
1795 catch (AccessViolationException)
1796 {
1797 m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
1798 ode.dunlock(_parent_scene.world);
1799 return;
1800 }
1801 }
1802 }
1803 else
1804 {
1805 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1806 try
1807 {
1808//Console.WriteLine(" CreateGeom 3");
1809 SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
1810 }
1811 catch (AccessViolationException)
1812 {
1813 m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
1814 ode.dunlock(_parent_scene.world);
1815 return;
1816 }
1817 }
1818 }
1819
1820 else
1821 {
1822 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1823 try
1824 {
1825//Console.WriteLine(" CreateGeom 4");
1826 SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
1827 }
1828 catch (AccessViolationException)
1829 {
1830 m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
1831 ode.dunlock(_parent_scene.world);
1832 return;
1833 }
1834 }
1835 }
1836 }
1837
1838 public void changeadd(float timestep)
1839 {
1840 int[] iprimspaceArrItem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
1841 IntPtr targetspace = _parent_scene.calculateSpaceForGeom(_position);
1842
1843 if (targetspace == IntPtr.Zero)
1844 targetspace = _parent_scene.createprimspace(iprimspaceArrItem[0], iprimspaceArrItem[1]);
1845
1846 m_targetSpace = targetspace;
1847
1848 if (_mesh == null)
1849 {
1850 if (_parent_scene.needsMeshing(_pbs))
1851 {
1852 // Don't need to re-enable body.. it's done in SetMesh
1853 _mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size, _parent_scene.meshSculptLOD, IsPhysical);
1854 // createmesh returns null when it's a shape that isn't a cube.
1855 // m_log.Debug(m_localID);
1856 }
1857 }
1858
1859
1860 lock (_parent_scene.OdeLock)
1861 {
1862//Console.WriteLine("changeadd 1");
1863 CreateGeom(m_targetSpace, _mesh);
1864
1865 if (prim_geom != IntPtr.Zero)
1866 {
1867 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1868 d.Quaternion myrot = new d.Quaternion();
1869 myrot.X = _orientation.X;
1870 myrot.Y = _orientation.Y;
1871 myrot.Z = _orientation.Z;
1872 myrot.W = _orientation.W;
1873 d.GeomSetQuaternion(prim_geom, ref myrot);
1874 }
1875
1876 if (m_isphysical && Body == IntPtr.Zero)
1877 {
1878 enableBody();
1879 }
1880 }
1881
1882 _parent_scene.geom_name_map[prim_geom] = this.m_primName;
1883 _parent_scene.actor_name_map[prim_geom] = (PhysicsActor)this;
1884
1885 changeSelectedStatus(timestep);
1886
1887 m_taintadd = false;
1888 }
1889
1890 public void changemove(float timestep)
1891 {
1892//Console.WriteLine("changemove sing/root {0} to {1}", m_primName, _position );
1893 if (m_isphysical)
1894 {
1895//Console.WriteLine("phys {0} {1} {2}", m_disabled, m_taintremove, childPrim);
1896// if (!m_disabled && !m_taintremove && !childPrim) After one edit m_disabled is sometimes set, disabling further edits!
1897 if (!m_taintremove && !childPrim)
1898 {
1899 if (Body == IntPtr.Zero)
1900 enableBody();
1901 //Prim auto disable after 20 frames,
1902 //if you move it, re-enable the prim manually.
1903 if (_parent != null)
1904 {
1905 if (m_linkJoint != IntPtr.Zero)
1906 {
1907 d.JointDestroy(m_linkJoint);
1908 m_linkJoint = IntPtr.Zero;
1909 }
1910 }
1911 if (Body != IntPtr.Zero)
1912 {
1913 d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
1914
1915 if (_parent != null)
1916 {
1917 OdePrim odParent = (OdePrim)_parent;
1918 if (Body != (IntPtr)0 && odParent.Body != (IntPtr)0 && Body != odParent.Body)
1919 {
1920// KF: Fixed Joints were removed? Anyway - this Console.WriteLine does not show up, so routine is not used??
1921Console.WriteLine(" JointCreateFixed");
1922 m_linkJoint = d.JointCreateFixed(_parent_scene.world, _linkJointGroup);
1923 d.JointAttach(m_linkJoint, Body, odParent.Body);
1924 d.JointSetFixed(m_linkJoint);
1925 }
1926 }
1927 d.BodyEnable(Body);
1928 if (m_type != Vehicle.TYPE_NONE)
1929 {
1930 Enable(Body, _parent_scene);
1931 }
1932 }
1933 else
1934 {
1935 m_log.Warn("[PHYSICS]: Body Still null after enableBody(). This is a crash scenario.");
1936 }
1937 }
1938 //else
1939 // {
1940 //m_log.Debug("[BUG]: race!");
1941 //}
1942 }
1943 else
1944 {
1945 // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
1946 // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
1947 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1948
1949 IntPtr tempspace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position, m_targetSpace);
1950 m_targetSpace = tempspace;
1951
1952 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1953 if (prim_geom != IntPtr.Zero)
1954 {
1955 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1956
1957 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1958 d.SpaceAdd(m_targetSpace, prim_geom);
1959 }
1960 }
1961
1962 changeSelectedStatus(timestep);
1963
1964 resetCollisionAccounting();
1965 m_taintposition = _position;
1966 }
1967
1968
1969
1970 public void rotate(float timestep)
1971 {
1972 d.Quaternion myrot = new d.Quaternion();
1973 myrot.X = _orientation.X;
1974 myrot.Y = _orientation.Y;
1975 myrot.Z = _orientation.Z;
1976 myrot.W = _orientation.W;
1977 if (Body != IntPtr.Zero)
1978 {
1979 // KF: If this is a root prim do BodySet
1980 d.BodySetQuaternion(Body, ref myrot);
1981 }
1982 else
1983 {
1984 // daughter prim, do Geom set
1985 d.GeomSetQuaternion(prim_geom, ref myrot);
1986 }
1987
1988 resetCollisionAccounting();
1989 m_taintrot = _orientation;
1990 }
1991
1992 private void resetCollisionAccounting()
1993 {
1994 m_collisionscore = 0;
1995 m_interpenetrationcount = 0;
1996 m_disabled = false;
1997 }
1998
1999 public void changedisable(float timestep)
2000 {
2001 m_disabled = true;
2002 if (Body != IntPtr.Zero)
2003 {
2004 d.BodyDisable(Body);
2005 Body = IntPtr.Zero;
2006 }
2007
2008 m_taintdisable = false;
2009 }
2010
2011 public void changePhysicsStatus(float timestep)
2012 {
2013 if (m_isphysical == true)
2014 {
2015 if (Body == IntPtr.Zero)
2016 {
2017 if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim)
2018 {
2019 changeshape(2f);
2020 }
2021 else
2022 {
2023 enableBody();
2024 }
2025 }
2026 }
2027 else
2028 {
2029 if (Body != IntPtr.Zero)
2030 {
2031 if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim)
2032 {
2033
2034
2035 if (prim_geom != IntPtr.Zero)
2036 {
2037 try
2038 {
2039 d.GeomDestroy(prim_geom);
2040 prim_geom = IntPtr.Zero;
2041 _mesh = null;
2042 }
2043 catch (System.AccessViolationException)
2044 {
2045 prim_geom = IntPtr.Zero;
2046 m_log.Error("[PHYSICS]: PrimGeom dead");
2047 }
2048 }
2049//Console.WriteLine("changePhysicsStatus for " + m_primName );
2050 changeadd(2f);
2051 }
2052 if (childPrim)
2053 {
2054 if (_parent != null)
2055 {
2056 OdePrim parent = (OdePrim)_parent;
2057 parent.ChildDelink(this);
2058 }
2059 }
2060 else
2061 {
2062 disableBody();
2063 }
2064 }
2065 }
2066
2067 changeSelectedStatus(timestep);
2068
2069 resetCollisionAccounting();
2070 m_taintPhysics = m_isphysical;
2071 }
2072
2073 public void changesize(float timestamp)
2074 {
2075
2076 string oldname = _parent_scene.geom_name_map[prim_geom];
2077
2078 if (_size.X <= 0) _size.X = 0.01f;
2079 if (_size.Y <= 0) _size.Y = 0.01f;
2080 if (_size.Z <= 0) _size.Z = 0.01f;
2081
2082 // Cleanup of old prim geometry
2083 if (_mesh != null)
2084 {
2085 // Cleanup meshing here
2086 }
2087 //kill body to rebuild
2088 if (IsPhysical && Body != IntPtr.Zero)
2089 {
2090 if (childPrim)
2091 {
2092 if (_parent != null)
2093 {
2094 OdePrim parent = (OdePrim)_parent;
2095 parent.ChildDelink(this);
2096 }
2097 }
2098 else
2099 {
2100 disableBody();
2101 }
2102 }
2103 if (d.SpaceQuery(m_targetSpace, prim_geom))
2104 {
2105 _parent_scene.waitForSpaceUnlock(m_targetSpace);
2106 d.SpaceRemove(m_targetSpace, prim_geom);
2107 }
2108 d.GeomDestroy(prim_geom);
2109 prim_geom = IntPtr.Zero;
2110 // we don't need to do space calculation because the client sends a position update also.
2111
2112 // Construction of new prim
2113 if (_parent_scene.needsMeshing(_pbs))
2114 {
2115 float meshlod = _parent_scene.meshSculptLOD;
2116
2117 if (IsPhysical)
2118 meshlod = _parent_scene.MeshSculptphysicalLOD;
2119 // Don't need to re-enable body.. it's done in SetMesh
2120
2121 IMesh mesh = null;
2122
2123 if (_parent_scene.needsMeshing(_pbs))
2124 mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical);
2125
2126 //IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical);
2127//Console.WriteLine("changesize 1");
2128 CreateGeom(m_targetSpace, mesh);
2129
2130
2131 }
2132 else
2133 {
2134 _mesh = null;
2135//Console.WriteLine("changesize 2");
2136 CreateGeom(m_targetSpace, _mesh);
2137 }
2138
2139 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2140 d.Quaternion myrot = new d.Quaternion();
2141 myrot.X = _orientation.X;
2142 myrot.Y = _orientation.Y;
2143 myrot.Z = _orientation.Z;
2144 myrot.W = _orientation.W;
2145 d.GeomSetQuaternion(prim_geom, ref myrot);
2146
2147 //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
2148 if (IsPhysical && Body == IntPtr.Zero && !childPrim)
2149 {
2150 // Re creates body on size.
2151 // EnableBody also does setMass()
2152 enableBody();
2153 d.BodyEnable(Body);
2154 }
2155
2156 _parent_scene.geom_name_map[prim_geom] = oldname;
2157
2158 changeSelectedStatus(timestamp);
2159 if (childPrim)
2160 {
2161 if (_parent is OdePrim)
2162 {
2163 OdePrim parent = (OdePrim)_parent;
2164 parent.ChildSetGeom(this);
2165 }
2166 }
2167 resetCollisionAccounting();
2168 m_taintsize = _size;
2169 }
2170
2171
2172
2173 public void changefloatonwater(float timestep)
2174 {
2175 m_collidesWater = m_taintCollidesWater;
2176
2177 if (prim_geom != IntPtr.Zero)
2178 {
2179 if (m_collidesWater)
2180 {
2181 m_collisionFlags |= CollisionCategories.Water;
2182 }
2183 else
2184 {
2185 m_collisionFlags &= ~CollisionCategories.Water;
2186 }
2187 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
2188 }
2189 }
2190
2191 public void changeshape(float timestamp)
2192 {
2193 string oldname = _parent_scene.geom_name_map[prim_geom];
2194
2195 // Cleanup of old prim geometry and Bodies
2196 if (IsPhysical && Body != IntPtr.Zero)
2197 {
2198 if (childPrim)
2199 {
2200 if (_parent != null)
2201 {
2202 OdePrim parent = (OdePrim)_parent;
2203 parent.ChildDelink(this);
2204 }
2205 }
2206 else
2207 {
2208 disableBody();
2209 }
2210 }
2211 try
2212 {
2213 d.GeomDestroy(prim_geom);
2214 }
2215 catch (System.AccessViolationException)
2216 {
2217 prim_geom = IntPtr.Zero;
2218 m_log.Error("[PHYSICS]: PrimGeom dead");
2219 }
2220 prim_geom = IntPtr.Zero;
2221 // we don't need to do space calculation because the client sends a position update also.
2222 if (_size.X <= 0) _size.X = 0.01f;
2223 if (_size.Y <= 0) _size.Y = 0.01f;
2224 if (_size.Z <= 0) _size.Z = 0.01f;
2225 // Construction of new prim
2226
2227 if (_parent_scene.needsMeshing(_pbs))
2228 {
2229 // Don't need to re-enable body.. it's done in SetMesh
2230 float meshlod = _parent_scene.meshSculptLOD;
2231
2232 if (IsPhysical)
2233 meshlod = _parent_scene.MeshSculptphysicalLOD;
2234
2235 IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical);
2236 // createmesh returns null when it doesn't mesh.
2237 CreateGeom(m_targetSpace, mesh);
2238 }
2239 else
2240 {
2241 _mesh = null;
2242//Console.WriteLine("changeshape");
2243 CreateGeom(m_targetSpace, null);
2244 }
2245
2246 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2247 d.Quaternion myrot = new d.Quaternion();
2248 //myrot.W = _orientation.w;
2249 myrot.W = _orientation.W;
2250 myrot.X = _orientation.X;
2251 myrot.Y = _orientation.Y;
2252 myrot.Z = _orientation.Z;
2253 d.GeomSetQuaternion(prim_geom, ref myrot);
2254
2255 //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
2256 if (IsPhysical && Body == IntPtr.Zero)
2257 {
2258 // Re creates body on size.
2259 // EnableBody also does setMass()
2260 enableBody();
2261 if (Body != IntPtr.Zero)
2262 {
2263 d.BodyEnable(Body);
2264 }
2265 }
2266 _parent_scene.geom_name_map[prim_geom] = oldname;
2267
2268 changeSelectedStatus(timestamp);
2269 if (childPrim)
2270 {
2271 if (_parent is OdePrim)
2272 {
2273 OdePrim parent = (OdePrim)_parent;
2274 parent.ChildSetGeom(this);
2275 }
2276 }
2277 resetCollisionAccounting();
2278 m_taintshape = false;
2279 }
2280
2281 public void changeAddForce(float timestamp)
2282 {
2283 if (!m_isSelected)
2284 {
2285 lock (m_forcelist)
2286 {
2287 //m_log.Info("[PHYSICS]: dequeing forcelist");
2288 if (IsPhysical)
2289 {
2290 Vector3 iforce = Vector3.Zero;
2291 int i = 0;
2292 try
2293 {
2294 for (i = 0; i < m_forcelist.Count; i++)
2295 {
2296
2297 iforce = iforce + (m_forcelist[i] * 100);
2298 }
2299 }
2300 catch (IndexOutOfRangeException)
2301 {
2302 m_forcelist = new List<Vector3>();
2303 m_collisionscore = 0;
2304 m_interpenetrationcount = 0;
2305 m_taintforce = false;
2306 return;
2307 }
2308 catch (ArgumentOutOfRangeException)
2309 {
2310 m_forcelist = new List<Vector3>();
2311 m_collisionscore = 0;
2312 m_interpenetrationcount = 0;
2313 m_taintforce = false;
2314 return;
2315 }
2316 d.BodyEnable(Body);
2317 d.BodyAddForce(Body, iforce.X, iforce.Y, iforce.Z);
2318 }
2319 m_forcelist.Clear();
2320 }
2321
2322 m_collisionscore = 0;
2323 m_interpenetrationcount = 0;
2324 }
2325
2326 m_taintforce = false;
2327
2328 }
2329
2330
2331
2332 public void changeSetTorque(float timestamp)
2333 {
2334 if (!m_isSelected)
2335 {
2336 if (IsPhysical && Body != IntPtr.Zero)
2337 {
2338 d.BodySetTorque(Body, m_taintTorque.X, m_taintTorque.Y, m_taintTorque.Z);
2339 }
2340 }
2341
2342 m_taintTorque = Vector3.Zero;
2343 }
2344
2345 public void changeAddAngularForce(float timestamp)
2346 {
2347 if (!m_isSelected)
2348 {
2349 lock (m_angularforcelist)
2350 {
2351 //m_log.Info("[PHYSICS]: dequeing forcelist");
2352 if (IsPhysical)
2353 {
2354 Vector3 iforce = Vector3.Zero;
2355 for (int i = 0; i < m_angularforcelist.Count; i++)
2356 {
2357 iforce = iforce + (m_angularforcelist[i] * 100);
2358 }
2359 d.BodyEnable(Body);
2360 d.BodyAddTorque(Body, iforce.X, iforce.Y, iforce.Z);
2361
2362 }
2363 m_angularforcelist.Clear();
2364 }
2365
2366 m_collisionscore = 0;
2367 m_interpenetrationcount = 0;
2368 }
2369
2370 m_taintaddangularforce = false;
2371 }
2372
2373 private void changevelocity(float timestep)
2374 {
2375 if (!m_isSelected)
2376 {
2377 Thread.Sleep(20);
2378 if (IsPhysical)
2379 {
2380 if (Body != IntPtr.Zero)
2381 d.BodySetLinearVel(Body, m_taintVelocity.X, m_taintVelocity.Y, m_taintVelocity.Z);
2382 }
2383
2384 //resetCollisionAccounting();
2385 }
2386 m_taintVelocity = Vector3.Zero;
2387 }
2388
2389 public void UpdatePositionAndVelocity()
2390 {
2391 return; // moved to the Move () method
2392 }
2393
2394 public d.Mass FromMatrix4(Matrix4 pMat, ref d.Mass obj)
2395 {
2396 obj.I.M00 = pMat[0, 0];
2397 obj.I.M01 = pMat[0, 1];
2398 obj.I.M02 = pMat[0, 2];
2399 obj.I.M10 = pMat[1, 0];
2400 obj.I.M11 = pMat[1, 1];
2401 obj.I.M12 = pMat[1, 2];
2402 obj.I.M20 = pMat[2, 0];
2403 obj.I.M21 = pMat[2, 1];
2404 obj.I.M22 = pMat[2, 2];
2405 return obj;
2406 }
2407
2408 public override void SubscribeEvents(int ms)
2409 {
2410 m_eventsubscription = ms;
2411 _parent_scene.addCollisionEventReporting(this);
2412 }
2413
2414 public override void UnSubscribeEvents()
2415 {
2416 _parent_scene.remCollisionEventReporting(this);
2417 m_eventsubscription = 0;
2418 }
2419
2420 public void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
2421 {
2422 if (CollisionEventsThisFrame == null)
2423 CollisionEventsThisFrame = new CollisionEventUpdate();
2424 CollisionEventsThisFrame.addCollider(CollidedWith, contact);
2425 }
2426
2427 public void SendCollisions()
2428 {
2429 if (CollisionEventsThisFrame == null)
2430 return;
2431
2432 base.SendCollisionUpdate(CollisionEventsThisFrame);
2433
2434 if (CollisionEventsThisFrame.m_objCollisionList.Count == 0)
2435 CollisionEventsThisFrame = null;
2436 else
2437 CollisionEventsThisFrame = new CollisionEventUpdate();
2438 }
2439
2440 public override bool SubscribedEvents()
2441 {
2442 if (m_eventsubscription > 0)
2443 return true;
2444 return false;
2445 }
2446
2447 public static Matrix4 Inverse(Matrix4 pMat)
2448 {
2449 if (determinant3x3(pMat) == 0)
2450 {
2451 return Matrix4.Identity; // should probably throw an error. singluar matrix inverse not possible
2452 }
2453
2454
2455
2456 return (Adjoint(pMat) / determinant3x3(pMat));
2457 }
2458
2459 public static Matrix4 Adjoint(Matrix4 pMat)
2460 {
2461 Matrix4 adjointMatrix = new Matrix4();
2462 for (int i=0; i<4; i++)
2463 {
2464 for (int j=0; j<4; j++)
2465 {
2466 Matrix4SetValue(ref adjointMatrix, i, j, (float)(Math.Pow(-1, i + j) * (determinant3x3(Minor(pMat, i, j)))));
2467 }
2468 }
2469
2470 adjointMatrix = Transpose(adjointMatrix);
2471 return adjointMatrix;
2472 }
2473
2474 public static Matrix4 Minor(Matrix4 matrix, int iRow, int iCol)
2475 {
2476 Matrix4 minor = new Matrix4();
2477 int m = 0, n = 0;
2478 for (int i = 0; i < 4; i++)
2479 {
2480 if (i == iRow)
2481 continue;
2482 n = 0;
2483 for (int j = 0; j < 4; j++)
2484 {
2485 if (j == iCol)
2486 continue;
2487 Matrix4SetValue(ref minor, m,n, matrix[i, j]);
2488 n++;
2489 }
2490 m++;
2491 }
2492 return minor;
2493 }
2494
2495 public static Matrix4 Transpose(Matrix4 pMat)
2496 {
2497 Matrix4 transposeMatrix = new Matrix4();
2498 for (int i = 0; i < 4; i++)
2499 for (int j = 0; j < 4; j++)
2500 Matrix4SetValue(ref transposeMatrix, i, j, pMat[j, i]);
2501 return transposeMatrix;
2502 }
2503
2504 public static void Matrix4SetValue(ref Matrix4 pMat, int r, int c, float val)
2505 {
2506 switch (r)
2507 {
2508 case 0:
2509 switch (c)
2510 {
2511 case 0:
2512 pMat.M11 = val;
2513 break;
2514 case 1:
2515 pMat.M12 = val;
2516 break;
2517 case 2:
2518 pMat.M13 = val;
2519 break;
2520 case 3:
2521 pMat.M14 = val;
2522 break;
2523 }
2524
2525 break;
2526 case 1:
2527 switch (c)
2528 {
2529 case 0:
2530 pMat.M21 = val;
2531 break;
2532 case 1:
2533 pMat.M22 = val;
2534 break;
2535 case 2:
2536 pMat.M23 = val;
2537 break;
2538 case 3:
2539 pMat.M24 = val;
2540 break;
2541 }
2542
2543 break;
2544 case 2:
2545 switch (c)
2546 {
2547 case 0:
2548 pMat.M31 = val;
2549 break;
2550 case 1:
2551 pMat.M32 = val;
2552 break;
2553 case 2:
2554 pMat.M33 = val;
2555 break;
2556 case 3:
2557 pMat.M34 = val;
2558 break;
2559 }
2560
2561 break;
2562 case 3:
2563 switch (c)
2564 {
2565 case 0:
2566 pMat.M41 = val;
2567 break;
2568 case 1:
2569 pMat.M42 = val;
2570 break;
2571 case 2:
2572 pMat.M43 = val;
2573 break;
2574 case 3:
2575 pMat.M44 = val;
2576 break;
2577 }
2578
2579 break;
2580 }
2581 }
2582 private static float determinant3x3(Matrix4 pMat)
2583 {
2584 float det = 0;
2585 float diag1 = pMat[0, 0]*pMat[1, 1]*pMat[2, 2];
2586 float diag2 = pMat[0, 1]*pMat[2, 1]*pMat[2, 0];
2587 float diag3 = pMat[0, 2]*pMat[1, 0]*pMat[2, 1];
2588 float diag4 = pMat[2, 0]*pMat[1, 1]*pMat[0, 2];
2589 float diag5 = pMat[2, 1]*pMat[1, 2]*pMat[0, 0];
2590 float diag6 = pMat[2, 2]*pMat[1, 0]*pMat[0, 1];
2591
2592 det = diag1 + diag2 + diag3 - (diag4 + diag5 + diag6);
2593 return det;
2594
2595 }
2596
2597 private static void DMassCopy(ref d.Mass src, ref d.Mass dst)
2598 {
2599 dst.c.W = src.c.W;
2600 dst.c.X = src.c.X;
2601 dst.c.Y = src.c.Y;
2602 dst.c.Z = src.c.Z;
2603 dst.mass = src.mass;
2604 dst.I.M00 = src.I.M00;
2605 dst.I.M01 = src.I.M01;
2606 dst.I.M02 = src.I.M02;
2607 dst.I.M10 = src.I.M10;
2608 dst.I.M11 = src.I.M11;
2609 dst.I.M12 = src.I.M12;
2610 dst.I.M20 = src.I.M20;
2611 dst.I.M21 = src.I.M21;
2612 dst.I.M22 = src.I.M22;
2613 }
2614
2615 public override void SetMaterial(int pMaterial)
2616 {
2617 m_material = pMaterial;
2618 }
2619
2620 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
2621 {
2622 switch (pParam)
2623 {
2624 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
2625 if (pValue < 0.01f) pValue = 0.01f;
2626 // m_angularDeflectionEfficiency = pValue;
2627 break;
2628 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
2629 if (pValue < 0.1f) pValue = 0.1f;
2630 // m_angularDeflectionTimescale = pValue;
2631 break;
2632 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
2633 if (pValue < 0.3f) pValue = 0.3f;
2634 m_angularMotorDecayTimescale = pValue;
2635 break;
2636 case Vehicle.ANGULAR_MOTOR_TIMESCALE:
2637 if (pValue < 0.3f) pValue = 0.3f;
2638 m_angularMotorTimescale = pValue;
2639 break;
2640 case Vehicle.BANKING_EFFICIENCY:
2641 if (pValue < 0.01f) pValue = 0.01f;
2642 // m_bankingEfficiency = pValue;
2643 break;
2644 case Vehicle.BANKING_MIX:
2645 if (pValue < 0.01f) pValue = 0.01f;
2646 // m_bankingMix = pValue;
2647 break;
2648 case Vehicle.BANKING_TIMESCALE:
2649 if (pValue < 0.01f) pValue = 0.01f;
2650 // m_bankingTimescale = pValue;
2651 break;
2652 case Vehicle.BUOYANCY:
2653 if (pValue < -1f) pValue = -1f;
2654 if (pValue > 1f) pValue = 1f;
2655 m_VehicleBuoyancy = pValue;
2656 break;
2657// case Vehicle.HOVER_EFFICIENCY:
2658// if (pValue < 0f) pValue = 0f;
2659// if (pValue > 1f) pValue = 1f;
2660// m_VhoverEfficiency = pValue;
2661// break;
2662 case Vehicle.HOVER_HEIGHT:
2663 m_VhoverHeight = pValue;
2664 break;
2665 case Vehicle.HOVER_TIMESCALE:
2666 if (pValue < 0.1f) pValue = 0.1f;
2667 m_VhoverTimescale = pValue;
2668 break;
2669 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
2670 if (pValue < 0.01f) pValue = 0.01f;
2671 // m_linearDeflectionEfficiency = pValue;
2672 break;
2673 case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
2674 if (pValue < 0.01f) pValue = 0.01f;
2675 // m_linearDeflectionTimescale = pValue;
2676 break;
2677 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
2678 if (pValue < 0.3f) pValue = 0.3f;
2679 m_linearMotorDecayTimescale = pValue;
2680 break;
2681 case Vehicle.LINEAR_MOTOR_TIMESCALE:
2682 if (pValue < 0.1f) pValue = 0.1f;
2683 m_linearMotorTimescale = pValue;
2684 break;
2685 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
2686 if (pValue < 0.1f) pValue = 0.1f; // Less goes unstable
2687 if (pValue > 1.0f) pValue = 1.0f;
2688 m_verticalAttractionEfficiency = pValue;
2689 break;
2690 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
2691 if (pValue < 0.1f) pValue = 0.1f;
2692 m_verticalAttractionTimescale = pValue;
2693 break;
2694
2695 // These are vector properties but the engine lets you use a single float value to
2696 // set all of the components to the same value
2697 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
2698 if (pValue > 30f) pValue = 30f;
2699 if (pValue < 0.1f) pValue = 0.1f;
2700 m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
2701 break;
2702 case Vehicle.ANGULAR_MOTOR_DIRECTION:
2703 m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
2704 UpdateAngDecay();
2705 break;
2706 case Vehicle.LINEAR_FRICTION_TIMESCALE:
2707 if (pValue < 0.1f) pValue = 0.1f;
2708 m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
2709 break;
2710 case Vehicle.LINEAR_MOTOR_DIRECTION:
2711 m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
2712 UpdateLinDecay();
2713 break;
2714 case Vehicle.LINEAR_MOTOR_OFFSET:
2715 // m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
2716 break;
2717
2718 }
2719
2720 }//end ProcessFloatVehicleParam
2721
2722 internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue)
2723 {
2724 switch (pParam)
2725 {
2726 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
2727 if (pValue.X > 30f) pValue.X = 30f;
2728 if (pValue.X < 0.1f) pValue.X = 0.1f;
2729 if (pValue.Y > 30f) pValue.Y = 30f;
2730 if (pValue.Y < 0.1f) pValue.Y = 0.1f;
2731 if (pValue.Z > 30f) pValue.Z = 30f;
2732 if (pValue.Z < 0.1f) pValue.Z = 0.1f;
2733 m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
2734 break;
2735 case Vehicle.ANGULAR_MOTOR_DIRECTION:
2736 m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
2737 // Limit requested angular speed to 2 rps= 4 pi rads/sec
2738 if(m_angularMotorDirection.X > 12.56f) m_angularMotorDirection.X = 12.56f;
2739 if(m_angularMotorDirection.X < - 12.56f) m_angularMotorDirection.X = - 12.56f;
2740 if(m_angularMotorDirection.Y > 12.56f) m_angularMotorDirection.Y = 12.56f;
2741 if(m_angularMotorDirection.Y < - 12.56f) m_angularMotorDirection.Y = - 12.56f;
2742 if(m_angularMotorDirection.Z > 12.56f) m_angularMotorDirection.Z = 12.56f;
2743 if(m_angularMotorDirection.Z < - 12.56f) m_angularMotorDirection.Z = - 12.56f;
2744 UpdateAngDecay();
2745 break;
2746 case Vehicle.LINEAR_FRICTION_TIMESCALE:
2747 if (pValue.X < 0.1f) pValue.X = 0.1f;
2748 if (pValue.Y < 0.1f) pValue.Y = 0.1f;
2749 if (pValue.Z < 0.1f) pValue.Z = 0.1f;
2750 m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
2751 break;
2752 case Vehicle.LINEAR_MOTOR_DIRECTION:
2753 m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); // velocity requested by LSL, for max limiting
2754 UpdateLinDecay();
2755 break;
2756 case Vehicle.LINEAR_MOTOR_OFFSET:
2757 // m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z);
2758 break;
2759 }
2760
2761 }//end ProcessVectorVehicleParam
2762
2763 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
2764 {
2765 switch (pParam)
2766 {
2767 case Vehicle.REFERENCE_FRAME:
2768 // m_referenceFrame = pValue;
2769 break;
2770 }
2771
2772 }//end ProcessRotationVehicleParam
2773
2774 internal void ProcessVehicleFlags(int pParam, bool remove)
2775 {
2776 if (remove)
2777 {
2778 m_flags &= ~((VehicleFlag)pParam);
2779 }
2780 else
2781 {
2782 m_flags |= (VehicleFlag)pParam;
2783 }
2784 }
2785
2786 internal void ProcessTypeChange(Vehicle pType)
2787 {
2788 // Set Defaults For Type
2789 m_type = pType;
2790 switch (pType)
2791 {
2792 case Vehicle.TYPE_SLED:
2793 m_linearFrictionTimescale = new Vector3(30, 1, 1000);
2794 m_angularFrictionTimescale = new Vector3(30, 30, 30);
2795// m_lLinMotorVel = Vector3.Zero;
2796 m_linearMotorTimescale = 1000;
2797 m_linearMotorDecayTimescale = 120;
2798 m_angularMotorDirection = Vector3.Zero;
2799 m_angularMotorDVel = Vector3.Zero;
2800 m_angularMotorTimescale = 1000;
2801 m_angularMotorDecayTimescale = 120;
2802 m_VhoverHeight = 0;
2803// m_VhoverEfficiency = 1;
2804 m_VhoverTimescale = 10;
2805 m_VehicleBuoyancy = 0;
2806 // m_linearDeflectionEfficiency = 1;
2807 // m_linearDeflectionTimescale = 1;
2808 // m_angularDeflectionEfficiency = 1;
2809 // m_angularDeflectionTimescale = 1000;
2810 // m_bankingEfficiency = 0;
2811 // m_bankingMix = 1;
2812 // m_bankingTimescale = 10;
2813 // m_referenceFrame = Quaternion.Identity;
2814 m_flags &=
2815 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
2816 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
2817 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
2818 break;
2819 case Vehicle.TYPE_CAR:
2820 m_linearFrictionTimescale = new Vector3(100, 2, 1000);
2821 m_angularFrictionTimescale = new Vector3(30, 30, 30); // was 1000, but sl max frict time is 30.
2822// m_lLinMotorVel = Vector3.Zero;
2823 m_linearMotorTimescale = 1;
2824 m_linearMotorDecayTimescale = 60;
2825 m_angularMotorDirection = Vector3.Zero;
2826 m_angularMotorDVel = Vector3.Zero;
2827 m_angularMotorTimescale = 1;
2828 m_angularMotorDecayTimescale = 0.8f;
2829 m_VhoverHeight = 0;
2830// m_VhoverEfficiency = 0;
2831 m_VhoverTimescale = 1000;
2832 m_VehicleBuoyancy = 0;
2833 // // m_linearDeflectionEfficiency = 1;
2834 // // m_linearDeflectionTimescale = 2;
2835 // // m_angularDeflectionEfficiency = 0;
2836 // m_angularDeflectionTimescale = 10;
2837 m_verticalAttractionEfficiency = 1f;
2838 m_verticalAttractionTimescale = 10f;
2839 // m_bankingEfficiency = -0.2f;
2840 // m_bankingMix = 1;
2841 // m_bankingTimescale = 1;
2842 // m_referenceFrame = Quaternion.Identity;
2843 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
2844 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.HOVER_UP_ONLY |
2845 VehicleFlag.LIMIT_MOTOR_UP);
2846 break;
2847 case Vehicle.TYPE_BOAT:
2848 m_linearFrictionTimescale = new Vector3(10, 3, 2);
2849 m_angularFrictionTimescale = new Vector3(10,10,10);
2850// m_lLinMotorVel = Vector3.Zero;
2851 m_linearMotorTimescale = 5;
2852 m_linearMotorDecayTimescale = 60;
2853 m_angularMotorDirection = Vector3.Zero;
2854 m_angularMotorDVel = Vector3.Zero;
2855 m_angularMotorTimescale = 4;
2856 m_angularMotorDecayTimescale = 4;
2857 m_VhoverHeight = 0;
2858// m_VhoverEfficiency = 0.5f;
2859 m_VhoverTimescale = 2;
2860 m_VehicleBuoyancy = 1;
2861 // m_linearDeflectionEfficiency = 0.5f;
2862 // m_linearDeflectionTimescale = 3;
2863 // m_angularDeflectionEfficiency = 0.5f;
2864 // m_angularDeflectionTimescale = 5;
2865 m_verticalAttractionEfficiency = 0.5f;
2866 m_verticalAttractionTimescale = 5f;
2867 // m_bankingEfficiency = -0.3f;
2868 // m_bankingMix = 0.8f;
2869 // m_bankingTimescale = 1;
2870 // m_referenceFrame = Quaternion.Identity;
2871 m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.LIMIT_ROLL_ONLY |
2872 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
2873 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY |
2874 VehicleFlag.LIMIT_MOTOR_UP);
2875 break;
2876 case Vehicle.TYPE_AIRPLANE:
2877 m_linearFrictionTimescale = new Vector3(200, 10, 5);
2878 m_angularFrictionTimescale = new Vector3(20, 20, 20);
2879// m_lLinMotorVel = Vector3.Zero;
2880 m_linearMotorTimescale = 2;
2881 m_linearMotorDecayTimescale = 60;
2882 m_angularMotorDirection = Vector3.Zero;
2883 m_angularMotorDVel = Vector3.Zero;
2884 m_angularMotorTimescale = 4;
2885 m_angularMotorDecayTimescale = 4;
2886 m_VhoverHeight = 0;
2887// m_VhoverEfficiency = 0.5f;
2888 m_VhoverTimescale = 1000;
2889 m_VehicleBuoyancy = 0;
2890 // m_linearDeflectionEfficiency = 0.5f;
2891 // m_linearDeflectionTimescale = 3;
2892 // m_angularDeflectionEfficiency = 1;
2893 // m_angularDeflectionTimescale = 2;
2894 m_verticalAttractionEfficiency = 0.9f;
2895 m_verticalAttractionTimescale = 2f;
2896 // m_bankingEfficiency = 1;
2897 // m_bankingMix = 0.7f;
2898 // m_bankingTimescale = 2;
2899 // m_referenceFrame = Quaternion.Identity;
2900 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
2901 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
2902 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
2903 break;
2904 case Vehicle.TYPE_BALLOON:
2905 m_linearFrictionTimescale = new Vector3(5, 5, 5);
2906 m_angularFrictionTimescale = new Vector3(10, 10, 10);
2907 m_linearMotorTimescale = 5;
2908 m_linearMotorDecayTimescale = 60;
2909 m_angularMotorDirection = Vector3.Zero;
2910 m_angularMotorDVel = Vector3.Zero;
2911 m_angularMotorTimescale = 6;
2912 m_angularMotorDecayTimescale = 10;
2913 m_VhoverHeight = 5;
2914// m_VhoverEfficiency = 0.8f;
2915 m_VhoverTimescale = 10;
2916 m_VehicleBuoyancy = 1;
2917 // m_linearDeflectionEfficiency = 0;
2918 // m_linearDeflectionTimescale = 5;
2919 // m_angularDeflectionEfficiency = 0;
2920 // m_angularDeflectionTimescale = 5;
2921 m_verticalAttractionEfficiency = 1f;
2922 m_verticalAttractionTimescale = 100f;
2923 // m_bankingEfficiency = 0;
2924 // m_bankingMix = 0.7f;
2925 // m_bankingTimescale = 5;
2926 // m_referenceFrame = Quaternion.Identity;
2927 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
2928 VehicleFlag.HOVER_UP_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
2929 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
2930 break;
2931
2932 }
2933 }//end SetDefaultsForType
2934
2935 internal void Enable(IntPtr pBody, OdeScene pParentScene)
2936 {
2937 if (m_type == Vehicle.TYPE_NONE)
2938 return;
2939
2940 m_body = pBody;
2941 }
2942
2943
2944 internal void Halt()
2945 { // Kill all motions, when non-physical
2946 // m_linearMotorDirection = Vector3.Zero;
2947 m_lLinMotorDVel = Vector3.Zero;
2948 m_lLinObjectVel = Vector3.Zero;
2949 m_wLinObjectVel = Vector3.Zero;
2950 m_angularMotorDirection = Vector3.Zero;
2951 m_lastAngularVelocity = Vector3.Zero;
2952 m_angularMotorDVel = Vector3.Zero;
2953 _acceleration = Vector3.Zero;
2954 }
2955
2956 private void UpdateLinDecay()
2957 {
2958// if (Math.Abs(m_linearMotorDirection.X) > Math.Abs(m_lLinMotorDVel.X)) m_lLinMotorDVel.X = m_linearMotorDirection.X;
2959// if (Math.Abs(m_linearMotorDirection.Y) > Math.Abs(m_lLinMotorDVel.Y)) m_lLinMotorDVel.Y = m_linearMotorDirection.Y;
2960// if (Math.Abs(m_linearMotorDirection.Z) > Math.Abs(m_lLinMotorDVel.Z)) m_lLinMotorDVel.Z = m_linearMotorDirection.Z;
2961 m_lLinMotorDVel.X = m_linearMotorDirection.X;
2962 m_lLinMotorDVel.Y = m_linearMotorDirection.Y;
2963 m_lLinMotorDVel.Z = m_linearMotorDirection.Z;
2964 } // else let the motor decay on its own
2965
2966 private void UpdateAngDecay()
2967 {
2968// if (Math.Abs(m_angularMotorDirection.X) > Math.Abs(m_angularMotorDVel.X)) m_angularMotorDVel.X = m_angularMotorDirection.X;
2969// if (Math.Abs(m_angularMotorDirection.Y) > Math.Abs(m_angularMotorDVel.Y)) m_angularMotorDVel.Y = m_angularMotorDirection.Y;
2970// if (Math.Abs(m_angularMotorDirection.Z) > Math.Abs(m_angularMotorDVel.Z)) m_angularMotorDVel.Z = m_angularMotorDirection.Z;
2971 m_angularMotorDVel.X = m_angularMotorDirection.X;
2972 m_angularMotorDVel.Y = m_angularMotorDirection.Y;
2973 m_angularMotorDVel.Z = m_angularMotorDirection.Z;
2974 } // else let the motor decay on its own
2975
2976 public void Move(float timestep)
2977 {
2978 float fx = 0;
2979 float fy = 0;
2980 float fz = 0;
2981 Vector3 linvel; // velocity applied, including any reversal
2982 int outside = 0;
2983
2984 // If geomCrossingFailuresBeforeOutofbounds is set to 0 in OpenSim.ini then phys objects bounce off region borders.
2985 // This is a temp patch until proper region crossing is developed.
2986
2987 int failureLimit = _parent_scene.geomCrossingFailuresBeforeOutofbounds;
2988 int fence = _parent_scene.geomRegionFence;
2989
2990 float border_limit = 0.05f; // original limit
2991 if (fence == 1) border_limit = 0.5f; // bounce point
2992
2993 frcount++; // used to limit debug comment output
2994 if (frcount > 10)
2995 frcount = 0;
2996
2997 if(revcount > 0) revcount--;
2998
2999 if (IsPhysical && (Body != IntPtr.Zero) && !m_isSelected && !childPrim) // Only move root prims.
3000 {
3001 // Old public void UpdatePositionAndVelocity(), more accuratley calculated here
3002 bool lastZeroFlag = _zeroFlag; // was it stopped
3003
3004 d.Vector3 vec = d.BodyGetPosition(Body);
3005 Vector3 l_position = Vector3.Zero;
3006 l_position.X = vec.X;
3007 l_position.Y = vec.Y;
3008 l_position.Z = vec.Z;
3009 m_lastposition = _position;
3010 _position = l_position;
3011
3012 d.Quaternion ori = d.BodyGetQuaternion(Body);
3013 // Quaternion l_orientation = Quaternion.Identity;
3014 _orientation.X = ori.X;
3015 _orientation.Y = ori.Y;
3016 _orientation.Z = ori.Z;
3017 _orientation.W = ori.W;
3018 m_lastorientation = _orientation;
3019
3020 d.Vector3 vel = d.BodyGetLinearVel(Body);
3021 m_lastVelocity = _velocity;
3022 _velocity.X = vel.X;
3023 _velocity.Y = vel.Y;
3024 _velocity.Z = vel.Z;
3025 _acceleration = ((_velocity - m_lastVelocity) / timestep);
3026
3027 d.Vector3 torque = d.BodyGetTorque(Body);
3028 _torque = new Vector3(torque.X, torque.Y, torque.Z);
3029
3030 base.RequestPhysicsterseUpdate();
3031
3032//Console.WriteLine("Move {0} at {1}", m_primName, l_position);
3033
3034 // Check if outside region
3035 // In Scene.cs/CrossPrimGroupIntoNewRegion the object is checked for 0.1M from border!
3036 if (l_position.X > ((float)_parent_scene.WorldExtents.X - border_limit))
3037 {
3038 l_position.X = ((float)_parent_scene.WorldExtents.X - border_limit);
3039 outside = 1;
3040 }
3041
3042 if (l_position.X < border_limit)
3043 {
3044 l_position.X = border_limit;
3045 outside = 2;
3046 }
3047 if (l_position.Y > ((float)_parent_scene.WorldExtents.Y - border_limit))
3048 {
3049 l_position.Y = ((float)_parent_scene.WorldExtents.Y - border_limit);
3050 outside = 3;
3051 }
3052
3053 if (l_position.Y < border_limit)
3054 {
3055 l_position.Y = border_limit;
3056 outside = 4;
3057 }
3058
3059 if (outside > 0)
3060 {
3061//Console.WriteLine(" fence = {0}",fence);
3062
3063//Console.WriteLine("Border {0}", l_position);
3064 if (fence == 1) // bounce object off boundary
3065 {
3066 if (revcount == 0)
3067 {
3068 if (outside < 3)
3069 {
3070 _velocity.X = -_velocity.X;
3071 }
3072 else
3073 {
3074 _velocity.Y = -_velocity.Y;
3075 }
3076 if (m_type != Vehicle.TYPE_NONE) Halt();
3077 _position = l_position;
3078 m_taintposition = _position;
3079 m_lastVelocity = _velocity;
3080 _acceleration = Vector3.Zero;
3081 d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
3082 d.BodySetLinearVel(Body, _velocity.X, _velocity.Y, _velocity.Z);
3083 base.RequestPhysicsterseUpdate();
3084
3085 revcount = 25; // wait for object to move away from border
3086 }
3087 } // else old crossing mode
3088 else if (m_crossingfailures < failureLimit)
3089 { // keep trying to cross?
3090 _position = l_position;
3091 //_parent_scene.remActivePrim(this);
3092 if (_parent == null) base.RequestPhysicsterseUpdate();
3093 return; // Dont process any other motion?
3094 }
3095 else
3096 { // Too many tries
3097 if (_parent == null) base.RaiseOutOfBounds(l_position);
3098//Console.WriteLine("ROOB 2");
3099
3100 return; // Dont process any other motion?
3101 } // end various methods
3102 } // end outside region horizontally
3103
3104
3105 if (l_position.Z < 0)
3106 {
3107 // This is so prim that get lost underground don't fall forever and suck up
3108 //
3109 // Sim resources and memory.
3110 // Disables the prim's movement physics....
3111 // It's a hack and will generate a console message if it fails.
3112
3113 //IsPhysical = false;
3114 if (_parent == null) base.RaiseOutOfBounds(_position);
3115//Console.WriteLine("ROOB 3");
3116
3117
3118 _acceleration.X = 0; // This stuff may stop client display but it has no
3119 _acceleration.Y = 0; // effect on the object in phys engine!
3120 _acceleration.Z = 0;
3121
3122 _velocity.X = 0;
3123 _velocity.Y = 0;
3124 _velocity.Z = 0;
3125 m_rotationalVelocity.X = 0;
3126 m_rotationalVelocity.Y = 0;
3127 m_rotationalVelocity.Z = 0;
3128
3129 if (_parent == null) base.RequestPhysicsterseUpdate();
3130
3131 m_throttleUpdates = false;
3132 throttleCounter = 0;
3133 _zeroFlag = true;
3134 //outofBounds = true;
3135 } // end neg Z check
3136
3137 // Is it moving?
3138 if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02)
3139 && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02)
3140 && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02)
3141 && (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, _orientation)) < 0.0001)) // KF 0.01 is far to large
3142 {
3143 _zeroFlag = true;
3144 m_throttleUpdates = false;
3145 }
3146 else
3147 {
3148 //m_log.Debug(Math.Abs(m_lastposition.X - l_position.X).ToString());
3149 _zeroFlag = false;
3150 m_lastUpdateSent = false;
3151 //m_throttleUpdates = false;
3152 }
3153
3154 if (_zeroFlag)
3155 { // Its stopped
3156 _velocity.X = 0.0f;
3157 _velocity.Y = 0.0f;
3158 _velocity.Z = 0.0f;
3159
3160 _acceleration.X = 0;
3161 _acceleration.Y = 0;
3162 _acceleration.Z = 0;
3163
3164 m_rotationalVelocity.X = 0;
3165 m_rotationalVelocity.Y = 0;
3166 m_rotationalVelocity.Z = 0;
3167 if (!m_lastUpdateSent)
3168 {
3169 m_throttleUpdates = false;
3170 throttleCounter = 0;
3171 if (_parent == null)
3172 {
3173 base.RequestPhysicsterseUpdate();
3174 }
3175
3176 m_lastUpdateSent = true;
3177 }
3178 }
3179 else
3180 { // Its moving
3181 if (lastZeroFlag != _zeroFlag)
3182 {
3183 if (_parent == null)
3184 {
3185 base.RequestPhysicsterseUpdate();
3186 }
3187 }
3188 m_lastUpdateSent = false;
3189 if (!m_throttleUpdates || throttleCounter > _parent_scene.geomUpdatesPerThrottledUpdate)
3190 {
3191 if (_parent == null)
3192 {
3193 base.RequestPhysicsterseUpdate();
3194 }
3195 }
3196 else
3197 {
3198 throttleCounter++;
3199 }
3200 }
3201 m_lastposition = l_position;
3202
3203 /// End UpdatePositionAndVelocity insert
3204
3205 if (m_type != Vehicle.TYPE_NONE)
3206 {
3207 // get body attitude
3208 d.Quaternion rot = d.BodyGetQuaternion(Body);
3209 Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object
3210 Quaternion irotq = Quaternion.Inverse(rotq);
3211
3212 // VEHICLE Linear Motion
3213 d.Vector3 velnow = d.BodyGetLinearVel(Body); // this is in world frame
3214 Vector3 vel_now = new Vector3(velnow.X, velnow.Y, velnow.Z);
3215 m_lLinObjectVel = vel_now * irotq;
3216
3217 if (m_linearMotorDecayTimescale < 300.0f) //setting of 300 or more disables decay rate
3218 {
3219 if ( Vector3.Mag(m_lLinMotorDVel) < 1.0f)
3220 {
3221 float decayfactor = m_linearMotorDecayTimescale/timestep;
3222 Vector3 decayAmount = (m_lLinMotorDVel/decayfactor);
3223 m_lLinMotorDVel -= decayAmount;
3224 }
3225 else
3226 {
3227 float decayfactor = 3.0f - (0.57f * (float)Math.Log((double)(m_linearMotorDecayTimescale)));
3228 Vector3 decel = Vector3.Normalize(m_lLinMotorDVel) * decayfactor * timestep;
3229 m_lLinMotorDVel -= decel;
3230 }
3231 if (m_lLinMotorDVel.ApproxEquals(Vector3.Zero, 0.01f))
3232 {
3233 m_lLinMotorDVel = Vector3.Zero;
3234 }
3235
3236 /* else
3237 {
3238 if (Math.Abs(m_lLinMotorDVel.X) < Math.Abs(m_lLinObjectVel.X)) m_lLinObjectVel.X = m_lLinMotorDVel.X;
3239 if (Math.Abs(m_lLinMotorDVel.Y) < Math.Abs(m_lLinObjectVel.Y)) m_lLinObjectVel.Y = m_lLinMotorDVel.Y;
3240 if (Math.Abs(m_lLinMotorDVel.Z) < Math.Abs(m_lLinObjectVel.Z)) m_lLinObjectVel.Z = m_lLinMotorDVel.Z;
3241 } */
3242 } // end linear motor decay
3243
3244 if ( (! m_lLinMotorDVel.ApproxEquals(Vector3.Zero, 0.01f)) || (! m_lLinObjectVel.ApproxEquals(Vector3.Zero, 0.01f)) )
3245 {
3246 if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body);
3247 if (m_linearMotorTimescale < 300.0f)
3248 {
3249 Vector3 attack_error = m_lLinMotorDVel - m_lLinObjectVel;
3250 float linfactor = m_linearMotorTimescale/timestep;
3251 Vector3 attackAmount = (attack_error/linfactor) * 1.3f;
3252 m_lLinObjectVel += attackAmount;
3253 }
3254 if (m_linearFrictionTimescale.X < 300.0f)
3255 {
3256 float fricfactor = m_linearFrictionTimescale.X / timestep;
3257 float fricX = m_lLinObjectVel.X / fricfactor;
3258 m_lLinObjectVel.X -= fricX;
3259 }
3260 if (m_linearFrictionTimescale.Y < 300.0f)
3261 {
3262 float fricfactor = m_linearFrictionTimescale.Y / timestep;
3263 float fricY = m_lLinObjectVel.Y / fricfactor;
3264 m_lLinObjectVel.Y -= fricY;
3265 }
3266 if (m_linearFrictionTimescale.Z < 300.0f)
3267 {
3268 float fricfactor = m_linearFrictionTimescale.Z / timestep;
3269 float fricZ = m_lLinObjectVel.Z / fricfactor;
3270 m_lLinObjectVel.Z -= fricZ;
3271 }
3272 }
3273 m_wLinObjectVel = m_lLinObjectVel * rotq;
3274
3275 // Gravity and Buoyancy
3276 Vector3 grav = Vector3.Zero;
3277 if(m_VehicleBuoyancy < 1.0f)
3278 {
3279 // There is some gravity, make a gravity force vector
3280 // that is applied after object velocity.
3281 d.Mass objMass;
3282 d.BodyGetMass(Body, out objMass);
3283 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
3284 grav.Z = _parent_scene.gravityz * objMass.mass * (1f - m_VehicleBuoyancy); // Applied later as a force
3285 } // else its 1.0, no gravity.
3286
3287 // Hovering
3288 if( (m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
3289 {
3290 // We should hover, get the target height
3291 d.Vector3 pos = d.BodyGetPosition(Body);
3292 if((m_flags & VehicleFlag.HOVER_WATER_ONLY) == VehicleFlag.HOVER_WATER_ONLY)
3293 {
3294 m_VhoverTargetHeight = _parent_scene.GetWaterLevel() + m_VhoverHeight;
3295 }
3296 else if((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) == VehicleFlag.HOVER_TERRAIN_ONLY)
3297 {
3298 m_VhoverTargetHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight;
3299 }
3300 else if((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) == VehicleFlag.HOVER_GLOBAL_HEIGHT)
3301 {
3302 m_VhoverTargetHeight = m_VhoverHeight;
3303 }
3304
3305 if((m_flags & VehicleFlag.HOVER_UP_ONLY) == VehicleFlag.HOVER_UP_ONLY)
3306 {
3307 // If body is aready heigher, use its height as target height
3308 if(pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z;
3309 }
3310
3311// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped
3312// m_VhoverTimescale = 0f; // time to acheive height
3313// timestep is time since last frame,in secs
3314 float herr0 = pos.Z - m_VhoverTargetHeight;
3315 // Replace Vertical speed with correction figure if significant
3316 if(Math.Abs(herr0) > 0.01f )
3317 {
3318 //? d.Mass objMass;
3319 //? d.BodyGetMass(Body, out objMass);
3320 m_wLinObjectVel.Z = - ( (herr0 * timestep * 50.0f) / m_VhoverTimescale);
3321 //KF: m_VhoverEfficiency is not yet implemented
3322 }
3323 else
3324 {
3325 m_wLinObjectVel.Z = 0f;
3326 }
3327 }
3328 else
3329 { // not hovering
3330 if (m_wLinObjectVel.Z == 0f)
3331 { // Gravity rules
3332 m_wLinObjectVel.Z = vel_now.Z;
3333 } // else the motor has it
3334 }
3335 linvel = m_wLinObjectVel;
3336
3337 // Vehicle Linear Motion done =======================================
3338 // Apply velocity
3339 d.BodySetLinearVel(Body, linvel.X, linvel.Y, linvel.Z);
3340 // apply gravity force
3341 d.BodyAddForce(Body, grav.X, grav.Y, grav.Z);
3342//if(frcount == 0) Console.WriteLine("Grav {0}", grav);
3343 // end MoveLinear()
3344
3345
3346 // MoveAngular
3347 /*
3348 private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor
3349
3350 private float m_angularMotorTimescale = 0; // motor angular Attack rate set by LSL
3351 private float m_angularMotorDecayTimescale = 0; // motor angular Decay rate set by LSL
3352 private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular Friction set by LSL
3353
3354 private Vector3 m_angularMotorDVel = Vector3.Zero; // decayed angular motor
3355 private Vector3 m_angObjectVel = Vector3.Zero; // what was last applied to body
3356 */
3357//if(frcount == 0) Console.WriteLine("MoveAngular ");
3358
3359 d.Vector3 angularObjectVel = d.BodyGetAngularVel(Body);
3360 Vector3 angObjectVel = new Vector3(angularObjectVel.X, angularObjectVel.Y, angularObjectVel.Z);
3361 angObjectVel = angObjectVel * irotq; // ============ Converts to LOCAL rotation
3362
3363//if(frcount == 0) Console.WriteLine("V0 = {0}", angObjectVel);
3364
3365 // Decay Angular Motor 1. In SL this also depends on attack rate! decay ~= 23/Attack.
3366 float atk_decayfactor = 23.0f / (m_angularMotorTimescale * timestep);
3367 m_angularMotorDVel -= m_angularMotorDVel / atk_decayfactor;
3368 // Decay Angular Motor 2.
3369 if (m_angularMotorDecayTimescale < 300.0f)
3370 {
3371 if ( Vector3.Mag(m_angularMotorDVel) < 1.0f)
3372 {
3373 float decayfactor = (m_angularMotorDecayTimescale)/timestep;
3374 Vector3 decayAmount = (m_angularMotorDVel/decayfactor);
3375 m_angularMotorDVel -= decayAmount;
3376 }
3377 else
3378 {
3379 Vector3 decel = Vector3.Normalize(m_angularMotorDVel) * timestep / m_angularMotorDecayTimescale;
3380 m_angularMotorDVel -= decel;
3381 }
3382
3383 if (m_angularMotorDVel.ApproxEquals(Vector3.Zero, 0.01f))
3384 {
3385 m_angularMotorDVel = Vector3.Zero;
3386 }
3387 else
3388 {
3389 if (Math.Abs(m_angularMotorDVel.X) < Math.Abs(angObjectVel.X)) angObjectVel.X = m_angularMotorDVel.X;
3390 if (Math.Abs(m_angularMotorDVel.Y) < Math.Abs(angObjectVel.Y)) angObjectVel.Y = m_angularMotorDVel.Y;
3391 if (Math.Abs(m_angularMotorDVel.Z) < Math.Abs(angObjectVel.Z)) angObjectVel.Z = m_angularMotorDVel.Z;
3392 }
3393 } // end decay angular motor
3394//if(frcount == 0) Console.WriteLine("MotorDvel {0} Obj {1}", m_angularMotorDVel, angObjectVel);
3395
3396//if(frcount == 0) Console.WriteLine("VA = {0}", angObjectVel);
3397
3398 if ( (! m_angularMotorDVel.ApproxEquals(Vector3.Zero, 0.01f)) || (! angObjectVel.ApproxEquals(Vector3.Zero, 0.01f)) )
3399 { // if motor or object have motion
3400 if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body);
3401
3402 if (m_angularMotorTimescale < 300.0f)
3403 {
3404 Vector3 attack_error = m_angularMotorDVel - angObjectVel;
3405 float angfactor = m_angularMotorTimescale/timestep;
3406 Vector3 attackAmount = (attack_error/angfactor);
3407 angObjectVel += attackAmount;
3408//if(frcount == 0) Console.WriteLine("Accel {0} Attk {1}",FrAaccel, attackAmount);
3409//if(frcount == 0) Console.WriteLine("V2+= {0}", angObjectVel);
3410 }
3411
3412 angObjectVel.X -= angObjectVel.X / (m_angularFrictionTimescale.X * 0.7f / timestep);
3413 angObjectVel.Y -= angObjectVel.Y / (m_angularFrictionTimescale.Y * 0.7f / timestep);
3414 angObjectVel.Z -= angObjectVel.Z / (m_angularFrictionTimescale.Z * 0.7f / timestep);
3415 } // else no signif. motion
3416
3417//if(frcount == 0) Console.WriteLine("Dmotor {0} Obj {1}", m_angularMotorDVel, angObjectVel);
3418 // Bank section tba
3419 // Deflection section tba
3420//if(frcount == 0) Console.WriteLine("V3 = {0}", angObjectVel);
3421
3422
3423 // Rotation Axis Disables:
3424 if (!m_angularEnable.ApproxEquals(Vector3.One, 0.003f))
3425 {
3426 if (m_angularEnable.X == 0)
3427 angObjectVel.X = 0f;
3428 if (m_angularEnable.Y == 0)
3429 angObjectVel.Y = 0f;
3430 if (m_angularEnable.Z == 0)
3431 angObjectVel.Z = 0f;
3432 }
3433
3434 angObjectVel = angObjectVel * rotq; // ================ Converts to WORLD rotation
3435
3436 // Vertical attractor section
3437 Vector3 vertattr = Vector3.Zero;
3438
3439 if(m_verticalAttractionTimescale < 300)
3440 {
3441 float VAservo = 1.0f / (m_verticalAttractionTimescale * timestep);
3442 // make a vector pointing up
3443 Vector3 verterr = Vector3.Zero;
3444 verterr.Z = 1.0f;
3445 // rotate it to Body Angle
3446 verterr = verterr * rotq;
3447 // verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1.
3448 // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go
3449 // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body.
3450
3451 if (verterr.Z < 0.0f)
3452 { // Deflection from vertical exceeds 90-degrees. This method will ensure stable return to
3453 // vertical, BUT for some reason a z-rotation is imparted to the object. TBI.
3454//Console.WriteLine("InvertFlip");
3455 verterr.X = 2.0f - verterr.X;
3456 verterr.Y = 2.0f - verterr.Y;
3457 }
3458 verterr *= 0.5f;
3459 // verterror is 0 (no error) to +/- 1 (max error at 180-deg tilt)
3460 Vector3 xyav = angObjectVel;
3461 xyav.Z = 0.0f;
3462 if ((!xyav.ApproxEquals(Vector3.Zero, 0.001f)) || (verterr.Z < 0.49f))
3463 {
3464 // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so
3465 // Change Body angular velocity X based on Y, and Y based on X. Z is not changed.
3466 vertattr.X = verterr.Y;
3467 vertattr.Y = - verterr.X;
3468 vertattr.Z = 0f;
3469//if(frcount == 0) Console.WriteLine("VAerr=" + verterr);
3470
3471 // scaling appears better usingsquare-law
3472 float damped = m_verticalAttractionEfficiency * m_verticalAttractionEfficiency;
3473 float bounce = 1.0f - damped;
3474 // 0 = crit damp, 1 = bouncy
3475 float oavz = angObjectVel.Z; // retain z velocity
3476 // time-scaled correction, which sums, therefore is bouncy:
3477 angObjectVel = (angObjectVel + (vertattr * VAservo * 0.0333f)) * bounce;
3478 // damped, good @ < 90:
3479 angObjectVel = angObjectVel + (vertattr * VAservo * 0.0667f * damped);
3480 angObjectVel.Z = oavz;
3481//if(frcount == 0) Console.WriteLine("VA+");
3482//Console.WriteLine("VAttr {0} OAvel {1}", vertattr, angObjectVel);
3483 }
3484 else
3485 {
3486 // else error is very small
3487 angObjectVel.X = 0f;
3488 angObjectVel.Y = 0f;
3489//if(frcount == 0) Console.WriteLine("VA0");
3490 }
3491 } // else vertical attractor is off
3492//if(frcount == 0) Console.WriteLine("V1 = {0}", angObjectVel);
3493
3494
3495 m_lastAngularVelocity = angObjectVel;
3496 // apply Angular Velocity to body
3497 d.BodySetAngularVel (Body, m_lastAngularVelocity.X, m_lastAngularVelocity.Y, m_lastAngularVelocity.Z);
3498//if(frcount == 0) Console.WriteLine("V4 = {0}", m_lastAngularVelocity);
3499
3500 } // end VEHICLES
3501 else
3502 {
3503 if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); // KF add 161009
3504 // NON-'VEHICLES' are dealt with here
3505 /// Dynamics Angular Lock ========================================================================
3506 if (d.BodyIsEnabled(Body) && !m_angularEnable.ApproxEquals(Vector3.One, 0.003f))
3507 {
3508 d.Vector3 avel2 = d.BodyGetAngularVel(Body);
3509 if (m_angularEnable.X == 0)
3510 avel2.X = 0;
3511 if (m_angularEnable.Y == 0)
3512 avel2.Y = 0;
3513 if (m_angularEnable.Z == 0)
3514 avel2.Z = 0;
3515 d.BodySetAngularVel(Body, avel2.X, avel2.Y, avel2.Z);
3516 }
3517
3518
3519 /// Dynamics Buoyancy ===============================================================================
3520 //KF: m_buoyancy is set by llSetBuoyancy() and is for non-vehicle.
3521 // m_buoyancy: (unlimited value) <0=Falls fast; 0=1g; 1=0g; >1 = floats up
3522 // NB Prims in ODE are no subject to global gravity
3523 float m_mass = CalculateMass();
3524 fz = _parent_scene.gravityz * (1.0f - m_buoyancy) * m_mass; // force = acceleration * mass
3525
3526 if (m_usePID)
3527 {
3528//if(frcount == 0) Console.WriteLine("PID " + m_primName);
3529 // KF - this is for object MoveToTarget.
3530
3531 //if (!d.BodyIsEnabled(Body))
3532 //d.BodySetForce(Body, 0f, 0f, 0f);
3533
3534 // no lock; for now it's only called from within Simulate()
3535
3536 // If the PID Controller isn't active then we set our force
3537 // calculating base velocity to the current position
3538
3539 if ((m_PIDTau < 1) && (m_PIDTau != 0))
3540 {
3541 //PID_G = PID_G / m_PIDTau;
3542 m_PIDTau = 1;
3543 }
3544
3545 if ((PID_G - m_PIDTau) <= 0)
3546 {
3547 PID_G = m_PIDTau + 1;
3548 }
3549 //PidStatus = true;
3550
3551 // PhysicsVector vec = new PhysicsVector();
3552// d.Vector3 vel = d.BodyGetLinearVel(Body);
3553
3554 d.Vector3 pos = d.BodyGetPosition(Body);
3555 _target_velocity =
3556 new Vector3(
3557 (m_PIDTarget.X - pos.X) * ((PID_G - m_PIDTau) * timestep),
3558 (m_PIDTarget.Y - pos.Y) * ((PID_G - m_PIDTau) * timestep),
3559 (m_PIDTarget.Z - pos.Z) * ((PID_G - m_PIDTau) * timestep)
3560 );
3561
3562 // if velocity is zero, use position control; otherwise, velocity control
3563
3564 if (_target_velocity.ApproxEquals(Vector3.Zero,0.1f))
3565 {
3566 // keep track of where we stopped. No more slippin' & slidin'
3567
3568 // We only want to deactivate the PID Controller if we think we want to have our surrogate
3569 // react to the physics scene by moving it's position.
3570 // Avatar to Avatar collisions
3571 // Prim to avatar collisions
3572
3573 //fx = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2);
3574 //fy = (_target_velocity.Y - vel.Y) * (PID_D) + (_zeroPosition.Y - pos.Y) * (PID_P * 2);
3575 //fz = fz + (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P;
3576 d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z);
3577 d.BodySetLinearVel(Body, 0, 0, 0);
3578 d.BodyAddForce(Body, 0, 0, fz);
3579 // return;
3580 }
3581 else
3582 {
3583 _zeroFlag = false;
3584
3585 // We're flying and colliding with something
3586 fx = ((_target_velocity.X) - vel.X) * (PID_D);
3587 fy = ((_target_velocity.Y) - vel.Y) * (PID_D);
3588
3589 // vec.Z = (_target_velocity.Z - vel.Z) * PID_D + (_zeroPosition.Z - pos.Z) * PID_P;
3590
3591 fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass);
3592 }
3593 } // end if (m_usePID)
3594
3595 /// Dynamics Hover ===================================================================================
3596 // Hover PID Controller needs to be mutually exlusive to MoveTo PID controller
3597 if (m_useHoverPID && !m_usePID)
3598 {
3599//Console.WriteLine("Hover " + m_primName);
3600
3601 // If we're using the PID controller, then we have no gravity
3602 fz = (-1 * _parent_scene.gravityz) * m_mass;
3603
3604 // no lock; for now it's only called from within Simulate()
3605
3606 // If the PID Controller isn't active then we set our force
3607 // calculating base velocity to the current position
3608
3609 if ((m_PIDTau < 1))
3610 {
3611 PID_G = PID_G / m_PIDTau;
3612 }
3613
3614 if ((PID_G - m_PIDTau) <= 0)
3615 {
3616 PID_G = m_PIDTau + 1;
3617 }
3618
3619
3620 // Where are we, and where are we headed?
3621 d.Vector3 pos = d.BodyGetPosition(Body);
3622// d.Vector3 vel = d.BodyGetLinearVel(Body);
3623
3624
3625 // Non-Vehicles have a limited set of Hover options.
3626 // determine what our target height really is based on HoverType
3627 switch (m_PIDHoverType)
3628 {
3629 case PIDHoverType.Ground:
3630 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y);
3631 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
3632 break;
3633 case PIDHoverType.GroundAndWater:
3634 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y);
3635 m_waterHeight = _parent_scene.GetWaterLevel();
3636 if (m_groundHeight > m_waterHeight)
3637 {
3638 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
3639 }
3640 else
3641 {
3642 m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight;
3643 }
3644 break;
3645
3646 } // end switch (m_PIDHoverType)
3647
3648
3649 _target_velocity =
3650 new Vector3(0.0f, 0.0f,
3651 (m_targetHoverHeight - pos.Z) * ((PID_G - m_PIDHoverTau) * timestep)
3652 );
3653
3654 // if velocity is zero, use position control; otherwise, velocity control
3655
3656 if (_target_velocity.ApproxEquals(Vector3.Zero, 0.1f))
3657 {
3658 // keep track of where we stopped. No more slippin' & slidin'
3659
3660 // We only want to deactivate the PID Controller if we think we want to have our surrogate
3661 // react to the physics scene by moving it's position.
3662 // Avatar to Avatar collisions
3663 // Prim to avatar collisions
3664 d.Vector3 dlinvel = vel;
3665
3666 d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight);
3667 d.BodySetLinearVel(Body, dlinvel.X, dlinvel.Y, dlinvel.Z);
3668 d.BodyAddForce(Body, 0, 0, fz);
3669 //KF this prevents furthur motions return;
3670 }
3671 else
3672 {
3673 _zeroFlag = false;
3674
3675 // We're flying and colliding with something
3676 fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass);
3677 }
3678 } // end m_useHoverPID && !m_usePID
3679
3680 /// Dynamics RotLookAt =================================================================================
3681 if (m_useAPID)
3682 {
3683 // RotLookAt, apparently overrides all other rotation sources. Inputs:
3684 // Quaternion m_APIDTarget
3685 // float m_APIDStrength // From SL experiments, this is the time to get there
3686 // float m_APIDDamping // From SL experiments, this is damping, 1.0 = damped, 0.1 = wobbly
3687 // Also in SL the mass of the object has no effect on time to get there.
3688 // Factors:
3689 // get present body rotation
3690 float limit = 1.0f;
3691 float scaler = 50f; // adjusts damping time
3692 float RLAservo = 0f;
3693
3694 d.Quaternion rot = d.BodyGetQuaternion(Body);
3695 Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W);
3696 Quaternion rot_diff = Quaternion.Inverse(rotq) * m_APIDTarget;
3697 float diff_angle;
3698 Vector3 diff_axis;
3699 rot_diff.GetAxisAngle(out diff_axis, out diff_angle);
3700 diff_axis.Normalize();
3701 if(diff_angle > 0.01f) // diff_angle is always +ve
3702 {
3703// PhysicsVector rotforce = new PhysicsVector(diff_axis.X, diff_axis.Y, diff_axis.Z);
3704 Vector3 rotforce = new Vector3(diff_axis.X, diff_axis.Y, diff_axis.Z);
3705 rotforce = rotforce * rotq;
3706 if(diff_angle > limit) diff_angle = limit; // cap the rotate rate
3707// RLAservo = timestep / m_APIDStrength * m_mass * scaler;
3708 // rotforce = rotforce * RLAservo * diff_angle ;
3709 // d.BodyAddRelTorque(Body, rotforce.X, rotforce.Y, rotforce.Z);
3710 RLAservo = timestep / m_APIDStrength * scaler;
3711 rotforce = rotforce * RLAservo * diff_angle ;
3712
3713 if (m_angularEnable.X == 0)
3714 rotforce.X = 0;
3715 if (m_angularEnable.Y == 0)
3716 rotforce.Y = 0;
3717 if (m_angularEnable.Z == 0)
3718 rotforce.Z = 0;
3719
3720 d.BodySetAngularVel (Body, rotforce.X, rotforce.Y, rotforce.Z);
3721//Console.WriteLine("axis= " + diff_axis + " angle= " + diff_angle + "servo= " + RLAservo);
3722 }
3723//if(frcount == 0) Console.WriteLine("mass= " + m_mass + " servo= " + RLAservo + " angle= " + diff_angle);
3724 } // end m_useAPID
3725
3726 /// Dynamics Apply Forces ===================================================================================
3727 fx *= m_mass;
3728 fy *= m_mass;
3729 //fz *= m_mass;
3730
3731 fx += m_force.X;
3732 fy += m_force.Y;
3733 fz += m_force.Z;
3734
3735 //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString());
3736 if (fx != 0 || fy != 0 || fz != 0)
3737 {
3738 //m_taintdisable = true;
3739 //base.RaiseOutOfBounds(Position);
3740 //d.BodySetLinearVel(Body, fx, fy, 0f);
3741 if (!d.BodyIsEnabled(Body))
3742 {
3743 // A physical body at rest on a surface will auto-disable after a while,
3744 // this appears to re-enable it incase the surface it is upon vanishes,
3745 // and the body should fall again.
3746 d.BodySetLinearVel(Body, 0f, 0f, 0f);
3747 d.BodySetForce(Body, 0, 0, 0);
3748 enableBodySoft();
3749 }
3750
3751 // 35x10 = 350n times the mass per second applied maximum.
3752 float nmax = 35f * m_mass;
3753 float nmin = -35f * m_mass;
3754
3755
3756 if (fx > nmax)
3757 fx = nmax;
3758 if (fx < nmin)
3759 fx = nmin;
3760 if (fy > nmax)
3761 fy = nmax;
3762 if (fy < nmin)
3763 fy = nmin;
3764 d.BodyAddForce(Body, fx, fy, fz);
3765//Console.WriteLine("AddForce " + fx + "," + fy + "," + fz);
3766 }
3767 }
3768 }
3769 else
3770 { // is not physical, or is not a body or is selected
3771 // from old UpdatePositionAndVelocity, ... Not a body.. so Make sure the client isn't interpolating
3772 _velocity.X = 0;
3773 _velocity.Y = 0;
3774 _velocity.Z = 0;
3775
3776 _acceleration.X = 0;
3777 _acceleration.Y = 0;
3778 _acceleration.Z = 0;
3779
3780 m_rotationalVelocity.X = 0;
3781 m_rotationalVelocity.Y = 0;
3782 m_rotationalVelocity.Z = 0;
3783 _zeroFlag = true;
3784 return;
3785 }
3786 } // end Move()
3787 } // end class
3788}
diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODERayCastRequestManager.cs b/OpenSim/Region/Physics/ChOdePlugin/ODERayCastRequestManager.cs
new file mode 100644
index 0000000..7314107
--- /dev/null
+++ b/OpenSim/Region/Physics/ChOdePlugin/ODERayCastRequestManager.cs
@@ -0,0 +1,375 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Runtime.InteropServices;
32using System.Text;
33using OpenMetaverse;
34using OpenSim.Region.Physics.Manager;
35using Ode.NET;
36using log4net;
37
38namespace OpenSim.Region.Physics.OdePlugin
39{
40 /// <summary>
41 /// Processes raycast requests as ODE is in a state to be able to do them.
42 /// This ensures that it's thread safe and there will be no conflicts.
43 /// Requests get returned by a different thread then they were requested by.
44 /// </summary>
45 public class ODERayCastRequestManager
46 {
47 /// <summary>
48 /// Pending Raycast Requests
49 /// </summary>
50 protected List<ODERayCastRequest> m_PendingRequests = new List<ODERayCastRequest>();
51
52 /// <summary>
53 /// Scene that created this object.
54 /// </summary>
55 private OdeScene m_scene;
56
57 /// <summary>
58 /// ODE contact array to be filled by the collision testing
59 /// </summary>
60 d.ContactGeom[] contacts = new d.ContactGeom[5];
61
62 /// <summary>
63 /// ODE near callback delegate
64 /// </summary>
65 private d.NearCallback nearCallback;
66 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
67 private List<ContactResult> m_contactResults = new List<ContactResult>();
68
69
70 public ODERayCastRequestManager(OdeScene pScene)
71 {
72 m_scene = pScene;
73 nearCallback = near;
74
75 }
76
77 /// <summary>
78 /// Queues a raycast
79 /// </summary>
80 /// <param name="position">Origin of Ray</param>
81 /// <param name="direction">Ray normal</param>
82 /// <param name="length">Ray length</param>
83 /// <param name="retMethod">Return method to send the results</param>
84 public void QueueRequest(Vector3 position, Vector3 direction, float length, RaycastCallback retMethod)
85 {
86 lock (m_PendingRequests)
87 {
88 ODERayCastRequest req = new ODERayCastRequest();
89 req.callbackMethod = retMethod;
90 req.length = length;
91 req.Normal = direction;
92 req.Origin = position;
93
94 m_PendingRequests.Add(req);
95 }
96 }
97
98 /// <summary>
99 /// Process all queued raycast requests
100 /// </summary>
101 /// <returns>Time in MS the raycasts took to process.</returns>
102 public int ProcessQueuedRequests()
103 {
104 int time = System.Environment.TickCount;
105 lock (m_PendingRequests)
106 {
107 if (m_PendingRequests.Count > 0)
108 {
109 ODERayCastRequest[] reqs = m_PendingRequests.ToArray();
110 for (int i = 0; i < reqs.Length; i++)
111 {
112 if (reqs[i].callbackMethod != null) // quick optimization here, don't raycast
113 RayCast(reqs[i]); // if there isn't anyone to send results
114 }
115 /*
116 foreach (ODERayCastRequest req in m_PendingRequests)
117 {
118 if (req.callbackMethod != null) // quick optimization here, don't raycast
119 RayCast(req); // if there isn't anyone to send results to
120
121 }
122 */
123 m_PendingRequests.Clear();
124 }
125 }
126
127 lock (m_contactResults)
128 m_contactResults.Clear();
129
130 return System.Environment.TickCount - time;
131 }
132
133 /// <summary>
134 /// Method that actually initiates the raycast
135 /// </summary>
136 /// <param name="req"></param>
137 private void RayCast(ODERayCastRequest req)
138 {
139 // Create the ray
140 IntPtr ray = d.CreateRay(m_scene.space, req.length);
141 d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z);
142
143 // Collide test
144 d.SpaceCollide2(m_scene.space, ray, IntPtr.Zero, nearCallback);
145
146 // Remove Ray
147 d.GeomDestroy(ray);
148
149
150 // Define default results
151 bool hitYN = false;
152 uint hitConsumerID = 0;
153 float distance = 999999999999f;
154 Vector3 closestcontact = new Vector3(99999f, 99999f, 99999f);
155 Vector3 snormal = Vector3.Zero;
156
157 // Find closest contact and object.
158 lock (m_contactResults)
159 {
160 foreach (ContactResult cResult in m_contactResults)
161 {
162 if (Vector3.Distance(req.Origin, cResult.Pos) < Vector3.Distance(req.Origin, closestcontact))
163 {
164 closestcontact = cResult.Pos;
165 hitConsumerID = cResult.ConsumerID;
166 distance = cResult.Depth;
167 hitYN = true;
168 snormal = cResult.Normal;
169 }
170 }
171
172 m_contactResults.Clear();
173 }
174
175 // Return results
176 if (req.callbackMethod != null)
177 req.callbackMethod(hitYN, closestcontact, hitConsumerID, distance, snormal);
178 }
179
180 // This is the standard Near. Uses space AABBs to speed up detection.
181 private void near(IntPtr space, IntPtr g1, IntPtr g2)
182 {
183
184 //Don't test against heightfield Geom, or you'll be sorry!
185
186 /*
187 terminate called after throwing an instance of 'std::bad_alloc'
188 what(): std::bad_alloc
189 Stacktrace:
190
191 at (wrapper managed-to-native) Ode.NET.d.Collide (intptr,intptr,int,Ode.NET.d/ContactGeom[],int) <0x00004>
192 at (wrapper managed-to-native) Ode.NET.d.Collide (intptr,intptr,int,Ode.NET.d/ContactGeom[],int) <0xffffffff>
193 at OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.near (intptr,intptr,intptr) <0x00280>
194 at (wrapper native-to-managed) OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.near (intptr,intptr,intptr) <0xfff
195 fffff>
196 at (wrapper managed-to-native) Ode.NET.d.SpaceCollide2 (intptr,intptr,intptr,Ode.NET.d/NearCallback) <0x00004>
197 at (wrapper managed-to-native) Ode.NET.d.SpaceCollide2 (intptr,intptr,intptr,Ode.NET.d/NearCallback) <0xffffffff>
198 at OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.RayCast (OpenSim.Region.Physics.OdePlugin.ODERayCastRequest) <
199 0x00114>
200 at OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.ProcessQueuedRequests () <0x000eb>
201 at OpenSim.Region.Physics.OdePlugin.OdeScene.Simulate (single) <0x017e6>
202 at OpenSim.Region.Framework.Scenes.SceneGraph.UpdatePhysics (double) <0x00042>
203 at OpenSim.Region.Framework.Scenes.Scene.Update () <0x0039e>
204 at OpenSim.Region.Framework.Scenes.Scene.Heartbeat (object) <0x00019>
205 at (wrapper runtime-invoke) object.runtime_invoke_void__this___object (object,intptr,intptr,intptr) <0xffffffff>
206
207 Native stacktrace:
208
209 mono [0x80d2a42]
210 [0xb7f5840c]
211 /lib/i686/cmov/libc.so.6(abort+0x188) [0xb7d1a018]
212 /usr/lib/libstdc++.so.6(_ZN9__gnu_cxx27__verbose_terminate_handlerEv+0x158) [0xb45fc988]
213 /usr/lib/libstdc++.so.6 [0xb45fa865]
214 /usr/lib/libstdc++.so.6 [0xb45fa8a2]
215 /usr/lib/libstdc++.so.6 [0xb45fa9da]
216 /usr/lib/libstdc++.so.6(_Znwj+0x83) [0xb45fb033]
217 /usr/lib/libstdc++.so.6(_Znaj+0x1d) [0xb45fb11d]
218 libode.so(_ZN13dxHeightfield23dCollideHeightfieldZoneEiiiiP6dxGeomiiP12dContactGeomi+0xd04) [0xb46678e4]
219 libode.so(_Z19dCollideHeightfieldP6dxGeomS0_iP12dContactGeomi+0x54b) [0xb466832b]
220 libode.so(dCollide+0x102) [0xb46571b2]
221 [0x95cfdec9]
222 [0x8ea07fe1]
223 [0xab260146]
224 libode.so [0xb465a5c4]
225 libode.so(_ZN11dxHashSpace8collide2EPvP6dxGeomPFvS0_S2_S2_E+0x75) [0xb465bcf5]
226 libode.so(dSpaceCollide2+0x177) [0xb465ac67]
227 [0x95cf978e]
228 [0x8ea07945]
229 [0x95cf2bbc]
230 [0xab2787e7]
231 [0xab419fb3]
232 [0xab416657]
233 [0xab415bda]
234 [0xb609b08e]
235 mono(mono_runtime_delegate_invoke+0x34) [0x8192534]
236 mono [0x81a2f0f]
237 mono [0x81d28b6]
238 mono [0x81ea2c6]
239 /lib/i686/cmov/libpthread.so.0 [0xb7e744c0]
240 /lib/i686/cmov/libc.so.6(clone+0x5e) [0xb7dcd6de]
241 */
242
243 // Exclude heightfield geom
244
245 if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
246 return;
247 if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass || d.GeomGetClass(g2) == d.GeomClassID.HeightfieldClass)
248 return;
249
250 // Raytest against AABBs of spaces first, then dig into the spaces it hits for actual geoms.
251 if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2))
252 {
253 if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
254 return;
255
256 // Separating static prim geometry spaces.
257 // We'll be calling near recursivly if one
258 // of them is a space to find all of the
259 // contact points in the space
260 try
261 {
262 d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
263 }
264 catch (AccessViolationException)
265 {
266 m_log.Warn("[PHYSICS]: Unable to collide test a space");
267 return;
268 }
269 //Colliding a space or a geom with a space or a geom. so drill down
270
271 //Collide all geoms in each space..
272 //if (d.GeomIsSpace(g1)) d.SpaceCollide(g1, IntPtr.Zero, nearCallback);
273 //if (d.GeomIsSpace(g2)) d.SpaceCollide(g2, IntPtr.Zero, nearCallback);
274 return;
275 }
276
277 if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
278 return;
279
280 int count = 0;
281 try
282 {
283
284 if (g1 == g2)
285 return; // Can't collide with yourself
286
287 lock (contacts)
288 {
289 count = d.Collide(g1, g2, contacts.GetLength(0), contacts, d.ContactGeom.SizeOf);
290 }
291 }
292 catch (SEHException)
293 {
294 m_log.Error("[PHYSICS]: The Operating system shut down ODE because of corrupt memory. This could be a result of really irregular terrain. If this repeats continuously, restart using Basic Physics and terrain fill your terrain. Restarting the sim.");
295 }
296 catch (Exception e)
297 {
298 m_log.WarnFormat("[PHYSICS]: Unable to collide test an object: {0}", e.Message);
299 return;
300 }
301
302 PhysicsActor p1 = null;
303 PhysicsActor p2 = null;
304
305 if (g1 != IntPtr.Zero)
306 m_scene.actor_name_map.TryGetValue(g1, out p1);
307
308 if (g2 != IntPtr.Zero)
309 m_scene.actor_name_map.TryGetValue(g1, out p2);
310
311 // Loop over contacts, build results.
312 for (int i = 0; i < count; i++)
313 {
314 if (p1 != null) {
315 if (p1 is OdePrim)
316 {
317 ContactResult collisionresult = new ContactResult();
318
319 collisionresult.ConsumerID = ((OdePrim)p1).m_localID;
320 collisionresult.Pos = new Vector3(contacts[i].pos.X, contacts[i].pos.Y, contacts[i].pos.Z);
321 collisionresult.Depth = contacts[i].depth;
322 collisionresult.Normal = new Vector3(contacts[i].normal.X, contacts[i].normal.Y,
323 contacts[i].normal.Z);
324 lock (m_contactResults)
325 m_contactResults.Add(collisionresult);
326 }
327 }
328
329 if (p2 != null)
330 {
331 if (p2 is OdePrim)
332 {
333 ContactResult collisionresult = new ContactResult();
334
335 collisionresult.ConsumerID = ((OdePrim)p2).m_localID;
336 collisionresult.Pos = new Vector3(contacts[i].pos.X, contacts[i].pos.Y, contacts[i].pos.Z);
337 collisionresult.Depth = contacts[i].depth;
338 collisionresult.Normal = new Vector3(contacts[i].normal.X, contacts[i].normal.Y,
339 contacts[i].normal.Z);
340
341 lock (m_contactResults)
342 m_contactResults.Add(collisionresult);
343 }
344 }
345
346
347 }
348
349 }
350
351 /// <summary>
352 /// Dereference the creator scene so that it can be garbage collected if needed.
353 /// </summary>
354 internal void Dispose()
355 {
356 m_scene = null;
357 }
358 }
359
360 public struct ODERayCastRequest
361 {
362 public Vector3 Origin;
363 public Vector3 Normal;
364 public float length;
365 public RaycastCallback callbackMethod;
366 }
367
368 public struct ContactResult
369 {
370 public Vector3 Pos;
371 public float Depth;
372 public uint ConsumerID;
373 public Vector3 Normal;
374 }
375}
diff --git a/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs b/OpenSim/Region/Physics/ChOdePlugin/OdePhysicsJoint.cs
index ca7a4f8..b4a3c48 100644
--- a/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs
+++ b/OpenSim/Region/Physics/ChOdePlugin/OdePhysicsJoint.cs
@@ -26,51 +26,23 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using OpenMetaverse;
30using Nini.Config; 30using Ode.NET;
31using OpenSim.Framework; 31using OpenSim.Framework;
32using OpenSim.Region.Physics.Manager; 32using OpenSim.Region.Physics.Manager;
33using PhysXWrapper; 33using OpenSim.Region.Physics.OdePlugin;
34using Quaternion=OpenMetaverse.Quaternion;
35using System.Reflection;
36using log4net;
37using OpenMetaverse;
38 34
39namespace OpenSim.Region.Physics.PhysXPlugin 35namespace OpenSim.Region.Physics.OdePlugin
40{ 36{
41 /// <summary> 37 class OdePhysicsJoint : PhysicsJoint
42 /// Will be the PhysX plugin but for now will be a very basic physics engine
43 /// </summary>
44 public class PhysXPlugin : IPhysicsPlugin
45 { 38 {
46 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 39 public override bool IsInPhysicsEngine
47 private PhysXScene _mScene;
48
49 public PhysXPlugin()
50 {
51 }
52
53 public bool Init()
54 { 40 {
55 return true; 41 get
56 }
57
58 public PhysicsScene GetScene(string sceneIdentifier)
59 {
60 if (_mScene == null)
61 { 42 {
62 _mScene = new PhysXScene(sceneIdentifier); 43 return (jointID != IntPtr.Zero);
63 } 44 }
64 return (_mScene);
65 }
66
67 public string GetName()
68 {
69 return ("RealPhysX");
70 }
71
72 public void Dispose()
73 {
74 } 45 }
46 public IntPtr jointID;
75 } 47 }
76} 48}
diff --git a/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs
new file mode 100644
index 0000000..79e2986
--- /dev/null
+++ b/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs
@@ -0,0 +1,3853 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28//#define USE_DRAWSTUFF
29
30using System;
31using System.Collections.Generic;
32using System.Reflection;
33using System.Runtime.InteropServices;
34using System.Threading;
35using System.IO;
36using System.Diagnostics;
37using log4net;
38using Nini.Config;
39using Ode.NET;
40#if USE_DRAWSTUFF
41using Drawstuff.NET;
42#endif
43using OpenSim.Framework;
44using OpenSim.Region.Physics.Manager;
45using OpenMetaverse;
46
47//using OpenSim.Region.Physics.OdePlugin.Meshing;
48
49namespace OpenSim.Region.Physics.OdePlugin
50{
51 /// <summary>
52 /// ODE plugin
53 /// </summary>
54 public class OdePlugin : IPhysicsPlugin
55 {
56 //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
57
58 private CollisionLocker ode;
59 private OdeScene _mScene;
60
61 public OdePlugin()
62 {
63 ode = new CollisionLocker();
64 }
65
66 public bool Init()
67 {
68 return true;
69 }
70
71 public PhysicsScene GetScene(String sceneIdentifier)
72 {
73 if (_mScene == null)
74 {
75 // Initializing ODE only when a scene is created allows alternative ODE plugins to co-habit (according to
76 // http://opensimulator.org/mantis/view.php?id=2750).
77 d.InitODE();
78
79 _mScene = new OdeScene(ode, sceneIdentifier);
80 }
81 return (_mScene);
82 }
83
84 public string GetName()
85 {
86 return ("ChODE");
87 }
88
89 public void Dispose()
90 {
91 }
92 }
93
94 public enum StatusIndicators : int
95 {
96 Generic = 0,
97 Start = 1,
98 End = 2
99 }
100
101 public struct sCollisionData
102 {
103 public uint ColliderLocalId;
104 public uint CollidedWithLocalId;
105 public int NumberOfCollisions;
106 public int CollisionType;
107 public int StatusIndicator;
108 public int lastframe;
109 }
110
111 [Flags]
112 public enum CollisionCategories : int
113 {
114 Disabled = 0,
115 Geom = 0x00000001,
116 Body = 0x00000002,
117 Space = 0x00000004,
118 Character = 0x00000008,
119 Land = 0x00000010,
120 Water = 0x00000020,
121 Wind = 0x00000040,
122 Sensor = 0x00000080,
123 Selected = 0x00000100
124 }
125
126 /// <summary>
127 /// Material type for a primitive
128 /// </summary>
129 public enum Material : int
130 {
131 /// <summary></summary>
132 Stone = 0,
133 /// <summary></summary>
134 Metal = 1,
135 /// <summary></summary>
136 Glass = 2,
137 /// <summary></summary>
138 Wood = 3,
139 /// <summary></summary>
140 Flesh = 4,
141 /// <summary></summary>
142 Plastic = 5,
143 /// <summary></summary>
144 Rubber = 6
145
146 }
147
148 public sealed class OdeScene : PhysicsScene
149 {
150 private readonly ILog m_log;
151 // private Dictionary<string, sCollisionData> m_storedCollisions = new Dictionary<string, sCollisionData>();
152
153 CollisionLocker ode;
154
155 private Random fluidRandomizer = new Random(Environment.TickCount);
156
157 private const uint m_regionWidth = Constants.RegionSize;
158 private const uint m_regionHeight = Constants.RegionSize;
159
160 private float ODE_STEPSIZE = 0.020f;
161 private float metersInSpace = 29.9f;
162 private float m_timeDilation = 1.0f;
163
164 public float gravityx = 0f;
165 public float gravityy = 0f;
166 public float gravityz = -9.8f;
167
168 private float contactsurfacelayer = 0.001f;
169
170 private int worldHashspaceLow = -4;
171 private int worldHashspaceHigh = 128;
172
173 private int smallHashspaceLow = -4;
174 private int smallHashspaceHigh = 66;
175
176 private float waterlevel = 0f;
177 private int framecount = 0;
178 //private int m_returncollisions = 10;
179
180 private readonly IntPtr contactgroup;
181
182 internal IntPtr LandGeom;
183 internal IntPtr WaterGeom;
184
185 private float nmTerrainContactFriction = 255.0f;
186 private float nmTerrainContactBounce = 0.1f;
187 private float nmTerrainContactERP = 0.1025f;
188
189 private float mTerrainContactFriction = 75f;
190 private float mTerrainContactBounce = 0.1f;
191 private float mTerrainContactERP = 0.05025f;
192
193 private float nmAvatarObjectContactFriction = 250f;
194 private float nmAvatarObjectContactBounce = 0.1f;
195
196 private float mAvatarObjectContactFriction = 75f;
197 private float mAvatarObjectContactBounce = 0.1f;
198
199 private float avPIDD = 3200f;
200 private float avPIDP = 1400f;
201 private float avCapRadius = 0.37f;
202 private float avStandupTensor = 2000000f;
203 private bool avCapsuleTilted = true; // true = old compatibility mode with leaning capsule; false = new corrected mode
204 public bool IsAvCapsuleTilted { get { return avCapsuleTilted; } set { avCapsuleTilted = value; } }
205 private float avDensity = 80f;
206 private float avHeightFudgeFactor = 0.52f;
207 private float avMovementDivisorWalk = 1.3f;
208 private float avMovementDivisorRun = 0.8f;
209 private float minimumGroundFlightOffset = 3f;
210 public float maximumMassObject = 10000.01f;
211
212 public bool meshSculptedPrim = true;
213 public bool forceSimplePrimMeshing = false;
214
215 public float meshSculptLOD = 32;
216 public float MeshSculptphysicalLOD = 16;
217
218 public float geomDefaultDensity = 10.000006836f;
219
220 public int geomContactPointsStartthrottle = 3;
221 public int geomUpdatesPerThrottledUpdate = 15;
222
223 public float bodyPIDD = 35f;
224 public float bodyPIDG = 25;
225
226 public int geomCrossingFailuresBeforeOutofbounds = 5;
227 public int geomRegionFence = 0;
228
229 public float bodyMotorJointMaxforceTensor = 2;
230
231 public int bodyFramesAutoDisable = 20;
232
233 private DateTime m_lastframe = DateTime.UtcNow;
234
235 private float[] _watermap;
236 private bool m_filterCollisions = true;
237
238 private d.NearCallback nearCallback;
239 public d.TriCallback triCallback;
240 public d.TriArrayCallback triArrayCallback;
241 private readonly HashSet<OdeCharacter> _characters = new HashSet<OdeCharacter>();
242 private readonly HashSet<OdePrim> _prims = new HashSet<OdePrim>();
243 private readonly HashSet<OdePrim> _activeprims = new HashSet<OdePrim>();
244 private readonly HashSet<OdePrim> _taintedPrimH = new HashSet<OdePrim>();
245 private readonly Object _taintedPrimLock = new Object();
246 private readonly List<OdePrim> _taintedPrimL = new List<OdePrim>();
247 private readonly HashSet<OdeCharacter> _taintedActors = new HashSet<OdeCharacter>();
248 private readonly List<d.ContactGeom> _perloopContact = new List<d.ContactGeom>();
249 private readonly List<PhysicsActor> _collisionEventPrim = new List<PhysicsActor>();
250 private readonly HashSet<OdeCharacter> _badCharacter = new HashSet<OdeCharacter>();
251 public Dictionary<IntPtr, String> geom_name_map = new Dictionary<IntPtr, String>();
252 public Dictionary<IntPtr, PhysicsActor> actor_name_map = new Dictionary<IntPtr, PhysicsActor>();
253 private bool m_NINJA_physics_joints_enabled = false;
254 //private Dictionary<String, IntPtr> jointpart_name_map = new Dictionary<String,IntPtr>();
255 private readonly Dictionary<String, List<PhysicsJoint>> joints_connecting_actor = new Dictionary<String, List<PhysicsJoint>>();
256 private d.ContactGeom[] contacts;
257 private readonly List<PhysicsJoint> requestedJointsToBeCreated = new List<PhysicsJoint>(); // lock only briefly. accessed by external code (to request new joints) and by OdeScene.Simulate() to move those joints into pending/active
258 private readonly List<PhysicsJoint> pendingJoints = new List<PhysicsJoint>(); // can lock for longer. accessed only by OdeScene.
259 private readonly List<PhysicsJoint> activeJoints = new List<PhysicsJoint>(); // can lock for longer. accessed only by OdeScene.
260 private readonly List<string> requestedJointsToBeDeleted = new List<string>(); // lock only briefly. accessed by external code (to request deletion of joints) and by OdeScene.Simulate() to move those joints out of pending/active
261 private Object externalJointRequestsLock = new Object();
262 private readonly Dictionary<String, PhysicsJoint> SOPName_to_activeJoint = new Dictionary<String, PhysicsJoint>();
263 private readonly Dictionary<String, PhysicsJoint> SOPName_to_pendingJoint = new Dictionary<String, PhysicsJoint>();
264 private readonly DoubleDictionary<Vector3, IntPtr, IntPtr> RegionTerrain = new DoubleDictionary<Vector3, IntPtr, IntPtr>();
265 private readonly Dictionary<IntPtr,float[]> TerrainHeightFieldHeights = new Dictionary<IntPtr, float[]>();
266
267 private d.Contact contact;
268 private d.Contact TerrainContact;
269 private d.Contact AvatarMovementprimContact;
270 private d.Contact AvatarMovementTerrainContact;
271 private d.Contact WaterContact;
272 private d.Contact[,] m_materialContacts;
273
274//Ckrinke: Comment out until used. We declare it, initialize it, but do not use it
275//Ckrinke private int m_randomizeWater = 200;
276 private int m_physicsiterations = 10;
277 private const float m_SkipFramesAtms = 0.40f; // Drop frames gracefully at a 400 ms lag
278 private readonly PhysicsActor PANull = new NullPhysicsActor();
279 private float step_time = 0.0f;
280//Ckrinke: Comment out until used. We declare it, initialize it, but do not use it
281//Ckrinke private int ms = 0;
282 public IntPtr world;
283 //private bool returncollisions = false;
284 // private uint obj1LocalID = 0;
285 private uint obj2LocalID = 0;
286 //private int ctype = 0;
287 private OdeCharacter cc1;
288 private OdePrim cp1;
289 private OdeCharacter cc2;
290 private OdePrim cp2;
291 //private int cStartStop = 0;
292 //private string cDictKey = "";
293
294 public IntPtr space;
295
296 //private IntPtr tmpSpace;
297 // split static geometry collision handling into spaces of 30 meters
298 public IntPtr[,] staticPrimspace;
299
300 public Object OdeLock;
301
302 public IMesher mesher;
303
304 private IConfigSource m_config;
305
306 public bool physics_logging = false;
307 public int physics_logging_interval = 0;
308 public bool physics_logging_append_existing_logfile = false;
309
310 public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f);
311 public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f);
312
313 // TODO: unused: private uint heightmapWidth = m_regionWidth + 1;
314 // TODO: unused: private uint heightmapHeight = m_regionHeight + 1;
315 // TODO: unused: private uint heightmapWidthSamples;
316 // TODO: unused: private uint heightmapHeightSamples;
317
318 private volatile int m_global_contactcount = 0;
319
320 private Vector3 m_worldOffset = Vector3.Zero;
321 public Vector2 WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize);
322 private PhysicsScene m_parentScene = null;
323
324 private ODERayCastRequestManager m_rayCastManager;
325
326 /// <summary>
327 /// Initiailizes the scene
328 /// Sets many properties that ODE requires to be stable
329 /// These settings need to be tweaked 'exactly' right or weird stuff happens.
330 /// </summary>
331 public OdeScene(CollisionLocker dode, string sceneIdentifier)
332 {
333 m_log
334 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.ToString() + "." + sceneIdentifier);
335
336 OdeLock = new Object();
337 ode = dode;
338 nearCallback = near;
339 triCallback = TriCallback;
340 triArrayCallback = TriArrayCallback;
341 m_rayCastManager = new ODERayCastRequestManager(this);
342 lock (OdeLock)
343 {
344 // Create the world and the first space
345 world = d.WorldCreate();
346 space = d.HashSpaceCreate(IntPtr.Zero);
347
348
349 contactgroup = d.JointGroupCreate(0);
350 //contactgroup
351
352 d.WorldSetAutoDisableFlag(world, false);
353 #if USE_DRAWSTUFF
354
355 Thread viewthread = new Thread(new ParameterizedThreadStart(startvisualization));
356 viewthread.Start();
357 #endif
358 }
359
360
361 _watermap = new float[258 * 258];
362
363 // Zero out the prim spaces array (we split our space into smaller spaces so
364 // we can hit test less.
365 }
366
367#if USE_DRAWSTUFF
368 public void startvisualization(object o)
369 {
370 ds.Functions fn;
371 fn.version = ds.VERSION;
372 fn.start = new ds.CallbackFunction(start);
373 fn.step = new ds.CallbackFunction(step);
374 fn.command = new ds.CallbackFunction(command);
375 fn.stop = null;
376 fn.path_to_textures = "./textures";
377 string[] args = new string[0];
378 ds.SimulationLoop(args.Length, args, 352, 288, ref fn);
379 }
380#endif
381
382 // Initialize the mesh plugin
383 public override void Initialise(IMesher meshmerizer, IConfigSource config)
384 {
385 mesher = meshmerizer;
386 m_config = config;
387 // Defaults
388
389 if (Environment.OSVersion.Platform == PlatformID.Unix)
390 {
391 avPIDD = 3200.0f;
392 avPIDP = 1400.0f;
393 avStandupTensor = 2000000f;
394 }
395 else
396 {
397 avPIDD = 2200.0f;
398 avPIDP = 900.0f;
399 avStandupTensor = 550000f;
400 }
401
402 int contactsPerCollision = 80;
403
404 if (m_config != null)
405 {
406 IConfig physicsconfig = m_config.Configs["ODEPhysicsSettings"];
407 if (physicsconfig != null)
408 {
409 gravityx = physicsconfig.GetFloat("world_gravityx", 0f);
410 gravityy = physicsconfig.GetFloat("world_gravityy", 0f);
411 gravityz = physicsconfig.GetFloat("world_gravityz", -9.8f);
412
413 worldHashspaceLow = physicsconfig.GetInt("world_hashspace_size_low", -4);
414 worldHashspaceHigh = physicsconfig.GetInt("world_hashspace_size_high", 128);
415
416 metersInSpace = physicsconfig.GetFloat("meters_in_small_space", 29.9f);
417 smallHashspaceLow = physicsconfig.GetInt("small_hashspace_size_low", -4);
418 smallHashspaceHigh = physicsconfig.GetInt("small_hashspace_size_high", 66);
419
420 contactsurfacelayer = physicsconfig.GetFloat("world_contact_surface_layer", 0.001f);
421
422 nmTerrainContactFriction = physicsconfig.GetFloat("nm_terraincontact_friction", 255.0f);
423 nmTerrainContactBounce = physicsconfig.GetFloat("nm_terraincontact_bounce", 0.1f);
424 nmTerrainContactERP = physicsconfig.GetFloat("nm_terraincontact_erp", 0.1025f);
425
426 mTerrainContactFriction = physicsconfig.GetFloat("m_terraincontact_friction", 75f);
427 mTerrainContactBounce = physicsconfig.GetFloat("m_terraincontact_bounce", 0.05f);
428 mTerrainContactERP = physicsconfig.GetFloat("m_terraincontact_erp", 0.05025f);
429
430 nmAvatarObjectContactFriction = physicsconfig.GetFloat("objectcontact_friction", 250f);
431 nmAvatarObjectContactBounce = physicsconfig.GetFloat("objectcontact_bounce", 0.2f);
432
433 mAvatarObjectContactFriction = physicsconfig.GetFloat("m_avatarobjectcontact_friction", 75f);
434 mAvatarObjectContactBounce = physicsconfig.GetFloat("m_avatarobjectcontact_bounce", 0.1f);
435
436 ODE_STEPSIZE = physicsconfig.GetFloat("world_stepsize", 0.020f);
437 m_physicsiterations = physicsconfig.GetInt("world_internal_steps_without_collisions", 10);
438
439 avDensity = physicsconfig.GetFloat("av_density", 80f);
440 avHeightFudgeFactor = physicsconfig.GetFloat("av_height_fudge_factor", 0.52f);
441 avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", 1.3f);
442 avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", 0.8f);
443 avCapRadius = physicsconfig.GetFloat("av_capsule_radius", 0.37f);
444 avCapsuleTilted = physicsconfig.GetBoolean("av_capsule_tilted", false);
445
446 contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80);
447
448 geomContactPointsStartthrottle = physicsconfig.GetInt("geom_contactpoints_start_throttling", 3);
449 geomUpdatesPerThrottledUpdate = physicsconfig.GetInt("geom_updates_before_throttled_update", 15);
450 geomCrossingFailuresBeforeOutofbounds = physicsconfig.GetInt("geom_crossing_failures_before_outofbounds", 5);
451 geomRegionFence = physicsconfig.GetInt("region_border_fence", 0);
452
453 geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", 10.000006836f);
454 bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", 20);
455
456 bodyPIDD = physicsconfig.GetFloat("body_pid_derivative", 35f);
457 bodyPIDG = physicsconfig.GetFloat("body_pid_gain", 25f);
458
459 forceSimplePrimMeshing = physicsconfig.GetBoolean("force_simple_prim_meshing", forceSimplePrimMeshing);
460 meshSculptedPrim = physicsconfig.GetBoolean("mesh_sculpted_prim", true);
461 meshSculptLOD = physicsconfig.GetFloat("mesh_lod", 32f);
462 MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f);
463 m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false);
464
465 if (Environment.OSVersion.Platform == PlatformID.Unix)
466 {
467 avPIDD = physicsconfig.GetFloat("av_pid_derivative_linux", 2200.0f);
468 avPIDP = physicsconfig.GetFloat("av_pid_proportional_linux", 900.0f);
469 avStandupTensor = physicsconfig.GetFloat("av_capsule_standup_tensor_linux", 550000f);
470 bodyMotorJointMaxforceTensor = physicsconfig.GetFloat("body_motor_joint_maxforce_tensor_linux", 5f);
471 }
472 else
473 {
474 avPIDD = physicsconfig.GetFloat("av_pid_derivative_win", 2200.0f);
475 avPIDP = physicsconfig.GetFloat("av_pid_proportional_win", 900.0f);
476 avStandupTensor = physicsconfig.GetFloat("av_capsule_standup_tensor_win", 550000f);
477 bodyMotorJointMaxforceTensor = physicsconfig.GetFloat("body_motor_joint_maxforce_tensor_win", 5f);
478 }
479
480 physics_logging = physicsconfig.GetBoolean("physics_logging", false);
481 physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0);
482 physics_logging_append_existing_logfile = physicsconfig.GetBoolean("physics_logging_append_existing_logfile", false);
483
484 m_NINJA_physics_joints_enabled = physicsconfig.GetBoolean("use_NINJA_physics_joints", false);
485 minimumGroundFlightOffset = physicsconfig.GetFloat("minimum_ground_flight_offset", 3f);
486 maximumMassObject = physicsconfig.GetFloat("maximum_mass_object", 10000.01f);
487 }
488 }
489
490 contacts = new d.ContactGeom[contactsPerCollision];
491
492 staticPrimspace = new IntPtr[(int)(300 / metersInSpace), (int)(300 / metersInSpace)];
493
494 // Centeral contact friction and bounce
495 // ckrinke 11/10/08 Enabling soft_erp but not soft_cfm until I figure out why
496 // an avatar falls through in Z but not in X or Y when walking on a prim.
497 contact.surface.mode |= d.ContactFlags.SoftERP;
498 contact.surface.mu = nmAvatarObjectContactFriction;
499 contact.surface.bounce = nmAvatarObjectContactBounce;
500 contact.surface.soft_cfm = 0.010f;
501 contact.surface.soft_erp = 0.010f;
502
503 // Terrain contact friction and Bounce
504 // This is the *non* moving version. Use this when an avatar
505 // isn't moving to keep it in place better
506 TerrainContact.surface.mode |= d.ContactFlags.SoftERP;
507 TerrainContact.surface.mu = nmTerrainContactFriction;
508 TerrainContact.surface.bounce = nmTerrainContactBounce;
509 TerrainContact.surface.soft_erp = nmTerrainContactERP;
510
511 WaterContact.surface.mode |= (d.ContactFlags.SoftERP | d.ContactFlags.SoftCFM);
512 WaterContact.surface.mu = 0f; // No friction
513 WaterContact.surface.bounce = 0.0f; // No bounce
514 WaterContact.surface.soft_cfm = 0.010f;
515 WaterContact.surface.soft_erp = 0.010f;
516
517 // Prim contact friction and bounce
518 // THis is the *non* moving version of friction and bounce
519 // Use this when an avatar comes in contact with a prim
520 // and is moving
521 AvatarMovementprimContact.surface.mu = mAvatarObjectContactFriction;
522 AvatarMovementprimContact.surface.bounce = mAvatarObjectContactBounce;
523
524 // Terrain contact friction bounce and various error correcting calculations
525 // Use this when an avatar is in contact with the terrain and moving.
526 AvatarMovementTerrainContact.surface.mode |= d.ContactFlags.SoftERP;
527 AvatarMovementTerrainContact.surface.mu = mTerrainContactFriction;
528 AvatarMovementTerrainContact.surface.bounce = mTerrainContactBounce;
529 AvatarMovementTerrainContact.surface.soft_erp = mTerrainContactERP;
530
531
532 /*
533 <summary></summary>
534 Stone = 0,
535 /// <summary></summary>
536 Metal = 1,
537 /// <summary></summary>
538 Glass = 2,
539 /// <summary></summary>
540 Wood = 3,
541 /// <summary></summary>
542 Flesh = 4,
543 /// <summary></summary>
544 Plastic = 5,
545 /// <summary></summary>
546 Rubber = 6
547 */
548
549 m_materialContacts = new d.Contact[7,2];
550
551 m_materialContacts[(int)Material.Stone, 0] = new d.Contact();
552 m_materialContacts[(int)Material.Stone, 0].surface.mode |= d.ContactFlags.SoftERP;
553 m_materialContacts[(int)Material.Stone, 0].surface.mu = nmAvatarObjectContactFriction;
554 m_materialContacts[(int)Material.Stone, 0].surface.bounce = nmAvatarObjectContactBounce;
555 m_materialContacts[(int)Material.Stone, 0].surface.soft_cfm = 0.010f;
556 m_materialContacts[(int)Material.Stone, 0].surface.soft_erp = 0.010f;
557
558 m_materialContacts[(int)Material.Stone, 1] = new d.Contact();
559 m_materialContacts[(int)Material.Stone, 1].surface.mode |= d.ContactFlags.SoftERP;
560 m_materialContacts[(int)Material.Stone, 1].surface.mu = mAvatarObjectContactFriction;
561 m_materialContacts[(int)Material.Stone, 1].surface.bounce = mAvatarObjectContactBounce;
562 m_materialContacts[(int)Material.Stone, 1].surface.soft_cfm = 0.010f;
563 m_materialContacts[(int)Material.Stone, 1].surface.soft_erp = 0.010f;
564
565 m_materialContacts[(int)Material.Metal, 0] = new d.Contact();
566 m_materialContacts[(int)Material.Metal, 0].surface.mode |= d.ContactFlags.SoftERP;
567 m_materialContacts[(int)Material.Metal, 0].surface.mu = nmAvatarObjectContactFriction;
568 m_materialContacts[(int)Material.Metal, 0].surface.bounce = nmAvatarObjectContactBounce;
569 m_materialContacts[(int)Material.Metal, 0].surface.soft_cfm = 0.010f;
570 m_materialContacts[(int)Material.Metal, 0].surface.soft_erp = 0.010f;
571
572 m_materialContacts[(int)Material.Metal, 1] = new d.Contact();
573 m_materialContacts[(int)Material.Metal, 1].surface.mode |= d.ContactFlags.SoftERP;
574 m_materialContacts[(int)Material.Metal, 1].surface.mu = mAvatarObjectContactFriction;
575 m_materialContacts[(int)Material.Metal, 1].surface.bounce = mAvatarObjectContactBounce;
576 m_materialContacts[(int)Material.Metal, 1].surface.soft_cfm = 0.010f;
577 m_materialContacts[(int)Material.Metal, 1].surface.soft_erp = 0.010f;
578
579 m_materialContacts[(int)Material.Glass, 0] = new d.Contact();
580 m_materialContacts[(int)Material.Glass, 0].surface.mode |= d.ContactFlags.SoftERP;
581 m_materialContacts[(int)Material.Glass, 0].surface.mu = 1f;
582 m_materialContacts[(int)Material.Glass, 0].surface.bounce = 0.5f;
583 m_materialContacts[(int)Material.Glass, 0].surface.soft_cfm = 0.010f;
584 m_materialContacts[(int)Material.Glass, 0].surface.soft_erp = 0.010f;
585
586 /*
587 private float nmAvatarObjectContactFriction = 250f;
588 private float nmAvatarObjectContactBounce = 0.1f;
589
590 private float mAvatarObjectContactFriction = 75f;
591 private float mAvatarObjectContactBounce = 0.1f;
592 */
593 m_materialContacts[(int)Material.Glass, 1] = new d.Contact();
594 m_materialContacts[(int)Material.Glass, 1].surface.mode |= d.ContactFlags.SoftERP;
595 m_materialContacts[(int)Material.Glass, 1].surface.mu = 1f;
596 m_materialContacts[(int)Material.Glass, 1].surface.bounce = 0.5f;
597 m_materialContacts[(int)Material.Glass, 1].surface.soft_cfm = 0.010f;
598 m_materialContacts[(int)Material.Glass, 1].surface.soft_erp = 0.010f;
599
600 m_materialContacts[(int)Material.Wood, 0] = new d.Contact();
601 m_materialContacts[(int)Material.Wood, 0].surface.mode |= d.ContactFlags.SoftERP;
602 m_materialContacts[(int)Material.Wood, 0].surface.mu = nmAvatarObjectContactFriction;
603 m_materialContacts[(int)Material.Wood, 0].surface.bounce = nmAvatarObjectContactBounce;
604 m_materialContacts[(int)Material.Wood, 0].surface.soft_cfm = 0.010f;
605 m_materialContacts[(int)Material.Wood, 0].surface.soft_erp = 0.010f;
606
607 m_materialContacts[(int)Material.Wood, 1] = new d.Contact();
608 m_materialContacts[(int)Material.Wood, 1].surface.mode |= d.ContactFlags.SoftERP;
609 m_materialContacts[(int)Material.Wood, 1].surface.mu = mAvatarObjectContactFriction;
610 m_materialContacts[(int)Material.Wood, 1].surface.bounce = mAvatarObjectContactBounce;
611 m_materialContacts[(int)Material.Wood, 1].surface.soft_cfm = 0.010f;
612 m_materialContacts[(int)Material.Wood, 1].surface.soft_erp = 0.010f;
613
614 m_materialContacts[(int)Material.Flesh, 0] = new d.Contact();
615 m_materialContacts[(int)Material.Flesh, 0].surface.mode |= d.ContactFlags.SoftERP;
616 m_materialContacts[(int)Material.Flesh, 0].surface.mu = nmAvatarObjectContactFriction;
617 m_materialContacts[(int)Material.Flesh, 0].surface.bounce = nmAvatarObjectContactBounce;
618 m_materialContacts[(int)Material.Flesh, 0].surface.soft_cfm = 0.010f;
619 m_materialContacts[(int)Material.Flesh, 0].surface.soft_erp = 0.010f;
620
621 m_materialContacts[(int)Material.Flesh, 1] = new d.Contact();
622 m_materialContacts[(int)Material.Flesh, 1].surface.mode |= d.ContactFlags.SoftERP;
623 m_materialContacts[(int)Material.Flesh, 1].surface.mu = mAvatarObjectContactFriction;
624 m_materialContacts[(int)Material.Flesh, 1].surface.bounce = mAvatarObjectContactBounce;
625 m_materialContacts[(int)Material.Flesh, 1].surface.soft_cfm = 0.010f;
626 m_materialContacts[(int)Material.Flesh, 1].surface.soft_erp = 0.010f;
627
628 m_materialContacts[(int)Material.Plastic, 0] = new d.Contact();
629 m_materialContacts[(int)Material.Plastic, 0].surface.mode |= d.ContactFlags.SoftERP;
630 m_materialContacts[(int)Material.Plastic, 0].surface.mu = nmAvatarObjectContactFriction;
631 m_materialContacts[(int)Material.Plastic, 0].surface.bounce = nmAvatarObjectContactBounce;
632 m_materialContacts[(int)Material.Plastic, 0].surface.soft_cfm = 0.010f;
633 m_materialContacts[(int)Material.Plastic, 0].surface.soft_erp = 0.010f;
634
635 m_materialContacts[(int)Material.Plastic, 1] = new d.Contact();
636 m_materialContacts[(int)Material.Plastic, 1].surface.mode |= d.ContactFlags.SoftERP;
637 m_materialContacts[(int)Material.Plastic, 1].surface.mu = mAvatarObjectContactFriction;
638 m_materialContacts[(int)Material.Plastic, 1].surface.bounce = mAvatarObjectContactBounce;
639 m_materialContacts[(int)Material.Plastic, 1].surface.soft_cfm = 0.010f;
640 m_materialContacts[(int)Material.Plastic, 1].surface.soft_erp = 0.010f;
641
642 m_materialContacts[(int)Material.Rubber, 0] = new d.Contact();
643 m_materialContacts[(int)Material.Rubber, 0].surface.mode |= d.ContactFlags.SoftERP;
644 m_materialContacts[(int)Material.Rubber, 0].surface.mu = nmAvatarObjectContactFriction;
645 m_materialContacts[(int)Material.Rubber, 0].surface.bounce = nmAvatarObjectContactBounce;
646 m_materialContacts[(int)Material.Rubber, 0].surface.soft_cfm = 0.010f;
647 m_materialContacts[(int)Material.Rubber, 0].surface.soft_erp = 0.010f;
648
649 m_materialContacts[(int)Material.Rubber, 1] = new d.Contact();
650 m_materialContacts[(int)Material.Rubber, 1].surface.mode |= d.ContactFlags.SoftERP;
651 m_materialContacts[(int)Material.Rubber, 1].surface.mu = mAvatarObjectContactFriction;
652 m_materialContacts[(int)Material.Rubber, 1].surface.bounce = mAvatarObjectContactBounce;
653 m_materialContacts[(int)Material.Rubber, 1].surface.soft_cfm = 0.010f;
654 m_materialContacts[(int)Material.Rubber, 1].surface.soft_erp = 0.010f;
655
656 d.HashSpaceSetLevels(space, worldHashspaceLow, worldHashspaceHigh);
657
658 // Set the gravity,, don't disable things automatically (we set it explicitly on some things)
659
660 d.WorldSetGravity(world, gravityx, gravityy, gravityz);
661 d.WorldSetContactSurfaceLayer(world, contactsurfacelayer);
662
663 d.WorldSetLinearDamping(world, 256f);
664 d.WorldSetAngularDamping(world, 256f);
665 d.WorldSetAngularDampingThreshold(world, 256f);
666 d.WorldSetLinearDampingThreshold(world, 256f);
667 d.WorldSetMaxAngularSpeed(world, 256f);
668
669 // Set how many steps we go without running collision testing
670 // This is in addition to the step size.
671 // Essentially Steps * m_physicsiterations
672 d.WorldSetQuickStepNumIterations(world, m_physicsiterations);
673 //d.WorldSetContactMaxCorrectingVel(world, 1000.0f);
674
675
676
677 for (int i = 0; i < staticPrimspace.GetLength(0); i++)
678 {
679 for (int j = 0; j < staticPrimspace.GetLength(1); j++)
680 {
681 staticPrimspace[i, j] = IntPtr.Zero;
682 }
683 }
684 }
685
686 internal void waitForSpaceUnlock(IntPtr space)
687 {
688 //if (space != IntPtr.Zero)
689 //while (d.SpaceLockQuery(space)) { } // Wait and do nothing
690 }
691
692 /// <summary>
693 /// Debug space message for printing the space that a prim/avatar is in.
694 /// </summary>
695 /// <param name="pos"></param>
696 /// <returns>Returns which split up space the given position is in.</returns>
697 public string whichspaceamIin(Vector3 pos)
698 {
699 return calculateSpaceForGeom(pos).ToString();
700 }
701
702 #region Collision Detection
703
704 /// <summary>
705 /// This is our near callback. A geometry is near a body
706 /// </summary>
707 /// <param name="space">The space that contains the geoms. Remember, spaces are also geoms</param>
708 /// <param name="g1">a geometry or space</param>
709 /// <param name="g2">another geometry or space</param>
710 private void near(IntPtr space, IntPtr g1, IntPtr g2)
711 {
712 // no lock here! It's invoked from within Simulate(), which is thread-locked
713
714 // Test if we're colliding a geom with a space.
715 // If so we have to drill down into the space recursively
716
717 if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2))
718 {
719 if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
720 return;
721
722 // Separating static prim geometry spaces.
723 // We'll be calling near recursivly if one
724 // of them is a space to find all of the
725 // contact points in the space
726 try
727 {
728 d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
729 }
730 catch (AccessViolationException)
731 {
732 m_log.Warn("[PHYSICS]: Unable to collide test a space");
733 return;
734 }
735 //Colliding a space or a geom with a space or a geom. so drill down
736
737 //Collide all geoms in each space..
738 //if (d.GeomIsSpace(g1)) d.SpaceCollide(g1, IntPtr.Zero, nearCallback);
739 //if (d.GeomIsSpace(g2)) d.SpaceCollide(g2, IntPtr.Zero, nearCallback);
740 return;
741 }
742
743 if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
744 return;
745
746 IntPtr b1 = d.GeomGetBody(g1);
747 IntPtr b2 = d.GeomGetBody(g2);
748
749 // d.GeomClassID id = d.GeomGetClass(g1);
750
751 String name1 = null;
752 String name2 = null;
753
754 if (!geom_name_map.TryGetValue(g1, out name1))
755 {
756 name1 = "null";
757 }
758 if (!geom_name_map.TryGetValue(g2, out name2))
759 {
760 name2 = "null";
761 }
762
763 //if (id == d.GeomClassId.TriMeshClass)
764 //{
765 // m_log.InfoFormat("near: A collision was detected between {1} and {2}", 0, name1, name2);
766 //m_log.Debug("near: A collision was detected between {1} and {2}", 0, name1, name2);
767 //}
768
769 // Figure out how many contact points we have
770 int count = 0;
771 try
772 {
773 // Colliding Geom To Geom
774 // This portion of the function 'was' blatantly ripped off from BoxStack.cs
775
776 if (g1 == g2)
777 return; // Can't collide with yourself
778
779 if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
780 return;
781
782 lock (contacts)
783 {
784 count = d.Collide(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf);
785 if (count > contacts.Length)
786 m_log.Error("[PHYSICS]: Got " + count + " contacts when we asked for a maximum of " + contacts.Length);
787 }
788 }
789 catch (SEHException)
790 {
791 m_log.Error("[PHYSICS]: The Operating system shut down ODE because of corrupt memory. This could be a result of really irregular terrain. If this repeats continuously, restart using Basic Physics and terrain fill your terrain. Restarting the sim.");
792 ode.drelease(world);
793 base.TriggerPhysicsBasedRestart();
794 }
795 catch (Exception e)
796 {
797 m_log.WarnFormat("[PHYSICS]: Unable to collide test an object: {0}", e.Message);
798 return;
799 }
800
801 PhysicsActor p1;
802 PhysicsActor p2;
803
804 if (!actor_name_map.TryGetValue(g1, out p1))
805 {
806 p1 = PANull;
807 }
808
809 if (!actor_name_map.TryGetValue(g2, out p2))
810 {
811 p2 = PANull;
812 }
813
814 ContactPoint maxDepthContact = new ContactPoint();
815 if (p1.CollisionScore + count >= float.MaxValue)
816 p1.CollisionScore = 0;
817 p1.CollisionScore += count;
818
819 if (p2.CollisionScore + count >= float.MaxValue)
820 p2.CollisionScore = 0;
821 p2.CollisionScore += count;
822
823 for (int i = 0; i < count; i++)
824 {
825 d.ContactGeom curContact = contacts[i];
826
827 if (curContact.depth > maxDepthContact.PenetrationDepth)
828 {
829 maxDepthContact = new ContactPoint(
830 new Vector3(curContact.pos.X, curContact.pos.Y, curContact.pos.Z),
831 new Vector3(curContact.normal.X, curContact.normal.Y, curContact.normal.Z),
832 curContact.depth
833 );
834 }
835
836 //m_log.Warn("[CCOUNT]: " + count);
837 IntPtr joint;
838 // If we're colliding with terrain, use 'TerrainContact' instead of contact.
839 // allows us to have different settings
840
841 // We only need to test p2 for 'jump crouch purposes'
842 if (p2 is OdeCharacter && p1.PhysicsActorType == (int)ActorTypes.Prim)
843 {
844 // Testing if the collision is at the feet of the avatar
845
846 //m_log.DebugFormat("[PHYSICS]: {0} - {1} - {2} - {3}", curContact.pos.Z, p2.Position.Z, (p2.Position.Z - curContact.pos.Z), (p2.Size.Z * 0.6f));
847 if ((p2.Position.Z - curContact.pos.Z) > (p2.Size.Z * 0.6f))
848 p2.IsColliding = true;
849 }
850 else
851 {
852 p2.IsColliding = true;
853 }
854
855 //if ((framecount % m_returncollisions) == 0)
856
857 switch (p1.PhysicsActorType)
858 {
859 case (int)ActorTypes.Agent:
860 p2.CollidingObj = true;
861 break;
862 case (int)ActorTypes.Prim:
863 if (p2.Velocity.LengthSquared() > 0.0f)
864 p2.CollidingObj = true;
865 break;
866 case (int)ActorTypes.Unknown:
867 p2.CollidingGround = true;
868 break;
869 default:
870 p2.CollidingGround = true;
871 break;
872 }
873
874 // we don't want prim or avatar to explode
875
876 #region InterPenetration Handling - Unintended physics explosions
877# region disabled code1
878
879 if (curContact.depth >= 0.08f)
880 {
881 //This is disabled at the moment only because it needs more tweaking
882 //It will eventually be uncommented
883 /*
884 if (contact.depth >= 1.00f)
885 {
886 //m_log.Debug("[PHYSICS]: " + contact.depth.ToString());
887 }
888
889 //If you interpenetrate a prim with an agent
890 if ((p2.PhysicsActorType == (int) ActorTypes.Agent &&
891 p1.PhysicsActorType == (int) ActorTypes.Prim) ||
892 (p1.PhysicsActorType == (int) ActorTypes.Agent &&
893 p2.PhysicsActorType == (int) ActorTypes.Prim))
894 {
895
896 //contact.depth = contact.depth * 4.15f;
897 /*
898 if (p2.PhysicsActorType == (int) ActorTypes.Agent)
899 {
900 p2.CollidingObj = true;
901 contact.depth = 0.003f;
902 p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 2.5f);
903 OdeCharacter character = (OdeCharacter) p2;
904 character.SetPidStatus(true);
905 contact.pos = new d.Vector3(contact.pos.X + (p1.Size.X / 2), contact.pos.Y + (p1.Size.Y / 2), contact.pos.Z + (p1.Size.Z / 2));
906
907 }
908 else
909 {
910
911 //contact.depth = 0.0000000f;
912 }
913 if (p1.PhysicsActorType == (int) ActorTypes.Agent)
914 {
915
916 p1.CollidingObj = true;
917 contact.depth = 0.003f;
918 p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 2.5f);
919 contact.pos = new d.Vector3(contact.pos.X + (p2.Size.X / 2), contact.pos.Y + (p2.Size.Y / 2), contact.pos.Z + (p2.Size.Z / 2));
920 OdeCharacter character = (OdeCharacter)p1;
921 character.SetPidStatus(true);
922 }
923 else
924 {
925
926 //contact.depth = 0.0000000f;
927 }
928
929
930
931 }
932*/
933 // If you interpenetrate a prim with another prim
934 /*
935 if (p1.PhysicsActorType == (int) ActorTypes.Prim && p2.PhysicsActorType == (int) ActorTypes.Prim)
936 {
937 #region disabledcode2
938 //OdePrim op1 = (OdePrim)p1;
939 //OdePrim op2 = (OdePrim)p2;
940 //op1.m_collisionscore++;
941 //op2.m_collisionscore++;
942
943 //if (op1.m_collisionscore > 8000 || op2.m_collisionscore > 8000)
944 //{
945 //op1.m_taintdisable = true;
946 //AddPhysicsActorTaint(p1);
947 //op2.m_taintdisable = true;
948 //AddPhysicsActorTaint(p2);
949 //}
950
951 //if (contact.depth >= 0.25f)
952 //{
953 // Don't collide, one or both prim will expld.
954
955 //op1.m_interpenetrationcount++;
956 //op2.m_interpenetrationcount++;
957 //interpenetrations_before_disable = 200;
958 //if (op1.m_interpenetrationcount >= interpenetrations_before_disable)
959 //{
960 //op1.m_taintdisable = true;
961 //AddPhysicsActorTaint(p1);
962 //}
963 //if (op2.m_interpenetrationcount >= interpenetrations_before_disable)
964 //{
965 // op2.m_taintdisable = true;
966 //AddPhysicsActorTaint(p2);
967 //}
968
969 //contact.depth = contact.depth / 8f;
970 //contact.normal = new d.Vector3(0, 0, 1);
971 //}
972 //if (op1.m_disabled || op2.m_disabled)
973 //{
974 //Manually disabled objects stay disabled
975 //contact.depth = 0f;
976 //}
977 #endregion
978 }
979 */
980#endregion
981 if (curContact.depth >= 1.00f)
982 {
983 //m_log.Info("[P]: " + contact.depth.ToString());
984 if ((p2.PhysicsActorType == (int) ActorTypes.Agent &&
985 p1.PhysicsActorType == (int) ActorTypes.Unknown) ||
986 (p1.PhysicsActorType == (int) ActorTypes.Agent &&
987 p2.PhysicsActorType == (int) ActorTypes.Unknown))
988 {
989 if (p2.PhysicsActorType == (int) ActorTypes.Agent)
990 {
991 if (p2 is OdeCharacter)
992 {
993 OdeCharacter character = (OdeCharacter) p2;
994
995 //p2.CollidingObj = true;
996 curContact.depth = 0.00000003f;
997 p2.Velocity = p2.Velocity + new Vector3(0f, 0f, 0.5f);
998 curContact.pos =
999 new d.Vector3(curContact.pos.X + (p1.Size.X/2),
1000 curContact.pos.Y + (p1.Size.Y/2),
1001 curContact.pos.Z + (p1.Size.Z/2));
1002 character.SetPidStatus(true);
1003 }
1004 }
1005
1006
1007 if (p1.PhysicsActorType == (int) ActorTypes.Agent)
1008 {
1009 if (p1 is OdeCharacter)
1010 {
1011 OdeCharacter character = (OdeCharacter) p1;
1012
1013 //p2.CollidingObj = true;
1014 curContact.depth = 0.00000003f;
1015 p1.Velocity = p1.Velocity + new Vector3(0f, 0f, 0.5f);
1016 curContact.pos =
1017 new d.Vector3(curContact.pos.X + (p1.Size.X/2),
1018 curContact.pos.Y + (p1.Size.Y/2),
1019 curContact.pos.Z + (p1.Size.Z/2));
1020 character.SetPidStatus(true);
1021 }
1022 }
1023 }
1024 }
1025 }
1026
1027 #endregion
1028
1029 // Logic for collision handling
1030 // Note, that if *all* contacts are skipped (VolumeDetect)
1031 // The prim still detects (and forwards) collision events but
1032 // appears to be phantom for the world
1033 Boolean skipThisContact = false;
1034
1035 if ((p1 is OdePrim) && (((OdePrim)p1).m_isVolumeDetect))
1036 skipThisContact = true; // No collision on volume detect prims
1037
1038 if (!skipThisContact && (p2 is OdePrim) && (((OdePrim)p2).m_isVolumeDetect))
1039 skipThisContact = true; // No collision on volume detect prims
1040
1041 if (!skipThisContact && curContact.depth < 0f)
1042 skipThisContact = true;
1043
1044 if (!skipThisContact && checkDupe(curContact, p2.PhysicsActorType))
1045 skipThisContact = true;
1046
1047 const int maxContactsbeforedeath = 4000;
1048 joint = IntPtr.Zero;
1049
1050 if (!skipThisContact)
1051 {
1052 // If we're colliding against terrain
1053 if (name1 == "Terrain" || name2 == "Terrain")
1054 {
1055 // If we're moving
1056 if ((p2.PhysicsActorType == (int) ActorTypes.Agent) &&
1057 (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f))
1058 {
1059 // Use the movement terrain contact
1060 AvatarMovementTerrainContact.geom = curContact;
1061 _perloopContact.Add(curContact);
1062 if (m_global_contactcount < maxContactsbeforedeath)
1063 {
1064 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementTerrainContact);
1065 m_global_contactcount++;
1066 }
1067 }
1068 else
1069 {
1070 if (p2.PhysicsActorType == (int)ActorTypes.Agent)
1071 {
1072 // Use the non moving terrain contact
1073 TerrainContact.geom = curContact;
1074 _perloopContact.Add(curContact);
1075 if (m_global_contactcount < maxContactsbeforedeath)
1076 {
1077 joint = d.JointCreateContact(world, contactgroup, ref TerrainContact);
1078 m_global_contactcount++;
1079 }
1080 }
1081 else
1082 {
1083 if (p2.PhysicsActorType == (int)ActorTypes.Prim && p1.PhysicsActorType == (int)ActorTypes.Prim)
1084 {
1085 // prim prim contact
1086 // int pj294950 = 0;
1087 int movintYN = 0;
1088 int material = (int) Material.Wood;
1089 // prim terrain contact
1090 if (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)
1091 {
1092 movintYN = 1;
1093 }
1094
1095 if (p2 is OdePrim)
1096 material = ((OdePrim)p2).m_material;
1097
1098 //m_log.DebugFormat("Material: {0}", material);
1099 m_materialContacts[material, movintYN].geom = curContact;
1100 _perloopContact.Add(curContact);
1101
1102 if (m_global_contactcount < maxContactsbeforedeath)
1103 {
1104 joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, movintYN]);
1105 m_global_contactcount++;
1106
1107 }
1108
1109 }
1110 else
1111 {
1112
1113 int movintYN = 0;
1114 // prim terrain contact
1115 if (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)
1116 {
1117 movintYN = 1;
1118 }
1119
1120 int material = (int)Material.Wood;
1121
1122 if (p2 is OdePrim)
1123 material = ((OdePrim)p2).m_material;
1124 //m_log.DebugFormat("Material: {0}", material);
1125 m_materialContacts[material, movintYN].geom = curContact;
1126 _perloopContact.Add(curContact);
1127
1128 if (m_global_contactcount < maxContactsbeforedeath)
1129 {
1130 joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, movintYN]);
1131 m_global_contactcount++;
1132
1133 }
1134 }
1135 }
1136 }
1137 //if (p2.PhysicsActorType == (int)ActorTypes.Prim)
1138 //{
1139 //m_log.Debug("[PHYSICS]: prim contacting with ground");
1140 //}
1141 }
1142 else if (name1 == "Water" || name2 == "Water")
1143 {
1144 /*
1145 if ((p2.PhysicsActorType == (int) ActorTypes.Prim))
1146 {
1147 }
1148 else
1149 {
1150 }
1151 */
1152 //WaterContact.surface.soft_cfm = 0.0000f;
1153 //WaterContact.surface.soft_erp = 0.00000f;
1154 if (curContact.depth > 0.1f)
1155 {
1156 curContact.depth *= 52;
1157 //contact.normal = new d.Vector3(0, 0, 1);
1158 //contact.pos = new d.Vector3(0, 0, contact.pos.Z - 5f);
1159 }
1160 WaterContact.geom = curContact;
1161 _perloopContact.Add(curContact);
1162 if (m_global_contactcount < maxContactsbeforedeath)
1163 {
1164 joint = d.JointCreateContact(world, contactgroup, ref WaterContact);
1165 m_global_contactcount++;
1166 }
1167 //m_log.Info("[PHYSICS]: Prim Water Contact" + contact.depth);
1168 }
1169 else
1170 {
1171 // we're colliding with prim or avatar
1172 // check if we're moving
1173 if ((p2.PhysicsActorType == (int)ActorTypes.Agent))
1174 {
1175 if ((Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f))
1176 {
1177 // Use the Movement prim contact
1178 AvatarMovementprimContact.geom = curContact;
1179 _perloopContact.Add(curContact);
1180 if (m_global_contactcount < maxContactsbeforedeath)
1181 {
1182 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementprimContact);
1183 m_global_contactcount++;
1184 }
1185 }
1186 else
1187 {
1188 // Use the non movement contact
1189 contact.geom = curContact;
1190 _perloopContact.Add(curContact);
1191
1192 if (m_global_contactcount < maxContactsbeforedeath)
1193 {
1194 joint = d.JointCreateContact(world, contactgroup, ref contact);
1195 m_global_contactcount++;
1196 }
1197 }
1198 }
1199 else if (p2.PhysicsActorType == (int)ActorTypes.Prim)
1200 {
1201 //p1.PhysicsActorType
1202 int material = (int)Material.Wood;
1203
1204 if (p2 is OdePrim)
1205 material = ((OdePrim)p2).m_material;
1206
1207 //m_log.DebugFormat("Material: {0}", material);
1208 m_materialContacts[material, 0].geom = curContact;
1209 _perloopContact.Add(curContact);
1210
1211 if (m_global_contactcount < maxContactsbeforedeath)
1212 {
1213 joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, 0]);
1214 m_global_contactcount++;
1215
1216 }
1217 }
1218 }
1219
1220 if (m_global_contactcount < maxContactsbeforedeath && joint != IntPtr.Zero) // stack collide!
1221 {
1222 d.JointAttach(joint, b1, b2);
1223 m_global_contactcount++;
1224 }
1225
1226 }
1227 collision_accounting_events(p1, p2, maxDepthContact);
1228 if (count > geomContactPointsStartthrottle)
1229 {
1230 // If there are more then 3 contact points, it's likely
1231 // that we've got a pile of objects, so ...
1232 // We don't want to send out hundreds of terse updates over and over again
1233 // so lets throttle them and send them again after it's somewhat sorted out.
1234 p2.ThrottleUpdates = true;
1235 }
1236 //m_log.Debug(count.ToString());
1237 //m_log.Debug("near: A collision was detected between {1} and {2}", 0, name1, name2);
1238 }
1239 }
1240
1241 private bool checkDupe(d.ContactGeom contactGeom, int atype)
1242 {
1243 bool result = false;
1244 //return result;
1245 if (!m_filterCollisions)
1246 return false;
1247
1248 ActorTypes at = (ActorTypes)atype;
1249 lock (_perloopContact)
1250 {
1251 foreach (d.ContactGeom contact in _perloopContact)
1252 {
1253 //if ((contact.g1 == contactGeom.g1 && contact.g2 == contactGeom.g2))
1254 //{
1255 // || (contact.g2 == contactGeom.g1 && contact.g1 == contactGeom.g2)
1256 if (at == ActorTypes.Agent)
1257 {
1258 if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)) && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom)
1259 {
1260
1261 if (Math.Abs(contact.depth - contactGeom.depth) < 0.052f)
1262 {
1263 //contactGeom.depth *= .00005f;
1264 //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth));
1265 // m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z));
1266 result = true;
1267 break;
1268 }
1269 else
1270 {
1271 //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth));
1272 }
1273 }
1274 else
1275 {
1276 //m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z));
1277 //int i = 0;
1278 }
1279 }
1280 else if (at == ActorTypes.Prim)
1281 {
1282 //d.AABB aabb1 = new d.AABB();
1283 //d.AABB aabb2 = new d.AABB();
1284
1285 //d.GeomGetAABB(contactGeom.g2, out aabb2);
1286 //d.GeomGetAABB(contactGeom.g1, out aabb1);
1287 //aabb1.
1288 if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)) && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom)
1289 {
1290 if (contactGeom.normal.X == contact.normal.X && contactGeom.normal.Y == contact.normal.Y && contactGeom.normal.Z == contact.normal.Z)
1291 {
1292 if (Math.Abs(contact.depth - contactGeom.depth) < 0.272f)
1293 {
1294 result = true;
1295 break;
1296 }
1297 }
1298 //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth));
1299 //m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z));
1300 }
1301
1302 }
1303
1304 //}
1305
1306 }
1307 }
1308 return result;
1309 }
1310
1311 private void collision_accounting_events(PhysicsActor p1, PhysicsActor p2, ContactPoint contact)
1312 {
1313 // obj1LocalID = 0;
1314 //returncollisions = false;
1315 obj2LocalID = 0;
1316 //ctype = 0;
1317 //cStartStop = 0;
1318 if (!p2.SubscribedEvents() && !p1.SubscribedEvents())
1319 return;
1320
1321 switch ((ActorTypes)p2.PhysicsActorType)
1322 {
1323 case ActorTypes.Agent:
1324 cc2 = (OdeCharacter)p2;
1325
1326 // obj1LocalID = cc2.m_localID;
1327 switch ((ActorTypes)p1.PhysicsActorType)
1328 {
1329 case ActorTypes.Agent:
1330 cc1 = (OdeCharacter)p1;
1331 obj2LocalID = cc1.m_localID;
1332 cc1.AddCollisionEvent(cc2.m_localID, contact);
1333 //ctype = (int)CollisionCategories.Character;
1334
1335 //if (cc1.CollidingObj)
1336 //cStartStop = (int)StatusIndicators.Generic;
1337 //else
1338 //cStartStop = (int)StatusIndicators.Start;
1339
1340 //returncollisions = true;
1341 break;
1342 case ActorTypes.Prim:
1343 if (p1 is OdePrim)
1344 {
1345 cp1 = (OdePrim) p1;
1346 obj2LocalID = cp1.m_localID;
1347 cp1.AddCollisionEvent(cc2.m_localID, contact);
1348 }
1349 //ctype = (int)CollisionCategories.Geom;
1350
1351 //if (cp1.CollidingObj)
1352 //cStartStop = (int)StatusIndicators.Generic;
1353 //else
1354 //cStartStop = (int)StatusIndicators.Start;
1355
1356 //returncollisions = true;
1357 break;
1358
1359 case ActorTypes.Ground:
1360 case ActorTypes.Unknown:
1361 obj2LocalID = 0;
1362 //ctype = (int)CollisionCategories.Land;
1363 //returncollisions = true;
1364 break;
1365 }
1366
1367 cc2.AddCollisionEvent(obj2LocalID, contact);
1368 break;
1369 case ActorTypes.Prim:
1370
1371 if (p2 is OdePrim)
1372 {
1373 cp2 = (OdePrim) p2;
1374
1375 // obj1LocalID = cp2.m_localID;
1376 switch ((ActorTypes) p1.PhysicsActorType)
1377 {
1378 case ActorTypes.Agent:
1379 if (p1 is OdeCharacter)
1380 {
1381 cc1 = (OdeCharacter) p1;
1382 obj2LocalID = cc1.m_localID;
1383 cc1.AddCollisionEvent(cp2.m_localID, contact);
1384 //ctype = (int)CollisionCategories.Character;
1385
1386 //if (cc1.CollidingObj)
1387 //cStartStop = (int)StatusIndicators.Generic;
1388 //else
1389 //cStartStop = (int)StatusIndicators.Start;
1390 //returncollisions = true;
1391 }
1392 break;
1393 case ActorTypes.Prim:
1394
1395 if (p1 is OdePrim)
1396 {
1397 cp1 = (OdePrim) p1;
1398 obj2LocalID = cp1.m_localID;
1399 cp1.AddCollisionEvent(cp2.m_localID, contact);
1400 //ctype = (int)CollisionCategories.Geom;
1401
1402 //if (cp1.CollidingObj)
1403 //cStartStop = (int)StatusIndicators.Generic;
1404 //else
1405 //cStartStop = (int)StatusIndicators.Start;
1406
1407 //returncollisions = true;
1408 }
1409 break;
1410
1411 case ActorTypes.Ground:
1412 case ActorTypes.Unknown:
1413 obj2LocalID = 0;
1414 //ctype = (int)CollisionCategories.Land;
1415
1416 //returncollisions = true;
1417 break;
1418 }
1419
1420 cp2.AddCollisionEvent(obj2LocalID, contact);
1421 }
1422 break;
1423 }
1424 //if (returncollisions)
1425 //{
1426
1427 //lock (m_storedCollisions)
1428 //{
1429 //cDictKey = obj1LocalID.ToString() + obj2LocalID.ToString() + cStartStop.ToString() + ctype.ToString();
1430 //if (m_storedCollisions.ContainsKey(cDictKey))
1431 //{
1432 //sCollisionData objd = m_storedCollisions[cDictKey];
1433 //objd.NumberOfCollisions += 1;
1434 //objd.lastframe = framecount;
1435 //m_storedCollisions[cDictKey] = objd;
1436 //}
1437 //else
1438 //{
1439 //sCollisionData objd = new sCollisionData();
1440 //objd.ColliderLocalId = obj1LocalID;
1441 //objd.CollidedWithLocalId = obj2LocalID;
1442 //objd.CollisionType = ctype;
1443 //objd.NumberOfCollisions = 1;
1444 //objd.lastframe = framecount;
1445 //objd.StatusIndicator = cStartStop;
1446 //m_storedCollisions.Add(cDictKey, objd);
1447 //}
1448 //}
1449 // }
1450 }
1451
1452 public int TriArrayCallback(IntPtr trimesh, IntPtr refObject, int[] triangleIndex, int triCount)
1453 {
1454 /* String name1 = null;
1455 String name2 = null;
1456
1457 if (!geom_name_map.TryGetValue(trimesh, out name1))
1458 {
1459 name1 = "null";
1460 }
1461 if (!geom_name_map.TryGetValue(refObject, out name2))
1462 {
1463 name2 = "null";
1464 }
1465
1466 m_log.InfoFormat("TriArrayCallback: A collision was detected between {1} and {2}", 0, name1, name2);
1467 */
1468 return 1;
1469 }
1470
1471 public int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex)
1472 {
1473 String name1 = null;
1474 String name2 = null;
1475
1476 if (!geom_name_map.TryGetValue(trimesh, out name1))
1477 {
1478 name1 = "null";
1479 }
1480
1481 if (!geom_name_map.TryGetValue(refObject, out name2))
1482 {
1483 name2 = "null";
1484 }
1485
1486 // m_log.InfoFormat("TriCallback: A collision was detected between {1} and {2}. Index was {3}", 0, name1, name2, triangleIndex);
1487
1488 d.Vector3 v0 = new d.Vector3();
1489 d.Vector3 v1 = new d.Vector3();
1490 d.Vector3 v2 = new d.Vector3();
1491
1492 d.GeomTriMeshGetTriangle(trimesh, 0, ref v0, ref v1, ref v2);
1493 // m_log.DebugFormat("Triangle {0} is <{1},{2},{3}>, <{4},{5},{6}>, <{7},{8},{9}>", triangleIndex, v0.X, v0.Y, v0.Z, v1.X, v1.Y, v1.Z, v2.X, v2.Y, v2.Z);
1494
1495 return 1;
1496 }
1497
1498 /// <summary>
1499 /// This is our collision testing routine in ODE
1500 /// </summary>
1501 /// <param name="timeStep"></param>
1502 private void collision_optimized(float timeStep)
1503 {
1504 _perloopContact.Clear();
1505
1506 lock (_characters)
1507 {
1508 foreach (OdeCharacter chr in _characters)
1509 {
1510 // Reset the collision values to false
1511 // since we don't know if we're colliding yet
1512
1513 // For some reason this can happen. Don't ask...
1514 //
1515 if (chr == null)
1516 continue;
1517
1518 if (chr.Shell == IntPtr.Zero || chr.Body == IntPtr.Zero)
1519 continue;
1520
1521 chr.IsColliding = false;
1522 chr.CollidingGround = false;
1523 chr.CollidingObj = false;
1524
1525 // test the avatar's geometry for collision with the space
1526 // This will return near and the space that they are the closest to
1527 // And we'll run this again against the avatar and the space segment
1528 // This will return with a bunch of possible objects in the space segment
1529 // and we'll run it again on all of them.
1530 try
1531 {
1532 d.SpaceCollide2(space, chr.Shell, IntPtr.Zero, nearCallback);
1533 }
1534 catch (AccessViolationException)
1535 {
1536 m_log.Warn("[PHYSICS]: Unable to space collide");
1537 }
1538 //float terrainheight = GetTerrainHeightAtXY(chr.Position.X, chr.Position.Y);
1539 //if (chr.Position.Z + (chr.Velocity.Z * timeStep) < terrainheight + 10)
1540 //{
1541 //chr.Position.Z = terrainheight + 10.0f;
1542 //forcedZ = true;
1543 //}
1544 }
1545 }
1546
1547 lock (_activeprims)
1548 {
1549 List<OdePrim> removeprims = null;
1550 foreach (OdePrim chr in _activeprims)
1551 {
1552 if (chr.Body != IntPtr.Zero && d.BodyIsEnabled(chr.Body) && (!chr.m_disabled))
1553 {
1554 try
1555 {
1556 lock (chr)
1557 {
1558 if (space != IntPtr.Zero && chr.prim_geom != IntPtr.Zero && chr.m_taintremove == false)
1559 {
1560 d.SpaceCollide2(space, chr.prim_geom, IntPtr.Zero, nearCallback);
1561 }
1562 else
1563 {
1564 if (removeprims == null)
1565 {
1566 removeprims = new List<OdePrim>();
1567 }
1568 removeprims.Add(chr);
1569 m_log.Debug("[PHYSICS]: unable to collide test active prim against space. The space was zero, the geom was zero or it was in the process of being removed. Removed it from the active prim list. This needs to be fixed!");
1570 }
1571 }
1572 }
1573 catch (AccessViolationException)
1574 {
1575 m_log.Warn("[PHYSICS]: Unable to space collide");
1576 }
1577 }
1578 }
1579 if (removeprims != null)
1580 {
1581 foreach (OdePrim chr in removeprims)
1582 {
1583 _activeprims.Remove(chr);
1584 }
1585 }
1586 }
1587
1588 _perloopContact.Clear();
1589 }
1590
1591 #endregion
1592
1593 public override void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents)
1594 {
1595 m_worldOffset = offset;
1596 WorldExtents = new Vector2(extents.X, extents.Y);
1597 m_parentScene = pScene;
1598
1599 }
1600
1601 // Recovered for use by fly height. Kitto Flora
1602 public float GetTerrainHeightAtXY(float x, float y)
1603 {
1604
1605 int offsetX = ((int)(x / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
1606 int offsetY = ((int)(y / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
1607
1608 IntPtr heightFieldGeom = IntPtr.Zero;
1609
1610 if (RegionTerrain.TryGetValue(new Vector3(offsetX,offsetY,0), out heightFieldGeom))
1611 {
1612 if (heightFieldGeom != IntPtr.Zero)
1613 {
1614 if (TerrainHeightFieldHeights.ContainsKey(heightFieldGeom))
1615 {
1616
1617 int index;
1618
1619
1620 if ((int)x > WorldExtents.X || (int)y > WorldExtents.Y ||
1621 (int)x < 0.001f || (int)y < 0.001f)
1622 return 0;
1623
1624 x = x - offsetX;
1625 y = y - offsetY;
1626
1627 index = (int)((int)x * ((int)Constants.RegionSize + 2) + (int)y);
1628
1629 if (index < TerrainHeightFieldHeights[heightFieldGeom].Length)
1630 {
1631 //m_log.DebugFormat("x{0} y{1} = {2}", x, y, (float)TerrainHeightFieldHeights[heightFieldGeom][index]);
1632 return (float)TerrainHeightFieldHeights[heightFieldGeom][index];
1633 }
1634
1635 else
1636 return 0f;
1637 }
1638 else
1639 {
1640 return 0f;
1641 }
1642
1643 }
1644 else
1645 {
1646 return 0f;
1647 }
1648
1649 }
1650 else
1651 {
1652 return 0f;
1653 }
1654
1655
1656 }
1657// End recovered. Kitto Flora
1658
1659 public void addCollisionEventReporting(PhysicsActor obj)
1660 {
1661 lock (_collisionEventPrim)
1662 {
1663 if (!_collisionEventPrim.Contains(obj))
1664 _collisionEventPrim.Add(obj);
1665 }
1666 }
1667
1668 public void remCollisionEventReporting(PhysicsActor obj)
1669 {
1670 lock (_collisionEventPrim)
1671 {
1672 if (!_collisionEventPrim.Contains(obj))
1673 _collisionEventPrim.Remove(obj);
1674 }
1675 }
1676
1677 #region Add/Remove Entities
1678
1679 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying)
1680 {
1681 Vector3 pos;
1682 pos.X = position.X;
1683 pos.Y = position.Y;
1684 pos.Z = position.Z;
1685 OdeCharacter newAv = new OdeCharacter(avName, this, pos, ode, size, avPIDD, avPIDP, avCapRadius, avStandupTensor, avDensity, avHeightFudgeFactor, avMovementDivisorWalk, avMovementDivisorRun);
1686 newAv.Flying = isFlying;
1687 newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset;
1688
1689 return newAv;
1690 }
1691
1692 public void AddCharacter(OdeCharacter chr)
1693 {
1694 lock (_characters)
1695 {
1696 if (!_characters.Contains(chr))
1697 {
1698 _characters.Add(chr);
1699 if (chr.bad)
1700 m_log.DebugFormat("[PHYSICS] Added BAD actor {0} to characters list", chr.m_uuid);
1701 }
1702 }
1703 }
1704
1705 public void RemoveCharacter(OdeCharacter chr)
1706 {
1707 lock (_characters)
1708 {
1709 if (_characters.Contains(chr))
1710 {
1711 _characters.Remove(chr);
1712 }
1713 }
1714 }
1715 public void BadCharacter(OdeCharacter chr)
1716 {
1717 lock (_badCharacter)
1718 {
1719 if (!_badCharacter.Contains(chr))
1720 _badCharacter.Add(chr);
1721 }
1722 }
1723
1724 public override void RemoveAvatar(PhysicsActor actor)
1725 {
1726 //m_log.Debug("[PHYSICS]:ODELOCK");
1727 ((OdeCharacter) actor).Destroy();
1728
1729 }
1730
1731 private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation,
1732 IMesh mesh, PrimitiveBaseShape pbs, bool isphysical)
1733 {
1734
1735 Vector3 pos = position;
1736 Vector3 siz = size;
1737 Quaternion rot = rotation;
1738
1739 OdePrim newPrim;
1740 lock (OdeLock)
1741 {
1742 newPrim = new OdePrim(name, this, pos, siz, rot, mesh, pbs, isphysical, ode);
1743
1744 lock (_prims)
1745 _prims.Add(newPrim);
1746 }
1747
1748 return newPrim;
1749 }
1750
1751 public void addActivePrim(OdePrim activatePrim)
1752 {
1753 // adds active prim.. (ones that should be iterated over in collisions_optimized
1754 lock (_activeprims)
1755 {
1756 if (!_activeprims.Contains(activatePrim))
1757 _activeprims.Add(activatePrim);
1758 //else
1759 // m_log.Warn("[PHYSICS]: Double Entry in _activeprims detected, potential crash immenent");
1760 }
1761 }
1762
1763 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
1764 Vector3 size, Quaternion rotation) //To be removed
1765 {
1766 return AddPrimShape(primName, pbs, position, size, rotation, false);
1767 }
1768
1769 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
1770 Vector3 size, Quaternion rotation, bool isPhysical)
1771 {
1772 PhysicsActor result;
1773 IMesh mesh = null;
1774
1775 if (needsMeshing(pbs))
1776 mesh = mesher.CreateMesh(primName, pbs, size, 32f, isPhysical);
1777
1778 result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical);
1779
1780 return result;
1781 }
1782
1783 public override float TimeDilation
1784 {
1785 get { return m_timeDilation; }
1786 }
1787
1788 public override bool SupportsNINJAJoints
1789 {
1790 get { return m_NINJA_physics_joints_enabled; }
1791 }
1792
1793 // internal utility function: must be called within a lock (OdeLock)
1794 private void InternalAddActiveJoint(PhysicsJoint joint)
1795 {
1796 activeJoints.Add(joint);
1797 SOPName_to_activeJoint.Add(joint.ObjectNameInScene, joint);
1798 }
1799
1800 // internal utility function: must be called within a lock (OdeLock)
1801 private void InternalAddPendingJoint(OdePhysicsJoint joint)
1802 {
1803 pendingJoints.Add(joint);
1804 SOPName_to_pendingJoint.Add(joint.ObjectNameInScene, joint);
1805 }
1806
1807 // internal utility function: must be called within a lock (OdeLock)
1808 private void InternalRemovePendingJoint(PhysicsJoint joint)
1809 {
1810 pendingJoints.Remove(joint);
1811 SOPName_to_pendingJoint.Remove(joint.ObjectNameInScene);
1812 }
1813
1814 // internal utility function: must be called within a lock (OdeLock)
1815 private void InternalRemoveActiveJoint(PhysicsJoint joint)
1816 {
1817 activeJoints.Remove(joint);
1818 SOPName_to_activeJoint.Remove(joint.ObjectNameInScene);
1819 }
1820
1821 public override void DumpJointInfo()
1822 {
1823 string hdr = "[NINJA] JOINTINFO: ";
1824 foreach (PhysicsJoint j in pendingJoints)
1825 {
1826 m_log.Debug(hdr + " pending joint, Name: " + j.ObjectNameInScene + " raw parms:" + j.RawParams);
1827 }
1828 m_log.Debug(hdr + pendingJoints.Count + " total pending joints");
1829 foreach (string jointName in SOPName_to_pendingJoint.Keys)
1830 {
1831 m_log.Debug(hdr + " pending joints dict contains Name: " + jointName);
1832 }
1833 m_log.Debug(hdr + SOPName_to_pendingJoint.Keys.Count + " total pending joints dict entries");
1834 foreach (PhysicsJoint j in activeJoints)
1835 {
1836 m_log.Debug(hdr + " active joint, Name: " + j.ObjectNameInScene + " raw parms:" + j.RawParams);
1837 }
1838 m_log.Debug(hdr + activeJoints.Count + " total active joints");
1839 foreach (string jointName in SOPName_to_activeJoint.Keys)
1840 {
1841 m_log.Debug(hdr + " active joints dict contains Name: " + jointName);
1842 }
1843 m_log.Debug(hdr + SOPName_to_activeJoint.Keys.Count + " total active joints dict entries");
1844
1845 m_log.Debug(hdr + " Per-body joint connectivity information follows.");
1846 m_log.Debug(hdr + joints_connecting_actor.Keys.Count + " bodies are connected by joints.");
1847 foreach (string actorName in joints_connecting_actor.Keys)
1848 {
1849 m_log.Debug(hdr + " Actor " + actorName + " has the following joints connecting it");
1850 foreach (PhysicsJoint j in joints_connecting_actor[actorName])
1851 {
1852 m_log.Debug(hdr + " * joint Name: " + j.ObjectNameInScene + " raw parms:" + j.RawParams);
1853 }
1854 m_log.Debug(hdr + joints_connecting_actor[actorName].Count + " connecting joints total for this actor");
1855 }
1856 }
1857
1858 public override void RequestJointDeletion(string ObjectNameInScene)
1859 {
1860 lock (externalJointRequestsLock)
1861 {
1862 if (!requestedJointsToBeDeleted.Contains(ObjectNameInScene)) // forbid same deletion request from entering twice to prevent spurious deletions processed asynchronously
1863 {
1864 requestedJointsToBeDeleted.Add(ObjectNameInScene);
1865 }
1866 }
1867 }
1868
1869 private void DeleteRequestedJoints()
1870 {
1871 List<string> myRequestedJointsToBeDeleted;
1872 lock (externalJointRequestsLock)
1873 {
1874 // make a local copy of the shared list for processing (threading issues)
1875 myRequestedJointsToBeDeleted = new List<string>(requestedJointsToBeDeleted);
1876 }
1877
1878 foreach (string jointName in myRequestedJointsToBeDeleted)
1879 {
1880 lock (OdeLock)
1881 {
1882 //m_log.Debug("[NINJA] trying to deleting requested joint " + jointName);
1883 if (SOPName_to_activeJoint.ContainsKey(jointName) || SOPName_to_pendingJoint.ContainsKey(jointName))
1884 {
1885 OdePhysicsJoint joint = null;
1886 if (SOPName_to_activeJoint.ContainsKey(jointName))
1887 {
1888 joint = SOPName_to_activeJoint[jointName] as OdePhysicsJoint;
1889 InternalRemoveActiveJoint(joint);
1890 }
1891 else if (SOPName_to_pendingJoint.ContainsKey(jointName))
1892 {
1893 joint = SOPName_to_pendingJoint[jointName] as OdePhysicsJoint;
1894 InternalRemovePendingJoint(joint);
1895 }
1896
1897 if (joint != null)
1898 {
1899 //m_log.Debug("joint.BodyNames.Count is " + joint.BodyNames.Count + " and contents " + joint.BodyNames);
1900 for (int iBodyName = 0; iBodyName < 2; iBodyName++)
1901 {
1902 string bodyName = joint.BodyNames[iBodyName];
1903 if (bodyName != "NULL")
1904 {
1905 joints_connecting_actor[bodyName].Remove(joint);
1906 if (joints_connecting_actor[bodyName].Count == 0)
1907 {
1908 joints_connecting_actor.Remove(bodyName);
1909 }
1910 }
1911 }
1912
1913 DoJointDeactivated(joint);
1914 if (joint.jointID != IntPtr.Zero)
1915 {
1916 d.JointDestroy(joint.jointID);
1917 joint.jointID = IntPtr.Zero;
1918 //DoJointErrorMessage(joint, "successfully destroyed joint " + jointName);
1919 }
1920 else
1921 {
1922 //m_log.Warn("[NINJA] Ignoring re-request to destroy joint " + jointName);
1923 }
1924 }
1925 else
1926 {
1927 // DoJointErrorMessage(joint, "coult not find joint to destroy based on name " + jointName);
1928 }
1929 }
1930 else
1931 {
1932 // DoJointErrorMessage(joint, "WARNING - joint removal failed, joint " + jointName);
1933 }
1934 }
1935 }
1936
1937 // remove processed joints from the shared list
1938 lock (externalJointRequestsLock)
1939 {
1940 foreach (string jointName in myRequestedJointsToBeDeleted)
1941 {
1942 requestedJointsToBeDeleted.Remove(jointName);
1943 }
1944 }
1945 }
1946
1947 // for pending joints we don't know if their associated bodies exist yet or not.
1948 // the joint is actually created during processing of the taints
1949 private void CreateRequestedJoints()
1950 {
1951 List<PhysicsJoint> myRequestedJointsToBeCreated;
1952 lock (externalJointRequestsLock)
1953 {
1954 // make a local copy of the shared list for processing (threading issues)
1955 myRequestedJointsToBeCreated = new List<PhysicsJoint>(requestedJointsToBeCreated);
1956 }
1957
1958 foreach (PhysicsJoint joint in myRequestedJointsToBeCreated)
1959 {
1960 lock (OdeLock)
1961 {
1962 if (SOPName_to_pendingJoint.ContainsKey(joint.ObjectNameInScene) && SOPName_to_pendingJoint[joint.ObjectNameInScene] != null)
1963 {
1964 DoJointErrorMessage(joint, "WARNING: ignoring request to re-add already pending joint Name:" + joint.ObjectNameInScene + " type:" + joint.Type + " parms: " + joint.RawParams + " pos: " + joint.Position + " rot:" + joint.Rotation);
1965 continue;
1966 }
1967 if (SOPName_to_activeJoint.ContainsKey(joint.ObjectNameInScene) && SOPName_to_activeJoint[joint.ObjectNameInScene] != null)
1968 {
1969 DoJointErrorMessage(joint, "WARNING: ignoring request to re-add already active joint Name:" + joint.ObjectNameInScene + " type:" + joint.Type + " parms: " + joint.RawParams + " pos: " + joint.Position + " rot:" + joint.Rotation);
1970 continue;
1971 }
1972
1973 InternalAddPendingJoint(joint as OdePhysicsJoint);
1974
1975 if (joint.BodyNames.Count >= 2)
1976 {
1977 for (int iBodyName = 0; iBodyName < 2; iBodyName++)
1978 {
1979 string bodyName = joint.BodyNames[iBodyName];
1980 if (bodyName != "NULL")
1981 {
1982 if (!joints_connecting_actor.ContainsKey(bodyName))
1983 {
1984 joints_connecting_actor.Add(bodyName, new List<PhysicsJoint>());
1985 }
1986 joints_connecting_actor[bodyName].Add(joint);
1987 }
1988 }
1989 }
1990 }
1991 }
1992
1993 // remove processed joints from shared list
1994 lock (externalJointRequestsLock)
1995 {
1996 foreach (PhysicsJoint joint in myRequestedJointsToBeCreated)
1997 {
1998 requestedJointsToBeCreated.Remove(joint);
1999 }
2000 }
2001
2002 }
2003
2004 // public function to add an request for joint creation
2005 // this joint will just be added to a waiting list that is NOT processed during the main
2006 // Simulate() loop (to avoid deadlocks). After Simulate() is finished, we handle unprocessed joint requests.
2007
2008 public override PhysicsJoint RequestJointCreation(string objectNameInScene, PhysicsJointType jointType, Vector3 position,
2009 Quaternion rotation, string parms, List<string> bodyNames, string trackedBodyName, Quaternion localRotation)
2010
2011 {
2012
2013 OdePhysicsJoint joint = new OdePhysicsJoint();
2014 joint.ObjectNameInScene = objectNameInScene;
2015 joint.Type = jointType;
2016 joint.Position = position;
2017 joint.Rotation = rotation;
2018 joint.RawParams = parms;
2019 joint.BodyNames = new List<string>(bodyNames);
2020 joint.TrackedBodyName = trackedBodyName;
2021 joint.LocalRotation = localRotation;
2022 joint.jointID = IntPtr.Zero;
2023 joint.ErrorMessageCount = 0;
2024
2025 lock (externalJointRequestsLock)
2026 {
2027 if (!requestedJointsToBeCreated.Contains(joint)) // forbid same creation request from entering twice
2028 {
2029 requestedJointsToBeCreated.Add(joint);
2030 }
2031 }
2032 return joint;
2033 }
2034
2035 private void RemoveAllJointsConnectedToActor(PhysicsActor actor)
2036 {
2037 //m_log.Debug("RemoveAllJointsConnectedToActor: start");
2038 if (actor.SOPName != null && joints_connecting_actor.ContainsKey(actor.SOPName) && joints_connecting_actor[actor.SOPName] != null)
2039 {
2040
2041 List<PhysicsJoint> jointsToRemove = new List<PhysicsJoint>();
2042 //TODO: merge these 2 loops (originally it was needed to avoid altering a list being iterated over, but it is no longer needed due to the joint request queue mechanism)
2043 foreach (PhysicsJoint j in joints_connecting_actor[actor.SOPName])
2044 {
2045 jointsToRemove.Add(j);
2046 }
2047 foreach (PhysicsJoint j in jointsToRemove)
2048 {
2049 //m_log.Debug("RemoveAllJointsConnectedToActor: about to request deletion of " + j.ObjectNameInScene);
2050 RequestJointDeletion(j.ObjectNameInScene);
2051 //m_log.Debug("RemoveAllJointsConnectedToActor: done request deletion of " + j.ObjectNameInScene);
2052 j.TrackedBodyName = null; // *IMMEDIATELY* prevent any further movement of this joint (else a deleted actor might cause spurious tracking motion of the joint for a few frames, leading to the joint proxy object disappearing)
2053 }
2054 }
2055 }
2056
2057 public override void RemoveAllJointsConnectedToActorThreadLocked(PhysicsActor actor)
2058 {
2059 //m_log.Debug("RemoveAllJointsConnectedToActorThreadLocked: start");
2060 lock (OdeLock)
2061 {
2062 //m_log.Debug("RemoveAllJointsConnectedToActorThreadLocked: got lock");
2063 RemoveAllJointsConnectedToActor(actor);
2064 }
2065 }
2066
2067 // normally called from within OnJointMoved, which is called from within a lock (OdeLock)
2068 public override Vector3 GetJointAnchor(PhysicsJoint joint)
2069 {
2070 Debug.Assert(joint.IsInPhysicsEngine);
2071 d.Vector3 pos = new d.Vector3();
2072
2073 if (!(joint is OdePhysicsJoint))
2074 {
2075 DoJointErrorMessage(joint, "warning: non-ODE joint requesting anchor: " + joint.ObjectNameInScene);
2076 }
2077 else
2078 {
2079 OdePhysicsJoint odeJoint = (OdePhysicsJoint)joint;
2080 switch (odeJoint.Type)
2081 {
2082 case PhysicsJointType.Ball:
2083 d.JointGetBallAnchor(odeJoint.jointID, out pos);
2084 break;
2085 case PhysicsJointType.Hinge:
2086 d.JointGetHingeAnchor(odeJoint.jointID, out pos);
2087 break;
2088 }
2089 }
2090 return new Vector3(pos.X, pos.Y, pos.Z);
2091 }
2092
2093 // normally called from within OnJointMoved, which is called from within a lock (OdeLock)
2094 // WARNING: ODE sometimes returns <0,0,0> as the joint axis! Therefore this function
2095 // appears to be unreliable. Fortunately we can compute the joint axis ourselves by
2096 // keeping track of the joint's original orientation relative to one of the involved bodies.
2097 public override Vector3 GetJointAxis(PhysicsJoint joint)
2098 {
2099 Debug.Assert(joint.IsInPhysicsEngine);
2100 d.Vector3 axis = new d.Vector3();
2101
2102 if (!(joint is OdePhysicsJoint))
2103 {
2104 DoJointErrorMessage(joint, "warning: non-ODE joint requesting anchor: " + joint.ObjectNameInScene);
2105 }
2106 else
2107 {
2108 OdePhysicsJoint odeJoint = (OdePhysicsJoint)joint;
2109 switch (odeJoint.Type)
2110 {
2111 case PhysicsJointType.Ball:
2112 DoJointErrorMessage(joint, "warning - axis requested for ball joint: " + joint.ObjectNameInScene);
2113 break;
2114 case PhysicsJointType.Hinge:
2115 d.JointGetHingeAxis(odeJoint.jointID, out axis);
2116 break;
2117 }
2118 }
2119 return new Vector3(axis.X, axis.Y, axis.Z);
2120 }
2121
2122
2123 public void remActivePrim(OdePrim deactivatePrim)
2124 {
2125 lock (_activeprims)
2126 {
2127 _activeprims.Remove(deactivatePrim);
2128 }
2129 }
2130
2131 public override void RemovePrim(PhysicsActor prim)
2132 {
2133 if (prim is OdePrim)
2134 {
2135 lock (OdeLock)
2136 {
2137 OdePrim p = (OdePrim) prim;
2138
2139 p.setPrimForRemoval();
2140 AddPhysicsActorTaint(prim);
2141 //RemovePrimThreadLocked(p);
2142 }
2143 }
2144 }
2145
2146 /// <summary>
2147 /// This is called from within simulate but outside the locked portion
2148 /// We need to do our own locking here
2149 /// Essentially, we need to remove the prim from our space segment, whatever segment it's in.
2150 ///
2151 /// If there are no more prim in the segment, we need to empty (spacedestroy)the segment and reclaim memory
2152 /// that the space was using.
2153 /// </summary>
2154 /// <param name="prim"></param>
2155 public void RemovePrimThreadLocked(OdePrim prim)
2156 {
2157//Console.WriteLine("RemovePrimThreadLocked " + prim.m_primName);
2158 lock (prim)
2159 {
2160 remCollisionEventReporting(prim);
2161 lock (ode)
2162 {
2163 if (prim.prim_geom != IntPtr.Zero)
2164 {
2165 prim.ResetTaints();
2166
2167 if (prim.IsPhysical)
2168 {
2169 prim.disableBody();
2170 if (prim.childPrim)
2171 {
2172 prim.childPrim = false;
2173 prim.Body = IntPtr.Zero;
2174 prim.m_disabled = true;
2175 prim.IsPhysical = false;
2176 }
2177
2178
2179 }
2180 // we don't want to remove the main space
2181
2182 // If the geometry is in the targetspace, remove it from the target space
2183 //m_log.Warn(prim.m_targetSpace);
2184
2185 //if (prim.m_targetSpace != IntPtr.Zero)
2186 //{
2187 //if (d.SpaceQuery(prim.m_targetSpace, prim.prim_geom))
2188 //{
2189
2190 //if (d.GeomIsSpace(prim.m_targetSpace))
2191 //{
2192 //waitForSpaceUnlock(prim.m_targetSpace);
2193 //d.SpaceRemove(prim.m_targetSpace, prim.prim_geom);
2194 prim.m_targetSpace = IntPtr.Zero;
2195 //}
2196 //else
2197 //{
2198 // m_log.Info("[Physics]: Invalid Scene passed to 'removeprim from scene':" +
2199 //((OdePrim)prim).m_targetSpace.ToString());
2200 //}
2201
2202 //}
2203 //}
2204 //m_log.Warn(prim.prim_geom);
2205 try
2206 {
2207 if (prim.prim_geom != IntPtr.Zero)
2208 {
2209 d.GeomDestroy(prim.prim_geom);
2210 prim.prim_geom = IntPtr.Zero;
2211 }
2212 else
2213 {
2214 m_log.Warn("[PHYSICS]: Unable to remove prim from physics scene");
2215 }
2216 }
2217 catch (AccessViolationException)
2218 {
2219 m_log.Info("[PHYSICS]: Couldn't remove prim from physics scene, it was already be removed.");
2220 }
2221 lock (_prims)
2222 _prims.Remove(prim);
2223
2224 //If there are no more geometries in the sub-space, we don't need it in the main space anymore
2225 //if (d.SpaceGetNumGeoms(prim.m_targetSpace) == 0)
2226 //{
2227 //if (prim.m_targetSpace != null)
2228 //{
2229 //if (d.GeomIsSpace(prim.m_targetSpace))
2230 //{
2231 //waitForSpaceUnlock(prim.m_targetSpace);
2232 //d.SpaceRemove(space, prim.m_targetSpace);
2233 // free up memory used by the space.
2234 //d.SpaceDestroy(prim.m_targetSpace);
2235 //int[] xyspace = calculateSpaceArrayItemFromPos(prim.Position);
2236 //resetSpaceArrayItemToZero(xyspace[0], xyspace[1]);
2237 //}
2238 //else
2239 //{
2240 //m_log.Info("[Physics]: Invalid Scene passed to 'removeprim from scene':" +
2241 //((OdePrim) prim).m_targetSpace.ToString());
2242 //}
2243 //}
2244 //}
2245
2246 if (SupportsNINJAJoints)
2247 {
2248 RemoveAllJointsConnectedToActorThreadLocked(prim);
2249 }
2250 }
2251 }
2252 }
2253 }
2254
2255 #endregion
2256
2257 #region Space Separation Calculation
2258
2259 /// <summary>
2260 /// Takes a space pointer and zeros out the array we're using to hold the spaces
2261 /// </summary>
2262 /// <param name="pSpace"></param>
2263 public void resetSpaceArrayItemToZero(IntPtr pSpace)
2264 {
2265 for (int x = 0; x < staticPrimspace.GetLength(0); x++)
2266 {
2267 for (int y = 0; y < staticPrimspace.GetLength(1); y++)
2268 {
2269 if (staticPrimspace[x, y] == pSpace)
2270 staticPrimspace[x, y] = IntPtr.Zero;
2271 }
2272 }
2273 }
2274
2275 public void resetSpaceArrayItemToZero(int arrayitemX, int arrayitemY)
2276 {
2277 staticPrimspace[arrayitemX, arrayitemY] = IntPtr.Zero;
2278 }
2279
2280 /// <summary>
2281 /// Called when a static prim moves. Allocates a space for the prim based on its position
2282 /// </summary>
2283 /// <param name="geom">the pointer to the geom that moved</param>
2284 /// <param name="pos">the position that the geom moved to</param>
2285 /// <param name="currentspace">a pointer to the space it was in before it was moved.</param>
2286 /// <returns>a pointer to the new space it's in</returns>
2287 public IntPtr recalculateSpaceForGeom(IntPtr geom, Vector3 pos, IntPtr currentspace)
2288 {
2289 // Called from setting the Position and Size of an ODEPrim so
2290 // it's already in locked space.
2291
2292 // we don't want to remove the main space
2293 // we don't need to test physical here because this function should
2294 // never be called if the prim is physical(active)
2295
2296 // All physical prim end up in the root space
2297 //Thread.Sleep(20);
2298 if (currentspace != space)
2299 {
2300 //m_log.Info("[SPACE]: C:" + currentspace.ToString() + " g:" + geom.ToString());
2301 //if (currentspace == IntPtr.Zero)
2302 //{
2303 //int adfadf = 0;
2304 //}
2305 if (d.SpaceQuery(currentspace, geom) && currentspace != IntPtr.Zero)
2306 {
2307 if (d.GeomIsSpace(currentspace))
2308 {
2309 waitForSpaceUnlock(currentspace);
2310 d.SpaceRemove(currentspace, geom);
2311 }
2312 else
2313 {
2314 m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + currentspace +
2315 " Geom:" + geom);
2316 }
2317 }
2318 else
2319 {
2320 IntPtr sGeomIsIn = d.GeomGetSpace(geom);
2321 if (sGeomIsIn != IntPtr.Zero)
2322 {
2323 if (d.GeomIsSpace(currentspace))
2324 {
2325 waitForSpaceUnlock(sGeomIsIn);
2326 d.SpaceRemove(sGeomIsIn, geom);
2327 }
2328 else
2329 {
2330 m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" +
2331 sGeomIsIn + " Geom:" + geom);
2332 }
2333 }
2334 }
2335
2336 //If there are no more geometries in the sub-space, we don't need it in the main space anymore
2337 if (d.SpaceGetNumGeoms(currentspace) == 0)
2338 {
2339 if (currentspace != IntPtr.Zero)
2340 {
2341 if (d.GeomIsSpace(currentspace))
2342 {
2343 waitForSpaceUnlock(currentspace);
2344 waitForSpaceUnlock(space);
2345 d.SpaceRemove(space, currentspace);
2346 // free up memory used by the space.
2347
2348 //d.SpaceDestroy(currentspace);
2349 resetSpaceArrayItemToZero(currentspace);
2350 }
2351 else
2352 {
2353 m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" +
2354 currentspace + " Geom:" + geom);
2355 }
2356 }
2357 }
2358 }
2359 else
2360 {
2361 // this is a physical object that got disabled. ;.;
2362 if (currentspace != IntPtr.Zero && geom != IntPtr.Zero)
2363 {
2364 if (d.SpaceQuery(currentspace, geom))
2365 {
2366 if (d.GeomIsSpace(currentspace))
2367 {
2368 waitForSpaceUnlock(currentspace);
2369 d.SpaceRemove(currentspace, geom);
2370 }
2371 else
2372 {
2373 m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" +
2374 currentspace + " Geom:" + geom);
2375 }
2376 }
2377 else
2378 {
2379 IntPtr sGeomIsIn = d.GeomGetSpace(geom);
2380 if (sGeomIsIn != IntPtr.Zero)
2381 {
2382 if (d.GeomIsSpace(sGeomIsIn))
2383 {
2384 waitForSpaceUnlock(sGeomIsIn);
2385 d.SpaceRemove(sGeomIsIn, geom);
2386 }
2387 else
2388 {
2389 m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" +
2390 sGeomIsIn + " Geom:" + geom);
2391 }
2392 }
2393 }
2394 }
2395 }
2396
2397 // The routines in the Position and Size sections do the 'inserting' into the space,
2398 // so all we have to do is make sure that the space that we're putting the prim into
2399 // is in the 'main' space.
2400 int[] iprimspaceArrItem = calculateSpaceArrayItemFromPos(pos);
2401 IntPtr newspace = calculateSpaceForGeom(pos);
2402
2403 if (newspace == IntPtr.Zero)
2404 {
2405 newspace = createprimspace(iprimspaceArrItem[0], iprimspaceArrItem[1]);
2406 d.HashSpaceSetLevels(newspace, smallHashspaceLow, smallHashspaceHigh);
2407 }
2408
2409 return newspace;
2410 }
2411
2412 /// <summary>
2413 /// Creates a new space at X Y
2414 /// </summary>
2415 /// <param name="iprimspaceArrItemX"></param>
2416 /// <param name="iprimspaceArrItemY"></param>
2417 /// <returns>A pointer to the created space</returns>
2418 public IntPtr createprimspace(int iprimspaceArrItemX, int iprimspaceArrItemY)
2419 {
2420 // creating a new space for prim and inserting it into main space.
2421 staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY] = d.HashSpaceCreate(IntPtr.Zero);
2422 d.GeomSetCategoryBits(staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY], (int)CollisionCategories.Space);
2423 waitForSpaceUnlock(space);
2424 d.SpaceSetSublevel(space, 1);
2425 d.SpaceAdd(space, staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY]);
2426 return staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY];
2427 }
2428
2429 /// <summary>
2430 /// Calculates the space the prim should be in by its position
2431 /// </summary>
2432 /// <param name="pos"></param>
2433 /// <returns>a pointer to the space. This could be a new space or reused space.</returns>
2434 public IntPtr calculateSpaceForGeom(Vector3 pos)
2435 {
2436 int[] xyspace = calculateSpaceArrayItemFromPos(pos);
2437 //m_log.Info("[Physics]: Attempting to use arrayItem: " + xyspace[0].ToString() + "," + xyspace[1].ToString());
2438 return staticPrimspace[xyspace[0], xyspace[1]];
2439 }
2440
2441 /// <summary>
2442 /// Holds the space allocation logic
2443 /// </summary>
2444 /// <param name="pos"></param>
2445 /// <returns>an array item based on the position</returns>
2446 public int[] calculateSpaceArrayItemFromPos(Vector3 pos)
2447 {
2448 int[] returnint = new int[2];
2449
2450 returnint[0] = (int) (pos.X/metersInSpace);
2451
2452 if (returnint[0] > ((int) (259f/metersInSpace)))
2453 returnint[0] = ((int) (259f/metersInSpace));
2454 if (returnint[0] < 0)
2455 returnint[0] = 0;
2456
2457 returnint[1] = (int) (pos.Y/metersInSpace);
2458 if (returnint[1] > ((int) (259f/metersInSpace)))
2459 returnint[1] = ((int) (259f/metersInSpace));
2460 if (returnint[1] < 0)
2461 returnint[1] = 0;
2462
2463 return returnint;
2464 }
2465
2466 #endregion
2467
2468 /// <summary>
2469 /// Routine to figure out if we need to mesh this prim with our mesher
2470 /// </summary>
2471 /// <param name="pbs"></param>
2472 /// <returns></returns>
2473 public bool needsMeshing(PrimitiveBaseShape pbs)
2474 {
2475 // most of this is redundant now as the mesher will return null if it cant mesh a prim
2476 // but we still need to check for sculptie meshing being enabled so this is the most
2477 // convenient place to do it for now...
2478
2479 // //if (pbs.PathCurve == (byte)Primitive.PathCurve.Circle && pbs.ProfileCurve == (byte)Primitive.ProfileCurve.Circle && pbs.PathScaleY <= 0.75f)
2480 // //m_log.Debug("needsMeshing: " + " pathCurve: " + pbs.PathCurve.ToString() + " profileCurve: " + pbs.ProfileCurve.ToString() + " pathScaleY: " + Primitive.UnpackPathScale(pbs.PathScaleY).ToString());
2481 int iPropertiesNotSupportedDefault = 0;
2482
2483 if (pbs.SculptEntry && !meshSculptedPrim)
2484 {
2485#if SPAM
2486 m_log.Warn("NonMesh");
2487#endif
2488 return false;
2489 }
2490
2491 // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since ODE can use an internal representation for the prim
2492 if (!forceSimplePrimMeshing)
2493 {
2494 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
2495 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
2496 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
2497 {
2498
2499 if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
2500 && pbs.ProfileHollow == 0
2501 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
2502 && pbs.PathBegin == 0 && pbs.PathEnd == 0
2503 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
2504 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
2505 && pbs.PathShearX == 0 && pbs.PathShearY == 0)
2506 {
2507#if SPAM
2508 m_log.Warn("NonMesh");
2509#endif
2510 return false;
2511 }
2512 }
2513 }
2514
2515 if (pbs.ProfileHollow != 0)
2516 iPropertiesNotSupportedDefault++;
2517
2518 if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
2519 iPropertiesNotSupportedDefault++;
2520
2521 if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
2522 iPropertiesNotSupportedDefault++;
2523
2524 if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
2525 iPropertiesNotSupportedDefault++;
2526
2527 if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
2528 iPropertiesNotSupportedDefault++;
2529
2530 if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
2531 iPropertiesNotSupportedDefault++;
2532
2533 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 && (pbs.Scale.X != pbs.Scale.Y || pbs.Scale.Y != pbs.Scale.Z || pbs.Scale.Z != pbs.Scale.X))
2534 iPropertiesNotSupportedDefault++;
2535
2536 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte) Extrusion.Curve1)
2537 iPropertiesNotSupportedDefault++;
2538
2539 // test for torus
2540 if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
2541 {
2542 if (pbs.PathCurve == (byte)Extrusion.Curve1)
2543 {
2544 iPropertiesNotSupportedDefault++;
2545 }
2546 }
2547 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
2548 {
2549 if (pbs.PathCurve == (byte)Extrusion.Straight)
2550 {
2551 iPropertiesNotSupportedDefault++;
2552 }
2553
2554 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
2555 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
2556 {
2557 iPropertiesNotSupportedDefault++;
2558 }
2559 }
2560 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
2561 {
2562 if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
2563 {
2564 iPropertiesNotSupportedDefault++;
2565 }
2566 }
2567 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
2568 {
2569 if (pbs.PathCurve == (byte)Extrusion.Straight)
2570 {
2571 iPropertiesNotSupportedDefault++;
2572 }
2573 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
2574 {
2575 iPropertiesNotSupportedDefault++;
2576 }
2577 }
2578
2579
2580 if (iPropertiesNotSupportedDefault == 0)
2581 {
2582#if SPAM
2583 m_log.Warn("NonMesh");
2584#endif
2585 return false;
2586 }
2587#if SPAM
2588 m_log.Debug("Mesh");
2589#endif
2590 return true;
2591 }
2592
2593 /// <summary>
2594 /// Called after our prim properties are set Scale, position etc.
2595 /// We use this event queue like method to keep changes to the physical scene occuring in the threadlocked mutex
2596 /// This assures us that we have no race conditions
2597 /// </summary>
2598 /// <param name="prim"></param>
2599 public override void AddPhysicsActorTaint(PhysicsActor prim)
2600 {
2601
2602 if (prim is OdePrim)
2603 {
2604 OdePrim taintedprim = ((OdePrim) prim);
2605 lock (_taintedPrimLock)
2606 {
2607 if (!(_taintedPrimH.Contains(taintedprim)))
2608 {
2609//Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.m_primName);
2610 _taintedPrimH.Add(taintedprim); // HashSet for searching
2611 _taintedPrimL.Add(taintedprim); // List for ordered readout
2612 }
2613 }
2614 return;
2615 }
2616 else if (prim is OdeCharacter)
2617 {
2618 OdeCharacter taintedchar = ((OdeCharacter)prim);
2619 lock (_taintedActors)
2620 {
2621 if (!(_taintedActors.Contains(taintedchar)))
2622 {
2623 _taintedActors.Add(taintedchar);
2624 if (taintedchar.bad)
2625 m_log.DebugFormat("[PHYSICS]: Added BAD actor {0} to tainted actors", taintedchar.m_uuid);
2626 }
2627 }
2628 }
2629 }
2630
2631 /// <summary>
2632 /// This is our main simulate loop
2633 /// It's thread locked by a Mutex in the scene.
2634 /// It holds Collisions, it instructs ODE to step through the physical reactions
2635 /// It moves the objects around in memory
2636 /// It calls the methods that report back to the object owners.. (scenepresence, SceneObjectGroup)
2637 /// </summary>
2638 /// <param name="timeStep"></param>
2639 /// <returns></returns>
2640 public override float Simulate(float timeStep)
2641 {
2642 if (framecount >= int.MaxValue)
2643 framecount = 0;
2644 //if (m_worldOffset != Vector3.Zero)
2645 // return 0;
2646
2647 framecount++;
2648
2649 DateTime now = DateTime.UtcNow;
2650 TimeSpan SinceLastFrame = now - m_lastframe;
2651 m_lastframe = now;
2652 float realtime = (float)SinceLastFrame.TotalSeconds;
2653// Console.WriteLine("ts={0} rt={1}", timeStep, realtime);
2654 timeStep = realtime;
2655
2656 // float fps = 1.0f / realtime;
2657 float fps = 0.0f; // number of ODE steps in this Simulate step
2658 //m_log.Info(timeStep.ToString());
2659 step_time += timeStep;
2660
2661 // If We're loaded down by something else,
2662 // or debugging with the Visual Studio project on pause
2663 // skip a few frames to catch up gracefully.
2664 // without shooting the physicsactors all over the place
2665
2666 if (step_time >= m_SkipFramesAtms)
2667 {
2668 // Instead of trying to catch up, it'll do 5 physics frames only
2669 step_time = ODE_STEPSIZE;
2670 m_physicsiterations = 5;
2671 }
2672 else
2673 {
2674 m_physicsiterations = 10;
2675 }
2676
2677 if (SupportsNINJAJoints)
2678 {
2679 DeleteRequestedJoints(); // this must be outside of the lock (OdeLock) to avoid deadlocks
2680 CreateRequestedJoints(); // this must be outside of the lock (OdeLock) to avoid deadlocks
2681 }
2682
2683 lock (OdeLock)
2684 {
2685 // Process 10 frames if the sim is running normal..
2686 // process 5 frames if the sim is running slow
2687 //try
2688 //{
2689 //d.WorldSetQuickStepNumIterations(world, m_physicsiterations);
2690 //}
2691 //catch (StackOverflowException)
2692 //{
2693 // m_log.Error("[PHYSICS]: The operating system wasn't able to allocate enough memory for the simulation. Restarting the sim.");
2694 // ode.drelease(world);
2695 //base.TriggerPhysicsBasedRestart();
2696 //}
2697
2698 int i = 0;
2699
2700 // Figure out the Frames Per Second we're going at.
2701 //(step_time == 0.004f, there's 250 of those per second. Times the step time/step size
2702
2703 // fps = (step_time / ODE_STEPSIZE) * 1000;
2704 // HACK: Using a time dilation of 1.0 to debug rubberbanding issues
2705 //m_timeDilation = Math.Min((step_time / ODE_STEPSIZE) / (0.09375f / ODE_STEPSIZE), 1.0f);
2706
2707 // step_time = 0.09375f;
2708
2709 while (step_time > 0.0f)
2710 {
2711 //lock (ode)
2712 //{
2713 //if (!ode.lockquery())
2714 //{
2715 // ode.dlock(world);
2716 try
2717 {
2718 // Insert, remove Characters
2719 bool processedtaints = false;
2720
2721 lock (_taintedActors)
2722 {
2723 if (_taintedActors.Count > 0)
2724 {
2725 foreach (OdeCharacter character in _taintedActors)
2726 {
2727
2728 character.ProcessTaints(ODE_STEPSIZE);
2729
2730 processedtaints = true;
2731 //character.m_collisionscore = 0;
2732 }
2733
2734 if (processedtaints)
2735 _taintedActors.Clear();
2736 }
2737 } // end lock _taintedActors
2738
2739 // Modify other objects in the scene.
2740 processedtaints = false;
2741
2742 lock (_taintedPrimLock)
2743 {
2744 foreach (OdePrim prim in _taintedPrimL)
2745 {
2746 if (prim.m_taintremove)
2747 {
2748 //Console.WriteLine("Simulate calls RemovePrimThreadLocked");
2749 RemovePrimThreadLocked(prim);
2750 }
2751 else
2752 {
2753 //Console.WriteLine("Simulate calls ProcessTaints");
2754 prim.ProcessTaints(ODE_STEPSIZE);
2755 }
2756 processedtaints = true;
2757 prim.m_collisionscore = 0;
2758
2759 // This loop can block up the Heartbeat for a very long time on large regions.
2760 // We need to let the Watchdog know that the Heartbeat is not dead
2761 // NOTE: This is currently commented out, but if things like OAR loading are
2762 // timing the heartbeat out we will need to uncomment it
2763 //Watchdog.UpdateThread();
2764 }
2765
2766 if (SupportsNINJAJoints)
2767 {
2768 // Create pending joints, if possible
2769
2770 // joints can only be processed after ALL bodies are processed (and exist in ODE), since creating
2771 // a joint requires specifying the body id of both involved bodies
2772 if (pendingJoints.Count > 0)
2773 {
2774 List<PhysicsJoint> successfullyProcessedPendingJoints = new List<PhysicsJoint>();
2775 //DoJointErrorMessage(joints_connecting_actor, "taint: " + pendingJoints.Count + " pending joints");
2776 foreach (PhysicsJoint joint in pendingJoints)
2777 {
2778 //DoJointErrorMessage(joint, "taint: time to create joint with parms: " + joint.RawParams);
2779 string[] jointParams = joint.RawParams.Split(" ".ToCharArray(),
2780 System.StringSplitOptions.RemoveEmptyEntries);
2781 List<IntPtr> jointBodies = new List<IntPtr>();
2782 bool allJointBodiesAreReady = true;
2783 foreach (string jointParam in jointParams)
2784 {
2785 if (jointParam == "NULL")
2786 {
2787 //DoJointErrorMessage(joint, "attaching NULL joint to world");
2788 jointBodies.Add(IntPtr.Zero);
2789 }
2790 else
2791 {
2792 //DoJointErrorMessage(joint, "looking for prim name: " + jointParam);
2793 bool foundPrim = false;
2794 lock (_prims)
2795 {
2796 foreach (OdePrim prim in _prims) // FIXME: inefficient
2797 {
2798 if (prim.SOPName == jointParam)
2799 {
2800 //DoJointErrorMessage(joint, "found for prim name: " + jointParam);
2801 if (prim.IsPhysical && prim.Body != IntPtr.Zero)
2802 {
2803 jointBodies.Add(prim.Body);
2804 foundPrim = true;
2805 break;
2806 }
2807 else
2808 {
2809 DoJointErrorMessage(joint, "prim name " + jointParam +
2810 " exists but is not (yet) physical; deferring joint creation. " +
2811 "IsPhysical property is " + prim.IsPhysical +
2812 " and body is " + prim.Body);
2813 foundPrim = false;
2814 break;
2815 }
2816 }
2817 }
2818 }
2819 if (foundPrim)
2820 {
2821 // all is fine
2822 }
2823 else
2824 {
2825 allJointBodiesAreReady = false;
2826 break;
2827 }
2828 }
2829 }
2830 if (allJointBodiesAreReady)
2831 {
2832 //DoJointErrorMessage(joint, "allJointBodiesAreReady for " + joint.ObjectNameInScene + " with parms " + joint.RawParams);
2833 if (jointBodies[0] == jointBodies[1])
2834 {
2835 DoJointErrorMessage(joint, "ERROR: joint cannot be created; the joint bodies are the same, body1==body2. Raw body is " + jointBodies[0] + ". raw parms: " + joint.RawParams);
2836 }
2837 else
2838 {
2839 switch (joint.Type)
2840 {
2841 case PhysicsJointType.Ball:
2842 {
2843 IntPtr odeJoint;
2844 //DoJointErrorMessage(joint, "ODE creating ball joint ");
2845 odeJoint = d.JointCreateBall(world, IntPtr.Zero);
2846 //DoJointErrorMessage(joint, "ODE attaching ball joint: " + odeJoint + " with b1:" + jointBodies[0] + " b2:" + jointBodies[1]);
2847 d.JointAttach(odeJoint, jointBodies[0], jointBodies[1]);
2848 //DoJointErrorMessage(joint, "ODE setting ball anchor: " + odeJoint + " to vec:" + joint.Position);
2849 d.JointSetBallAnchor(odeJoint,
2850 joint.Position.X,
2851 joint.Position.Y,
2852 joint.Position.Z);
2853 //DoJointErrorMessage(joint, "ODE joint setting OK");
2854 //DoJointErrorMessage(joint, "The ball joint's bodies are here: b0: ");
2855 //DoJointErrorMessage(joint, "" + (jointBodies[0] != IntPtr.Zero ? "" + d.BodyGetPosition(jointBodies[0]) : "fixed environment"));
2856 //DoJointErrorMessage(joint, "The ball joint's bodies are here: b1: ");
2857 //DoJointErrorMessage(joint, "" + (jointBodies[1] != IntPtr.Zero ? "" + d.BodyGetPosition(jointBodies[1]) : "fixed environment"));
2858
2859 if (joint is OdePhysicsJoint)
2860 {
2861 ((OdePhysicsJoint)joint).jointID = odeJoint;
2862 }
2863 else
2864 {
2865 DoJointErrorMessage(joint, "WARNING: non-ode joint in ODE!");
2866 }
2867 }
2868 break;
2869 case PhysicsJointType.Hinge:
2870 {
2871 IntPtr odeJoint;
2872 //DoJointErrorMessage(joint, "ODE creating hinge joint ");
2873 odeJoint = d.JointCreateHinge(world, IntPtr.Zero);
2874 //DoJointErrorMessage(joint, "ODE attaching hinge joint: " + odeJoint + " with b1:" + jointBodies[0] + " b2:" + jointBodies[1]);
2875 d.JointAttach(odeJoint, jointBodies[0], jointBodies[1]);
2876 //DoJointErrorMessage(joint, "ODE setting hinge anchor: " + odeJoint + " to vec:" + joint.Position);
2877 d.JointSetHingeAnchor(odeJoint,
2878 joint.Position.X,
2879 joint.Position.Y,
2880 joint.Position.Z);
2881 // We use the orientation of the x-axis of the joint's coordinate frame
2882 // as the axis for the hinge.
2883
2884 // Therefore, we must get the joint's coordinate frame based on the
2885 // joint.Rotation field, which originates from the orientation of the
2886 // joint's proxy object in the scene.
2887
2888 // The joint's coordinate frame is defined as the transformation matrix
2889 // that converts a vector from joint-local coordinates into world coordinates.
2890 // World coordinates are defined as the XYZ coordinate system of the sim,
2891 // as shown in the top status-bar of the viewer.
2892
2893 // Once we have the joint's coordinate frame, we extract its X axis (AtAxis)
2894 // and use that as the hinge axis.
2895
2896 //joint.Rotation.Normalize();
2897 Matrix4 proxyFrame = Matrix4.CreateFromQuaternion(joint.Rotation);
2898
2899 // Now extract the X axis of the joint's coordinate frame.
2900
2901 // Do not try to use proxyFrame.AtAxis or you will become mired in the
2902 // tar pit of transposed, inverted, and generally messed-up orientations.
2903 // (In other words, Matrix4.AtAxis() is borked.)
2904 // Vector3 jointAxis = proxyFrame.AtAxis; <--- this path leadeth to madness
2905
2906 // Instead, compute the X axis of the coordinate frame by transforming
2907 // the (1,0,0) vector. At least that works.
2908
2909 //m_log.Debug("PHY: making axis: complete matrix is " + proxyFrame);
2910 Vector3 jointAxis = Vector3.Transform(Vector3.UnitX, proxyFrame);
2911 //m_log.Debug("PHY: making axis: hinge joint axis is " + jointAxis);
2912 //DoJointErrorMessage(joint, "ODE setting hinge axis: " + odeJoint + " to vec:" + jointAxis);
2913 d.JointSetHingeAxis(odeJoint,
2914 jointAxis.X,
2915 jointAxis.Y,
2916 jointAxis.Z);
2917 //d.JointSetHingeParam(odeJoint, (int)dParam.CFM, 0.1f);
2918 if (joint is OdePhysicsJoint)
2919 {
2920 ((OdePhysicsJoint)joint).jointID = odeJoint;
2921 }
2922 else
2923 {
2924 DoJointErrorMessage(joint, "WARNING: non-ode joint in ODE!");
2925 }
2926 }
2927 break;
2928 }
2929 successfullyProcessedPendingJoints.Add(joint);
2930 }
2931 }
2932 else
2933 {
2934 DoJointErrorMessage(joint, "joint could not yet be created; still pending");
2935 }
2936 }
2937 foreach (PhysicsJoint successfullyProcessedJoint in successfullyProcessedPendingJoints)
2938 {
2939 //DoJointErrorMessage(successfullyProcessedJoint, "finalizing succesfully procsssed joint " + successfullyProcessedJoint.ObjectNameInScene + " parms " + successfullyProcessedJoint.RawParams);
2940 //DoJointErrorMessage(successfullyProcessedJoint, "removing from pending");
2941 InternalRemovePendingJoint(successfullyProcessedJoint);
2942 //DoJointErrorMessage(successfullyProcessedJoint, "adding to active");
2943 InternalAddActiveJoint(successfullyProcessedJoint);
2944 //DoJointErrorMessage(successfullyProcessedJoint, "done");
2945 }
2946 }
2947 } // end SupportsNINJAJoints
2948
2949 if (processedtaints)
2950//Console.WriteLine("Simulate calls Clear of _taintedPrim list");
2951 _taintedPrimH.Clear(); // ??? if this only ???
2952 _taintedPrimL.Clear();
2953 } // end lock _taintedPrimLock
2954
2955 // Move characters
2956 lock (_characters)
2957 {
2958 List<OdeCharacter> defects = new List<OdeCharacter>();
2959 foreach (OdeCharacter actor in _characters)
2960 {
2961 if (actor != null)
2962 actor.Move(ODE_STEPSIZE, defects);
2963 }
2964 if (0 != defects.Count)
2965 {
2966 foreach (OdeCharacter defect in defects)
2967 {
2968 RemoveCharacter(defect);
2969 }
2970 }
2971 } // end lock _characters
2972
2973 // Move other active objects
2974 lock (_activeprims)
2975 {
2976 foreach (OdePrim prim in _activeprims)
2977 {
2978 prim.m_collisionscore = 0;
2979 prim.Move(ODE_STEPSIZE);
2980 }
2981 } // end lock _activeprims
2982
2983 //if ((framecount % m_randomizeWater) == 0)
2984 // randomizeWater(waterlevel);
2985
2986 //int RayCastTimeMS = m_rayCastManager.ProcessQueuedRequests();
2987 m_rayCastManager.ProcessQueuedRequests();
2988
2989 collision_optimized(ODE_STEPSIZE);
2990
2991 lock (_collisionEventPrim)
2992 {
2993 foreach (PhysicsActor obj in _collisionEventPrim)
2994 {
2995 if (obj == null)
2996 continue;
2997
2998 switch ((ActorTypes)obj.PhysicsActorType)
2999 {
3000 case ActorTypes.Agent:
3001 OdeCharacter cobj = (OdeCharacter)obj;
3002 cobj.AddCollisionFrameTime(100);
3003 cobj.SendCollisions();
3004 break;
3005 case ActorTypes.Prim:
3006 OdePrim pobj = (OdePrim)obj;
3007 pobj.SendCollisions();
3008 break;
3009 }
3010 }
3011 } // end lock _collisionEventPrim
3012
3013 //if (m_global_contactcount > 5)
3014 //{
3015 // m_log.DebugFormat("[PHYSICS]: Contacts:{0}", m_global_contactcount);
3016 //}
3017
3018 m_global_contactcount = 0;
3019
3020 d.WorldQuickStep(world, ODE_STEPSIZE);
3021 d.JointGroupEmpty(contactgroup);
3022 fps++;
3023 //ode.dunlock(world);
3024 } // end try
3025 catch (Exception e)
3026 {
3027 m_log.ErrorFormat("[PHYSICS]: {0}, {1}, {2}", e.Message, e.TargetSite, e);
3028 ode.dunlock(world);
3029 }
3030
3031 step_time -= ODE_STEPSIZE;
3032 i++;
3033 //}
3034 //else
3035 //{
3036 //fps = 0;
3037 //}
3038 //}
3039 } // end while (step_time > 0.0f)
3040
3041 lock (_characters)
3042 {
3043 foreach (OdeCharacter actor in _characters)
3044 {
3045 if (actor != null)
3046 {
3047 if (actor.bad)
3048 m_log.WarnFormat("[PHYSICS]: BAD Actor {0} in _characters list was not removed?", actor.m_uuid);
3049 actor.UpdatePositionAndVelocity();
3050 }
3051 }
3052 }
3053
3054 lock (_badCharacter)
3055 {
3056 if (_badCharacter.Count > 0)
3057 {
3058 foreach (OdeCharacter chr in _badCharacter)
3059 {
3060 RemoveCharacter(chr);
3061 }
3062 _badCharacter.Clear();
3063 }
3064 }
3065
3066 lock (_activeprims)
3067 {
3068 //if (timeStep < 0.2f)
3069 {
3070 foreach (OdePrim actor in _activeprims)
3071 {
3072 if (actor.IsPhysical && (d.BodyIsEnabled(actor.Body) || !actor._zeroFlag))
3073 {
3074 actor.UpdatePositionAndVelocity();
3075
3076 if (SupportsNINJAJoints)
3077 {
3078 // If an actor moved, move its joint proxy objects as well.
3079 // There seems to be an event PhysicsActor.OnPositionUpdate that could be used
3080 // for this purpose but it is never called! So we just do the joint
3081 // movement code here.
3082
3083 if (actor.SOPName != null &&
3084 joints_connecting_actor.ContainsKey(actor.SOPName) &&
3085 joints_connecting_actor[actor.SOPName] != null &&
3086 joints_connecting_actor[actor.SOPName].Count > 0)
3087 {
3088 foreach (PhysicsJoint affectedJoint in joints_connecting_actor[actor.SOPName])
3089 {
3090 if (affectedJoint.IsInPhysicsEngine)
3091 {
3092 DoJointMoved(affectedJoint);
3093 }
3094 else
3095 {
3096 DoJointErrorMessage(affectedJoint, "a body connected to a joint was moved, but the joint doesn't exist yet! this will lead to joint error. joint was: " + affectedJoint.ObjectNameInScene + " parms:" + affectedJoint.RawParams);
3097 }
3098 }
3099 }
3100 }
3101 }
3102 }
3103 }
3104 } // end lock _activeprims
3105
3106 //DumpJointInfo();
3107
3108 // Finished with all sim stepping. If requested, dump world state to file for debugging.
3109 // TODO: This call to the export function is already inside lock (OdeLock) - but is an extra lock needed?
3110 // TODO: This overwrites all dump files in-place. Should this be a growing logfile, or separate snapshots?
3111 if (physics_logging && (physics_logging_interval>0) && (framecount % physics_logging_interval == 0))
3112 {
3113 string fname = "state-" + world.ToString() + ".DIF"; // give each physics world a separate filename
3114 string prefix = "world" + world.ToString(); // prefix for variable names in exported .DIF file
3115
3116 if (physics_logging_append_existing_logfile)
3117 {
3118 string header = "-------------- START OF PHYSICS FRAME " + framecount.ToString() + " --------------";
3119 TextWriter fwriter = File.AppendText(fname);
3120 fwriter.WriteLine(header);
3121 fwriter.Close();
3122 }
3123 d.WorldExportDIF(world, fname, physics_logging_append_existing_logfile, prefix);
3124 }
3125 } // end lock OdeLock
3126
3127 return fps * 1000.0f; //NB This is a FRAME COUNT, not a time! AND is divide by 1000 in SimStatusReporter!
3128 } // end Simulate
3129
3130 public override void GetResults()
3131 {
3132 }
3133
3134 public override bool IsThreaded
3135 {
3136 // for now we won't be multithreaded
3137 get { return (false); }
3138 }
3139
3140 #region ODE Specific Terrain Fixes
3141 public float[] ResizeTerrain512NearestNeighbour(float[] heightMap)
3142 {
3143 float[] returnarr = new float[262144];
3144 float[,] resultarr = new float[(int)WorldExtents.X, (int)WorldExtents.Y];
3145
3146 // Filling out the array into its multi-dimensional components
3147 for (int y = 0; y < WorldExtents.Y; y++)
3148 {
3149 for (int x = 0; x < WorldExtents.X; x++)
3150 {
3151 resultarr[y, x] = heightMap[y * (int)WorldExtents.Y + x];
3152 }
3153 }
3154
3155 // Resize using Nearest Neighbour
3156
3157 // This particular way is quick but it only works on a multiple of the original
3158
3159 // The idea behind this method can be described with the following diagrams
3160 // second pass and third pass happen in the same loop really.. just separated
3161 // them to show what this does.
3162
3163 // First Pass
3164 // ResultArr:
3165 // 1,1,1,1,1,1
3166 // 1,1,1,1,1,1
3167 // 1,1,1,1,1,1
3168 // 1,1,1,1,1,1
3169 // 1,1,1,1,1,1
3170 // 1,1,1,1,1,1
3171
3172 // Second Pass
3173 // ResultArr2:
3174 // 1,,1,,1,,1,,1,,1,
3175 // ,,,,,,,,,,
3176 // 1,,1,,1,,1,,1,,1,
3177 // ,,,,,,,,,,
3178 // 1,,1,,1,,1,,1,,1,
3179 // ,,,,,,,,,,
3180 // 1,,1,,1,,1,,1,,1,
3181 // ,,,,,,,,,,
3182 // 1,,1,,1,,1,,1,,1,
3183 // ,,,,,,,,,,
3184 // 1,,1,,1,,1,,1,,1,
3185
3186 // Third pass fills in the blanks
3187 // ResultArr2:
3188 // 1,1,1,1,1,1,1,1,1,1,1,1
3189 // 1,1,1,1,1,1,1,1,1,1,1,1
3190 // 1,1,1,1,1,1,1,1,1,1,1,1
3191 // 1,1,1,1,1,1,1,1,1,1,1,1
3192 // 1,1,1,1,1,1,1,1,1,1,1,1
3193 // 1,1,1,1,1,1,1,1,1,1,1,1
3194 // 1,1,1,1,1,1,1,1,1,1,1,1
3195 // 1,1,1,1,1,1,1,1,1,1,1,1
3196 // 1,1,1,1,1,1,1,1,1,1,1,1
3197 // 1,1,1,1,1,1,1,1,1,1,1,1
3198 // 1,1,1,1,1,1,1,1,1,1,1,1
3199
3200 // X,Y = .
3201 // X+1,y = ^
3202 // X,Y+1 = *
3203 // X+1,Y+1 = #
3204
3205 // Filling in like this;
3206 // .*
3207 // ^#
3208 // 1st .
3209 // 2nd *
3210 // 3rd ^
3211 // 4th #
3212 // on single loop.
3213
3214 float[,] resultarr2 = new float[512, 512];
3215 for (int y = 0; y < WorldExtents.Y; y++)
3216 {
3217 for (int x = 0; x < WorldExtents.X; x++)
3218 {
3219 resultarr2[y * 2, x * 2] = resultarr[y, x];
3220
3221 if (y < WorldExtents.Y)
3222 {
3223 resultarr2[(y * 2) + 1, x * 2] = resultarr[y, x];
3224 }
3225 if (x < WorldExtents.X)
3226 {
3227 resultarr2[y * 2, (x * 2) + 1] = resultarr[y, x];
3228 }
3229 if (x < WorldExtents.X && y < WorldExtents.Y)
3230 {
3231 resultarr2[(y * 2) + 1, (x * 2) + 1] = resultarr[y, x];
3232 }
3233 }
3234 }
3235
3236 //Flatten out the array
3237 int i = 0;
3238 for (int y = 0; y < 512; y++)
3239 {
3240 for (int x = 0; x < 512; x++)
3241 {
3242 if (resultarr2[y, x] <= 0)
3243 returnarr[i] = 0.0000001f;
3244 else
3245 returnarr[i] = resultarr2[y, x];
3246
3247 i++;
3248 }
3249 }
3250
3251 return returnarr;
3252 }
3253
3254 public float[] ResizeTerrain512Interpolation(float[] heightMap)
3255 {
3256 float[] returnarr = new float[262144];
3257 float[,] resultarr = new float[512,512];
3258
3259 // Filling out the array into its multi-dimensional components
3260 for (int y = 0; y < 256; y++)
3261 {
3262 for (int x = 0; x < 256; x++)
3263 {
3264 resultarr[y, x] = heightMap[y * 256 + x];
3265 }
3266 }
3267
3268 // Resize using interpolation
3269
3270 // This particular way is quick but it only works on a multiple of the original
3271
3272 // The idea behind this method can be described with the following diagrams
3273 // second pass and third pass happen in the same loop really.. just separated
3274 // them to show what this does.
3275
3276 // First Pass
3277 // ResultArr:
3278 // 1,1,1,1,1,1
3279 // 1,1,1,1,1,1
3280 // 1,1,1,1,1,1
3281 // 1,1,1,1,1,1
3282 // 1,1,1,1,1,1
3283 // 1,1,1,1,1,1
3284
3285 // Second Pass
3286 // ResultArr2:
3287 // 1,,1,,1,,1,,1,,1,
3288 // ,,,,,,,,,,
3289 // 1,,1,,1,,1,,1,,1,
3290 // ,,,,,,,,,,
3291 // 1,,1,,1,,1,,1,,1,
3292 // ,,,,,,,,,,
3293 // 1,,1,,1,,1,,1,,1,
3294 // ,,,,,,,,,,
3295 // 1,,1,,1,,1,,1,,1,
3296 // ,,,,,,,,,,
3297 // 1,,1,,1,,1,,1,,1,
3298
3299 // Third pass fills in the blanks
3300 // ResultArr2:
3301 // 1,1,1,1,1,1,1,1,1,1,1,1
3302 // 1,1,1,1,1,1,1,1,1,1,1,1
3303 // 1,1,1,1,1,1,1,1,1,1,1,1
3304 // 1,1,1,1,1,1,1,1,1,1,1,1
3305 // 1,1,1,1,1,1,1,1,1,1,1,1
3306 // 1,1,1,1,1,1,1,1,1,1,1,1
3307 // 1,1,1,1,1,1,1,1,1,1,1,1
3308 // 1,1,1,1,1,1,1,1,1,1,1,1
3309 // 1,1,1,1,1,1,1,1,1,1,1,1
3310 // 1,1,1,1,1,1,1,1,1,1,1,1
3311 // 1,1,1,1,1,1,1,1,1,1,1,1
3312
3313 // X,Y = .
3314 // X+1,y = ^
3315 // X,Y+1 = *
3316 // X+1,Y+1 = #
3317
3318 // Filling in like this;
3319 // .*
3320 // ^#
3321 // 1st .
3322 // 2nd *
3323 // 3rd ^
3324 // 4th #
3325 // on single loop.
3326
3327 float[,] resultarr2 = new float[512,512];
3328 for (int y = 0; y < (int)Constants.RegionSize; y++)
3329 {
3330 for (int x = 0; x < (int)Constants.RegionSize; x++)
3331 {
3332 resultarr2[y*2, x*2] = resultarr[y, x];
3333
3334 if (y < (int)Constants.RegionSize)
3335 {
3336 if (y + 1 < (int)Constants.RegionSize)
3337 {
3338 if (x + 1 < (int)Constants.RegionSize)
3339 {
3340 resultarr2[(y*2) + 1, x*2] = ((resultarr[y, x] + resultarr[y + 1, x] +
3341 resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4);
3342 }
3343 else
3344 {
3345 resultarr2[(y*2) + 1, x*2] = ((resultarr[y, x] + resultarr[y + 1, x])/2);
3346 }
3347 }
3348 else
3349 {
3350 resultarr2[(y*2) + 1, x*2] = resultarr[y, x];
3351 }
3352 }
3353 if (x < (int)Constants.RegionSize)
3354 {
3355 if (x + 1 < (int)Constants.RegionSize)
3356 {
3357 if (y + 1 < (int)Constants.RegionSize)
3358 {
3359 resultarr2[y*2, (x*2) + 1] = ((resultarr[y, x] + resultarr[y + 1, x] +
3360 resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4);
3361 }
3362 else
3363 {
3364 resultarr2[y*2, (x*2) + 1] = ((resultarr[y, x] + resultarr[y, x + 1])/2);
3365 }
3366 }
3367 else
3368 {
3369 resultarr2[y*2, (x*2) + 1] = resultarr[y, x];
3370 }
3371 }
3372 if (x < (int)Constants.RegionSize && y < (int)Constants.RegionSize)
3373 {
3374 if ((x + 1 < (int)Constants.RegionSize) && (y + 1 < (int)Constants.RegionSize))
3375 {
3376 resultarr2[(y*2) + 1, (x*2) + 1] = ((resultarr[y, x] + resultarr[y + 1, x] +
3377 resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4);
3378 }
3379 else
3380 {
3381 resultarr2[(y*2) + 1, (x*2) + 1] = resultarr[y, x];
3382 }
3383 }
3384 }
3385 }
3386 //Flatten out the array
3387 int i = 0;
3388 for (int y = 0; y < 512; y++)
3389 {
3390 for (int x = 0; x < 512; x++)
3391 {
3392 if (Single.IsNaN(resultarr2[y, x]) || Single.IsInfinity(resultarr2[y, x]))
3393 {
3394 m_log.Warn("[PHYSICS]: Non finite heightfield element detected. Setting it to 0");
3395 resultarr2[y, x] = 0;
3396 }
3397 returnarr[i] = resultarr2[y, x];
3398 i++;
3399 }
3400 }
3401
3402 return returnarr;
3403 }
3404
3405 #endregion
3406
3407 public override void SetTerrain(float[] heightMap)
3408 {
3409 if (m_worldOffset != Vector3.Zero && m_parentScene != null)
3410 {
3411 if (m_parentScene is OdeScene)
3412 {
3413 ((OdeScene)m_parentScene).SetTerrain(heightMap, m_worldOffset);
3414 }
3415 }
3416 else
3417 {
3418 SetTerrain(heightMap, m_worldOffset);
3419 }
3420 }
3421
3422 public void SetTerrain(float[] heightMap, Vector3 pOffset)
3423 {
3424
3425 uint regionsize = (uint) Constants.RegionSize; // visible region size eg. 256(M)
3426
3427 uint heightmapWidth = regionsize + 1; // ODE map size 257 x 257 (Meters) (1 extra
3428 uint heightmapHeight = regionsize + 1;
3429
3430 uint heightmapWidthSamples = (uint)regionsize + 2; // Sample file size, 258 x 258 samples
3431 uint heightmapHeightSamples = (uint)regionsize + 2;
3432
3433 // Array of height samples for ODE
3434 float[] _heightmap;
3435 _heightmap = new float[(heightmapWidthSamples * heightmapHeightSamples)]; // loaded samples 258 x 258
3436
3437 // Other ODE parameters
3438 const float scale = 1.0f;
3439 const float offset = 0.0f;
3440 const float thickness = 2.0f; // Was 0.2f, Larger appears to prevent Av fall-through
3441 const int wrap = 0;
3442
3443 float hfmin = 2000f;
3444 float hfmax = -2000f;
3445 float minele = 0.0f; // Dont allow -ve heights
3446
3447 uint x = 0;
3448 uint y = 0;
3449 uint xx = 0;
3450 uint yy = 0;
3451
3452 // load the height samples array from the heightMap
3453 for ( x = 0; x < heightmapWidthSamples; x++) // 0 to 257
3454 {
3455 for ( y = 0; y < heightmapHeightSamples; y++) // 0 to 257
3456 {
3457 xx = x - 1;
3458 if (xx < 0) xx = 0;
3459 if (xx > (regionsize - 1)) xx = regionsize - 1;
3460
3461 yy = y - 1;
3462 if (yy < 0) yy = 0;
3463 if (yy > (regionsize - 1)) yy = regionsize - 1;
3464 // Input xx = 0 0 1 2 ..... 254 255 255 256 total in
3465 // Output x = 0 1 2 3 ..... 255 256 257 258 total out
3466 float val= heightMap[(yy * regionsize) + xx]; // input from heightMap, <0-255 * 256> <0-255>
3467 if (val < minele) val = minele;
3468 _heightmap[x * (regionsize + 2) + y] = val; // samples output to _heightmap, <0-257 * 258> <0-257>
3469 hfmin = (val < hfmin) ? val : hfmin;
3470 hfmax = (val > hfmax) ? val : hfmax;
3471 }
3472 }
3473
3474 lock (OdeLock)
3475 {
3476 IntPtr GroundGeom = IntPtr.Zero;
3477 if (RegionTerrain.TryGetValue(pOffset, out GroundGeom))
3478 {
3479 RegionTerrain.Remove(pOffset);
3480 if (GroundGeom != IntPtr.Zero)
3481 {
3482 if (TerrainHeightFieldHeights.ContainsKey(GroundGeom))
3483 {
3484 TerrainHeightFieldHeights.Remove(GroundGeom);
3485 }
3486 d.SpaceRemove(space, GroundGeom);
3487 d.GeomDestroy(GroundGeom);
3488 }
3489 }
3490 IntPtr HeightmapData = d.GeomHeightfieldDataCreate();
3491 d.GeomHeightfieldDataBuildSingle(HeightmapData, _heightmap, 0,
3492 heightmapWidth, heightmapHeight, (int)heightmapWidthSamples,
3493 (int)heightmapHeightSamples, scale, offset, thickness, wrap);
3494 d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1);
3495 GroundGeom = d.CreateHeightfield(space, HeightmapData, 1);
3496 if (GroundGeom != IntPtr.Zero)
3497 {
3498 d.GeomSetCategoryBits(GroundGeom, (int)(CollisionCategories.Land));
3499 d.GeomSetCollideBits(GroundGeom, (int)(CollisionCategories.Space));
3500 }
3501 geom_name_map[GroundGeom] = "Terrain";
3502
3503 d.Matrix3 R = new d.Matrix3();
3504
3505 Quaternion q1 = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 1.5707f);
3506 Quaternion q2 = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), 1.5707f);
3507 //Axiom.Math.Quaternion q3 = Axiom.Math.Quaternion.FromAngleAxis(3.14f, new Axiom.Math.Vector3(0, 0, 1));
3508
3509 q1 = q1 * q2;
3510 //q1 = q1 * q3;
3511 Vector3 v3;
3512 float angle;
3513 q1.GetAxisAngle(out v3, out angle);
3514
3515 d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle);
3516 d.GeomSetRotation(GroundGeom, ref R);
3517 d.GeomSetPosition(GroundGeom, (pOffset.X + (regionsize * 0.5f)) - 0.5f, (pOffset.Y + (regionsize * 0.5f)) - 0.5f, 0);
3518 IntPtr testGround = IntPtr.Zero;
3519 if (RegionTerrain.TryGetValue(pOffset, out testGround))
3520 {
3521 RegionTerrain.Remove(pOffset);
3522 }
3523 RegionTerrain.Add(pOffset, GroundGeom, GroundGeom);
3524 TerrainHeightFieldHeights.Add(GroundGeom,_heightmap);
3525 }
3526 }
3527
3528 public override void DeleteTerrain()
3529 {
3530 }
3531
3532 public float GetWaterLevel()
3533 {
3534 return waterlevel;
3535 }
3536
3537 public override bool SupportsCombining()
3538 {
3539 return true;
3540 }
3541
3542 public override void UnCombine(PhysicsScene pScene)
3543 {
3544 IntPtr localGround = IntPtr.Zero;
3545// float[] localHeightfield;
3546 bool proceed = false;
3547 List<IntPtr> geomDestroyList = new List<IntPtr>();
3548
3549 lock (OdeLock)
3550 {
3551 if (RegionTerrain.TryGetValue(Vector3.Zero, out localGround))
3552 {
3553 foreach (IntPtr geom in TerrainHeightFieldHeights.Keys)
3554 {
3555 if (geom == localGround)
3556 {
3557// localHeightfield = TerrainHeightFieldHeights[geom];
3558 proceed = true;
3559 }
3560 else
3561 {
3562 geomDestroyList.Add(geom);
3563 }
3564 }
3565
3566 if (proceed)
3567 {
3568 m_worldOffset = Vector3.Zero;
3569 WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize);
3570 m_parentScene = null;
3571
3572 foreach (IntPtr g in geomDestroyList)
3573 {
3574 // removingHeightField needs to be done or the garbage collector will
3575 // collect the terrain data before we tell ODE to destroy it causing
3576 // memory corruption
3577 if (TerrainHeightFieldHeights.ContainsKey(g))
3578 {
3579// float[] removingHeightField = TerrainHeightFieldHeights[g];
3580 TerrainHeightFieldHeights.Remove(g);
3581
3582 if (RegionTerrain.ContainsKey(g))
3583 {
3584 RegionTerrain.Remove(g);
3585 }
3586
3587 d.GeomDestroy(g);
3588 //removingHeightField = new float[0];
3589 }
3590 }
3591
3592 }
3593 else
3594 {
3595 m_log.Warn("[PHYSICS]: Couldn't proceed with UnCombine. Region has inconsistant data.");
3596
3597 }
3598 }
3599 }
3600 }
3601
3602 public override void SetWaterLevel(float baseheight)
3603 {
3604 waterlevel = baseheight;
3605 randomizeWater(waterlevel);
3606 }
3607
3608 public void randomizeWater(float baseheight)
3609 {
3610 const uint heightmapWidth = m_regionWidth + 2;
3611 const uint heightmapHeight = m_regionHeight + 2;
3612 const uint heightmapWidthSamples = m_regionWidth + 2;
3613 const uint heightmapHeightSamples = m_regionHeight + 2;
3614 const float scale = 1.0f;
3615 const float offset = 0.0f;
3616 const float thickness = 2.9f;
3617 const int wrap = 0;
3618
3619 for (int i = 0; i < (258 * 258); i++)
3620 {
3621 _watermap[i] = (baseheight-0.1f) + ((float)fluidRandomizer.Next(1,9) / 10f);
3622 // m_log.Info((baseheight - 0.1f) + ((float)fluidRandomizer.Next(1, 9) / 10f));
3623 }
3624
3625 lock (OdeLock)
3626 {
3627 if (WaterGeom != IntPtr.Zero)
3628 {
3629 d.SpaceRemove(space, WaterGeom);
3630 }
3631 IntPtr HeightmapData = d.GeomHeightfieldDataCreate();
3632 d.GeomHeightfieldDataBuildSingle(HeightmapData, _watermap, 0, heightmapWidth, heightmapHeight,
3633 (int)heightmapWidthSamples, (int)heightmapHeightSamples, scale,
3634 offset, thickness, wrap);
3635 d.GeomHeightfieldDataSetBounds(HeightmapData, m_regionWidth, m_regionHeight);
3636 WaterGeom = d.CreateHeightfield(space, HeightmapData, 1);
3637 if (WaterGeom != IntPtr.Zero)
3638 {
3639 d.GeomSetCategoryBits(WaterGeom, (int)(CollisionCategories.Water));
3640 d.GeomSetCollideBits(WaterGeom, (int)(CollisionCategories.Space));
3641
3642 }
3643 geom_name_map[WaterGeom] = "Water";
3644
3645 d.Matrix3 R = new d.Matrix3();
3646
3647 Quaternion q1 = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 1.5707f);
3648 Quaternion q2 = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), 1.5707f);
3649 //Axiom.Math.Quaternion q3 = Axiom.Math.Quaternion.FromAngleAxis(3.14f, new Axiom.Math.Vector3(0, 0, 1));
3650
3651 q1 = q1 * q2;
3652 //q1 = q1 * q3;
3653 Vector3 v3;
3654 float angle;
3655 q1.GetAxisAngle(out v3, out angle);
3656
3657 d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle);
3658 d.GeomSetRotation(WaterGeom, ref R);
3659 d.GeomSetPosition(WaterGeom, 128, 128, 0);
3660
3661 }
3662
3663 }
3664
3665 public override void Dispose()
3666 {
3667 m_rayCastManager.Dispose();
3668 m_rayCastManager = null;
3669
3670 lock (OdeLock)
3671 {
3672 lock (_prims)
3673 {
3674 foreach (OdePrim prm in _prims)
3675 {
3676 RemovePrim(prm);
3677 }
3678 }
3679
3680 //foreach (OdeCharacter act in _characters)
3681 //{
3682 //RemoveAvatar(act);
3683 //}
3684 d.WorldDestroy(world);
3685 //d.CloseODE();
3686 }
3687 }
3688 public override Dictionary<uint, float> GetTopColliders()
3689 {
3690 Dictionary<uint, float> returncolliders = new Dictionary<uint, float>();
3691 int cnt = 0;
3692 lock (_prims)
3693 {
3694 foreach (OdePrim prm in _prims)
3695 {
3696 if (prm.CollisionScore > 0)
3697 {
3698 returncolliders.Add(prm.m_localID, prm.CollisionScore);
3699 cnt++;
3700 prm.CollisionScore = 0f;
3701 if (cnt > 25)
3702 {
3703 break;
3704 }
3705 }
3706 }
3707 }
3708 return returncolliders;
3709 }
3710
3711 public override bool SupportsRayCast()
3712 {
3713 return true;
3714 }
3715
3716 public override void RaycastWorld(Vector3 position, Vector3 direction, float length, RaycastCallback retMethod)
3717 {
3718 if (retMethod != null)
3719 {
3720 m_rayCastManager.QueueRequest(position, direction, length, retMethod);
3721 }
3722 }
3723
3724#if USE_DRAWSTUFF
3725 // Keyboard callback
3726 public void command(int cmd)
3727 {
3728 IntPtr geom;
3729 d.Mass mass;
3730 d.Vector3 sides = new d.Vector3(d.RandReal() * 0.5f + 0.1f, d.RandReal() * 0.5f + 0.1f, d.RandReal() * 0.5f + 0.1f);
3731
3732
3733
3734 Char ch = Char.ToLower((Char)cmd);
3735 switch ((Char)ch)
3736 {
3737 case 'w':
3738 try
3739 {
3740 Vector3 rotate = (new Vector3(1, 0, 0) * Quaternion.CreateFromEulers(hpr.Z * Utils.DEG_TO_RAD, hpr.Y * Utils.DEG_TO_RAD, hpr.X * Utils.DEG_TO_RAD));
3741
3742 xyz.X += rotate.X; xyz.Y += rotate.Y; xyz.Z += rotate.Z;
3743 ds.SetViewpoint(ref xyz, ref hpr);
3744 }
3745 catch (ArgumentException)
3746 { hpr.X = 0; }
3747 break;
3748
3749 case 'a':
3750 hpr.X++;
3751 ds.SetViewpoint(ref xyz, ref hpr);
3752 break;
3753
3754 case 's':
3755 try
3756 {
3757 Vector3 rotate2 = (new Vector3(-1, 0, 0) * Quaternion.CreateFromEulers(hpr.Z * Utils.DEG_TO_RAD, hpr.Y * Utils.DEG_TO_RAD, hpr.X * Utils.DEG_TO_RAD));
3758
3759 xyz.X += rotate2.X; xyz.Y += rotate2.Y; xyz.Z += rotate2.Z;
3760 ds.SetViewpoint(ref xyz, ref hpr);
3761 }
3762 catch (ArgumentException)
3763 { hpr.X = 0; }
3764 break;
3765 case 'd':
3766 hpr.X--;
3767 ds.SetViewpoint(ref xyz, ref hpr);
3768 break;
3769 case 'r':
3770 xyz.Z++;
3771 ds.SetViewpoint(ref xyz, ref hpr);
3772 break;
3773 case 'f':
3774 xyz.Z--;
3775 ds.SetViewpoint(ref xyz, ref hpr);
3776 break;
3777 case 'e':
3778 xyz.Y++;
3779 ds.SetViewpoint(ref xyz, ref hpr);
3780 break;
3781 case 'q':
3782 xyz.Y--;
3783 ds.SetViewpoint(ref xyz, ref hpr);
3784 break;
3785 }
3786 }
3787
3788 public void step(int pause)
3789 {
3790
3791 ds.SetColor(1.0f, 1.0f, 0.0f);
3792 ds.SetTexture(ds.Texture.Wood);
3793 lock (_prims)
3794 {
3795 foreach (OdePrim prm in _prims)
3796 {
3797 //IntPtr body = d.GeomGetBody(prm.prim_geom);
3798 if (prm.prim_geom != IntPtr.Zero)
3799 {
3800 d.Vector3 pos;
3801 d.GeomCopyPosition(prm.prim_geom, out pos);
3802 //d.BodyCopyPosition(body, out pos);
3803
3804 d.Matrix3 R;
3805 d.GeomCopyRotation(prm.prim_geom, out R);
3806 //d.BodyCopyRotation(body, out R);
3807
3808
3809 d.Vector3 sides = new d.Vector3();
3810 sides.X = prm.Size.X;
3811 sides.Y = prm.Size.Y;
3812 sides.Z = prm.Size.Z;
3813
3814 ds.DrawBox(ref pos, ref R, ref sides);
3815 }
3816 }
3817 }
3818 ds.SetColor(1.0f, 0.0f, 0.0f);
3819 lock (_characters)
3820 {
3821 foreach (OdeCharacter chr in _characters)
3822 {
3823 if (chr.Shell != IntPtr.Zero)
3824 {
3825 IntPtr body = d.GeomGetBody(chr.Shell);
3826
3827 d.Vector3 pos;
3828 d.GeomCopyPosition(chr.Shell, out pos);
3829 //d.BodyCopyPosition(body, out pos);
3830
3831 d.Matrix3 R;
3832 d.GeomCopyRotation(chr.Shell, out R);
3833 //d.BodyCopyRotation(body, out R);
3834
3835 ds.DrawCapsule(ref pos, ref R, chr.Size.Z, 0.35f);
3836 d.Vector3 sides = new d.Vector3();
3837 sides.X = 0.5f;
3838 sides.Y = 0.5f;
3839 sides.Z = 0.5f;
3840
3841 ds.DrawBox(ref pos, ref R, ref sides);
3842 }
3843 }
3844 }
3845 }
3846
3847 public void start(int unused)
3848 {
3849 ds.SetViewpoint(ref xyz, ref hpr);
3850 }
3851#endif
3852 }
3853}
diff --git a/OpenSim/Region/Physics/ChOdePlugin/Tests/ODETestClass.cs b/OpenSim/Region/Physics/ChOdePlugin/Tests/ODETestClass.cs
new file mode 100644
index 0000000..69e2d03
--- /dev/null
+++ b/OpenSim/Region/Physics/ChOdePlugin/Tests/ODETestClass.cs
@@ -0,0 +1,122 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using Nini.Config;
30using NUnit.Framework;
31using OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Region.Physics.Manager;
34using log4net;
35using System.Reflection;
36
37namespace OpenSim.Region.Physics.OdePlugin
38{
39 [TestFixture]
40 public class ODETestClass
41 {
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43
44 private OdePlugin cbt;
45 private PhysicsScene ps;
46 private IMeshingPlugin imp;
47
48 [SetUp]
49 public void Initialize()
50 {
51 // Loading ODEPlugin
52 cbt = new OdePlugin();
53 // Loading Zero Mesher
54 imp = new ZeroMesherPlugin();
55 // Getting Physics Scene
56 ps = cbt.GetScene("test");
57 // Initializing Physics Scene.
58 ps.Initialise(imp.GetMesher(),null);
59 float[] _heightmap = new float[(int)Constants.RegionSize * (int)Constants.RegionSize];
60 for (int i = 0; i < ((int)Constants.RegionSize * (int)Constants.RegionSize); i++)
61 {
62 _heightmap[i] = 21f;
63 }
64 ps.SetTerrain(_heightmap);
65 }
66
67 [TearDown]
68 public void Terminate()
69 {
70 ps.DeleteTerrain();
71 ps.Dispose();
72
73 }
74
75 [Test]
76 public void CreateAndDropPhysicalCube()
77 {
78 PrimitiveBaseShape newcube = PrimitiveBaseShape.CreateBox();
79 Vector3 position = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), 128f);
80 Vector3 size = new Vector3(0.5f, 0.5f, 0.5f);
81 Quaternion rot = Quaternion.Identity;
82 PhysicsActor prim = ps.AddPrimShape("CoolShape", newcube, position, size, rot, true);
83 OdePrim oprim = (OdePrim)prim;
84 OdeScene pscene = (OdeScene) ps;
85
86 Assert.That(oprim.m_taintadd);
87
88 prim.LocalID = 5;
89
90 for (int i = 0; i < 58; i++)
91 {
92 ps.Simulate(0.133f);
93
94 Assert.That(oprim.prim_geom != (IntPtr)0);
95
96 Assert.That(oprim.m_targetSpace != (IntPtr)0);
97
98 //Assert.That(oprim.m_targetSpace == pscene.space);
99 m_log.Info("TargetSpace: " + oprim.m_targetSpace + " - SceneMainSpace: " + pscene.space);
100
101 Assert.That(!oprim.m_taintadd);
102 m_log.Info("Prim Position (" + oprim.m_localID + "): " + prim.Position.ToString());
103
104 // Make sure we're above the ground
105 //Assert.That(prim.Position.Z > 20f);
106 //m_log.Info("PrimCollisionScore (" + oprim.m_localID + "): " + oprim.m_collisionscore);
107
108 // Make sure we've got a Body
109 Assert.That(oprim.Body != (IntPtr)0);
110 //m_log.Info(
111 }
112
113 // Make sure we're not somewhere above the ground
114 Assert.That(prim.Position.Z < 21.5f);
115
116 ps.RemovePrim(prim);
117 Assert.That(oprim.m_taintremove);
118 ps.Simulate(0.133f);
119 Assert.That(oprim.Body == (IntPtr)0);
120 }
121 }
122}
diff --git a/OpenSim/Region/Physics/ChOdePlugin/drawstuff.cs b/OpenSim/Region/Physics/ChOdePlugin/drawstuff.cs
new file mode 100644
index 0000000..87ca446
--- /dev/null
+++ b/OpenSim/Region/Physics/ChOdePlugin/drawstuff.cs
@@ -0,0 +1,98 @@
1/*
2 * Copyright ODE
3 * Ode.NET - .NET bindings for ODE
4 * Jason Perkins (starkos@industriousone.com)
5 * Licensed under the New BSD
6 * Part of the OpenDynamicsEngine
7Open Dynamics Engine
8Copyright (c) 2001-2007, Russell L. Smith.
9All rights reserved.
10
11Redistribution and use in source and binary forms, with or without
12modification, are permitted provided that the following conditions
13are met:
14
15Redistributions of source code must retain the above copyright notice,
16this list of conditions and the following disclaimer.
17
18Redistributions in binary form must reproduce the above copyright notice,
19this list of conditions and the following disclaimer in the documentation
20and/or other materials provided with the distribution.
21
22Neither the names of ODE's copyright owner nor the names of its
23contributors may be used to endorse or promote products derived from
24this software without specific prior written permission.
25
26THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
29FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
32TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 *
38 *
39 */
40
41using System;
42using System.Runtime.InteropServices;
43using Ode.NET;
44
45namespace Drawstuff.NET
46{
47#if dDOUBLE
48 using dReal = System.Double;
49#else
50 using dReal = System.Single;
51#endif
52
53 public static class ds
54 {
55 public const int VERSION = 2;
56
57 public enum Texture
58 {
59 None,
60 Wood
61 }
62
63 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
64 public delegate void CallbackFunction(int arg);
65
66 [StructLayout(LayoutKind.Sequential)]
67 public struct Functions
68 {
69 public int version;
70 public CallbackFunction start;
71 public CallbackFunction step;
72 public CallbackFunction command;
73 public CallbackFunction stop;
74 public string path_to_textures;
75 }
76
77 [DllImport("drawstuff", EntryPoint = "dsDrawBox")]
78 public static extern void DrawBox(ref d.Vector3 pos, ref d.Matrix3 R, ref d.Vector3 sides);
79
80 [DllImport("drawstuff", EntryPoint = "dsDrawCapsule")]
81 public static extern void DrawCapsule(ref d.Vector3 pos, ref d.Matrix3 R, dReal length, dReal radius);
82
83 [DllImport("drawstuff", EntryPoint = "dsDrawConvex")]
84 public static extern void DrawConvex(ref d.Vector3 pos, ref d.Matrix3 R, dReal[] planes, int planeCount, dReal[] points, int pointCount, int[] polygons);
85
86 [DllImport("drawstuff", EntryPoint = "dsSetColor")]
87 public static extern void SetColor(float red, float green, float blue);
88
89 [DllImport("drawstuff", EntryPoint = "dsSetTexture")]
90 public static extern void SetTexture(Texture texture);
91
92 [DllImport("drawstuff", EntryPoint = "dsSetViewpoint")]
93 public static extern void SetViewpoint(ref d.Vector3 xyz, ref d.Vector3 hpr);
94
95 [DllImport("drawstuff", EntryPoint = "dsSimulationLoop")]
96 public static extern void SimulationLoop(int argc, string[] argv, int window_width, int window_height, ref Functions fn);
97 }
98}
diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
index a2229e8..2a66060 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
@@ -1210,7 +1210,6 @@ namespace OpenSim.Region.Physics.OdePlugin
1210 1210
1211 public override float APIDDamping{ set { return; } } 1211 public override float APIDDamping{ set { return; } }
1212 1212
1213
1214 public override void SubscribeEvents(int ms) 1213 public override void SubscribeEvents(int ms)
1215 { 1214 {
1216 m_requestedUpdateFrequency = ms; 1215 m_requestedUpdateFrequency = ms;
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
index 0720b5e..be7c348 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
@@ -2831,7 +2831,7 @@ Console.WriteLine(" JointCreateFixed");
2831 } 2831 }
2832 public override bool PIDActive { set { m_usePID = value; } } 2832 public override bool PIDActive { set { m_usePID = value; } }
2833 public override float PIDTau { set { m_PIDTau = value; } } 2833 public override float PIDTau { set { m_PIDTau = value; } }
2834 2834
2835 public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } } 2835 public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } }
2836 public override bool PIDHoverActive { set { m_useHoverPID = value; } } 2836 public override bool PIDHoverActive { set { m_useHoverPID = value; } }
2837 public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } } 2837 public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } }
diff --git a/OpenSim/Region/Physics/POSPlugin/POSPrim.cs b/OpenSim/Region/Physics/POSPlugin/POSPrim.cs
index 91ec3df..9ba5ebb 100644
--- a/OpenSim/Region/Physics/POSPlugin/POSPrim.cs
+++ b/OpenSim/Region/Physics/POSPlugin/POSPrim.cs
@@ -301,7 +301,7 @@ namespace OpenSim.Region.Physics.POSPlugin
301 { 301 {
302 set { return; } 302 set { return; }
303 } 303 }
304 304
305 public override Quaternion APIDTarget 305 public override Quaternion APIDTarget
306 { 306 {
307 set { return; } 307 set { return; }
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
index 9cb349a..b42d3bf 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
@@ -88,89 +88,7 @@ namespace OpenSim.Region.RegionCombinerModule
88 public void RegionLoaded(Scene scene) 88 public void RegionLoaded(Scene scene)
89 { 89 {
90 if (enabledYN) 90 if (enabledYN)
91 {
92 RegionLoadedDoWork(scene); 91 RegionLoadedDoWork(scene);
93
94 scene.EventManager.OnNewPresence += NewPresence;
95 }
96 }
97
98 private void NewPresence(ScenePresence presence)
99 {
100 if (presence.IsChildAgent)
101 {
102 byte[] throttleData;
103
104 try
105 {
106 throttleData = presence.ControllingClient.GetThrottlesPacked(1);
107 }
108 catch (NotImplementedException)
109 {
110 return;
111 }
112
113 if (throttleData == null)
114 return;
115
116 if (throttleData.Length == 0)
117 return;
118
119 if (throttleData.Length != 28)
120 return;
121
122 byte[] adjData;
123 int pos = 0;
124
125 if (!BitConverter.IsLittleEndian)
126 {
127 byte[] newData = new byte[7 * 4];
128 Buffer.BlockCopy(throttleData, 0, newData, 0, 7 * 4);
129
130 for (int i = 0; i < 7; i++)
131 Array.Reverse(newData, i * 4, 4);
132
133 adjData = newData;
134 }
135 else
136 {
137 adjData = throttleData;
138 }
139
140 // 0.125f converts from bits to bytes
141 int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
142 int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
143 int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
144 int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
145 int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
146 int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
147 int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
148 // State is a subcategory of task that we allocate a percentage to
149
150
151 //int total = resend + land + wind + cloud + task + texture + asset;
152
153 byte[] data = new byte[7 * 4];
154 int ii = 0;
155
156 Buffer.BlockCopy(Utils.FloatToBytes(resend), 0, data, ii, 4); ii += 4;
157 Buffer.BlockCopy(Utils.FloatToBytes(land * 50), 0, data, ii, 4); ii += 4;
158 Buffer.BlockCopy(Utils.FloatToBytes(wind), 0, data, ii, 4); ii += 4;
159 Buffer.BlockCopy(Utils.FloatToBytes(cloud), 0, data, ii, 4); ii += 4;
160 Buffer.BlockCopy(Utils.FloatToBytes(task), 0, data, ii, 4); ii += 4;
161 Buffer.BlockCopy(Utils.FloatToBytes(texture), 0, data, ii, 4); ii += 4;
162 Buffer.BlockCopy(Utils.FloatToBytes(asset), 0, data, ii, 4);
163
164 try
165 {
166 presence.ControllingClient.SetChildAgentThrottle(data);
167 }
168 catch (NotImplementedException)
169 {
170 return;
171 }
172
173 }
174 } 92 }
175 93
176 private void RegionLoadedDoWork(Scene scene) 94 private void RegionLoadedDoWork(Scene scene)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs
index 880ca1b..3e62c1a 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs
@@ -113,6 +113,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
113 } 113 }
114 114
115 /// <summary> 115 /// <summary>
116 /// Like osGetAgents but returns enough info for a radar
117 /// </summary>
118 /// <returns>Strided list of the UUID, position and name of each avatar in the region</returns>
119 public LSL_List cmGetAvatarList()
120 {
121 LSL_List result = new LSL_List();
122 World.ForEachScenePresence(delegate (ScenePresence avatar)
123 {
124 if (avatar != null && avatar.UUID != m_host.OwnerID)
125 {
126 if (avatar.IsChildAgent == false)
127 {
128 result.Add(avatar.UUID);
129 result.Add(avatar.PhysicsActor.Position);
130 result.Add(avatar.Name);
131 }
132 }
133 });
134 return result;
135 }
136
137 /// <summary>
116 /// Get the current Windlight scene 138 /// Get the current Windlight scene
117 /// </summary> 139 /// </summary>
118 /// <returns>List of windlight parameters</returns> 140 /// <returns>List of windlight parameters</returns>
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 7a9a92d..68f6e7b 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);
@@ -219,6 +222,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
219 public List<SceneObjectPart> GetLinkParts(int linkType) 222 public List<SceneObjectPart> GetLinkParts(int linkType)
220 { 223 {
221 List<SceneObjectPart> ret = new List<SceneObjectPart>(); 224 List<SceneObjectPart> ret = new List<SceneObjectPart>();
225 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
226 return ret;
222 ret.Add(m_host); 227 ret.Add(m_host);
223 228
224 switch (linkType) 229 switch (linkType)
@@ -272,40 +277,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
272 protected UUID InventorySelf() 277 protected UUID InventorySelf()
273 { 278 {
274 UUID invItemID = new UUID(); 279 UUID invItemID = new UUID();
275 280 bool unlock = false;
276 lock (m_host.TaskInventory) 281 if (!m_host.TaskInventory.IsReadLockedByMe())
277 { 282 {
278 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 283 m_host.TaskInventory.LockItemsForRead(true);
284 unlock = true;
285 }
286 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
287 {
288 if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID)
279 { 289 {
280 if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID) 290 invItemID = inv.Key;
281 { 291 break;
282 invItemID = inv.Key;
283 break;
284 }
285 } 292 }
286 } 293 }
287 294 if (unlock)
295 {
296 m_host.TaskInventory.LockItemsForRead(false);
297 }
288 return invItemID; 298 return invItemID;
289 } 299 }
290 300
291 protected UUID InventoryKey(string name, int type) 301 protected UUID InventoryKey(string name, int type)
292 { 302 {
293 m_host.AddScriptLPS(1); 303 m_host.AddScriptLPS(1);
294 304 m_host.TaskInventory.LockItemsForRead(true);
295 lock (m_host.TaskInventory) 305
306 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
296 { 307 {
297 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 308 if (inv.Value.Name == name)
298 { 309 {
299 if (inv.Value.Name == name) 310 m_host.TaskInventory.LockItemsForRead(false);
311
312 if (inv.Value.Type != type)
300 { 313 {
301 if (inv.Value.Type != type) 314 return UUID.Zero;
302 return UUID.Zero;
303
304 return inv.Value.AssetID;
305 } 315 }
316
317 return inv.Value.AssetID;
306 } 318 }
307 } 319 }
308 320
321 m_host.TaskInventory.LockItemsForRead(false);
309 return UUID.Zero; 322 return UUID.Zero;
310 } 323 }
311 324
@@ -313,17 +326,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
313 { 326 {
314 m_host.AddScriptLPS(1); 327 m_host.AddScriptLPS(1);
315 328
316 lock (m_host.TaskInventory) 329
330 m_host.TaskInventory.LockItemsForRead(true);
331
332 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
317 { 333 {
318 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 334 if (inv.Value.Name == name)
319 { 335 {
320 if (inv.Value.Name == name) 336 m_host.TaskInventory.LockItemsForRead(false);
321 { 337 return inv.Value.AssetID;
322 return inv.Value.AssetID;
323 }
324 } 338 }
325 } 339 }
326 340
341 m_host.TaskInventory.LockItemsForRead(false);
342
343
327 return UUID.Zero; 344 return UUID.Zero;
328 } 345 }
329 346
@@ -705,6 +722,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
705 { 722 {
706 //A and B should both be normalized 723 //A and B should both be normalized
707 m_host.AddScriptLPS(1); 724 m_host.AddScriptLPS(1);
725 /* This method is more accurate than the SL one, and thus causes problems
726 for scripts that deal with the SL inaccuracy around 180-degrees -.- .._.
727
708 double dotProduct = LSL_Vector.Dot(a, b); 728 double dotProduct = LSL_Vector.Dot(a, b);
709 LSL_Vector crossProduct = LSL_Vector.Cross(a, b); 729 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
710 double magProduct = LSL_Vector.Mag(a) * LSL_Vector.Mag(b); 730 double magProduct = LSL_Vector.Mag(a) * LSL_Vector.Mag(b);
@@ -721,8 +741,57 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
721 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); 741 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
722 742
723 return new LSL_Rotation((float)x, (float)y, (float)z, (float)w); 743 return new LSL_Rotation((float)x, (float)y, (float)z, (float)w);
724 } 744 */
725 745
746 // This method mimics the 180 errors found in SL
747 // See www.euclideanspace.com... angleBetween
748 LSL_Vector vec_a = a;
749 LSL_Vector vec_b = b;
750
751 // Eliminate zero length
752 LSL_Float vec_a_mag = LSL_Vector.Mag(vec_a);
753 LSL_Float vec_b_mag = LSL_Vector.Mag(vec_b);
754 if (vec_a_mag < 0.00001 ||
755 vec_b_mag < 0.00001)
756 {
757 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
758 }
759
760 // Normalize
761 vec_a = llVecNorm(vec_a);
762 vec_b = llVecNorm(vec_b);
763
764 // Calculate axis and rotation angle
765 LSL_Vector axis = vec_a % vec_b;
766 LSL_Float cos_theta = vec_a * vec_b;
767
768 // Check if parallel
769 if (cos_theta > 0.99999)
770 {
771 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
772 }
773
774 // Check if anti-parallel
775 else if (cos_theta < -0.99999)
776 {
777 LSL_Vector orthog_axis = new LSL_Vector(1.0, 0.0, 0.0) - (vec_a.x / (vec_a * vec_a) * vec_a);
778 if (LSL_Vector.Mag(orthog_axis) < 0.000001) orthog_axis = new LSL_Vector(0.0, 0.0, 1.0);
779 return new LSL_Rotation((float)orthog_axis.x, (float)orthog_axis.y, (float)orthog_axis.z, 0.0);
780 }
781 else // other rotation
782 {
783 LSL_Float theta = (LSL_Float)Math.Acos(cos_theta) * 0.5f;
784 axis = llVecNorm(axis);
785 double x, y, z, s, t;
786 s = Math.Cos(theta);
787 t = Math.Sin(theta);
788 x = axis.x * t;
789 y = axis.y * t;
790 z = axis.z * t;
791 return new LSL_Rotation(x,y,z,s);
792 }
793 }
794
726 public void llWhisper(int channelID, string text) 795 public void llWhisper(int channelID, string text)
727 { 796 {
728 m_host.AddScriptLPS(1); 797 m_host.AddScriptLPS(1);
@@ -1046,10 +1115,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1046 return detectedParams.TouchUV; 1115 return detectedParams.TouchUV;
1047 } 1116 }
1048 1117
1118 [DebuggerNonUserCode]
1049 public virtual void llDie() 1119 public virtual void llDie()
1050 { 1120 {
1051 m_host.AddScriptLPS(1); 1121 m_host.AddScriptLPS(1);
1052 throw new SelfDeleteException(); 1122 if (!m_host.IsAttachment) throw new SelfDeleteException();
1053 } 1123 }
1054 1124
1055 public LSL_Float llGround(LSL_Vector offset) 1125 public LSL_Float llGround(LSL_Vector offset)
@@ -1122,6 +1192,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1122 1192
1123 public void llSetStatus(int status, int value) 1193 public void llSetStatus(int status, int value)
1124 { 1194 {
1195 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
1196 return;
1125 m_host.AddScriptLPS(1); 1197 m_host.AddScriptLPS(1);
1126 1198
1127 int statusrotationaxis = 0; 1199 int statusrotationaxis = 0;
@@ -1351,6 +1423,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1351 { 1423 {
1352 m_host.AddScriptLPS(1); 1424 m_host.AddScriptLPS(1);
1353 1425
1426 SetColor(m_host, color, face);
1427 }
1428
1429 protected void SetColor(SceneObjectPart part, LSL_Vector color, int face)
1430 {
1431 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1432 return;
1433
1434 Primitive.TextureEntry tex = part.Shape.Textures;
1435 Color4 texcolor;
1436 if (face >= 0 && face < GetNumberOfSides(part))
1437 {
1438 texcolor = tex.CreateFace((uint)face).RGBA;
1439 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1440 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1441 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1442 tex.FaceTextures[face].RGBA = texcolor;
1443 part.UpdateTexture(tex);
1444 return;
1445 }
1446 else if (face == ScriptBaseClass.ALL_SIDES)
1447 {
1448 for (uint i = 0; i < GetNumberOfSides(part); i++)
1449 {
1450 if (tex.FaceTextures[i] != null)
1451 {
1452 texcolor = tex.FaceTextures[i].RGBA;
1453 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1454 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1455 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1456 tex.FaceTextures[i].RGBA = texcolor;
1457 }
1458 texcolor = tex.DefaultTexture.RGBA;
1459 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1460 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1461 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1462 tex.DefaultTexture.RGBA = texcolor;
1463 }
1464 part.UpdateTexture(tex);
1465 return;
1466 }
1467
1354 if (face == ScriptBaseClass.ALL_SIDES) 1468 if (face == ScriptBaseClass.ALL_SIDES)
1355 face = SceneObjectPart.ALL_SIDES; 1469 face = SceneObjectPart.ALL_SIDES;
1356 1470
@@ -1359,6 +1473,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1359 1473
1360 public void SetTexGen(SceneObjectPart part, int face,int style) 1474 public void SetTexGen(SceneObjectPart part, int face,int style)
1361 { 1475 {
1476 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1477 return;
1478
1362 Primitive.TextureEntry tex = part.Shape.Textures; 1479 Primitive.TextureEntry tex = part.Shape.Textures;
1363 MappingType textype; 1480 MappingType textype;
1364 textype = MappingType.Default; 1481 textype = MappingType.Default;
@@ -1389,6 +1506,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1389 1506
1390 public void SetGlow(SceneObjectPart part, int face, float glow) 1507 public void SetGlow(SceneObjectPart part, int face, float glow)
1391 { 1508 {
1509 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1510 return;
1511
1392 Primitive.TextureEntry tex = part.Shape.Textures; 1512 Primitive.TextureEntry tex = part.Shape.Textures;
1393 if (face >= 0 && face < GetNumberOfSides(part)) 1513 if (face >= 0 && face < GetNumberOfSides(part))
1394 { 1514 {
@@ -1414,6 +1534,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1414 1534
1415 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump) 1535 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump)
1416 { 1536 {
1537 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1538 return;
1417 1539
1418 Shininess sval = new Shininess(); 1540 Shininess sval = new Shininess();
1419 1541
@@ -1464,6 +1586,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1464 1586
1465 public void SetFullBright(SceneObjectPart part, int face, bool bright) 1587 public void SetFullBright(SceneObjectPart part, int face, bool bright)
1466 { 1588 {
1589 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1590 return;
1591
1467 Primitive.TextureEntry tex = part.Shape.Textures; 1592 Primitive.TextureEntry tex = part.Shape.Textures;
1468 if (face >= 0 && face < GetNumberOfSides(part)) 1593 if (face >= 0 && face < GetNumberOfSides(part))
1469 { 1594 {
@@ -1531,6 +1656,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1531 1656
1532 protected void SetAlpha(SceneObjectPart part, double alpha, int face) 1657 protected void SetAlpha(SceneObjectPart part, double alpha, int face)
1533 { 1658 {
1659 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1660 return;
1661
1534 Primitive.TextureEntry tex = part.Shape.Textures; 1662 Primitive.TextureEntry tex = part.Shape.Textures;
1535 Color4 texcolor; 1663 Color4 texcolor;
1536 if (face >= 0 && face < GetNumberOfSides(part)) 1664 if (face >= 0 && face < GetNumberOfSides(part))
@@ -1576,7 +1704,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1576 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction, 1704 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction,
1577 float wind, float tension, LSL_Vector Force) 1705 float wind, float tension, LSL_Vector Force)
1578 { 1706 {
1579 if (part == null) 1707 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1580 return; 1708 return;
1581 1709
1582 if (flexi) 1710 if (flexi)
@@ -1611,7 +1739,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1611 /// <param name="falloff"></param> 1739 /// <param name="falloff"></param>
1612 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff) 1740 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
1613 { 1741 {
1614 if (part == null) 1742 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1615 return; 1743 return;
1616 1744
1617 if (light) 1745 if (light)
@@ -1697,6 +1825,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1697 1825
1698 protected void SetTexture(SceneObjectPart part, string texture, int face) 1826 protected void SetTexture(SceneObjectPart part, string texture, int face)
1699 { 1827 {
1828 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1829 return;
1830
1700 UUID textureID=new UUID(); 1831 UUID textureID=new UUID();
1701 1832
1702 if (!UUID.TryParse(texture, out textureID)) 1833 if (!UUID.TryParse(texture, out textureID))
@@ -1742,6 +1873,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1742 1873
1743 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face) 1874 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face)
1744 { 1875 {
1876 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1877 return;
1878
1745 Primitive.TextureEntry tex = part.Shape.Textures; 1879 Primitive.TextureEntry tex = part.Shape.Textures;
1746 if (face >= 0 && face < GetNumberOfSides(part)) 1880 if (face >= 0 && face < GetNumberOfSides(part))
1747 { 1881 {
@@ -1778,6 +1912,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1778 1912
1779 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face) 1913 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face)
1780 { 1914 {
1915 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1916 return;
1917
1781 Primitive.TextureEntry tex = part.Shape.Textures; 1918 Primitive.TextureEntry tex = part.Shape.Textures;
1782 if (face >= 0 && face < GetNumberOfSides(part)) 1919 if (face >= 0 && face < GetNumberOfSides(part))
1783 { 1920 {
@@ -1814,6 +1951,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1814 1951
1815 protected void RotateTexture(SceneObjectPart part, double rotation, int face) 1952 protected void RotateTexture(SceneObjectPart part, double rotation, int face)
1816 { 1953 {
1954 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1955 return;
1956
1817 Primitive.TextureEntry tex = part.Shape.Textures; 1957 Primitive.TextureEntry tex = part.Shape.Textures;
1818 if (face >= 0 && face < GetNumberOfSides(part)) 1958 if (face >= 0 && face < GetNumberOfSides(part))
1819 { 1959 {
@@ -1884,6 +2024,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1884 2024
1885 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos) 2025 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos)
1886 { 2026 {
2027 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2028 return;
2029
1887 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) 2030 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
1888 LSL_Vector currentPos = llGetLocalPos(); 2031 LSL_Vector currentPos = llGetLocalPos();
1889 2032
@@ -1970,6 +2113,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1970 2113
1971 protected void SetRot(SceneObjectPart part, Quaternion rot) 2114 protected void SetRot(SceneObjectPart part, Quaternion rot)
1972 { 2115 {
2116 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2117 return;
2118
1973 part.UpdateRotation(rot); 2119 part.UpdateRotation(rot);
1974 // Update rotation does not move the object in the physics scene if it's a linkset. 2120 // Update rotation does not move the object in the physics scene if it's a linkset.
1975 2121
@@ -2589,12 +2735,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2589 2735
2590 m_host.AddScriptLPS(1); 2736 m_host.AddScriptLPS(1);
2591 2737
2738 m_host.TaskInventory.LockItemsForRead(true);
2592 TaskInventoryItem item = m_host.TaskInventory[invItemID]; 2739 TaskInventoryItem item = m_host.TaskInventory[invItemID];
2593 2740 m_host.TaskInventory.LockItemsForRead(false);
2594 lock (m_host.TaskInventory)
2595 {
2596 item = m_host.TaskInventory[invItemID];
2597 }
2598 2741
2599 if (item.PermsGranter == UUID.Zero) 2742 if (item.PermsGranter == UUID.Zero)
2600 return 0; 2743 return 0;
@@ -2669,6 +2812,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2669 if (dist > m_ScriptDistanceFactor * 10.0f) 2812 if (dist > m_ScriptDistanceFactor * 10.0f)
2670 return; 2813 return;
2671 2814
2815 //Clone is thread-safe
2672 TaskInventoryDictionary partInventory = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 2816 TaskInventoryDictionary partInventory = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
2673 2817
2674 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in partInventory) 2818 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in partInventory)
@@ -2729,6 +2873,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2729 2873
2730 public void llLookAt(LSL_Vector target, double strength, double damping) 2874 public void llLookAt(LSL_Vector target, double strength, double damping)
2731 { 2875 {
2876 /*
2732 m_host.AddScriptLPS(1); 2877 m_host.AddScriptLPS(1);
2733 // Determine where we are looking from 2878 // Determine where we are looking from
2734 LSL_Vector from = llGetPos(); 2879 LSL_Vector from = llGetPos();
@@ -2748,10 +2893,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2748 // the angles of rotation in radians into rotation value 2893 // the angles of rotation in radians into rotation value
2749 2894
2750 LSL_Types.Quaternion rot = llEuler2Rot(angle); 2895 LSL_Types.Quaternion rot = llEuler2Rot(angle);
2751 Quaternion rotation = new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s); 2896
2752 m_host.startLookAt(rotation, (float)damping, (float)strength); 2897 // This would only work if your physics system contains an APID controller:
2898 // Quaternion rotation = new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s);
2899 // m_host.startLookAt(rotation, (float)damping, (float)strength);
2900
2753 // Orient the object to the angle calculated 2901 // Orient the object to the angle calculated
2754 //llSetRot(rot); 2902 llSetRot(rot);
2903 */
2904
2905 //The above code, while nice, doesn't replicate the behaviour of SL and tends to "roll" the object.
2906 //There's probably a smarter way of doing this, my rotation math-fu is weak.
2907 // http://bugs.meta7.com/view.php?id=28
2908 // - Tom
2909
2910 LSL_Rotation newrot = llGetRot() * llRotBetween(new LSL_Vector(1.0d, 0.0d, 0.0d) * llGetRot(), new LSL_Vector(0.0d, 0.0d, -1.0d));
2911 llSetRot(newrot * llRotBetween(new LSL_Vector(0.0d,0.0d,1.0d) * newrot, target - llGetPos()));
2912
2913 }
2914
2915 public void llRotLookAt(LSL_Rotation target, double strength, double damping)
2916 {
2917 m_host.AddScriptLPS(1);
2918// NotImplemented("llRotLookAt");
2919 m_host.RotLookAt(Rot2Quaternion(target), (float)strength, (float)damping);
2920
2755 } 2921 }
2756 2922
2757 public void llStopLookAt() 2923 public void llStopLookAt()
@@ -2800,13 +2966,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2800 { 2966 {
2801 TaskInventoryItem item; 2967 TaskInventoryItem item;
2802 2968
2803 lock (m_host.TaskInventory) 2969 m_host.TaskInventory.LockItemsForRead(true);
2970 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2804 { 2971 {
2805 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 2972 m_host.TaskInventory.LockItemsForRead(false);
2806 return; 2973 return;
2807 else 2974 }
2808 item = m_host.TaskInventory[InventorySelf()]; 2975 else
2976 {
2977 item = m_host.TaskInventory[InventorySelf()];
2809 } 2978 }
2979 m_host.TaskInventory.LockItemsForRead(false);
2810 2980
2811 if (item.PermsGranter != UUID.Zero) 2981 if (item.PermsGranter != UUID.Zero)
2812 { 2982 {
@@ -2828,13 +2998,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2828 { 2998 {
2829 TaskInventoryItem item; 2999 TaskInventoryItem item;
2830 3000
3001 m_host.TaskInventory.LockItemsForRead(true);
2831 lock (m_host.TaskInventory) 3002 lock (m_host.TaskInventory)
2832 { 3003 {
3004
2833 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3005 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3006 {
3007 m_host.TaskInventory.LockItemsForRead(false);
2834 return; 3008 return;
3009 }
2835 else 3010 else
3011 {
2836 item = m_host.TaskInventory[InventorySelf()]; 3012 item = m_host.TaskInventory[InventorySelf()];
3013 }
2837 } 3014 }
3015 m_host.TaskInventory.LockItemsForRead(false);
2838 3016
2839 m_host.AddScriptLPS(1); 3017 m_host.AddScriptLPS(1);
2840 3018
@@ -2871,14 +3049,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2871 3049
2872 TaskInventoryItem item; 3050 TaskInventoryItem item;
2873 3051
2874 lock (m_host.TaskInventory) 3052 m_host.TaskInventory.LockItemsForRead(true);
3053
3054 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2875 { 3055 {
2876 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3056 m_host.TaskInventory.LockItemsForRead(false);
2877 return; 3057 return;
2878 else 3058 }
2879 item = m_host.TaskInventory[InventorySelf()]; 3059 else
3060 {
3061 item = m_host.TaskInventory[InventorySelf()];
2880 } 3062 }
2881 3063
3064 m_host.TaskInventory.LockItemsForRead(false);
3065
2882 if (item.PermsGranter != m_host.OwnerID) 3066 if (item.PermsGranter != m_host.OwnerID)
2883 return; 3067 return;
2884 3068
@@ -2905,13 +3089,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2905 3089
2906 TaskInventoryItem item; 3090 TaskInventoryItem item;
2907 3091
2908 lock (m_host.TaskInventory) 3092 m_host.TaskInventory.LockItemsForRead(true);
3093
3094 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2909 { 3095 {
2910 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3096 m_host.TaskInventory.LockItemsForRead(false);
2911 return; 3097 return;
2912 else
2913 item = m_host.TaskInventory[InventorySelf()];
2914 } 3098 }
3099 else
3100 {
3101 item = m_host.TaskInventory[InventorySelf()];
3102 }
3103 m_host.TaskInventory.LockItemsForRead(false);
3104
2915 3105
2916 if (item.PermsGranter != m_host.OwnerID) 3106 if (item.PermsGranter != m_host.OwnerID)
2917 return; 3107 return;
@@ -2948,8 +3138,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2948 return m_host.OwnerID.ToString(); 3138 return m_host.OwnerID.ToString();
2949 } 3139 }
2950 3140
3141 [DebuggerNonUserCode]
2951 public void llInstantMessage(string user, string message) 3142 public void llInstantMessage(string user, string message)
2952 { 3143 {
3144 UUID result;
3145 if (!UUID.TryParse(user, out result))
3146 {
3147 throw new Exception(String.Format("An invalid key of '{0} was passed to llInstantMessage", user));
3148 return;
3149 }
3150
3151
2953 m_host.AddScriptLPS(1); 3152 m_host.AddScriptLPS(1);
2954 3153
2955 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. 3154 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
@@ -2964,7 +3163,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2964 UUID friendTransactionID = UUID.Random(); 3163 UUID friendTransactionID = UUID.Random();
2965 3164
2966 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); 3165 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
2967 3166
2968 GridInstantMessage msg = new GridInstantMessage(); 3167 GridInstantMessage msg = new GridInstantMessage();
2969 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; 3168 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid;
2970 msg.toAgentID = new Guid(user); // toAgentID.Guid; 3169 msg.toAgentID = new Guid(user); // toAgentID.Guid;
@@ -3113,13 +3312,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3113 m_host.AddScriptLPS(1); 3312 m_host.AddScriptLPS(1);
3114 } 3313 }
3115 3314
3116 public void llRotLookAt(LSL_Rotation target, double strength, double damping)
3117 {
3118 m_host.AddScriptLPS(1);
3119 Quaternion rot = new Quaternion((float)target.x, (float)target.y, (float)target.z, (float)target.s);
3120 m_host.RotLookAt(rot, (float)strength, (float)damping);
3121 }
3122
3123 public LSL_Integer llStringLength(string str) 3315 public LSL_Integer llStringLength(string str)
3124 { 3316 {
3125 m_host.AddScriptLPS(1); 3317 m_host.AddScriptLPS(1);
@@ -3143,14 +3335,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3143 3335
3144 TaskInventoryItem item; 3336 TaskInventoryItem item;
3145 3337
3146 lock (m_host.TaskInventory) 3338 m_host.TaskInventory.LockItemsForRead(true);
3339 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3147 { 3340 {
3148 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3341 m_host.TaskInventory.LockItemsForRead(false);
3149 return; 3342 return;
3150 else
3151 item = m_host.TaskInventory[InventorySelf()];
3152 } 3343 }
3153 3344 else
3345 {
3346 item = m_host.TaskInventory[InventorySelf()];
3347 }
3348 m_host.TaskInventory.LockItemsForRead(false);
3154 if (item.PermsGranter == UUID.Zero) 3349 if (item.PermsGranter == UUID.Zero)
3155 return; 3350 return;
3156 3351
@@ -3180,13 +3375,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3180 3375
3181 TaskInventoryItem item; 3376 TaskInventoryItem item;
3182 3377
3183 lock (m_host.TaskInventory) 3378 m_host.TaskInventory.LockItemsForRead(true);
3379 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3184 { 3380 {
3185 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3381 m_host.TaskInventory.LockItemsForRead(false);
3186 return; 3382 return;
3187 else
3188 item = m_host.TaskInventory[InventorySelf()];
3189 } 3383 }
3384 else
3385 {
3386 item = m_host.TaskInventory[InventorySelf()];
3387 }
3388 m_host.TaskInventory.LockItemsForRead(false);
3389
3190 3390
3191 if (item.PermsGranter == UUID.Zero) 3391 if (item.PermsGranter == UUID.Zero)
3192 return; 3392 return;
@@ -3263,10 +3463,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3263 3463
3264 TaskInventoryItem item; 3464 TaskInventoryItem item;
3265 3465
3266 lock (m_host.TaskInventory) 3466
3467 m_host.TaskInventory.LockItemsForRead(true);
3468 if (!m_host.TaskInventory.ContainsKey(invItemID))
3469 {
3470 m_host.TaskInventory.LockItemsForRead(false);
3471 return;
3472 }
3473 else
3267 { 3474 {
3268 item = m_host.TaskInventory[invItemID]; 3475 item = m_host.TaskInventory[invItemID];
3269 } 3476 }
3477 m_host.TaskInventory.LockItemsForRead(false);
3270 3478
3271 if (agentID == UUID.Zero || perm == 0) // Releasing permissions 3479 if (agentID == UUID.Zero || perm == 0) // Releasing permissions
3272 { 3480 {
@@ -3298,11 +3506,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3298 3506
3299 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3507 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3300 { 3508 {
3301 lock (m_host.TaskInventory) 3509 m_host.TaskInventory.LockItemsForWrite(true);
3302 { 3510 m_host.TaskInventory[invItemID].PermsGranter = agentID;
3303 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3511 m_host.TaskInventory[invItemID].PermsMask = perm;
3304 m_host.TaskInventory[invItemID].PermsMask = perm; 3512 m_host.TaskInventory.LockItemsForWrite(false);
3305 }
3306 3513
3307 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3514 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3308 "run_time_permissions", new Object[] { 3515 "run_time_permissions", new Object[] {
@@ -3322,11 +3529,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3322 3529
3323 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3530 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3324 { 3531 {
3325 lock (m_host.TaskInventory) 3532 m_host.TaskInventory.LockItemsForWrite(true);
3326 { 3533 m_host.TaskInventory[invItemID].PermsGranter = agentID;
3327 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3534 m_host.TaskInventory[invItemID].PermsMask = perm;
3328 m_host.TaskInventory[invItemID].PermsMask = perm; 3535 m_host.TaskInventory.LockItemsForWrite(false);
3329 }
3330 3536
3331 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3537 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3332 "run_time_permissions", new Object[] { 3538 "run_time_permissions", new Object[] {
@@ -3347,11 +3553,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3347 3553
3348 if (!m_waitingForScriptAnswer) 3554 if (!m_waitingForScriptAnswer)
3349 { 3555 {
3350 lock (m_host.TaskInventory) 3556 m_host.TaskInventory.LockItemsForWrite(true);
3351 { 3557 m_host.TaskInventory[invItemID].PermsGranter = agentID;
3352 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3558 m_host.TaskInventory[invItemID].PermsMask = 0;
3353 m_host.TaskInventory[invItemID].PermsMask = 0; 3559 m_host.TaskInventory.LockItemsForWrite(false);
3354 }
3355 3560
3356 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; 3561 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
3357 m_waitingForScriptAnswer=true; 3562 m_waitingForScriptAnswer=true;
@@ -3386,10 +3591,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3386 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) 3591 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
3387 llReleaseControls(); 3592 llReleaseControls();
3388 3593
3389 lock (m_host.TaskInventory) 3594
3390 { 3595 m_host.TaskInventory.LockItemsForWrite(true);
3391 m_host.TaskInventory[invItemID].PermsMask = answer; 3596 m_host.TaskInventory[invItemID].PermsMask = answer;
3392 } 3597 m_host.TaskInventory.LockItemsForWrite(false);
3598
3393 3599
3394 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3600 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3395 "run_time_permissions", new Object[] { 3601 "run_time_permissions", new Object[] {
@@ -3401,16 +3607,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3401 { 3607 {
3402 m_host.AddScriptLPS(1); 3608 m_host.AddScriptLPS(1);
3403 3609
3404 lock (m_host.TaskInventory) 3610 m_host.TaskInventory.LockItemsForRead(true);
3611
3612 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3405 { 3613 {
3406 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 3614 if (item.Type == 10 && item.ItemID == m_itemID)
3407 { 3615 {
3408 if (item.Type == 10 && item.ItemID == m_itemID) 3616 m_host.TaskInventory.LockItemsForRead(false);
3409 { 3617 return item.PermsGranter.ToString();
3410 return item.PermsGranter.ToString();
3411 }
3412 } 3618 }
3413 } 3619 }
3620 m_host.TaskInventory.LockItemsForRead(false);
3414 3621
3415 return UUID.Zero.ToString(); 3622 return UUID.Zero.ToString();
3416 } 3623 }
@@ -3419,19 +3626,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3419 { 3626 {
3420 m_host.AddScriptLPS(1); 3627 m_host.AddScriptLPS(1);
3421 3628
3422 lock (m_host.TaskInventory) 3629 m_host.TaskInventory.LockItemsForRead(true);
3630
3631 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3423 { 3632 {
3424 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 3633 if (item.Type == 10 && item.ItemID == m_itemID)
3425 { 3634 {
3426 if (item.Type == 10 && item.ItemID == m_itemID) 3635 int perms = item.PermsMask;
3427 { 3636 if (m_automaticLinkPermission)
3428 int perms = item.PermsMask; 3637 perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS;
3429 if (m_automaticLinkPermission) 3638 m_host.TaskInventory.LockItemsForRead(false);
3430 perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS; 3639 return perms;
3431 return perms;
3432 }
3433 } 3640 }
3434 } 3641 }
3642 m_host.TaskInventory.LockItemsForRead(false);
3435 3643
3436 return 0; 3644 return 0;
3437 } 3645 }
@@ -3464,11 +3672,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3464 UUID invItemID = InventorySelf(); 3672 UUID invItemID = InventorySelf();
3465 3673
3466 TaskInventoryItem item; 3674 TaskInventoryItem item;
3467 lock (m_host.TaskInventory) 3675 m_host.TaskInventory.LockItemsForRead(true);
3468 { 3676 item = m_host.TaskInventory[invItemID];
3469 item = m_host.TaskInventory[invItemID]; 3677 m_host.TaskInventory.LockItemsForRead(false);
3470 } 3678
3471
3472 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 3679 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
3473 && !m_automaticLinkPermission) 3680 && !m_automaticLinkPermission)
3474 { 3681 {
@@ -3521,16 +3728,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3521 m_host.AddScriptLPS(1); 3728 m_host.AddScriptLPS(1);
3522 UUID invItemID = InventorySelf(); 3729 UUID invItemID = InventorySelf();
3523 3730
3524 lock (m_host.TaskInventory) 3731 m_host.TaskInventory.LockItemsForRead(true);
3525 {
3526 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 3732 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
3527 && !m_automaticLinkPermission) 3733 && !m_automaticLinkPermission)
3528 { 3734 {
3529 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!"); 3735 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
3736 m_host.TaskInventory.LockItemsForRead(false);
3530 return; 3737 return;
3531 } 3738 }
3532 } 3739 m_host.TaskInventory.LockItemsForRead(false);
3533 3740
3534 if (linknum < ScriptBaseClass.LINK_THIS) 3741 if (linknum < ScriptBaseClass.LINK_THIS)
3535 return; 3742 return;
3536 3743
@@ -3707,17 +3914,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3707 m_host.AddScriptLPS(1); 3914 m_host.AddScriptLPS(1);
3708 int count = 0; 3915 int count = 0;
3709 3916
3710 lock (m_host.TaskInventory) 3917 m_host.TaskInventory.LockItemsForRead(true);
3918 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3711 { 3919 {
3712 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 3920 if (inv.Value.Type == type || type == -1)
3713 { 3921 {
3714 if (inv.Value.Type == type || type == -1) 3922 count = count + 1;
3715 {
3716 count = count + 1;
3717 }
3718 } 3923 }
3719 } 3924 }
3720 3925
3926 m_host.TaskInventory.LockItemsForRead(false);
3721 return count; 3927 return count;
3722 } 3928 }
3723 3929
@@ -3726,16 +3932,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3726 m_host.AddScriptLPS(1); 3932 m_host.AddScriptLPS(1);
3727 ArrayList keys = new ArrayList(); 3933 ArrayList keys = new ArrayList();
3728 3934
3729 lock (m_host.TaskInventory) 3935 m_host.TaskInventory.LockItemsForRead(true);
3936 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3730 { 3937 {
3731 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 3938 if (inv.Value.Type == type || type == -1)
3732 { 3939 {
3733 if (inv.Value.Type == type || type == -1) 3940 keys.Add(inv.Value.Name);
3734 {
3735 keys.Add(inv.Value.Name);
3736 }
3737 } 3941 }
3738 } 3942 }
3943 m_host.TaskInventory.LockItemsForRead(false);
3739 3944
3740 if (keys.Count == 0) 3945 if (keys.Count == 0)
3741 { 3946 {
@@ -3772,20 +3977,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3772 } 3977 }
3773 3978
3774 // move the first object found with this inventory name 3979 // move the first object found with this inventory name
3775 lock (m_host.TaskInventory) 3980 m_host.TaskInventory.LockItemsForRead(true);
3981 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3776 { 3982 {
3777 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 3983 if (inv.Value.Name == inventory)
3778 { 3984 {
3779 if (inv.Value.Name == inventory) 3985 found = true;
3780 { 3986 objId = inv.Key;
3781 found = true; 3987 assetType = inv.Value.Type;
3782 objId = inv.Key; 3988 objName = inv.Value.Name;
3783 assetType = inv.Value.Type; 3989 break;
3784 objName = inv.Value.Name;
3785 break;
3786 }
3787 } 3990 }
3788 } 3991 }
3992 m_host.TaskInventory.LockItemsForRead(false);
3789 3993
3790 if (!found) 3994 if (!found)
3791 { 3995 {
@@ -3793,9 +3997,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3793 throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory)); 3997 throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
3794 } 3998 }
3795 3999
3796 // check if destination is an avatar 4000 // check if destination is an object
3797 if (World.GetScenePresence(destId) != null) 4001 if (World.GetSceneObjectPart(destId) != null)
4002 {
4003 // destination is an object
4004 World.MoveTaskInventoryItem(destId, m_host, objId);
4005 }
4006 else
3798 { 4007 {
4008 ScenePresence presence = World.GetScenePresence(destId);
4009
4010 if (presence == null)
4011 {
4012 UserAccount account =
4013 World.UserAccountService.GetUserAccount(
4014 World.RegionInfo.ScopeID,
4015 destId);
4016
4017 if (account == null)
4018 {
4019 llSay(0, "Can't find destination "+destId.ToString());
4020 return;
4021 }
4022 }
4023
3799 // destination is an avatar 4024 // destination is an avatar
3800 InventoryItemBase agentItem = 4025 InventoryItemBase agentItem =
3801 World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId); 4026 World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId);
@@ -3821,33 +4046,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3821 4046
3822 if (m_TransferModule != null) 4047 if (m_TransferModule != null)
3823 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 4048 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
4049
4050 //This delay should only occur when giving inventory to avatars.
4051 ScriptSleep(3000);
3824 } 4052 }
3825 else
3826 {
3827 // destination is an object
3828 World.MoveTaskInventoryItem(destId, m_host, objId);
3829 }
3830 ScriptSleep(3000);
3831 } 4053 }
3832 4054
4055 [DebuggerNonUserCode]
3833 public void llRemoveInventory(string name) 4056 public void llRemoveInventory(string name)
3834 { 4057 {
3835 m_host.AddScriptLPS(1); 4058 m_host.AddScriptLPS(1);
3836 4059
3837 lock (m_host.TaskInventory) 4060 m_host.TaskInventory.LockItemsForRead(true);
4061 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3838 { 4062 {
3839 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4063 if (item.Name == name)
3840 { 4064 {
3841 if (item.Name == name) 4065 if (item.ItemID == m_itemID)
3842 { 4066 throw new ScriptDeleteException();
3843 if (item.ItemID == m_itemID) 4067 else
3844 throw new ScriptDeleteException(); 4068 m_host.Inventory.RemoveInventoryItem(item.ItemID);
3845 else 4069
3846 m_host.Inventory.RemoveInventoryItem(item.ItemID); 4070 m_host.TaskInventory.LockItemsForRead(false);
3847 return; 4071 return;
3848 }
3849 } 4072 }
3850 } 4073 }
4074 m_host.TaskInventory.LockItemsForRead(false);
3851 } 4075 }
3852 4076
3853 public void llSetText(string text, LSL_Vector color, double alpha) 4077 public void llSetText(string text, LSL_Vector color, double alpha)
@@ -3938,6 +4162,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3938 { 4162 {
3939 m_host.AddScriptLPS(1); 4163 m_host.AddScriptLPS(1);
3940 4164
4165 //Clone is thread safe
3941 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 4166 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
3942 4167
3943 foreach (TaskInventoryItem item in itemDictionary.Values) 4168 foreach (TaskInventoryItem item in itemDictionary.Values)
@@ -3991,6 +4216,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3991 ScenePresence presence = World.GetScenePresence(agentId); 4216 ScenePresence presence = World.GetScenePresence(agentId);
3992 if (presence != null) 4217 if (presence != null)
3993 { 4218 {
4219 // agent must not be a god
4220 if (presence.GodLevel >= 200) return;
4221
3994 // agent must be over the owners land 4222 // agent must be over the owners land
3995 if (m_host.OwnerID == World.LandChannel.GetLandObject( 4223 if (m_host.OwnerID == World.LandChannel.GetLandObject(
3996 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) 4224 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
@@ -4051,17 +4279,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4051 UUID soundId = UUID.Zero; 4279 UUID soundId = UUID.Zero;
4052 if (!UUID.TryParse(impact_sound, out soundId)) 4280 if (!UUID.TryParse(impact_sound, out soundId))
4053 { 4281 {
4054 lock (m_host.TaskInventory) 4282 m_host.TaskInventory.LockItemsForRead(true);
4283 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
4055 { 4284 {
4056 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4285 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound)
4057 { 4286 {
4058 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound) 4287 soundId = item.AssetID;
4059 { 4288 break;
4060 soundId = item.AssetID;
4061 break;
4062 }
4063 } 4289 }
4064 } 4290 }
4291 m_host.TaskInventory.LockItemsForRead(false);
4065 } 4292 }
4066 m_host.CollisionSound = soundId; 4293 m_host.CollisionSound = soundId;
4067 m_host.CollisionSoundVolume = (float)impact_volume; 4294 m_host.CollisionSoundVolume = (float)impact_volume;
@@ -4107,6 +4334,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4107 UUID partItemID; 4334 UUID partItemID;
4108 foreach (SceneObjectPart part in parts) 4335 foreach (SceneObjectPart part in parts)
4109 { 4336 {
4337 //Clone is thread safe
4110 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); 4338 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
4111 4339
4112 foreach (TaskInventoryItem item in itemsDictionary.Values) 4340 foreach (TaskInventoryItem item in itemsDictionary.Values)
@@ -4321,17 +4549,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4321 4549
4322 m_host.AddScriptLPS(1); 4550 m_host.AddScriptLPS(1);
4323 4551
4324 lock (m_host.TaskInventory) 4552 m_host.TaskInventory.LockItemsForRead(true);
4553 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
4325 { 4554 {
4326 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4555 if (item.Type == 10 && item.ItemID == m_itemID)
4327 { 4556 {
4328 if (item.Type == 10 && item.ItemID == m_itemID) 4557 result = item.Name!=null?item.Name:String.Empty;
4329 { 4558 break;
4330 result = item.Name != null ? item.Name : String.Empty;
4331 break;
4332 }
4333 } 4559 }
4334 } 4560 }
4561 m_host.TaskInventory.LockItemsForRead(false);
4335 4562
4336 return result; 4563 return result;
4337 } 4564 }
@@ -4484,23 +4711,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4484 { 4711 {
4485 m_host.AddScriptLPS(1); 4712 m_host.AddScriptLPS(1);
4486 4713
4487 lock (m_host.TaskInventory) 4714 m_host.TaskInventory.LockItemsForRead(true);
4715 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
4488 { 4716 {
4489 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4717 if (inv.Value.Name == name)
4490 { 4718 {
4491 if (inv.Value.Name == name) 4719 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
4492 { 4720 {
4493 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) 4721 m_host.TaskInventory.LockItemsForRead(false);
4494 { 4722 return inv.Value.AssetID.ToString();
4495 return inv.Value.AssetID.ToString(); 4723 }
4496 } 4724 else
4497 else 4725 {
4498 { 4726 m_host.TaskInventory.LockItemsForRead(false);
4499 return UUID.Zero.ToString(); 4727 return UUID.Zero.ToString();
4500 }
4501 } 4728 }
4502 } 4729 }
4503 } 4730 }
4731 m_host.TaskInventory.LockItemsForRead(false);
4504 4732
4505 return UUID.Zero.ToString(); 4733 return UUID.Zero.ToString();
4506 } 4734 }
@@ -6018,6 +6246,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6018 tempf = (float)rules.GetLSLFloatItem(i + 1); 6246 tempf = (float)rules.GetLSLFloatItem(i + 1);
6019 prules.OuterAngle = (float)tempf; 6247 prules.OuterAngle = (float)tempf;
6020 break; 6248 break;
6249
6250 case (int)ScriptBaseClass.PSYS_SRC_INNERANGLE:
6251 tempf = (float)rules.GetLSLFloatItem(i + 1);
6252 prules.InnerAngle = (float)tempf;
6253 break;
6254
6255 case (int)ScriptBaseClass.PSYS_SRC_OUTERANGLE:
6256 tempf = (float)rules.GetLSLFloatItem(i + 1);
6257 prules.OuterAngle = (float)tempf;
6258 break;
6021 } 6259 }
6022 6260
6023 } 6261 }
@@ -6056,14 +6294,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6056 6294
6057 protected UUID GetTaskInventoryItem(string name) 6295 protected UUID GetTaskInventoryItem(string name)
6058 { 6296 {
6059 lock (m_host.TaskInventory) 6297 m_host.TaskInventory.LockItemsForRead(true);
6298 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6060 { 6299 {
6061 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 6300 if (inv.Value.Name == name)
6062 { 6301 {
6063 if (inv.Value.Name == name) 6302 m_host.TaskInventory.LockItemsForRead(false);
6064 return inv.Key; 6303 return inv.Key;
6065 } 6304 }
6066 } 6305 }
6306 m_host.TaskInventory.LockItemsForRead(false);
6067 6307
6068 return UUID.Zero; 6308 return UUID.Zero;
6069 } 6309 }
@@ -6391,22 +6631,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6391 } 6631 }
6392 6632
6393 // copy the first script found with this inventory name 6633 // copy the first script found with this inventory name
6394 lock (m_host.TaskInventory) 6634 m_host.TaskInventory.LockItemsForRead(true);
6635 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6395 { 6636 {
6396 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 6637 if (inv.Value.Name == name)
6397 { 6638 {
6398 if (inv.Value.Name == name) 6639 // make sure the object is a script
6640 if (10 == inv.Value.Type)
6399 { 6641 {
6400 // make sure the object is a script 6642 found = true;
6401 if (10 == inv.Value.Type) 6643 srcId = inv.Key;
6402 { 6644 break;
6403 found = true;
6404 srcId = inv.Key;
6405 break;
6406 }
6407 } 6645 }
6408 } 6646 }
6409 } 6647 }
6648 m_host.TaskInventory.LockItemsForRead(false);
6410 6649
6411 if (!found) 6650 if (!found)
6412 { 6651 {
@@ -6490,6 +6729,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6490 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist) 6729 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist)
6491 { 6730 {
6492 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 6731 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
6732 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
6733 return shapeBlock;
6493 6734
6494 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && 6735 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
6495 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && 6736 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
@@ -6560,6 +6801,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6560 6801
6561 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte fudge) 6802 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte fudge)
6562 { 6803 {
6804 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
6805 return;
6806
6563 ObjectShapePacket.ObjectDataBlock shapeBlock; 6807 ObjectShapePacket.ObjectDataBlock shapeBlock;
6564 6808
6565 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist); 6809 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist);
@@ -6609,6 +6853,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6609 6853
6610 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte fudge) 6854 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte fudge)
6611 { 6855 {
6856 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
6857 return;
6858
6612 ObjectShapePacket.ObjectDataBlock shapeBlock; 6859 ObjectShapePacket.ObjectDataBlock shapeBlock;
6613 6860
6614 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist); 6861 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist);
@@ -6651,6 +6898,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6651 6898
6652 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector holesize, LSL_Vector topshear, LSL_Vector profilecut, LSL_Vector taper_a, float revolutions, float radiusoffset, float skew, byte fudge) 6899 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector holesize, LSL_Vector topshear, LSL_Vector profilecut, LSL_Vector taper_a, float revolutions, float radiusoffset, float skew, byte fudge)
6653 { 6900 {
6901 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
6902 return;
6903
6654 ObjectShapePacket.ObjectDataBlock shapeBlock; 6904 ObjectShapePacket.ObjectDataBlock shapeBlock;
6655 6905
6656 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist); 6906 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist);
@@ -6772,6 +7022,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6772 7022
6773 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type) 7023 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type)
6774 { 7024 {
7025 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7026 return;
7027
6775 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7028 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
6776 UUID sculptId; 7029 UUID sculptId;
6777 7030
@@ -6812,7 +7065,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6812 7065
6813 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) 7066 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
6814 { 7067 {
6815 m_host.AddScriptLPS(1); 7068 m_host.AddScriptLPS(1);
6816 7069
6817 List<SceneObjectPart> parts = GetLinkParts(linknumber); 7070 List<SceneObjectPart> parts = GetLinkParts(linknumber);
6818 7071
@@ -6827,6 +7080,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6827 7080
6828 protected void SetPrimParams(SceneObjectPart part, LSL_List rules) 7081 protected void SetPrimParams(SceneObjectPart part, LSL_List rules)
6829 { 7082 {
7083 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7084 return;
7085
6830 int idx = 0; 7086 int idx = 0;
6831 7087
6832 while (idx < rules.Length) 7088 while (idx < rules.Length)
@@ -7658,24 +7914,95 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7658 break; 7914 break;
7659 7915
7660 case (int)ScriptBaseClass.PRIM_BUMP_SHINY: 7916 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
7661 // TODO--------------
7662 if (remain < 1) 7917 if (remain < 1)
7663 return res; 7918 return res;
7919 face = (int)rules.GetLSLIntegerItem(idx++);
7664 7920
7665 face=(int)rules.GetLSLIntegerItem(idx++); 7921 tex = part.Shape.Textures;
7666 7922 int shiny;
7667 res.Add(new LSL_Integer(0)); 7923 if (face == ScriptBaseClass.ALL_SIDES)
7668 res.Add(new LSL_Integer(0)); 7924 {
7925 for (face = 0; face < GetNumberOfSides(part); face++)
7926 {
7927 Shininess shinyness = tex.GetFace((uint)face).Shiny;
7928 if (shinyness == Shininess.High)
7929 {
7930 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
7931 }
7932 else if (shinyness == Shininess.Medium)
7933 {
7934 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
7935 }
7936 else if (shinyness == Shininess.Low)
7937 {
7938 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
7939 }
7940 else
7941 {
7942 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
7943 }
7944 res.Add(new LSL_Integer(shiny));
7945 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
7946 }
7947 }
7948 else
7949 {
7950 Shininess shinyness = tex.GetFace((uint)face).Shiny;
7951 if (shinyness == Shininess.High)
7952 {
7953 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
7954 }
7955 else if (shinyness == Shininess.Medium)
7956 {
7957 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
7958 }
7959 else if (shinyness == Shininess.Low)
7960 {
7961 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
7962 }
7963 else
7964 {
7965 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
7966 }
7967 res.Add(new LSL_Integer(shiny));
7968 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
7969 }
7669 break; 7970 break;
7670 7971
7671 case (int)ScriptBaseClass.PRIM_FULLBRIGHT: 7972 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
7672 // TODO--------------
7673 if (remain < 1) 7973 if (remain < 1)
7674 return res; 7974 return res;
7975 face = (int)rules.GetLSLIntegerItem(idx++);
7675 7976
7676 face=(int)rules.GetLSLIntegerItem(idx++); 7977 tex = part.Shape.Textures;
7677 7978 int fullbright;
7678 res.Add(new LSL_Integer(0)); 7979 if (face == ScriptBaseClass.ALL_SIDES)
7980 {
7981 for (face = 0; face < GetNumberOfSides(part); face++)
7982 {
7983 if (tex.GetFace((uint)face).Fullbright == true)
7984 {
7985 fullbright = ScriptBaseClass.TRUE;
7986 }
7987 else
7988 {
7989 fullbright = ScriptBaseClass.FALSE;
7990 }
7991 res.Add(new LSL_Integer(fullbright));
7992 }
7993 }
7994 else
7995 {
7996 if (tex.GetFace((uint)face).Fullbright == true)
7997 {
7998 fullbright = ScriptBaseClass.TRUE;
7999 }
8000 else
8001 {
8002 fullbright = ScriptBaseClass.FALSE;
8003 }
8004 res.Add(new LSL_Integer(fullbright));
8005 }
7679 break; 8006 break;
7680 8007
7681 case (int)ScriptBaseClass.PRIM_FLEXIBLE: 8008 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
@@ -7696,14 +8023,37 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7696 break; 8023 break;
7697 8024
7698 case (int)ScriptBaseClass.PRIM_TEXGEN: 8025 case (int)ScriptBaseClass.PRIM_TEXGEN:
7699 // TODO--------------
7700 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR) 8026 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
7701 if (remain < 1) 8027 if (remain < 1)
7702 return res; 8028 return res;
8029 face = (int)rules.GetLSLIntegerItem(idx++);
7703 8030
7704 face=(int)rules.GetLSLIntegerItem(idx++); 8031 tex = part.Shape.Textures;
7705 8032 if (face == ScriptBaseClass.ALL_SIDES)
7706 res.Add(new LSL_Integer(0)); 8033 {
8034 for (face = 0; face < GetNumberOfSides(part); face++)
8035 {
8036 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8037 {
8038 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8039 }
8040 else
8041 {
8042 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8043 }
8044 }
8045 }
8046 else
8047 {
8048 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8049 {
8050 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8051 }
8052 else
8053 {
8054 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8055 }
8056 }
7707 break; 8057 break;
7708 8058
7709 case (int)ScriptBaseClass.PRIM_POINT_LIGHT: 8059 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
@@ -7722,13 +8072,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7722 break; 8072 break;
7723 8073
7724 case (int)ScriptBaseClass.PRIM_GLOW: 8074 case (int)ScriptBaseClass.PRIM_GLOW:
7725 // TODO--------------
7726 if (remain < 1) 8075 if (remain < 1)
7727 return res; 8076 return res;
8077 face = (int)rules.GetLSLIntegerItem(idx++);
7728 8078
7729 face=(int)rules.GetLSLIntegerItem(idx++); 8079 tex = part.Shape.Textures;
7730 8080 float primglow;
7731 res.Add(new LSL_Float(0)); 8081 if (face == ScriptBaseClass.ALL_SIDES)
8082 {
8083 for (face = 0; face < GetNumberOfSides(part); face++)
8084 {
8085 primglow = tex.GetFace((uint)face).Glow;
8086 res.Add(new LSL_Float(primglow));
8087 }
8088 }
8089 else
8090 {
8091 primglow = tex.GetFace((uint)face).Glow;
8092 res.Add(new LSL_Float(primglow));
8093 }
7732 break; 8094 break;
7733 case (int)ScriptBaseClass.PRIM_TEXT: 8095 case (int)ScriptBaseClass.PRIM_TEXT:
7734 Color4 textColor = part.GetTextColor(); 8096 Color4 textColor = part.GetTextColor();
@@ -8265,28 +8627,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8265 { 8627 {
8266 m_host.AddScriptLPS(1); 8628 m_host.AddScriptLPS(1);
8267 8629
8268 lock (m_host.TaskInventory) 8630 m_host.TaskInventory.LockItemsForRead(true);
8631 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
8269 { 8632 {
8270 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 8633 if (inv.Value.Name == item)
8271 { 8634 {
8272 if (inv.Value.Name == item) 8635 m_host.TaskInventory.LockItemsForRead(false);
8636 switch (mask)
8273 { 8637 {
8274 switch (mask) 8638 case 0:
8275 { 8639 return (int)inv.Value.BasePermissions;
8276 case 0: 8640 case 1:
8277 return (int)inv.Value.BasePermissions; 8641 return (int)inv.Value.CurrentPermissions;
8278 case 1: 8642 case 2:
8279 return (int)inv.Value.CurrentPermissions; 8643 return (int)inv.Value.GroupPermissions;
8280 case 2: 8644 case 3:
8281 return (int)inv.Value.GroupPermissions; 8645 return (int)inv.Value.EveryonePermissions;
8282 case 3: 8646 case 4:
8283 return (int)inv.Value.EveryonePermissions; 8647 return (int)inv.Value.NextPermissions;
8284 case 4:
8285 return (int)inv.Value.NextPermissions;
8286 }
8287 } 8648 }
8288 } 8649 }
8289 } 8650 }
8651 m_host.TaskInventory.LockItemsForRead(false);
8290 8652
8291 return -1; 8653 return -1;
8292 } 8654 }
@@ -8333,16 +8695,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8333 { 8695 {
8334 m_host.AddScriptLPS(1); 8696 m_host.AddScriptLPS(1);
8335 8697
8336 lock (m_host.TaskInventory) 8698 m_host.TaskInventory.LockItemsForRead(true);
8699 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
8337 { 8700 {
8338 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 8701 if (inv.Value.Name == item)
8339 { 8702 {
8340 if (inv.Value.Name == item) 8703 m_host.TaskInventory.LockItemsForRead(false);
8341 { 8704 return inv.Value.CreatorID.ToString();
8342 return inv.Value.CreatorID.ToString();
8343 }
8344 } 8705 }
8345 } 8706 }
8707 m_host.TaskInventory.LockItemsForRead(false);
8346 8708
8347 llSay(0, "No item name '" + item + "'"); 8709 llSay(0, "No item name '" + item + "'");
8348 8710
@@ -8875,16 +9237,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8875 { 9237 {
8876 m_host.AddScriptLPS(1); 9238 m_host.AddScriptLPS(1);
8877 9239
8878 lock (m_host.TaskInventory) 9240 m_host.TaskInventory.LockItemsForRead(true);
9241 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
8879 { 9242 {
8880 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9243 if (inv.Value.Name == name)
8881 { 9244 {
8882 if (inv.Value.Name == name) 9245 m_host.TaskInventory.LockItemsForRead(false);
8883 { 9246 return inv.Value.Type;
8884 return inv.Value.Type;
8885 }
8886 } 9247 }
8887 } 9248 }
9249 m_host.TaskInventory.LockItemsForRead(false);
8888 9250
8889 return -1; 9251 return -1;
8890 } 9252 }
@@ -8895,15 +9257,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8895 9257
8896 if (quick_pay_buttons.Data.Length < 4) 9258 if (quick_pay_buttons.Data.Length < 4)
8897 { 9259 {
8898 LSLError("List must have at least 4 elements"); 9260 int x;
8899 return; 9261 for (x=quick_pay_buttons.Data.Length; x<= 4; x++)
9262 {
9263 quick_pay_buttons.Add(ScriptBaseClass.PAY_HIDE);
9264 }
8900 } 9265 }
8901 m_host.ParentGroup.RootPart.PayPrice[0]=price; 9266 int[] nPrice = new int[5];
8902 9267 nPrice[0]=price;
8903 m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; 9268 nPrice[1] = (LSL_Integer)quick_pay_buttons.Data[0];
8904 m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; 9269 nPrice[2] = (LSL_Integer)quick_pay_buttons.Data[1];
8905 m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; 9270 nPrice[3] = (LSL_Integer)quick_pay_buttons.Data[2];
8906 m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; 9271 nPrice[4] = (LSL_Integer)quick_pay_buttons.Data[3];
9272 m_host.ParentGroup.RootPart.PayPrice = nPrice;
8907 m_host.ParentGroup.HasGroupChanged = true; 9273 m_host.ParentGroup.HasGroupChanged = true;
8908 } 9274 }
8909 9275
@@ -8915,17 +9281,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8915 if (invItemID == UUID.Zero) 9281 if (invItemID == UUID.Zero)
8916 return new LSL_Vector(); 9282 return new LSL_Vector();
8917 9283
8918 lock (m_host.TaskInventory) 9284 m_host.TaskInventory.LockItemsForRead(true);
9285 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
8919 { 9286 {
8920 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) 9287 m_host.TaskInventory.LockItemsForRead(false);
8921 return new LSL_Vector(); 9288 return new LSL_Vector();
9289 }
8922 9290
8923 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) 9291 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
8924 { 9292 {
8925 ShoutError("No permissions to track the camera"); 9293 ShoutError("No permissions to track the camera");
8926 return new LSL_Vector(); 9294 m_host.TaskInventory.LockItemsForRead(false);
8927 } 9295 return new LSL_Vector();
8928 } 9296 }
9297 m_host.TaskInventory.LockItemsForRead(false);
8929 9298
8930 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 9299 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
8931 if (presence != null) 9300 if (presence != null)
@@ -8943,17 +9312,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8943 if (invItemID == UUID.Zero) 9312 if (invItemID == UUID.Zero)
8944 return new LSL_Rotation(); 9313 return new LSL_Rotation();
8945 9314
8946 lock (m_host.TaskInventory) 9315 m_host.TaskInventory.LockItemsForRead(true);
9316 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
8947 { 9317 {
8948 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) 9318 m_host.TaskInventory.LockItemsForRead(false);
8949 return new LSL_Rotation(); 9319 return new LSL_Rotation();
8950 9320 }
8951 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) 9321 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
8952 { 9322 {
8953 ShoutError("No permissions to track the camera"); 9323 ShoutError("No permissions to track the camera");
8954 return new LSL_Rotation(); 9324 m_host.TaskInventory.LockItemsForRead(false);
8955 } 9325 return new LSL_Rotation();
8956 } 9326 }
9327 m_host.TaskInventory.LockItemsForRead(false);
8957 9328
8958 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 9329 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
8959 if (presence != null) 9330 if (presence != null)
@@ -9103,14 +9474,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9103 if (objectID == UUID.Zero) return; 9474 if (objectID == UUID.Zero) return;
9104 9475
9105 UUID agentID; 9476 UUID agentID;
9106 lock (m_host.TaskInventory) 9477 m_host.TaskInventory.LockItemsForRead(true);
9107 { 9478 // we need the permission first, to know which avatar we want to set the camera for
9108 // we need the permission first, to know which avatar we want to set the camera for 9479 agentID = m_host.TaskInventory[invItemID].PermsGranter;
9109 agentID = m_host.TaskInventory[invItemID].PermsGranter;
9110 9480
9111 if (agentID == UUID.Zero) return; 9481 if (agentID == UUID.Zero)
9112 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return; 9482 {
9483 m_host.TaskInventory.LockItemsForRead(false);
9484 return;
9485 }
9486 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0)
9487 {
9488 m_host.TaskInventory.LockItemsForRead(false);
9489 return;
9113 } 9490 }
9491 m_host.TaskInventory.LockItemsForRead(false);
9114 9492
9115 ScenePresence presence = World.GetScenePresence(agentID); 9493 ScenePresence presence = World.GetScenePresence(agentID);
9116 9494
@@ -9160,12 +9538,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9160 9538
9161 // we need the permission first, to know which avatar we want to clear the camera for 9539 // we need the permission first, to know which avatar we want to clear the camera for
9162 UUID agentID; 9540 UUID agentID;
9163 lock (m_host.TaskInventory) 9541 m_host.TaskInventory.LockItemsForRead(true);
9542 agentID = m_host.TaskInventory[invItemID].PermsGranter;
9543 if (agentID == UUID.Zero)
9164 { 9544 {
9165 agentID = m_host.TaskInventory[invItemID].PermsGranter; 9545 m_host.TaskInventory.LockItemsForRead(false);
9166 if (agentID == UUID.Zero) return; 9546 return;
9167 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return;
9168 } 9547 }
9548 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0)
9549 {
9550 m_host.TaskInventory.LockItemsForRead(false);
9551 return;
9552 }
9553 m_host.TaskInventory.LockItemsForRead(false);
9169 9554
9170 ScenePresence presence = World.GetScenePresence(agentID); 9555 ScenePresence presence = World.GetScenePresence(agentID);
9171 9556
@@ -9622,15 +10007,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9622 10007
9623 internal UUID ScriptByName(string name) 10008 internal UUID ScriptByName(string name)
9624 { 10009 {
9625 lock (m_host.TaskInventory) 10010 m_host.TaskInventory.LockItemsForRead(true);
10011
10012 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
9626 { 10013 {
9627 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 10014 if (item.Type == 10 && item.Name == name)
9628 { 10015 {
9629 if (item.Type == 10 && item.Name == name) 10016 m_host.TaskInventory.LockItemsForRead(false);
9630 return item.ItemID; 10017 return item.ItemID;
9631 } 10018 }
9632 } 10019 }
9633 10020
10021 m_host.TaskInventory.LockItemsForRead(false);
10022
9634 return UUID.Zero; 10023 return UUID.Zero;
9635 } 10024 }
9636 10025
@@ -9671,6 +10060,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9671 { 10060 {
9672 m_host.AddScriptLPS(1); 10061 m_host.AddScriptLPS(1);
9673 10062
10063 //Clone is thread safe
9674 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 10064 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
9675 10065
9676 UUID assetID = UUID.Zero; 10066 UUID assetID = UUID.Zero;
@@ -9733,6 +10123,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9733 { 10123 {
9734 m_host.AddScriptLPS(1); 10124 m_host.AddScriptLPS(1);
9735 10125
10126 //Clone is thread safe
9736 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 10127 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
9737 10128
9738 UUID assetID = UUID.Zero; 10129 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 15469db..942e4ef 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -719,18 +719,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
719 if (target != null) 719 if (target != null)
720 { 720 {
721 UUID animID=UUID.Zero; 721 UUID animID=UUID.Zero;
722 lock (m_host.TaskInventory) 722 m_host.TaskInventory.LockItemsForRead(true);
723 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
723 { 724 {
724 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 725 if (inv.Value.Name == animation)
725 { 726 {
726 if (inv.Value.Name == animation) 727 if (inv.Value.Type == (int)AssetType.Animation)
727 { 728 animID = inv.Value.AssetID;
728 if (inv.Value.Type == (int)AssetType.Animation) 729 continue;
729 animID = inv.Value.AssetID;
730 continue;
731 }
732 } 730 }
733 } 731 }
732 m_host.TaskInventory.LockItemsForRead(false);
734 if (animID == UUID.Zero) 733 if (animID == UUID.Zero)
735 target.Animator.AddAnimation(animation, m_host.UUID); 734 target.Animator.AddAnimation(animation, m_host.UUID);
736 else 735 else
@@ -752,18 +751,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
752 if (target != null) 751 if (target != null)
753 { 752 {
754 UUID animID=UUID.Zero; 753 UUID animID=UUID.Zero;
755 lock (m_host.TaskInventory) 754 m_host.TaskInventory.LockItemsForRead(true);
755 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
756 { 756 {
757 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 757 if (inv.Value.Name == animation)
758 { 758 {
759 if (inv.Value.Name == animation) 759 if (inv.Value.Type == (int)AssetType.Animation)
760 { 760 animID = inv.Value.AssetID;
761 if (inv.Value.Type == (int)AssetType.Animation) 761 continue;
762 animID = inv.Value.AssetID;
763 continue;
764 }
765 } 762 }
766 } 763 }
764 m_host.TaskInventory.LockItemsForRead(false);
767 765
768 if (animID == UUID.Zero) 766 if (animID == UUID.Zero)
769 target.Animator.RemoveAnimation(animation); 767 target.Animator.RemoveAnimation(animation);
@@ -1614,6 +1612,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1614 1612
1615 if (!UUID.TryParse(name, out assetID)) 1613 if (!UUID.TryParse(name, out assetID))
1616 { 1614 {
1615 m_host.TaskInventory.LockItemsForRead(true);
1617 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 1616 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
1618 { 1617 {
1619 if (item.Type == 7 && item.Name == name) 1618 if (item.Type == 7 && item.Name == name)
@@ -1621,6 +1620,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1621 assetID = item.AssetID; 1620 assetID = item.AssetID;
1622 } 1621 }
1623 } 1622 }
1623 m_host.TaskInventory.LockItemsForRead(false);
1624 } 1624 }
1625 1625
1626 if (assetID == UUID.Zero) 1626 if (assetID == UUID.Zero)
@@ -1667,6 +1667,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1667 1667
1668 if (!UUID.TryParse(name, out assetID)) 1668 if (!UUID.TryParse(name, out assetID))
1669 { 1669 {
1670 m_host.TaskInventory.LockItemsForRead(true);
1670 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 1671 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
1671 { 1672 {
1672 if (item.Type == 7 && item.Name == name) 1673 if (item.Type == 7 && item.Name == name)
@@ -1674,6 +1675,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1674 assetID = item.AssetID; 1675 assetID = item.AssetID;
1675 } 1676 }
1676 } 1677 }
1678 m_host.TaskInventory.LockItemsForRead(false);
1677 } 1679 }
1678 1680
1679 if (assetID == UUID.Zero) 1681 if (assetID == UUID.Zero)
@@ -1724,6 +1726,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1724 1726
1725 if (!UUID.TryParse(name, out assetID)) 1727 if (!UUID.TryParse(name, out assetID))
1726 { 1728 {
1729 m_host.TaskInventory.LockItemsForRead(true);
1727 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 1730 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
1728 { 1731 {
1729 if (item.Type == 7 && item.Name == name) 1732 if (item.Type == 7 && item.Name == name)
@@ -1731,6 +1734,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1731 assetID = item.AssetID; 1734 assetID = item.AssetID;
1732 } 1735 }
1733 } 1736 }
1737 m_host.TaskInventory.LockItemsForRead(false);
1734 } 1738 }
1735 1739
1736 if (assetID == UUID.Zero) 1740 if (assetID == UUID.Zero)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
index 5c2abd5..a5b1124 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
@@ -204,7 +204,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
204 // Is the sensor type is AGENT and not SCRIPTED then include agents 204 // Is the sensor type is AGENT and not SCRIPTED then include agents
205 if ((ts.type & AGENT) != 0 && (ts.type & SCRIPTED) == 0) 205 if ((ts.type & AGENT) != 0 && (ts.type & SCRIPTED) == 0)
206 { 206 {
207 sensedEntities.AddRange(doAgentSensor(ts)); 207 sensedEntities.AddRange(doAgentSensor(ts));
208 } 208 }
209 209
210 // If SCRIPTED or PASSIVE or ACTIVE check objects 210 // If SCRIPTED or PASSIVE or ACTIVE check objects
@@ -309,6 +309,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
309 // in mouselook. 309 // in mouselook.
310 310
311 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.RootPart.AttachedAvatar); 311 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.RootPart.AttachedAvatar);
312 fromRegionPos = avatar.AbsolutePosition;
312 q = avatar.Rotation; 313 q = avatar.Rotation;
313 } 314 }
314 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); 315 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W);
@@ -422,6 +423,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
422 SceneObjectPart SensePoint = ts.host; 423 SceneObjectPart SensePoint = ts.host;
423 Vector3 fromRegionPos = SensePoint.AbsolutePosition; 424 Vector3 fromRegionPos = SensePoint.AbsolutePosition;
424 Quaternion q = SensePoint.RotationOffset; 425 Quaternion q = SensePoint.RotationOffset;
426 if (SensePoint.ParentGroup.RootPart.IsAttachment)
427 {
428 // In attachments, the sensor cone always orients with the
429 // avatar rotation. This may include a nonzero elevation if
430 // in mouselook.
431
432 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.RootPart.AttachedAvatar);
433 fromRegionPos = avatar.AbsolutePosition;
434 q = avatar.Rotation;
435 }
425 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); 436 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W);
426 LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r); 437 LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r);
427 double mag_fwd = LSL_Types.Vector3.Mag(forward_dir); 438 double mag_fwd = LSL_Types.Vector3.Mag(forward_dir);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs
index eeb59d9..2fd33fe 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs
@@ -109,25 +109,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
109 if (Timers.Count == 0) 109 if (Timers.Count == 0)
110 return; 110 return;
111 111
112 Dictionary<string, TimerClass>.ValueCollection tvals;
112 lock (TimerListLock) 113 lock (TimerListLock)
113 { 114 {
114 // Go through all timers 115 // Go through all timers
115 Dictionary<string, TimerClass>.ValueCollection tvals = Timers.Values; 116 tvals = Timers.Values;
116 foreach (TimerClass ts in tvals) 117 }
118
119 foreach (TimerClass ts in tvals)
120 {
121 // Time has passed?
122 if (ts.next < DateTime.Now.Ticks)
117 { 123 {
118 // Time has passed? 124 //m_log.Debug("Time has passed: Now: " + DateTime.Now.Ticks + ", Passed: " + ts.next);
119 if (ts.next < DateTime.Now.Ticks) 125 // Add it to queue
120 { 126 m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID,
121 //m_log.Debug("Time has passed: Now: " + DateTime.Now.Ticks + ", Passed: " + ts.next); 127 new EventParams("timer", new Object[0],
122 // Add it to queue 128 new DetectParams[0]));
123 m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID, 129 // set next interval
124 new EventParams("timer", new Object[0], 130
125 new DetectParams[0])); 131 //ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
126 // set next interval 132 ts.next = DateTime.Now.Ticks + ts.interval;
127
128 //ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
129 ts.next = DateTime.Now.Ticks + ts.interval;
130 }
131 } 133 }
132 } 134 }
133 } 135 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs
index f13b6e5..fba27f9 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs
@@ -44,5 +44,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
44 LSL_List cmGetWindlightScene(LSL_List rules); 44 LSL_List cmGetWindlightScene(LSL_List rules);
45 int cmSetWindlightScene(LSL_List rules); 45 int cmSetWindlightScene(LSL_List rules);
46 int cmSetWindlightSceneTargeted(LSL_List rules, key target); 46 int cmSetWindlightSceneTargeted(LSL_List rules, key target);
47 LSL_List cmGetAvatarList();
47 } 48 }
48} 49}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index 7a8f469..9dbd369 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -80,7 +80,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
80 // Avatar Info Commands 80 // Avatar Info Commands
81 string osGetAgentIP(string agent); 81 string osGetAgentIP(string agent);
82 LSL_List osGetAgents(); 82 LSL_List osGetAgents();
83 83
84 // Teleport commands 84 // Teleport commands
85 void osTeleportAgent(string agent, string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat); 85 void osTeleportAgent(string agent, string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat);
86 void osTeleportAgent(string agent, int regionX, int regionY, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat); 86 void osTeleportAgent(string agent, int regionX, int regionY, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs
index c0edaae..aaffbe4 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs
@@ -72,5 +72,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
72 { 72 {
73 return m_CM_Functions.cmSetWindlightSceneTargeted(rules, target); 73 return m_CM_Functions.cmSetWindlightSceneTargeted(rules, target);
74 } 74 }
75 public LSL_List cmGetAvatarList()
76 {
77 return m_CM_Functions.cmGetAvatarList();
78 }
75 } 79 }
76} 80}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs
index 9615315..943d7a2 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;
@@ -132,6 +133,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
132 return (eventFlags); 133 return (eventFlags);
133 } 134 }
134 135
136 [DebuggerNonUserCode]
135 public void ExecuteEvent(string state, string FunctionName, object[] args) 137 public void ExecuteEvent(string state, string FunctionName, object[] args)
136 { 138 {
137 // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory. 139 // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory.
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
index dba6502..96f6486 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
@@ -274,6 +274,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
274 public const int CHANGED_ALLOWED_DROP = 64; 274 public const int CHANGED_ALLOWED_DROP = 64;
275 public const int CHANGED_OWNER = 128; 275 public const int CHANGED_OWNER = 128;
276 public const int CHANGED_REGION_RESTART = 256; 276 public const int CHANGED_REGION_RESTART = 256;
277 public const int CHANGED_REGION_START = 256; //LL Changed the constant from CHANGED_REGION_RESTART
277 public const int CHANGED_REGION = 512; 278 public const int CHANGED_REGION = 512;
278 public const int CHANGED_TELEPORT = 1024; 279 public const int CHANGED_TELEPORT = 1024;
279 public const int CHANGED_ANIMATION = 16384; 280 public const int CHANGED_ANIMATION = 16384;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
index 3339995..e86d08c 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Diagnostics; //for [DebuggerNonUserCode]
29using System.Runtime.Remoting.Lifetime; 30using System.Runtime.Remoting.Lifetime;
30using System.Threading; 31using System.Threading;
31using System.Reflection; 32using System.Reflection;
@@ -309,6 +310,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
309 m_LSL_Functions.llDialog(avatar, message, buttons, chat_channel); 310 m_LSL_Functions.llDialog(avatar, message, buttons, chat_channel);
310 } 311 }
311 312
313 [DebuggerNonUserCode]
312 public void llDie() 314 public void llDie()
313 { 315 {
314 m_LSL_Functions.llDie(); 316 m_LSL_Functions.llDie();
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs
index edbbc2a..b138da3 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 3dd381d..b348403 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;
@@ -238,13 +239,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
238 239
239 if (part != null) 240 if (part != null)
240 { 241 {
241 lock (part.TaskInventory) 242 part.TaskInventory.LockItemsForRead(true);
243 if (part.TaskInventory.ContainsKey(m_ItemID))
242 { 244 {
243 if (part.TaskInventory.ContainsKey(m_ItemID)) 245 m_thisScriptTask = part.TaskInventory[m_ItemID];
244 {
245 m_thisScriptTask = part.TaskInventory[m_ItemID];
246 }
247 } 246 }
247 part.TaskInventory.LockItemsForRead(false);
248 } 248 }
249 249
250 ApiManager am = new ApiManager(); 250 ApiManager am = new ApiManager();
@@ -429,14 +429,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
429 { 429 {
430 int permsMask; 430 int permsMask;
431 UUID permsGranter; 431 UUID permsGranter;
432 lock (part.TaskInventory) 432 part.TaskInventory.LockItemsForRead(true);
433 if (!part.TaskInventory.ContainsKey(m_ItemID))
433 { 434 {
434 if (!part.TaskInventory.ContainsKey(m_ItemID)) 435 part.TaskInventory.LockItemsForRead(false);
435 return; 436 return;
436
437 permsGranter = part.TaskInventory[m_ItemID].PermsGranter;
438 permsMask = part.TaskInventory[m_ItemID].PermsMask;
439 } 437 }
438 permsGranter = part.TaskInventory[m_ItemID].PermsGranter;
439 permsMask = part.TaskInventory[m_ItemID].PermsMask;
440 part.TaskInventory.LockItemsForRead(false);
440 441
441 if ((permsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0) 442 if ((permsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)
442 { 443 {
@@ -545,6 +546,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
545 return true; 546 return true;
546 } 547 }
547 548
549 [DebuggerNonUserCode] //Prevents the debugger from farting in this function
548 public void SetState(string state) 550 public void SetState(string state)
549 { 551 {
550 if (state == State) 552 if (state == State)
@@ -556,7 +558,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
556 new DetectParams[0])); 558 new DetectParams[0]));
557 PostEvent(new EventParams("state_entry", new Object[0], 559 PostEvent(new EventParams("state_entry", new Object[0],
558 new DetectParams[0])); 560 new DetectParams[0]));
559 561
560 throw new EventAbortException(); 562 throw new EventAbortException();
561 } 563 }
562 564
@@ -639,14 +641,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
639 /// <returns></returns> 641 /// <returns></returns>
640 public object EventProcessor() 642 public object EventProcessor()
641 { 643 {
642 if (m_Suspended) 644 EventParams data = null;
643 return 0;
644 645
645 lock (m_Script) 646 lock (m_EventQueue)
646 { 647 {
647 EventParams data = null; 648 if (m_Suspended)
649 return 0;
648 650
649 lock (m_EventQueue) 651 lock (m_Script)
650 { 652 {
651 data = (EventParams) m_EventQueue.Dequeue(); 653 data = (EventParams) m_EventQueue.Dequeue();
652 if (data == null) // Shouldn't happen 654 if (data == null) // Shouldn't happen
@@ -672,6 +674,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
672 if (data.EventName == "collision") 674 if (data.EventName == "collision")
673 m_CollisionInQueue = false; 675 m_CollisionInQueue = false;
674 } 676 }
677 }
678 lock(m_Script)
679 {
675 680
676 //m_log.DebugFormat("[XENGINE]: Processing event {0} for {1}", data.EventName, this); 681 //m_log.DebugFormat("[XENGINE]: Processing event {0} for {1}", data.EventName, this);
677 682
@@ -828,6 +833,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
828 new Object[0], new DetectParams[0])); 833 new Object[0], new DetectParams[0]));
829 } 834 }
830 835
836 [DebuggerNonUserCode] //Stops the VS debugger from farting in this function
831 public void ApiResetScript() 837 public void ApiResetScript()
832 { 838 {
833 // bool running = Running; 839 // bool running = Running;
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 54074ed..463b052 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;
@@ -102,6 +103,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
102 private Dictionary<UUID, IScriptInstance> m_Scripts = 103 private Dictionary<UUID, IScriptInstance> m_Scripts =
103 new Dictionary<UUID, IScriptInstance>(); 104 new Dictionary<UUID, IScriptInstance>();
104 105
106 private OpenMetaverse.ReaderWriterLockSlim m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
107
105 // Maps the asset ID to the assembly 108 // Maps the asset ID to the assembly
106 109
107 private Dictionary<UUID, string> m_Assemblies = 110 private Dictionary<UUID, string> m_Assemblies =
@@ -123,6 +126,71 @@ namespace OpenSim.Region.ScriptEngine.XEngine
123 private ScriptCompileQueue m_CompileQueue = new ScriptCompileQueue(); 126 private ScriptCompileQueue m_CompileQueue = new ScriptCompileQueue();
124 IWorkItemResult m_CurrentCompile = null; 127 IWorkItemResult m_CurrentCompile = null;
125 128
129 private void lockScriptsForRead(bool locked)
130 {
131 if (locked)
132 {
133 if (m_scriptsLock.RecursiveReadCount > 0)
134 {
135 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.");
136 m_scriptsLock.ExitReadLock();
137 }
138 if (m_scriptsLock.RecursiveWriteCount > 0)
139 {
140 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
141 m_scriptsLock.ExitWriteLock();
142 }
143
144 while (!m_scriptsLock.TryEnterReadLock(60000))
145 {
146 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.");
147 if (m_scriptsLock.IsWriteLockHeld)
148 {
149 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
150 }
151 }
152 }
153 else
154 {
155 if (m_scriptsLock.RecursiveReadCount > 0)
156 {
157 m_scriptsLock.ExitReadLock();
158 }
159 }
160 }
161 private void lockScriptsForWrite(bool locked)
162 {
163 if (locked)
164 {
165 if (m_scriptsLock.RecursiveReadCount > 0)
166 {
167 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.");
168 m_scriptsLock.ExitReadLock();
169 }
170 if (m_scriptsLock.RecursiveWriteCount > 0)
171 {
172 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
173 m_scriptsLock.ExitWriteLock();
174 }
175
176 while (!m_scriptsLock.TryEnterWriteLock(60000))
177 {
178 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.");
179 if (m_scriptsLock.IsWriteLockHeld)
180 {
181 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
182 }
183 }
184 }
185 else
186 {
187 if (m_scriptsLock.RecursiveWriteCount > 0)
188 {
189 m_scriptsLock.ExitWriteLock();
190 }
191 }
192 }
193
126 public string ScriptEngineName 194 public string ScriptEngineName
127 { 195 {
128 get { return "XEngine"; } 196 get { return "XEngine"; }
@@ -262,43 +330,45 @@ namespace OpenSim.Region.ScriptEngine.XEngine
262 330
263 public void RemoveRegion(Scene scene) 331 public void RemoveRegion(Scene scene)
264 { 332 {
265 lock (m_Scripts) 333 lockScriptsForRead(true);
334 foreach (IScriptInstance instance in m_Scripts.Values)
266 { 335 {
267 foreach (IScriptInstance instance in m_Scripts.Values) 336 // Force a final state save
337 //
338 if (m_Assemblies.ContainsKey(instance.AssetID))
268 { 339 {
269 // Force a final state save 340 string assembly = m_Assemblies[instance.AssetID];
270 // 341 instance.SaveState(assembly);
271 if (m_Assemblies.ContainsKey(instance.AssetID)) 342 }
272 {
273 string assembly = m_Assemblies[instance.AssetID];
274 instance.SaveState(assembly);
275 }
276 343
277 // Clear the event queue and abort the instance thread 344 // Clear the event queue and abort the instance thread
278 // 345 //
279 instance.ClearQueue(); 346 instance.ClearQueue();
280 instance.Stop(0); 347 instance.Stop(0);
281 348
282 // Release events, timer, etc 349 // Release events, timer, etc
283 // 350 //
284 instance.DestroyScriptInstance(); 351 instance.DestroyScriptInstance();
285 352
286 // Unload scripts and app domains 353 // Unload scripts and app domains
287 // Must be done explicitly because they have infinite 354 // Must be done explicitly because they have infinite
288 // lifetime 355 // lifetime
289 // 356 //
290 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 357 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
291 if (m_DomainScripts[instance.AppDomain].Count == 0) 358 if (m_DomainScripts[instance.AppDomain].Count == 0)
292 { 359 {
293 m_DomainScripts.Remove(instance.AppDomain); 360 m_DomainScripts.Remove(instance.AppDomain);
294 UnloadAppDomain(instance.AppDomain); 361 UnloadAppDomain(instance.AppDomain);
295 }
296 } 362 }
297 m_Scripts.Clear();
298 m_PrimObjects.Clear();
299 m_Assemblies.Clear();
300 m_DomainScripts.Clear();
301 } 363 }
364 lockScriptsForRead(false);
365 lockScriptsForWrite(true);
366 m_Scripts.Clear();
367 lockScriptsForWrite(false);
368 m_PrimObjects.Clear();
369 m_Assemblies.Clear();
370 m_DomainScripts.Clear();
371
302 lock (m_ScriptEngines) 372 lock (m_ScriptEngines)
303 { 373 {
304 m_ScriptEngines.Remove(this); 374 m_ScriptEngines.Remove(this);
@@ -357,22 +427,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
357 427
358 List<IScriptInstance> instances = new List<IScriptInstance>(); 428 List<IScriptInstance> instances = new List<IScriptInstance>();
359 429
360 lock (m_Scripts) 430 lockScriptsForRead(true);
361 { 431 foreach (IScriptInstance instance in m_Scripts.Values)
362 foreach (IScriptInstance instance in m_Scripts.Values)
363 instances.Add(instance); 432 instances.Add(instance);
364 } 433 lockScriptsForRead(false);
365 434
366 foreach (IScriptInstance i in instances) 435 foreach (IScriptInstance i in instances)
367 { 436 {
368 string assembly = String.Empty; 437 string assembly = String.Empty;
369 438
370 lock (m_Scripts) 439
371 {
372 if (!m_Assemblies.ContainsKey(i.AssetID)) 440 if (!m_Assemblies.ContainsKey(i.AssetID))
373 continue; 441 continue;
374 assembly = m_Assemblies[i.AssetID]; 442 assembly = m_Assemblies[i.AssetID];
375 } 443
376 444
377 i.SaveState(assembly); 445 i.SaveState(assembly);
378 } 446 }
@@ -684,170 +752,181 @@ namespace OpenSim.Region.ScriptEngine.XEngine
684 } 752 }
685 } 753 }
686 754
687 lock (m_Scripts) 755
756
757 ScriptInstance instance = null;
758 // Create the object record
759 lockScriptsForRead(true);
760 if ((!m_Scripts.ContainsKey(itemID)) ||
761 (m_Scripts[itemID].AssetID != assetID))
688 { 762 {
689 ScriptInstance instance = null; 763 lockScriptsForRead(false);
690 // Create the object record
691 764
692 if ((!m_Scripts.ContainsKey(itemID)) || 765 UUID appDomain = assetID;
693 (m_Scripts[itemID].AssetID != assetID))
694 {
695 UUID appDomain = assetID;
696 766
697 if (part.ParentGroup.IsAttachment) 767 if (part.ParentGroup.IsAttachment)
698 appDomain = part.ParentGroup.RootPart.UUID; 768 appDomain = part.ParentGroup.RootPart.UUID;
699 769
700 if (!m_AppDomains.ContainsKey(appDomain)) 770 if (!m_AppDomains.ContainsKey(appDomain))
771 {
772 try
701 { 773 {
702 try 774 AppDomainSetup appSetup = new AppDomainSetup();
703 { 775 // appSetup.ApplicationBase = Path.Combine(
704 AppDomainSetup appSetup = new AppDomainSetup(); 776 // "ScriptEngines",
705// appSetup.ApplicationBase = Path.Combine( 777 // m_Scene.RegionInfo.RegionID.ToString());
706// "ScriptEngines", 778
707// m_Scene.RegionInfo.RegionID.ToString()); 779 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
708 780 Evidence evidence = new Evidence(baseEvidence);
709 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 781
710 Evidence evidence = new Evidence(baseEvidence); 782 AppDomain sandbox;
711 783 if (m_AppDomainLoading)
712 AppDomain sandbox; 784 sandbox = AppDomain.CreateDomain(
713 if (m_AppDomainLoading) 785 m_Scene.RegionInfo.RegionID.ToString(),
714 sandbox = AppDomain.CreateDomain( 786 evidence, appSetup);
715 m_Scene.RegionInfo.RegionID.ToString(), 787 else
716 evidence, appSetup); 788 sandbox = AppDomain.CurrentDomain;
717 else 789
718 sandbox = AppDomain.CurrentDomain; 790 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
719 791 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
720 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); 792 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
721 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); 793 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
722 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet"); 794 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
723 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet); 795 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
724 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement); 796 //sandbox.SetAppDomainPolicy(sandboxPolicy);
725 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup; 797
726 //sandbox.SetAppDomainPolicy(sandboxPolicy); 798 m_AppDomains[appDomain] = sandbox;
727 799
728 m_AppDomains[appDomain] = sandbox; 800 m_AppDomains[appDomain].AssemblyResolve +=
729 801 new ResolveEventHandler(
730 m_AppDomains[appDomain].AssemblyResolve += 802 AssemblyResolver.OnAssemblyResolve);
731 new ResolveEventHandler( 803 m_DomainScripts[appDomain] = new List<UUID>();
732 AssemblyResolver.OnAssemblyResolve);
733 m_DomainScripts[appDomain] = new List<UUID>();
734 }
735 catch (Exception e)
736 {
737 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
738 m_ScriptErrorMessage += "Exception creating app domain:\n";
739 m_ScriptFailCount++;
740 lock (m_AddingAssemblies)
741 {
742 m_AddingAssemblies[assembly]--;
743 }
744 return false;
745 }
746 } 804 }
747 m_DomainScripts[appDomain].Add(itemID); 805 catch (Exception e)
748
749 instance = new ScriptInstance(this, part,
750 itemID, assetID, assembly,
751 m_AppDomains[appDomain],
752 part.ParentGroup.RootPart.Name,
753 item.Name, startParam, postOnRez,
754 stateSource, m_MaxScriptQueue);
755
756 m_log.DebugFormat("[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}",
757 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, part.ParentGroup.RootPart.AbsolutePosition.ToString());
758
759 if (presence != null)
760 { 806 {
761 ShowScriptSaveResponse(item.OwnerID, 807 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
762 assetID, "Compile successful", true); 808 m_ScriptErrorMessage += "Exception creating app domain:\n";
809 m_ScriptFailCount++;
810 lock (m_AddingAssemblies)
811 {
812 m_AddingAssemblies[assembly]--;
813 }
814 return false;
763 } 815 }
816 }
817 m_DomainScripts[appDomain].Add(itemID);
764 818
765 instance.AppDomain = appDomain; 819 instance = new ScriptInstance(this, part,
766 instance.LineMap = linemap; 820 itemID, assetID, assembly,
821 m_AppDomains[appDomain],
822 part.ParentGroup.RootPart.Name,
823 item.Name, startParam, postOnRez,
824 stateSource, m_MaxScriptQueue);
767 825
768 m_Scripts[itemID] = instance; 826 m_log.DebugFormat("[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}",
769 } 827 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, part.ParentGroup.RootPart.AbsolutePosition.ToString());
770 828
771 lock (m_PrimObjects) 829 if (presence != null)
772 { 830 {
773 if (!m_PrimObjects.ContainsKey(localID)) 831 ShowScriptSaveResponse(item.OwnerID,
774 m_PrimObjects[localID] = new List<UUID>(); 832 assetID, "Compile successful", true);
833 }
775 834
776 if (!m_PrimObjects[localID].Contains(itemID)) 835 instance.AppDomain = appDomain;
777 m_PrimObjects[localID].Add(itemID); 836 instance.LineMap = linemap;
837 lockScriptsForWrite(true);
838 m_Scripts[itemID] = instance;
839 lockScriptsForWrite(false);
840 }
841 else
842 {
843 lockScriptsForRead(false);
844 }
845 lock (m_PrimObjects)
846 {
847 if (!m_PrimObjects.ContainsKey(localID))
848 m_PrimObjects[localID] = new List<UUID>();
778 849
779 } 850 if (!m_PrimObjects[localID].Contains(itemID))
851 m_PrimObjects[localID].Add(itemID);
780 852
781 if (!m_Assemblies.ContainsKey(assetID)) 853 }
782 m_Assemblies[assetID] = assembly;
783 854
784 lock (m_AddingAssemblies) 855 if (!m_Assemblies.ContainsKey(assetID))
785 { 856 m_Assemblies[assetID] = assembly;
786 m_AddingAssemblies[assembly]--;
787 }
788 857
789 if (instance!=null) 858 lock (m_AddingAssemblies)
790 instance.Init(); 859 {
860 m_AddingAssemblies[assembly]--;
791 } 861 }
862
863 if (instance!=null)
864 instance.Init();
865
792 return true; 866 return true;
793 } 867 }
794 868
795 public void OnRemoveScript(uint localID, UUID itemID) 869 public void OnRemoveScript(uint localID, UUID itemID)
796 { 870 {
797 lock (m_Scripts) 871 lockScriptsForRead(true);
872 // Do we even have it?
873 if (!m_Scripts.ContainsKey(itemID))
798 { 874 {
799 // Do we even have it? 875 lockScriptsForRead(false);
800 if (!m_Scripts.ContainsKey(itemID)) 876 return;
801 return; 877 }
802 878
803 IScriptInstance instance=m_Scripts[itemID];
804 m_Scripts.Remove(itemID);
805 879
806 instance.ClearQueue(); 880 IScriptInstance instance=m_Scripts[itemID];
807 instance.Stop(0); 881 lockScriptsForRead(false);
882 lockScriptsForWrite(true);
883 m_Scripts.Remove(itemID);
884 lockScriptsForWrite(false);
885 instance.ClearQueue();
886 instance.Stop(0);
808 887
809// bool objectRemoved = false; 888// bool objectRemoved = false;
810 889
811 lock (m_PrimObjects) 890 lock (m_PrimObjects)
891 {
892 // Remove the script from it's prim
893 if (m_PrimObjects.ContainsKey(localID))
812 { 894 {
813 // Remove the script from it's prim 895 // Remove inventory item record
814 if (m_PrimObjects.ContainsKey(localID)) 896 if (m_PrimObjects[localID].Contains(itemID))
815 { 897 m_PrimObjects[localID].Remove(itemID);
816 // Remove inventory item record
817 if (m_PrimObjects[localID].Contains(itemID))
818 m_PrimObjects[localID].Remove(itemID);
819 898
820 // If there are no more scripts, remove prim 899 // If there are no more scripts, remove prim
821 if (m_PrimObjects[localID].Count == 0) 900 if (m_PrimObjects[localID].Count == 0)
822 { 901 {
823 m_PrimObjects.Remove(localID); 902 m_PrimObjects.Remove(localID);
824// objectRemoved = true; 903// objectRemoved = true;
825 }
826 } 904 }
827 } 905 }
906 }
828 907
829 instance.RemoveState(); 908 instance.RemoveState();
830 instance.DestroyScriptInstance(); 909 instance.DestroyScriptInstance();
831
832 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
833 if (m_DomainScripts[instance.AppDomain].Count == 0)
834 {
835 m_DomainScripts.Remove(instance.AppDomain);
836 UnloadAppDomain(instance.AppDomain);
837 }
838 910
839 instance = null; 911 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
912 if (m_DomainScripts[instance.AppDomain].Count == 0)
913 {
914 m_DomainScripts.Remove(instance.AppDomain);
915 UnloadAppDomain(instance.AppDomain);
916 }
840 917
841 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 918 instance = null;
842 if (handlerObjectRemoved != null)
843 {
844 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
845 handlerObjectRemoved(part.UUID);
846 }
847 919
848 CleanAssemblies(); 920 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
921 if (handlerObjectRemoved != null)
922 {
923 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
924 handlerObjectRemoved(part.UUID);
849 } 925 }
850 926
927 CleanAssemblies();
928
929
851 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 930 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
852 if (handlerScriptRemoved != null) 931 if (handlerScriptRemoved != null)
853 handlerScriptRemoved(itemID); 932 handlerScriptRemoved(itemID);
@@ -1099,12 +1178,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1099 private IScriptInstance GetInstance(UUID itemID) 1178 private IScriptInstance GetInstance(UUID itemID)
1100 { 1179 {
1101 IScriptInstance instance; 1180 IScriptInstance instance;
1102 lock (m_Scripts) 1181 lockScriptsForRead(true);
1182 if (!m_Scripts.ContainsKey(itemID))
1103 { 1183 {
1104 if (!m_Scripts.ContainsKey(itemID)) 1184 lockScriptsForRead(false);
1105 return null; 1185 return null;
1106 instance = m_Scripts[itemID];
1107 } 1186 }
1187 instance = m_Scripts[itemID];
1188 lockScriptsForRead(false);
1108 return instance; 1189 return instance;
1109 } 1190 }
1110 1191
@@ -1128,6 +1209,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1128 return false; 1209 return false;
1129 } 1210 }
1130 1211
1212 [DebuggerNonUserCode]
1131 public void ApiResetScript(UUID itemID) 1213 public void ApiResetScript(UUID itemID)
1132 { 1214 {
1133 IScriptInstance instance = GetInstance(itemID); 1215 IScriptInstance instance = GetInstance(itemID);
@@ -1179,6 +1261,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1179 return UUID.Zero; 1261 return UUID.Zero;
1180 } 1262 }
1181 1263
1264 [DebuggerNonUserCode]
1182 public void SetState(UUID itemID, string newState) 1265 public void SetState(UUID itemID, string newState)
1183 { 1266 {
1184 IScriptInstance instance = GetInstance(itemID); 1267 IScriptInstance instance = GetInstance(itemID);
@@ -1199,11 +1282,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1199 { 1282 {
1200 List<IScriptInstance> instances = new List<IScriptInstance>(); 1283 List<IScriptInstance> instances = new List<IScriptInstance>();
1201 1284
1202 lock (m_Scripts) 1285 lockScriptsForRead(true);
1203 { 1286 foreach (IScriptInstance instance in m_Scripts.Values)
1204 foreach (IScriptInstance instance in m_Scripts.Values)
1205 instances.Add(instance); 1287 instances.Add(instance);
1206 } 1288 lockScriptsForRead(false);
1207 1289
1208 foreach (IScriptInstance i in instances) 1290 foreach (IScriptInstance i in instances)
1209 { 1291 {