aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Application/OpenSim.cs2
-rw-r--r--OpenSim/Region/Application/OpenSimBase.cs49
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs3
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs148
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs5
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs66
-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.cs49
-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/Framework/EntityTransfer/EntityTransferModule.cs31
-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/ModuleLoader.cs3
-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.cs27
-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.cs94
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs26
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs702
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs153
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs722
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs679
-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.cs25
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs1113
-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
63 files changed, 13367 insertions, 1660 deletions
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index a09b903..75561a7 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -427,7 +427,7 @@ namespace OpenSim
427 if (alert != null) 427 if (alert != null)
428 presence.ControllingClient.Kick(alert); 428 presence.ControllingClient.Kick(alert);
429 else 429 else
430 presence.ControllingClient.Kick("\nThe OpenSim manager kicked you out.\n"); 430 presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n");
431 431
432 // ...and close on our side 432 // ...and close on our side
433 presence.Scene.IncomingCloseAgent(presence.UUID); 433 presence.Scene.IncomingCloseAgent(presence.UUID);
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/J2KImage.cs b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs
index 9869a99..5c17b0e 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs
@@ -202,6 +202,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
202 m_stopPacket = TexturePacketCount(); 202 m_stopPacket = TexturePacketCount();
203 } 203 }
204 204
205 //Give them at least two packets, to play nice with some broken viewers (SL also behaves this way)
206 if (m_stopPacket == 1 && Layers[0].End > FIRST_PACKET_SIZE) m_stopPacket++;
207
205 m_currentPacket = StartPacket; 208 m_currentPacket = StartPacket;
206 } 209 }
207 } 210 }
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index a516a54..fe8475a 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -337,6 +337,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
337 private AgentUpdateArgs lastarg; 337 private AgentUpdateArgs lastarg;
338 private bool m_IsActive = true; 338 private bool m_IsActive = true;
339 private bool m_IsLoggingOut = false; 339 private bool m_IsLoggingOut = false;
340 private bool m_IsPresenceReady = false;
340 341
341 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>(); 342 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>();
342 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers 343 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
@@ -360,6 +361,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
360 361
361 private Timer m_propertiesPacketTimer; 362 private Timer m_propertiesPacketTimer;
362 private List<ObjectPropertiesPacket.ObjectDataBlock> m_propertiesBlocks = new List<ObjectPropertiesPacket.ObjectDataBlock>(); 363 private List<ObjectPropertiesPacket.ObjectDataBlock> m_propertiesBlocks = new List<ObjectPropertiesPacket.ObjectDataBlock>();
364 private List<Packet> m_pendingPackets;
363 365
364 #endregion Class Members 366 #endregion Class Members
365 367
@@ -400,6 +402,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
400 get { return m_IsActive; } 402 get { return m_IsActive; }
401 set { m_IsActive = value; } 403 set { m_IsActive = value; }
402 } 404 }
405
403 public bool IsLoggingOut 406 public bool IsLoggingOut
404 { 407 {
405 get { return m_IsLoggingOut; } 408 get { return m_IsLoggingOut; }
@@ -463,18 +466,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
463 466
464 #region Client Methods 467 #region Client Methods
465 468
469
466 /// <summary> 470 /// <summary>
467 /// Shut down the client view 471 /// Shut down the client view
468 /// </summary> 472 /// </summary>
469 public void Close() 473 public void Close()
470 { 474 {
475 Close(true);
476 }
477
478 /// <summary>
479 /// Shut down the client view
480 /// </summary>
481 public void Close(bool sendStop)
482 {
471 m_log.DebugFormat( 483 m_log.DebugFormat(
472 "[CLIENT]: Close has been called for {0} attached to scene {1}", 484 "[CLIENT]: Close has been called for {0} attached to scene {1}",
473 Name, m_scene.RegionInfo.RegionName); 485 Name, m_scene.RegionInfo.RegionName);
474 486
475 // Send the STOP packet 487 if (sendStop)
476 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator); 488 {
477 OutPacket(disable, ThrottleOutPacketType.Unknown); 489 // Send the STOP packet
490 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
491 OutPacket(disable, ThrottleOutPacketType.Unknown);
492 }
478 493
479 IsActive = false; 494 IsActive = false;
480 495
@@ -1040,6 +1055,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1040 public virtual void SendLayerData(float[] map) 1055 public virtual void SendLayerData(float[] map)
1041 { 1056 {
1042 Util.FireAndForget(DoSendLayerData, map); 1057 Util.FireAndForget(DoSendLayerData, map);
1058
1059 // Send it sync, and async. It's not that much data
1060 // and it improves user experience just so much!
1061 DoSendLayerData(map);
1043 } 1062 }
1044 1063
1045 /// <summary> 1064 /// <summary>
@@ -1052,16 +1071,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1052 1071
1053 try 1072 try
1054 { 1073 {
1055 //for (int y = 0; y < 16; y++) 1074 for (int y = 0; y < 16; y++)
1056 //{ 1075 {
1057 // for (int x = 0; x < 16; x++) 1076 for (int x = 0; x < 16; x+=4)
1058 // { 1077 {
1059 // SendLayerData(x, y, map); 1078 SendLayerPacket(x, y, map);
1060 // } 1079 }
1061 //} 1080 }
1062
1063 // Send LayerData in a spiral pattern. Fun!
1064 SendLayerTopRight(map, 0, 0, 15, 15);
1065 } 1081 }
1066 catch (Exception e) 1082 catch (Exception e)
1067 { 1083 {
@@ -1069,51 +1085,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1069 } 1085 }
1070 } 1086 }
1071 1087
1072 private void SendLayerTopRight(float[] map, int x1, int y1, int x2, int y2)
1073 {
1074 // Row
1075 for (int i = x1; i <= x2; i++)
1076 SendLayerData(i, y1, map);
1077
1078 // Column
1079 for (int j = y1 + 1; j <= y2; j++)
1080 SendLayerData(x2, j, map);
1081
1082 if (x2 - x1 > 0)
1083 SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2);
1084 }
1085
1086 void SendLayerBottomLeft(float[] map, int x1, int y1, int x2, int y2)
1087 {
1088 // Row in reverse
1089 for (int i = x2; i >= x1; i--)
1090 SendLayerData(i, y2, map);
1091
1092 // Column in reverse
1093 for (int j = y2 - 1; j >= y1; j--)
1094 SendLayerData(x1, j, map);
1095
1096 if (x2 - x1 > 0)
1097 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
1098 }
1099
1100 /// <summary> 1088 /// <summary>
1101 /// Sends a set of four patches (x, x+1, ..., x+3) to the client 1089 /// Sends a set of four patches (x, x+1, ..., x+3) to the client
1102 /// </summary> 1090 /// </summary>
1103 /// <param name="map">heightmap</param> 1091 /// <param name="map">heightmap</param>
1104 /// <param name="px">X coordinate for patches 0..12</param> 1092 /// <param name="px">X coordinate for patches 0..12</param>
1105 /// <param name="py">Y coordinate for patches 0..15</param> 1093 /// <param name="py">Y coordinate for patches 0..15</param>
1106 // private void SendLayerPacket(float[] map, int y, int x) 1094 private void SendLayerPacket(int x, int y, float[] map)
1107 // { 1095 {
1108 // int[] patches = new int[4]; 1096 int[] patches = new int[4];
1109 // patches[0] = x + 0 + y * 16; 1097 patches[0] = x + 0 + y * 16;
1110 // patches[1] = x + 1 + y * 16; 1098 patches[1] = x + 1 + y * 16;
1111 // patches[2] = x + 2 + y * 16; 1099 patches[2] = x + 2 + y * 16;
1112 // patches[3] = x + 3 + y * 16; 1100 patches[3] = x + 3 + y * 16;
1113 1101
1114 // Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); 1102 float[] heightmap = (map.Length == 65536) ?
1115 // OutPacket(layerpack, ThrottleOutPacketType.Land); 1103 map :
1116 // } 1104 LLHeightFieldMoronize(map);
1105
1106 try
1107 {
1108 Packet layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1109 OutPacket(layerpack, ThrottleOutPacketType.Land);
1110 }
1111 catch
1112 {
1113 for (int px = x ; px < x + 4 ; px++)
1114 SendLayerData(px, y, map);
1115 }
1116 }
1117 1117
1118 /// <summary> 1118 /// <summary>
1119 /// Sends a specified patch to a client 1119 /// Sends a specified patch to a client
@@ -1133,7 +1133,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1133 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); 1133 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1134 layerpack.Header.Reliable = true; 1134 layerpack.Header.Reliable = true;
1135 1135
1136 OutPacket(layerpack, ThrottleOutPacketType.Land); 1136 OutPacket(layerpack, ThrottleOutPacketType.Task);
1137 } 1137 }
1138 catch (Exception e) 1138 catch (Exception e)
1139 { 1139 {
@@ -3896,6 +3896,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3896 { 3896 {
3897 m_propertiesPacketTimer.Stop(); 3897 m_propertiesPacketTimer.Stop();
3898 3898
3899 if (m_propertiesBlocks.Count == 0)
3900 return;
3901
3899 proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[m_propertiesBlocks.Count]; 3902 proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[m_propertiesBlocks.Count];
3900 3903
3901 int index = 0; 3904 int index = 0;
@@ -4887,6 +4890,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4887 (x.CameraLeftAxis != lastarg.CameraLeftAxis) || 4890 (x.CameraLeftAxis != lastarg.CameraLeftAxis) ||
4888 (x.CameraUpAxis != lastarg.CameraUpAxis) || 4891 (x.CameraUpAxis != lastarg.CameraUpAxis) ||
4889 (x.ControlFlags != lastarg.ControlFlags) || 4892 (x.ControlFlags != lastarg.ControlFlags) ||
4893 (x.ControlFlags != 0) ||
4890 (x.Far != lastarg.Far) || 4894 (x.Far != lastarg.Far) ||
4891 (x.Flags != lastarg.Flags) || 4895 (x.Flags != lastarg.Flags) ||
4892 (x.State != lastarg.State) || 4896 (x.State != lastarg.State) ||
@@ -5258,7 +5262,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5258 args.Channel = ch; 5262 args.Channel = ch;
5259 args.From = String.Empty; 5263 args.From = String.Empty;
5260 args.Message = Utils.BytesToString(msg); 5264 args.Message = Utils.BytesToString(msg);
5261 args.Type = ChatTypeEnum.Shout; 5265 args.Type = ChatTypeEnum.Region; //Behaviour in SL is that the response can be heard from any distance
5262 args.Position = new Vector3(); 5266 args.Position = new Vector3();
5263 args.Scene = Scene; 5267 args.Scene = Scene;
5264 args.Sender = this; 5268 args.Sender = this;
@@ -11176,18 +11180,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11176 } 11180 }
11177 11181
11178 /// <summary> 11182 /// <summary>
11183 /// This processes packets which have accumulated while the presence was still in the process of initialising.
11184 /// </summary>
11185 public void ProcessPendingPackets()
11186 {
11187 m_IsPresenceReady = true;
11188 if (m_pendingPackets == null)
11189 return;
11190 foreach (Packet p in m_pendingPackets)
11191 {
11192 ProcessInPacket(p);
11193 }
11194 m_pendingPackets.Clear();
11195 }
11196
11197 /// <summary>
11179 /// Entryway from the client to the simulator. All UDP packets from the client will end up here 11198 /// Entryway from the client to the simulator. All UDP packets from the client will end up here
11180 /// </summary> 11199 /// </summary>
11181 /// <param name="Pack">OpenMetaverse.packet</param> 11200 /// <param name="Pack">OpenMetaverse.packet</param>
11182 public void ProcessInPacket(Packet Pack) 11201 public void ProcessInPacket(Packet Pack)
11183 { 11202 {
11184 if (m_debugPacketLevel >= 255) 11203 if (!m_IsPresenceReady)
11185 m_log.DebugFormat("[CLIENT]: Packet IN {0}", Pack.Type); 11204 {
11205 if (m_pendingPackets == null)
11206 {
11207 m_pendingPackets = new List<Packet>();
11208 }
11209 m_pendingPackets.Add(Pack);
11210 }
11211 else
11212 {
11213 if (m_debugPacketLevel >= 255)
11214 m_log.DebugFormat("[CLIENT]: Packet IN {0}", Pack.Type);
11186 11215
11187 if (!ProcessPacketMethod(Pack)) 11216 if (!ProcessPacketMethod(Pack))
11188 m_log.Warn("[CLIENT]: unhandled packet " + Pack.Type); 11217 m_log.Warn("[CLIENT]: unhandled packet " + Pack.Type);
11189 11218
11190 PacketPool.Instance.ReturnPacket(Pack); 11219 PacketPool.Instance.ReturnPacket(Pack);
11220 }
11191 } 11221 }
11192 11222
11193 private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) 11223 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/ClientStack/LindenUDP/TokenBucket.cs b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
index bdbd284..91e3d20 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
@@ -133,7 +133,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
133 this.parent = parent; 133 this.parent = parent;
134 MaxBurst = maxBurst; 134 MaxBurst = maxBurst;
135 DripRate = dripRate; 135 DripRate = dripRate;
136 lastDrip = Environment.TickCount & Int32.MaxValue; 136 lastDrip = Environment.TickCount;
137 } 137 }
138 138
139 /// <summary> 139 /// <summary>
@@ -144,40 +144,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
144 /// the bucket, otherwise false</returns> 144 /// the bucket, otherwise false</returns>
145 public bool RemoveTokens(int amount) 145 public bool RemoveTokens(int amount)
146 { 146 {
147 bool dummy;
148 return RemoveTokens(amount, out dummy);
149 }
150
151 /// <summary>
152 /// Remove a given number of tokens from the bucket
153 /// </summary>
154 /// <param name="amount">Number of tokens to remove from the bucket</param>
155 /// <param name="dripSucceeded">True if tokens were added to the bucket
156 /// during this call, otherwise false</param>
157 /// <returns>True if the requested number of tokens were removed from
158 /// the bucket, otherwise false</returns>
159 public bool RemoveTokens(int amount, out bool dripSucceeded)
160 {
161 if (maxBurst == 0) 147 if (maxBurst == 0)
162 { 148 {
163 dripSucceeded = true;
164 return true; 149 return true;
165 } 150 }
166 151
167 dripSucceeded = Drip(); 152 if (amount > maxBurst)
168
169 if (content - amount >= 0)
170 { 153 {
171 if (parent != null && !parent.RemoveTokens(amount)) 154 throw new Exception("amount " + amount + " exceeds maxBurst " + maxBurst);
172 return false; 155 }
173 156
174 content -= amount; 157 Drip();
175 return true; 158
159 if (content < amount)
160 {
161 return false;
176 } 162 }
177 else 163
164 if (parent != null && !parent.RemoveTokens(amount))
178 { 165 {
179 return false; 166 return false;
180 } 167 }
168
169 content -= amount;
170 return true;
181 } 171 }
182 172
183 /// <summary> 173 /// <summary>
@@ -193,25 +183,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP
193 content = maxBurst; 183 content = maxBurst;
194 return true; 184 return true;
195 } 185 }
196 else
197 {
198 int now = Environment.TickCount & Int32.MaxValue;
199 int deltaMS = now - lastDrip;
200 186
201 if (deltaMS <= 0) 187 int now = Environment.TickCount;
202 { 188 int deltaMS = now - lastDrip;
203 if (deltaMS < 0) 189 lastDrip = now;
204 lastDrip = now;
205 return false;
206 }
207 190
208 int dripAmount = deltaMS * tokensPerMS; 191 if (deltaMS <= 0)
209 192 {
210 content = Math.Min(content + dripAmount, maxBurst); 193 return false;
211 lastDrip = now; 194 }
212 195
213 return true; 196 long dripAmount = (long)deltaMS * (long)tokensPerMS + (long)content;
197 if (dripAmount > maxBurst)
198 {
199 dripAmount = maxBurst;
214 } 200 }
201 content = (int)dripAmount;
202 return true;
215 } 203 }
216 } 204 }
217} 205}
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 0050653..b255415 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>();
@@ -203,9 +203,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
203 203
204 UserFriendData data = m_Friends[principalID]; 204 UserFriendData data = m_Friends[principalID];
205 205
206 string searchFor = friendID.ToString();
206 foreach (FriendInfo fi in data.Friends) 207 foreach (FriendInfo fi in data.Friends)
207 { 208 {
208 if (fi.Friend == friendID.ToString()) 209 if (fi.Friend == searchFor)
209 return (uint)fi.TheirFlags; 210 return (uint)fi.TheirFlags;
210 } 211 }
211 return 0; 212 return 0;
@@ -295,7 +296,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
295 296
296 // Inform the friends that this user is online 297 // Inform the friends that this user is online
297 StatusChange(agentID, true); 298 StatusChange(agentID, true);
298 299
299 // Register that we need to send the list of online friends to this user 300 // Register that we need to send the list of online friends to this user
300 lock (m_NeedsListOfFriends) 301 lock (m_NeedsListOfFriends)
301 if (!m_NeedsListOfFriends.Contains(agentID)) 302 if (!m_NeedsListOfFriends.Contains(agentID))
@@ -445,11 +446,47 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
445 if (((fi.MyFlags & 1) != 0) && (fi.TheirFlags != -1)) 446 if (((fi.MyFlags & 1) != 0) && (fi.TheirFlags != -1))
446 friendList.Add(fi); 447 friendList.Add(fi);
447 } 448 }
449 /*
448 foreach (FriendInfo fi in friendList) 450 foreach (FriendInfo fi in friendList)
449 { 451 {
450 // Notify about this user status 452 // Notify about this user status
451 StatusNotify(fi, agentID, online); 453 StatusNotify(fi, agentID, online);
452 } 454 }
455 */
456
457 StatusNotifyMass(friendList, agentID, online);
458 }
459 }
460
461 private void StatusNotifyMass(List<FriendInfo> friendList, UUID userID, bool online)
462 {
463 int fct = friendList.Count;
464 string[] friendIDs = new string[fct];
465 int notlocal = 0;
466 for (int x = 0 ; x < fct ; x++)
467 {
468 UUID friendID = UUID.Zero;
469 if (UUID.TryParse(friendList[x].Friend, out friendID))
470 {
471 if (!LocalStatusNotification(userID, friendID, online))
472 {
473 friendIDs[notlocal++] = friendID.ToString();
474 }
475 }
476 }
477
478 PresenceInfo[] friendSessions = PresenceService.GetAgents(friendIDs);
479
480 for (int x = 0; x < friendSessions.GetLength(0); x++)
481 {
482 if (friendIDs.Length <= x)
483 continue;
484 PresenceInfo friendSession = friendSessions[x];
485 if (friendSession != null)
486 {
487 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
488 m_FriendsSimConnector.StatusNotify(region, userID, new UUID(friendIDs[x]), online);
489 }
453 } 490 }
454 } 491 }
455 492
@@ -462,7 +499,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
462 // Try local 499 // Try local
463 if (LocalStatusNotification(userID, friendID, online)) 500 if (LocalStatusNotification(userID, friendID, online))
464 return; 501 return;
465 502
466 // The friend is not here [as root]. Let's forward. 503 // The friend is not here [as root]. Let's forward.
467 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); 504 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() });
468 if (friendSessions != null && friendSessions.Length > 0) 505 if (friendSessions != null && friendSessions.Length > 0)
@@ -482,7 +519,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
482 private void OnInstantMessage(IClientAPI client, GridInstantMessage im) 519 private void OnInstantMessage(IClientAPI client, GridInstantMessage im)
483 { 520 {
484 if (im.dialog == (byte)OpenMetaverse.InstantMessageDialog.FriendshipOffered) 521 if (im.dialog == (byte)OpenMetaverse.InstantMessageDialog.FriendshipOffered)
485 { 522 {
486 // we got a friendship offer 523 // we got a friendship offer
487 UUID principalID = new UUID(im.fromAgentID); 524 UUID principalID = new UUID(im.fromAgentID);
488 UUID friendID = new UUID(im.toAgentID); 525 UUID friendID = new UUID(im.toAgentID);
@@ -711,7 +748,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
711 // we're done 748 // we're done
712 return true; 749 return true;
713 } 750 }
714 751
715 return false; 752 return false;
716 } 753 }
717 754
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/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index ef37f63..dc1025d 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -261,7 +261,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
261 // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field, 261 // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field,
262 // it's actually doing a lot of work. 262 // it's actually doing a lot of work.
263 IPEndPoint endPoint = finalDestination.ExternalEndPoint; 263 IPEndPoint endPoint = finalDestination.ExternalEndPoint;
264 if (endPoint.Address != null) 264 if (endPoint != null && endPoint.Address != null)
265 { 265 {
266 // Fixing a bug where teleporting while sitting results in the avatar ending up removed from 266 // Fixing a bug where teleporting while sitting results in the avatar ending up removed from
267 // both regions 267 // both regions
@@ -825,15 +825,19 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
825 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID); 825 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID);
826 826
827 IEventQueue eq = agent.Scene.RequestModuleInterface<IEventQueue>(); 827 IEventQueue eq = agent.Scene.RequestModuleInterface<IEventQueue>();
828 if (eq != null) 828 IPEndPoint neighbourExternal = neighbourRegion.ExternalEndPoint;
829 { 829 if (neighbourExternal != null)
830 eq.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint,
831 capsPath, agent.UUID, agent.ControllingClient.SessionId);
832 }
833 else
834 { 830 {
835 agent.ControllingClient.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint, 831 if (eq != null)
836 capsPath); 832 {
833 eq.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourExternal,
834 capsPath, agent.UUID, agent.ControllingClient.SessionId);
835 }
836 else
837 {
838 agent.ControllingClient.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourExternal,
839 capsPath);
840 }
837 } 841 }
838 842
839 if (!WaitForCallback(agent.UUID)) 843 if (!WaitForCallback(agent.UUID))
@@ -906,10 +910,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
906 agent.child = true; 910 agent.child = true;
907 agent.Appearance = sp.Appearance; 911 agent.Appearance = sp.Appearance;
908 912
909 InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync; 913 IPEndPoint external = region.ExternalEndPoint;
910 d.BeginInvoke(sp, agent, region, region.ExternalEndPoint, true, 914 if (external != null)
915 {
916 InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync;
917 d.BeginInvoke(sp, agent, region, external, true,
911 InformClientOfNeighbourCompleted, 918 InformClientOfNeighbourCompleted,
912 d); 919 d);
920 }
913 } 921 }
914 #endregion 922 #endregion
915 923
@@ -1038,6 +1046,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1038 InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync; 1046 InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync;
1039 try 1047 try
1040 { 1048 {
1049 //neighbour.ExternalEndPoint may return null, which will be caught
1041 d.BeginInvoke(sp, cagents[count], neighbour, neighbour.ExternalEndPoint, newAgent, 1050 d.BeginInvoke(sp, cagents[count], neighbour, neighbour.ExternalEndPoint, newAgent,
1042 InformClientOfNeighbourCompleted, 1051 InformClientOfNeighbourCompleted,
1043 d); 1052 d);
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 bc653ce..57b7672 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -261,10 +261,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver
261 // Fix ownership/creator of inventory items 261 // Fix ownership/creator of inventory items
262 // Not doing so results in inventory items 262 // Not doing so results in inventory items
263 // being no copy/no mod for everyone 263 // being no copy/no mod for everyone
264 lock (part.TaskInventory) 264 part.TaskInventory.LockItemsForRead(true);
265 TaskInventoryDictionary inv = part.TaskInventory;
266 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv)
265 { 267 {
266 TaskInventoryDictionary inv = part.TaskInventory; 268 if (!ResolveUserUuid(kvp.Value.OwnerID))
267 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv)
268 { 269 {
269 if (!ResolveUserUuid(kvp.Value.OwnerID)) 270 if (!ResolveUserUuid(kvp.Value.OwnerID))
270 { 271 {
@@ -276,6 +277,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
276 } 277 }
277 } 278 }
278 } 279 }
280 part.TaskInventory.LockItemsForRead(false);
279 } 281 }
280 282
281 if (m_scene.AddRestoredSceneObject(sceneObject, true, false)) 283 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 2681d4f..a84a3c8 100644
--- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
+++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
@@ -821,12 +821,21 @@ namespace OpenSim.Region.Examples.SimpleModule
821 { 821 {
822 } 822 }
823 823
824 public void ProcessPendingPackets()
825 {
826 }
827
824 public void ProcessInPacket(Packet NewPack) 828 public void ProcessInPacket(Packet NewPack)
825 { 829 {
826 } 830 }
827 831
828 public void Close() 832 public void Close()
829 { 833 {
834 Close(true);
835 }
836
837 public void Close(bool sendStop)
838 {
830 } 839 }
831 840
832 public void Start() 841 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/ModuleLoader.cs b/OpenSim/Region/Framework/ModuleLoader.cs
index 23be9c2..69ba2042 100644
--- a/OpenSim/Region/Framework/ModuleLoader.cs
+++ b/OpenSim/Region/Framework/ModuleLoader.cs
@@ -226,7 +226,8 @@ namespace OpenSim.Region.Framework
226 "[MODULES]: Could not load types for [{0}]. Exception {1}", pluginAssembly.FullName, e); 226 "[MODULES]: Could not load types for [{0}]. Exception {1}", pluginAssembly.FullName, e);
227 227
228 // justincc: Right now this is fatal to really get the user's attention 228 // justincc: Right now this is fatal to really get the user's attention
229 throw e; 229 // TomMeta: WTF? No, how about we /don't/ throw a fatal exception when there's no need to?
230 //throw e;
230 } 231 }
231 } 232 }
232 233
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 cc7b648..e111867 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 {
@@ -836,8 +851,12 @@ namespace OpenSim.Region.Framework.Scenes
836 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID) 851 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID)
837 { 852 {
838 SceneObjectPart part = GetSceneObjectPart(localID); 853 SceneObjectPart part = GetSceneObjectPart(localID);
839 SceneObjectGroup group = part.ParentGroup; 854 SceneObjectGroup group = null;
840 if (group != null) 855 if (part != null)
856 {
857 group = part.ParentGroup;
858 }
859 if (part != null && group != null)
841 { 860 {
842 TaskInventoryItem item = group.GetInventoryItem(localID, itemID); 861 TaskInventoryItem item = group.GetInventoryItem(localID, itemID);
843 if (item == null) 862 if (item == null)
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 6300665..22248af 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -149,6 +149,20 @@ namespace OpenSim.Region.Framework.Scenes
149 149
150 public IXfer XferManager; 150 public IXfer XferManager;
151 151
152 protected ISnmpModule m_snmpService = null;
153 public ISnmpModule SnmpService
154 {
155 get
156 {
157 if (m_snmpService == null)
158 {
159 m_snmpService = RequestModuleInterface<ISnmpModule>();
160 }
161
162 return m_snmpService;
163 }
164 }
165
152 protected IAssetService m_AssetService; 166 protected IAssetService m_AssetService;
153 protected IAuthorizationService m_AuthorizationService; 167 protected IAuthorizationService m_AuthorizationService;
154 168
@@ -608,6 +622,8 @@ namespace OpenSim.Region.Framework.Scenes
608 622
609 // Load region settings 623 // Load region settings
610 m_regInfo.RegionSettings = m_storageManager.DataStore.LoadRegionSettings(m_regInfo.RegionID); 624 m_regInfo.RegionSettings = m_storageManager.DataStore.LoadRegionSettings(m_regInfo.RegionID);
625 m_regInfo.WindlightSettings = m_storageManager.DataStore.LoadRegionWindlightSettings(m_regInfo.RegionID);
626
611 if (m_storageManager.EstateDataStore != null) 627 if (m_storageManager.EstateDataStore != null)
612 { 628 {
613 m_regInfo.EstateSettings = m_storageManager.EstateDataStore.LoadEstateSettings(m_regInfo.RegionID, false); 629 m_regInfo.EstateSettings = m_storageManager.EstateDataStore.LoadEstateSettings(m_regInfo.RegionID, false);
@@ -710,7 +726,7 @@ namespace OpenSim.Region.Framework.Scenes
710 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); 726 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
711 // TODO: Change default to true once the feature is supported 727 // TODO: Change default to true once the feature is supported
712 m_usePreJump = startupConfig.GetBoolean("enableprejump", false); 728 m_usePreJump = startupConfig.GetBoolean("enableprejump", false);
713 729 m_usePreJump = true; // Above line fails!?
714 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); 730 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys);
715 if (RegionInfo.NonphysPrimMax > 0) 731 if (RegionInfo.NonphysPrimMax > 0)
716 { 732 {
@@ -1030,6 +1046,15 @@ namespace OpenSim.Region.Framework.Scenes
1030 /// <param name="seconds">float indicating duration before restart.</param> 1046 /// <param name="seconds">float indicating duration before restart.</param>
1031 public virtual void Restart(float seconds) 1047 public virtual void Restart(float seconds)
1032 { 1048 {
1049 Restart(seconds, true);
1050 }
1051
1052 /// <summary>
1053 /// Given float seconds, this will restart the region. showDialog will optionally alert the users.
1054 /// </summary>
1055 /// <param name="seconds">float indicating duration before restart.</param>
1056 public virtual void Restart(float seconds, bool showDialog)
1057 {
1033 // notifications are done in 15 second increments 1058 // notifications are done in 15 second increments
1034 // so .. if the number of seconds is less then 15 seconds, it's not really a restart request 1059 // so .. if the number of seconds is less then 15 seconds, it's not really a restart request
1035 // It's a 'Cancel restart' request. 1060 // It's a 'Cancel restart' request.
@@ -1050,8 +1075,11 @@ namespace OpenSim.Region.Framework.Scenes
1050 m_restartTimer.Elapsed += new ElapsedEventHandler(RestartTimer_Elapsed); 1075 m_restartTimer.Elapsed += new ElapsedEventHandler(RestartTimer_Elapsed);
1051 m_log.Info("[REGION]: Restarting Region in " + (seconds / 60) + " minutes"); 1076 m_log.Info("[REGION]: Restarting Region in " + (seconds / 60) + " minutes");
1052 m_restartTimer.Start(); 1077 m_restartTimer.Start();
1053 m_dialogModule.SendNotificationToUsersInRegion( 1078 if (showDialog)
1079 {
1080 m_dialogModule.SendNotificationToUsersInRegion(
1054 UUID.Random(), String.Empty, RegionInfo.RegionName + String.Format(": Restarting in {0} Minutes", (int)(seconds / 60.0))); 1081 UUID.Random(), String.Empty, RegionInfo.RegionName + String.Format(": Restarting in {0} Minutes", (int)(seconds / 60.0)));
1082 }
1055 } 1083 }
1056 } 1084 }
1057 1085
@@ -1407,16 +1435,16 @@ namespace OpenSim.Region.Framework.Scenes
1407 // Check if any objects have reached their targets 1435 // Check if any objects have reached their targets
1408 CheckAtTargets(); 1436 CheckAtTargets();
1409 1437
1410 // Update SceneObjectGroups that have scheduled themselves for updates
1411 // Objects queue their updates onto all scene presences
1412 if (m_frame % m_update_objects == 0)
1413 m_sceneGraph.UpdateObjectGroups();
1414
1415 // Run through all ScenePresences looking for updates 1438 // Run through all ScenePresences looking for updates
1416 // Presence updates and queued object updates for each presence are sent to clients 1439 // Presence updates and queued object updates for each presence are sent to clients
1417 if (m_frame % m_update_presences == 0) 1440 if (m_frame % m_update_presences == 0)
1418 m_sceneGraph.UpdatePresences(); 1441 m_sceneGraph.UpdatePresences();
1419 1442
1443 // Update SceneObjectGroups that have scheduled themselves for updates
1444 // Objects queue their updates onto all scene presences
1445 if (m_frame % m_update_objects == 0)
1446 m_sceneGraph.UpdateObjectGroups();
1447
1420 int tmpPhysicsMS2 = Util.EnvironmentTickCount(); 1448 int tmpPhysicsMS2 = Util.EnvironmentTickCount();
1421 if ((m_frame % m_update_physics == 0) && m_physics_enabled) 1449 if ((m_frame % m_update_physics == 0) && m_physics_enabled)
1422 m_sceneGraph.UpdatePreparePhysics(); 1450 m_sceneGraph.UpdatePreparePhysics();
@@ -2118,7 +2146,7 @@ namespace OpenSim.Region.Framework.Scenes
2118 public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 2146 public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
2119 { 2147 {
2120 return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates); 2148 return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates);
2121 } 2149 }
2122 2150
2123 /// <summary> 2151 /// <summary>
2124 /// Delete every object from the scene. This does not include attachments worn by avatars. 2152 /// Delete every object from the scene. This does not include attachments worn by avatars.
@@ -3464,12 +3492,15 @@ namespace OpenSim.Region.Framework.Scenes
3464 { 3492 {
3465 // We have a zombie from a crashed session. Kill it. 3493 // We have a zombie from a crashed session. Kill it.
3466 m_log.DebugFormat("[SCENE]: Zombie scene presence detected for {0} in {1}", agent.AgentID, RegionInfo.RegionName); 3494 m_log.DebugFormat("[SCENE]: Zombie scene presence detected for {0} in {1}", agent.AgentID, RegionInfo.RegionName);
3467 sp.ControllingClient.Close(); 3495 sp.ControllingClient.Close(false);
3468 } 3496 }
3469 } 3497 }
3470 3498
3471 CapsModule.AddCapsHandler(agent.AgentID); 3499 CapsModule.AddCapsHandler(agent.AgentID);
3472 3500
3501 if ((teleportFlags & ((uint)TeleportFlags.ViaLandmark | (uint)TeleportFlags.ViaLocation | (uint)TeleportFlags.ViaLandmark | (uint)TeleportFlags.Default)) != 0)
3502 System.Threading.Thread.Sleep(2000);
3503
3473 if (!agent.child) 3504 if (!agent.child)
3474 { 3505 {
3475 if (TestBorderCross(agent.startpos,Cardinals.E)) 3506 if (TestBorderCross(agent.startpos,Cardinals.E))
@@ -3528,6 +3559,8 @@ namespace OpenSim.Region.Framework.Scenes
3528 } 3559 }
3529 } 3560 }
3530 // Honor parcel landing type and position. 3561 // Honor parcel landing type and position.
3562 /*
3563 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3531 if (land != null) 3564 if (land != null)
3532 { 3565 {
3533 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3566 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3535,6 +3568,7 @@ namespace OpenSim.Region.Framework.Scenes
3535 agent.startpos = land.LandData.UserLocation; 3568 agent.startpos = land.LandData.UserLocation;
3536 } 3569 }
3537 } 3570 }
3571 */// This is now handled properly in ScenePresence.MakeRootAgent
3538 } 3572 }
3539 3573
3540 agent.teleportFlags = teleportFlags; 3574 agent.teleportFlags = teleportFlags;
@@ -3883,12 +3917,22 @@ namespace OpenSim.Region.Framework.Scenes
3883 return false; 3917 return false;
3884 } 3918 }
3885 3919
3920 public bool IncomingCloseAgent(UUID agentID)
3921 {
3922 return IncomingCloseAgent(agentID, false);
3923 }
3924
3925 public bool IncomingCloseChildAgent(UUID agentID)
3926 {
3927 return IncomingCloseAgent(agentID, true);
3928 }
3929
3886 /// <summary> 3930 /// <summary>
3887 /// Tell a single agent to disconnect from the region. 3931 /// Tell a single agent to disconnect from the region.
3888 /// </summary> 3932 /// </summary>
3889 /// <param name="regionHandle"></param>
3890 /// <param name="agentID"></param> 3933 /// <param name="agentID"></param>
3891 public bool IncomingCloseAgent(UUID agentID) 3934 /// <param name="childOnly"></param>
3935 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
3892 { 3936 {
3893 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 3937 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
3894 3938
@@ -3900,7 +3944,7 @@ namespace OpenSim.Region.Framework.Scenes
3900 { 3944 {
3901 m_sceneGraph.removeUserCount(false); 3945 m_sceneGraph.removeUserCount(false);
3902 } 3946 }
3903 else 3947 else if (!childOnly)
3904 { 3948 {
3905 m_sceneGraph.removeUserCount(true); 3949 m_sceneGraph.removeUserCount(true);
3906 } 3950 }
@@ -3916,9 +3960,12 @@ namespace OpenSim.Region.Framework.Scenes
3916 } 3960 }
3917 else 3961 else
3918 presence.ControllingClient.SendShutdownConnectionNotice(); 3962 presence.ControllingClient.SendShutdownConnectionNotice();
3963 presence.ControllingClient.Close(false);
3964 }
3965 else if (!childOnly)
3966 {
3967 presence.ControllingClient.Close(true);
3919 } 3968 }
3920
3921 presence.ControllingClient.Close();
3922 return true; 3969 return true;
3923 } 3970 }
3924 3971
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 a02f614..5fbc658 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();
@@ -524,7 +553,8 @@ namespace OpenSim.Region.Framework.Scenes
524 553
525 Entities[presence.UUID] = presence; 554 Entities[presence.UUID] = presence;
526 555
527 lock (m_presenceLock) 556 m_scenePresencesLock.EnterWriteLock();
557 try
528 { 558 {
529 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 559 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
530 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 560 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -548,6 +578,10 @@ namespace OpenSim.Region.Framework.Scenes
548 m_scenePresenceMap = newmap; 578 m_scenePresenceMap = newmap;
549 m_scenePresenceArray = newlist; 579 m_scenePresenceArray = newlist;
550 } 580 }
581 finally
582 {
583 m_scenePresencesLock.ExitWriteLock();
584 }
551 } 585 }
552 586
553 /// <summary> 587 /// <summary>
@@ -562,7 +596,8 @@ namespace OpenSim.Region.Framework.Scenes
562 agentID); 596 agentID);
563 } 597 }
564 598
565 lock (m_presenceLock) 599 m_scenePresencesLock.EnterWriteLock();
600 try
566 { 601 {
567 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 602 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
568 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 603 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -583,6 +618,10 @@ namespace OpenSim.Region.Framework.Scenes
583 m_log.WarnFormat("[SCENE] Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 618 m_log.WarnFormat("[SCENE] Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
584 } 619 }
585 } 620 }
621 finally
622 {
623 m_scenePresencesLock.ExitWriteLock();
624 }
586 } 625 }
587 626
588 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 627 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1460,10 +1499,13 @@ namespace OpenSim.Region.Framework.Scenes
1460 /// <param name="childPrims"></param> 1499 /// <param name="childPrims"></param>
1461 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) 1500 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
1462 { 1501 {
1502 SceneObjectGroup parentGroup = root.ParentGroup;
1503 if (parentGroup == null) return;
1463 Monitor.Enter(m_updateLock); 1504 Monitor.Enter(m_updateLock);
1505
1464 try 1506 try
1465 { 1507 {
1466 SceneObjectGroup parentGroup = root.ParentGroup; 1508 parentGroup.areUpdatesSuspended = true;
1467 1509
1468 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1510 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1469 if (parentGroup != null) 1511 if (parentGroup != null)
@@ -1502,12 +1544,12 @@ namespace OpenSim.Region.Framework.Scenes
1502 // occur on link to invoke this elsewhere (such as object selection) 1544 // occur on link to invoke this elsewhere (such as object selection)
1503 parentGroup.RootPart.CreateSelected = true; 1545 parentGroup.RootPart.CreateSelected = true;
1504 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1546 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1505 parentGroup.HasGroupChanged = true;
1506 parentGroup.ScheduleGroupForFullUpdate();
1507
1508 } 1547 }
1509 finally 1548 finally
1510 { 1549 {
1550 parentGroup.areUpdatesSuspended = false;
1551 parentGroup.HasGroupChanged = true;
1552 parentGroup.ScheduleGroupForFullUpdate();
1511 Monitor.Exit(m_updateLock); 1553 Monitor.Exit(m_updateLock);
1512 } 1554 }
1513 } 1555 }
@@ -1544,11 +1586,22 @@ namespace OpenSim.Region.Framework.Scenes
1544 } 1586 }
1545 } 1587 }
1546 1588
1547 foreach (SceneObjectPart child in childParts) 1589 if (childParts.Count > 0)
1548 { 1590 {
1549 // Unlink all child parts from their groups 1591 try
1550 // 1592 {
1551 child.ParentGroup.DelinkFromGroup(child, true); 1593 childParts[0].ParentGroup.areUpdatesSuspended = true;
1594 foreach (SceneObjectPart child in childParts)
1595 {
1596 // Unlink all child parts from their groups
1597 //
1598 child.ParentGroup.DelinkFromGroup(child, true);
1599 }
1600 }
1601 finally
1602 {
1603 childParts[0].ParentGroup.areUpdatesSuspended = false;
1604 }
1552 } 1605 }
1553 1606
1554 foreach (SceneObjectPart root in rootParts) 1607 foreach (SceneObjectPart root in rootParts)
@@ -1572,10 +1625,21 @@ namespace OpenSim.Region.Framework.Scenes
1572 if (numChildren > 1) 1625 if (numChildren > 1)
1573 sendEventsToRemainder = false; 1626 sendEventsToRemainder = false;
1574 1627
1575 foreach (SceneObjectPart p in newSet) 1628 if (newSet.Count > 0)
1576 { 1629 {
1577 if (p != group.RootPart) 1630 try
1578 group.DelinkFromGroup(p, sendEventsToRemainder); 1631 {
1632 newSet[0].ParentGroup.areUpdatesSuspended = true;
1633 foreach (SceneObjectPart p in newSet)
1634 {
1635 if (p != group.RootPart)
1636 group.DelinkFromGroup(p, sendEventsToRemainder);
1637 }
1638 }
1639 finally
1640 {
1641 newSet[0].ParentGroup.areUpdatesSuspended = false;
1642 }
1579 } 1643 }
1580 1644
1581 // If there is more than one prim remaining, we 1645 // If there is more than one prim remaining, we
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 837d3a2..7e73f91 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -104,8 +104,95 @@ 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 private bool m_suspendUpdates;
113
114 private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim();
115
116 public bool areUpdatesSuspended
117 {
118 get
119 {
120 return m_suspendUpdates;
121 }
122 set
123 {
124 m_suspendUpdates = value;
125 if (!value)
126 {
127 QueueForUpdateCheck();
128 }
129 }
130 }
131
132 public void lockPartsForRead(bool locked)
133 {
134 if (locked)
135 {
136 if (m_partsLock.RecursiveReadCount > 0)
137 {
138 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.");
139 m_partsLock.ExitReadLock();
140 }
141 if (m_partsLock.RecursiveWriteCount > 0)
142 {
143 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.");
144 m_partsLock.ExitWriteLock();
145 }
146
147 while (!m_partsLock.TryEnterReadLock(60000))
148 {
149 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.");
150 if (m_partsLock.IsWriteLockHeld)
151 {
152 m_partsLock = new System.Threading.ReaderWriterLockSlim();
153 }
154 }
155 }
156 else
157 {
158 if (m_partsLock.RecursiveReadCount > 0)
159 {
160 m_partsLock.ExitReadLock();
161 }
162 }
163 }
164 public void lockPartsForWrite(bool locked)
165 {
166 if (locked)
167 {
168 if (m_partsLock.RecursiveReadCount > 0)
169 {
170 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.");
171 m_partsLock.ExitReadLock();
172 }
173 if (m_partsLock.RecursiveWriteCount > 0)
174 {
175 m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
176 m_partsLock.ExitWriteLock();
177 }
178
179 while (!m_partsLock.TryEnterWriteLock(60000))
180 {
181 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.");
182 if (m_partsLock.IsWriteLockHeld)
183 {
184 m_partsLock = new System.Threading.ReaderWriterLockSlim();
185 }
186 }
187 }
188 else
189 {
190 if (m_partsLock.RecursiveWriteCount > 0)
191 {
192 m_partsLock.ExitWriteLock();
193 }
194 }
195 }
109 196
110 public bool HasGroupChanged 197 public bool HasGroupChanged
111 { 198 {
@@ -116,6 +203,32 @@ namespace OpenSim.Region.Framework.Scenes
116 timeLastChanged = DateTime.Now.Ticks; 203 timeLastChanged = DateTime.Now.Ticks;
117 if (!m_hasGroupChanged) 204 if (!m_hasGroupChanged)
118 timeFirstChanged = DateTime.Now.Ticks; 205 timeFirstChanged = DateTime.Now.Ticks;
206 if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null)
207 {
208 if (m_rand == null)
209 {
210 byte[] val = new byte[16];
211 m_rootPart.UUID.ToBytes(val, 0);
212 m_rand = new Random(BitConverter.ToInt32(val, 0));
213 }
214
215 if (m_scene.GetRootAgentCount() == 0)
216 {
217 //If the region is empty, this change has been made by an automated process
218 //and thus we delay the persist time by a random amount between 1.5 and 2.5.
219
220 float factor = 1.5f + (float)(m_rand.NextDouble());
221 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor);
222 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor);
223 }
224 else
225 {
226 //If the region is not empty, we want to obey the minimum and maximum persist times
227 //but add a random factor so we stagger the object persistance a little
228 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5
229 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0
230 }
231 }
119 } 232 }
120 m_hasGroupChanged = value; 233 m_hasGroupChanged = value;
121 } 234 }
@@ -131,8 +244,19 @@ namespace OpenSim.Region.Framework.Scenes
131 return false; 244 return false;
132 if (m_scene.ShuttingDown) 245 if (m_scene.ShuttingDown)
133 return true; 246 return true;
247
248 if (m_minPersistTime == 0 || m_maxPersistTime == 0)
249 {
250 m_maxPersistTime = m_scene.m_persistAfter;
251 m_minPersistTime = m_scene.m_dontPersistBefore;
252 }
253
134 long currentTime = DateTime.Now.Ticks; 254 long currentTime = DateTime.Now.Ticks;
135 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) 255
256 if (timeLastChanged == 0) timeLastChanged = currentTime;
257 if (timeFirstChanged == 0) timeFirstChanged = currentTime;
258
259 if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime)
136 return true; 260 return true;
137 return false; 261 return false;
138 } 262 }
@@ -258,13 +382,16 @@ namespace OpenSim.Region.Framework.Scenes
258 set 382 set
259 { 383 {
260 m_regionHandle = value; 384 m_regionHandle = value;
261 lock (m_parts) 385 lockPartsForRead(true);
262 { 386 {
263 foreach (SceneObjectPart part in m_parts.Values) 387 foreach (SceneObjectPart part in m_parts.Values)
264 { 388 {
389
265 part.RegionHandle = m_regionHandle; 390 part.RegionHandle = m_regionHandle;
391
266 } 392 }
267 } 393 }
394 lockPartsForRead(false);
268 } 395 }
269 } 396 }
270 397
@@ -298,6 +425,9 @@ namespace OpenSim.Region.Framework.Scenes
298 { 425 {
299 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 426 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
300 } 427 }
428
429 lockPartsForRead(true);
430
301 if (RootPart.GetStatusSandbox()) 431 if (RootPart.GetStatusSandbox())
302 { 432 {
303 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 433 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -305,17 +435,18 @@ namespace OpenSim.Region.Framework.Scenes
305 RootPart.ScriptSetPhysicsStatus(false); 435 RootPart.ScriptSetPhysicsStatus(false);
306 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), 436 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
307 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); 437 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
438 lockPartsForRead(false);
308 return; 439 return;
309 } 440 }
310 } 441 }
311 lock (m_parts) 442
443 foreach (SceneObjectPart part in m_parts.Values)
312 { 444 {
313 foreach (SceneObjectPart part in m_parts.Values) 445 part.GroupPosition = val;
314 {
315 part.GroupPosition = val;
316 }
317 } 446 }
318 447
448 lockPartsForRead(false);
449
319 //if (m_rootPart.PhysActor != null) 450 //if (m_rootPart.PhysActor != null)
320 //{ 451 //{
321 //m_rootPart.PhysActor.Position = 452 //m_rootPart.PhysActor.Position =
@@ -457,6 +588,7 @@ namespace OpenSim.Region.Framework.Scenes
457 /// </summary> 588 /// </summary>
458 public SceneObjectGroup() 589 public SceneObjectGroup()
459 { 590 {
591
460 } 592 }
461 593
462 /// <summary> 594 /// <summary>
@@ -473,7 +605,7 @@ namespace OpenSim.Region.Framework.Scenes
473 /// Constructor. This object is added to the scene later via AttachToScene() 605 /// Constructor. This object is added to the scene later via AttachToScene()
474 /// </summary> 606 /// </summary>
475 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 607 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
476 { 608 {
477 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 609 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
478 } 610 }
479 611
@@ -504,13 +636,16 @@ namespace OpenSim.Region.Framework.Scenes
504 636
505 public void SetFromItemID(UUID AssetId) 637 public void SetFromItemID(UUID AssetId)
506 { 638 {
507 lock (m_parts) 639 lockPartsForRead(true);
508 { 640 {
509 foreach (SceneObjectPart part in m_parts.Values) 641 foreach (SceneObjectPart part in m_parts.Values)
510 { 642 {
643
511 part.FromItemID = AssetId; 644 part.FromItemID = AssetId;
645
512 } 646 }
513 } 647 }
648 lockPartsForRead(false);
514 } 649 }
515 650
516 public UUID GetFromItemID() 651 public UUID GetFromItemID()
@@ -579,10 +714,11 @@ namespace OpenSim.Region.Framework.Scenes
579 Vector3 maxScale = Vector3.Zero; 714 Vector3 maxScale = Vector3.Zero;
580 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); 715 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
581 716
582 lock (m_parts) 717 lockPartsForRead(true);
583 { 718 {
584 foreach (SceneObjectPart part in m_parts.Values) 719 foreach (SceneObjectPart part in m_parts.Values)
585 { 720 {
721
586 Vector3 partscale = part.Scale; 722 Vector3 partscale = part.Scale;
587 Vector3 partoffset = part.OffsetPosition; 723 Vector3 partoffset = part.OffsetPosition;
588 724
@@ -593,8 +729,11 @@ namespace OpenSim.Region.Framework.Scenes
593 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; 729 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; 730 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; 731 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
732
596 } 733 }
597 } 734 }
735 lockPartsForRead(false);
736
598 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; 737 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
599 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; 738 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
600 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; 739 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
@@ -610,10 +749,11 @@ namespace OpenSim.Region.Framework.Scenes
610 749
611 EntityIntersection result = new EntityIntersection(); 750 EntityIntersection result = new EntityIntersection();
612 751
613 lock (m_parts) 752 lockPartsForRead(true);
614 { 753 {
615 foreach (SceneObjectPart part in m_parts.Values) 754 foreach (SceneObjectPart part in m_parts.Values)
616 { 755 {
756
617 // Temporary commented to stop compiler warning 757 // Temporary commented to stop compiler warning
618 //Vector3 partPosition = 758 //Vector3 partPosition =
619 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); 759 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
@@ -641,8 +781,10 @@ namespace OpenSim.Region.Framework.Scenes
641 result.distance = inter.distance; 781 result.distance = inter.distance;
642 } 782 }
643 } 783 }
784
644 } 785 }
645 } 786 }
787 lockPartsForRead(false);
646 return result; 788 return result;
647 } 789 }
648 790
@@ -661,10 +803,11 @@ namespace OpenSim.Region.Framework.Scenes
661 minY = 256f; 803 minY = 256f;
662 minZ = 8192f; 804 minZ = 8192f;
663 805
664 lock(m_parts); 806 lockPartsForRead(true);
665 { 807 {
666 foreach (SceneObjectPart part in m_parts.Values) 808 foreach (SceneObjectPart part in m_parts.Values)
667 { 809 {
810
668 Vector3 worldPos = part.GetWorldPosition(); 811 Vector3 worldPos = part.GetWorldPosition();
669 Vector3 offset = worldPos - AbsolutePosition; 812 Vector3 offset = worldPos - AbsolutePosition;
670 Quaternion worldRot; 813 Quaternion worldRot;
@@ -723,6 +866,8 @@ namespace OpenSim.Region.Framework.Scenes
723 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 866 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
724 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 867 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
725 868
869
870
726 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); 871 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
727 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); 872 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
728 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); 873 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
@@ -894,6 +1039,7 @@ namespace OpenSim.Region.Framework.Scenes
894 minZ = backBottomLeft.Z; 1039 minZ = backBottomLeft.Z;
895 } 1040 }
896 } 1041 }
1042 lockPartsForRead(false);
897 } 1043 }
898 1044
899 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) 1045 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight)
@@ -929,21 +1075,29 @@ namespace OpenSim.Region.Framework.Scenes
929 1075
930 public void SaveScriptedState(XmlTextWriter writer) 1076 public void SaveScriptedState(XmlTextWriter writer)
931 { 1077 {
1078 SaveScriptedState(writer, false);
1079 }
1080
1081 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1082 {
932 XmlDocument doc = new XmlDocument(); 1083 XmlDocument doc = new XmlDocument();
933 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1084 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
934 1085
935 // Capture script state while holding the lock 1086 // Capture script state while holding the lock
936 lock (m_parts) 1087 lockPartsForRead(true);
937 { 1088 {
938 foreach (SceneObjectPart part in m_parts.Values) 1089 foreach (SceneObjectPart part in m_parts.Values)
939 { 1090 {
940 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); 1091
1092 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(oldIDs);
941 foreach (UUID itemid in pstates.Keys) 1093 foreach (UUID itemid in pstates.Keys)
942 { 1094 {
943 states.Add(itemid, pstates[itemid]); 1095 states.Add(itemid, pstates[itemid]);
944 } 1096 }
1097
945 } 1098 }
946 } 1099 }
1100 lockPartsForRead(false);
947 1101
948 if (states.Count > 0) 1102 if (states.Count > 0)
949 { 1103 {
@@ -1111,13 +1265,16 @@ namespace OpenSim.Region.Framework.Scenes
1111 1265
1112 public override void UpdateMovement() 1266 public override void UpdateMovement()
1113 { 1267 {
1114 lock (m_parts) 1268 lockPartsForRead(true);
1115 { 1269 {
1116 foreach (SceneObjectPart part in m_parts.Values) 1270 foreach (SceneObjectPart part in m_parts.Values)
1117 { 1271 {
1272
1118 part.UpdateMovement(); 1273 part.UpdateMovement();
1274
1119 } 1275 }
1120 } 1276 }
1277 lockPartsForRead(false);
1121 } 1278 }
1122 1279
1123 public ushort GetTimeDilation() 1280 public ushort GetTimeDilation()
@@ -1161,7 +1318,7 @@ namespace OpenSim.Region.Framework.Scenes
1161 /// <param name="part"></param> 1318 /// <param name="part"></param>
1162 public void AddPart(SceneObjectPart part) 1319 public void AddPart(SceneObjectPart part)
1163 { 1320 {
1164 lock (m_parts) 1321 lockPartsForWrite(true);
1165 { 1322 {
1166 part.SetParent(this); 1323 part.SetParent(this);
1167 m_parts.Add(part.UUID, part); 1324 m_parts.Add(part.UUID, part);
@@ -1171,6 +1328,7 @@ namespace OpenSim.Region.Framework.Scenes
1171 if (part.LinkNum == 2 && RootPart != null) 1328 if (part.LinkNum == 2 && RootPart != null)
1172 RootPart.LinkNum = 1; 1329 RootPart.LinkNum = 1;
1173 } 1330 }
1331 lockPartsForWrite(false);
1174 } 1332 }
1175 1333
1176 /// <summary> 1334 /// <summary>
@@ -1178,28 +1336,33 @@ namespace OpenSim.Region.Framework.Scenes
1178 /// </summary> 1336 /// </summary>
1179 private void UpdateParentIDs() 1337 private void UpdateParentIDs()
1180 { 1338 {
1181 lock (m_parts) 1339 lockPartsForRead(true);
1182 { 1340 {
1183 foreach (SceneObjectPart part in m_parts.Values) 1341 foreach (SceneObjectPart part in m_parts.Values)
1184 { 1342 {
1343
1185 if (part.UUID != m_rootPart.UUID) 1344 if (part.UUID != m_rootPart.UUID)
1186 { 1345 {
1187 part.ParentID = m_rootPart.LocalId; 1346 part.ParentID = m_rootPart.LocalId;
1188 } 1347 }
1348
1189 } 1349 }
1190 } 1350 }
1351 lockPartsForRead(false);
1191 } 1352 }
1192 1353
1193 public void RegenerateFullIDs() 1354 public void RegenerateFullIDs()
1194 { 1355 {
1195 lock (m_parts) 1356 lockPartsForRead(true);
1196 { 1357 {
1197 foreach (SceneObjectPart part in m_parts.Values) 1358 foreach (SceneObjectPart part in m_parts.Values)
1198 { 1359 {
1360
1199 part.UUID = UUID.Random(); 1361 part.UUID = UUID.Random();
1200 1362
1201 } 1363 }
1202 } 1364 }
1365 lockPartsForRead(false);
1203 } 1366 }
1204 1367
1205 // helper provided for parts. 1368 // helper provided for parts.
@@ -1280,27 +1443,32 @@ namespace OpenSim.Region.Framework.Scenes
1280 1443
1281 DetachFromBackup(); 1444 DetachFromBackup();
1282 1445
1283 lock (m_parts) 1446 lockPartsForRead(true);
1447 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1448 lockPartsForRead(false);
1449
1450 foreach (SceneObjectPart part in values)
1284 { 1451 {
1285 foreach (SceneObjectPart part in m_parts.Values)
1286 {
1287// part.Inventory.RemoveScriptInstances(); 1452// part.Inventory.RemoveScriptInstances();
1288 Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1453
1454 Scene.ForEachScenePresence(delegate (ScenePresence sp)
1455 {
1456 if (sp.ParentID == LocalId)
1289 { 1457 {
1290 if (avatar.ParentID == LocalId) 1458 sp.StandUp();
1291 { 1459 }
1292 avatar.StandUp();
1293 }
1294 1460
1295 if (!silent) 1461 if (!silent)
1296 { 1462 {
1297 part.UpdateFlag = 0; 1463 part.UpdateFlag = 0;
1298 if (part == m_rootPart) 1464 if (part == m_rootPart)
1299 avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId); 1465 sp.ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1300 } 1466 }
1301 }); 1467 });
1302 } 1468
1303 } 1469 }
1470
1471
1304 } 1472 }
1305 1473
1306 public void AddScriptLPS(int count) 1474 public void AddScriptLPS(int count)
@@ -1325,17 +1493,20 @@ namespace OpenSim.Region.Framework.Scenes
1325 1493
1326 scriptEvents aggregateScriptEvents=0; 1494 scriptEvents aggregateScriptEvents=0;
1327 1495
1328 lock (m_parts) 1496 lockPartsForRead(true);
1329 { 1497 {
1330 foreach (SceneObjectPart part in m_parts.Values) 1498 foreach (SceneObjectPart part in m_parts.Values)
1331 { 1499 {
1500
1332 if (part == null) 1501 if (part == null)
1333 continue; 1502 continue;
1334 if (part != RootPart) 1503 if (part != RootPart)
1335 part.ObjectFlags = objectflagupdate; 1504 part.ObjectFlags = objectflagupdate;
1336 aggregateScriptEvents |= part.AggregateScriptEvents; 1505 aggregateScriptEvents |= part.AggregateScriptEvents;
1506
1337 } 1507 }
1338 } 1508 }
1509 lockPartsForRead(false);
1339 1510
1340 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); 1511 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
1341 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); 1512 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0);
@@ -1377,42 +1548,52 @@ namespace OpenSim.Region.Framework.Scenes
1377 /// <param name="m_physicalPrim"></param> 1548 /// <param name="m_physicalPrim"></param>
1378 public void ApplyPhysics(bool m_physicalPrim) 1549 public void ApplyPhysics(bool m_physicalPrim)
1379 { 1550 {
1380 lock (m_parts) 1551 lockPartsForRead(true);
1552
1553 if (m_parts.Count > 1)
1381 { 1554 {
1382 if (m_parts.Count > 1) 1555 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1556 lockPartsForRead(false);
1557 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1558 foreach (SceneObjectPart part in values)
1383 { 1559 {
1384 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); 1560
1385 foreach (SceneObjectPart part in m_parts.Values) 1561 if (part.LocalId != m_rootPart.LocalId)
1386 { 1562 {
1387 if (part.LocalId != m_rootPart.LocalId) 1563 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1388 {
1389 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1390 }
1391 } 1564 }
1392 1565
1393 // Hack to get the physics scene geometries in the right spot
1394 ResetChildPrimPhysicsPositions();
1395 }
1396 else
1397 {
1398 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1399 } 1566 }
1567 // Hack to get the physics scene geometries in the right spot
1568 ResetChildPrimPhysicsPositions();
1569 }
1570 else
1571 {
1572 lockPartsForRead(false);
1573 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1400 } 1574 }
1401 } 1575 }
1402 1576
1403 public void SetOwnerId(UUID userId) 1577 public void SetOwnerId(UUID userId)
1404 { 1578 {
1405 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1579 ForEachPart(delegate(SceneObjectPart part)
1580 {
1581
1582 part.OwnerID = userId;
1583
1584 });
1406 } 1585 }
1407 1586
1408 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1587 public void ForEachPart(Action<SceneObjectPart> whatToDo)
1409 { 1588 {
1410 lock (m_parts) 1589 lockPartsForRead(true);
1590 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1591 lockPartsForRead(false);
1592 foreach (SceneObjectPart part in values)
1411 { 1593 {
1412 foreach (SceneObjectPart part in m_parts.Values) 1594
1413 { 1595 whatToDo(part);
1414 whatToDo(part); 1596
1415 }
1416 } 1597 }
1417 } 1598 }
1418 1599
@@ -1510,15 +1691,17 @@ namespace OpenSim.Region.Framework.Scenes
1510 RootPart.SendFullUpdate( 1691 RootPart.SendFullUpdate(
1511 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); 1692 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
1512 1693
1513 lock (m_parts) 1694 lockPartsForRead(true);
1514 { 1695 {
1515 foreach (SceneObjectPart part in m_parts.Values) 1696 foreach (SceneObjectPart part in m_parts.Values)
1516 { 1697 {
1698
1517 if (part != RootPart) 1699 if (part != RootPart)
1518 part.SendFullUpdate( 1700 part.SendFullUpdate(
1519 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); 1701 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
1520 } 1702 }
1521 } 1703 }
1704 lockPartsForRead(false);
1522 } 1705 }
1523 1706
1524 #region Copying 1707 #region Copying
@@ -1587,10 +1770,11 @@ namespace OpenSim.Region.Framework.Scenes
1587 1770
1588 List<SceneObjectPart> partList; 1771 List<SceneObjectPart> partList;
1589 1772
1590 lock (m_parts) 1773 lockPartsForRead(true);
1591 { 1774
1592 partList = new List<SceneObjectPart>(m_parts.Values); 1775 partList = new List<SceneObjectPart>(m_parts.Values);
1593 } 1776
1777 lockPartsForRead(false);
1594 1778
1595 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1779 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1596 { 1780 {
@@ -1813,13 +1997,40 @@ namespace OpenSim.Region.Framework.Scenes
1813 } 1997 }
1814 } 1998 }
1815 1999
2000 public void rotLookAt(Quaternion target, float strength, float damping)
2001 {
2002 SceneObjectPart rootpart = m_rootPart;
2003 if (rootpart != null)
2004 {
2005 if (IsAttachment)
2006 {
2007 /*
2008 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2009 if (avatar != null)
2010 {
2011 Rotate the Av?
2012 } */
2013 }
2014 else
2015 {
2016 if (rootpart.PhysActor != null)
2017 { // APID must be implemented in your physics system for this to function.
2018 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2019 rootpart.PhysActor.APIDStrength = strength;
2020 rootpart.PhysActor.APIDDamping = damping;
2021 rootpart.PhysActor.APIDActive = true;
2022 }
2023 }
2024 }
2025 }
2026
1816 public void stopLookAt() 2027 public void stopLookAt()
1817 { 2028 {
1818 SceneObjectPart rootpart = m_rootPart; 2029 SceneObjectPart rootpart = m_rootPart;
1819 if (rootpart != null) 2030 if (rootpart != null)
1820 { 2031 {
1821 if (rootpart.PhysActor != null) 2032 if (rootpart.PhysActor != null)
1822 { 2033 { // APID must be implemented in your physics system for this to function.
1823 rootpart.PhysActor.APIDActive = false; 2034 rootpart.PhysActor.APIDActive = false;
1824 } 2035 }
1825 } 2036 }
@@ -1887,10 +2098,11 @@ namespace OpenSim.Region.Framework.Scenes
1887 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2098 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1888 newPart.SetParent(this); 2099 newPart.SetParent(this);
1889 2100
1890 lock (m_parts) 2101 lockPartsForWrite(true);
1891 { 2102 {
1892 m_parts.Add(newPart.UUID, newPart); 2103 m_parts.Add(newPart.UUID, newPart);
1893 } 2104 }
2105 lockPartsForWrite(false);
1894 2106
1895 SetPartAsNonRoot(newPart); 2107 SetPartAsNonRoot(newPart);
1896 2108
@@ -1953,7 +2165,7 @@ namespace OpenSim.Region.Framework.Scenes
1953 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2165 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1954 // return; 2166 // return;
1955 2167
1956 lock (m_parts) 2168 lockPartsForRead(true);
1957 { 2169 {
1958 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2170 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1959 2171
@@ -1973,9 +2185,12 @@ namespace OpenSim.Region.Framework.Scenes
1973 { 2185 {
1974 if (!IsSelected) 2186 if (!IsSelected)
1975 part.UpdateLookAt(); 2187 part.UpdateLookAt();
2188
1976 part.SendScheduledUpdates(); 2189 part.SendScheduledUpdates();
2190
1977 } 2191 }
1978 } 2192 }
2193 lockPartsForRead(false);
1979 } 2194 }
1980 2195
1981 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2196 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
@@ -1984,27 +2199,29 @@ namespace OpenSim.Region.Framework.Scenes
1984 2199
1985 RootPart.AddFullUpdateToAvatar(presence); 2200 RootPart.AddFullUpdateToAvatar(presence);
1986 2201
1987 lock (m_parts) 2202 lockPartsForRead(true);
1988 { 2203 {
1989 foreach (SceneObjectPart part in m_parts.Values) 2204 foreach (SceneObjectPart part in m_parts.Values)
1990 { 2205 {
2206
1991 if (part != RootPart) 2207 if (part != RootPart)
1992 part.AddFullUpdateToAvatar(presence); 2208 part.AddFullUpdateToAvatar(presence);
2209
1993 } 2210 }
1994 } 2211 }
2212 lockPartsForRead(false);
1995 } 2213 }
1996 2214
1997 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2215 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
1998 { 2216 {
1999// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); 2217 lockPartsForRead(true);
2000 2218
2001 lock (m_parts) 2219 foreach (SceneObjectPart part in m_parts.Values)
2002 { 2220 {
2003 foreach (SceneObjectPart part in m_parts.Values) 2221 part.AddTerseUpdateToAvatar(presence);
2004 {
2005 part.AddTerseUpdateToAvatar(presence);
2006 }
2007 } 2222 }
2223
2224 lockPartsForRead(false);
2008 } 2225 }
2009 2226
2010 /// <summary> 2227 /// <summary>
@@ -2017,14 +2234,17 @@ namespace OpenSim.Region.Framework.Scenes
2017 checkAtTargets(); 2234 checkAtTargets();
2018 RootPart.ScheduleFullUpdate(); 2235 RootPart.ScheduleFullUpdate();
2019 2236
2020 lock (m_parts) 2237 lockPartsForRead(true);
2021 { 2238 {
2022 foreach (SceneObjectPart part in m_parts.Values) 2239 foreach (SceneObjectPart part in m_parts.Values)
2023 { 2240 {
2241
2024 if (part != RootPart) 2242 if (part != RootPart)
2025 part.ScheduleFullUpdate(); 2243 part.ScheduleFullUpdate();
2244
2026 } 2245 }
2027 } 2246 }
2247 lockPartsForRead(false);
2028 } 2248 }
2029 2249
2030 /// <summary> 2250 /// <summary>
@@ -2032,37 +2252,38 @@ namespace OpenSim.Region.Framework.Scenes
2032 /// </summary> 2252 /// </summary>
2033 public void ScheduleGroupForTerseUpdate() 2253 public void ScheduleGroupForTerseUpdate()
2034 { 2254 {
2035// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); 2255 lockPartsForRead(true);
2036 2256 foreach (SceneObjectPart part in m_parts.Values)
2037 lock (m_parts)
2038 { 2257 {
2039 foreach (SceneObjectPart part in m_parts.Values) 2258 part.ScheduleTerseUpdate();
2040 {
2041 part.ScheduleTerseUpdate();
2042 }
2043 } 2259 }
2260
2261 lockPartsForRead(false);
2044 } 2262 }
2045 2263
2046 /// <summary> 2264 /// <summary>
2047 /// Immediately send a full update for this scene object. 2265 /// Immediately send a full update for this scene object.
2048 /// </summary> 2266 /// </summary>
2049 public void SendGroupFullUpdate() 2267 public void SendGroupFullUpdate()
2050 { 2268 {
2051 if (IsDeleted) 2269 if (IsDeleted)
2052 return; 2270 return;
2053 2271
2054// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2272// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
2055 2273
2056 RootPart.SendFullUpdateToAllClients(); 2274 RootPart.SendFullUpdateToAllClients();
2057 2275
2058 lock (m_parts) 2276 lockPartsForRead(true);
2059 { 2277 {
2060 foreach (SceneObjectPart part in m_parts.Values) 2278 foreach (SceneObjectPart part in m_parts.Values)
2061 { 2279 {
2280
2062 if (part != RootPart) 2281 if (part != RootPart)
2063 part.SendFullUpdateToAllClients(); 2282 part.SendFullUpdateToAllClients();
2283
2064 } 2284 }
2065 } 2285 }
2286 lockPartsForRead(false);
2066 } 2287 }
2067 2288
2068 /// <summary> 2289 /// <summary>
@@ -2094,14 +2315,15 @@ namespace OpenSim.Region.Framework.Scenes
2094 { 2315 {
2095 if (IsDeleted) 2316 if (IsDeleted)
2096 return; 2317 return;
2097 2318
2098 lock (m_parts) 2319 lockPartsForRead(true);
2099 { 2320 {
2100 foreach (SceneObjectPart part in m_parts.Values) 2321 foreach (SceneObjectPart part in m_parts.Values)
2101 { 2322 {
2102 part.SendTerseUpdateToAllClients(); 2323 part.SendTerseUpdateToAllClients();
2103 } 2324 }
2104 } 2325 }
2326 lockPartsForRead(false);
2105 } 2327 }
2106 2328
2107 #endregion 2329 #endregion
@@ -2115,16 +2337,18 @@ namespace OpenSim.Region.Framework.Scenes
2115 /// <returns>null if no child part with that linknum or child part</returns> 2337 /// <returns>null if no child part with that linknum or child part</returns>
2116 public SceneObjectPart GetLinkNumPart(int linknum) 2338 public SceneObjectPart GetLinkNumPart(int linknum)
2117 { 2339 {
2118 lock (m_parts) 2340 lockPartsForRead(true);
2119 { 2341 {
2120 foreach (SceneObjectPart part in m_parts.Values) 2342 foreach (SceneObjectPart part in m_parts.Values)
2121 { 2343 {
2122 if (part.LinkNum == linknum) 2344 if (part.LinkNum == linknum)
2123 { 2345 {
2346 lockPartsForRead(false);
2124 return part; 2347 return part;
2125 } 2348 }
2126 } 2349 }
2127 } 2350 }
2351 lockPartsForRead(false);
2128 2352
2129 return null; 2353 return null;
2130 } 2354 }
@@ -2152,17 +2376,19 @@ namespace OpenSim.Region.Framework.Scenes
2152 public SceneObjectPart GetChildPart(uint localID) 2376 public SceneObjectPart GetChildPart(uint localID)
2153 { 2377 {
2154 //m_log.DebugFormat("Entered looking for {0}", localID); 2378 //m_log.DebugFormat("Entered looking for {0}", localID);
2155 lock (m_parts) 2379 lockPartsForRead(true);
2156 { 2380 {
2157 foreach (SceneObjectPart part in m_parts.Values) 2381 foreach (SceneObjectPart part in m_parts.Values)
2158 { 2382 {
2159 //m_log.DebugFormat("Found {0}", part.LocalId); 2383 //m_log.DebugFormat("Found {0}", part.LocalId);
2160 if (part.LocalId == localID) 2384 if (part.LocalId == localID)
2161 { 2385 {
2386 lockPartsForRead(false);
2162 return part; 2387 return part;
2163 } 2388 }
2164 } 2389 }
2165 } 2390 }
2391 lockPartsForRead(false);
2166 2392
2167 return null; 2393 return null;
2168 } 2394 }
@@ -2192,17 +2418,19 @@ namespace OpenSim.Region.Framework.Scenes
2192 public bool HasChildPrim(uint localID) 2418 public bool HasChildPrim(uint localID)
2193 { 2419 {
2194 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2420 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2195 lock (m_parts) 2421 lockPartsForRead(true);
2196 { 2422 {
2197 foreach (SceneObjectPart part in m_parts.Values) 2423 foreach (SceneObjectPart part in m_parts.Values)
2198 { 2424 {
2199 //m_log.DebugFormat("Found {0}", part.LocalId); 2425 //m_log.DebugFormat("Found {0}", part.LocalId);
2200 if (part.LocalId == localID) 2426 if (part.LocalId == localID)
2201 { 2427 {
2428 lockPartsForRead(false);
2202 return true; 2429 return true;
2203 } 2430 }
2204 } 2431 }
2205 } 2432 }
2433 lockPartsForRead(false);
2206 2434
2207 return false; 2435 return false;
2208 } 2436 }
@@ -2252,53 +2480,57 @@ namespace OpenSim.Region.Framework.Scenes
2252 if (m_rootPart.LinkNum == 0) 2480 if (m_rootPart.LinkNum == 0)
2253 m_rootPart.LinkNum = 1; 2481 m_rootPart.LinkNum = 1;
2254 2482
2255 lock (m_parts) 2483 lockPartsForWrite(true);
2256 { 2484
2257 m_parts.Add(linkPart.UUID, linkPart); 2485 m_parts.Add(linkPart.UUID, linkPart);
2486
2487 lockPartsForWrite(false);
2258 2488
2259 // Insert in terms of link numbers, the new links 2489 // Insert in terms of link numbers, the new links
2260 // before the current ones (with the exception of 2490 // before the current ones (with the exception of
2261 // the root prim. Shuffle the old ones up 2491 // the root prim. Shuffle the old ones up
2262 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2492 lockPartsForRead(true);
2493 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2494 {
2495 if (kvp.Value.LinkNum != 1)
2263 { 2496 {
2264 if (kvp.Value.LinkNum != 1) 2497 // Don't update root prim link number
2265 { 2498 kvp.Value.LinkNum += objectGroup.PrimCount;
2266 // Don't update root prim link number
2267 kvp.Value.LinkNum += objectGroup.PrimCount;
2268 }
2269 } 2499 }
2500 }
2501 lockPartsForRead(false);
2270 2502
2271 linkPart.LinkNum = 2; 2503 linkPart.LinkNum = 2;
2272 2504
2273 linkPart.SetParent(this); 2505 linkPart.SetParent(this);
2274 linkPart.CreateSelected = true; 2506 linkPart.CreateSelected = true;
2275 2507
2276 //if (linkPart.PhysActor != null) 2508 //if (linkPart.PhysActor != null)
2277 //{ 2509 //{
2278 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2510 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2279 2511
2280 //linkPart.PhysActor = null; 2512 //linkPart.PhysActor = null;
2281 //} 2513 //}
2282 2514
2283 //TODO: rest of parts 2515 //TODO: rest of parts
2284 int linkNum = 3; 2516 int linkNum = 3;
2285 foreach (SceneObjectPart part in objectGroup.Children.Values) 2517 foreach (SceneObjectPart part in objectGroup.Children.Values)
2518 {
2519 if (part.UUID != objectGroup.m_rootPart.UUID)
2286 { 2520 {
2287 if (part.UUID != objectGroup.m_rootPart.UUID) 2521 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2288 {
2289 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2290 }
2291 part.ClearUndoState();
2292 } 2522 }
2523 part.ClearUndoState();
2293 } 2524 }
2294 2525
2295 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2526 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2296 objectGroup.m_isDeleted = true; 2527 objectGroup.m_isDeleted = true;
2528
2529 objectGroup.lockPartsForWrite(true);
2297 2530
2298 lock (objectGroup.m_parts) 2531 objectGroup.m_parts.Clear();
2299 { 2532
2300 objectGroup.m_parts.Clear(); 2533 objectGroup.lockPartsForWrite(false);
2301 }
2302 2534
2303 // Can't do this yet since backup still makes use of the root part without any synchronization 2535 // Can't do this yet since backup still makes use of the root part without any synchronization
2304// objectGroup.m_rootPart = null; 2536// objectGroup.m_rootPart = null;
@@ -2368,11 +2600,12 @@ namespace OpenSim.Region.Framework.Scenes
2368 Quaternion worldRot = linkPart.GetWorldRotation(); 2600 Quaternion worldRot = linkPart.GetWorldRotation();
2369 2601
2370 // Remove the part from this object 2602 // Remove the part from this object
2371 lock (m_parts) 2603 lockPartsForWrite(true);
2372 { 2604 {
2373 m_parts.Remove(linkPart.UUID); 2605 m_parts.Remove(linkPart.UUID);
2374 } 2606 }
2375 2607 lockPartsForWrite(false);
2608 lockPartsForRead(true);
2376 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2609 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2377 RootPart.LinkNum = 0; 2610 RootPart.LinkNum = 0;
2378 else 2611 else
@@ -2383,6 +2616,7 @@ namespace OpenSim.Region.Framework.Scenes
2383 p.LinkNum--; 2616 p.LinkNum--;
2384 } 2617 }
2385 } 2618 }
2619 lockPartsForRead(false);
2386 2620
2387 linkPart.ParentID = 0; 2621 linkPart.ParentID = 0;
2388 linkPart.LinkNum = 0; 2622 linkPart.LinkNum = 0;
@@ -2704,9 +2938,12 @@ namespace OpenSim.Region.Framework.Scenes
2704 2938
2705 if (selectionPart != null) 2939 if (selectionPart != null)
2706 { 2940 {
2707 lock (m_parts) 2941 lockPartsForRead(true);
2942 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
2943 lockPartsForRead(false);
2944 foreach (SceneObjectPart part in parts)
2708 { 2945 {
2709 foreach (SceneObjectPart part in m_parts.Values) 2946 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2710 { 2947 {
2711 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 2948 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2712 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 2949 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
@@ -2716,12 +2953,13 @@ namespace OpenSim.Region.Framework.Scenes
2716 break; 2953 break;
2717 } 2954 }
2718 } 2955 }
2956 }
2719 2957
2720 foreach (SceneObjectPart part in m_parts.Values) 2958 foreach (SceneObjectPart part in parts)
2721 { 2959 {
2722 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2960 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2723 }
2724 } 2961 }
2962
2725 } 2963 }
2726 } 2964 }
2727 2965
@@ -2807,11 +3045,9 @@ namespace OpenSim.Region.Framework.Scenes
2807 scale.Y = m_scene.m_maxNonphys; 3045 scale.Y = m_scene.m_maxNonphys;
2808 if (scale.Z > m_scene.m_maxNonphys) 3046 if (scale.Z > m_scene.m_maxNonphys)
2809 scale.Z = m_scene.m_maxNonphys; 3047 scale.Z = m_scene.m_maxNonphys;
2810
2811 SceneObjectPart part = GetChildPart(localID); 3048 SceneObjectPart part = GetChildPart(localID);
2812 if (part != null) 3049 if (part != null)
2813 { 3050 {
2814 part.Resize(scale);
2815 if (part.PhysActor != null) 3051 if (part.PhysActor != null)
2816 { 3052 {
2817 if (part.PhysActor.IsPhysical) 3053 if (part.PhysActor.IsPhysical)
@@ -2826,7 +3062,7 @@ namespace OpenSim.Region.Framework.Scenes
2826 part.PhysActor.Size = scale; 3062 part.PhysActor.Size = scale;
2827 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 3063 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2828 } 3064 }
2829 //if (part.UUID != m_rootPart.UUID) 3065 part.Resize(scale);
2830 3066
2831 HasGroupChanged = true; 3067 HasGroupChanged = true;
2832 ScheduleGroupForFullUpdate(); 3068 ScheduleGroupForFullUpdate();
@@ -2868,73 +3104,71 @@ namespace OpenSim.Region.Framework.Scenes
2868 float y = (scale.Y / part.Scale.Y); 3104 float y = (scale.Y / part.Scale.Y);
2869 float z = (scale.Z / part.Scale.Z); 3105 float z = (scale.Z / part.Scale.Z);
2870 3106
2871 lock (m_parts) 3107 lockPartsForRead(true);
3108 if (x > 1.0f || y > 1.0f || z > 1.0f)
2872 { 3109 {
2873 if (x > 1.0f || y > 1.0f || z > 1.0f) 3110 foreach (SceneObjectPart obPart in m_parts.Values)
2874 { 3111 {
2875 foreach (SceneObjectPart obPart in m_parts.Values) 3112 if (obPart.UUID != m_rootPart.UUID)
2876 { 3113 {
2877 if (obPart.UUID != m_rootPart.UUID) 3114 Vector3 oldSize = new Vector3(obPart.Scale);
2878 { 3115 obPart.IgnoreUndoUpdate = true;
2879 obPart.IgnoreUndoUpdate = true;
2880 Vector3 oldSize = new Vector3(obPart.Scale);
2881 3116
2882 float f = 1.0f; 3117 float f = 1.0f;
2883 float a = 1.0f; 3118 float a = 1.0f;
2884 3119
2885 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3120 if (part.PhysActor != null && part.PhysActor.IsPhysical)
3121 {
3122 if (oldSize.X*x > m_scene.m_maxPhys)
2886 { 3123 {
2887 if (oldSize.X*x > m_scene.m_maxPhys) 3124 f = m_scene.m_maxPhys / oldSize.X;
2888 { 3125 a = f / x;
2889 f = m_scene.m_maxPhys / oldSize.X; 3126 x *= a;
2890 a = f / x; 3127 y *= a;
2891 x *= a; 3128 z *= a;
2892 y *= a;
2893 z *= a;
2894 }
2895 if (oldSize.Y*y > m_scene.m_maxPhys)
2896 {
2897 f = m_scene.m_maxPhys / oldSize.Y;
2898 a = f / y;
2899 x *= a;
2900 y *= a;
2901 z *= a;
2902 }
2903 if (oldSize.Z*z > m_scene.m_maxPhys)
2904 {
2905 f = m_scene.m_maxPhys / oldSize.Z;
2906 a = f / z;
2907 x *= a;
2908 y *= a;
2909 z *= a;
2910 }
2911 } 3129 }
2912 else 3130 if (oldSize.Y*y > m_scene.m_maxPhys)
2913 { 3131 {
2914 if (oldSize.X*x > m_scene.m_maxNonphys) 3132 f = m_scene.m_maxPhys / oldSize.Y;
2915 { 3133 a = f / y;
2916 f = m_scene.m_maxNonphys / oldSize.X; 3134 x *= a;
2917 a = f / x; 3135 y *= a;
2918 x *= a; 3136 z *= a;
2919 y *= a; 3137 }
2920 z *= a; 3138 if (oldSize.Z*z > m_scene.m_maxPhys)
2921 } 3139 {
2922 if (oldSize.Y*y > m_scene.m_maxNonphys) 3140 f = m_scene.m_maxPhys / oldSize.Z;
2923 { 3141 a = f / z;
2924 f = m_scene.m_maxNonphys / oldSize.Y; 3142 x *= a;
2925 a = f / y; 3143 y *= a;
2926 x *= a; 3144 z *= a;
2927 y *= a; 3145 }
2928 z *= a; 3146 }
2929 } 3147 else
2930 if (oldSize.Z*z > m_scene.m_maxNonphys) 3148 {
2931 { 3149 if (oldSize.X*x > m_scene.m_maxNonphys)
2932 f = m_scene.m_maxNonphys / oldSize.Z; 3150 {
2933 a = f / z; 3151 f = m_scene.m_maxNonphys / oldSize.X;
2934 x *= a; 3152 a = f / x;
2935 y *= a; 3153 x *= a;
2936 z *= a; 3154 y *= a;
2937 } 3155 z *= a;
3156 }
3157 if (oldSize.Y*y > m_scene.m_maxNonphys)
3158 {
3159 f = m_scene.m_maxNonphys / oldSize.Y;
3160 a = f / y;
3161 x *= a;
3162 y *= a;
3163 z *= a;
3164 }
3165 if (oldSize.Z*z > m_scene.m_maxNonphys)
3166 {
3167 f = m_scene.m_maxNonphys / oldSize.Z;
3168 a = f / z;
3169 x *= a;
3170 y *= a;
3171 z *= a;
2938 } 3172 }
2939 obPart.IgnoreUndoUpdate = false; 3173 obPart.IgnoreUndoUpdate = false;
2940 obPart.StoreUndoState(); 3174 obPart.StoreUndoState();
@@ -2942,6 +3176,7 @@ namespace OpenSim.Region.Framework.Scenes
2942 } 3176 }
2943 } 3177 }
2944 } 3178 }
3179 lockPartsForRead(false);
2945 3180
2946 Vector3 prevScale = part.Scale; 3181 Vector3 prevScale = part.Scale;
2947 prevScale.X *= x; 3182 prevScale.X *= x;
@@ -2949,7 +3184,7 @@ namespace OpenSim.Region.Framework.Scenes
2949 prevScale.Z *= z; 3184 prevScale.Z *= z;
2950 part.Resize(prevScale); 3185 part.Resize(prevScale);
2951 3186
2952 lock (m_parts) 3187 lockPartsForRead(true);
2953 { 3188 {
2954 foreach (SceneObjectPart obPart in m_parts.Values) 3189 foreach (SceneObjectPart obPart in m_parts.Values)
2955 { 3190 {
@@ -2971,6 +3206,7 @@ namespace OpenSim.Region.Framework.Scenes
2971 obPart.StoreUndoState(); 3206 obPart.StoreUndoState();
2972 } 3207 }
2973 } 3208 }
3209 lockPartsForRead(false);
2974 3210
2975 if (part.PhysActor != null) 3211 if (part.PhysActor != null)
2976 { 3212 {
@@ -3073,7 +3309,7 @@ namespace OpenSim.Region.Framework.Scenes
3073 axDiff *= Quaternion.Inverse(partRotation); 3309 axDiff *= Quaternion.Inverse(partRotation);
3074 diff = axDiff; 3310 diff = axDiff;
3075 3311
3076 lock (m_parts) 3312 lockPartsForRead(true);
3077 { 3313 {
3078 foreach (SceneObjectPart obPart in m_parts.Values) 3314 foreach (SceneObjectPart obPart in m_parts.Values)
3079 { 3315 {
@@ -3083,6 +3319,7 @@ namespace OpenSim.Region.Framework.Scenes
3083 } 3319 }
3084 } 3320 }
3085 } 3321 }
3322 lockPartsForRead(false);
3086 3323
3087 AbsolutePosition = newPos; 3324 AbsolutePosition = newPos;
3088 3325
@@ -3216,25 +3453,25 @@ namespace OpenSim.Region.Framework.Scenes
3216 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3453 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3217 } 3454 }
3218 3455
3219 lock (m_parts) 3456 lockPartsForRead(true);
3457
3458 foreach (SceneObjectPart prim in m_parts.Values)
3220 { 3459 {
3221 foreach (SceneObjectPart prim in m_parts.Values) 3460 if (prim.UUID != m_rootPart.UUID)
3222 { 3461 {
3223 if (prim.UUID != m_rootPart.UUID) 3462 prim.IgnoreUndoUpdate = true;
3224 { 3463 Vector3 axPos = prim.OffsetPosition;
3225 prim.IgnoreUndoUpdate = true; 3464 axPos *= oldParentRot;
3226 Vector3 axPos = prim.OffsetPosition; 3465 axPos *= Quaternion.Inverse(axRot);
3227 axPos *= oldParentRot; 3466 prim.OffsetPosition = axPos;
3228 axPos *= Quaternion.Inverse(axRot); 3467 Quaternion primsRot = prim.RotationOffset;
3229 prim.OffsetPosition = axPos; 3468 Quaternion newRot = primsRot * oldParentRot;
3230 Quaternion primsRot = prim.RotationOffset; 3469 newRot *= Quaternion.Inverse(axRot);
3231 Quaternion newRot = primsRot * oldParentRot; 3470 prim.RotationOffset = newRot;
3232 newRot *= Quaternion.Inverse(axRot); 3471 prim.ScheduleTerseUpdate();
3233 prim.RotationOffset = newRot;
3234 prim.ScheduleTerseUpdate();
3235 }
3236 } 3472 }
3237 } 3473 }
3474
3238 foreach (SceneObjectPart childpart in Children.Values) 3475 foreach (SceneObjectPart childpart in Children.Values)
3239 { 3476 {
3240 if (childpart != m_rootPart) 3477 if (childpart != m_rootPart)
@@ -3243,6 +3480,9 @@ namespace OpenSim.Region.Framework.Scenes
3243 childpart.StoreUndoState(); 3480 childpart.StoreUndoState();
3244 } 3481 }
3245 } 3482 }
3483
3484 lockPartsForRead(false);
3485
3246 m_rootPart.ScheduleTerseUpdate(); 3486 m_rootPart.ScheduleTerseUpdate();
3247 } 3487 }
3248 3488
@@ -3364,7 +3604,7 @@ namespace OpenSim.Region.Framework.Scenes
3364 if (atTargets.Count > 0) 3604 if (atTargets.Count > 0)
3365 { 3605 {
3366 uint[] localids = new uint[0]; 3606 uint[] localids = new uint[0];
3367 lock (m_parts) 3607 lockPartsForRead(true);
3368 { 3608 {
3369 localids = new uint[m_parts.Count]; 3609 localids = new uint[m_parts.Count];
3370 int cntr = 0; 3610 int cntr = 0;
@@ -3374,6 +3614,7 @@ namespace OpenSim.Region.Framework.Scenes
3374 cntr++; 3614 cntr++;
3375 } 3615 }
3376 } 3616 }
3617 lockPartsForRead(false);
3377 3618
3378 for (int ctr = 0; ctr < localids.Length; ctr++) 3619 for (int ctr = 0; ctr < localids.Length; ctr++)
3379 { 3620 {
@@ -3392,7 +3633,7 @@ namespace OpenSim.Region.Framework.Scenes
3392 { 3633 {
3393 //trigger not_at_target 3634 //trigger not_at_target
3394 uint[] localids = new uint[0]; 3635 uint[] localids = new uint[0];
3395 lock (m_parts) 3636 lockPartsForRead(true);
3396 { 3637 {
3397 localids = new uint[m_parts.Count]; 3638 localids = new uint[m_parts.Count];
3398 int cntr = 0; 3639 int cntr = 0;
@@ -3402,7 +3643,8 @@ namespace OpenSim.Region.Framework.Scenes
3402 cntr++; 3643 cntr++;
3403 } 3644 }
3404 } 3645 }
3405 3646 lockPartsForRead(false);
3647
3406 for (int ctr = 0; ctr < localids.Length; ctr++) 3648 for (int ctr = 0; ctr < localids.Length; ctr++)
3407 { 3649 {
3408 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3650 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3443,7 +3685,8 @@ namespace OpenSim.Region.Framework.Scenes
3443 if (atRotTargets.Count > 0) 3685 if (atRotTargets.Count > 0)
3444 { 3686 {
3445 uint[] localids = new uint[0]; 3687 uint[] localids = new uint[0];
3446 lock (m_parts) 3688 lockPartsForRead(true);
3689 try
3447 { 3690 {
3448 localids = new uint[m_parts.Count]; 3691 localids = new uint[m_parts.Count];
3449 int cntr = 0; 3692 int cntr = 0;
@@ -3453,6 +3696,10 @@ namespace OpenSim.Region.Framework.Scenes
3453 cntr++; 3696 cntr++;
3454 } 3697 }
3455 } 3698 }
3699 finally
3700 {
3701 lockPartsForRead(false);
3702 }
3456 3703
3457 for (int ctr = 0; ctr < localids.Length; ctr++) 3704 for (int ctr = 0; ctr < localids.Length; ctr++)
3458 { 3705 {
@@ -3471,7 +3718,8 @@ namespace OpenSim.Region.Framework.Scenes
3471 { 3718 {
3472 //trigger not_at_target 3719 //trigger not_at_target
3473 uint[] localids = new uint[0]; 3720 uint[] localids = new uint[0];
3474 lock (m_parts) 3721 lockPartsForRead(true);
3722 try
3475 { 3723 {
3476 localids = new uint[m_parts.Count]; 3724 localids = new uint[m_parts.Count];
3477 int cntr = 0; 3725 int cntr = 0;
@@ -3481,6 +3729,10 @@ namespace OpenSim.Region.Framework.Scenes
3481 cntr++; 3729 cntr++;
3482 } 3730 }
3483 } 3731 }
3732 finally
3733 {
3734 lockPartsForRead(false);
3735 }
3484 3736
3485 for (int ctr = 0; ctr < localids.Length; ctr++) 3737 for (int ctr = 0; ctr < localids.Length; ctr++)
3486 { 3738 {
@@ -3494,19 +3746,20 @@ namespace OpenSim.Region.Framework.Scenes
3494 public float GetMass() 3746 public float GetMass()
3495 { 3747 {
3496 float retmass = 0f; 3748 float retmass = 0f;
3497 lock (m_parts) 3749 lockPartsForRead(true);
3498 { 3750 {
3499 foreach (SceneObjectPart part in m_parts.Values) 3751 foreach (SceneObjectPart part in m_parts.Values)
3500 { 3752 {
3501 retmass += part.GetMass(); 3753 retmass += part.GetMass();
3502 } 3754 }
3503 } 3755 }
3756 lockPartsForRead(false);
3504 return retmass; 3757 return retmass;
3505 } 3758 }
3506 3759
3507 public void CheckSculptAndLoad() 3760 public void CheckSculptAndLoad()
3508 { 3761 {
3509 lock (m_parts) 3762 lockPartsForRead(true);
3510 { 3763 {
3511 if (!IsDeleted) 3764 if (!IsDeleted)
3512 { 3765 {
@@ -3531,6 +3784,7 @@ namespace OpenSim.Region.Framework.Scenes
3531 } 3784 }
3532 } 3785 }
3533 } 3786 }
3787 lockPartsForRead(false);
3534 } 3788 }
3535 3789
3536 protected void AssetReceived(string id, Object sender, AssetBase asset) 3790 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3551,7 +3805,7 @@ namespace OpenSim.Region.Framework.Scenes
3551 /// <param name="client"></param> 3805 /// <param name="client"></param>
3552 public void SetGroup(UUID GroupID, IClientAPI client) 3806 public void SetGroup(UUID GroupID, IClientAPI client)
3553 { 3807 {
3554 lock (m_parts) 3808 lockPartsForRead(true);
3555 { 3809 {
3556 foreach (SceneObjectPart part in m_parts.Values) 3810 foreach (SceneObjectPart part in m_parts.Values)
3557 { 3811 {
@@ -3561,6 +3815,7 @@ namespace OpenSim.Region.Framework.Scenes
3561 3815
3562 HasGroupChanged = true; 3816 HasGroupChanged = true;
3563 } 3817 }
3818 lockPartsForRead(false);
3564 3819
3565 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 3820 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
3566 // for the same object with very different properties. The caller must schedule the update. 3821 // for the same object with very different properties. The caller must schedule the update.
@@ -3582,11 +3837,12 @@ namespace OpenSim.Region.Framework.Scenes
3582 3837
3583 public void SetAttachmentPoint(byte point) 3838 public void SetAttachmentPoint(byte point)
3584 { 3839 {
3585 lock (m_parts) 3840 lockPartsForRead(true);
3586 { 3841 {
3587 foreach (SceneObjectPart part in m_parts.Values) 3842 foreach (SceneObjectPart part in m_parts.Values)
3588 part.SetAttachmentPoint(point); 3843 part.SetAttachmentPoint(point);
3589 } 3844 }
3845 lockPartsForRead(false);
3590 } 3846 }
3591 3847
3592 #region ISceneObject 3848 #region ISceneObject
@@ -3620,6 +3876,14 @@ namespace OpenSim.Region.Framework.Scenes
3620 SetFromItemID(uuid); 3876 SetFromItemID(uuid);
3621 } 3877 }
3622 3878
3879 public void ResetOwnerChangeFlag()
3880 {
3881 ForEachPart(delegate(SceneObjectPart part)
3882 {
3883 part.ResetOwnerChangeFlag();
3884 });
3885 }
3886
3623 #endregion 3887 #endregion
3624 } 3888 }
3625} 3889}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 38b2dc2..e4a36ef 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);
@@ -453,12 +454,16 @@ namespace OpenSim.Region.Framework.Scenes
453 } 454 }
454 455
455 /// <value> 456 /// <value>
456 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 457 /// Get the inventory list
457 /// </value> 458 /// </value>
458 public TaskInventoryDictionary TaskInventory 459 public TaskInventoryDictionary TaskInventory
459 { 460 {
460 get { return m_inventory.Items; } 461 get {
461 set { m_inventory.Items = value; } 462 return m_inventory.Items;
463 }
464 set {
465 m_inventory.Items = value;
466 }
462 } 467 }
463 468
464 public uint ObjectFlags 469 public uint ObjectFlags
@@ -587,14 +592,12 @@ namespace OpenSim.Region.Framework.Scenes
587 set { m_LoopSoundSlavePrims = value; } 592 set { m_LoopSoundSlavePrims = value; }
588 } 593 }
589 594
590 [XmlIgnore]
591 public Byte[] TextureAnimation 595 public Byte[] TextureAnimation
592 { 596 {
593 get { return m_TextureAnimation; } 597 get { return m_TextureAnimation; }
594 set { m_TextureAnimation = value; } 598 set { m_TextureAnimation = value; }
595 } 599 }
596 600
597 [XmlIgnore]
598 public Byte[] ParticleSystem 601 public Byte[] ParticleSystem
599 { 602 {
600 get { return m_particleSystem; } 603 get { return m_particleSystem; }
@@ -648,7 +651,6 @@ namespace OpenSim.Region.Framework.Scenes
648 set 651 set
649 { 652 {
650 m_groupPosition = value; 653 m_groupPosition = value;
651
652 PhysicsActor actor = PhysActor; 654 PhysicsActor actor = PhysActor;
653 if (actor != null) 655 if (actor != null)
654 { 656 {
@@ -835,7 +837,16 @@ namespace OpenSim.Region.Framework.Scenes
835 /// <summary></summary> 837 /// <summary></summary>
836 public Vector3 Acceleration 838 public Vector3 Acceleration
837 { 839 {
838 get { return m_acceleration; } 840 get
841 {
842 PhysicsActor actor = PhysActor;
843 if (actor != null)
844 {
845 m_acceleration = actor.Acceleration;
846 }
847 return m_acceleration;
848 }
849
839 set { m_acceleration = value; } 850 set { m_acceleration = value; }
840 } 851 }
841 852
@@ -986,7 +997,8 @@ namespace OpenSim.Region.Framework.Scenes
986 if (IsAttachment) 997 if (IsAttachment)
987 return GroupPosition; 998 return GroupPosition;
988 999
989 return m_offsetPosition + m_groupPosition; } 1000// return m_offsetPosition + m_groupPosition; }
1001 return m_groupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset) ; } //KF: Rotation was ignored!
990 } 1002 }
991 1003
992 public SceneObjectGroup ParentGroup 1004 public SceneObjectGroup ParentGroup
@@ -1137,6 +1149,13 @@ namespace OpenSim.Region.Framework.Scenes
1137 get { return _flags; } 1149 get { return _flags; }
1138 set { _flags = value; } 1150 set { _flags = value; }
1139 } 1151 }
1152
1153 [XmlIgnore]
1154 public bool IsOccupied // KF If an av is sittingon this prim
1155 {
1156 get { return m_occupied; }
1157 set { m_occupied = value; }
1158 }
1140 1159
1141 [XmlIgnore] 1160 [XmlIgnore]
1142 public UUID SitTargetAvatar 1161 public UUID SitTargetAvatar
@@ -1212,14 +1231,6 @@ namespace OpenSim.Region.Framework.Scenes
1212 } 1231 }
1213 } 1232 }
1214 1233
1215 /// <summary>
1216 /// Clear all pending updates of parts to clients
1217 /// </summary>
1218 private void ClearUpdateSchedule()
1219 {
1220 m_updateFlag = 0;
1221 }
1222
1223 private void SendObjectPropertiesToClient(UUID AgentID) 1234 private void SendObjectPropertiesToClient(UUID AgentID)
1224 { 1235 {
1225 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1236 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
@@ -1962,12 +1973,17 @@ namespace OpenSim.Region.Framework.Scenes
1962 public Vector3 GetWorldPosition() 1973 public Vector3 GetWorldPosition()
1963 { 1974 {
1964 Quaternion parentRot = ParentGroup.RootPart.RotationOffset; 1975 Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
1965
1966 Vector3 axPos = OffsetPosition; 1976 Vector3 axPos = OffsetPosition;
1967
1968 axPos *= parentRot; 1977 axPos *= parentRot;
1969 Vector3 translationOffsetPosition = axPos; 1978 Vector3 translationOffsetPosition = axPos;
1970 return GroupPosition + translationOffsetPosition; 1979 if(_parentID == 0)
1980 {
1981 return GroupPosition;
1982 }
1983 else
1984 {
1985 return ParentGroup.AbsolutePosition + translationOffsetPosition; //KF: Fix child prim position
1986 }
1971 } 1987 }
1972 1988
1973 /// <summary> 1989 /// <summary>
@@ -1978,7 +1994,7 @@ namespace OpenSim.Region.Framework.Scenes
1978 { 1994 {
1979 Quaternion newRot; 1995 Quaternion newRot;
1980 1996
1981 if (this.LinkNum == 0) 1997 if (this.LinkNum < 2) //KF Single or root prim
1982 { 1998 {
1983 newRot = RotationOffset; 1999 newRot = RotationOffset;
1984 } 2000 }
@@ -2624,17 +2640,18 @@ namespace OpenSim.Region.Framework.Scenes
2624 //Trys to fetch sound id from prim's inventory. 2640 //Trys to fetch sound id from prim's inventory.
2625 //Prim's inventory doesn't support non script items yet 2641 //Prim's inventory doesn't support non script items yet
2626 2642
2627 lock (TaskInventory) 2643 TaskInventory.LockItemsForRead(true);
2644
2645 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2628 { 2646 {
2629 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2647 if (item.Value.Name == sound)
2630 { 2648 {
2631 if (item.Value.Name == sound) 2649 soundID = item.Value.ItemID;
2632 { 2650 break;
2633 soundID = item.Value.ItemID;
2634 break;
2635 }
2636 } 2651 }
2637 } 2652 }
2653
2654 TaskInventory.LockItemsForRead(false);
2638 } 2655 }
2639 2656
2640 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp) 2657 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp)
@@ -2703,38 +2720,7 @@ namespace OpenSim.Region.Framework.Scenes
2703 2720
2704 public void RotLookAt(Quaternion target, float strength, float damping) 2721 public void RotLookAt(Quaternion target, float strength, float damping)
2705 { 2722 {
2706 rotLookAt(target, strength, damping); 2723 m_parentGroup.rotLookAt(target, strength, damping); // This calls method in SceneObjectGroup.
2707 }
2708
2709 public void rotLookAt(Quaternion target, float strength, float damping)
2710 {
2711 if (IsAttachment)
2712 {
2713 /*
2714 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2715 if (avatar != null)
2716 {
2717 Rotate the Av?
2718 } */
2719 }
2720 else
2721 {
2722 APIDDamp = damping;
2723 APIDStrength = strength;
2724 APIDTarget = target;
2725 }
2726 }
2727
2728 public void startLookAt(Quaternion rot, float damp, float strength)
2729 {
2730 APIDDamp = damp;
2731 APIDStrength = strength;
2732 APIDTarget = rot;
2733 }
2734
2735 public void stopLookAt()
2736 {
2737 APIDTarget = Quaternion.Identity;
2738 } 2724 }
2739 2725
2740 /// <summary> 2726 /// <summary>
@@ -2746,7 +2732,10 @@ namespace OpenSim.Region.Framework.Scenes
2746 2732
2747 if (m_parentGroup != null) 2733 if (m_parentGroup != null)
2748 { 2734 {
2749 m_parentGroup.QueueForUpdateCheck(); 2735 if (!m_parentGroup.areUpdatesSuspended)
2736 {
2737 m_parentGroup.QueueForUpdateCheck();
2738 }
2750 } 2739 }
2751 2740
2752 int timeNow = Util.UnixTimeSinceEpoch(); 2741 int timeNow = Util.UnixTimeSinceEpoch();
@@ -2963,8 +2952,8 @@ namespace OpenSim.Region.Framework.Scenes
2963 { 2952 {
2964 const float ROTATION_TOLERANCE = 0.01f; 2953 const float ROTATION_TOLERANCE = 0.01f;
2965 const float VELOCITY_TOLERANCE = 0.001f; 2954 const float VELOCITY_TOLERANCE = 0.001f;
2966 const float POSITION_TOLERANCE = 0.05f; 2955 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2967 const int TIME_MS_TOLERANCE = 3000; 2956 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2968 2957
2969 if (m_updateFlag == 1) 2958 if (m_updateFlag == 1)
2970 { 2959 {
@@ -2978,7 +2967,7 @@ namespace OpenSim.Region.Framework.Scenes
2978 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 2967 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
2979 { 2968 {
2980 AddTerseUpdateToAllAvatars(); 2969 AddTerseUpdateToAllAvatars();
2981 ClearUpdateSchedule(); 2970
2982 2971
2983 // This causes the Scene to 'poll' physical objects every couple of frames 2972 // This causes the Scene to 'poll' physical objects every couple of frames
2984 // bad, so it's been replaced by an event driven method. 2973 // bad, so it's been replaced by an event driven method.
@@ -2996,16 +2985,18 @@ namespace OpenSim.Region.Framework.Scenes
2996 m_lastAngularVelocity = AngularVelocity; 2985 m_lastAngularVelocity = AngularVelocity;
2997 m_lastTerseSent = Environment.TickCount; 2986 m_lastTerseSent = Environment.TickCount;
2998 } 2987 }
2988 //Moved this outside of the if clause so updates don't get blocked.. *sigh*
2989 m_updateFlag = 0; //Why were we calling a function to do this? Inefficient! *screams*
2999 } 2990 }
3000 else 2991 else
3001 { 2992 {
3002 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes 2993 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes
3003 { 2994 {
3004 AddFullUpdateToAllAvatars(); 2995 AddFullUpdateToAllAvatars();
3005 ClearUpdateSchedule(); 2996 m_updateFlag = 0; //Same here
3006 } 2997 }
3007 } 2998 }
3008 ClearUpdateSchedule(); 2999 m_updateFlag = 0;
3009 } 3000 }
3010 3001
3011 /// <summary> 3002 /// <summary>
@@ -3032,17 +3023,16 @@ namespace OpenSim.Region.Framework.Scenes
3032 if (!UUID.TryParse(sound, out soundID)) 3023 if (!UUID.TryParse(sound, out soundID))
3033 { 3024 {
3034 // search sound file from inventory 3025 // search sound file from inventory
3035 lock (TaskInventory) 3026 TaskInventory.LockItemsForRead(true);
3027 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
3036 { 3028 {
3037 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3029 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
3038 { 3030 {
3039 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3031 soundID = item.Value.ItemID;
3040 { 3032 break;
3041 soundID = item.Value.ItemID;
3042 break;
3043 }
3044 } 3033 }
3045 } 3034 }
3035 TaskInventory.LockItemsForRead(false);
3046 } 3036 }
3047 3037
3048 if (soundID == UUID.Zero) 3038 if (soundID == UUID.Zero)
@@ -3477,7 +3467,7 @@ namespace OpenSim.Region.Framework.Scenes
3477 3467
3478 public void StopLookAt() 3468 public void StopLookAt()
3479 { 3469 {
3480 m_parentGroup.stopLookAt(); 3470 m_parentGroup.stopLookAt(); // This calls method in SceneObjectGroup.
3481 3471
3482 m_parentGroup.ScheduleGroupForTerseUpdate(); 3472 m_parentGroup.ScheduleGroupForTerseUpdate();
3483 } 3473 }
@@ -4471,8 +4461,9 @@ namespace OpenSim.Region.Framework.Scenes
4471 { 4461 {
4472 m_shape.TextureEntry = textureEntry; 4462 m_shape.TextureEntry = textureEntry;
4473 TriggerScriptChangedEvent(Changed.TEXTURE); 4463 TriggerScriptChangedEvent(Changed.TEXTURE);
4474 4464 m_updateFlag = 1;
4475 ParentGroup.HasGroupChanged = true; 4465 ParentGroup.HasGroupChanged = true;
4466
4476 //This is madness.. 4467 //This is madness..
4477 //ParentGroup.ScheduleGroupForFullUpdate(); 4468 //ParentGroup.ScheduleGroupForFullUpdate();
4478 //This is sparta 4469 //This is sparta
@@ -4717,5 +4708,17 @@ namespace OpenSim.Region.Framework.Scenes
4717 Color color = Color; 4708 Color color = Color;
4718 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 4709 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4719 } 4710 }
4711
4712 public void ResetOwnerChangeFlag()
4713 {
4714 List<UUID> inv = Inventory.GetInventoryList();
4715
4716 foreach (UUID itemID in inv)
4717 {
4718 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
4719 item.OwnerChanged = false;
4720 Inventory.UpdateInventoryItem(item);
4721 }
4722 }
4720 } 4723 }
4721} 4724}
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 45375b0..e3bbe8a 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;
@@ -157,7 +163,6 @@ namespace OpenSim.Region.Framework.Scenes
157 private int m_perfMonMS; 163 private int m_perfMonMS;
158 164
159 private bool m_setAlwaysRun; 165 private bool m_setAlwaysRun;
160
161 private bool m_forceFly; 166 private bool m_forceFly;
162 private bool m_flyDisabled; 167 private bool m_flyDisabled;
163 168
@@ -183,7 +188,8 @@ namespace OpenSim.Region.Framework.Scenes
183 protected RegionInfo m_regionInfo; 188 protected RegionInfo m_regionInfo;
184 protected ulong crossingFromRegion; 189 protected ulong crossingFromRegion;
185 190
186 private readonly Vector3[] Dir_Vectors = new Vector3[9]; 191 private readonly Vector3[] Dir_Vectors = new Vector3[11];
192 private bool m_isNudging = false;
187 193
188 // Position of agent's camera in world (region cordinates) 194 // Position of agent's camera in world (region cordinates)
189 protected Vector3 m_CameraCenter; 195 protected Vector3 m_CameraCenter;
@@ -208,6 +214,7 @@ namespace OpenSim.Region.Framework.Scenes
208 private bool m_autopilotMoving; 214 private bool m_autopilotMoving;
209 private Vector3 m_autoPilotTarget; 215 private Vector3 m_autoPilotTarget;
210 private bool m_sitAtAutoTarget; 216 private bool m_sitAtAutoTarget;
217 private Vector3 m_initialSitTarget = Vector3.Zero; //KF: First estimate of where to sit
211 218
212 private string m_nextSitAnimation = String.Empty; 219 private string m_nextSitAnimation = String.Empty;
213 220
@@ -218,6 +225,9 @@ namespace OpenSim.Region.Framework.Scenes
218 private bool m_followCamAuto; 225 private bool m_followCamAuto;
219 226
220 private int m_movementUpdateCount; 227 private int m_movementUpdateCount;
228 private int m_lastColCount = -1; //KF: Look for Collision chnages
229 private int m_updateCount = 0; //KF: Update Anims for a while
230 private static readonly int UPDATE_COUNT = 10; // how many frames to update for
221 private const int NumMovementsBetweenRayCast = 5; 231 private const int NumMovementsBetweenRayCast = 5;
222 232
223 private bool CameraConstraintActive; 233 private bool CameraConstraintActive;
@@ -245,7 +255,9 @@ namespace OpenSim.Region.Framework.Scenes
245 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, 255 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
246 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, 256 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
247 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS, 257 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, 258 DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
259 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
260 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 261 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
250 } 262 }
251 263
@@ -452,7 +464,8 @@ namespace OpenSim.Region.Framework.Scenes
452 get 464 get
453 { 465 {
454 PhysicsActor actor = m_physicsActor; 466 PhysicsActor actor = m_physicsActor;
455 if (actor != null) 467// if (actor != null)
468 if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting!
456 m_pos = actor.Position; 469 m_pos = actor.Position;
457 470
458 return m_parentPosition + m_pos; 471 return m_parentPosition + m_pos;
@@ -473,7 +486,8 @@ namespace OpenSim.Region.Framework.Scenes
473 } 486 }
474 } 487 }
475 488
476 m_pos = value; 489 if (m_parentID == 0) // KF Do NOT update m_pos here if Av is sitting!
490 m_pos = value;
477 m_parentPosition = Vector3.Zero; 491 m_parentPosition = Vector3.Zero;
478 } 492 }
479 } 493 }
@@ -671,7 +685,7 @@ namespace OpenSim.Region.Framework.Scenes
671 CreateSceneViewer(); 685 CreateSceneViewer();
672 m_animator = new ScenePresenceAnimator(this); 686 m_animator = new ScenePresenceAnimator(this);
673 } 687 }
674 688
675 private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this() 689 private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this()
676 { 690 {
677 m_rootRegionHandle = reginfo.RegionHandle; 691 m_rootRegionHandle = reginfo.RegionHandle;
@@ -703,16 +717,16 @@ namespace OpenSim.Region.Framework.Scenes
703 m_reprioritization_timer.AutoReset = false; 717 m_reprioritization_timer.AutoReset = false;
704 718
705 AdjustKnownSeeds(); 719 AdjustKnownSeeds();
706
707 // TODO: I think, this won't send anything, as we are still a child here...
708 Animator.TrySetMovementAnimation("STAND"); 720 Animator.TrySetMovementAnimation("STAND");
709
710 // we created a new ScenePresence (a new child agent) in a fresh region. 721 // we created a new ScenePresence (a new child agent) in a fresh region.
711 // Request info about all the (root) agents in this region 722 // 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) 723 // Note: This won't send data *to* other clients in that region (children don't send)
713 SendInitialFullUpdateToAllClients(); 724 SendInitialFullUpdateToAllClients();
714
715 RegisterToEvents(); 725 RegisterToEvents();
726 if (m_controllingClient != null)
727 {
728 m_controllingClient.ProcessPendingPackets();
729 }
716 SetDirectionVectors(); 730 SetDirectionVectors();
717 } 731 }
718 732
@@ -762,25 +776,47 @@ namespace OpenSim.Region.Framework.Scenes
762 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT 776 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT
763 Dir_Vectors[4] = Vector3.UnitZ; //UP 777 Dir_Vectors[4] = Vector3.UnitZ; //UP
764 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN 778 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN
765 Dir_Vectors[8] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge 779 Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE
766 Dir_Vectors[6] = Vector3.UnitX*2; //FORWARD 780 Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE
767 Dir_Vectors[7] = -Vector3.UnitX; //BACK 781 Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE
782 Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE
783 Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
768 } 784 }
769 785
770 private Vector3[] GetWalkDirectionVectors() 786 private Vector3[] GetWalkDirectionVectors()
771 { 787 {
772 Vector3[] vector = new Vector3[9]; 788 Vector3[] vector = new Vector3[11];
773 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD 789 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 790 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK
775 vector[2] = Vector3.UnitY; //LEFT 791 vector[2] = Vector3.UnitY; //LEFT
776 vector[3] = -Vector3.UnitY; //RIGHT 792 vector[3] = -Vector3.UnitY; //RIGHT
777 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP 793 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 794 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 795 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 796 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 797 vector[8] = Vector3.UnitY; //LEFT_NUDGE
798 vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
799 vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE
782 return vector; 800 return vector;
783 } 801 }
802
803 private bool[] GetDirectionIsNudge()
804 {
805 bool[] isNudge = new bool[11];
806 isNudge[0] = false; //FORWARD
807 isNudge[1] = false; //BACK
808 isNudge[2] = false; //LEFT
809 isNudge[3] = false; //RIGHT
810 isNudge[4] = false; //UP
811 isNudge[5] = false; //DOWN
812 isNudge[6] = true; //FORWARD_NUDGE
813 isNudge[7] = true; //BACK_NUDGE
814 isNudge[8] = true; //LEFT_NUDGE
815 isNudge[9] = true; //RIGHT_NUDGE
816 isNudge[10] = true; //DOWN_Nudge
817 return isNudge;
818 }
819
784 820
785 #endregion 821 #endregion
786 822
@@ -823,7 +859,6 @@ namespace OpenSim.Region.Framework.Scenes
823 m_grouptitle = gm.GetGroupTitle(m_uuid); 859 m_grouptitle = gm.GetGroupTitle(m_uuid);
824 860
825 m_rootRegionHandle = m_scene.RegionInfo.RegionHandle; 861 m_rootRegionHandle = m_scene.RegionInfo.RegionHandle;
826
827 m_scene.SetRootAgentScene(m_uuid); 862 m_scene.SetRootAgentScene(m_uuid);
828 863
829 // Moved this from SendInitialData to ensure that m_appearance is initialized 864 // Moved this from SendInitialData to ensure that m_appearance is initialized
@@ -842,6 +877,52 @@ namespace OpenSim.Region.Framework.Scenes
842 pos.Y = crossedBorder.BorderLine.Z - 1; 877 pos.Y = crossedBorder.BorderLine.Z - 1;
843 } 878 }
844 879
880 //If they're TP'ing in or logging in, we haven't had time to add any known child regions yet.
881 //This has the unfortunate consequence that if somebody is TP'ing who is already a child agent,
882 //they'll bypass the landing point. But I can't think of any decent way of fixing this.
883 if (KnownChildRegionHandles.Count == 0)
884 {
885 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
886 if (land != null)
887 {
888 //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni.
889 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)
890 {
891 pos = land.LandData.UserLocation;
892 }
893 }
894 }
895
896 if (pos.X < 0 || pos.Y < 0 || pos.Z < 0)
897 {
898 Vector3 emergencyPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 128);
899
900 if (pos.X < 0)
901 {
902 emergencyPos.X = (int)Constants.RegionSize + pos.X;
903 if (!(pos.Y < 0))
904 emergencyPos.Y = pos.Y;
905 if (!(pos.Z < 0))
906 emergencyPos.Z = pos.Z;
907 }
908 if (pos.Y < 0)
909 {
910 emergencyPos.Y = (int)Constants.RegionSize + pos.Y;
911 if (!(pos.X < 0))
912 emergencyPos.X = pos.X;
913 if (!(pos.Z < 0))
914 emergencyPos.Z = pos.Z;
915 }
916 if (pos.Z < 0)
917 {
918 emergencyPos.Z = 128;
919 if (!(pos.Y < 0))
920 emergencyPos.Y = pos.Y;
921 if (!(pos.X < 0))
922 emergencyPos.X = pos.X;
923 }
924 }
925
845 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 926 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
846 { 927 {
847 m_log.WarnFormat( 928 m_log.WarnFormat(
@@ -974,9 +1055,10 @@ namespace OpenSim.Region.Framework.Scenes
974 public void Teleport(Vector3 pos) 1055 public void Teleport(Vector3 pos)
975 { 1056 {
976 bool isFlying = false; 1057 bool isFlying = false;
1058
977 if (m_physicsActor != null) 1059 if (m_physicsActor != null)
978 isFlying = m_physicsActor.Flying; 1060 isFlying = m_physicsActor.Flying;
979 1061
980 RemoveFromPhysicalScene(); 1062 RemoveFromPhysicalScene();
981 Velocity = Vector3.Zero; 1063 Velocity = Vector3.Zero;
982 AbsolutePosition = pos; 1064 AbsolutePosition = pos;
@@ -988,6 +1070,7 @@ namespace OpenSim.Region.Framework.Scenes
988 } 1070 }
989 1071
990 SendTerseUpdateToAllClients(); 1072 SendTerseUpdateToAllClients();
1073
991 } 1074 }
992 1075
993 public void TeleportWithMomentum(Vector3 pos) 1076 public void TeleportWithMomentum(Vector3 pos)
@@ -1032,7 +1115,9 @@ namespace OpenSim.Region.Framework.Scenes
1032 { 1115 {
1033 AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f)); 1116 AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f));
1034 } 1117 }
1035 1118
1119 m_updateCount = UPDATE_COUNT; //KF: Trigger Anim updates to catch falling anim.
1120
1036 ControllingClient.SendPrimUpdate(this, PrimUpdateFlags.Position); 1121 ControllingClient.SendPrimUpdate(this, PrimUpdateFlags.Position);
1037 //ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId, 1122 //ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId,
1038 // AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient))); 1123 // AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient)));
@@ -1119,7 +1204,6 @@ namespace OpenSim.Region.Framework.Scenes
1119 pos.Z = ground + 1.5f; 1204 pos.Z = ground + 1.5f;
1120 AbsolutePosition = pos; 1205 AbsolutePosition = pos;
1121 } 1206 }
1122
1123 m_isChildAgent = false; 1207 m_isChildAgent = false;
1124 bool m_flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); 1208 bool m_flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
1125 MakeRootAgent(AbsolutePosition, m_flying); 1209 MakeRootAgent(AbsolutePosition, m_flying);
@@ -1218,6 +1302,7 @@ namespace OpenSim.Region.Framework.Scenes
1218 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); 1302 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902");
1219 1303
1220 m_pos = m_LastFinitePos; 1304 m_pos = m_LastFinitePos;
1305
1221 if (!m_pos.IsFinite()) 1306 if (!m_pos.IsFinite())
1222 { 1307 {
1223 m_pos.X = 127f; 1308 m_pos.X = 127f;
@@ -1284,7 +1369,6 @@ namespace OpenSim.Region.Framework.Scenes
1284 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback); 1369 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback);
1285 } 1370 }
1286 } 1371 }
1287
1288 lock (scriptedcontrols) 1372 lock (scriptedcontrols)
1289 { 1373 {
1290 if (scriptedcontrols.Count > 0) 1374 if (scriptedcontrols.Count > 0)
@@ -1299,6 +1383,9 @@ namespace OpenSim.Region.Framework.Scenes
1299 1383
1300 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) 1384 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
1301 { 1385 {
1386 m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.
1387 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
1388
1302 // TODO: This doesn't prevent the user from walking yet. 1389 // TODO: This doesn't prevent the user from walking yet.
1303 // Setting parent ID would fix this, if we knew what value 1390 // Setting parent ID would fix this, if we knew what value
1304 // to use. Or we could add a m_isSitting variable. 1391 // to use. Or we could add a m_isSitting variable.
@@ -1353,6 +1440,11 @@ namespace OpenSim.Region.Framework.Scenes
1353 update_rotation = true; 1440 update_rotation = true;
1354 } 1441 }
1355 1442
1443 //guilty until proven innocent..
1444 bool Nudging = true;
1445 //Basically, if there is at least one non-nudge control then we don't need
1446 //to worry about stopping the avatar
1447
1356 if (m_parentID == 0) 1448 if (m_parentID == 0)
1357 { 1449 {
1358 bool bAllowUpdateMoveToPosition = false; 1450 bool bAllowUpdateMoveToPosition = false;
@@ -1367,9 +1459,12 @@ namespace OpenSim.Region.Framework.Scenes
1367 else 1459 else
1368 dirVectors = Dir_Vectors; 1460 dirVectors = Dir_Vectors;
1369 1461
1370 // The fact that m_movementflag is a byte needs to be fixed 1462 bool[] isNudge = GetDirectionIsNudge();
1371 // it really should be a uint 1463
1372 uint nudgehack = 250; 1464
1465
1466
1467
1373 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) 1468 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
1374 { 1469 {
1375 if (((uint)flags & (uint)DCF) != 0) 1470 if (((uint)flags & (uint)DCF) != 0)
@@ -1379,40 +1474,28 @@ namespace OpenSim.Region.Framework.Scenes
1379 try 1474 try
1380 { 1475 {
1381 agent_control_v3 += dirVectors[i]; 1476 agent_control_v3 += dirVectors[i];
1382 //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]); 1477 if (isNudge[i] == false)
1478 {
1479 Nudging = false;
1480 }
1383 } 1481 }
1384 catch (IndexOutOfRangeException) 1482 catch (IndexOutOfRangeException)
1385 { 1483 {
1386 // Why did I get this? 1484 // Why did I get this?
1387 } 1485 }
1388 1486
1389 if ((m_movementflag & (byte)(uint)DCF) == 0) 1487 if ((m_movementflag & (uint)DCF) == 0)
1390 { 1488 {
1391 if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1392 {
1393 m_movementflag |= (byte)nudgehack;
1394 }
1395 m_movementflag += (byte)(uint)DCF; 1489 m_movementflag += (byte)(uint)DCF;
1396 update_movementflag = true; 1490 update_movementflag = true;
1397 } 1491 }
1398 } 1492 }
1399 else 1493 else
1400 { 1494 {
1401 if ((m_movementflag & (byte)(uint)DCF) != 0 || 1495 if ((m_movementflag & (uint)DCF) != 0)
1402 ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1403 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1404 ) // This or is for Nudge forward
1405 { 1496 {
1406 m_movementflag -= ((byte)(uint)DCF); 1497 m_movementflag -= (byte)(uint)DCF;
1407
1408 update_movementflag = true; 1498 update_movementflag = true;
1409 /*
1410 if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1411 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1412 {
1413 m_log.Debug("Removed Hack flag");
1414 }
1415 */
1416 } 1499 }
1417 else 1500 else
1418 { 1501 {
@@ -1421,7 +1504,6 @@ namespace OpenSim.Region.Framework.Scenes
1421 } 1504 }
1422 i++; 1505 i++;
1423 } 1506 }
1424
1425 //Paupaw:Do Proper PID for Autopilot here 1507 //Paupaw:Do Proper PID for Autopilot here
1426 if (bResetMoveToPosition) 1508 if (bResetMoveToPosition)
1427 { 1509 {
@@ -1456,6 +1538,9 @@ namespace OpenSim.Region.Framework.Scenes
1456 // Ignore z component of vector 1538 // Ignore z component of vector
1457 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); 1539 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
1458 LocalVectorToTarget2D.Normalize(); 1540 LocalVectorToTarget2D.Normalize();
1541
1542 //We're not nudging
1543 Nudging = false;
1459 agent_control_v3 += LocalVectorToTarget2D; 1544 agent_control_v3 += LocalVectorToTarget2D;
1460 1545
1461 // update avatar movement flags. the avatar coordinate system is as follows: 1546 // update avatar movement flags. the avatar coordinate system is as follows:
@@ -1544,13 +1629,13 @@ namespace OpenSim.Region.Framework.Scenes
1544 // m_log.DebugFormat( 1629 // m_log.DebugFormat(
1545 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3); 1630 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
1546 1631
1547 AddNewMovement(agent_control_v3, q); 1632 AddNewMovement(agent_control_v3, q, Nudging);
1548 1633
1549 1634
1550 } 1635 }
1551 } 1636 }
1552 1637
1553 if (update_movementflag && ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) == 0) && (m_parentID == 0) && !SitGround) 1638 if (update_movementflag && !SitGround)
1554 Animator.UpdateMovementAnimations(); 1639 Animator.UpdateMovementAnimations();
1555 1640
1556 m_scene.EventManager.TriggerOnClientMovement(this); 1641 m_scene.EventManager.TriggerOnClientMovement(this);
@@ -1565,7 +1650,6 @@ namespace OpenSim.Region.Framework.Scenes
1565 m_sitAtAutoTarget = false; 1650 m_sitAtAutoTarget = false;
1566 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default; 1651 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
1567 //proxy.PCode = (byte)PCode.ParticleSystem; 1652 //proxy.PCode = (byte)PCode.ParticleSystem;
1568
1569 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy); 1653 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy);
1570 proxyObjectGroup.AttachToScene(m_scene); 1654 proxyObjectGroup.AttachToScene(m_scene);
1571 1655
@@ -1607,7 +1691,7 @@ namespace OpenSim.Region.Framework.Scenes
1607 } 1691 }
1608 m_moveToPositionInProgress = true; 1692 m_moveToPositionInProgress = true;
1609 m_moveToPositionTarget = new Vector3(locx, locy, locz); 1693 m_moveToPositionTarget = new Vector3(locx, locy, locz);
1610 } 1694 }
1611 catch (Exception ex) 1695 catch (Exception ex)
1612 { 1696 {
1613 //Why did I get this error? 1697 //Why did I get this error?
@@ -1629,7 +1713,7 @@ namespace OpenSim.Region.Framework.Scenes
1629 Velocity = Vector3.Zero; 1713 Velocity = Vector3.Zero;
1630 SendFullUpdateToAllClients(); 1714 SendFullUpdateToAllClients();
1631 1715
1632 //HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); 1716 HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ??
1633 } 1717 }
1634 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false); 1718 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false);
1635 m_requestedSitTargetUUID = UUID.Zero; 1719 m_requestedSitTargetUUID = UUID.Zero;
@@ -1666,50 +1750,82 @@ namespace OpenSim.Region.Framework.Scenes
1666 1750
1667 if (m_parentID != 0) 1751 if (m_parentID != 0)
1668 { 1752 {
1669 m_log.Debug("StandupCode Executed");
1670 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); 1753 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
1671 if (part != null) 1754 if (part != null)
1672 { 1755 {
1756 part.TaskInventory.LockItemsForRead(true);
1673 TaskInventoryDictionary taskIDict = part.TaskInventory; 1757 TaskInventoryDictionary taskIDict = part.TaskInventory;
1674 if (taskIDict != null) 1758 if (taskIDict != null)
1675 { 1759 {
1676 lock (taskIDict) 1760 foreach (UUID taskID in taskIDict.Keys)
1677 { 1761 {
1678 foreach (UUID taskID in taskIDict.Keys) 1762 UnRegisterControlEventsToScript(LocalId, taskID);
1679 { 1763 taskIDict[taskID].PermsMask &= ~(
1680 UnRegisterControlEventsToScript(LocalId, taskID); 1764 2048 | //PERMISSION_CONTROL_CAMERA
1681 taskIDict[taskID].PermsMask &= ~( 1765 4); // PERMISSION_TAKE_CONTROLS
1682 2048 | //PERMISSION_CONTROL_CAMERA
1683 4); // PERMISSION_TAKE_CONTROLS
1684 }
1685 } 1766 }
1686
1687 } 1767 }
1768 part.TaskInventory.LockItemsForRead(false);
1688 // Reset sit target. 1769 // Reset sit target.
1689 if (part.GetAvatarOnSitTarget() == UUID) 1770 if (part.GetAvatarOnSitTarget() == UUID)
1690 part.SetAvatarOnSitTarget(UUID.Zero); 1771 part.SetAvatarOnSitTarget(UUID.Zero);
1691
1692 m_parentPosition = part.GetWorldPosition(); 1772 m_parentPosition = part.GetWorldPosition();
1693 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1773 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1694 } 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 }
1695 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
1800
1801
1696 if (m_physicsActor == null) 1802 if (m_physicsActor == null)
1697 { 1803 {
1698 AddToPhysicalScene(false); 1804 AddToPhysicalScene(false);
1699 } 1805 }
1700 1806 //CW: If the part isn't null then we can set the current position
1701 m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight); 1807 if (part != null)
1702 m_parentPosition = Vector3.Zero; 1808 {
1703 1809 Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + (m_pos * partRot); // + av sit offset!
1704 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;
1705 SendFullUpdateToAllClients(); 1821 SendFullUpdateToAllClients();
1706 m_requestedSitTargetID = 0; 1822 m_requestedSitTargetID = 0;
1823
1707 if ((m_physicsActor != null) && (m_avHeight > 0)) 1824 if ((m_physicsActor != null) && (m_avHeight > 0))
1708 { 1825 {
1709 SetHeight(m_avHeight); 1826 SetHeight(m_avHeight);
1710 } 1827 }
1711 } 1828 }
1712
1713 Animator.TrySetMovementAnimation("STAND"); 1829 Animator.TrySetMovementAnimation("STAND");
1714 } 1830 }
1715 1831
@@ -1740,13 +1856,9 @@ namespace OpenSim.Region.Framework.Scenes
1740 Vector3 avSitOffSet = part.SitTargetPosition; 1856 Vector3 avSitOffSet = part.SitTargetPosition;
1741 Quaternion avSitOrientation = part.SitTargetOrientation; 1857 Quaternion avSitOrientation = part.SitTargetOrientation;
1742 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1858 UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
1743 1859 bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero);
1744 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1860 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1745 bool SitTargetisSet = 1861 if (SitTargetisSet && !SitTargetOccupied)
1746 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 1f &&
1747 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f));
1748
1749 if (SitTargetisSet && SitTargetUnOccupied)
1750 { 1862 {
1751 //switch the target to this prim 1863 //switch the target to this prim
1752 return part; 1864 return part;
@@ -1760,84 +1872,153 @@ namespace OpenSim.Region.Framework.Scenes
1760 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation) 1872 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation)
1761 { 1873 {
1762 bool autopilot = true; 1874 bool autopilot = true;
1875 Vector3 autopilotTarget = new Vector3();
1876 Quaternion sitOrientation = Quaternion.Identity;
1763 Vector3 pos = new Vector3(); 1877 Vector3 pos = new Vector3();
1764 Quaternion sitOrientation = pSitOrientation;
1765 Vector3 cameraEyeOffset = Vector3.Zero; 1878 Vector3 cameraEyeOffset = Vector3.Zero;
1766 Vector3 cameraAtOffset = Vector3.Zero; 1879 Vector3 cameraAtOffset = Vector3.Zero;
1767 bool forceMouselook = false; 1880 bool forceMouselook = false;
1768 1881
1769 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); 1882 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
1770 SceneObjectPart part = FindNextAvailableSitTarget(targetID); 1883 SceneObjectPart part = FindNextAvailableSitTarget(targetID);
1771 if (part != null) 1884 if (part == null) return;
1772 { 1885
1773 // 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
1774 // 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
1775 1888
1776 // Is a sit target available? 1889 // part is the prim to sit on
1777 Vector3 avSitOffSet = part.SitTargetPosition; 1890 // offset is the world-ref vector distance from that prim center to the click-spot
1778 Quaternion avSitOrientation = part.SitTargetOrientation; 1891 // UUID is the UUID of the Avatar doing the clicking
1779 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1892
1780 1893 m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation
1781 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1894
1782 bool SitTargetisSet = 1895 // Is a sit target available?
1783 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && 1896 Vector3 avSitOffSet = part.SitTargetPosition;
1784 ( 1897 Quaternion avSitOrientation = part.SitTargetOrientation;
1785 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 1f // Valid Zero Rotation quaternion 1898
1786 || 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.
1787 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 0f // Invalid Quaternion 1900 // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
1788 ) 1901 Quaternion partRot;
1789 )); 1902// if (part.LinkNum == 1)
1790 1903// { // Root prim of linkset
1791 if (SitTargetisSet && SitTargetUnOccupied) 1904// partRot = part.ParentGroup.RootPart.RotationOffset;
1792 { 1905// }
1793 part.SetAvatarOnSitTarget(UUID); 1906// else
1794 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); 1907// { // single or child prim
1795 sitOrientation = avSitOrientation; 1908 partRot = part.GetWorldRotation();
1796 autopilot = false; 1909// }
1797 } 1910 Quaternion partIRot = Quaternion.Inverse(partRot);
1798 1911//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet);
1799 pos = part.AbsolutePosition + offset; 1912 // Sit analysis rewritten by KF 091125
1800 //if (Math.Abs(part.AbsolutePosition.Z - AbsolutePosition.Z) > 1) 1913 if (SitTargetisSet) // scipted sit
1801 //{ 1914 {
1802 // offset = pos; 1915 if (!part.IsOccupied)
1803 //autopilot = false; 1916 {
1804 //} 1917//Console.WriteLine("Scripted, unoccupied");
1805 if (m_physicsActor != null) 1918 part.SetAvatarOnSitTarget(UUID); // set that Av will be on it
1806 { 1919 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
1807 // 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
1808 // We can remove the physicsActor until they stand up. 1921 autopilot = false; // Jump direct to scripted llSitPos()
1809 m_sitAvatarHeight = m_physicsActor.Size.Z; 1922 }
1810 1923 else
1811 if (autopilot) 1924 {
1812 { 1925//Console.WriteLine("Scripted, occupied");
1813 if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5) 1926 return;
1814 { 1927 }
1815 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); //
1816 1960
1817 RemoveFromPhysicalScene(); 1961 if (m_physicsActor != null)
1818 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); 1962 {
1819 } 1963 // If we're not using the client autopilot, we're immediately warping the avatar to the location
1820 } 1964 // We can remove the physicsActor until they stand up.
1821 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) )
1822 { 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? */
1823 RemoveFromPhysicalScene(); 1975 RemoveFromPhysicalScene();
1824 } 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();
1825 } 1985 }
1826
1827 cameraAtOffset = part.GetCameraAtOffset();
1828 cameraEyeOffset = part.GetCameraEyeOffset();
1829 forceMouselook = part.GetForceMouselook();
1830 } 1986 }
1831 1987 else return; // physactor is null!
1832 ControllingClient.SendSitResponse(targetID, offset, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); 1988
1833 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
1834 // This calls HandleAgentSit twice, once from here, and the client calls 2014 // This calls HandleAgentSit twice, once from here, and the client calls
1835 // HandleAgentSit itself after it gets to the location 2015 // HandleAgentSit itself after it gets to the location
1836 // 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
1837 // which happens in HandleAgentSit :P 2017 // which happens in HandleAgentSit :P
1838 m_autopilotMoving = autopilot; 2018 m_autopilotMoving = autopilot;
1839 m_autoPilotTarget = pos; 2019 m_autoPilotTarget = autopilotTarget;
1840 m_sitAtAutoTarget = autopilot; 2020 m_sitAtAutoTarget = autopilot;
2021 m_initialSitTarget = autopilotTarget;
1841 if (!autopilot) 2022 if (!autopilot)
1842 HandleAgentSit(remoteClient, UUID); 2023 HandleAgentSit(remoteClient, UUID);
1843 } 2024 }
@@ -2132,31 +2313,66 @@ namespace OpenSim.Region.Framework.Scenes
2132 { 2313 {
2133 if (part != null) 2314 if (part != null)
2134 { 2315 {
2316//Console.WriteLine("Link #{0}, Rot {1}", part.LinkNum, part.GetWorldRotation());
2135 if (part.GetAvatarOnSitTarget() == UUID) 2317 if (part.GetAvatarOnSitTarget() == UUID)
2136 { 2318 {
2319//Console.WriteLine("Scripted Sit");
2320 // Scripted sit
2137 Vector3 sitTargetPos = part.SitTargetPosition; 2321 Vector3 sitTargetPos = part.SitTargetPosition;
2138 Quaternion sitTargetOrient = part.SitTargetOrientation; 2322 Quaternion sitTargetOrient = part.SitTargetOrientation;
2139
2140 //Quaternion vq = new Quaternion(sitTargetPos.X, sitTargetPos.Y+0.2f, sitTargetPos.Z+0.2f, 0);
2141 //Quaternion nq = new Quaternion(-sitTargetOrient.X, -sitTargetOrient.Y, -sitTargetOrient.Z, sitTargetOrient.w);
2142
2143 //Quaternion result = (sitTargetOrient * vq) * nq;
2144
2145 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z); 2323 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
2146 m_pos += SIT_TARGET_ADJUSTMENT; 2324 m_pos += SIT_TARGET_ADJUSTMENT;
2147 m_bodyRot = sitTargetOrient; 2325 m_bodyRot = sitTargetOrient;
2148 //Rotation = sitTargetOrient;
2149 m_parentPosition = part.AbsolutePosition; 2326 m_parentPosition = part.AbsolutePosition;
2150 2327 part.IsOccupied = true;
2151 //SendTerseUpdateToAllClients(); 2328Console.WriteLine("Scripted Sit ofset {0}", m_pos);
2152 } 2329 }
2153 else 2330 else
2154 { 2331 {
2155 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
2156 m_parentPosition = part.AbsolutePosition; 2356 m_parentPosition = part.AbsolutePosition;
2157 } 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
2158 } 2374 }
2159 else 2375 else // no Av
2160 { 2376 {
2161 return; 2377 return;
2162 } 2378 }
@@ -2168,11 +2384,39 @@ namespace OpenSim.Region.Framework.Scenes
2168 2384
2169 Animator.TrySetMovementAnimation(sitAnimation); 2385 Animator.TrySetMovementAnimation(sitAnimation);
2170 SendFullUpdateToAllClients(); 2386 SendFullUpdateToAllClients();
2171 // This may seem stupid, but Our Full updates don't send avatar rotation :P
2172 // So we're also sending a terse update (which has avatar rotation)
2173 // [Update] We do now.
2174 //SendTerseUpdateToAllClients();
2175 } 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.
2176 2420
2177 /// <summary> 2421 /// <summary>
2178 /// Event handler for the 'Always run' setting on the client 2422 /// Event handler for the 'Always run' setting on the client
@@ -2202,7 +2446,7 @@ namespace OpenSim.Region.Framework.Scenes
2202 /// </summary> 2446 /// </summary>
2203 /// <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>
2204 /// <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.
2205 public void AddNewMovement(Vector3 vec, Quaternion rotation) 2449 public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging)
2206 { 2450 {
2207 if (m_isChildAgent) 2451 if (m_isChildAgent)
2208 { 2452 {
@@ -2243,10 +2487,11 @@ namespace OpenSim.Region.Framework.Scenes
2243 Rotation = rotation; 2487 Rotation = rotation;
2244 Vector3 direc = vec * rotation; 2488 Vector3 direc = vec * rotation;
2245 direc.Normalize(); 2489 direc.Normalize();
2490 PhysicsActor actor = m_physicsActor;
2491 if ((vec.Z == 0f) && !actor.Flying) direc.Z = 0f; // Prevent camera WASD up.
2246 2492
2247 direc *= 0.03f * 128f * m_speedModifier; 2493 direc *= 0.03f * 128f * m_speedModifier;
2248 2494
2249 PhysicsActor actor = m_physicsActor;
2250 if (actor != null) 2495 if (actor != null)
2251 { 2496 {
2252 if (actor.Flying) 2497 if (actor.Flying)
@@ -2268,18 +2513,25 @@ namespace OpenSim.Region.Framework.Scenes
2268 { 2513 {
2269 if (direc.Z > 2.0f) 2514 if (direc.Z > 2.0f)
2270 { 2515 {
2271 direc.Z *= 3.0f; 2516 if(m_animator.m_animTickJump == -1)
2272 2517 {
2273 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored. 2518 direc.Z *= 3.0f; // jump
2274 Animator.TrySetMovementAnimation("PREJUMP"); 2519 }
2275 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 */
2276 } 2528 }
2277 } 2529 }
2278 } 2530 }
2279 2531
2280 // 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?
2281 m_forceToApply = direc; 2533 m_forceToApply = direc;
2282 2534 m_isNudging = Nudging;
2283 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); 2535 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
2284 } 2536 }
2285 2537
@@ -2294,7 +2546,7 @@ namespace OpenSim.Region.Framework.Scenes
2294 const float POSITION_TOLERANCE = 0.05f; 2546 const float POSITION_TOLERANCE = 0.05f;
2295 //const int TIME_MS_TOLERANCE = 3000; 2547 //const int TIME_MS_TOLERANCE = 3000;
2296 2548
2297 SendPrimUpdates(); 2549
2298 2550
2299 if (m_newCoarseLocations) 2551 if (m_newCoarseLocations)
2300 { 2552 {
@@ -2330,6 +2582,9 @@ namespace OpenSim.Region.Framework.Scenes
2330 CheckForBorderCrossing(); 2582 CheckForBorderCrossing();
2331 CheckForSignificantMovement(); // sends update to the modules. 2583 CheckForSignificantMovement(); // sends update to the modules.
2332 } 2584 }
2585
2586 //Sending prim updates AFTER the avatar terse updates are sent
2587 SendPrimUpdates();
2333 } 2588 }
2334 2589
2335 #endregion 2590 #endregion
@@ -3140,6 +3395,7 @@ namespace OpenSim.Region.Framework.Scenes
3140 m_callbackURI = cAgent.CallbackURI; 3395 m_callbackURI = cAgent.CallbackURI;
3141 3396
3142 m_pos = cAgent.Position; 3397 m_pos = cAgent.Position;
3398
3143 m_velocity = cAgent.Velocity; 3399 m_velocity = cAgent.Velocity;
3144 m_CameraCenter = cAgent.Center; 3400 m_CameraCenter = cAgent.Center;
3145 //m_avHeight = cAgent.Size.Z; 3401 //m_avHeight = cAgent.Size.Z;
@@ -3228,14 +3484,25 @@ namespace OpenSim.Region.Framework.Scenes
3228 { 3484 {
3229 if (m_forceToApply.HasValue) 3485 if (m_forceToApply.HasValue)
3230 { 3486 {
3231 Vector3 force = m_forceToApply.Value;
3232 3487
3488 Vector3 force = m_forceToApply.Value;
3233 m_updateflag = true; 3489 m_updateflag = true;
3234// movementvector = force;
3235 Velocity = force; 3490 Velocity = force;
3236 3491
3237 m_forceToApply = null; 3492 m_forceToApply = null;
3238 } 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 }
3239 } 3506 }
3240 3507
3241 public override void SetText(string text, Vector3 color, double alpha) 3508 public override void SetText(string text, Vector3 color, double alpha)
@@ -3286,18 +3553,29 @@ namespace OpenSim.Region.Framework.Scenes
3286 { 3553 {
3287 if (e == null) 3554 if (e == null)
3288 return; 3555 return;
3289 3556
3290 //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(
3291 // The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3292 // as of this comment the interval is set in AddToPhysicalScene 3558 // as of this comment the interval is set in AddToPhysicalScene
3293 if (Animator!=null) 3559 if (Animator!=null)
3294 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 }
3295 3567
3296 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 3568 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
3297 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 3569 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
3298 3570
3299 CollisionPlane = Vector4.UnitW; 3571 CollisionPlane = Vector4.UnitW;
3300 3572
3573 if (m_lastColCount != coldata.Count)
3574 {
3575 m_updateCount = UPDATE_COUNT;
3576 m_lastColCount = coldata.Count;
3577 }
3578
3301 if (coldata.Count != 0 && Animator != null) 3579 if (coldata.Count != 0 && Animator != null)
3302 { 3580 {
3303 switch (Animator.CurrentMovementAnimation) 3581 switch (Animator.CurrentMovementAnimation)
@@ -3501,7 +3779,10 @@ namespace OpenSim.Region.Framework.Scenes
3501 m_scene = scene; 3779 m_scene = scene;
3502 3780
3503 RegisterToEvents(); 3781 RegisterToEvents();
3504 3782 if (m_controllingClient != null)
3783 {
3784 m_controllingClient.ProcessPendingPackets();
3785 }
3505 /* 3786 /*
3506 AbsolutePosition = client.StartPos; 3787 AbsolutePosition = client.StartPos;
3507 3788
@@ -3732,6 +4013,32 @@ namespace OpenSim.Region.Framework.Scenes
3732 return; 4013 return;
3733 } 4014 }
3734 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
3735 List<int> attPoints = m_appearance.GetAttachedPoints(); 4042 List<int> attPoints = m_appearance.GetAttachedPoints();
3736 foreach (int p in attPoints) 4043 foreach (int p in attPoints)
3737 { 4044 {
@@ -3751,9 +4058,26 @@ namespace OpenSim.Region.Framework.Scenes
3751 4058
3752 try 4059 try
3753 { 4060 {
3754 // Rez from inventory 4061 string xmlData;
3755 UUID asset 4062 XmlDocument d = new XmlDocument();
3756 = 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 }
3757 4081
3758 m_log.InfoFormat( 4082 m_log.InfoFormat(
3759 "[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})",
@@ -3790,5 +4114,16 @@ namespace OpenSim.Region.Framework.Scenes
3790 m_reprioritization_called = false; 4114 m_reprioritization_called = false;
3791 } 4115 }
3792 } 4116 }
4117
4118 private Vector3 Quat2Euler(Quaternion rot){
4119 float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) ,
4120 (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z)));
4121 float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W)));
4122 float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) ,
4123 (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z)));
4124 return(new Vector3(x,y,z));
4125 }
4126
4127
3793 } 4128 }
3794} 4129}
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index 7453eae..2ed8fbf 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 146b3d6..e43ef78 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
@@ -836,12 +836,21 @@ namespace OpenSim.Region.OptionalModules.World.NPC
836 { 836 {
837 } 837 }
838 838
839 public void ProcessPendingPackets()
840 {
841 }
842
839 public void ProcessInPacket(Packet NewPack) 843 public void ProcessInPacket(Packet NewPack)
840 { 844 {
841 } 845 }
842 846
843 public void Close() 847 public void Close()
844 { 848 {
849 Close(true);
850 }
851
852 public void Close(bool sendStop)
853 {
845 } 854 }
846 855
847 public void Start() 856 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..4fb5c95 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs
@@ -113,6 +113,31 @@ 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 if (avatar.PhysicsActor != null && avatar.PhysicsActor.Position != null)
129 {
130 result.Add(avatar.UUID);
131 result.Add(avatar.PhysicsActor.Position);
132 result.Add(avatar.Name);
133 }
134 }
135 }
136 });
137 return result;
138 }
139
140 /// <summary>
116 /// Get the current Windlight scene 141 /// Get the current Windlight scene
117 /// </summary> 142 /// </summary>
118 /// <returns>List of windlight parameters</returns> 143 /// <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 5400a4f..3c2ef34 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())
282 {
283 m_host.TaskInventory.LockItemsForRead(true);
284 unlock = true;
285 }
286 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
277 { 287 {
278 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 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 {
@@ -1524,13 +1649,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1524 m_host.AddScriptLPS(1); 1649 m_host.AddScriptLPS(1);
1525 1650
1526 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1651 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1527 1652 if (parts.Count > 0)
1528 foreach (SceneObjectPart part in parts) 1653 {
1529 SetAlpha(part, alpha, face); 1654 try
1655 {
1656 parts[0].ParentGroup.areUpdatesSuspended = true;
1657 foreach (SceneObjectPart part in parts)
1658 SetAlpha(part, alpha, face);
1659 }
1660 finally
1661 {
1662 parts[0].ParentGroup.areUpdatesSuspended = false;
1663 }
1664 }
1530 } 1665 }
1531 1666
1532 protected void SetAlpha(SceneObjectPart part, double alpha, int face) 1667 protected void SetAlpha(SceneObjectPart part, double alpha, int face)
1533 { 1668 {
1669 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1670 return;
1671
1534 Primitive.TextureEntry tex = part.Shape.Textures; 1672 Primitive.TextureEntry tex = part.Shape.Textures;
1535 Color4 texcolor; 1673 Color4 texcolor;
1536 if (face >= 0 && face < GetNumberOfSides(part)) 1674 if (face >= 0 && face < GetNumberOfSides(part))
@@ -1576,7 +1714,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1576 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction, 1714 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction,
1577 float wind, float tension, LSL_Vector Force) 1715 float wind, float tension, LSL_Vector Force)
1578 { 1716 {
1579 if (part == null) 1717 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1580 return; 1718 return;
1581 1719
1582 if (flexi) 1720 if (flexi)
@@ -1611,7 +1749,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1611 /// <param name="falloff"></param> 1749 /// <param name="falloff"></param>
1612 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff) 1750 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
1613 { 1751 {
1614 if (part == null) 1752 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1615 return; 1753 return;
1616 1754
1617 if (light) 1755 if (light)
@@ -1688,15 +1826,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1688 m_host.AddScriptLPS(1); 1826 m_host.AddScriptLPS(1);
1689 1827
1690 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1828 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1691 1829 if (parts.Count > 0)
1692 foreach (SceneObjectPart part in parts) 1830 {
1693 SetTexture(part, texture, face); 1831 try
1694 1832 {
1833 parts[0].ParentGroup.areUpdatesSuspended = true;
1834 foreach (SceneObjectPart part in parts)
1835 SetTexture(part, texture, face);
1836 }
1837 finally
1838 {
1839 parts[0].ParentGroup.areUpdatesSuspended = false;
1840 }
1841 }
1695 ScriptSleep(200); 1842 ScriptSleep(200);
1696 } 1843 }
1697 1844
1698 protected void SetTexture(SceneObjectPart part, string texture, int face) 1845 protected void SetTexture(SceneObjectPart part, string texture, int face)
1699 { 1846 {
1847 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1848 return;
1849
1700 UUID textureID=new UUID(); 1850 UUID textureID=new UUID();
1701 1851
1702 if (!UUID.TryParse(texture, out textureID)) 1852 if (!UUID.TryParse(texture, out textureID))
@@ -1742,6 +1892,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1742 1892
1743 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face) 1893 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face)
1744 { 1894 {
1895 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1896 return;
1897
1745 Primitive.TextureEntry tex = part.Shape.Textures; 1898 Primitive.TextureEntry tex = part.Shape.Textures;
1746 if (face >= 0 && face < GetNumberOfSides(part)) 1899 if (face >= 0 && face < GetNumberOfSides(part))
1747 { 1900 {
@@ -1778,6 +1931,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1778 1931
1779 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face) 1932 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face)
1780 { 1933 {
1934 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1935 return;
1936
1781 Primitive.TextureEntry tex = part.Shape.Textures; 1937 Primitive.TextureEntry tex = part.Shape.Textures;
1782 if (face >= 0 && face < GetNumberOfSides(part)) 1938 if (face >= 0 && face < GetNumberOfSides(part))
1783 { 1939 {
@@ -1814,6 +1970,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1814 1970
1815 protected void RotateTexture(SceneObjectPart part, double rotation, int face) 1971 protected void RotateTexture(SceneObjectPart part, double rotation, int face)
1816 { 1972 {
1973 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1974 return;
1975
1817 Primitive.TextureEntry tex = part.Shape.Textures; 1976 Primitive.TextureEntry tex = part.Shape.Textures;
1818 if (face >= 0 && face < GetNumberOfSides(part)) 1977 if (face >= 0 && face < GetNumberOfSides(part))
1819 { 1978 {
@@ -1884,6 +2043,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1884 2043
1885 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos) 2044 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos)
1886 { 2045 {
2046 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2047 return;
2048
1887 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) 2049 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
1888 LSL_Vector currentPos = llGetLocalPos(); 2050 LSL_Vector currentPos = llGetLocalPos();
1889 2051
@@ -1970,6 +2132,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1970 2132
1971 protected void SetRot(SceneObjectPart part, Quaternion rot) 2133 protected void SetRot(SceneObjectPart part, Quaternion rot)
1972 { 2134 {
2135 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2136 return;
2137
1973 part.UpdateRotation(rot); 2138 part.UpdateRotation(rot);
1974 // Update rotation does not move the object in the physics scene if it's a linkset. 2139 // Update rotation does not move the object in the physics scene if it's a linkset.
1975 2140
@@ -2589,12 +2754,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2589 2754
2590 m_host.AddScriptLPS(1); 2755 m_host.AddScriptLPS(1);
2591 2756
2757 m_host.TaskInventory.LockItemsForRead(true);
2592 TaskInventoryItem item = m_host.TaskInventory[invItemID]; 2758 TaskInventoryItem item = m_host.TaskInventory[invItemID];
2593 2759 m_host.TaskInventory.LockItemsForRead(false);
2594 lock (m_host.TaskInventory)
2595 {
2596 item = m_host.TaskInventory[invItemID];
2597 }
2598 2760
2599 if (item.PermsGranter == UUID.Zero) 2761 if (item.PermsGranter == UUID.Zero)
2600 return 0; 2762 return 0;
@@ -2669,6 +2831,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2669 if (dist > m_ScriptDistanceFactor * 10.0f) 2831 if (dist > m_ScriptDistanceFactor * 10.0f)
2670 return; 2832 return;
2671 2833
2834 //Clone is thread-safe
2672 TaskInventoryDictionary partInventory = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 2835 TaskInventoryDictionary partInventory = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
2673 2836
2674 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in partInventory) 2837 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in partInventory)
@@ -2729,6 +2892,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2729 2892
2730 public void llLookAt(LSL_Vector target, double strength, double damping) 2893 public void llLookAt(LSL_Vector target, double strength, double damping)
2731 { 2894 {
2895 /*
2732 m_host.AddScriptLPS(1); 2896 m_host.AddScriptLPS(1);
2733 // Determine where we are looking from 2897 // Determine where we are looking from
2734 LSL_Vector from = llGetPos(); 2898 LSL_Vector from = llGetPos();
@@ -2748,10 +2912,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2748 // the angles of rotation in radians into rotation value 2912 // the angles of rotation in radians into rotation value
2749 2913
2750 LSL_Types.Quaternion rot = llEuler2Rot(angle); 2914 LSL_Types.Quaternion rot = llEuler2Rot(angle);
2751 Quaternion rotation = new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s); 2915
2752 m_host.startLookAt(rotation, (float)damping, (float)strength); 2916 // This would only work if your physics system contains an APID controller:
2917 // Quaternion rotation = new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s);
2918 // m_host.startLookAt(rotation, (float)damping, (float)strength);
2919
2753 // Orient the object to the angle calculated 2920 // Orient the object to the angle calculated
2754 //llSetRot(rot); 2921 llSetRot(rot);
2922 */
2923
2924 //The above code, while nice, doesn't replicate the behaviour of SL and tends to "roll" the object.
2925 //There's probably a smarter way of doing this, my rotation math-fu is weak.
2926 // http://bugs.meta7.com/view.php?id=28
2927 // - Tom
2928
2929 LSL_Rotation newrot = llGetRot() * llRotBetween(new LSL_Vector(1.0d, 0.0d, 0.0d) * llGetRot(), new LSL_Vector(0.0d, 0.0d, -1.0d));
2930 llSetRot(newrot * llRotBetween(new LSL_Vector(0.0d,0.0d,1.0d) * newrot, target - llGetPos()));
2931
2932 }
2933
2934 public void llRotLookAt(LSL_Rotation target, double strength, double damping)
2935 {
2936 m_host.AddScriptLPS(1);
2937// NotImplemented("llRotLookAt");
2938 m_host.RotLookAt(Rot2Quaternion(target), (float)strength, (float)damping);
2939
2755 } 2940 }
2756 2941
2757 public void llStopLookAt() 2942 public void llStopLookAt()
@@ -2800,13 +2985,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2800 { 2985 {
2801 TaskInventoryItem item; 2986 TaskInventoryItem item;
2802 2987
2803 lock (m_host.TaskInventory) 2988 m_host.TaskInventory.LockItemsForRead(true);
2989 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2804 { 2990 {
2805 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 2991 m_host.TaskInventory.LockItemsForRead(false);
2806 return; 2992 return;
2807 else
2808 item = m_host.TaskInventory[InventorySelf()];
2809 } 2993 }
2994 else
2995 {
2996 item = m_host.TaskInventory[InventorySelf()];
2997 }
2998 m_host.TaskInventory.LockItemsForRead(false);
2810 2999
2811 if (item.PermsGranter != UUID.Zero) 3000 if (item.PermsGranter != UUID.Zero)
2812 { 3001 {
@@ -2828,13 +3017,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2828 { 3017 {
2829 TaskInventoryItem item; 3018 TaskInventoryItem item;
2830 3019
3020 m_host.TaskInventory.LockItemsForRead(true);
2831 lock (m_host.TaskInventory) 3021 lock (m_host.TaskInventory)
2832 { 3022 {
3023
2833 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3024 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3025 {
3026 m_host.TaskInventory.LockItemsForRead(false);
2834 return; 3027 return;
3028 }
2835 else 3029 else
3030 {
2836 item = m_host.TaskInventory[InventorySelf()]; 3031 item = m_host.TaskInventory[InventorySelf()];
3032 }
2837 } 3033 }
3034 m_host.TaskInventory.LockItemsForRead(false);
2838 3035
2839 m_host.AddScriptLPS(1); 3036 m_host.AddScriptLPS(1);
2840 3037
@@ -2871,14 +3068,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2871 3068
2872 TaskInventoryItem item; 3069 TaskInventoryItem item;
2873 3070
2874 lock (m_host.TaskInventory) 3071 m_host.TaskInventory.LockItemsForRead(true);
3072
3073 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2875 { 3074 {
2876 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3075 m_host.TaskInventory.LockItemsForRead(false);
2877 return; 3076 return;
2878 else 3077 }
2879 item = m_host.TaskInventory[InventorySelf()]; 3078 else
3079 {
3080 item = m_host.TaskInventory[InventorySelf()];
2880 } 3081 }
2881 3082
3083 m_host.TaskInventory.LockItemsForRead(false);
3084
2882 if (item.PermsGranter != m_host.OwnerID) 3085 if (item.PermsGranter != m_host.OwnerID)
2883 return; 3086 return;
2884 3087
@@ -2905,13 +3108,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2905 3108
2906 TaskInventoryItem item; 3109 TaskInventoryItem item;
2907 3110
2908 lock (m_host.TaskInventory) 3111 m_host.TaskInventory.LockItemsForRead(true);
3112
3113 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2909 { 3114 {
2910 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3115 m_host.TaskInventory.LockItemsForRead(false);
2911 return; 3116 return;
2912 else
2913 item = m_host.TaskInventory[InventorySelf()];
2914 } 3117 }
3118 else
3119 {
3120 item = m_host.TaskInventory[InventorySelf()];
3121 }
3122 m_host.TaskInventory.LockItemsForRead(false);
3123
2915 3124
2916 if (item.PermsGranter != m_host.OwnerID) 3125 if (item.PermsGranter != m_host.OwnerID)
2917 return; 3126 return;
@@ -2948,8 +3157,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2948 return m_host.OwnerID.ToString(); 3157 return m_host.OwnerID.ToString();
2949 } 3158 }
2950 3159
3160 [DebuggerNonUserCode]
2951 public void llInstantMessage(string user, string message) 3161 public void llInstantMessage(string user, string message)
2952 { 3162 {
3163 UUID result;
3164 if (!UUID.TryParse(user, out result))
3165 {
3166 throw new Exception(String.Format("An invalid key of '{0} was passed to llInstantMessage", user));
3167 return;
3168 }
3169
3170
2953 m_host.AddScriptLPS(1); 3171 m_host.AddScriptLPS(1);
2954 3172
2955 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. 3173 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
@@ -2964,7 +3182,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2964 UUID friendTransactionID = UUID.Random(); 3182 UUID friendTransactionID = UUID.Random();
2965 3183
2966 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); 3184 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
2967 3185
2968 GridInstantMessage msg = new GridInstantMessage(); 3186 GridInstantMessage msg = new GridInstantMessage();
2969 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; 3187 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid;
2970 msg.toAgentID = new Guid(user); // toAgentID.Guid; 3188 msg.toAgentID = new Guid(user); // toAgentID.Guid;
@@ -3113,13 +3331,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3113 m_host.AddScriptLPS(1); 3331 m_host.AddScriptLPS(1);
3114 } 3332 }
3115 3333
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) 3334 public LSL_Integer llStringLength(string str)
3124 { 3335 {
3125 m_host.AddScriptLPS(1); 3336 m_host.AddScriptLPS(1);
@@ -3143,14 +3354,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3143 3354
3144 TaskInventoryItem item; 3355 TaskInventoryItem item;
3145 3356
3146 lock (m_host.TaskInventory) 3357 m_host.TaskInventory.LockItemsForRead(true);
3358 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3147 { 3359 {
3148 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3360 m_host.TaskInventory.LockItemsForRead(false);
3149 return; 3361 return;
3150 else
3151 item = m_host.TaskInventory[InventorySelf()];
3152 } 3362 }
3153 3363 else
3364 {
3365 item = m_host.TaskInventory[InventorySelf()];
3366 }
3367 m_host.TaskInventory.LockItemsForRead(false);
3154 if (item.PermsGranter == UUID.Zero) 3368 if (item.PermsGranter == UUID.Zero)
3155 return; 3369 return;
3156 3370
@@ -3180,13 +3394,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3180 3394
3181 TaskInventoryItem item; 3395 TaskInventoryItem item;
3182 3396
3183 lock (m_host.TaskInventory) 3397 m_host.TaskInventory.LockItemsForRead(true);
3398 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3184 { 3399 {
3185 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3400 m_host.TaskInventory.LockItemsForRead(false);
3186 return; 3401 return;
3187 else
3188 item = m_host.TaskInventory[InventorySelf()];
3189 } 3402 }
3403 else
3404 {
3405 item = m_host.TaskInventory[InventorySelf()];
3406 }
3407 m_host.TaskInventory.LockItemsForRead(false);
3408
3190 3409
3191 if (item.PermsGranter == UUID.Zero) 3410 if (item.PermsGranter == UUID.Zero)
3192 return; 3411 return;
@@ -3263,10 +3482,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3263 3482
3264 TaskInventoryItem item; 3483 TaskInventoryItem item;
3265 3484
3266 lock (m_host.TaskInventory) 3485
3486 m_host.TaskInventory.LockItemsForRead(true);
3487 if (!m_host.TaskInventory.ContainsKey(invItemID))
3488 {
3489 m_host.TaskInventory.LockItemsForRead(false);
3490 return;
3491 }
3492 else
3267 { 3493 {
3268 item = m_host.TaskInventory[invItemID]; 3494 item = m_host.TaskInventory[invItemID];
3269 } 3495 }
3496 m_host.TaskInventory.LockItemsForRead(false);
3270 3497
3271 if (agentID == UUID.Zero || perm == 0) // Releasing permissions 3498 if (agentID == UUID.Zero || perm == 0) // Releasing permissions
3272 { 3499 {
@@ -3298,11 +3525,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3298 3525
3299 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3526 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3300 { 3527 {
3301 lock (m_host.TaskInventory) 3528 m_host.TaskInventory.LockItemsForWrite(true);
3302 { 3529 m_host.TaskInventory[invItemID].PermsGranter = agentID;
3303 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3530 m_host.TaskInventory[invItemID].PermsMask = perm;
3304 m_host.TaskInventory[invItemID].PermsMask = perm; 3531 m_host.TaskInventory.LockItemsForWrite(false);
3305 }
3306 3532
3307 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3533 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3308 "run_time_permissions", new Object[] { 3534 "run_time_permissions", new Object[] {
@@ -3322,11 +3548,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3322 3548
3323 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3549 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3324 { 3550 {
3325 lock (m_host.TaskInventory) 3551 m_host.TaskInventory.LockItemsForWrite(true);
3326 { 3552 m_host.TaskInventory[invItemID].PermsGranter = agentID;
3327 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3553 m_host.TaskInventory[invItemID].PermsMask = perm;
3328 m_host.TaskInventory[invItemID].PermsMask = perm; 3554 m_host.TaskInventory.LockItemsForWrite(false);
3329 }
3330 3555
3331 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3556 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3332 "run_time_permissions", new Object[] { 3557 "run_time_permissions", new Object[] {
@@ -3347,11 +3572,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3347 3572
3348 if (!m_waitingForScriptAnswer) 3573 if (!m_waitingForScriptAnswer)
3349 { 3574 {
3350 lock (m_host.TaskInventory) 3575 m_host.TaskInventory.LockItemsForWrite(true);
3351 { 3576 m_host.TaskInventory[invItemID].PermsGranter = agentID;
3352 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3577 m_host.TaskInventory[invItemID].PermsMask = 0;
3353 m_host.TaskInventory[invItemID].PermsMask = 0; 3578 m_host.TaskInventory.LockItemsForWrite(false);
3354 }
3355 3579
3356 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; 3580 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
3357 m_waitingForScriptAnswer=true; 3581 m_waitingForScriptAnswer=true;
@@ -3386,10 +3610,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3386 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) 3610 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
3387 llReleaseControls(); 3611 llReleaseControls();
3388 3612
3389 lock (m_host.TaskInventory) 3613
3390 { 3614 m_host.TaskInventory.LockItemsForWrite(true);
3391 m_host.TaskInventory[invItemID].PermsMask = answer; 3615 m_host.TaskInventory[invItemID].PermsMask = answer;
3392 } 3616 m_host.TaskInventory.LockItemsForWrite(false);
3617
3393 3618
3394 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3619 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3395 "run_time_permissions", new Object[] { 3620 "run_time_permissions", new Object[] {
@@ -3401,16 +3626,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3401 { 3626 {
3402 m_host.AddScriptLPS(1); 3627 m_host.AddScriptLPS(1);
3403 3628
3404 lock (m_host.TaskInventory) 3629 m_host.TaskInventory.LockItemsForRead(true);
3630
3631 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3405 { 3632 {
3406 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 3633 if (item.Type == 10 && item.ItemID == m_itemID)
3407 { 3634 {
3408 if (item.Type == 10 && item.ItemID == m_itemID) 3635 m_host.TaskInventory.LockItemsForRead(false);
3409 { 3636 return item.PermsGranter.ToString();
3410 return item.PermsGranter.ToString();
3411 }
3412 } 3637 }
3413 } 3638 }
3639 m_host.TaskInventory.LockItemsForRead(false);
3414 3640
3415 return UUID.Zero.ToString(); 3641 return UUID.Zero.ToString();
3416 } 3642 }
@@ -3419,19 +3645,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3419 { 3645 {
3420 m_host.AddScriptLPS(1); 3646 m_host.AddScriptLPS(1);
3421 3647
3422 lock (m_host.TaskInventory) 3648 m_host.TaskInventory.LockItemsForRead(true);
3649
3650 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3423 { 3651 {
3424 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 3652 if (item.Type == 10 && item.ItemID == m_itemID)
3425 { 3653 {
3426 if (item.Type == 10 && item.ItemID == m_itemID) 3654 int perms = item.PermsMask;
3427 { 3655 if (m_automaticLinkPermission)
3428 int perms = item.PermsMask; 3656 perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS;
3429 if (m_automaticLinkPermission) 3657 m_host.TaskInventory.LockItemsForRead(false);
3430 perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS; 3658 return perms;
3431 return perms;
3432 }
3433 } 3659 }
3434 } 3660 }
3661 m_host.TaskInventory.LockItemsForRead(false);
3435 3662
3436 return 0; 3663 return 0;
3437 } 3664 }
@@ -3453,9 +3680,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3453 public void llSetLinkColor(int linknumber, LSL_Vector color, int face) 3680 public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
3454 { 3681 {
3455 List<SceneObjectPart> parts = GetLinkParts(linknumber); 3682 List<SceneObjectPart> parts = GetLinkParts(linknumber);
3456 3683 if (parts.Count > 0)
3457 foreach (SceneObjectPart part in parts) 3684 {
3458 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); 3685 try
3686 {
3687 parts[0].ParentGroup.areUpdatesSuspended = true;
3688 foreach (SceneObjectPart part in parts)
3689 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face);
3690 }
3691 finally
3692 {
3693 parts[0].ParentGroup.areUpdatesSuspended = false;
3694 }
3695 }
3459 } 3696 }
3460 3697
3461 public void llCreateLink(string target, int parent) 3698 public void llCreateLink(string target, int parent)
@@ -3464,11 +3701,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3464 UUID invItemID = InventorySelf(); 3701 UUID invItemID = InventorySelf();
3465 3702
3466 TaskInventoryItem item; 3703 TaskInventoryItem item;
3467 lock (m_host.TaskInventory) 3704 m_host.TaskInventory.LockItemsForRead(true);
3468 { 3705 item = m_host.TaskInventory[invItemID];
3469 item = m_host.TaskInventory[invItemID]; 3706 m_host.TaskInventory.LockItemsForRead(false);
3470 } 3707
3471
3472 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 3708 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
3473 && !m_automaticLinkPermission) 3709 && !m_automaticLinkPermission)
3474 { 3710 {
@@ -3521,16 +3757,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3521 m_host.AddScriptLPS(1); 3757 m_host.AddScriptLPS(1);
3522 UUID invItemID = InventorySelf(); 3758 UUID invItemID = InventorySelf();
3523 3759
3524 lock (m_host.TaskInventory) 3760 m_host.TaskInventory.LockItemsForRead(true);
3525 {
3526 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 3761 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
3527 && !m_automaticLinkPermission) 3762 && !m_automaticLinkPermission)
3528 { 3763 {
3529 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!"); 3764 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
3765 m_host.TaskInventory.LockItemsForRead(false);
3530 return; 3766 return;
3531 } 3767 }
3532 } 3768 m_host.TaskInventory.LockItemsForRead(false);
3533 3769
3534 if (linknum < ScriptBaseClass.LINK_THIS) 3770 if (linknum < ScriptBaseClass.LINK_THIS)
3535 return; 3771 return;
3536 3772
@@ -3569,10 +3805,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3569 // Restructuring Multiple Prims. 3805 // Restructuring Multiple Prims.
3570 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values); 3806 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values);
3571 parts.Remove(parentPrim.RootPart); 3807 parts.Remove(parentPrim.RootPart);
3572 foreach (SceneObjectPart part in parts) 3808 if (parts.Count > 0)
3573 { 3809 {
3574 parentPrim.DelinkFromGroup(part.LocalId, true); 3810 try
3811 {
3812 parts[0].ParentGroup.areUpdatesSuspended = true;
3813 foreach (SceneObjectPart part in parts)
3814 {
3815 parentPrim.DelinkFromGroup(part.LocalId, true);
3816 }
3817 }
3818 finally
3819 {
3820 parts[0].ParentGroup.areUpdatesSuspended = false;
3821 }
3575 } 3822 }
3823
3576 parentPrim.HasGroupChanged = true; 3824 parentPrim.HasGroupChanged = true;
3577 parentPrim.ScheduleGroupForFullUpdate(); 3825 parentPrim.ScheduleGroupForFullUpdate();
3578 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 3826 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
@@ -3581,11 +3829,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3581 { 3829 {
3582 SceneObjectPart newRoot = parts[0]; 3830 SceneObjectPart newRoot = parts[0];
3583 parts.Remove(newRoot); 3831 parts.Remove(newRoot);
3584 foreach (SceneObjectPart part in parts) 3832
3833 try
3585 { 3834 {
3586 part.UpdateFlag = 0; 3835 parts[0].ParentGroup.areUpdatesSuspended = true;
3587 newRoot.ParentGroup.LinkToGroup(part.ParentGroup); 3836 foreach (SceneObjectPart part in parts)
3837 {
3838 part.UpdateFlag = 0;
3839 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
3840 }
3588 } 3841 }
3842 finally
3843 {
3844 parts[0].ParentGroup.areUpdatesSuspended = false;
3845 }
3846
3847
3589 newRoot.ParentGroup.HasGroupChanged = true; 3848 newRoot.ParentGroup.HasGroupChanged = true;
3590 newRoot.ParentGroup.ScheduleGroupForFullUpdate(); 3849 newRoot.ParentGroup.ScheduleGroupForFullUpdate();
3591 } 3850 }
@@ -3611,11 +3870,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3611 3870
3612 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values); 3871 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values);
3613 parts.Remove(parentPrim.RootPart); 3872 parts.Remove(parentPrim.RootPart);
3614 3873 if (parts.Count > 0)
3615 foreach (SceneObjectPart part in parts)
3616 { 3874 {
3617 parentPrim.DelinkFromGroup(part.LocalId, true); 3875 try
3618 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 3876 {
3877 parts[0].ParentGroup.areUpdatesSuspended = true;
3878 foreach (SceneObjectPart part in parts)
3879 {
3880 parentPrim.DelinkFromGroup(part.LocalId, true);
3881 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
3882 }
3883 }
3884 finally
3885 {
3886 parts[0].ParentGroup.areUpdatesSuspended = false;
3887 }
3619 } 3888 }
3620 parentPrim.HasGroupChanged = true; 3889 parentPrim.HasGroupChanged = true;
3621 parentPrim.ScheduleGroupForFullUpdate(); 3890 parentPrim.ScheduleGroupForFullUpdate();
@@ -3707,17 +3976,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3707 m_host.AddScriptLPS(1); 3976 m_host.AddScriptLPS(1);
3708 int count = 0; 3977 int count = 0;
3709 3978
3710 lock (m_host.TaskInventory) 3979 m_host.TaskInventory.LockItemsForRead(true);
3980 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3711 { 3981 {
3712 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 3982 if (inv.Value.Type == type || type == -1)
3713 { 3983 {
3714 if (inv.Value.Type == type || type == -1) 3984 count = count + 1;
3715 {
3716 count = count + 1;
3717 }
3718 } 3985 }
3719 } 3986 }
3720 3987
3988 m_host.TaskInventory.LockItemsForRead(false);
3721 return count; 3989 return count;
3722 } 3990 }
3723 3991
@@ -3726,16 +3994,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3726 m_host.AddScriptLPS(1); 3994 m_host.AddScriptLPS(1);
3727 ArrayList keys = new ArrayList(); 3995 ArrayList keys = new ArrayList();
3728 3996
3729 lock (m_host.TaskInventory) 3997 m_host.TaskInventory.LockItemsForRead(true);
3998 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3730 { 3999 {
3731 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4000 if (inv.Value.Type == type || type == -1)
3732 { 4001 {
3733 if (inv.Value.Type == type || type == -1) 4002 keys.Add(inv.Value.Name);
3734 {
3735 keys.Add(inv.Value.Name);
3736 }
3737 } 4003 }
3738 } 4004 }
4005 m_host.TaskInventory.LockItemsForRead(false);
3739 4006
3740 if (keys.Count == 0) 4007 if (keys.Count == 0)
3741 { 4008 {
@@ -3772,20 +4039,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3772 } 4039 }
3773 4040
3774 // move the first object found with this inventory name 4041 // move the first object found with this inventory name
3775 lock (m_host.TaskInventory) 4042 m_host.TaskInventory.LockItemsForRead(true);
4043 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3776 { 4044 {
3777 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4045 if (inv.Value.Name == inventory)
3778 { 4046 {
3779 if (inv.Value.Name == inventory) 4047 found = true;
3780 { 4048 objId = inv.Key;
3781 found = true; 4049 assetType = inv.Value.Type;
3782 objId = inv.Key; 4050 objName = inv.Value.Name;
3783 assetType = inv.Value.Type; 4051 break;
3784 objName = inv.Value.Name;
3785 break;
3786 }
3787 } 4052 }
3788 } 4053 }
4054 m_host.TaskInventory.LockItemsForRead(false);
3789 4055
3790 if (!found) 4056 if (!found)
3791 { 4057 {
@@ -3793,9 +4059,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3793 throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory)); 4059 throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
3794 } 4060 }
3795 4061
3796 // check if destination is an avatar 4062 // check if destination is an object
3797 if (World.GetScenePresence(destId) != null) 4063 if (World.GetSceneObjectPart(destId) != null)
4064 {
4065 // destination is an object
4066 World.MoveTaskInventoryItem(destId, m_host, objId);
4067 }
4068 else
3798 { 4069 {
4070 ScenePresence presence = World.GetScenePresence(destId);
4071
4072 if (presence == null)
4073 {
4074 UserAccount account =
4075 World.UserAccountService.GetUserAccount(
4076 World.RegionInfo.ScopeID,
4077 destId);
4078
4079 if (account == null)
4080 {
4081 llSay(0, "Can't find destination "+destId.ToString());
4082 return;
4083 }
4084 }
4085
3799 // destination is an avatar 4086 // destination is an avatar
3800 InventoryItemBase agentItem = 4087 InventoryItemBase agentItem =
3801 World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId); 4088 World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId);
@@ -3821,33 +4108,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3821 4108
3822 if (m_TransferModule != null) 4109 if (m_TransferModule != null)
3823 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 4110 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
4111
4112 //This delay should only occur when giving inventory to avatars.
4113 ScriptSleep(3000);
3824 } 4114 }
3825 else
3826 {
3827 // destination is an object
3828 World.MoveTaskInventoryItem(destId, m_host, objId);
3829 }
3830 ScriptSleep(3000);
3831 } 4115 }
3832 4116
4117 [DebuggerNonUserCode]
3833 public void llRemoveInventory(string name) 4118 public void llRemoveInventory(string name)
3834 { 4119 {
3835 m_host.AddScriptLPS(1); 4120 m_host.AddScriptLPS(1);
3836 4121
3837 lock (m_host.TaskInventory) 4122 m_host.TaskInventory.LockItemsForRead(true);
4123 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3838 { 4124 {
3839 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4125 if (item.Name == name)
3840 { 4126 {
3841 if (item.Name == name) 4127 if (item.ItemID == m_itemID)
3842 { 4128 throw new ScriptDeleteException();
3843 if (item.ItemID == m_itemID) 4129 else
3844 throw new ScriptDeleteException(); 4130 m_host.Inventory.RemoveInventoryItem(item.ItemID);
3845 else 4131
3846 m_host.Inventory.RemoveInventoryItem(item.ItemID); 4132 m_host.TaskInventory.LockItemsForRead(false);
3847 return; 4133 return;
3848 }
3849 } 4134 }
3850 } 4135 }
4136 m_host.TaskInventory.LockItemsForRead(false);
3851 } 4137 }
3852 4138
3853 public void llSetText(string text, LSL_Vector color, double alpha) 4139 public void llSetText(string text, LSL_Vector color, double alpha)
@@ -3938,6 +4224,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3938 { 4224 {
3939 m_host.AddScriptLPS(1); 4225 m_host.AddScriptLPS(1);
3940 4226
4227 //Clone is thread safe
3941 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 4228 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
3942 4229
3943 foreach (TaskInventoryItem item in itemDictionary.Values) 4230 foreach (TaskInventoryItem item in itemDictionary.Values)
@@ -3991,6 +4278,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3991 ScenePresence presence = World.GetScenePresence(agentId); 4278 ScenePresence presence = World.GetScenePresence(agentId);
3992 if (presence != null) 4279 if (presence != null)
3993 { 4280 {
4281 // agent must not be a god
4282 if (presence.GodLevel >= 200) return;
4283
3994 // agent must be over the owners land 4284 // agent must be over the owners land
3995 if (m_host.OwnerID == World.LandChannel.GetLandObject( 4285 if (m_host.OwnerID == World.LandChannel.GetLandObject(
3996 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) 4286 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
@@ -4051,17 +4341,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4051 UUID soundId = UUID.Zero; 4341 UUID soundId = UUID.Zero;
4052 if (!UUID.TryParse(impact_sound, out soundId)) 4342 if (!UUID.TryParse(impact_sound, out soundId))
4053 { 4343 {
4054 lock (m_host.TaskInventory) 4344 m_host.TaskInventory.LockItemsForRead(true);
4345 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
4055 { 4346 {
4056 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4347 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound)
4057 { 4348 {
4058 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound) 4349 soundId = item.AssetID;
4059 { 4350 break;
4060 soundId = item.AssetID;
4061 break;
4062 }
4063 } 4351 }
4064 } 4352 }
4353 m_host.TaskInventory.LockItemsForRead(false);
4065 } 4354 }
4066 m_host.CollisionSound = soundId; 4355 m_host.CollisionSound = soundId;
4067 m_host.CollisionSoundVolume = (float)impact_volume; 4356 m_host.CollisionSoundVolume = (float)impact_volume;
@@ -4107,6 +4396,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4107 UUID partItemID; 4396 UUID partItemID;
4108 foreach (SceneObjectPart part in parts) 4397 foreach (SceneObjectPart part in parts)
4109 { 4398 {
4399 //Clone is thread safe
4110 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); 4400 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
4111 4401
4112 foreach (TaskInventoryItem item in itemsDictionary.Values) 4402 foreach (TaskInventoryItem item in itemsDictionary.Values)
@@ -4321,17 +4611,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4321 4611
4322 m_host.AddScriptLPS(1); 4612 m_host.AddScriptLPS(1);
4323 4613
4324 lock (m_host.TaskInventory) 4614 m_host.TaskInventory.LockItemsForRead(true);
4615 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
4325 { 4616 {
4326 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4617 if (item.Type == 10 && item.ItemID == m_itemID)
4327 { 4618 {
4328 if (item.Type == 10 && item.ItemID == m_itemID) 4619 result = item.Name!=null?item.Name:String.Empty;
4329 { 4620 break;
4330 result = item.Name != null ? item.Name : String.Empty;
4331 break;
4332 }
4333 } 4621 }
4334 } 4622 }
4623 m_host.TaskInventory.LockItemsForRead(false);
4335 4624
4336 return result; 4625 return result;
4337 } 4626 }
@@ -4484,23 +4773,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4484 { 4773 {
4485 m_host.AddScriptLPS(1); 4774 m_host.AddScriptLPS(1);
4486 4775
4487 lock (m_host.TaskInventory) 4776 m_host.TaskInventory.LockItemsForRead(true);
4777 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
4488 { 4778 {
4489 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4779 if (inv.Value.Name == name)
4490 { 4780 {
4491 if (inv.Value.Name == name) 4781 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
4492 { 4782 {
4493 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) 4783 m_host.TaskInventory.LockItemsForRead(false);
4494 { 4784 return inv.Value.AssetID.ToString();
4495 return inv.Value.AssetID.ToString(); 4785 }
4496 } 4786 else
4497 else 4787 {
4498 { 4788 m_host.TaskInventory.LockItemsForRead(false);
4499 return UUID.Zero.ToString(); 4789 return UUID.Zero.ToString();
4500 }
4501 } 4790 }
4502 } 4791 }
4503 } 4792 }
4793 m_host.TaskInventory.LockItemsForRead(false);
4504 4794
4505 return UUID.Zero.ToString(); 4795 return UUID.Zero.ToString();
4506 } 4796 }
@@ -5436,10 +5726,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5436 m_host.AddScriptLPS(1); 5726 m_host.AddScriptLPS(1);
5437 5727
5438 List<SceneObjectPart> parts = GetLinkParts(linknumber); 5728 List<SceneObjectPart> parts = GetLinkParts(linknumber);
5439 5729 if (parts.Count > 0)
5440 foreach (var part in parts)
5441 { 5730 {
5442 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); 5731 try
5732 {
5733 parts[0].ParentGroup.areUpdatesSuspended = true;
5734 foreach (var part in parts)
5735 {
5736 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
5737 }
5738 }
5739 finally
5740 {
5741 parts[0].ParentGroup.areUpdatesSuspended = false;
5742 }
5443 } 5743 }
5444 } 5744 }
5445 5745
@@ -6018,6 +6318,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6018 tempf = (float)rules.GetLSLFloatItem(i + 1); 6318 tempf = (float)rules.GetLSLFloatItem(i + 1);
6019 prules.OuterAngle = (float)tempf; 6319 prules.OuterAngle = (float)tempf;
6020 break; 6320 break;
6321
6322 case (int)ScriptBaseClass.PSYS_SRC_INNERANGLE:
6323 tempf = (float)rules.GetLSLFloatItem(i + 1);
6324 prules.InnerAngle = (float)tempf;
6325 break;
6326
6327 case (int)ScriptBaseClass.PSYS_SRC_OUTERANGLE:
6328 tempf = (float)rules.GetLSLFloatItem(i + 1);
6329 prules.OuterAngle = (float)tempf;
6330 break;
6021 } 6331 }
6022 6332
6023 } 6333 }
@@ -6056,14 +6366,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6056 6366
6057 protected UUID GetTaskInventoryItem(string name) 6367 protected UUID GetTaskInventoryItem(string name)
6058 { 6368 {
6059 lock (m_host.TaskInventory) 6369 m_host.TaskInventory.LockItemsForRead(true);
6370 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6060 { 6371 {
6061 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 6372 if (inv.Value.Name == name)
6062 { 6373 {
6063 if (inv.Value.Name == name) 6374 m_host.TaskInventory.LockItemsForRead(false);
6064 return inv.Key; 6375 return inv.Key;
6065 } 6376 }
6066 } 6377 }
6378 m_host.TaskInventory.LockItemsForRead(false);
6067 6379
6068 return UUID.Zero; 6380 return UUID.Zero;
6069 } 6381 }
@@ -6391,22 +6703,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6391 } 6703 }
6392 6704
6393 // copy the first script found with this inventory name 6705 // copy the first script found with this inventory name
6394 lock (m_host.TaskInventory) 6706 m_host.TaskInventory.LockItemsForRead(true);
6707 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6395 { 6708 {
6396 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 6709 if (inv.Value.Name == name)
6397 { 6710 {
6398 if (inv.Value.Name == name) 6711 // make sure the object is a script
6712 if (10 == inv.Value.Type)
6399 { 6713 {
6400 // make sure the object is a script 6714 found = true;
6401 if (10 == inv.Value.Type) 6715 srcId = inv.Key;
6402 { 6716 break;
6403 found = true;
6404 srcId = inv.Key;
6405 break;
6406 }
6407 } 6717 }
6408 } 6718 }
6409 } 6719 }
6720 m_host.TaskInventory.LockItemsForRead(false);
6410 6721
6411 if (!found) 6722 if (!found)
6412 { 6723 {
@@ -6490,6 +6801,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6490 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist) 6801 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist)
6491 { 6802 {
6492 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 6803 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
6804 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
6805 return shapeBlock;
6493 6806
6494 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && 6807 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
6495 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && 6808 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
@@ -6560,6 +6873,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6560 6873
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) 6874 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 { 6875 {
6876 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
6877 return;
6878
6563 ObjectShapePacket.ObjectDataBlock shapeBlock; 6879 ObjectShapePacket.ObjectDataBlock shapeBlock;
6564 6880
6565 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist); 6881 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist);
@@ -6609,6 +6925,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6609 6925
6610 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte fudge) 6926 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte fudge)
6611 { 6927 {
6928 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
6929 return;
6930
6612 ObjectShapePacket.ObjectDataBlock shapeBlock; 6931 ObjectShapePacket.ObjectDataBlock shapeBlock;
6613 6932
6614 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist); 6933 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist);
@@ -6651,6 +6970,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6651 6970
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) 6971 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 { 6972 {
6973 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
6974 return;
6975
6654 ObjectShapePacket.ObjectDataBlock shapeBlock; 6976 ObjectShapePacket.ObjectDataBlock shapeBlock;
6655 6977
6656 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist); 6978 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist);
@@ -6772,6 +7094,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6772 7094
6773 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type) 7095 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type)
6774 { 7096 {
7097 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7098 return;
7099
6775 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7100 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
6776 UUID sculptId; 7101 UUID sculptId;
6777 7102
@@ -6812,12 +7137,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6812 7137
6813 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) 7138 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
6814 { 7139 {
6815 m_host.AddScriptLPS(1); 7140 m_host.AddScriptLPS(1);
6816 7141
6817 List<SceneObjectPart> parts = GetLinkParts(linknumber); 7142 List<SceneObjectPart> parts = GetLinkParts(linknumber);
6818 7143 if (parts.Count>0)
6819 foreach (SceneObjectPart part in parts) 7144 {
6820 SetPrimParams(part, rules); 7145 try
7146 {
7147 parts[0].ParentGroup.areUpdatesSuspended = true;
7148 foreach (SceneObjectPart part in parts)
7149 SetPrimParams(part, rules);
7150 }
7151 finally
7152 {
7153 parts[0].ParentGroup.areUpdatesSuspended = false;
7154 }
7155 }
6821 } 7156 }
6822 7157
6823 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) 7158 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
@@ -6827,6 +7162,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6827 7162
6828 protected void SetPrimParams(SceneObjectPart part, LSL_List rules) 7163 protected void SetPrimParams(SceneObjectPart part, LSL_List rules)
6829 { 7164 {
7165 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7166 return;
7167
6830 int idx = 0; 7168 int idx = 0;
6831 7169
6832 while (idx < rules.Length) 7170 while (idx < rules.Length)
@@ -7658,24 +7996,95 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7658 break; 7996 break;
7659 7997
7660 case (int)ScriptBaseClass.PRIM_BUMP_SHINY: 7998 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
7661 // TODO--------------
7662 if (remain < 1) 7999 if (remain < 1)
7663 return res; 8000 return res;
8001 face = (int)rules.GetLSLIntegerItem(idx++);
7664 8002
7665 face=(int)rules.GetLSLIntegerItem(idx++); 8003 tex = part.Shape.Textures;
7666 8004 int shiny;
7667 res.Add(new LSL_Integer(0)); 8005 if (face == ScriptBaseClass.ALL_SIDES)
7668 res.Add(new LSL_Integer(0)); 8006 {
8007 for (face = 0; face < GetNumberOfSides(part); face++)
8008 {
8009 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8010 if (shinyness == Shininess.High)
8011 {
8012 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8013 }
8014 else if (shinyness == Shininess.Medium)
8015 {
8016 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8017 }
8018 else if (shinyness == Shininess.Low)
8019 {
8020 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8021 }
8022 else
8023 {
8024 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8025 }
8026 res.Add(new LSL_Integer(shiny));
8027 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8028 }
8029 }
8030 else
8031 {
8032 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8033 if (shinyness == Shininess.High)
8034 {
8035 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8036 }
8037 else if (shinyness == Shininess.Medium)
8038 {
8039 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8040 }
8041 else if (shinyness == Shininess.Low)
8042 {
8043 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8044 }
8045 else
8046 {
8047 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8048 }
8049 res.Add(new LSL_Integer(shiny));
8050 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8051 }
7669 break; 8052 break;
7670 8053
7671 case (int)ScriptBaseClass.PRIM_FULLBRIGHT: 8054 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
7672 // TODO--------------
7673 if (remain < 1) 8055 if (remain < 1)
7674 return res; 8056 return res;
8057 face = (int)rules.GetLSLIntegerItem(idx++);
7675 8058
7676 face=(int)rules.GetLSLIntegerItem(idx++); 8059 tex = part.Shape.Textures;
7677 8060 int fullbright;
7678 res.Add(new LSL_Integer(0)); 8061 if (face == ScriptBaseClass.ALL_SIDES)
8062 {
8063 for (face = 0; face < GetNumberOfSides(part); face++)
8064 {
8065 if (tex.GetFace((uint)face).Fullbright == true)
8066 {
8067 fullbright = ScriptBaseClass.TRUE;
8068 }
8069 else
8070 {
8071 fullbright = ScriptBaseClass.FALSE;
8072 }
8073 res.Add(new LSL_Integer(fullbright));
8074 }
8075 }
8076 else
8077 {
8078 if (tex.GetFace((uint)face).Fullbright == true)
8079 {
8080 fullbright = ScriptBaseClass.TRUE;
8081 }
8082 else
8083 {
8084 fullbright = ScriptBaseClass.FALSE;
8085 }
8086 res.Add(new LSL_Integer(fullbright));
8087 }
7679 break; 8088 break;
7680 8089
7681 case (int)ScriptBaseClass.PRIM_FLEXIBLE: 8090 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
@@ -7696,14 +8105,37 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7696 break; 8105 break;
7697 8106
7698 case (int)ScriptBaseClass.PRIM_TEXGEN: 8107 case (int)ScriptBaseClass.PRIM_TEXGEN:
7699 // TODO--------------
7700 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR) 8108 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
7701 if (remain < 1) 8109 if (remain < 1)
7702 return res; 8110 return res;
8111 face = (int)rules.GetLSLIntegerItem(idx++);
7703 8112
7704 face=(int)rules.GetLSLIntegerItem(idx++); 8113 tex = part.Shape.Textures;
7705 8114 if (face == ScriptBaseClass.ALL_SIDES)
7706 res.Add(new LSL_Integer(0)); 8115 {
8116 for (face = 0; face < GetNumberOfSides(part); face++)
8117 {
8118 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8119 {
8120 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8121 }
8122 else
8123 {
8124 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8125 }
8126 }
8127 }
8128 else
8129 {
8130 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8131 {
8132 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8133 }
8134 else
8135 {
8136 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8137 }
8138 }
7707 break; 8139 break;
7708 8140
7709 case (int)ScriptBaseClass.PRIM_POINT_LIGHT: 8141 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
@@ -7722,13 +8154,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7722 break; 8154 break;
7723 8155
7724 case (int)ScriptBaseClass.PRIM_GLOW: 8156 case (int)ScriptBaseClass.PRIM_GLOW:
7725 // TODO--------------
7726 if (remain < 1) 8157 if (remain < 1)
7727 return res; 8158 return res;
8159 face = (int)rules.GetLSLIntegerItem(idx++);
7728 8160
7729 face=(int)rules.GetLSLIntegerItem(idx++); 8161 tex = part.Shape.Textures;
7730 8162 float primglow;
7731 res.Add(new LSL_Float(0)); 8163 if (face == ScriptBaseClass.ALL_SIDES)
8164 {
8165 for (face = 0; face < GetNumberOfSides(part); face++)
8166 {
8167 primglow = tex.GetFace((uint)face).Glow;
8168 res.Add(new LSL_Float(primglow));
8169 }
8170 }
8171 else
8172 {
8173 primglow = tex.GetFace((uint)face).Glow;
8174 res.Add(new LSL_Float(primglow));
8175 }
7732 break; 8176 break;
7733 case (int)ScriptBaseClass.PRIM_TEXT: 8177 case (int)ScriptBaseClass.PRIM_TEXT:
7734 Color4 textColor = part.GetTextColor(); 8178 Color4 textColor = part.GetTextColor();
@@ -8265,28 +8709,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8265 { 8709 {
8266 m_host.AddScriptLPS(1); 8710 m_host.AddScriptLPS(1);
8267 8711
8268 lock (m_host.TaskInventory) 8712 m_host.TaskInventory.LockItemsForRead(true);
8713 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
8269 { 8714 {
8270 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 8715 if (inv.Value.Name == item)
8271 { 8716 {
8272 if (inv.Value.Name == item) 8717 m_host.TaskInventory.LockItemsForRead(false);
8718 switch (mask)
8273 { 8719 {
8274 switch (mask) 8720 case 0:
8275 { 8721 return (int)inv.Value.BasePermissions;
8276 case 0: 8722 case 1:
8277 return (int)inv.Value.BasePermissions; 8723 return (int)inv.Value.CurrentPermissions;
8278 case 1: 8724 case 2:
8279 return (int)inv.Value.CurrentPermissions; 8725 return (int)inv.Value.GroupPermissions;
8280 case 2: 8726 case 3:
8281 return (int)inv.Value.GroupPermissions; 8727 return (int)inv.Value.EveryonePermissions;
8282 case 3: 8728 case 4:
8283 return (int)inv.Value.EveryonePermissions; 8729 return (int)inv.Value.NextPermissions;
8284 case 4:
8285 return (int)inv.Value.NextPermissions;
8286 }
8287 } 8730 }
8288 } 8731 }
8289 } 8732 }
8733 m_host.TaskInventory.LockItemsForRead(false);
8290 8734
8291 return -1; 8735 return -1;
8292 } 8736 }
@@ -8333,16 +8777,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8333 { 8777 {
8334 m_host.AddScriptLPS(1); 8778 m_host.AddScriptLPS(1);
8335 8779
8336 lock (m_host.TaskInventory) 8780 m_host.TaskInventory.LockItemsForRead(true);
8781 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
8337 { 8782 {
8338 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 8783 if (inv.Value.Name == item)
8339 { 8784 {
8340 if (inv.Value.Name == item) 8785 m_host.TaskInventory.LockItemsForRead(false);
8341 { 8786 return inv.Value.CreatorID.ToString();
8342 return inv.Value.CreatorID.ToString();
8343 }
8344 } 8787 }
8345 } 8788 }
8789 m_host.TaskInventory.LockItemsForRead(false);
8346 8790
8347 llSay(0, "No item name '" + item + "'"); 8791 llSay(0, "No item name '" + item + "'");
8348 8792
@@ -8602,17 +9046,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8602 int width = 0; 9046 int width = 0;
8603 int height = 0; 9047 int height = 0;
8604 9048
8605 ParcelMediaCommandEnum? commandToSend = null; 9049 uint commandToSend = 0;
8606 float time = 0.0f; // default is from start 9050 float time = 0.0f; // default is from start
8607 9051
8608 ScenePresence presence = null; 9052 ScenePresence presence = null;
8609 9053
8610 for (int i = 0; i < commandList.Data.Length; i++) 9054 for (int i = 0; i < commandList.Data.Length; i++)
8611 { 9055 {
8612 ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i]; 9056 uint command = (uint)(commandList.GetLSLIntegerItem(i));
8613 switch (command) 9057 switch (command)
8614 { 9058 {
8615 case ParcelMediaCommandEnum.Agent: 9059 case (uint)ParcelMediaCommandEnum.Agent:
8616 // we send only to one agent 9060 // we send only to one agent
8617 if ((i + 1) < commandList.Length) 9061 if ((i + 1) < commandList.Length)
8618 { 9062 {
@@ -8629,25 +9073,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8629 } 9073 }
8630 break; 9074 break;
8631 9075
8632 case ParcelMediaCommandEnum.Loop: 9076 case (uint)ParcelMediaCommandEnum.Loop:
8633 loop = 1; 9077 loop = 1;
8634 commandToSend = command; 9078 commandToSend = command;
8635 update = true; //need to send the media update packet to set looping 9079 update = true; //need to send the media update packet to set looping
8636 break; 9080 break;
8637 9081
8638 case ParcelMediaCommandEnum.Play: 9082 case (uint)ParcelMediaCommandEnum.Play:
8639 loop = 0; 9083 loop = 0;
8640 commandToSend = command; 9084 commandToSend = command;
8641 update = true; //need to send the media update packet to make sure it doesn't loop 9085 update = true; //need to send the media update packet to make sure it doesn't loop
8642 break; 9086 break;
8643 9087
8644 case ParcelMediaCommandEnum.Pause: 9088 case (uint)ParcelMediaCommandEnum.Pause:
8645 case ParcelMediaCommandEnum.Stop: 9089 case (uint)ParcelMediaCommandEnum.Stop:
8646 case ParcelMediaCommandEnum.Unload: 9090 case (uint)ParcelMediaCommandEnum.Unload:
8647 commandToSend = command; 9091 commandToSend = command;
8648 break; 9092 break;
8649 9093
8650 case ParcelMediaCommandEnum.Url: 9094 case (uint)ParcelMediaCommandEnum.Url:
8651 if ((i + 1) < commandList.Length) 9095 if ((i + 1) < commandList.Length)
8652 { 9096 {
8653 if (commandList.Data[i + 1] is LSL_String) 9097 if (commandList.Data[i + 1] is LSL_String)
@@ -8660,7 +9104,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8660 } 9104 }
8661 break; 9105 break;
8662 9106
8663 case ParcelMediaCommandEnum.Texture: 9107 case (uint)ParcelMediaCommandEnum.Texture:
8664 if ((i + 1) < commandList.Length) 9108 if ((i + 1) < commandList.Length)
8665 { 9109 {
8666 if (commandList.Data[i + 1] is LSL_String) 9110 if (commandList.Data[i + 1] is LSL_String)
@@ -8673,7 +9117,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8673 } 9117 }
8674 break; 9118 break;
8675 9119
8676 case ParcelMediaCommandEnum.Time: 9120 case (uint)ParcelMediaCommandEnum.Time:
8677 if ((i + 1) < commandList.Length) 9121 if ((i + 1) < commandList.Length)
8678 { 9122 {
8679 if (commandList.Data[i + 1] is LSL_Float) 9123 if (commandList.Data[i + 1] is LSL_Float)
@@ -8685,7 +9129,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8685 } 9129 }
8686 break; 9130 break;
8687 9131
8688 case ParcelMediaCommandEnum.AutoAlign: 9132 case (uint)ParcelMediaCommandEnum.AutoAlign:
8689 if ((i + 1) < commandList.Length) 9133 if ((i + 1) < commandList.Length)
8690 { 9134 {
8691 if (commandList.Data[i + 1] is LSL_Integer) 9135 if (commandList.Data[i + 1] is LSL_Integer)
@@ -8699,7 +9143,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8699 } 9143 }
8700 break; 9144 break;
8701 9145
8702 case ParcelMediaCommandEnum.Type: 9146 case (uint)ParcelMediaCommandEnum.Type:
8703 if ((i + 1) < commandList.Length) 9147 if ((i + 1) < commandList.Length)
8704 { 9148 {
8705 if (commandList.Data[i + 1] is LSL_String) 9149 if (commandList.Data[i + 1] is LSL_String)
@@ -8712,7 +9156,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8712 } 9156 }
8713 break; 9157 break;
8714 9158
8715 case ParcelMediaCommandEnum.Desc: 9159 case (uint)ParcelMediaCommandEnum.Desc:
8716 if ((i + 1) < commandList.Length) 9160 if ((i + 1) < commandList.Length)
8717 { 9161 {
8718 if (commandList.Data[i + 1] is LSL_String) 9162 if (commandList.Data[i + 1] is LSL_String)
@@ -8725,7 +9169,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8725 } 9169 }
8726 break; 9170 break;
8727 9171
8728 case ParcelMediaCommandEnum.Size: 9172 case (uint)ParcelMediaCommandEnum.Size:
8729 if ((i + 2) < commandList.Length) 9173 if ((i + 2) < commandList.Length)
8730 { 9174 {
8731 if (commandList.Data[i + 1] is LSL_Integer) 9175 if (commandList.Data[i + 1] is LSL_Integer)
@@ -8795,7 +9239,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8795 } 9239 }
8796 } 9240 }
8797 9241
8798 if (commandToSend != null) 9242 if (commandToSend != 0)
8799 { 9243 {
8800 // the commandList contained a start/stop/... command, too 9244 // the commandList contained a start/stop/... command, too
8801 if (presence == null) 9245 if (presence == null)
@@ -8875,16 +9319,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8875 { 9319 {
8876 m_host.AddScriptLPS(1); 9320 m_host.AddScriptLPS(1);
8877 9321
8878 lock (m_host.TaskInventory) 9322 m_host.TaskInventory.LockItemsForRead(true);
9323 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
8879 { 9324 {
8880 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9325 if (inv.Value.Name == name)
8881 { 9326 {
8882 if (inv.Value.Name == name) 9327 m_host.TaskInventory.LockItemsForRead(false);
8883 { 9328 return inv.Value.Type;
8884 return inv.Value.Type;
8885 }
8886 } 9329 }
8887 } 9330 }
9331 m_host.TaskInventory.LockItemsForRead(false);
8888 9332
8889 return -1; 9333 return -1;
8890 } 9334 }
@@ -8895,15 +9339,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8895 9339
8896 if (quick_pay_buttons.Data.Length < 4) 9340 if (quick_pay_buttons.Data.Length < 4)
8897 { 9341 {
8898 LSLError("List must have at least 4 elements"); 9342 int x;
8899 return; 9343 for (x=quick_pay_buttons.Data.Length; x<= 4; x++)
9344 {
9345 quick_pay_buttons.Add(ScriptBaseClass.PAY_HIDE);
9346 }
8900 } 9347 }
8901 m_host.ParentGroup.RootPart.PayPrice[0]=price; 9348 int[] nPrice = new int[5];
8902 9349 nPrice[0]=price;
8903 m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; 9350 nPrice[1] = (LSL_Integer)quick_pay_buttons.Data[0];
8904 m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; 9351 nPrice[2] = (LSL_Integer)quick_pay_buttons.Data[1];
8905 m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; 9352 nPrice[3] = (LSL_Integer)quick_pay_buttons.Data[2];
8906 m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; 9353 nPrice[4] = (LSL_Integer)quick_pay_buttons.Data[3];
9354 m_host.ParentGroup.RootPart.PayPrice = nPrice;
8907 m_host.ParentGroup.HasGroupChanged = true; 9355 m_host.ParentGroup.HasGroupChanged = true;
8908 } 9356 }
8909 9357
@@ -8915,17 +9363,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8915 if (invItemID == UUID.Zero) 9363 if (invItemID == UUID.Zero)
8916 return new LSL_Vector(); 9364 return new LSL_Vector();
8917 9365
8918 lock (m_host.TaskInventory) 9366 m_host.TaskInventory.LockItemsForRead(true);
9367 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
8919 { 9368 {
8920 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) 9369 m_host.TaskInventory.LockItemsForRead(false);
8921 return new LSL_Vector(); 9370 return new LSL_Vector();
9371 }
8922 9372
8923 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) 9373 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
8924 { 9374 {
8925 ShoutError("No permissions to track the camera"); 9375 ShoutError("No permissions to track the camera");
8926 return new LSL_Vector(); 9376 m_host.TaskInventory.LockItemsForRead(false);
8927 } 9377 return new LSL_Vector();
8928 } 9378 }
9379 m_host.TaskInventory.LockItemsForRead(false);
8929 9380
8930 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 9381 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
8931 if (presence != null) 9382 if (presence != null)
@@ -8943,17 +9394,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8943 if (invItemID == UUID.Zero) 9394 if (invItemID == UUID.Zero)
8944 return new LSL_Rotation(); 9395 return new LSL_Rotation();
8945 9396
8946 lock (m_host.TaskInventory) 9397 m_host.TaskInventory.LockItemsForRead(true);
9398 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
8947 { 9399 {
8948 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) 9400 m_host.TaskInventory.LockItemsForRead(false);
8949 return new LSL_Rotation(); 9401 return new LSL_Rotation();
8950 9402 }
8951 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) 9403 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
8952 { 9404 {
8953 ShoutError("No permissions to track the camera"); 9405 ShoutError("No permissions to track the camera");
8954 return new LSL_Rotation(); 9406 m_host.TaskInventory.LockItemsForRead(false);
8955 } 9407 return new LSL_Rotation();
8956 } 9408 }
9409 m_host.TaskInventory.LockItemsForRead(false);
8957 9410
8958 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 9411 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
8959 if (presence != null) 9412 if (presence != null)
@@ -9103,14 +9556,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9103 if (objectID == UUID.Zero) return; 9556 if (objectID == UUID.Zero) return;
9104 9557
9105 UUID agentID; 9558 UUID agentID;
9106 lock (m_host.TaskInventory) 9559 m_host.TaskInventory.LockItemsForRead(true);
9107 { 9560 // 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 9561 agentID = m_host.TaskInventory[invItemID].PermsGranter;
9109 agentID = m_host.TaskInventory[invItemID].PermsGranter;
9110 9562
9111 if (agentID == UUID.Zero) return; 9563 if (agentID == UUID.Zero)
9112 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return; 9564 {
9565 m_host.TaskInventory.LockItemsForRead(false);
9566 return;
9113 } 9567 }
9568 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0)
9569 {
9570 m_host.TaskInventory.LockItemsForRead(false);
9571 return;
9572 }
9573 m_host.TaskInventory.LockItemsForRead(false);
9114 9574
9115 ScenePresence presence = World.GetScenePresence(agentID); 9575 ScenePresence presence = World.GetScenePresence(agentID);
9116 9576
@@ -9160,12 +9620,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9160 9620
9161 // we need the permission first, to know which avatar we want to clear the camera for 9621 // we need the permission first, to know which avatar we want to clear the camera for
9162 UUID agentID; 9622 UUID agentID;
9163 lock (m_host.TaskInventory) 9623 m_host.TaskInventory.LockItemsForRead(true);
9624 agentID = m_host.TaskInventory[invItemID].PermsGranter;
9625 if (agentID == UUID.Zero)
9164 { 9626 {
9165 agentID = m_host.TaskInventory[invItemID].PermsGranter; 9627 m_host.TaskInventory.LockItemsForRead(false);
9166 if (agentID == UUID.Zero) return; 9628 return;
9167 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return; 9629 }
9630 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0)
9631 {
9632 m_host.TaskInventory.LockItemsForRead(false);
9633 return;
9168 } 9634 }
9635 m_host.TaskInventory.LockItemsForRead(false);
9169 9636
9170 ScenePresence presence = World.GetScenePresence(agentID); 9637 ScenePresence presence = World.GetScenePresence(agentID);
9171 9638
@@ -9622,15 +10089,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9622 10089
9623 internal UUID ScriptByName(string name) 10090 internal UUID ScriptByName(string name)
9624 { 10091 {
9625 lock (m_host.TaskInventory) 10092 m_host.TaskInventory.LockItemsForRead(true);
10093
10094 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
9626 { 10095 {
9627 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 10096 if (item.Type == 10 && item.Name == name)
9628 { 10097 {
9629 if (item.Type == 10 && item.Name == name) 10098 m_host.TaskInventory.LockItemsForRead(false);
9630 return item.ItemID; 10099 return item.ItemID;
9631 } 10100 }
9632 } 10101 }
9633 10102
10103 m_host.TaskInventory.LockItemsForRead(false);
10104
9634 return UUID.Zero; 10105 return UUID.Zero;
9635 } 10106 }
9636 10107
@@ -9671,6 +10142,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9671 { 10142 {
9672 m_host.AddScriptLPS(1); 10143 m_host.AddScriptLPS(1);
9673 10144
10145 //Clone is thread safe
9674 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 10146 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
9675 10147
9676 UUID assetID = UUID.Zero; 10148 UUID assetID = UUID.Zero;
@@ -9733,6 +10205,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9733 { 10205 {
9734 m_host.AddScriptLPS(1); 10206 m_host.AddScriptLPS(1);
9735 10207
10208 //Clone is thread safe
9736 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 10209 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
9737 10210
9738 UUID assetID = UUID.Zero; 10211 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 dde664e..f2a2f32 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -769,18 +769,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
769 if (target != null) 769 if (target != null)
770 { 770 {
771 UUID animID=UUID.Zero; 771 UUID animID=UUID.Zero;
772 lock (m_host.TaskInventory) 772 m_host.TaskInventory.LockItemsForRead(true);
773 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
773 { 774 {
774 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 775 if (inv.Value.Name == animation)
775 { 776 {
776 if (inv.Value.Name == animation) 777 if (inv.Value.Type == (int)AssetType.Animation)
777 { 778 animID = inv.Value.AssetID;
778 if (inv.Value.Type == (int)AssetType.Animation) 779 continue;
779 animID = inv.Value.AssetID;
780 continue;
781 }
782 } 780 }
783 } 781 }
782 m_host.TaskInventory.LockItemsForRead(false);
784 if (animID == UUID.Zero) 783 if (animID == UUID.Zero)
785 target.Animator.AddAnimation(animation, m_host.UUID); 784 target.Animator.AddAnimation(animation, m_host.UUID);
786 else 785 else
@@ -802,18 +801,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
802 if (target != null) 801 if (target != null)
803 { 802 {
804 UUID animID=UUID.Zero; 803 UUID animID=UUID.Zero;
805 lock (m_host.TaskInventory) 804 m_host.TaskInventory.LockItemsForRead(true);
805 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
806 { 806 {
807 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 807 if (inv.Value.Name == animation)
808 { 808 {
809 if (inv.Value.Name == animation) 809 if (inv.Value.Type == (int)AssetType.Animation)
810 { 810 animID = inv.Value.AssetID;
811 if (inv.Value.Type == (int)AssetType.Animation) 811 continue;
812 animID = inv.Value.AssetID;
813 continue;
814 }
815 } 812 }
816 } 813 }
814 m_host.TaskInventory.LockItemsForRead(false);
817 815
818 if (animID == UUID.Zero) 816 if (animID == UUID.Zero)
819 target.Animator.RemoveAnimation(animation); 817 target.Animator.RemoveAnimation(animation);
@@ -1664,6 +1662,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1664 1662
1665 if (!UUID.TryParse(name, out assetID)) 1663 if (!UUID.TryParse(name, out assetID))
1666 { 1664 {
1665 m_host.TaskInventory.LockItemsForRead(true);
1667 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 1666 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
1668 { 1667 {
1669 if (item.Type == 7 && item.Name == name) 1668 if (item.Type == 7 && item.Name == name)
@@ -1671,6 +1670,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1671 assetID = item.AssetID; 1670 assetID = item.AssetID;
1672 } 1671 }
1673 } 1672 }
1673 m_host.TaskInventory.LockItemsForRead(false);
1674 } 1674 }
1675 1675
1676 if (assetID == UUID.Zero) 1676 if (assetID == UUID.Zero)
@@ -1717,6 +1717,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1717 1717
1718 if (!UUID.TryParse(name, out assetID)) 1718 if (!UUID.TryParse(name, out assetID))
1719 { 1719 {
1720 m_host.TaskInventory.LockItemsForRead(true);
1720 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 1721 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
1721 { 1722 {
1722 if (item.Type == 7 && item.Name == name) 1723 if (item.Type == 7 && item.Name == name)
@@ -1724,6 +1725,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1724 assetID = item.AssetID; 1725 assetID = item.AssetID;
1725 } 1726 }
1726 } 1727 }
1728 m_host.TaskInventory.LockItemsForRead(false);
1727 } 1729 }
1728 1730
1729 if (assetID == UUID.Zero) 1731 if (assetID == UUID.Zero)
@@ -1774,6 +1776,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1774 1776
1775 if (!UUID.TryParse(name, out assetID)) 1777 if (!UUID.TryParse(name, out assetID))
1776 { 1778 {
1779 m_host.TaskInventory.LockItemsForRead(true);
1777 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 1780 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
1778 { 1781 {
1779 if (item.Type == 7 && item.Name == name) 1782 if (item.Type == 7 && item.Name == name)
@@ -1781,6 +1784,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1781 assetID = item.AssetID; 1784 assetID = item.AssetID;
1782 } 1785 }
1783 } 1786 }
1787 m_host.TaskInventory.LockItemsForRead(false);
1784 } 1788 }
1785 1789
1786 if (assetID == UUID.Zero) 1790 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 9785b24..1ab7f10 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -81,7 +81,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
81 // Avatar Info Commands 81 // Avatar Info Commands
82 string osGetAgentIP(string agent); 82 string osGetAgentIP(string agent);
83 LSL_List osGetAgents(); 83 LSL_List osGetAgents();
84 84
85 // Teleport commands 85 // Teleport commands
86 void osTeleportAgent(string agent, string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat); 86 void osTeleportAgent(string agent, string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat);
87 void osTeleportAgent(string agent, int regionX, int regionY, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat); 87 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 {