aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/Application/OpenSim.cs4
-rw-r--r--OpenSim/Region/Application/OpenSimBase.cs91
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs3
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs724
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs10
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs4
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs4
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs16
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs127
-rw-r--r--OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs11
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs66
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs115
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs17
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs204
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs26
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs102
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs65
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs5
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs63
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs32
-rw-r--r--OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs3
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs60
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs19
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs442
-rw-r--r--OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs16
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs152
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs74
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs23
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs15
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs6
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs12
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs15
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs18
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs68
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs495
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs43
-rw-r--r--OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs7
-rw-r--r--OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Region/RestartModule.cs35
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs2
-rw-r--r--OpenSim/Region/Examples/SimpleModule/ComplexObject.cs5
-rw-r--r--OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs11
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs20
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityInventory.cs3
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs4
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEstateModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IInterregionComms.cs8
-rw-r--r--OpenSim/Region/Framework/Interfaces/IScriptModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISnmpModule.cs27
-rw-r--r--OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs13
-rw-r--r--OpenSim/Region/Framework/ModuleLoader.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs226
-rw-r--r--OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs7
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs24
-rw-r--r--OpenSim/Region/Framework/Scenes/Prioritizer.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs267
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Permissions.cs17
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs504
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs50
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs219
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs7
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs708
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs316
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs759
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs1073
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneViewer.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs25
-rw-r--r--OpenSim/Region/Framework/Scenes/UndoState.cs168
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs4
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs10
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs6
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs22
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs16
-rw-r--r--OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs4
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs11
-rw-r--r--OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs4
-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.cs1437
-rw-r--r--OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs3873
-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.cs3847
-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.cs6
-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/AsyncCommandManager.cs20
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs118
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs2256
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs53
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs8
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs32
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs46
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs3
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs71
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs3
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs11
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs21
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Helpers.cs8
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs52
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs32
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs353
116 files changed, 17500 insertions, 3320 deletions
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index 8add2af..86975c9 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -454,7 +454,7 @@ namespace OpenSim
454 if (alert != null) 454 if (alert != null)
455 presence.ControllingClient.Kick(alert); 455 presence.ControllingClient.Kick(alert);
456 else 456 else
457 presence.ControllingClient.Kick("\nThe OpenSim manager kicked you out.\n"); 457 presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n");
458 458
459 // ...and close on our side 459 // ...and close on our side
460 presence.Scene.IncomingCloseAgent(presence.UUID); 460 presence.Scene.IncomingCloseAgent(presence.UUID);
@@ -1143,7 +1143,7 @@ namespace OpenSim
1143 MainConsole.Instance.Output(String.Format("loadOffsets <X,Y,Z> = <{0},{1},{2}>",loadOffset.X,loadOffset.Y,loadOffset.Z)); 1143 MainConsole.Instance.Output(String.Format("loadOffsets <X,Y,Z> = <{0},{1},{2}>",loadOffset.X,loadOffset.Y,loadOffset.Z));
1144 } 1144 }
1145 } 1145 }
1146 m_sceneManager.LoadCurrentSceneFromXml(cmdparams[2], generateNewIDS, loadOffset); 1146 m_sceneManager.LoadCurrentSceneFromXml(cmdparams[0], generateNewIDS, loadOffset);
1147 } 1147 }
1148 else 1148 else
1149 { 1149 {
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index 00b080c..04a68ae 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -88,6 +88,10 @@ namespace OpenSim
88 88
89 protected List<IApplicationPlugin> m_plugins = new List<IApplicationPlugin>(); 89 protected List<IApplicationPlugin> m_plugins = new List<IApplicationPlugin>();
90 90
91 private List<string> m_permsModules;
92
93 private bool m_securePermissionsLoading = true;
94
91 /// <value> 95 /// <value>
92 /// The config information passed into the OpenSimulator region server. 96 /// The config information passed into the OpenSimulator region server.
93 /// </value> 97 /// </value>
@@ -185,6 +189,11 @@ namespace OpenSim
185 CreatePIDFile(pidFile); 189 CreatePIDFile(pidFile);
186 190
187 userStatsURI = startupConfig.GetString("Stats_URI", String.Empty); 191 userStatsURI = startupConfig.GetString("Stats_URI", String.Empty);
192
193 m_securePermissionsLoading = startupConfig.GetBoolean("SecurePermissionsLoading", true);
194
195 string permissionModules = startupConfig.GetString("permissionmodules", "DefaultPermissionsModule");
196 m_permsModules = new List<string>(permissionModules.Split(','));
188 } 197 }
189 198
190 // Load the simulation data service 199 // Load the simulation data service
@@ -213,6 +222,12 @@ namespace OpenSim
213 m_moduleLoader = new ModuleLoader(m_config.Source); 222 m_moduleLoader = new ModuleLoader(m_config.Source);
214 223
215 LoadPlugins(); 224 LoadPlugins();
225
226 if (m_plugins.Count == 0) // We failed to load any modules. Mono Addins glitch!
227 {
228 Environment.Exit(1);
229 }
230
216 foreach (IApplicationPlugin plugin in m_plugins) 231 foreach (IApplicationPlugin plugin in m_plugins)
217 { 232 {
218 plugin.PostInitialise(); 233 plugin.PostInitialise();
@@ -360,7 +375,41 @@ namespace OpenSim
360 } 375 }
361 else m_log.Error("[REGIONMODULES]: The new RegionModulesController is missing..."); 376 else m_log.Error("[REGIONMODULES]: The new RegionModulesController is missing...");
362 377
378 if (m_securePermissionsLoading)
379 {
380 foreach (string s in m_permsModules)
381 {
382 if (!scene.RegionModules.ContainsKey(s))
383 {
384 bool found = false;
385 foreach (IRegionModule m in modules)
386 {
387 if (m.Name == s)
388 {
389 found = true;
390 }
391 }
392 if (!found)
393 {
394 m_log.Fatal("[MODULES]: Required module " + s + " not found.");
395 Environment.Exit(0);
396 }
397 }
398 }
399 }
400
363 scene.SetModuleInterfaces(); 401 scene.SetModuleInterfaces();
402// First Step of bootreport sequence
403 if (scene.SnmpService != null)
404 {
405 scene.SnmpService.ColdStart(1,scene);
406 scene.SnmpService.LinkDown(scene);
407 }
408
409 if (scene.SnmpService != null)
410 {
411 scene.SnmpService.BootInfo("Loading prins", scene);
412 }
364 413
365 // Prims have to be loaded after module configuration since some modules may be invoked during the load 414 // Prims have to be loaded after module configuration since some modules may be invoked during the load
366 scene.LoadPrimsFromStorage(regionInfo.originRegionID); 415 scene.LoadPrimsFromStorage(regionInfo.originRegionID);
@@ -368,6 +417,10 @@ namespace OpenSim
368 // TODO : Try setting resource for region xstats here on scene 417 // TODO : Try setting resource for region xstats here on scene
369 MainServer.Instance.AddStreamHandler(new Region.Framework.Scenes.RegionStatsHandler(regionInfo)); 418 MainServer.Instance.AddStreamHandler(new Region.Framework.Scenes.RegionStatsHandler(regionInfo));
370 419
420 if (scene.SnmpService != null)
421 {
422 scene.SnmpService.BootInfo("Grid Registration in progress", scene);
423 }
371 try 424 try
372 { 425 {
373 scene.RegisterRegionWithGrid(); 426 scene.RegisterRegionWithGrid();
@@ -378,11 +431,20 @@ namespace OpenSim
378 "[STARTUP]: Registration of region with grid failed, aborting startup due to {0} {1}", 431 "[STARTUP]: Registration of region with grid failed, aborting startup due to {0} {1}",
379 e.Message, e.StackTrace); 432 e.Message, e.StackTrace);
380 433
434 if (scene.SnmpService != null)
435 {
436 scene.SnmpService.Critical("Grid registration failed. Startup aborted.", scene);
437 }
381 // Carrying on now causes a lot of confusion down the 438 // Carrying on now causes a lot of confusion down the
382 // line - we need to get the user's attention 439 // line - we need to get the user's attention
383 Environment.Exit(1); 440 Environment.Exit(1);
384 } 441 }
385 442
443 if (scene.SnmpService != null)
444 {
445 scene.SnmpService.BootInfo("Grid Registration done", scene);
446 }
447
386 scene.loadAllLandObjectsFromStorage(regionInfo.originRegionID); 448 scene.loadAllLandObjectsFromStorage(regionInfo.originRegionID);
387 scene.EventManager.TriggerParcelPrimCountUpdate(); 449 scene.EventManager.TriggerParcelPrimCountUpdate();
388 450
@@ -390,6 +452,11 @@ namespace OpenSim
390 // scripting engines. 452 // scripting engines.
391 scene.CreateScriptInstances(); 453 scene.CreateScriptInstances();
392 454
455 if (scene.SnmpService != null)
456 {
457 scene.SnmpService.BootInfo("ScriptEngine started", scene);
458 }
459
393 m_sceneManager.Add(scene); 460 m_sceneManager.Add(scene);
394 461
395 if (m_autoCreateClientStack) 462 if (m_autoCreateClientStack)
@@ -398,6 +465,10 @@ namespace OpenSim
398 clientServer.Start(); 465 clientServer.Start();
399 } 466 }
400 467
468 if (scene.SnmpService != null)
469 {
470 scene.SnmpService.BootInfo("Initializing region modules", scene);
471 }
401 if (do_post_init) 472 if (do_post_init)
402 { 473 {
403 foreach (IRegionModule module in modules) 474 foreach (IRegionModule module in modules)
@@ -409,6 +480,12 @@ namespace OpenSim
409 480
410 mscene = scene; 481 mscene = scene;
411 482
483 if (scene.SnmpService != null)
484 {
485 scene.SnmpService.BootInfo("The region is operational", scene);
486 scene.SnmpService.LinkUp(scene);
487 }
488
412 scene.StartTimer(); 489 scene.StartTimer();
413 490
414 return clientServer; 491 return clientServer;
@@ -417,6 +494,11 @@ namespace OpenSim
417 private void ShutdownRegion(Scene scene) 494 private void ShutdownRegion(Scene scene)
418 { 495 {
419 m_log.DebugFormat("[SHUTDOWN]: Shutting down region {0}", scene.RegionInfo.RegionName); 496 m_log.DebugFormat("[SHUTDOWN]: Shutting down region {0}", scene.RegionInfo.RegionName);
497 if (scene.SnmpService != null)
498 {
499 scene.SnmpService.BootInfo("The region is shutting down", scene);
500 scene.SnmpService.LinkDown(scene);
501 }
420 IRegionModulesController controller; 502 IRegionModulesController controller;
421 if (ApplicationRegistry.TryGet<IRegionModulesController>(out controller)) 503 if (ApplicationRegistry.TryGet<IRegionModulesController>(out controller))
422 { 504 {
@@ -860,7 +942,7 @@ namespace OpenSim
860 = MainConsole.Instance.CmdPrompt( 942 = MainConsole.Instance.CmdPrompt(
861 string.Format( 943 string.Format(
862 "Do you wish to join region {0} to an existing estate (yes/no)?", regInfo.RegionName), 944 "Do you wish to join region {0} to an existing estate (yes/no)?", regInfo.RegionName),
863 "yes", 945 "no",
864 new List<string>() { "yes", "no" }); 946 new List<string>() { "yes", "no" });
865 947
866 if (response == "no") 948 if (response == "no")
@@ -876,12 +958,15 @@ namespace OpenSim
876 = MainConsole.Instance.CmdPrompt( 958 = MainConsole.Instance.CmdPrompt(
877 string.Format( 959 string.Format(
878 "Name of estate to join. Existing estate names are ({0})", string.Join(", ", estateNames.ToArray())), 960 "Name of estate to join. Existing estate names are ({0})", string.Join(", ", estateNames.ToArray())),
879 estateNames[0]); 961 "None");
962
963 if (response == "None")
964 continue;
880 965
881 List<int> estateIDs = EstateDataService.GetEstates(response); 966 List<int> estateIDs = EstateDataService.GetEstates(response);
882 if (estateIDs.Count < 1) 967 if (estateIDs.Count < 1)
883 { 968 {
884 MainConsole.Instance.Output("The name you have entered matches no known estate. Please try again."); 969 MainConsole.Instance.Output("The name you have entered matches no known estate. Please try again.");
885 continue; 970 continue;
886 } 971 }
887 972
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
index e9e2dca..9dd6663 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/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/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index f53e236..6048518 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -157,6 +157,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
157 public event RequestTaskInventory OnRequestTaskInventory; 157 public event RequestTaskInventory OnRequestTaskInventory;
158 public event UpdateInventoryItem OnUpdateInventoryItem; 158 public event UpdateInventoryItem OnUpdateInventoryItem;
159 public event CopyInventoryItem OnCopyInventoryItem; 159 public event CopyInventoryItem OnCopyInventoryItem;
160 public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy;
160 public event MoveInventoryItem OnMoveInventoryItem; 161 public event MoveInventoryItem OnMoveInventoryItem;
161 public event RemoveInventoryItem OnRemoveInventoryItem; 162 public event RemoveInventoryItem OnRemoveInventoryItem;
162 public event RemoveInventoryFolder OnRemoveInventoryFolder; 163 public event RemoveInventoryFolder OnRemoveInventoryFolder;
@@ -254,7 +255,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
254 public event ClassifiedInfoRequest OnClassifiedInfoRequest; 255 public event ClassifiedInfoRequest OnClassifiedInfoRequest;
255 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate; 256 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate;
256 public event ClassifiedDelete OnClassifiedDelete; 257 public event ClassifiedDelete OnClassifiedDelete;
257 public event ClassifiedDelete OnClassifiedGodDelete; 258 public event ClassifiedGodDelete OnClassifiedGodDelete;
258 public event EventNotificationAddRequest OnEventNotificationAddRequest; 259 public event EventNotificationAddRequest OnEventNotificationAddRequest;
259 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest; 260 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest;
260 public event EventGodDelete OnEventGodDelete; 261 public event EventGodDelete OnEventGodDelete;
@@ -330,7 +331,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
330 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an 331 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an
331 /// ownerless phantom. 332 /// ownerless phantom.
332 /// 333 ///
333 /// All manipulation of this set has to occur under a lock 334 /// All manipulation of this set has to occur under an m_entityUpdates.SyncRoot lock
334 /// 335 ///
335 /// </value> 336 /// </value>
336 protected HashSet<uint> m_killRecord; 337 protected HashSet<uint> m_killRecord;
@@ -338,6 +339,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
338// protected HashSet<uint> m_attachmentsSent; 339// protected HashSet<uint> m_attachmentsSent;
339 340
340 private int m_moneyBalance; 341 private int m_moneyBalance;
342 private bool m_deliverPackets = true;
341 private int m_animationSequenceNumber = 1; 343 private int m_animationSequenceNumber = 1;
342 private bool m_SendLogoutPacketWhenClosing = true; 344 private bool m_SendLogoutPacketWhenClosing = true;
343 private AgentUpdateArgs lastarg; 345 private AgentUpdateArgs lastarg;
@@ -378,6 +380,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
378 get { return m_startpos; } 380 get { return m_startpos; }
379 set { m_startpos = value; } 381 set { m_startpos = value; }
380 } 382 }
383 public bool DeliverPackets
384 {
385 get { return m_deliverPackets; }
386 set {
387 m_deliverPackets = value;
388 m_udpClient.m_deliverPackets = value;
389 }
390 }
381 public UUID AgentId { get { return m_agentId; } } 391 public UUID AgentId { get { return m_agentId; } }
382 public UUID ActiveGroupId { get { return m_activeGroupID; } } 392 public UUID ActiveGroupId { get { return m_activeGroupID; } }
383 public string ActiveGroupName { get { return m_activeGroupName; } } 393 public string ActiveGroupName { get { return m_activeGroupName; } }
@@ -484,18 +494,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
484 494
485 #region Client Methods 495 #region Client Methods
486 496
497
487 /// <summary> 498 /// <summary>
488 /// Shut down the client view 499 /// Shut down the client view
489 /// </summary> 500 /// </summary>
490 public void Close() 501 public void Close()
491 { 502 {
503 Close(true);
504 }
505
506 /// <summary>
507 /// Shut down the client view
508 /// </summary>
509 public void Close(bool sendStop)
510 {
492 m_log.DebugFormat( 511 m_log.DebugFormat(
493 "[CLIENT]: Close has been called for {0} attached to scene {1}", 512 "[CLIENT]: Close has been called for {0} attached to scene {1}",
494 Name, m_scene.RegionInfo.RegionName); 513 Name, m_scene.RegionInfo.RegionName);
495 514
496 // Send the STOP packet 515 if (sendStop)
497 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator); 516 {
498 OutPacket(disable, ThrottleOutPacketType.Unknown); 517 // Send the STOP packet
518 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
519 OutPacket(disable, ThrottleOutPacketType.Unknown);
520 }
499 521
500 IsActive = false; 522 IsActive = false;
501 523
@@ -776,7 +798,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
776 reply.ChatData.OwnerID = fromAgentID; 798 reply.ChatData.OwnerID = fromAgentID;
777 reply.ChatData.SourceID = fromAgentID; 799 reply.ChatData.SourceID = fromAgentID;
778 800
779 OutPacket(reply, ThrottleOutPacketType.Task); 801 OutPacket(reply, ThrottleOutPacketType.Unknown);
780 } 802 }
781 803
782 /// <summary> 804 /// <summary>
@@ -1062,6 +1084,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1062 public virtual void SendLayerData(float[] map) 1084 public virtual void SendLayerData(float[] map)
1063 { 1085 {
1064 Util.FireAndForget(DoSendLayerData, map); 1086 Util.FireAndForget(DoSendLayerData, map);
1087
1088 // Send it sync, and async. It's not that much data
1089 // and it improves user experience just so much!
1090 DoSendLayerData(map);
1065 } 1091 }
1066 1092
1067 /// <summary> 1093 /// <summary>
@@ -1074,16 +1100,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1074 1100
1075 try 1101 try
1076 { 1102 {
1077 //for (int y = 0; y < 16; y++) 1103 for (int y = 0; y < 16; y++)
1078 //{ 1104 {
1079 // for (int x = 0; x < 16; x++) 1105 for (int x = 0; x < 16; x+=4)
1080 // { 1106 {
1081 // SendLayerData(x, y, map); 1107 SendLayerPacket(x, y, map);
1082 // } 1108 }
1083 //} 1109 }
1084
1085 // Send LayerData in a spiral pattern. Fun!
1086 SendLayerTopRight(map, 0, 0, 15, 15);
1087 } 1110 }
1088 catch (Exception e) 1111 catch (Exception e)
1089 { 1112 {
@@ -1091,51 +1114,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1091 } 1114 }
1092 } 1115 }
1093 1116
1094 private void SendLayerTopRight(float[] map, int x1, int y1, int x2, int y2)
1095 {
1096 // Row
1097 for (int i = x1; i <= x2; i++)
1098 SendLayerData(i, y1, map);
1099
1100 // Column
1101 for (int j = y1 + 1; j <= y2; j++)
1102 SendLayerData(x2, j, map);
1103
1104 if (x2 - x1 > 0)
1105 SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2);
1106 }
1107
1108 void SendLayerBottomLeft(float[] map, int x1, int y1, int x2, int y2)
1109 {
1110 // Row in reverse
1111 for (int i = x2; i >= x1; i--)
1112 SendLayerData(i, y2, map);
1113
1114 // Column in reverse
1115 for (int j = y2 - 1; j >= y1; j--)
1116 SendLayerData(x1, j, map);
1117
1118 if (x2 - x1 > 0)
1119 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
1120 }
1121
1122 /// <summary> 1117 /// <summary>
1123 /// Sends a set of four patches (x, x+1, ..., x+3) to the client 1118 /// Sends a set of four patches (x, x+1, ..., x+3) to the client
1124 /// </summary> 1119 /// </summary>
1125 /// <param name="map">heightmap</param> 1120 /// <param name="map">heightmap</param>
1126 /// <param name="px">X coordinate for patches 0..12</param> 1121 /// <param name="px">X coordinate for patches 0..12</param>
1127 /// <param name="py">Y coordinate for patches 0..15</param> 1122 /// <param name="py">Y coordinate for patches 0..15</param>
1128 // private void SendLayerPacket(float[] map, int y, int x) 1123 private void SendLayerPacket(int x, int y, float[] map)
1129 // { 1124 {
1130 // int[] patches = new int[4]; 1125 int[] patches = new int[4];
1131 // patches[0] = x + 0 + y * 16; 1126 patches[0] = x + 0 + y * 16;
1132 // patches[1] = x + 1 + y * 16; 1127 patches[1] = x + 1 + y * 16;
1133 // patches[2] = x + 2 + y * 16; 1128 patches[2] = x + 2 + y * 16;
1134 // patches[3] = x + 3 + y * 16; 1129 patches[3] = x + 3 + y * 16;
1135 1130
1136 // Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); 1131 float[] heightmap = (map.Length == 65536) ?
1137 // OutPacket(layerpack, ThrottleOutPacketType.Land); 1132 map :
1138 // } 1133 LLHeightFieldMoronize(map);
1134
1135 try
1136 {
1137 Packet layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1138 OutPacket(layerpack, ThrottleOutPacketType.Land);
1139 }
1140 catch
1141 {
1142 for (int px = x ; px < x + 4 ; px++)
1143 SendLayerData(px, y, map);
1144 }
1145 }
1139 1146
1140 /// <summary> 1147 /// <summary>
1141 /// Sends a specified patch to a client 1148 /// Sends a specified patch to a client
@@ -1155,7 +1162,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1155 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); 1162 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1156 layerpack.Header.Reliable = true; 1163 layerpack.Header.Reliable = true;
1157 1164
1158 OutPacket(layerpack, ThrottleOutPacketType.Land); 1165 OutPacket(layerpack, ThrottleOutPacketType.Task);
1159 } 1166 }
1160 catch (Exception e) 1167 catch (Exception e)
1161 { 1168 {
@@ -1516,38 +1523,49 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1516 OutPacket(pc, ThrottleOutPacketType.Unknown); 1523 OutPacket(pc, ThrottleOutPacketType.Unknown);
1517 } 1524 }
1518 1525
1519 public void SendKillObject(ulong regionHandle, uint localID) 1526 public void SendKillObject(ulong regionHandle, List<uint> localIDs)
1520 { 1527 {
1521// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle); 1528// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle);
1522 1529
1523 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject); 1530 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject);
1524 // TODO: don't create new blocks if recycling an old packet 1531 // TODO: don't create new blocks if recycling an old packet
1525 kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1]; 1532 kill.ObjectData = new KillObjectPacket.ObjectDataBlock[localIDs.Count];
1526 kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock(); 1533 for (int i = 0 ; i < localIDs.Count ; i++ )
1527 kill.ObjectData[0].ID = localID; 1534 {
1535 kill.ObjectData[i] = new KillObjectPacket.ObjectDataBlock();
1536 kill.ObjectData[i].ID = localIDs[i];
1537 }
1528 kill.Header.Reliable = true; 1538 kill.Header.Reliable = true;
1529 kill.Header.Zerocoded = true; 1539 kill.Header.Zerocoded = true;
1530 1540
1531 if (m_scene.GetScenePresence(localID) == null) 1541 lock (m_killRecord)
1532 { 1542 {
1533 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race 1543 if (localIDs.Count == 1)
1534 // condition where a kill can be processed before an out-of-date update for the same object.
1535 lock (m_killRecord)
1536 { 1544 {
1537 m_killRecord.Add(localID); 1545 if (m_scene.GetScenePresence(localIDs[0]) != null)
1538 1546 {
1539 // The throttle queue used here must match that being used for updates. Otherwise, there is a 1547 OutPacket(kill, ThrottleOutPacketType.State);
1540 // chance that a kill packet put on a separate queue will be sent to the client before an existing 1548 return;
1541 // update packet on another queue. Receiving updates after kills results in unowned and undeletable 1549 }
1542 // scene objects in a viewer until that viewer is relogged in. 1550 m_killRecord.Add(localIDs[0]);
1543 OutPacket(kill, ThrottleOutPacketType.Task); 1551 }
1552 else
1553 {
1554 lock (m_entityUpdates.SyncRoot)
1555 {
1556 foreach (uint localID in localIDs)
1557 m_killRecord.Add(localID);
1558 }
1544 } 1559 }
1545 } 1560 }
1546 else 1561
1547 { 1562 // The throttle queue used here must match that being used for
1548 // OutPacket(kill, ThrottleOutPacketType.State); 1563 // updates. Otherwise, there is a chance that a kill packet put
1549 OutPacket(kill, ThrottleOutPacketType.Task); 1564 // on a separate queue will be sent to the client before an
1550 } 1565 // existing update packet on another queue. Receiving updates
1566 // after kills results in unowned and undeletable
1567 // scene objects in a viewer until that viewer is relogged in.
1568 OutPacket(kill, ThrottleOutPacketType.Task);
1551 } 1569 }
1552 1570
1553 /// <summary> 1571 /// <summary>
@@ -2272,6 +2290,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2272 OutPacket(sound, ThrottleOutPacketType.Task); 2290 OutPacket(sound, ThrottleOutPacketType.Task);
2273 } 2291 }
2274 2292
2293 public void SendTransferAbort(TransferRequestPacket transferRequest)
2294 {
2295 TransferAbortPacket abort = (TransferAbortPacket)PacketPool.Instance.GetPacket(PacketType.TransferAbort);
2296 abort.TransferInfo.TransferID = transferRequest.TransferInfo.TransferID;
2297 abort.TransferInfo.ChannelType = transferRequest.TransferInfo.ChannelType;
2298 m_log.Debug("[Assets] Aborting transfer; asset request failed");
2299 OutPacket(abort, ThrottleOutPacketType.Task);
2300 }
2301
2275 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain) 2302 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain)
2276 { 2303 {
2277 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger); 2304 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger);
@@ -3574,7 +3601,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3574 /// </summary> 3601 /// </summary>
3575 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) 3602 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
3576 { 3603 {
3577 //double priority = m_prioritizer.GetUpdatePriority(this, entity); 3604 if (entity is SceneObjectPart)
3605 {
3606 SceneObjectPart e = (SceneObjectPart)entity;
3607 SceneObjectGroup g = e.ParentGroup;
3608 if (g.RootPart.Shape.State > 30) // HUD
3609 if (g.OwnerID != AgentId)
3610 return; // Don't send updates for other people's HUDs
3611 }
3612
3578 uint priority = m_prioritizer.GetUpdatePriority(this, entity); 3613 uint priority = m_prioritizer.GetUpdatePriority(this, entity);
3579 3614
3580 lock (m_entityUpdates.SyncRoot) 3615 lock (m_entityUpdates.SyncRoot)
@@ -3641,211 +3676,230 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3641 3676
3642 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race 3677 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race
3643 // condition where a kill can be processed before an out-of-date update for the same object. 3678 // condition where a kill can be processed before an out-of-date update for the same object.
3644 lock (m_killRecord) 3679 float avgTimeDilation = 1.0f;
3680 IEntityUpdate iupdate;
3681 Int32 timeinqueue; // this is just debugging code & can be dropped later
3682
3683 while (updatesThisCall < maxUpdates)
3645 { 3684 {
3646 float avgTimeDilation = 1.0f; 3685 lock (m_entityUpdates.SyncRoot)
3647 IEntityUpdate iupdate; 3686 if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue))
3648 Int32 timeinqueue; // this is just debugging code & can be dropped later 3687 break;
3649
3650 while (updatesThisCall < maxUpdates)
3651 {
3652 lock (m_entityUpdates.SyncRoot)
3653 if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue))
3654 break;
3655 3688
3656 EntityUpdate update = (EntityUpdate)iupdate; 3689 EntityUpdate update = (EntityUpdate)iupdate;
3657 3690
3658 avgTimeDilation += update.TimeDilation; 3691 avgTimeDilation += update.TimeDilation;
3659 avgTimeDilation *= 0.5f; 3692 avgTimeDilation *= 0.5f;
3660 3693
3661 if (update.Entity is SceneObjectPart) 3694 if (update.Entity is SceneObjectPart)
3695 {
3696 SceneObjectPart part = (SceneObjectPart)update.Entity;
3697
3698 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3699 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3700 // safety measure.
3701 //
3702 // If a Linden Lab 1.23.5 client (and possibly later and earlier) receives an object update
3703 // after a kill, it will keep displaying the deleted object until relog. OpenSim currently performs
3704 // updates and kills on different threads with different scheduling strategies, hence this protection.
3705 //
3706 // This doesn't appear to apply to child prims - a client will happily ignore these updates
3707 // after the root prim has been deleted.
3708 lock (m_killRecord)
3662 { 3709 {
3663 SceneObjectPart part = (SceneObjectPart)update.Entity;
3664
3665 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3666 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3667 // safety measure.
3668 //
3669 // If a Linden Lab 1.23.5 client (and possibly later and earlier) receives an object update
3670 // after a kill, it will keep displaying the deleted object until relog. OpenSim currently performs
3671 // updates and kills on different threads with different scheduling strategies, hence this protection.
3672 //
3673 // This doesn't appear to apply to child prims - a client will happily ignore these updates
3674 // after the root prim has been deleted.
3675 if (m_killRecord.Contains(part.LocalId)) 3710 if (m_killRecord.Contains(part.LocalId))
3676 {
3677 // m_log.WarnFormat(
3678 // "[CLIENT]: Preventing update for prim with local id {0} after client for user {1} told it was deleted",
3679 // part.LocalId, Name);
3680 continue; 3711 continue;
3681 } 3712 if (m_killRecord.Contains(part.ParentGroup.RootPart.LocalId))
3682 3713 continue;
3683 if (part.ParentGroup.IsAttachment && m_disableFacelights) 3714 }
3715
3716 if (part.ParentGroup.IsDeleted)
3717 continue;
3718
3719 if (part.ParentGroup.IsAttachment)
3720 { // Someone else's HUD, why are we getting these?
3721 if (part.ParentGroup.OwnerID != AgentId &&
3722 part.ParentGroup.RootPart.Shape.State >= 30)
3723 continue;
3724 ScenePresence sp;
3725 // Owner is not in the sim, don't update it to
3726 // anyone
3727 if (!m_scene.TryGetScenePresence(part.OwnerID, out sp))
3728 continue;
3729
3730 List<SceneObjectGroup> atts = sp.Attachments;
3731 bool found = false;
3732 foreach (SceneObjectGroup att in atts)
3684 { 3733 {
3685 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand && 3734 if (att == part.ParentGroup)
3686 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
3687 { 3735 {
3688 part.Shape.LightEntry = false; 3736 found = true;
3737 break;
3689 } 3738 }
3690 } 3739 }
3740
3741 // It's an attachment of a valid avatar, but
3742 // doesn't seem to be attached, skip
3743 if (!found)
3744 continue;
3691 } 3745 }
3692 3746 if (part.ParentGroup.IsAttachment && m_disableFacelights)
3693 ++updatesThisCall;
3694
3695 #region UpdateFlags to packet type conversion
3696
3697 PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags;
3698
3699 bool canUseCompressed = true;
3700 bool canUseImproved = true;
3701
3702 // Compressed object updates only make sense for LL primitives
3703 if (!(update.Entity is SceneObjectPart))
3704 {
3705 canUseCompressed = false;
3706 }
3707
3708 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
3709 {
3710 canUseCompressed = false;
3711 canUseImproved = false;
3712 }
3713 else
3714 { 3747 {
3715 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) || 3748 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand &&
3716 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) || 3749 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
3717 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3718 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3719 { 3750 {
3720 canUseCompressed = false; 3751 part.Shape.LightEntry = false;
3721 }
3722
3723 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
3724 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3725 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
3726 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
3727 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
3728 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
3729 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
3730 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
3731 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
3732 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
3733 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
3734 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
3735 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
3736 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3737 {
3738 canUseImproved = false;
3739 } 3752 }
3740 } 3753 }
3741 3754 }
3742 #endregion UpdateFlags to packet type conversion 3755
3743 3756 ++updatesThisCall;
3744 #region Block Construction 3757
3745 3758 #region UpdateFlags to packet type conversion
3746 // TODO: Remove this once we can build compressed updates 3759
3760 PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags;
3761
3762 bool canUseCompressed = true;
3763 bool canUseImproved = true;
3764
3765 // Compressed object updates only make sense for LL primitives
3766 if (!(update.Entity is SceneObjectPart))
3767 {
3747 canUseCompressed = false; 3768 canUseCompressed = false;
3748 3769 }
3749 if (!canUseImproved && !canUseCompressed) 3770
3750 { 3771 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
3751 if (update.Entity is ScenePresence) 3772 {
3752 { 3773 canUseCompressed = false;
3753 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity)); 3774 canUseImproved = false;
3754 objectUpdates.Value.Add(update); 3775 }
3755 } 3776 else
3756 else 3777 {
3757 { 3778 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
3758 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId)); 3779 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
3759 objectUpdates.Value.Add(update); 3780 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3760 } 3781 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3761 }
3762 else if (!canUseImproved)
3763 { 3782 {
3764 compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags)); 3783 canUseCompressed = false;
3765 compressedUpdates.Value.Add(update);
3766 } 3784 }
3767 else 3785
3786 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
3787 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3788 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
3789 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
3790 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
3791 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
3792 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
3793 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
3794 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
3795 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
3796 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
3797 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
3798 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
3799 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3768 { 3800 {
3769 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId) 3801 canUseImproved = false;
3770 {
3771 // Self updates go into a special list
3772 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3773 terseAgentUpdates.Value.Add(update);
3774 }
3775 else
3776 {
3777 // Everything else goes here
3778 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3779 terseUpdates.Value.Add(update);
3780 }
3781 } 3802 }
3782
3783 #endregion Block Construction
3784 } 3803 }
3785
3786
3787 #region Packet Sending
3788 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f);
3789 3804
3790 if (terseAgentUpdateBlocks.IsValueCreated) 3805 #endregion UpdateFlags to packet type conversion
3791 {
3792 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
3793 3806
3794 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); 3807 #region Block Construction
3795 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3796 packet.RegionData.TimeDilation = timeDilation;
3797 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3798 3808
3799 for (int i = 0; i < blocks.Count; i++) 3809 // TODO: Remove this once we can build compressed updates
3800 packet.ObjectData[i] = blocks[i]; 3810 canUseCompressed = false;
3801 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
3802 OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseAgentUpdates.Value, oPacket); });
3803 }
3804 3811
3805 if (objectUpdateBlocks.IsValueCreated) 3812 if (!canUseImproved && !canUseCompressed)
3806 { 3813 {
3807 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value; 3814 if (update.Entity is ScenePresence)
3808 3815 {
3809 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); 3816 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
3810 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 3817 }
3811 packet.RegionData.TimeDilation = timeDilation; 3818 else
3812 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 3819 {
3813 3820 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3814 for (int i = 0; i < blocks.Count; i++) 3821 }
3815 packet.ObjectData[i] = blocks[i];
3816 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
3817 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(objectUpdates.Value, oPacket); });
3818 } 3822 }
3819 3823 else if (!canUseImproved)
3820 if (compressedUpdateBlocks.IsValueCreated)
3821 { 3824 {
3822 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value; 3825 compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
3823
3824 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
3825 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3826 packet.RegionData.TimeDilation = timeDilation;
3827 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
3828
3829 for (int i = 0; i < blocks.Count; i++)
3830 packet.ObjectData[i] = blocks[i];
3831 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
3832 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates.Value, oPacket); });
3833 } 3826 }
3834 3827 else
3835 if (terseUpdateBlocks.IsValueCreated)
3836 { 3828 {
3837 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value; 3829 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId)
3838 3830 // Self updates go into a special list
3839 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); 3831 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3840 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 3832 else
3841 packet.RegionData.TimeDilation = timeDilation; 3833 // Everything else goes here
3842 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 3834 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3843
3844 for (int i = 0; i < blocks.Count; i++)
3845 packet.ObjectData[i] = blocks[i];
3846 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
3847 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); });
3848 } 3835 }
3836
3837 #endregion Block Construction
3838 }
3839
3840 #region Packet Sending
3841
3842 const float TIME_DILATION = 1.0f;
3843 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f);
3844
3845 if (terseAgentUpdateBlocks.IsValueCreated)
3846 {
3847 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
3848
3849 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3850 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3851 packet.RegionData.TimeDilation = timeDilation;
3852 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3853
3854 for (int i = 0; i < blocks.Count; i++)
3855 packet.ObjectData[i] = blocks[i];
3856
3857 OutPacket(packet, ThrottleOutPacketType.Unknown, true);
3858 }
3859
3860 if (objectUpdateBlocks.IsValueCreated)
3861 {
3862 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
3863
3864 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3865 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3866 packet.RegionData.TimeDilation = timeDilation;
3867 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3868
3869 for (int i = 0; i < blocks.Count; i++)
3870 packet.ObjectData[i] = blocks[i];
3871
3872 OutPacket(packet, ThrottleOutPacketType.Task, true);
3873 }
3874
3875 if (compressedUpdateBlocks.IsValueCreated)
3876 {
3877 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
3878
3879 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
3880 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3881 packet.RegionData.TimeDilation = timeDilation;
3882 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
3883
3884 for (int i = 0; i < blocks.Count; i++)
3885 packet.ObjectData[i] = blocks[i];
3886
3887 OutPacket(packet, ThrottleOutPacketType.Task, true);
3888 }
3889
3890 if (terseUpdateBlocks.IsValueCreated)
3891 {
3892 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
3893
3894 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3895 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3896 packet.RegionData.TimeDilation = timeDilation;
3897 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3898
3899 for (int i = 0; i < blocks.Count; i++)
3900 packet.ObjectData[i] = blocks[i];
3901
3902 OutPacket(packet, ThrottleOutPacketType.Task, true);
3849 } 3903 }
3850 3904
3851 #endregion Packet Sending 3905 #endregion Packet Sending
@@ -4329,37 +4383,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4329 if (bl[i].BannedUserID == UUID.Zero) 4383 if (bl[i].BannedUserID == UUID.Zero)
4330 continue; 4384 continue;
4331 BannedUsers.Add(bl[i].BannedUserID); 4385 BannedUsers.Add(bl[i].BannedUserID);
4332 }
4333 4386
4334 EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); 4387 if (BannedUsers.Count >= 50 || (i == (bl.Length - 1) && BannedUsers.Count > 0))
4335 packet.AgentData.TransactionID = UUID.Random(); 4388 {
4336 packet.AgentData.AgentID = AgentId; 4389 EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket();
4337 packet.AgentData.SessionID = SessionId; 4390 packet.AgentData.TransactionID = UUID.Random();
4338 packet.MethodData.Invoice = invoice; 4391 packet.AgentData.AgentID = AgentId;
4339 packet.MethodData.Method = Utils.StringToBytes("setaccess"); 4392 packet.AgentData.SessionID = SessionId;
4393 packet.MethodData.Invoice = invoice;
4394 packet.MethodData.Method = Utils.StringToBytes("setaccess");
4340 4395
4341 EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + BannedUsers.Count]; 4396 EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + BannedUsers.Count];
4342 4397
4343 for (int i = 0; i < (6 + BannedUsers.Count); i++) 4398 int j;
4344 { 4399 for (j = 0; j < (6 + BannedUsers.Count); j++)
4345 returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); 4400 {
4346 } 4401 returnblock[j] = new EstateOwnerMessagePacket.ParamListBlock();
4347 int j = 0; 4402 }
4403 j = 0;
4348 4404
4349 returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; 4405 returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++;
4350 returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++; 4406 returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++;
4351 returnblock[j].Parameter = Utils.StringToBytes("0"); j++; 4407 returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
4352 returnblock[j].Parameter = Utils.StringToBytes("0"); j++; 4408 returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
4353 returnblock[j].Parameter = Utils.StringToBytes(BannedUsers.Count.ToString()); j++; 4409 returnblock[j].Parameter = Utils.StringToBytes(BannedUsers.Count.ToString()); j++;
4354 returnblock[j].Parameter = Utils.StringToBytes("0"); j++; 4410 returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
4355 4411
4356 foreach (UUID banned in BannedUsers) 4412 foreach (UUID banned in BannedUsers)
4357 { 4413 {
4358 returnblock[j].Parameter = banned.GetBytes(); j++; 4414 returnblock[j].Parameter = banned.GetBytes(); j++;
4415 }
4416 packet.ParamList = returnblock;
4417 packet.Header.Reliable = true;
4418 OutPacket(packet, ThrottleOutPacketType.Task);
4419
4420 BannedUsers.Clear();
4421 }
4359 } 4422 }
4360 packet.ParamList = returnblock; 4423
4361 packet.Header.Reliable = false;
4362 OutPacket(packet, ThrottleOutPacketType.Task);
4363 } 4424 }
4364 4425
4365 public void SendRegionInfoToEstateMenu(RegionInfoForEstateMenuArgs args) 4426 public void SendRegionInfoToEstateMenu(RegionInfoForEstateMenuArgs args)
@@ -4657,14 +4718,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4657 4718
4658 if (notifyCount > 0) 4719 if (notifyCount > 0)
4659 { 4720 {
4660 if (notifyCount > 32) 4721// if (notifyCount > 32)
4661 { 4722// {
4662 m_log.InfoFormat( 4723// m_log.InfoFormat(
4663 "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}" 4724// "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}"
4664 + " - a developer might want to investigate whether this is a hard limit", 32); 4725// + " - a developer might want to investigate whether this is a hard limit", 32);
4665 4726//
4666 notifyCount = 32; 4727// notifyCount = 32;
4667 } 4728// }
4668 4729
4669 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock 4730 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock
4670 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount]; 4731 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount];
@@ -5180,6 +5241,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5180 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false); 5241 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false);
5181 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false); 5242 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false);
5182 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode); 5243 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode);
5244 AddLocalPacketHandler(PacketType.CreateNewOutfitAttachments, HandleCreateNewOutfitAttachments);
5183 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false); 5245 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false);
5184 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents); 5246 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents);
5185 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery); 5247 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery);
@@ -5279,6 +5341,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5279 (x.CameraLeftAxis != lastarg.CameraLeftAxis) || 5341 (x.CameraLeftAxis != lastarg.CameraLeftAxis) ||
5280 (x.CameraUpAxis != lastarg.CameraUpAxis) || 5342 (x.CameraUpAxis != lastarg.CameraUpAxis) ||
5281 (x.ControlFlags != lastarg.ControlFlags) || 5343 (x.ControlFlags != lastarg.ControlFlags) ||
5344 (x.ControlFlags != 0) ||
5282 (x.Far != lastarg.Far) || 5345 (x.Far != lastarg.Far) ||
5283 (x.Flags != lastarg.Flags) || 5346 (x.Flags != lastarg.Flags) ||
5284 (x.State != lastarg.State) || 5347 (x.State != lastarg.State) ||
@@ -5652,7 +5715,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5652 args.Channel = ch; 5715 args.Channel = ch;
5653 args.From = String.Empty; 5716 args.From = String.Empty;
5654 args.Message = Utils.BytesToString(msg); 5717 args.Message = Utils.BytesToString(msg);
5655 args.Type = ChatTypeEnum.Shout; 5718 args.Type = ChatTypeEnum.Region; //Behaviour in SL is that the response can be heard from any distance
5656 args.Position = new Vector3(); 5719 args.Position = new Vector3();
5657 args.Scene = Scene; 5720 args.Scene = Scene;
5658 args.Sender = this; 5721 args.Sender = this;
@@ -9658,7 +9721,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9658 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID, 9721 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID,
9659 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName), 9722 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName),
9660 UpdateMuteListEntry.MuteData.MuteType, 9723 UpdateMuteListEntry.MuteData.MuteType,
9661 UpdateMuteListEntry.AgentData.AgentID); 9724 UpdateMuteListEntry.MuteData.MuteFlags);
9662 return true; 9725 return true;
9663 } 9726 }
9664 return false; 9727 return false;
@@ -9673,8 +9736,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9673 { 9736 {
9674 handlerRemoveMuteListEntry(this, 9737 handlerRemoveMuteListEntry(this,
9675 RemoveMuteListEntry.MuteData.MuteID, 9738 RemoveMuteListEntry.MuteData.MuteID,
9676 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName), 9739 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName));
9677 RemoveMuteListEntry.AgentData.AgentID);
9678 return true; 9740 return true;
9679 } 9741 }
9680 return false; 9742 return false;
@@ -9722,6 +9784,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9722 { 9784 {
9723 return true; 9785 return true;
9724 } 9786 }
9787
9788 private bool HandleCreateNewOutfitAttachments(IClientAPI sender, Packet Pack)
9789 {
9790 CreateNewOutfitAttachmentsPacket packet = (CreateNewOutfitAttachmentsPacket)Pack;
9791
9792 #region Packet Session and User Check
9793 if (m_checkPackets)
9794 {
9795 if (packet.AgentData.SessionID != SessionId ||
9796 packet.AgentData.AgentID != AgentId)
9797 return true;
9798 }
9799 #endregion
9800 MoveItemsAndLeaveCopy handlerMoveItemsAndLeaveCopy = null;
9801 List<InventoryItemBase> items = new List<InventoryItemBase>();
9802 foreach (CreateNewOutfitAttachmentsPacket.ObjectDataBlock n in packet.ObjectData)
9803 {
9804 InventoryItemBase b = new InventoryItemBase();
9805 b.ID = n.OldItemID;
9806 b.Folder = n.OldFolderID;
9807 items.Add(b);
9808 }
9809
9810 handlerMoveItemsAndLeaveCopy = OnMoveItemsAndLeaveCopy;
9811 if (handlerMoveItemsAndLeaveCopy != null)
9812 {
9813 handlerMoveItemsAndLeaveCopy(this, items, packet.HeaderData.NewFolderID);
9814 }
9815
9816 return true;
9817 }
9725 9818
9726 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack) 9819 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack)
9727 { 9820 {
@@ -10148,6 +10241,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10148 groupProfileReply.GroupData.MaturePublish = d.MaturePublish; 10241 groupProfileReply.GroupData.MaturePublish = d.MaturePublish;
10149 groupProfileReply.GroupData.OwnerRole = d.OwnerRole; 10242 groupProfileReply.GroupData.OwnerRole = d.OwnerRole;
10150 10243
10244 Scene scene = (Scene)m_scene;
10245 if (scene.Permissions.IsGod(sender.AgentId) && (!sender.IsGroupMember(groupProfileRequest.GroupData.GroupID)))
10246 {
10247 ScenePresence p;
10248 if (scene.TryGetScenePresence(sender.AgentId, out p))
10249 {
10250 if (p.GodLevel >= 200)
10251 {
10252 groupProfileReply.GroupData.OpenEnrollment = true;
10253 groupProfileReply.GroupData.MembershipFee = 0;
10254 }
10255 }
10256 }
10257
10151 OutPacket(groupProfileReply, ThrottleOutPacketType.Task); 10258 OutPacket(groupProfileReply, ThrottleOutPacketType.Task);
10152 } 10259 }
10153 return true; 10260 return true;
@@ -10720,11 +10827,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10720 10827
10721 StartLure handlerStartLure = OnStartLure; 10828 StartLure handlerStartLure = OnStartLure;
10722 if (handlerStartLure != null) 10829 if (handlerStartLure != null)
10723 handlerStartLure(startLureRequest.Info.LureType, 10830 {
10724 Utils.BytesToString( 10831 for (int i = 0 ; i < startLureRequest.TargetData.Length ; i++)
10725 startLureRequest.Info.Message), 10832 {
10726 startLureRequest.TargetData[0].TargetID, 10833 handlerStartLure(startLureRequest.Info.LureType,
10727 this); 10834 Utils.BytesToString(
10835 startLureRequest.Info.Message),
10836 startLureRequest.TargetData[i].TargetID,
10837 this);
10838 }
10839 }
10728 return true; 10840 return true;
10729 } 10841 }
10730 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack) 10842 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack)
@@ -10838,10 +10950,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10838 } 10950 }
10839 #endregion 10951 #endregion
10840 10952
10841 ClassifiedDelete handlerClassifiedGodDelete = OnClassifiedGodDelete; 10953 ClassifiedGodDelete handlerClassifiedGodDelete = OnClassifiedGodDelete;
10842 if (handlerClassifiedGodDelete != null) 10954 if (handlerClassifiedGodDelete != null)
10843 handlerClassifiedGodDelete( 10955 handlerClassifiedGodDelete(
10844 classifiedGodDelete.Data.ClassifiedID, 10956 classifiedGodDelete.Data.ClassifiedID,
10957 classifiedGodDelete.Data.QueryID,
10845 this); 10958 this);
10846 return true; 10959 return true;
10847 } 10960 }
@@ -11219,7 +11332,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11219 { 11332 {
11220 // It's a ghost! tell the client to delete it from view. 11333 // It's a ghost! tell the client to delete it from view.
11221 simClient.SendKillObject(Scene.RegionInfo.RegionHandle, 11334 simClient.SendKillObject(Scene.RegionInfo.RegionHandle,
11222 localId); 11335 new List<uint>() { localId });
11223 } 11336 }
11224 else 11337 else
11225 { 11338 {
@@ -11608,22 +11721,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11608 /// <param name="Pack">OpenMetaverse.packet</param> 11721 /// <param name="Pack">OpenMetaverse.packet</param>
11609 public void ProcessInPacket(Packet packet) 11722 public void ProcessInPacket(Packet packet)
11610 { 11723 {
11611 if (m_debugPacketLevel > 0) 11724 if (m_debugPacketLevel >= 255)
11612 { 11725 m_log.DebugFormat("[CLIENT]: Packet IN {0}", packet.Type);
11613 bool outputPacket = true;
11614
11615 if (m_debugPacketLevel <= 255 && packet.Type == PacketType.AgentUpdate)
11616 outputPacket = false;
11617
11618 if (m_debugPacketLevel <= 200 && packet.Type == PacketType.RequestImage)
11619 outputPacket = false;
11620
11621 if (m_debugPacketLevel <= 100 && (packet.Type == PacketType.ViewerEffect || packet.Type == PacketType.AgentAnimation))
11622 outputPacket = false;
11623
11624 if (outputPacket)
11625 m_log.DebugFormat("[CLIENT]: Packet IN {0}", packet.Type);
11626 }
11627 11726
11628 if (!ProcessPacketMethod(packet)) 11727 if (!ProcessPacketMethod(packet))
11629 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type); 11728 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type);
@@ -11865,7 +11964,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11865 11964
11866// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID); 11965// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID);
11867 11966
11967
11968 //Note, the bool returned from the below function is useless since it is always false.
11868 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived); 11969 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived);
11970
11869 } 11971 }
11870 11972
11871 /// <summary> 11973 /// <summary>
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
index ca5501d..95a8e23 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
@@ -158,6 +158,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
158 158
159 private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC 159 private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC
160 private int m_maxRTO = 60000; 160 private int m_maxRTO = 60000;
161 public bool m_deliverPackets = true;
161 162
162 /// <summary> 163 /// <summary>
163 /// Default constructor 164 /// Default constructor
@@ -430,6 +431,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
430 if (category >= 0 && category < m_packetOutboxes.Length) 431 if (category >= 0 && category < m_packetOutboxes.Length)
431 { 432 {
432 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category]; 433 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category];
434
435 if (m_deliverPackets == false)
436 {
437 queue.Enqueue(packet);
438 return true;
439 }
440
433 TokenBucket bucket = m_throttleCategories[category]; 441 TokenBucket bucket = m_throttleCategories[category];
434 442
435 // Don't send this packet if there is already a packet waiting in the queue 443 // Don't send this packet if there is already a packet waiting in the queue
@@ -479,6 +487,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
479 /// <returns>True if any packets were sent, otherwise false</returns> 487 /// <returns>True if any packets were sent, otherwise false</returns>
480 public bool DequeueOutgoing() 488 public bool DequeueOutgoing()
481 { 489 {
490 if (m_deliverPackets == false) return false;
491
482 OutgoingPacket packet; 492 OutgoingPacket packet;
483 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue; 493 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue;
484 TokenBucket bucket; 494 TokenBucket bucket;
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index aff90c5..ab6674d 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -960,7 +960,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
960 if (m_scene.TryGetClient(udpClient.AgentID, out client)) 960 if (m_scene.TryGetClient(udpClient.AgentID, out client))
961 { 961 {
962 client.IsLoggingOut = true; 962 client.IsLoggingOut = true;
963 client.Close(); 963 client.Close(false);
964 } 964 }
965 } 965 }
966 966
@@ -972,6 +972,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
972 972
973 while (base.IsRunning) 973 while (base.IsRunning)
974 { 974 {
975 m_scene.ThreadAlive(1);
975 try 976 try
976 { 977 {
977 IncomingPacket incomingPacket = null; 978 IncomingPacket incomingPacket = null;
@@ -1014,6 +1015,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1014 1015
1015 while (base.IsRunning) 1016 while (base.IsRunning)
1016 { 1017 {
1018 m_scene.ThreadAlive(2);
1017 try 1019 try
1018 { 1020 {
1019 m_packetSent = false; 1021 m_packetSent = false;
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index 6eebd9d..d2779ba 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -100,10 +100,6 @@ namespace OpenMetaverse
100 const int SIO_UDP_CONNRESET = -1744830452; 100 const int SIO_UDP_CONNRESET = -1744830452;
101 101
102 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort); 102 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort);
103
104 m_log.DebugFormat(
105 "[UDPBASE]: Binding UDP listener using internal IP address config {0}:{1}",
106 ipep.Address, ipep.Port);
107 103
108 m_udpSocket = new Socket( 104 m_udpSocket = new Socket(
109 AddressFamily.InterNetwork, 105 AddressFamily.InterNetwork,
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
index 9d8082b..ff4ec4c 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
@@ -168,6 +168,19 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
168 { 168 {
169 if (XferUploaders.ContainsKey(transactionID)) 169 if (XferUploaders.ContainsKey(transactionID))
170 { 170 {
171// m_log.DebugFormat("[XFER]: Asked to update item {0} ({1})",
172// item.Name, item.ID);
173
174 // Here we need to get the old asset to extract the
175 // texture UUIDs if it's a wearable.
176 if (item.AssetType == (int)AssetType.Bodypart ||
177 item.AssetType == (int)AssetType.Clothing)
178 {
179 AssetBase oldAsset = m_Scene.AssetService.Get(item.AssetID.ToString());
180 if (oldAsset != null)
181 XferUploaders[transactionID].SetOldData(oldAsset.Data);
182 }
183
171 AssetBase asset = GetTransactionAsset(transactionID); 184 AssetBase asset = GetTransactionAsset(transactionID);
172 185
173 if (asset != null) 186 if (asset != null)
@@ -182,6 +195,9 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
182 195
183 IInventoryService invService = m_Scene.InventoryService; 196 IInventoryService invService = m_Scene.InventoryService;
184 invService.UpdateItem(item); 197 invService.UpdateItem(item);
198
199// m_log.DebugFormat("[XFER]: Updated item {0} ({1}) with asset {2}",
200// item.Name, item.ID, asset.FullID);
185 } 201 }
186 } 202 }
187 } 203 }
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
index a7929ba..a5dcdcc 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.IO; 29using System.IO;
30using System.Reflection; 30using System.Reflection;
31using System.Collections.Generic;
31using log4net; 32using log4net;
32using OpenMetaverse; 33using OpenMetaverse;
33using OpenSim.Framework; 34using OpenSim.Framework;
@@ -38,6 +39,13 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
38{ 39{
39 public class AssetXferUploader 40 public class AssetXferUploader
40 { 41 {
42 // Viewer's notion of the default texture
43 private List<UUID> defaultIDs = new List<UUID> {
44 new UUID("5748decc-f629-461c-9a36-a35a221fe21f"),
45 new UUID("7ca39b4c-bd19-4699-aff7-f93fd03d3e7b"),
46 new UUID("6522e74d-1660-4e7f-b601-6f48c1659a77"),
47 new UUID("c228d1cf-4b5d-4ba8-84f4-899a0796aa97")
48 };
41 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
42 50
43 private AssetBase m_asset; 51 private AssetBase m_asset;
@@ -55,6 +63,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
55 private UUID TransactionID = UUID.Zero; 63 private UUID TransactionID = UUID.Zero;
56 private sbyte type = 0; 64 private sbyte type = 0;
57 private byte wearableType = 0; 65 private byte wearableType = 0;
66 private byte[] m_oldData = null;
58 public ulong XferID; 67 public ulong XferID;
59 private Scene m_Scene; 68 private Scene m_Scene;
60 69
@@ -219,6 +228,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
219 228
220 private void DoCreateItem(uint callbackID) 229 private void DoCreateItem(uint callbackID)
221 { 230 {
231 ValidateAssets();
222 m_Scene.AssetService.Store(m_asset); 232 m_Scene.AssetService.Store(m_asset);
223 233
224 InventoryItemBase item = new InventoryItemBase(); 234 InventoryItemBase item = new InventoryItemBase();
@@ -239,12 +249,84 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
239 item.Flags = (uint) wearableType; 249 item.Flags = (uint) wearableType;
240 item.CreationDate = Util.UnixTimeSinceEpoch(); 250 item.CreationDate = Util.UnixTimeSinceEpoch();
241 251
252 m_log.DebugFormat("[XFER]: Created item {0} with asset {1}",
253 item.ID, item.AssetID);
254
242 if (m_Scene.AddInventoryItem(item)) 255 if (m_Scene.AddInventoryItem(item))
243 ourClient.SendInventoryItemCreateUpdate(item, callbackID); 256 ourClient.SendInventoryItemCreateUpdate(item, callbackID);
244 else 257 else
245 ourClient.SendAlertMessage("Unable to create inventory item"); 258 ourClient.SendAlertMessage("Unable to create inventory item");
246 } 259 }
247 260
261 private void ValidateAssets()
262 {
263 if (m_asset.Type == (sbyte)AssetType.Clothing ||
264 m_asset.Type == (sbyte)AssetType.Bodypart)
265 {
266 string content = System.Text.Encoding.ASCII.GetString(m_asset.Data);
267 string[] lines = content.Split(new char[] {'\n'});
268
269 List<string> validated = new List<string>();
270
271 Dictionary<int, UUID> allowed = ExtractTexturesFromOldData();
272
273 int textures = 0;
274
275 foreach (string line in lines)
276 {
277 try
278 {
279 if (line.StartsWith("textures "))
280 {
281 textures = Convert.ToInt32(line.Substring(9));
282 validated.Add(line);
283 }
284 else if (textures > 0)
285 {
286 string[] parts = line.Split(new char[] {' '});
287
288 UUID tx = new UUID(parts[1]);
289 int id = Convert.ToInt32(parts[0]);
290
291 if (defaultIDs.Contains(tx) || tx == UUID.Zero ||
292 (allowed.ContainsKey(id) && allowed[id] == tx))
293 {
294 validated.Add(parts[0] + " " + tx.ToString());
295 }
296 else
297 {
298 int perms = m_Scene.InventoryService.GetAssetPermissions(ourClient.AgentId, tx);
299 int full = (int)(PermissionMask.Modify | PermissionMask.Transfer | PermissionMask.Copy);
300
301 if ((perms & full) != full)
302 {
303 m_log.ErrorFormat("[ASSET UPLOADER]: REJECTED update with texture {0} from {1} because they do not own the texture", tx, ourClient.AgentId);
304 validated.Add(parts[0] + " " + UUID.Zero.ToString());
305 }
306 else
307 {
308 validated.Add(line);
309 }
310 }
311 textures--;
312 }
313 else
314 {
315 validated.Add(line);
316 }
317 }
318 catch
319 {
320 // If it's malformed, skip it
321 }
322 }
323
324 string final = String.Join("\n", validated.ToArray());
325
326 m_asset.Data = System.Text.Encoding.ASCII.GetBytes(final);
327 }
328 }
329
248 /// <summary> 330 /// <summary>
249 /// Get the asset data uploaded in this transfer. 331 /// Get the asset data uploaded in this transfer.
250 /// </summary> 332 /// </summary>
@@ -253,10 +335,55 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
253 { 335 {
254 if (m_finished) 336 if (m_finished)
255 { 337 {
338 ValidateAssets();
256 return m_asset; 339 return m_asset;
257 } 340 }
258 341
259 return null; 342 return null;
260 } 343 }
344
345 public void SetOldData(byte[] d)
346 {
347 m_oldData = d;
348 }
349
350 private Dictionary<int,UUID> ExtractTexturesFromOldData()
351 {
352 Dictionary<int,UUID> result = new Dictionary<int,UUID>();
353 if (m_oldData == null)
354 return result;
355
356 string content = System.Text.Encoding.ASCII.GetString(m_oldData);
357 string[] lines = content.Split(new char[] {'\n'});
358
359 int textures = 0;
360
361 foreach (string line in lines)
362 {
363 try
364 {
365 if (line.StartsWith("textures "))
366 {
367 textures = Convert.ToInt32(line.Substring(9));
368 }
369 else if (textures > 0)
370 {
371 string[] parts = line.Split(new char[] {' '});
372
373 UUID tx = new UUID(parts[1]);
374 int id = Convert.ToInt32(parts[0]);
375 result[id] = tx;
376 textures--;
377 }
378 }
379 catch
380 {
381 // If it's malformed, skip it
382 }
383 }
384
385 return result;
386 }
261 } 387 }
262} 388}
389
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index 48ee277..9ef5bc9 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -268,7 +268,16 @@ namespace Flotsam.RegionModules.AssetCache
268 // If the file is already cached, don't cache it, just touch it so access time is updated 268 // If the file is already cached, don't cache it, just touch it so access time is updated
269 if (File.Exists(filename)) 269 if (File.Exists(filename))
270 { 270 {
271 File.SetLastAccessTime(filename, DateTime.Now); 271 // We don't really want to know about sharing
272 // violations here. If the file is locked, then
273 // the other thread has updated the time for us.
274 try
275 {
276 File.SetLastAccessTime(filename, DateTime.Now);
277 }
278 catch
279 {
280 }
272 } else { 281 } else {
273 282
274 // Once we start writing, make sure we flag that we're writing 283 // Once we start writing, make sure we flag that we're writing
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 520d794..47476a9 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using System.Xml;
31using log4net; 32using log4net;
32using Mono.Addins; 33using Mono.Addins;
33using Nini.Config; 34using Nini.Config;
@@ -118,6 +119,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
118 return; 119 return;
119 } 120 }
120 121
122 if (part.OwnerID != remoteClient.AgentId) // Not ours
123 {
124 remoteClient.SendAgentAlertMessage(
125 "You don't have sufficient permissions to attach this object", false);
126 return;
127 }
128
121 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should 129 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
122 // be removed when that functionality is implemented in opensim 130 // be removed when that functionality is implemented in opensim
123 AttachmentPt &= 0x7f; 131 AttachmentPt &= 0x7f;
@@ -226,15 +234,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
226 public UUID RezSingleAttachmentFromInventory( 234 public UUID RezSingleAttachmentFromInventory(
227 IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus) 235 IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus)
228 { 236 {
229 m_log.DebugFormat( 237 return RezSingleAttachmentFromInventory(remoteClient, itemID, AttachmentPt, true, null);
230 "[ATTACHMENTS MODULE]: Rezzing attachment to point {0} from item {1} for {2}", 238 }
231 (AttachmentPoint)AttachmentPt, itemID, remoteClient.Name); 239
232 240 public UUID RezSingleAttachmentFromInventory(
241 IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus, XmlDocument doc)
242 {
233 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should 243 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
234 // be removed when that functionality is implemented in opensim 244 // be removed when that functionality is implemented in opensim
235 AttachmentPt &= 0x7f; 245 AttachmentPt &= 0x7f;
236 246
237 SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(remoteClient, itemID, AttachmentPt); 247 SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(remoteClient, itemID, AttachmentPt, doc);
238 248
239 if (updateInventoryStatus) 249 if (updateInventoryStatus)
240 { 250 {
@@ -251,7 +261,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
251 } 261 }
252 262
253 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal( 263 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal(
254 IClientAPI remoteClient, UUID itemID, uint AttachmentPt) 264 IClientAPI remoteClient, UUID itemID, uint AttachmentPt, XmlDocument doc)
255 { 265 {
256 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>(); 266 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>();
257 if (invAccess != null) 267 if (invAccess != null)
@@ -289,13 +299,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
289 if (tainted) 299 if (tainted)
290 objatt.HasGroupChanged = true; 300 objatt.HasGroupChanged = true;
291 301
302 if (doc != null)
303 {
304 objatt.LoadScriptState(doc);
305 objatt.ResetOwnerChangeFlag();
306 }
307
292 // Fire after attach, so we don't get messy perms dialogs 308 // Fire after attach, so we don't get messy perms dialogs
293 // 4 == AttachedRez 309 // 4 == AttachedRez
294 objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4); 310 objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4);
295 objatt.ResumeScripts(); 311 objatt.ResumeScripts();
296 312
297 // Do this last so that event listeners have access to all the effects of the attachment 313 // Do this last so that event listeners have access to all the effects of the attachment
298 m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, remoteClient.AgentId); 314 //m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, remoteClient.AgentId);
299 } 315 }
300 else 316 else
301 { 317 {
@@ -332,7 +348,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
332 if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) 348 if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence))
333 { 349 {
334 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); 350 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId);
335 item = m_scene.InventoryService.GetItem(item); 351 if (m_scene.InventoryService != null)
352 item = m_scene.InventoryService.GetItem(item);
336 353
337 bool changed = presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID); 354 bool changed = presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID);
338 if (changed && m_scene.AvatarFactory != null) 355 if (changed && m_scene.AvatarFactory != null)
@@ -379,6 +396,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
379 { 396 {
380 // XXYY!! 397 // XXYY!!
381 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); 398 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId);
399 if (item == null)
400 m_log.Error("[ATTACHMENT]: item == null");
401 if (m_scene == null)
402 m_log.Error("[ATTACHMENT]: m_scene == null");
403 if (m_scene.InventoryService == null)
404 m_log.Error("[ATTACHMENT]: m_scene.InventoryService == null");
382 item = m_scene.InventoryService.GetItem(item); 405 item = m_scene.InventoryService.GetItem(item);
383 bool changed = presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID); 406 bool changed = presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID);
384 if (changed && m_scene.AvatarFactory != null) 407 if (changed && m_scene.AvatarFactory != null)
@@ -465,6 +488,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
465 if (group.GetFromItemID() == itemID) 488 if (group.GetFromItemID() == itemID)
466 { 489 {
467 m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero); 490 m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero);
491 // CM / XMREngine!!!! Needed to conclude attach event
492 //SceneObjectSerializer.ToOriginalXmlFormat(group);
468 group.DetachToInventoryPrep(); 493 group.DetachToInventoryPrep();
469 m_log.Debug("[ATTACHMENTS MODULE]: Saving attachpoint: " + ((uint)group.GetAttachmentPoint()).ToString()); 494 m_log.Debug("[ATTACHMENTS MODULE]: Saving attachpoint: " + ((uint)group.GetAttachmentPoint()).ToString());
470 495
@@ -482,22 +507,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
482 } 507 }
483 } 508 }
484 509
485 public void UpdateAttachmentPosition(SceneObjectGroup sog, Vector3 pos)
486 {
487 // First we save the
488 // attachment point information, then we update the relative
489 // positioning. Then we have to mark the object as NOT an
490 // attachment. This is necessary in order to correctly save
491 // and retrieve GroupPosition information for the attachment.
492 // Finally, we restore the object's attachment status.
493 byte attachmentPoint = sog.GetAttachmentPoint();
494 sog.UpdateGroupPosition(pos);
495 sog.RootPart.IsAttachment = false;
496 sog.AbsolutePosition = sog.RootPart.AttachedPos;
497 sog.SetAttachmentPoint(attachmentPoint);
498 sog.HasGroupChanged = true;
499 }
500
501 /// <summary> 510 /// <summary>
502 /// Update the attachment asset for the new sog details if they have changed. 511 /// Update the attachment asset for the new sog details if they have changed.
503 /// </summary> 512 /// </summary>
@@ -600,15 +609,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
600 609
601 if (!silent) 610 if (!silent)
602 { 611 {
603 // Killing it here will cause the client to deselect it
604 // It then reappears on the avatar, deselected
605 // through the full update below
606 //
607 if (so.IsSelected)
608 {
609 m_scene.SendKillObject(so.RootPart.LocalId);
610 }
611
612 so.IsSelected = false; // fudge.... 612 so.IsSelected = false; // fudge....
613 so.ScheduleGroupForFullUpdate(); 613 so.ScheduleGroupForFullUpdate();
614 } 614 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
index 4359c01..35a3f43 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:
@@ -231,8 +245,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
231 s.ForEachScenePresence( 245 s.ForEachScenePresence(
232 delegate(ScenePresence presence) 246 delegate(ScenePresence presence)
233 { 247 {
234 if (TrySendChatMessage(presence, fromPos, regionPos, fromID, fromName, c.Type, message, sourceType)) 248 ILandObject Presencecheck = s.LandChannel.GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y);
235 receiverIDs.Add(presence.UUID); 249 if (Presencecheck != null)
250 {
251 // This will pass all chat from objects. Not
252 // perfect, but it will do. For now. Better
253 // than the prior behavior of muting all
254 // objects on a parcel with access restrictions
255 if (c.Sender == null || Presencecheck.IsEitherBannedOrRestricted(c.Sender.AgentId) != true)
256 {
257 if (TrySendChatMessage(presence, fromPos, regionPos, fromID, fromNamePrefix + fromName, c.Type, message, sourceType))
258 receiverIDs.Add(presence.UUID);
259 }
260 }
261
236 } 262 }
237 ); 263 );
238 } 264 }
@@ -276,31 +302,34 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
276 } 302 }
277 303
278 // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType); 304 // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType);
279
280 HashSet<UUID> receiverIDs = new HashSet<UUID>(); 305 HashSet<UUID> receiverIDs = new HashSet<UUID>();
281 306
282 ((Scene)c.Scene).ForEachScenePresence( 307 if (c.Scene != null)
283 delegate(ScenePresence presence) 308 {
284 { 309 ((Scene)c.Scene).ForEachScenePresence
285 // ignore chat from child agents 310 (
286 if (presence.IsChildAgent) return; 311 delegate(ScenePresence presence)
287 312 {
288 IClientAPI client = presence.ControllingClient; 313 // ignore chat from child agents
289 314 if (presence.IsChildAgent) return;
290 // don't forward SayOwner chat from objects to 315
291 // non-owner agents 316 IClientAPI client = presence.ControllingClient;
292 if ((c.Type == ChatTypeEnum.Owner) && 317
293 (null != c.SenderObject) && 318 // don't forward SayOwner chat from objects to
294 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) 319 // non-owner agents
295 return; 320 if ((c.Type == ChatTypeEnum.Owner) &&
296 321 (null != c.SenderObject) &&
297 client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, 322 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId))
298 (byte)sourceType, (byte)ChatAudibleLevel.Fully); 323 return;
299 receiverIDs.Add(presence.UUID); 324
300 }); 325 client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID,
301 326 (byte)sourceType, (byte)ChatAudibleLevel.Fully);
302 (c.Scene as Scene).EventManager.TriggerOnChatToClients( 327 receiverIDs.Add(presence.UUID);
303 fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully); 328 }
329 );
330 (c.Scene as Scene).EventManager.TriggerOnChatToClients(
331 fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully);
332 }
304 } 333 }
305 334
306 /// <summary> 335 /// <summary>
@@ -343,5 +372,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
343 372
344 return true; 373 return true;
345 } 374 }
375
376 Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>();
377 public void ParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
378 {
379 System.Threading.Timer Timer;
380 if (flags == 0)
381 {
382 FreezeCache.Add(target.ToString());
383 System.Threading.TimerCallback timeCB = new System.Threading.TimerCallback(OnEndParcelFrozen);
384 Timer = new System.Threading.Timer(timeCB, target, 30000, 0);
385 Timers.Add(target, Timer);
386 }
387 else
388 {
389 FreezeCache.Remove(target.ToString());
390 Timers.TryGetValue(target, out Timer);
391 Timers.Remove(target);
392 Timer.Dispose();
393 }
394 }
395
396 private void OnEndParcelFrozen(object avatar)
397 {
398 UUID target = (UUID)avatar;
399 FreezeCache.Remove(target.ToString());
400 System.Threading.Timer Timer;
401 Timers.TryGetValue(target, out Timer);
402 Timers.Remove(target);
403 Timer.Dispose();
404 }
346 } 405 }
347} 406}
diff --git a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
index 0db31eb..8a16582 100644
--- a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
@@ -216,4 +216,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog
216 return result; 216 return result;
217 } 217 }
218 } 218 }
219} \ No newline at end of file 219}
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index daee4ca..c8167c5 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -304,7 +304,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
304 //m_log.DebugFormat("[XXX]: OnClientLogin!"); 304 //m_log.DebugFormat("[XXX]: OnClientLogin!");
305 // Inform the friends that this user is online 305 // Inform the friends that this user is online
306 StatusChange(agentID, true); 306 StatusChange(agentID, true);
307 307
308 // Register that we need to send the list of online friends to this user 308 // Register that we need to send the list of online friends to this user
309 lock (m_NeedsListOfFriends) 309 lock (m_NeedsListOfFriends)
310 m_NeedsListOfFriends.Add(agentID); 310 m_NeedsListOfFriends.Add(agentID);
@@ -579,6 +579,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
579 579
580 StoreFriendships(agentID, friendID); 580 StoreFriendships(agentID, friendID);
581 581
582 ICallingCardModule ccm = client.Scene.RequestModuleInterface<ICallingCardModule>();
583 if (ccm != null)
584 {
585 ccm.CreateCallingCard(agentID, friendID, UUID.Zero);
586 }
587
582 // Update the local cache 588 // Update the local cache
583 RefetchFriends(client); 589 RefetchFriends(client);
584 590
@@ -755,6 +761,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
755 (byte)OpenMetaverse.InstantMessageDialog.FriendshipAccepted, userID.ToString(), false, Vector3.Zero); 761 (byte)OpenMetaverse.InstantMessageDialog.FriendshipAccepted, userID.ToString(), false, Vector3.Zero);
756 friendClient.SendInstantMessage(im); 762 friendClient.SendInstantMessage(im);
757 763
764 ICallingCardModule ccm = friendClient.Scene.RequestModuleInterface<ICallingCardModule>();
765 if (ccm != null)
766 {
767 ccm.CreateCallingCard(friendID, userID, UUID.Zero);
768 }
769
770
758 // Update the local cache 771 // Update the local cache
759 RefetchFriends(friendClient); 772 RefetchFriends(friendClient);
760 773
@@ -777,7 +790,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
777 // we're done 790 // we're done
778 return true; 791 return true;
779 } 792 }
780 793
781 return false; 794 return false;
782 } 795 }
783 796
diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
index 5ec64d5..a83b3df 100644
--- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
@@ -31,16 +31,40 @@ using OpenMetaverse;
31using OpenSim.Framework; 31using OpenSim.Framework;
32using OpenSim.Region.Framework.Scenes; 32using OpenSim.Region.Framework.Scenes;
33using OpenSim.Region.Framework.Interfaces; 33using OpenSim.Region.Framework.Interfaces;
34using System;
35using System.Reflection;
36using System.Collections;
37using System.Collections.Specialized;
38using System.Reflection;
39using System.IO;
40using System.Web;
41using System.Xml;
42using log4net;
43using Mono.Addins;
44using OpenMetaverse.Messages.Linden;
45using OpenMetaverse.StructuredData;
46using OpenSim.Framework.Capabilities;
47using OpenSim.Framework.Servers;
48using OpenSim.Framework.Servers.HttpServer;
49using Caps = OpenSim.Framework.Capabilities.Caps;
50using OSDArray = OpenMetaverse.StructuredData.OSDArray;
51using OSDMap = OpenMetaverse.StructuredData.OSDMap;
34 52
35namespace OpenSim.Region.CoreModules.Avatar.Gods 53namespace OpenSim.Region.CoreModules.Avatar.Gods
36{ 54{
37 public class GodsModule : IRegionModule, IGodsModule 55 public class GodsModule : IRegionModule, IGodsModule
38 { 56 {
57 private static readonly ILog m_log =
58 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
59
39 /// <summary>Special UUID for actions that apply to all agents</summary> 60 /// <summary>Special UUID for actions that apply to all agents</summary>
40 private static readonly UUID ALL_AGENTS = new UUID("44e87126-e794-4ded-05b3-7c42da3d5cdb"); 61 private static readonly UUID ALL_AGENTS = new UUID("44e87126-e794-4ded-05b3-7c42da3d5cdb");
41 62
42 protected Scene m_scene; 63 protected Scene m_scene;
43 protected IDialogModule m_dialogModule; 64 protected IDialogModule m_dialogModule;
65
66 protected Dictionary<UUID, string> m_capsDict =
67 new Dictionary<UUID, string>();
44 68
45 public void Initialise(Scene scene, IConfigSource source) 69 public void Initialise(Scene scene, IConfigSource source)
46 { 70 {
@@ -48,6 +72,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
48 m_dialogModule = m_scene.RequestModuleInterface<IDialogModule>(); 72 m_dialogModule = m_scene.RequestModuleInterface<IDialogModule>();
49 m_scene.RegisterModuleInterface<IGodsModule>(this); 73 m_scene.RegisterModuleInterface<IGodsModule>(this);
50 m_scene.EventManager.OnNewClient += SubscribeToClientEvents; 74 m_scene.EventManager.OnNewClient += SubscribeToClientEvents;
75 m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
76 m_scene.EventManager.OnClientClosed += OnClientClosed;
77 scene.EventManager.OnIncomingInstantMessage +=
78 OnIncomingInstantMessage;
51 } 79 }
52 80
53 public void PostInitialise() {} 81 public void PostInitialise() {}
@@ -67,6 +95,54 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
67 client.OnRequestGodlikePowers -= RequestGodlikePowers; 95 client.OnRequestGodlikePowers -= RequestGodlikePowers;
68 } 96 }
69 97
98 private void OnClientClosed(UUID agentID, Scene scene)
99 {
100 m_capsDict.Remove(agentID);
101 }
102
103 private void OnRegisterCaps(UUID agentID, Caps caps)
104 {
105 string uri = "/CAPS/" + UUID.Random();
106 m_capsDict[agentID] = uri;
107
108 caps.RegisterHandler("UntrustedSimulatorMessage",
109 new RestStreamHandler("POST", uri,
110 HandleUntrustedSimulatorMessage));
111 }
112
113 private string HandleUntrustedSimulatorMessage(string request,
114 string path, string param, OSHttpRequest httpRequest,
115 OSHttpResponse httpResponse)
116 {
117 OSDMap osd = (OSDMap)OSDParser.DeserializeLLSDXml(request);
118
119 string message = osd["message"].AsString();
120
121 if (message == "GodKickUser")
122 {
123 OSDMap body = (OSDMap)osd["body"];
124 OSDArray userInfo = (OSDArray)body["UserInfo"];
125 OSDMap userData = (OSDMap)userInfo[0];
126
127 UUID agentID = userData["AgentID"].AsUUID();
128 UUID godID = userData["GodID"].AsUUID();
129 UUID godSessionID = userData["GodSessionID"].AsUUID();
130 uint kickFlags = userData["KickFlags"].AsUInteger();
131 string reason = userData["Reason"].AsString();
132
133 ScenePresence god = m_scene.GetScenePresence(godID);
134 if (god == null || god.ControllingClient.SessionId != godSessionID)
135 return String.Empty;
136
137 KickUser(godID, godSessionID, agentID, kickFlags, Util.StringToBytes1024(reason));
138 }
139 else
140 {
141 m_log.ErrorFormat("[GOD]: Unhandled UntrustedSimulatorMessage: {0}", message);
142 }
143 return String.Empty;
144 }
145
70 public void RequestGodlikePowers( 146 public void RequestGodlikePowers(
71 UUID agentID, UUID sessionID, UUID token, bool godLike, IClientAPI controllingClient) 147 UUID agentID, UUID sessionID, UUID token, bool godLike, IClientAPI controllingClient)
72 { 148 {
@@ -115,71 +191,85 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
115 /// <param name="reason">The message to send to the user after it's been turned into a field</param> 191 /// <param name="reason">The message to send to the user after it's been turned into a field</param>
116 public void KickUser(UUID godID, UUID sessionID, UUID agentID, uint kickflags, byte[] reason) 192 public void KickUser(UUID godID, UUID sessionID, UUID agentID, uint kickflags, byte[] reason)
117 { 193 {
118 UUID kickUserID = ALL_AGENTS; 194 if (!m_scene.Permissions.IsGod(godID))
119 195 return;
196
120 ScenePresence sp = m_scene.GetScenePresence(agentID); 197 ScenePresence sp = m_scene.GetScenePresence(agentID);
121 198
122 if (sp != null || agentID == kickUserID) 199 if (sp == null && agentID != ALL_AGENTS)
123 { 200 {
124 if (m_scene.Permissions.IsGod(godID)) 201 IMessageTransferModule transferModule =
202 m_scene.RequestModuleInterface<IMessageTransferModule>();
203 if (transferModule != null)
125 { 204 {
126 if (kickflags == 0) 205 m_log.DebugFormat("[GODS]: Sending nonlocal kill for agent {0}", agentID);
127 { 206 transferModule.SendInstantMessage(new GridInstantMessage(
128 if (agentID == kickUserID) 207 m_scene, godID, "God", agentID, (byte)250, false,
129 { 208 Utils.BytesToString(reason), UUID.Zero, true,
130 string reasonStr = Utils.BytesToString(reason); 209 new Vector3(), new byte[] {(byte)kickflags}),
131 210 delegate(bool success) {} );
132 m_scene.ForEachClient( 211 }
133 delegate(IClientAPI controller) 212 return;
134 { 213 }
135 if (controller.AgentId != godID)
136 controller.Kick(reasonStr);
137 }
138 );
139
140 // This is a bit crude. It seems the client will be null before it actually stops the thread
141 // The thread will kill itself eventually :/
142 // Is there another way to make sure *all* clients get this 'inter region' message?
143 m_scene.ForEachScenePresence(
144 delegate(ScenePresence p)
145 {
146 if (p.UUID != godID && !p.IsChildAgent)
147 {
148 // Possibly this should really be p.Close() though that method doesn't send a close
149 // to the client
150 p.ControllingClient.Close();
151 }
152 }
153 );
154 }
155 else
156 {
157 m_scene.SceneGraph.removeUserCount(!sp.IsChildAgent);
158 214
159 sp.ControllingClient.Kick(Utils.BytesToString(reason)); 215 switch (kickflags)
160 sp.ControllingClient.Close(); 216 {
161 } 217 case 0:
162 } 218 if (sp != null)
163 219 {
164 if (kickflags == 1) 220 KickPresence(sp, Utils.BytesToString(reason));
165 {
166 sp.AllowMovement = false;
167 m_dialogModule.SendAlertToUser(agentID, Utils.BytesToString(reason));
168 m_dialogModule.SendAlertToUser(godID, "User Frozen");
169 }
170
171 if (kickflags == 2)
172 {
173 sp.AllowMovement = true;
174 m_dialogModule.SendAlertToUser(agentID, Utils.BytesToString(reason));
175 m_dialogModule.SendAlertToUser(godID, "User Unfrozen");
176 }
177 } 221 }
178 else 222 else if (agentID == ALL_AGENTS)
179 { 223 {
180 m_dialogModule.SendAlertToUser(godID, "Kick request denied"); 224 m_scene.ForEachScenePresence(
225 delegate(ScenePresence p)
226 {
227 if (p.UUID != godID && (!m_scene.Permissions.IsGod(p.UUID)))
228 KickPresence(p, Utils.BytesToString(reason));
229 }
230 );
181 } 231 }
232 break;
233 case 1:
234 if (sp != null)
235 {
236 sp.AllowMovement = false;
237 m_dialogModule.SendAlertToUser(agentID, Utils.BytesToString(reason));
238 m_dialogModule.SendAlertToUser(godID, "User Frozen");
239 }
240 break;
241 case 2:
242 if (sp != null)
243 {
244 sp.AllowMovement = true;
245 m_dialogModule.SendAlertToUser(agentID, Utils.BytesToString(reason));
246 m_dialogModule.SendAlertToUser(godID, "User Unfrozen");
247 }
248 break;
249 default:
250 break;
251 }
252 }
253
254 private void KickPresence(ScenePresence sp, string reason)
255 {
256 if (sp.IsChildAgent)
257 return;
258 sp.ControllingClient.Kick(reason);
259 sp.Scene.IncomingCloseAgent(sp.UUID);
260 }
261
262 private void OnIncomingInstantMessage(GridInstantMessage msg)
263 {
264 if (msg.dialog == (uint)250) // Nonlocal kick
265 {
266 UUID agentID = new UUID(msg.toAgentID);
267 string reason = msg.message;
268 UUID godID = new UUID(msg.fromAgentID);
269 uint kickMode = (uint)msg.binaryBucket[0];
270
271 KickUser(godID, UUID.Zero, agentID, kickMode, Util.StringToBytes1024(reason));
182 } 272 }
183 } 273 }
184 } 274 }
185} \ No newline at end of file 275}
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
index af39565..feb5fb8 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
@@ -156,6 +156,32 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
156 return; 156 return;
157 } 157 }
158 158
159 //DateTime dt = DateTime.UtcNow;
160
161 // Ticks from UtcNow, but make it look like local. Evil, huh?
162 //dt = DateTime.SpecifyKind(dt, DateTimeKind.Local);
163
164 //try
165 //{
166 // // Convert that to the PST timezone
167 // TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
168 // dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo);
169 //}
170 //catch
171 //{
172 // //m_log.Info("[OFFLINE MESSAGING]: No PST timezone found on this machine. Saving with local timestamp.");
173 //}
174
175 //// And make it look local again to fool the unix time util
176 //dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
177
178 // If client is null, this message comes from storage and IS offline
179 if (client != null)
180 im.offline = 0;
181
182 if (im.offline == 0)
183 im.timestamp = (uint)Util.UnixTimeSinceEpoch();
184
159 if (m_TransferModule != null) 185 if (m_TransferModule != null)
160 { 186 {
161 if (client != null) 187 if (client != null)
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
index 77c7147..c1caf44 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
@@ -47,6 +47,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 48
49 private bool m_Enabled = false; 49 private bool m_Enabled = false;
50 protected string m_MessageKey = String.Empty;
50 protected List<Scene> m_Scenes = new List<Scene>(); 51 protected List<Scene> m_Scenes = new List<Scene>();
51 protected Dictionary<UUID, UUID> m_UserRegionMap = new Dictionary<UUID, UUID>(); 52 protected Dictionary<UUID, UUID> m_UserRegionMap = new Dictionary<UUID, UUID>();
52 53
@@ -66,14 +67,17 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
66 public virtual void Initialise(IConfigSource config) 67 public virtual void Initialise(IConfigSource config)
67 { 68 {
68 IConfig cnf = config.Configs["Messaging"]; 69 IConfig cnf = config.Configs["Messaging"];
69 if (cnf != null && cnf.GetString( 70 if (cnf != null)
70 "MessageTransferModule", "MessageTransferModule") !=
71 "MessageTransferModule")
72 { 71 {
73 m_log.Debug("[MESSAGE TRANSFER]: Disabled by configuration"); 72 if (cnf.GetString("MessageTransferModule",
74 return; 73 "MessageTransferModule") != "MessageTransferModule")
75 } 74 {
75 return;
76 }
76 77
78 m_MessageKey = cnf.GetString("MessageKey", String.Empty);
79 }
80 m_log.Debug("[MESSAGE TRANSFER]: Module enabled");
77 m_Enabled = true; 81 m_Enabled = true;
78 } 82 }
79 83
@@ -145,8 +149,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
145 ScenePresence user = (ScenePresence) scene.Entities[toAgentID]; 149 ScenePresence user = (ScenePresence) scene.Entities[toAgentID];
146 if (!user.IsChildAgent) 150 if (!user.IsChildAgent)
147 { 151 {
148 // Local message 152 // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering to client");
149// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID);
150 user.ControllingClient.SendInstantMessage(im); 153 user.ControllingClient.SendInstantMessage(im);
151 154
152 // Message sent 155 // Message sent
@@ -168,7 +171,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
168 // Local message 171 // Local message
169 ScenePresence user = (ScenePresence) scene.Entities[toAgentID]; 172 ScenePresence user = (ScenePresence) scene.Entities[toAgentID];
170 173
171// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID); 174 // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering to client");
172 user.ControllingClient.SendInstantMessage(im); 175 user.ControllingClient.SendInstantMessage(im);
173 176
174 // Message sent 177 // Message sent
@@ -251,6 +254,19 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
251 && requestData.ContainsKey("position_z") && requestData.ContainsKey("region_id") 254 && requestData.ContainsKey("position_z") && requestData.ContainsKey("region_id")
252 && requestData.ContainsKey("binary_bucket")) 255 && requestData.ContainsKey("binary_bucket"))
253 { 256 {
257 if (m_MessageKey != String.Empty)
258 {
259 XmlRpcResponse error_resp = new XmlRpcResponse();
260 Hashtable error_respdata = new Hashtable();
261 error_respdata["success"] = "FALSE";
262 error_resp.Value = error_respdata;
263
264 if (!requestData.Contains("message_key"))
265 return error_resp;
266 if (m_MessageKey != (string)requestData["message_key"])
267 return error_resp;
268 }
269
254 // Do the easy way of validating the UUIDs 270 // Do the easy way of validating the UUIDs
255 UUID.TryParse((string)requestData["from_agent_id"], out fromAgentID); 271 UUID.TryParse((string)requestData["from_agent_id"], out fromAgentID);
256 UUID.TryParse((string)requestData["to_agent_id"], out toAgentID); 272 UUID.TryParse((string)requestData["to_agent_id"], out toAgentID);
@@ -433,24 +449,37 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
433 return resp; 449 return resp;
434 } 450 }
435 451
436 /// <summary> 452 private delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result);
437 /// delegate for sending a grid instant message asynchronously
438 /// </summary>
439 public delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID);
440 453
441 protected virtual void GridInstantMessageCompleted(IAsyncResult iar) 454 private class GIM {
442 { 455 public GridInstantMessage im;
443 GridInstantMessageDelegate icon = 456 public MessageResultNotification result;
444 (GridInstantMessageDelegate)iar.AsyncState; 457 };
445 icon.EndInvoke(iar);
446 }
447 458
459 private Queue<GIM> pendingInstantMessages = new Queue<GIM>();
460 private int numInstantMessageThreads = 0;
448 461
449 protected virtual void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result) 462 private void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result)
450 { 463 {
451 GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsync; 464 lock (pendingInstantMessages) {
465 if (numInstantMessageThreads >= 4) {
466 GIM gim = new GIM();
467 gim.im = im;
468 gim.result = result;
469 pendingInstantMessages.Enqueue(gim);
470 } else {
471 ++ numInstantMessageThreads;
472 //m_log.DebugFormat("[SendGridInstantMessageViaXMLRPC]: ++numInstantMessageThreads={0}", numInstantMessageThreads);
473 GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsyncMain;
474 d.BeginInvoke(im, result, GridInstantMessageCompleted, d);
475 }
476 }
477 }
452 478
453 d.BeginInvoke(im, result, UUID.Zero, GridInstantMessageCompleted, d); 479 private void GridInstantMessageCompleted(IAsyncResult iar)
480 {
481 GridInstantMessageDelegate d = (GridInstantMessageDelegate)iar.AsyncState;
482 d.EndInvoke(iar);
454 } 483 }
455 484
456 /// <summary> 485 /// <summary>
@@ -465,8 +494,31 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
465 /// Pass in 0 the first time this method is called. It will be called recursively with the last 494 /// Pass in 0 the first time this method is called. It will be called recursively with the last
466 /// regionhandle tried 495 /// regionhandle tried
467 /// </param> 496 /// </param>
468 protected virtual void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID) 497 private void SendGridInstantMessageViaXMLRPCAsyncMain(GridInstantMessage im, MessageResultNotification result)
469 { 498 {
499 GIM gim;
500 do {
501 try {
502 SendGridInstantMessageViaXMLRPCAsync(im, result, UUID.Zero);
503 } catch (Exception e) {
504 m_log.Error("[SendGridInstantMessageViaXMLRPC]: exception " + e.Message);
505 }
506 lock (pendingInstantMessages) {
507 if (pendingInstantMessages.Count > 0) {
508 gim = pendingInstantMessages.Dequeue();
509 im = gim.im;
510 result = gim.result;
511 } else {
512 gim = null;
513 -- numInstantMessageThreads;
514 //m_log.DebugFormat("[SendGridInstantMessageViaXMLRPC]: --numInstantMessageThreads={0}", numInstantMessageThreads);
515 }
516 }
517 } while (gim != null);
518 }
519 private void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID)
520 {
521
470 UUID toAgentID = new UUID(im.toAgentID); 522 UUID toAgentID = new UUID(im.toAgentID);
471 523
472 PresenceInfo upd = null; 524 PresenceInfo upd = null;
@@ -533,7 +585,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
533 585
534 if (upd != null) 586 if (upd != null)
535 { 587 {
536 GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, 588 GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(UUID.Zero,
537 upd.RegionID); 589 upd.RegionID);
538 if (reginfo != null) 590 if (reginfo != null)
539 { 591 {
@@ -682,6 +734,8 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
682 gim["position_z"] = msg.Position.Z.ToString(); 734 gim["position_z"] = msg.Position.Z.ToString();
683 gim["region_id"] = msg.RegionID.ToString(); 735 gim["region_id"] = msg.RegionID.ToString();
684 gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket,Base64FormattingOptions.None); 736 gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket,Base64FormattingOptions.None);
737 if (m_MessageKey != String.Empty)
738 gim["message_key"] = m_MessageKey;
685 return gim; 739 return gim;
686 } 740 }
687 741
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
index 321b38b..1a0b914 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
@@ -171,16 +171,16 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
171 171
172 private void RetrieveInstantMessages(IClientAPI client) 172 private void RetrieveInstantMessages(IClientAPI client)
173 { 173 {
174 if (m_RestURL != "") 174 if (m_RestURL == String.Empty)
175 { 175 return;
176 m_log.DebugFormat("[OFFLINE MESSAGING] Retrieving stored messages for {0}", client.AgentId);
177 176
178 List<GridInstantMessage> msglist = SynchronousRestObjectPoster.BeginPostObject<UUID, List<GridInstantMessage>>( 177 m_log.DebugFormat("[OFFLINE MESSAGING] Retrieving stored messages for {0}", client.AgentId);
179 "POST", m_RestURL + "/RetrieveMessages/", client.AgentId);
180 178
181 if (msglist == null) 179 List<GridInstantMessage> msglist = SynchronousRestObjectPoster.BeginPostObject<UUID, List<GridInstantMessage>>(
182 m_log.WarnFormat("[OFFLINE MESSAGING]: WARNING null message list."); 180 "POST", m_RestURL + "/RetrieveMessages/", client.AgentId);
183 181
182 if (msglist != null)
183 {
184 foreach (GridInstantMessage im in msglist) 184 foreach (GridInstantMessage im in msglist)
185 { 185 {
186 // client.SendInstantMessage(im); 186 // client.SendInstantMessage(im);
@@ -191,6 +191,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
191 // Needed for proper state management for stored group 191 // Needed for proper state management for stored group
192 // invitations 192 // invitations
193 // 193 //
194
195 im.offline = 1;
196
194 Scene s = FindScene(client.AgentId); 197 Scene s = FindScene(client.AgentId);
195 if (s != null) 198 if (s != null)
196 s.EventManager.TriggerIncomingInstantMessage(im); 199 s.EventManager.TriggerIncomingInstantMessage(im);
@@ -200,26 +203,38 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
200 203
201 private void UndeliveredMessage(GridInstantMessage im) 204 private void UndeliveredMessage(GridInstantMessage im)
202 { 205 {
203 if ((im.offline != 0) 206 if (im.dialog != (byte)InstantMessageDialog.MessageFromObject &&
204 && (!im.fromGroup || (im.fromGroup && m_ForwardOfflineGroupMessages))) 207 im.dialog != (byte)InstantMessageDialog.MessageFromAgent &&
208 im.dialog != (byte)InstantMessageDialog.GroupNotice &&
209 im.dialog != (byte)InstantMessageDialog.GroupInvitation &&
210 im.dialog != (byte)InstantMessageDialog.InventoryOffered)
205 { 211 {
206 bool success = SynchronousRestObjectPoster.BeginPostObject<GridInstantMessage, bool>( 212 return;
207 "POST", m_RestURL+"/SaveMessage/", im); 213 }
208 214
209 if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent) 215 // It's not delivered. Make sure the scope id is saved
210 { 216 // We don't need the imSessionID here anymore, overwrite it
211 IClientAPI client = FindClient(new UUID(im.fromAgentID)); 217 Scene scene = FindScene(new UUID(im.fromAgentID));
212 if (client == null) 218 if (scene == null)
213 return; 219 scene = m_SceneList[0];
214 220
215 client.SendInstantMessage(new GridInstantMessage( 221 bool success = SynchronousRestObjectPoster.BeginPostObject<GridInstantMessage, bool>(
216 null, new UUID(im.toAgentID), 222 "POST", m_RestURL+"/SaveMessage/?scope=" +
217 "System", new UUID(im.fromAgentID), 223 scene.RegionInfo.ScopeID.ToString(), im);
218 (byte)InstantMessageDialog.MessageFromAgent, 224
219 "User is not logged in. "+ 225 if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent)
220 (success ? "Message saved." : "Message not saved"), 226 {
221 false, new Vector3())); 227 IClientAPI client = FindClient(new UUID(im.fromAgentID));
222 } 228 if (client == null)
229 return;
230
231 client.SendInstantMessage(new GridInstantMessage(
232 null, new UUID(im.toAgentID),
233 "System", new UUID(im.fromAgentID),
234 (byte)InstantMessageDialog.MessageFromAgent,
235 "User is not logged in. "+
236 (success ? "Message saved." : "Message not saved"),
237 false, new Vector3()));
223 } 238 }
224 } 239 }
225 } 240 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
index 6b24718..a19bbfd 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
@@ -632,4 +632,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
632 m_assetsLoaded = true; 632 m_assetsLoaded = true;
633 } 633 }
634 } 634 }
635} \ No newline at end of file 635}
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
index 36ecb3b..63fde07 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
@@ -178,9 +178,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
178 InventoryFolderBase inventoryFolder, string path, bool saveThisFolderItself, 178 InventoryFolderBase inventoryFolder, string path, bool saveThisFolderItself,
179 Dictionary<string, object> options, IUserAccountService userAccountService) 179 Dictionary<string, object> options, IUserAccountService userAccountService)
180 { 180 {
181 if (options.ContainsKey("verbose"))
182 m_log.InfoFormat("[INVENTORY ARCHIVER]: Saving folder {0}", inventoryFolder.Name);
183
184 if (saveThisFolderItself) 181 if (saveThisFolderItself)
185 { 182 {
186 path += CreateArchiveFolderName(inventoryFolder); 183 path += CreateArchiveFolderName(inventoryFolder);
@@ -449,4 +446,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
449 return s; 446 return s;
450 } 447 }
451 } 448 }
452} \ No newline at end of file 449}
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
index e3d4969..528bc8d 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
@@ -175,8 +175,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
175 if (im.binaryBucket.Length < 17) // Invalid 175 if (im.binaryBucket.Length < 17) // Invalid
176 return; 176 return;
177 177
178 UUID receipientID = new UUID(im.toAgentID); 178 UUID recipientID = new UUID(im.toAgentID);
179 ScenePresence user = scene.GetScenePresence(receipientID); 179 ScenePresence user = scene.GetScenePresence(recipientID);
180 UUID copyID; 180 UUID copyID;
181 181
182 // First byte is the asset type 182 // First byte is the asset type
@@ -191,7 +191,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
191 folderID, new UUID(im.toAgentID)); 191 folderID, new UUID(im.toAgentID));
192 192
193 InventoryFolderBase folderCopy 193 InventoryFolderBase folderCopy
194 = scene.GiveInventoryFolder(receipientID, client.AgentId, folderID, UUID.Zero); 194 = scene.GiveInventoryFolder(recipientID, client.AgentId, folderID, UUID.Zero);
195 195
196 if (folderCopy == null) 196 if (folderCopy == null)
197 { 197 {
@@ -248,6 +248,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
248 im.imSessionID = itemID.Guid; 248 im.imSessionID = itemID.Guid;
249 } 249 }
250 250
251 im.offline = 1; // Remember these
252
251 // Send the IM to the recipient. The item is already 253 // Send the IM to the recipient. The item is already
252 // in their inventory, so it will not be lost if 254 // in their inventory, so it will not be lost if
253 // they are offline. 255 // they are offline.
@@ -417,22 +419,67 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
417 /// 419 ///
418 /// </summary> 420 /// </summary>
419 /// <param name="msg"></param> 421 /// <param name="msg"></param>
420 private void OnGridInstantMessage(GridInstantMessage msg) 422 private void OnGridInstantMessage(GridInstantMessage im)
421 { 423 {
422 // Check if this is ours to handle 424 // Check if this is ours to handle
423 // 425 //
424 Scene scene = FindClientScene(new UUID(msg.toAgentID)); 426 Scene scene = FindClientScene(new UUID(im.toAgentID));
425 427
426 if (scene == null) 428 if (scene == null)
427 return; 429 return;
428 430
429 // Find agent to deliver to 431 // Find agent to deliver to
430 // 432 //
431 ScenePresence user = scene.GetScenePresence(new UUID(msg.toAgentID)); 433 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID));
434 if (user == null)
435 return;
436
437 // This requires a little bit of processing because we have to make the
438 // new item visible in the recipient's inventory here
439 //
440 if (im.dialog == (byte) InstantMessageDialog.InventoryOffered)
441 {
442 if (im.binaryBucket.Length < 17) // Invalid
443 return;
444
445 UUID recipientID = new UUID(im.toAgentID);
446
447 // First byte is the asset type
448 AssetType assetType = (AssetType)im.binaryBucket[0];
449
450 if (AssetType.Folder == assetType)
451 {
452 UUID folderID = new UUID(im.binaryBucket, 1);
453
454 InventoryFolderBase given =
455 new InventoryFolderBase(folderID, recipientID);
456 InventoryFolderBase folder =
457 scene.InventoryService.GetFolder(given);
458
459 if (folder != null)
460 user.ControllingClient.SendBulkUpdateInventory(folder);
461 }
462 else
463 {
464 UUID itemID = new UUID(im.binaryBucket, 1);
432 465
433 // Just forward to local handling 466 InventoryItemBase given =
434 OnInstantMessage(user.ControllingClient, msg); 467 new InventoryItemBase(itemID, recipientID);
468 InventoryItemBase item =
469 scene.InventoryService.GetItem(given);
435 470
471 if (item != null)
472 {
473 user.ControllingClient.SendBulkUpdateInventory(item);
474 }
475 }
476 user.ControllingClient.SendInstantMessage(im);
477 }
478 else if (im.dialog == (byte) InstantMessageDialog.InventoryAccepted ||
479 im.dialog == (byte) InstantMessageDialog.InventoryDeclined)
480 {
481 user.ControllingClient.SendInstantMessage(im);
482 }
436 } 483 }
437 } 484 }
438} 485}
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
index d295384..dcfdf8f 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
@@ -155,16 +155,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
155 scene.RegionInfo.RegionHandle, 155 scene.RegionInfo.RegionHandle,
156 (uint)presence.AbsolutePosition.X, 156 (uint)presence.AbsolutePosition.X,
157 (uint)presence.AbsolutePosition.Y, 157 (uint)presence.AbsolutePosition.Y,
158 (uint)presence.AbsolutePosition.Z); 158 (uint)presence.AbsolutePosition.Z + 2);
159 159
160 m_log.DebugFormat("TP invite with message {0}", message); 160 m_log.DebugFormat("[LURE]: TP invite with message {0}", message);
161
162 GridInstantMessage m;
163
164 if (scene.Permissions.IsAdministrator(client.AgentId) && presence.GodLevel >= 200 && (!scene.Permissions.IsAdministrator(targetid)))
165 {
166 m = new GridInstantMessage(scene, client.AgentId,
167 client.FirstName+" "+client.LastName, targetid,
168 (byte)InstantMessageDialog.GodLikeRequestTeleport, false,
169 message, dest, false, presence.AbsolutePosition,
170 new Byte[0]);
171 }
172 else
173 {
174 m = new GridInstantMessage(scene, client.AgentId,
175 client.FirstName+" "+client.LastName, targetid,
176 (byte)InstantMessageDialog.RequestTeleport, false,
177 message, dest, false, presence.AbsolutePosition,
178 new Byte[0]);
179 }
161 180
162 GridInstantMessage m = new GridInstantMessage(scene, client.AgentId,
163 client.FirstName+" "+client.LastName, targetid,
164 (byte)InstantMessageDialog.RequestTeleport, false,
165 message, dest, false, presence.AbsolutePosition,
166 new Byte[0]);
167
168 if (m_TransferModule != null) 181 if (m_TransferModule != null)
169 { 182 {
170 m_TransferModule.SendInstantMessage(m, 183 m_TransferModule.SendInstantMessage(m,
@@ -199,7 +212,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
199 { 212 {
200 // Forward remote teleport requests 213 // Forward remote teleport requests
201 // 214 //
202 if (msg.dialog != 22) 215 if (msg.dialog != (byte)InstantMessageDialog.RequestTeleport &&
216 msg.dialog != (byte)InstantMessageDialog.GodLikeRequestTeleport)
203 return; 217 return;
204 218
205 if (m_TransferModule != null) 219 if (m_TransferModule != null)
diff --git a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
index eb776fe..7ae304c 100644
--- a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
@@ -97,7 +97,8 @@ namespace OpenSim.Region.CoreModules.Framework
97 97
98 public void CreateCaps(UUID agentId) 98 public void CreateCaps(UUID agentId)
99 { 99 {
100 if (m_scene.RegionInfo.EstateSettings.IsBanned(agentId)) 100 int flags = m_scene.GetUserFlags(agentId);
101 if (m_scene.RegionInfo.EstateSettings.IsBanned(agentId, flags))
101 return; 102 return;
102 103
103 String capsObjectPath = GetCapsPath(agentId); 104 String capsObjectPath = GetCapsPath(agentId);
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index 1341533..02efcd8 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -104,7 +104,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
104 104
105 protected virtual void OnNewClient(IClientAPI client) 105 protected virtual void OnNewClient(IClientAPI client)
106 { 106 {
107 client.OnTeleportHomeRequest += TeleportHome; 107 client.OnTeleportHomeRequest += TriggerTeleportHome;
108 client.OnTeleportLandmarkRequest += RequestTeleportLandmark; 108 client.OnTeleportLandmarkRequest += RequestTeleportLandmark;
109 } 109 }
110 110
@@ -184,6 +184,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
184 sp.ControllingClient.SendTeleportStart(teleportFlags); 184 sp.ControllingClient.SendTeleportStart(teleportFlags);
185 185
186 sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags); 186 sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags);
187 sp.TeleportFlags = (TeleportFlags)teleportFlags;
187 sp.Teleport(position); 188 sp.Teleport(position);
188 189
189 foreach (SceneObjectGroup grp in sp.Attachments) 190 foreach (SceneObjectGroup grp in sp.Attachments)
@@ -275,7 +276,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
275 // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field, 276 // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field,
276 // it's actually doing a lot of work. 277 // it's actually doing a lot of work.
277 IPEndPoint endPoint = finalDestination.ExternalEndPoint; 278 IPEndPoint endPoint = finalDestination.ExternalEndPoint;
278 if (endPoint.Address != null) 279 if (endPoint != null && endPoint.Address != null)
279 { 280 {
280 // Fixing a bug where teleporting while sitting results in the avatar ending up removed from 281 // Fixing a bug where teleporting while sitting results in the avatar ending up removed from
281 // both regions 282 // both regions
@@ -524,7 +525,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
524 525
525 protected void KillEntity(Scene scene, uint localID) 526 protected void KillEntity(Scene scene, uint localID)
526 { 527 {
527 scene.SendKillObject(localID); 528 scene.SendKillObject(new List<uint>() { localID });
528 } 529 }
529 530
530 protected virtual GridRegion GetFinalDestination(GridRegion region) 531 protected virtual GridRegion GetFinalDestination(GridRegion region)
@@ -585,7 +586,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
585 586
586 #region Teleport Home 587 #region Teleport Home
587 588
588 public virtual void TeleportHome(UUID id, IClientAPI client) 589 public virtual void TriggerTeleportHome(UUID id, IClientAPI client)
590 {
591 TeleportHome(id, client);
592 }
593
594 public virtual bool TeleportHome(UUID id, IClientAPI client)
589 { 595 {
590 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Request to teleport {0} {1} home", client.FirstName, client.LastName); 596 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Request to teleport {0} {1} home", client.FirstName, client.LastName);
591 597
@@ -594,12 +600,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
594 600
595 if (uinfo != null) 601 if (uinfo != null)
596 { 602 {
603 if (uinfo.HomeRegionID == UUID.Zero)
604 {
605 // can't find the Home region: Tell viewer and abort
606 client.SendTeleportFailed("You don't have a home position set.");
607 return false;
608 }
597 GridRegion regionInfo = m_aScene.GridService.GetRegionByUUID(UUID.Zero, uinfo.HomeRegionID); 609 GridRegion regionInfo = m_aScene.GridService.GetRegionByUUID(UUID.Zero, uinfo.HomeRegionID);
598 if (regionInfo == null) 610 if (regionInfo == null)
599 { 611 {
600 // can't find the Home region: Tell viewer and abort 612 // can't find the Home region: Tell viewer and abort
601 client.SendTeleportFailed("Your home region could not be found."); 613 client.SendTeleportFailed("Your home region could not be found.");
602 return; 614 return false;
603 } 615 }
604 616
605 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: User's home region is {0} {1} ({2}-{3})", 617 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: User's home region is {0} {1} ({2}-{3})",
@@ -610,6 +622,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
610 client, regionInfo.RegionHandle, uinfo.HomePosition, uinfo.HomeLookAt, 622 client, regionInfo.RegionHandle, uinfo.HomePosition, uinfo.HomeLookAt,
611 (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome)); 623 (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome));
612 } 624 }
625 else
626 {
627 // can't find the Home region: Tell viewer and abort
628 client.SendTeleportFailed("Your home region could not be found.");
629 return false;
630 }
631 return true;
613 } 632 }
614 633
615 #endregion 634 #endregion
@@ -946,15 +965,19 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
946 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID); 965 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID);
947 966
948 IEventQueue eq = agent.Scene.RequestModuleInterface<IEventQueue>(); 967 IEventQueue eq = agent.Scene.RequestModuleInterface<IEventQueue>();
949 if (eq != null) 968 IPEndPoint neighbourExternal = neighbourRegion.ExternalEndPoint;
950 { 969 if (neighbourExternal != null)
951 eq.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint,
952 capsPath, agent.UUID, agent.ControllingClient.SessionId);
953 }
954 else
955 { 970 {
956 agent.ControllingClient.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint, 971 if (eq != null)
957 capsPath); 972 {
973 eq.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourExternal,
974 capsPath, agent.UUID, agent.ControllingClient.SessionId);
975 }
976 else
977 {
978 agent.ControllingClient.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourExternal,
979 capsPath);
980 }
958 } 981 }
959 982
960 if (!WaitForCallback(agent.UUID)) 983 if (!WaitForCallback(agent.UUID))
@@ -1066,10 +1089,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1066 agent.Id0 = currentAgentCircuit.Id0; 1089 agent.Id0 = currentAgentCircuit.Id0;
1067 } 1090 }
1068 1091
1069 InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync; 1092 IPEndPoint external = region.ExternalEndPoint;
1070 d.BeginInvoke(sp, agent, region, region.ExternalEndPoint, true, 1093 if (external != null)
1094 {
1095 InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync;
1096 d.BeginInvoke(sp, agent, region, external, true,
1071 InformClientOfNeighbourCompleted, 1097 InformClientOfNeighbourCompleted,
1072 d); 1098 d);
1099 }
1073 } 1100 }
1074 #endregion 1101 #endregion
1075 1102
@@ -1202,6 +1229,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1202 InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync; 1229 InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync;
1203 try 1230 try
1204 { 1231 {
1232 //neighbour.ExternalEndPoint may return null, which will be caught
1205 d.BeginInvoke(sp, cagents[count], neighbour, neighbour.ExternalEndPoint, newAgent, 1233 d.BeginInvoke(sp, cagents[count], neighbour, neighbour.ExternalEndPoint, newAgent,
1206 InformClientOfNeighbourCompleted, 1234 InformClientOfNeighbourCompleted,
1207 d); 1235 d);
@@ -1305,8 +1333,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1305 1333
1306 m_log.Debug("[ENTITY TRANSFER MODULE]: Completed inform client about neighbour " + endPoint.ToString()); 1334 m_log.Debug("[ENTITY TRANSFER MODULE]: Completed inform client about neighbour " + endPoint.ToString());
1307 } 1335 }
1308 if (!regionAccepted)
1309 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Region {0} did not accept agent: {1}", reg.RegionName, reason);
1310 } 1336 }
1311 1337
1312 /// <summary> 1338 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
index 4d77ef4..8858ad5 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
@@ -86,7 +86,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
86 86
87 protected override void OnNewClient(IClientAPI client) 87 protected override void OnNewClient(IClientAPI client)
88 { 88 {
89 client.OnTeleportHomeRequest += TeleportHome; 89 client.OnTeleportHomeRequest += TriggerTeleportHome;
90 client.OnTeleportLandmarkRequest += RequestTeleportLandmark; 90 client.OnTeleportLandmarkRequest += RequestTeleportLandmark;
91 client.OnConnectionClosed += new Action<IClientAPI>(OnConnectionClosed); 91 client.OnConnectionClosed += new Action<IClientAPI>(OnConnectionClosed);
92 } 92 }
@@ -181,7 +181,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
181 return m_aScene.SimulationService.CreateAgent(reg, agentCircuit, teleportFlags, out reason); 181 return m_aScene.SimulationService.CreateAgent(reg, agentCircuit, teleportFlags, out reason);
182 } 182 }
183 183
184 public override void TeleportHome(UUID id, IClientAPI client) 184 public void TriggerTeleportHome(UUID id, IClientAPI client)
185 {
186 TeleportHome(id, client);
187 }
188
189 public override bool TeleportHome(UUID id, IClientAPI client)
185 { 190 {
186 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Request to teleport {0} {1} home", client.FirstName, client.LastName); 191 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Request to teleport {0} {1} home", client.FirstName, client.LastName);
187 192
@@ -191,8 +196,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
191 { 196 {
192 // local grid user 197 // local grid user
193 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: User is local"); 198 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: User is local");
194 base.TeleportHome(id, client); 199 return base.TeleportHome(id, client);
195 return;
196 } 200 }
197 201
198 // Foreign user wants to go home 202 // Foreign user wants to go home
@@ -202,7 +206,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
202 { 206 {
203 client.SendTeleportFailed("Your information has been lost"); 207 client.SendTeleportFailed("Your information has been lost");
204 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Unable to locate agent's gateway information"); 208 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Unable to locate agent's gateway information");
205 return; 209 return false;
206 } 210 }
207 211
208 IUserAgentService userAgentService = new UserAgentServiceConnector(aCircuit.ServiceURLs["HomeURI"].ToString()); 212 IUserAgentService userAgentService = new UserAgentServiceConnector(aCircuit.ServiceURLs["HomeURI"].ToString());
@@ -212,7 +216,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
212 { 216 {
213 client.SendTeleportFailed("Your home region could not be found"); 217 client.SendTeleportFailed("Your home region could not be found");
214 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Agent's home region not found"); 218 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Agent's home region not found");
215 return; 219 return false;
216 } 220 }
217 221
218 ScenePresence sp = ((Scene)(client.Scene)).GetScenePresence(client.AgentId); 222 ScenePresence sp = ((Scene)(client.Scene)).GetScenePresence(client.AgentId);
@@ -220,7 +224,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
220 { 224 {
221 client.SendTeleportFailed("Internal error"); 225 client.SendTeleportFailed("Internal error");
222 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Agent not found in the scene where it is supposed to be"); 226 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Agent not found in the scene where it is supposed to be");
223 return; 227 return false;
224 } 228 }
225 229
226 IEventQueue eq = sp.Scene.RequestModuleInterface<IEventQueue>(); 230 IEventQueue eq = sp.Scene.RequestModuleInterface<IEventQueue>();
@@ -230,6 +234,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
230 aCircuit.firstname, aCircuit.lastname, finalDestination.RegionName, homeGatekeeper.ExternalHostName, homeGatekeeper.HttpPort, homeGatekeeper.RegionName); 234 aCircuit.firstname, aCircuit.lastname, finalDestination.RegionName, homeGatekeeper.ExternalHostName, homeGatekeeper.HttpPort, homeGatekeeper.RegionName);
231 235
232 DoTeleport(sp, homeGatekeeper, finalDestination, position, lookAt, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome), eq); 236 DoTeleport(sp, homeGatekeeper, finalDestination, position, lookAt, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome), eq);
237 return true;
233 } 238 }
234 239
235 /// <summary> 240 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index 2930303..7bad814 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -325,7 +325,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
325 } 325 }
326 } 326 }
327 327
328 // This is method scoped and will be returned. It will be the 328 // This is pethod scoped and will be returned. It will be the
329 // last created asset id 329 // last created asset id
330 UUID assetID = UUID.Zero; 330 UUID assetID = UUID.Zero;
331 331
@@ -354,6 +354,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
354 CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero); 354 CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero);
355 Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>(); 355 Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>();
356 356
357 Dictionary<UUID, string> xmlStrings =
358 new Dictionary<UUID, string>();
359
357 foreach (SceneObjectGroup objectGroup in objlist) 360 foreach (SceneObjectGroup objectGroup in objlist)
358 { 361 {
359 Vector3 inventoryStoredPosition = new Vector3 362 Vector3 inventoryStoredPosition = new Vector3
@@ -366,7 +369,12 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
366 : objectGroup.AbsolutePosition.Y, 369 : objectGroup.AbsolutePosition.Y,
367 objectGroup.AbsolutePosition.Z); 370 objectGroup.AbsolutePosition.Z);
368 371
369 originalPositions[objectGroup.UUID] = objectGroup.AbsolutePosition; 372 Vector3 originalPosition = objectGroup.AbsolutePosition;
373
374 // Restore attachment data after trip through the sim
375 if (objectGroup.RootPart.AttachPoint > 0)
376 inventoryStoredPosition = objectGroup.RootPart.AttachOffset;
377 objectGroup.RootPart.Shape.State = objectGroup.RootPart.AttachPoint;
370 378
371 objectGroup.AbsolutePosition = inventoryStoredPosition; 379 objectGroup.AbsolutePosition = inventoryStoredPosition;
372 380
@@ -380,159 +388,60 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
380 (uint)PermissionMask.Modify); 388 (uint)PermissionMask.Modify);
381 objectGroup.RootPart.NextOwnerMask |= 389 objectGroup.RootPart.NextOwnerMask |=
382 (uint)PermissionMask.Move; 390 (uint)PermissionMask.Move;
383
384 coa.Add(objectGroup);
385 }
386 391
387 string itemXml; 392 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(objectGroup);
388 393
389 if (objlist.Count > 1) 394 objectGroup.AbsolutePosition = originalPosition;
390 itemXml = CoalescedSceneObjectsSerializer.ToXml(coa);
391 else
392 itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0]);
393
394 // Restore the position of each group now that it has been stored to inventory.
395 foreach (SceneObjectGroup objectGroup in objlist)
396 objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID];
397 395
398 InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID); 396 xmlStrings[objectGroup.UUID] = sceneObjectXml;
399 if (item == null)
400 return UUID.Zero;
401
402 // Can't know creator is the same, so null it in inventory
403 if (objlist.Count > 1)
404 {
405 item.CreatorId = UUID.Zero.ToString();
406 item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems;
407 } 397 }
408 else
409 {
410 item.CreatorId = objlist[0].RootPart.CreatorID.ToString();
411 item.SaleType = objlist[0].RootPart.ObjectSaleType;
412 item.SalePrice = objlist[0].RootPart.SalePrice;
413 }
414 398
415 AssetBase asset = CreateAsset( 399 string itemXml;
416 objlist[0].GetPartName(objlist[0].RootPart.LocalId),
417 objlist[0].GetPartDescription(objlist[0].RootPart.LocalId),
418 (sbyte)AssetType.Object,
419 Utils.StringToBytes(itemXml),
420 objlist[0].OwnerID.ToString());
421 m_Scene.AssetService.Store(asset);
422
423 item.AssetID = asset.FullID;
424 assetID = asset.FullID;
425 400
426 if (DeRezAction.SaveToExistingUserInventoryItem == action) 401 if (objlist.Count > 1)
427 {
428 m_Scene.InventoryService.UpdateItem(item);
429 }
430 else
431 { 402 {
432 AddPermissions(item, objlist[0], objlist, remoteClient); 403 float minX, minY, minZ;
404 float maxX, maxY, maxZ;
433 405
434 item.CreationDate = Util.UnixTimeSinceEpoch(); 406 Vector3[] offsets = Scene.GetCombinedBoundingBox(objlist,
435 item.Description = asset.Description; 407 out minX, out maxX, out minY, out maxY,
436 item.Name = asset.Name; 408 out minZ, out maxZ);
437 item.AssetType = asset.Type;
438 409
439 m_Scene.AddInventoryItem(item); 410 // CreateWrapper
411 XmlDocument itemDoc = new XmlDocument();
412 XmlElement root = itemDoc.CreateElement("", "CoalescedObject", "");
413 itemDoc.AppendChild(root);
440 414
441 if (remoteClient != null && item.Owner == remoteClient.AgentId) 415 // Embed the offsets into the group XML
442 { 416 for ( int i = 0 ; i < objlist.Count ; i++ )
443 remoteClient.SendInventoryItemCreateUpdate(item, 0);
444 }
445 else
446 { 417 {
447 ScenePresence notifyUser = m_Scene.GetScenePresence(item.Owner); 418 XmlDocument doc = new XmlDocument();
448 if (notifyUser != null) 419 SceneObjectGroup g = objlist[i];
449 { 420 doc.LoadXml(xmlStrings[g.UUID]);
450 notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0); 421 XmlElement e = (XmlElement)doc.SelectSingleNode("/SceneObjectGroup");
451 } 422 e.SetAttribute("offsetx", offsets[i].X.ToString());
423 e.SetAttribute("offsety", offsets[i].Y.ToString());
424 e.SetAttribute("offsetz", offsets[i].Z.ToString());
425
426 XmlNode objectNode = itemDoc.ImportNode(e, true);
427 root.AppendChild(objectNode);
452 } 428 }
453 }
454
455 // This is a hook to do some per-asset post-processing for subclasses that need that
456 if (remoteClient != null)
457 ExportAsset(remoteClient.AgentId, assetID);
458
459 return assetID;
460 }
461 429
462 protected virtual void ExportAsset(UUID agentID, UUID assetID) 430 float sizeX = maxX - minX;
463 { 431 float sizeY = maxY - minY;
464 // nothing to do here 432 float sizeZ = maxZ - minZ;
465 }
466 433
467 /// <summary> 434 root.SetAttribute("x", sizeX.ToString());
468 /// Add relevant permissions for an object to the item. 435 root.SetAttribute("y", sizeY.ToString());
469 /// </summary> 436 root.SetAttribute("z", sizeZ.ToString());
470 /// <param name="item"></param>
471 /// <param name="so"></param>
472 /// <param name="objsForEffectivePermissions"></param>
473 /// <param name="remoteClient"></param>
474 /// <returns></returns>
475 protected InventoryItemBase AddPermissions(
476 InventoryItemBase item, SceneObjectGroup so, List<SceneObjectGroup> objsForEffectivePermissions,
477 IClientAPI remoteClient)
478 {
479 uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move) | 7;
480 foreach (SceneObjectGroup grp in objsForEffectivePermissions)
481 effectivePerms &= grp.GetEffectivePermissions();
482 effectivePerms |= (uint)PermissionMask.Move;
483 437
484 if (remoteClient != null && (remoteClient.AgentId != so.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions()) 438 itemXml = itemDoc.InnerXml;
485 {
486 uint perms = effectivePerms;
487 uint nextPerms = (perms & 7) << 13;
488 if ((nextPerms & (uint)PermissionMask.Copy) == 0)
489 perms &= ~(uint)PermissionMask.Copy;
490 if ((nextPerms & (uint)PermissionMask.Transfer) == 0)
491 perms &= ~(uint)PermissionMask.Transfer;
492 if ((nextPerms & (uint)PermissionMask.Modify) == 0)
493 perms &= ~(uint)PermissionMask.Modify;
494
495 item.BasePermissions = perms & so.RootPart.NextOwnerMask;
496 item.CurrentPermissions = item.BasePermissions;
497 item.NextPermissions = perms & so.RootPart.NextOwnerMask;
498 item.EveryOnePermissions = so.RootPart.EveryoneMask & so.RootPart.NextOwnerMask;
499 item.GroupPermissions = so.RootPart.GroupMask & so.RootPart.NextOwnerMask;
500
501 // Magic number badness. Maybe this deserves an enum.
502 // bit 4 (16) is the "Slam" bit, it means treat as passed
503 // and apply next owner perms on rez
504 item.CurrentPermissions |= 16; // Slam!
505 } 439 }
506 else 440 else
507 { 441 {
508 item.BasePermissions = effectivePerms; 442 itemXml = xmlStrings[objlist[0].UUID];
509 item.CurrentPermissions = effectivePerms; 443 }
510 item.NextPermissions = so.RootPart.NextOwnerMask & effectivePerms;
511 item.EveryOnePermissions = so.RootPart.EveryoneMask & effectivePerms;
512 item.GroupPermissions = so.RootPart.GroupMask & effectivePerms;
513 444
514 item.CurrentPermissions &=
515 ((uint)PermissionMask.Copy |
516 (uint)PermissionMask.Transfer |
517 (uint)PermissionMask.Modify |
518 (uint)PermissionMask.Move |
519 7); // Preserve folded permissions
520 }
521
522 return item;
523 }
524
525 /// <summary>
526 /// Create an item using details for the given scene object.
527 /// </summary>
528 /// <param name="action"></param>
529 /// <param name="remoteClient"></param>
530 /// <param name="so"></param>
531 /// <param name="folderID"></param>
532 /// <returns></returns>
533 protected InventoryItemBase CreateItemForObject(
534 DeRezAction action, IClientAPI remoteClient, SceneObjectGroup so, UUID folderID)
535 {
536 // Get the user info of the item destination 445 // Get the user info of the item destination
537 // 446 //
538 UUID userID = UUID.Zero; 447 UUID userID = UUID.Zero;
@@ -544,7 +453,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
544 // Saving changes requires a local user 453 // Saving changes requires a local user
545 // 454 //
546 if (remoteClient == null) 455 if (remoteClient == null)
547 return null; 456 return UUID.Zero;
548 457
549 userID = remoteClient.AgentId; 458 userID = remoteClient.AgentId;
550 } 459 }
@@ -552,12 +461,13 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
552 { 461 {
553 // All returns / deletes go to the object owner 462 // All returns / deletes go to the object owner
554 // 463 //
555 userID = so.RootPart.OwnerID; 464
465 userID = objlist[0].RootPart.OwnerID;
556 } 466 }
557 467
558 if (userID == UUID.Zero) // Can't proceed 468 if (userID == UUID.Zero) // Can't proceed
559 { 469 {
560 return null; 470 return UUID.Zero;
561 } 471 }
562 472
563 // If we're returning someone's item, it goes back to the 473 // If we're returning someone's item, it goes back to the
@@ -565,13 +475,13 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
565 // Delete is treated like return in this case 475 // Delete is treated like return in this case
566 // Deleting your own items makes them go to trash 476 // Deleting your own items makes them go to trash
567 // 477 //
568 478
569 InventoryFolderBase folder = null; 479 InventoryFolderBase folder = null;
570 InventoryItemBase item = null; 480 InventoryItemBase item = null;
571 481
572 if (DeRezAction.SaveToExistingUserInventoryItem == action) 482 if (DeRezAction.SaveToExistingUserInventoryItem == action)
573 { 483 {
574 item = new InventoryItemBase(so.RootPart.FromUserInventoryItemID, userID); 484 item = new InventoryItemBase(objlist[0].RootPart.FromUserInventoryItemID, userID);
575 item = m_Scene.InventoryService.GetItem(item); 485 item = m_Scene.InventoryService.GetItem(item);
576 486
577 //item = userInfo.RootFolder.FindItem( 487 //item = userInfo.RootFolder.FindItem(
@@ -581,9 +491,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
581 { 491 {
582 m_log.DebugFormat( 492 m_log.DebugFormat(
583 "[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.", 493 "[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.",
584 so.Name, so.UUID); 494 objlist[0].Name, objlist[0].UUID);
585 495 return UUID.Zero;
586 return null;
587 } 496 }
588 } 497 }
589 else 498 else
@@ -595,17 +504,19 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
595 // Deleting someone else's item 504 // Deleting someone else's item
596 // 505 //
597 if (remoteClient == null || 506 if (remoteClient == null ||
598 so.OwnerID != remoteClient.AgentId) 507 objlist[0].OwnerID != remoteClient.AgentId)
599 { 508 {
509
600 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); 510 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
601 } 511 }
602 else 512 else
603 { 513 {
604 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); 514 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder);
605 } 515 }
606 } 516 }
607 else if (action == DeRezAction.Return) 517 else if (action == DeRezAction.Return)
608 { 518 {
519
609 // Dump to lost + found unconditionally 520 // Dump to lost + found unconditionally
610 // 521 //
611 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); 522 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
@@ -621,7 +532,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
621 } 532 }
622 else 533 else
623 { 534 {
624 if (remoteClient == null || so.OwnerID != remoteClient.AgentId) 535 if (remoteClient == null ||
536 objlist[0].OwnerID != remoteClient.AgentId)
625 { 537 {
626 // Taking copy of another person's item. Take to 538 // Taking copy of another person's item. Take to
627 // Objects folder. 539 // Objects folder.
@@ -642,9 +554,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
642 // 554 //
643 if (action == DeRezAction.Take || action == DeRezAction.TakeCopy) 555 if (action == DeRezAction.Take || action == DeRezAction.TakeCopy)
644 { 556 {
645 if (so.RootPart.FromFolderID != UUID.Zero) 557 if (objlist[0].RootPart.FromFolderID != UUID.Zero && objlist[0].OwnerID == remoteClient.AgentId)
646 { 558 {
647 InventoryFolderBase f = new InventoryFolderBase(so.RootPart.FromFolderID, userID); 559 InventoryFolderBase f = new InventoryFolderBase(objlist[0].RootPart.FromFolderID, userID);
648 folder = m_Scene.InventoryService.GetFolder(f); 560 folder = m_Scene.InventoryService.GetFolder(f);
649 } 561 }
650 } 562 }
@@ -655,27 +567,133 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
655 567
656 if (folder == null) // Nowhere to put it 568 if (folder == null) // Nowhere to put it
657 { 569 {
658 return null; 570 return UUID.Zero;
659 } 571 }
660 } 572 }
661 573
662 item = new InventoryItemBase(); 574 item = new InventoryItemBase();
575 // Can't know creator is the same, so null it in inventory
576 if (objlist.Count > 1)
577 {
578 item.CreatorId = UUID.Zero.ToString();
579 item.CreatorData = String.Empty;
580 }
581 else
582 {
583 item.CreatorId = objlist[0].RootPart.CreatorID.ToString();
584 item.CreatorData = objlist[0].RootPart.CreatorData;
585 }
663 item.ID = UUID.Random(); 586 item.ID = UUID.Random();
664 item.InvType = (int)InventoryType.Object; 587 item.InvType = (int)InventoryType.Object;
665 item.Folder = folder.ID; 588 item.Folder = folder.ID;
666 item.Owner = userID; 589 item.Owner = userID;
667 } 590 if (objlist.Count > 1)
591 {
592 item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems;
593 }
594 else
595 {
596 item.SaleType = objlist[0].RootPart.ObjectSaleType;
597 item.SalePrice = objlist[0].RootPart.SalePrice;
598 }
599 }
600
601 AssetBase asset = CreateAsset(
602 objlist[0].GetPartName(objlist[0].RootPart.LocalId),
603 objlist[0].GetPartDescription(objlist[0].RootPart.LocalId),
604 (sbyte)AssetType.Object,
605 Utils.StringToBytes(itemXml),
606 objlist[0].OwnerID.ToString());
607 m_Scene.AssetService.Store(asset);
608 assetID = asset.FullID;
609
610 if (DeRezAction.SaveToExistingUserInventoryItem == action)
611 {
612 item.AssetID = asset.FullID;
613 m_Scene.InventoryService.UpdateItem(item);
614 }
615 else
616 {
617 item.AssetID = asset.FullID;
618
619 uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move) | 7;
620 foreach (SceneObjectGroup grp in objlist)
621 effectivePerms &= grp.GetEffectivePermissions();
622 effectivePerms |= (uint)PermissionMask.Move;
623
624 if (remoteClient != null && (remoteClient.AgentId != objlist[0].RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions())
625 {
626 uint perms = effectivePerms;
627 uint nextPerms = (perms & 7) << 13;
628 if ((nextPerms & (uint)PermissionMask.Copy) == 0)
629 perms &= ~(uint)PermissionMask.Copy;
630 if ((nextPerms & (uint)PermissionMask.Transfer) == 0)
631 perms &= ~(uint)PermissionMask.Transfer;
632 if ((nextPerms & (uint)PermissionMask.Modify) == 0)
633 perms &= ~(uint)PermissionMask.Modify;
634
635 item.BasePermissions = perms & objlist[0].RootPart.NextOwnerMask;
636 item.CurrentPermissions = item.BasePermissions;
637 item.NextPermissions = perms & objlist[0].RootPart.NextOwnerMask;
638 item.EveryOnePermissions = objlist[0].RootPart.EveryoneMask & objlist[0].RootPart.NextOwnerMask;
639 item.GroupPermissions = objlist[0].RootPart.GroupMask & objlist[0].RootPart.NextOwnerMask;
640
641 item.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm;
642 }
643 else
644 {
645 item.BasePermissions = effectivePerms;
646 item.CurrentPermissions = effectivePerms;
647 item.NextPermissions = objlist[0].RootPart.NextOwnerMask & effectivePerms;
648 item.EveryOnePermissions = objlist[0].RootPart.EveryoneMask & effectivePerms;
649 item.GroupPermissions = objlist[0].RootPart.GroupMask & effectivePerms;
650
651 item.CurrentPermissions &=
652 ((uint)PermissionMask.Copy |
653 (uint)PermissionMask.Transfer |
654 (uint)PermissionMask.Modify |
655 (uint)PermissionMask.Move |
656 7); // Preserve folded permissions
657 }
658
659 item.CreationDate = Util.UnixTimeSinceEpoch();
660 item.Description = asset.Description;
661 item.Name = asset.Name;
662 item.AssetType = asset.Type;
663
664 m_Scene.AddInventoryItem(item);
665
666 if (remoteClient != null && item.Owner == remoteClient.AgentId)
667 {
668 remoteClient.SendInventoryItemCreateUpdate(item, 0);
669 }
670 else
671 {
672 ScenePresence notifyUser = m_Scene.GetScenePresence(item.Owner);
673 if (notifyUser != null)
674 {
675 notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0);
676 }
677 }
678 }
679
680 // This is a hook to do some per-asset post-processing for subclasses that need that
681 if (remoteClient != null)
682 ExportAsset(remoteClient.AgentId, assetID);
668 683
669 return item; 684 return assetID;
685 }
686
687 protected virtual void ExportAsset(UUID agentID, UUID assetID)
688 {
689 // nothing to do here
670 } 690 }
671 691
672 /// <summary> 692 /// <summary>
673 /// Rez an object into the scene from the user's inventory 693 /// Rez an object into the scene from the user's inventory
674 /// </summary> 694 /// </summary>
675 /// <remarks>
676 /// FIXME: It would be really nice if inventory access modules didn't also actually do the work of rezzing 695 /// FIXME: It would be really nice if inventory access modules didn't also actually do the work of rezzing
677 /// things to the scene. The caller should be doing that, I think. 696 /// things to the scene. The caller should be doing that, I think.
678 /// </remarks>
679 /// <param name="remoteClient"></param> 697 /// <param name="remoteClient"></param>
680 /// <param name="itemID"></param> 698 /// <param name="itemID"></param>
681 /// <param name="RayEnd"></param> 699 /// <param name="RayEnd"></param>
@@ -692,10 +710,21 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
692 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, 710 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
693 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) 711 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
694 { 712 {
695// m_log.DebugFormat("[INVENTORY ACCESS MODULE]: RezObject for {0}, item {1}", remoteClient.Name, itemID); 713 // Work out position details
696 714 byte bRayEndIsIntersection = (byte)0;
697 byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0); 715
716 if (RayEndIsIntersection)
717 {
718 bRayEndIsIntersection = (byte)1;
719 }
720 else
721 {
722 bRayEndIsIntersection = (byte)0;
723 }
724
698 Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f); 725 Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f);
726
727
699 Vector3 pos = m_Scene.GetNewRezLocation( 728 Vector3 pos = m_Scene.GetNewRezLocation(
700 RayStart, RayEnd, RayTargetID, Quaternion.Identity, 729 RayStart, RayEnd, RayTargetID, Quaternion.Identity,
701 BypassRayCast, bRayEndIsIntersection, true, scale, false); 730 BypassRayCast, bRayEndIsIntersection, true, scale, false);
@@ -706,6 +735,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
706 735
707 if (item != null) 736 if (item != null)
708 { 737 {
738 if (item.ID == UUID.Zero)
739 {
740 m_log.Debug("[InventoryAccessModule]: Inventory object has UUID.Zero! Position 1");
741 }
709 item.Owner = remoteClient.AgentId; 742 item.Owner = remoteClient.AgentId;
710 743
711 AssetBase rezAsset = m_Scene.AssetService.Get(item.AssetID.ToString()); 744 AssetBase rezAsset = m_Scene.AssetService.Get(item.AssetID.ToString());
@@ -734,6 +767,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
734 } 767 }
735 } 768 }
736 769
770 if (item.ID == UUID.Zero)
771 {
772 m_log.Debug("[InventoryAccessModule]: Inventory object has UUID.Zero! Position 2");
773 }
774
737 string xmlData = Utils.BytesToString(rezAsset.Data); 775 string xmlData = Utils.BytesToString(rezAsset.Data);
738 List<SceneObjectGroup> objlist = 776 List<SceneObjectGroup> objlist =
739 new List<SceneObjectGroup>(); 777 new List<SceneObjectGroup>();
@@ -779,18 +817,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
779 itemId, n.OuterXml); 817 itemId, n.OuterXml);
780 objlist.Add(g); 818 objlist.Add(g);
781 XmlElement el = (XmlElement)n; 819 XmlElement el = (XmlElement)n;
782 820 float x = Convert.ToSingle(el.GetAttribute("offsetx"));
783 string rawX = el.GetAttribute("offsetx"); 821 float y = Convert.ToSingle(el.GetAttribute("offsety"));
784 string rawY = el.GetAttribute("offsety"); 822 float z = Convert.ToSingle(el.GetAttribute("offsetz"));
785 string rawZ = el.GetAttribute("offsetz");
786//
787// m_log.DebugFormat(
788// "[INVENTORY ACCESS MODULE]: Converting coalesced object {0} offset <{1}, {2}, {3}>",
789// g.Name, rawX, rawY, rawZ);
790
791 float x = Convert.ToSingle(rawX);
792 float y = Convert.ToSingle(rawY);
793 float z = Convert.ToSingle(rawZ);
794 veclist.Add(new Vector3(x, y, z)); 823 veclist.Add(new Vector3(x, y, z));
795 } 824 }
796 } 825 }
@@ -833,21 +862,27 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
833 foreach (SceneObjectPart child in group.Parts) 862 foreach (SceneObjectPart child in group.Parts)
834 child.CreateSelected = true; 863 child.CreateSelected = true;
835 } 864 }
865
836 group.ResetIDs(); 866 group.ResetIDs();
837 867
838 if (attachment) 868 if (attachment)
839 { 869 {
840 group.RootPart.Flags |= PrimFlags.Phantom; 870 group.RootPart.Flags |= PrimFlags.Phantom;
841 group.RootPart.IsAttachment = true; 871 group.RootPart.IsAttachment = true;
842 }
843 872
844 // If we're rezzing an attachment then don't ask 873 // If we're rezzing an attachment then don't ask
845 // AddNewSceneObject() to update the client since 874 // AddNewSceneObject() to update the client since
846 // we'll be doing that later on. Scheduling more than 875 // we'll be doing that later on. Scheduling more
847 // one full update during the attachment 876 // than one full update during the attachment
848 // process causes some clients to fail to display the 877 // process causes some clients to fail to display
849 // attachment properly. 878 // the attachment properly.
850 m_Scene.AddNewSceneObject(group, true, false); 879 // Also, don't persist attachments.
880 m_Scene.AddNewSceneObject(group, false, false);
881 }
882 else
883 {
884 m_Scene.AddNewSceneObject(group, true, false);
885 }
851 886
852 // if attachment we set it's asset id so object updates 887 // if attachment we set it's asset id so object updates
853 // can reflect that, if not, we set it's position in world. 888 // can reflect that, if not, we set it's position in world.
@@ -882,19 +917,24 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
882 // affect the name stored in the serialization, transfer 917 // affect the name stored in the serialization, transfer
883 // the correct name from the inventory to the 918 // the correct name from the inventory to the
884 // object itself before we rez. 919 // object itself before we rez.
885 // 920 // On coalesced objects, do the first one
886 // Only do these for the first object if we are rezzing a coalescence. 921 if (((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) || i == 0)
887 if (i == 0)
888 { 922 {
889 rootPart.Name = item.Name; 923 rootPart.Name = item.Name;
890 rootPart.Description = item.Description; 924 rootPart.Description = item.Description;
925 }
926 if ((item.Flags & (uint)InventoryItemFlags.ObjectSlamSale) != 0)
927 {
891 rootPart.ObjectSaleType = item.SaleType; 928 rootPart.ObjectSaleType = item.SaleType;
892 rootPart.SalePrice = item.SalePrice; 929 rootPart.SalePrice = item.SalePrice;
893 } 930 }
894 931
895 group.SetGroup(remoteClient.ActiveGroupId, remoteClient); 932 group.SetGroup(remoteClient.ActiveGroupId, remoteClient);
933 // TODO: Remove the magic number badness
934
896 if ((rootPart.OwnerID != item.Owner) || 935 if ((rootPart.OwnerID != item.Owner) ||
897 (item.CurrentPermissions & 16) != 0) 936 (item.CurrentPermissions & 16) != 0 || // Magic number
937 (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0)
898 { 938 {
899 //Need to kill the for sale here 939 //Need to kill the for sale here
900 rootPart.ObjectSaleType = 0; 940 rootPart.ObjectSaleType = 0;
@@ -906,28 +946,34 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
906 { 946 {
907 if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) 947 if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0)
908 { 948 {
909 part.EveryoneMask = item.EveryOnePermissions; 949 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
910 part.NextOwnerMask = item.NextPermissions; 950 part.EveryoneMask = item.EveryOnePermissions;
951 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
952 part.NextOwnerMask = item.NextPermissions;
953 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
954 part.GroupMask = item.GroupPermissions;
911 } 955 }
912 part.GroupMask = 0; // DO NOT propagate here
913 } 956 }
914 957
958 foreach (SceneObjectPart part in group.Parts)
959 {
960 part.LastOwnerID = part.OwnerID;
961 part.OwnerID = item.Owner;
962 part.Inventory.ChangeInventoryOwner(item.Owner);
963 }
964
915 group.ApplyNextOwnerPermissions(); 965 group.ApplyNextOwnerPermissions();
916 } 966 }
917 } 967 }
918 968
919 foreach (SceneObjectPart part in group.Parts) 969 foreach (SceneObjectPart part in group.Parts)
920 { 970 {
921 if ((part.OwnerID != item.Owner) || 971 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
922 (item.CurrentPermissions & 16) != 0) 972 part.EveryoneMask = item.EveryOnePermissions;
923 { 973 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
924 part.LastOwnerID = part.OwnerID; 974 part.NextOwnerMask = item.NextPermissions;
925 part.OwnerID = item.Owner; 975 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
926 part.Inventory.ChangeInventoryOwner(item.Owner); 976 part.GroupMask = item.GroupPermissions;
927 part.GroupMask = 0; // DO NOT propagate here
928 }
929 part.EveryoneMask = item.EveryOnePermissions;
930 part.NextOwnerMask = item.NextPermissions;
931 } 977 }
932 978
933 rootPart.TrimPermissions(); 979 rootPart.TrimPermissions();
@@ -935,7 +981,13 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
935 if (!attachment) 981 if (!attachment)
936 { 982 {
937 if (group.RootPart.Shape.PCode == (byte)PCode.Prim) 983 if (group.RootPart.Shape.PCode == (byte)PCode.Prim)
984 {
985 // Save attachment data
986 group.RootPart.AttachPoint = group.RootPart.Shape.State;
987 group.RootPart.AttachOffset = storedPosition;
988
938 group.ClearPartAttachmentData(); 989 group.ClearPartAttachmentData();
990 }
939 991
940 // Fire on_rez 992 // Fire on_rez
941 group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 1); 993 group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 1);
diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
index 43672d1..5e28ee1 100644
--- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
@@ -366,6 +366,10 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
366 try 366 try
367 { 367 {
368 Request = (HttpWebRequest) WebRequest.Create(Url); 368 Request = (HttpWebRequest) WebRequest.Create(Url);
369
370 //This works around some buggy HTTP Servers like Lighttpd
371 Request.ServicePoint.Expect100Continue = false;
372
369 Request.Method = HttpMethod; 373 Request.Method = HttpMethod;
370 Request.ContentType = HttpMIMEType; 374 Request.ContentType = HttpMIMEType;
371 375
@@ -440,7 +444,17 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
440 { 444 {
441 HttpWebResponse webRsp = (HttpWebResponse)((WebException)e).Response; 445 HttpWebResponse webRsp = (HttpWebResponse)((WebException)e).Response;
442 Status = (int)webRsp.StatusCode; 446 Status = (int)webRsp.StatusCode;
443 ResponseBody = webRsp.StatusDescription; 447 try
448 {
449 using (Stream responseStream = webRsp.GetResponseStream())
450 {
451 ResponseBody = responseStream.GetStreamString();
452 }
453 }
454 catch
455 {
456 ResponseBody = webRsp.StatusDescription;
457 }
444 } 458 }
445 else 459 else
446 { 460 {
diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
index a552a28..b6af1f2 100644
--- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
@@ -60,6 +60,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
60 //public ManualResetEvent ev; 60 //public ManualResetEvent ev;
61 public bool requestDone; 61 public bool requestDone;
62 public int startTime; 62 public int startTime;
63 public bool responseSent;
63 public string uri; 64 public string uri;
64 } 65 }
65 66
@@ -76,7 +77,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
76 new Dictionary<string, UrlData>(); 77 new Dictionary<string, UrlData>();
77 78
78 79
79 private int m_TotalUrls = 100; 80 private int m_TotalUrls = 5000;
80 81
81 private uint https_port = 0; 82 private uint https_port = 0;
82 private IHttpServer m_HttpServer = null; 83 private IHttpServer m_HttpServer = null;
@@ -155,7 +156,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
155 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); 156 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" });
156 return urlcode; 157 return urlcode;
157 } 158 }
158 string url = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + "/lslhttp/" + urlcode.ToString() + "/"; 159 string url = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + "/lslhttp/" + urlcode.ToString();
159 160
160 UrlData urlData = new UrlData(); 161 UrlData urlData = new UrlData();
161 urlData.hostID = host.UUID; 162 urlData.hostID = host.UUID;
@@ -165,10 +166,9 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
165 urlData.urlcode = urlcode; 166 urlData.urlcode = urlcode;
166 urlData.requests = new Dictionary<UUID, RequestData>(); 167 urlData.requests = new Dictionary<UUID, RequestData>();
167 168
168
169 m_UrlMap[url] = urlData; 169 m_UrlMap[url] = urlData;
170 170
171 string uri = "/lslhttp/" + urlcode.ToString() + "/"; 171 string uri = "/lslhttp/" + urlcode.ToString();
172 172
173 m_HttpServer.AddPollServiceHTTPHandler(uri,HandleHttpPoll, 173 m_HttpServer.AddPollServiceHTTPHandler(uri,HandleHttpPoll,
174 new PollServiceEventArgs(HttpRequestHandler,HasEvents, GetEvents, NoEvents, 174 new PollServiceEventArgs(HttpRequestHandler,HasEvents, GetEvents, NoEvents,
@@ -233,9 +233,12 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
233 return; 233 return;
234 } 234 }
235 235
236 foreach (UUID req in data.requests.Keys) 236 lock (m_RequestMap)
237 m_RequestMap.Remove(req); 237 {
238 238 foreach (UUID req in data.requests.Keys)
239 m_RequestMap.Remove(req);
240 }
241
239 RemoveUrl(data); 242 RemoveUrl(data);
240 m_UrlMap.Remove(url); 243 m_UrlMap.Remove(url);
241 } 244 }
@@ -243,32 +246,42 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
243 246
244 public void HttpResponse(UUID request, int status, string body) 247 public void HttpResponse(UUID request, int status, string body)
245 { 248 {
246 if (m_RequestMap.ContainsKey(request)) 249 lock (m_RequestMap)
247 {
248 UrlData urlData = m_RequestMap[request];
249 urlData.requests[request].responseCode = status;
250 urlData.requests[request].responseBody = body;
251 //urlData.requests[request].ev.Set();
252 urlData.requests[request].requestDone =true;
253 }
254 else
255 { 250 {
256 m_log.Info("[HttpRequestHandler] There is no http-in request with id " + request.ToString()); 251 if (m_RequestMap.ContainsKey(request))
252 {
253 UrlData urlData = m_RequestMap[request];
254 if (!urlData.requests[request].responseSent)
255 {
256 urlData.requests[request].responseCode = status;
257 urlData.requests[request].responseBody = body;
258 //urlData.requests[request].ev.Set();
259 urlData.requests[request].requestDone = true;
260 urlData.requests[request].responseSent = true;
261 }
262 }
263 else
264 {
265 m_log.Info("[HttpRequestHandler] There is no http-in request with id " + request.ToString());
266 }
257 } 267 }
258 } 268 }
259 269
260 public string GetHttpHeader(UUID requestId, string header) 270 public string GetHttpHeader(UUID requestId, string header)
261 { 271 {
262 if (m_RequestMap.ContainsKey(requestId)) 272 lock (m_RequestMap)
263 {
264 UrlData urlData=m_RequestMap[requestId];
265 string value;
266 if (urlData.requests[requestId].headers.TryGetValue(header,out value))
267 return value;
268 }
269 else
270 { 273 {
271 m_log.Warn("[HttpRequestHandler] There was no http-in request with id " + requestId); 274 if (m_RequestMap.ContainsKey(requestId))
275 {
276 UrlData urlData = m_RequestMap[requestId];
277 string value;
278 if (urlData.requests[requestId].headers.TryGetValue(header, out value))
279 return value;
280 }
281 else
282 {
283 m_log.Warn("[HttpRequestHandler] There was no http-in request with id " + requestId);
284 }
272 } 285 }
273 return String.Empty; 286 return String.Empty;
274 } 287 }
@@ -290,8 +303,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
290 { 303 {
291 RemoveUrl(url.Value); 304 RemoveUrl(url.Value);
292 removeURLs.Add(url.Key); 305 removeURLs.Add(url.Key);
293 foreach (UUID req in url.Value.requests.Keys) 306 lock (m_RequestMap)
294 m_RequestMap.Remove(req); 307 {
308 foreach (UUID req in url.Value.requests.Keys)
309 m_RequestMap.Remove(req);
310 }
295 } 311 }
296 } 312 }
297 313
@@ -312,8 +328,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
312 { 328 {
313 RemoveUrl(url.Value); 329 RemoveUrl(url.Value);
314 removeURLs.Add(url.Key); 330 removeURLs.Add(url.Key);
315 foreach (UUID req in url.Value.requests.Keys) 331 lock (m_RequestMap)
316 m_RequestMap.Remove(req); 332 {
333 foreach (UUID req in url.Value.requests.Keys)
334 m_RequestMap.Remove(req);
335 }
317 } 336 }
318 } 337 }
319 338
@@ -332,14 +351,16 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
332 { 351 {
333 Hashtable response = new Hashtable(); 352 Hashtable response = new Hashtable();
334 UrlData url; 353 UrlData url;
354 int startTime = 0;
335 lock (m_RequestMap) 355 lock (m_RequestMap)
336 { 356 {
337 if (!m_RequestMap.ContainsKey(requestID)) 357 if (!m_RequestMap.ContainsKey(requestID))
338 return response; 358 return response;
339 url = m_RequestMap[requestID]; 359 url = m_RequestMap[requestID];
360 startTime = url.requests[requestID].startTime;
340 } 361 }
341 362
342 if (System.Environment.TickCount - url.requests[requestID].startTime > 25000) 363 if (System.Environment.TickCount - startTime > 25000)
343 { 364 {
344 response["int_response_code"] = 500; 365 response["int_response_code"] = 500;
345 response["str_response_string"] = "Script timeout"; 366 response["str_response_string"] = "Script timeout";
@@ -348,9 +369,12 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
348 response["reusecontext"] = false; 369 response["reusecontext"] = false;
349 370
350 //remove from map 371 //remove from map
351 lock (url) 372 lock (url.requests)
352 { 373 {
353 url.requests.Remove(requestID); 374 url.requests.Remove(requestID);
375 }
376 lock (m_RequestMap)
377 {
354 m_RequestMap.Remove(requestID); 378 m_RequestMap.Remove(requestID);
355 } 379 }
356 380
@@ -372,22 +396,25 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
372 return false; 396 return false;
373 } 397 }
374 url = m_RequestMap[requestID]; 398 url = m_RequestMap[requestID];
399 }
400 lock (url.requests)
401 {
375 if (!url.requests.ContainsKey(requestID)) 402 if (!url.requests.ContainsKey(requestID))
376 { 403 {
377 return false; 404 return false;
378 } 405 }
406 else
407 {
408 if (System.Environment.TickCount - url.requests[requestID].startTime > 25000)
409 {
410 return true;
411 }
412 if (url.requests[requestID].requestDone)
413 return true;
414 else
415 return false;
416 }
379 } 417 }
380
381 if (System.Environment.TickCount-url.requests[requestID].startTime>25000)
382 {
383 return true;
384 }
385
386 if (url.requests[requestID].requestDone)
387 return true;
388 else
389 return false;
390
391 } 418 }
392 private Hashtable GetEvents(UUID requestID, UUID sessionID, string request) 419 private Hashtable GetEvents(UUID requestID, UUID sessionID, string request)
393 { 420 {
@@ -399,9 +426,12 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
399 if (!m_RequestMap.ContainsKey(requestID)) 426 if (!m_RequestMap.ContainsKey(requestID))
400 return NoEvents(requestID,sessionID); 427 return NoEvents(requestID,sessionID);
401 url = m_RequestMap[requestID]; 428 url = m_RequestMap[requestID];
429 }
430 lock (url.requests)
431 {
402 requestData = url.requests[requestID]; 432 requestData = url.requests[requestID];
403 } 433 }
404 434
405 if (!requestData.requestDone) 435 if (!requestData.requestDone)
406 return NoEvents(requestID,sessionID); 436 return NoEvents(requestID,sessionID);
407 437
@@ -424,14 +454,18 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
424 response["reusecontext"] = false; 454 response["reusecontext"] = false;
425 455
426 //remove from map 456 //remove from map
427 lock (url) 457 lock (url.requests)
428 { 458 {
429 url.requests.Remove(requestID); 459 url.requests.Remove(requestID);
460 }
461 lock (m_RequestMap)
462 {
430 m_RequestMap.Remove(requestID); 463 m_RequestMap.Remove(requestID);
431 } 464 }
432 465
433 return response; 466 return response;
434 } 467 }
468
435 public void HttpRequestHandler(UUID requestID, Hashtable request) 469 public void HttpRequestHandler(UUID requestID, Hashtable request)
436 { 470 {
437 lock (request) 471 lock (request)
@@ -447,8 +481,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
447 481
448 int pos1 = uri.IndexOf("/");// /lslhttp 482 int pos1 = uri.IndexOf("/");// /lslhttp
449 int pos2 = uri.IndexOf("/", pos1 + 1);// /lslhttp/ 483 int pos2 = uri.IndexOf("/", pos1 + 1);// /lslhttp/
450 int pos3 = uri.IndexOf("/", pos2 + 1);// /lslhttp/<UUID>/ 484 int pos3 = pos2 + 37; // /lslhttp/urlcode
451 string uri_tmp = uri.Substring(0, pos3 + 1); 485 string uri_tmp = uri.Substring(0, pos3);
452 //HTTP server code doesn't provide us with QueryStrings 486 //HTTP server code doesn't provide us with QueryStrings
453 string pathInfo; 487 string pathInfo;
454 string queryString; 488 string queryString;
@@ -457,10 +491,21 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
457 pathInfo = uri.Substring(pos3); 491 pathInfo = uri.Substring(pos3);
458 492
459 UrlData url = null; 493 UrlData url = null;
494 string urlkey;
460 if (!is_ssl) 495 if (!is_ssl)
461 url = m_UrlMap["http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri_tmp]; 496 urlkey = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri_tmp;
497 //m_UrlMap[];
462 else 498 else
463 url = m_UrlMap["https://" + m_ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + uri_tmp]; 499 urlkey = "https://" + m_ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + uri_tmp;
500
501 if (m_UrlMap.ContainsKey(urlkey))
502 {
503 url = m_UrlMap[urlkey];
504 }
505 else
506 {
507 m_log.Warn("[HttpRequestHandler]: http-in request failed; no such url: "+urlkey.ToString());
508 }
464 509
465 //for llGetHttpHeader support we need to store original URI here 510 //for llGetHttpHeader support we need to store original URI here
466 //to make x-path-info / x-query-string / x-script-url / x-remote-ip headers 511 //to make x-path-info / x-query-string / x-script-url / x-remote-ip headers
@@ -490,7 +535,14 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
490 if (request.ContainsKey(key)) 535 if (request.ContainsKey(key))
491 { 536 {
492 string val = (String)request[key]; 537 string val = (String)request[key];
493 queryString = queryString + key + "=" + val + "&"; 538 if (key != "")
539 {
540 queryString = queryString + key + "=" + val + "&";
541 }
542 else
543 {
544 queryString = queryString + val + "&";
545 }
494 } 546 }
495 } 547 }
496 if (queryString.Length > 1) 548 if (queryString.Length > 1)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
index c044407..150a4d5 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
@@ -55,9 +55,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests
55 config.Configs["Modules"].Set("GridServices", "LocalGridServicesConnector"); 55 config.Configs["Modules"].Set("GridServices", "LocalGridServicesConnector");
56 config.Configs["GridService"].Set("LocalServiceModule", "OpenSim.Services.GridService.dll:GridService"); 56 config.Configs["GridService"].Set("LocalServiceModule", "OpenSim.Services.GridService.dll:GridService");
57 config.Configs["GridService"].Set("StorageProvider", "OpenSim.Data.Null.dll"); 57 config.Configs["GridService"].Set("StorageProvider", "OpenSim.Data.Null.dll");
58 config.Configs["GridService"].Set("Region_Test_Region_1", "DefaultRegion"); 58 config.Configs["GridService"].Set("Region_Test_Region_1", "DefaultRegion");
59 config.Configs["GridService"].Set("Region_Test_Region_2", "FallbackRegion"); 59 config.Configs["GridService"].Set("Region_Test_Region_2", "FallbackRegion");
60 config.Configs["GridService"].Set("Region_Test_Region_3", "FallbackRegion"); 60 config.Configs["GridService"].Set("Region_Test_Region_3", "FallbackRegion");
61 config.Configs["GridService"].Set("Region_Other_Region_4", "FallbackRegion"); 61 config.Configs["GridService"].Set("Region_Other_Region_4", "FallbackRegion");
62 62
63 m_LocalConnector = new LocalGridServicesConnector(config); 63 m_LocalConnector = new LocalGridServicesConnector(config);
@@ -126,8 +126,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests
126 Assert.IsNotNull(result, "Retrieved GetRegionByName is null"); 126 Assert.IsNotNull(result, "Retrieved GetRegionByName is null");
127 Assert.That(result.RegionName, Is.EqualTo("Test Region 1"), "Retrieved region's name does not match"); 127 Assert.That(result.RegionName, Is.EqualTo("Test Region 1"), "Retrieved region's name does not match");
128 128
129 m_LocalConnector.RegisterRegion(UUID.Zero, r2); 129 m_LocalConnector.RegisterRegion(UUID.Zero, r2);
130 m_LocalConnector.RegisterRegion(UUID.Zero, r3); 130 m_LocalConnector.RegisterRegion(UUID.Zero, r3);
131 m_LocalConnector.RegisterRegion(UUID.Zero, r4); 131 m_LocalConnector.RegisterRegion(UUID.Zero, r4);
132 132
133 result = m_LocalConnector.GetRegionByUUID(UUID.Zero, new UUID(1)); 133 result = m_LocalConnector.GetRegionByUUID(UUID.Zero, new UUID(1));
@@ -152,38 +152,38 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests
152 Assert.IsNotNull(results, "Retrieved GetRegionRange collection is null"); 152 Assert.IsNotNull(results, "Retrieved GetRegionRange collection is null");
153 Assert.That(results.Count, Is.EqualTo(2), "Retrieved neighbour collection is not the number expected"); 153 Assert.That(results.Count, Is.EqualTo(2), "Retrieved neighbour collection is not the number expected");
154 154
155 results = m_LocalConnector.GetDefaultRegions(UUID.Zero); 155 results = m_LocalConnector.GetDefaultRegions(UUID.Zero);
156 Assert.IsNotNull(results, "Retrieved GetDefaultRegions collection is null"); 156 Assert.IsNotNull(results, "Retrieved GetDefaultRegions collection is null");
157 Assert.That(results.Count, Is.EqualTo(1), "Retrieved default regions collection has not the expected size"); 157 Assert.That(results.Count, Is.EqualTo(1), "Retrieved default regions collection has not the expected size");
158 Assert.That(results[0].RegionID, Is.EqualTo(new UUID(1)), "Retrieved default region's UUID does not match"); 158 Assert.That(results[0].RegionID, Is.EqualTo(new UUID(1)), "Retrieved default region's UUID does not match");
159 159
160 results = m_LocalConnector.GetFallbackRegions(UUID.Zero, r1.RegionLocX, r1.RegionLocY); 160 results = m_LocalConnector.GetFallbackRegions(UUID.Zero, r1.RegionLocX, r1.RegionLocY);
161 Assert.IsNotNull(results, "Retrieved GetFallbackRegions collection for region 1 is null"); 161 Assert.IsNotNull(results, "Retrieved GetFallbackRegions collection for region 1 is null");
162 Assert.That(results.Count, Is.EqualTo(3), "Retrieved fallback regions collection for region 1 has not the expected size"); 162 Assert.That(results.Count, Is.EqualTo(3), "Retrieved fallback regions collection for region 1 has not the expected size");
163 Assert.That(results[0].RegionID, Is.EqualTo(new UUID(2)), "Retrieved fallback regions for default region are not in the expected order 2-4-3"); 163 Assert.That(results[0].RegionID, Is.EqualTo(new UUID(2)), "Retrieved fallback regions for default region are not in the expected order 2-4-3");
164 Assert.That(results[1].RegionID, Is.EqualTo(new UUID(4)), "Retrieved fallback regions for default region are not in the expected order 2-4-3"); 164 Assert.That(results[1].RegionID, Is.EqualTo(new UUID(4)), "Retrieved fallback regions for default region are not in the expected order 2-4-3");
165 Assert.That(results[2].RegionID, Is.EqualTo(new UUID(3)), "Retrieved fallback regions for default region are not in the expected order 2-4-3"); 165 Assert.That(results[2].RegionID, Is.EqualTo(new UUID(3)), "Retrieved fallback regions for default region are not in the expected order 2-4-3");
166 166
167 results = m_LocalConnector.GetFallbackRegions(UUID.Zero, r2.RegionLocX, r2.RegionLocY); 167 results = m_LocalConnector.GetFallbackRegions(UUID.Zero, r2.RegionLocX, r2.RegionLocY);
168 Assert.IsNotNull(results, "Retrieved GetFallbackRegions collection for region 2 is null"); 168 Assert.IsNotNull(results, "Retrieved GetFallbackRegions collection for region 2 is null");
169 Assert.That(results.Count, Is.EqualTo(3), "Retrieved fallback regions collection for region 2 has not the expected size"); 169 Assert.That(results.Count, Is.EqualTo(3), "Retrieved fallback regions collection for region 2 has not the expected size");
170 Assert.That(results[0].RegionID, Is.EqualTo(new UUID(2)), "Retrieved fallback regions are not in the expected order 2-4-3"); 170 Assert.That(results[0].RegionID, Is.EqualTo(new UUID(2)), "Retrieved fallback regions are not in the expected order 2-4-3");
171 Assert.That(results[1].RegionID, Is.EqualTo(new UUID(4)), "Retrieved fallback regions are not in the expected order 2-4-3"); 171 Assert.That(results[1].RegionID, Is.EqualTo(new UUID(4)), "Retrieved fallback regions are not in the expected order 2-4-3");
172 Assert.That(results[2].RegionID, Is.EqualTo(new UUID(3)), "Retrieved fallback regions are not in the expected order 2-4-3"); 172 Assert.That(results[2].RegionID, Is.EqualTo(new UUID(3)), "Retrieved fallback regions are not in the expected order 2-4-3");
173 173
174 results = m_LocalConnector.GetFallbackRegions(UUID.Zero, r3.RegionLocX, r3.RegionLocY); 174 results = m_LocalConnector.GetFallbackRegions(UUID.Zero, r3.RegionLocX, r3.RegionLocY);
175 Assert.IsNotNull(results, "Retrieved GetFallbackRegions collection for region 3 is null"); 175 Assert.IsNotNull(results, "Retrieved GetFallbackRegions collection for region 3 is null");
176 Assert.That(results.Count, Is.EqualTo(3), "Retrieved fallback regions collection for region 3 has not the expected size"); 176 Assert.That(results.Count, Is.EqualTo(3), "Retrieved fallback regions collection for region 3 has not the expected size");
177 Assert.That(results[0].RegionID, Is.EqualTo(new UUID(3)), "Retrieved fallback regions are not in the expected order 3-4-2"); 177 Assert.That(results[0].RegionID, Is.EqualTo(new UUID(3)), "Retrieved fallback regions are not in the expected order 3-4-2");
178 Assert.That(results[1].RegionID, Is.EqualTo(new UUID(4)), "Retrieved fallback regions are not in the expected order 3-4-2"); 178 Assert.That(results[1].RegionID, Is.EqualTo(new UUID(4)), "Retrieved fallback regions are not in the expected order 3-4-2");
179 Assert.That(results[2].RegionID, Is.EqualTo(new UUID(2)), "Retrieved fallback regions are not in the expected order 3-4-2"); 179 Assert.That(results[2].RegionID, Is.EqualTo(new UUID(2)), "Retrieved fallback regions are not in the expected order 3-4-2");
180 180
181 results = m_LocalConnector.GetFallbackRegions(UUID.Zero, r4.RegionLocX, r4.RegionLocY); 181 results = m_LocalConnector.GetFallbackRegions(UUID.Zero, r4.RegionLocX, r4.RegionLocY);
182 Assert.IsNotNull(results, "Retrieved GetFallbackRegions collection for region 4 is null"); 182 Assert.IsNotNull(results, "Retrieved GetFallbackRegions collection for region 4 is null");
183 Assert.That(results.Count, Is.EqualTo(3), "Retrieved fallback regions collection for region 4 has not the expected size"); 183 Assert.That(results.Count, Is.EqualTo(3), "Retrieved fallback regions collection for region 4 has not the expected size");
184 Assert.That(results[0].RegionID, Is.EqualTo(new UUID(4)), "Retrieved fallback regions are not in the expected order 4-3-2"); 184 Assert.That(results[0].RegionID, Is.EqualTo(new UUID(4)), "Retrieved fallback regions are not in the expected order 4-3-2");
185 Assert.That(results[1].RegionID, Is.EqualTo(new UUID(3)), "Retrieved fallback regions are not in the expected order 4-3-2"); 185 Assert.That(results[1].RegionID, Is.EqualTo(new UUID(3)), "Retrieved fallback regions are not in the expected order 4-3-2");
186 Assert.That(results[2].RegionID, Is.EqualTo(new UUID(2)), "Retrieved fallback regions are not in the expected order 4-3-2"); 186 Assert.That(results[2].RegionID, Is.EqualTo(new UUID(2)), "Retrieved fallback regions are not in the expected order 4-3-2");
187 187
188 results = m_LocalConnector.GetHyperlinks(UUID.Zero); 188 results = m_LocalConnector.GetHyperlinks(UUID.Zero);
189 Assert.IsNotNull(results, "Retrieved GetHyperlinks list is null"); 189 Assert.IsNotNull(results, "Retrieved GetHyperlinks list is null");
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
index 2cf02b5..9714c36 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
@@ -272,7 +272,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
272 if (s.RegionInfo.RegionID == destination.RegionID) 272 if (s.RegionInfo.RegionID == destination.RegionID)
273 return s.QueryAccess(id, position, out reason); 273 return s.QueryAccess(id, position, out reason);
274 } 274 }
275 //m_log.Debug("[LOCAL COMMS]: region not found for QueryAccess");
276 return false; 275 return false;
277 } 276 }
278 277
@@ -302,10 +301,24 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
302 if (s.RegionInfo.RegionID == destination.RegionID) 301 if (s.RegionInfo.RegionID == destination.RegionID)
303 { 302 {
304 //m_log.Debug("[LOCAL COMMS]: Found region to SendCloseAgent"); 303 //m_log.Debug("[LOCAL COMMS]: Found region to SendCloseAgent");
305 // Let's spawn a threadlet right here, because this may take 304 return s.IncomingCloseAgent(id);
306 // a while 305 }
307 Util.FireAndForget(delegate { s.IncomingCloseAgent(id); }); 306 }
308 return true; 307 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent");
308 return false;
309 }
310
311 public bool CloseChildAgent(GridRegion destination, UUID id)
312 {
313 if (destination == null)
314 return false;
315
316 foreach (Scene s in m_sceneList)
317 {
318 if (s.RegionInfo.RegionID == destination.RegionID)
319 {
320 //m_log.Debug("[LOCAL COMMS]: Found region to SendCloseAgent");
321 return s.IncomingCloseChildAgent(id);
309 } 322 }
310 } 323 }
311 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent"); 324 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent");
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
index f8cea71..391b1a1 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
@@ -261,6 +261,21 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
261 return false; 261 return false;
262 } 262 }
263 263
264 public bool CloseChildAgent(GridRegion destination, UUID id)
265 {
266 if (destination == null)
267 return false;
268
269 // Try local first
270 if (m_localBackend.CloseChildAgent(destination, id))
271 return true;
272
273 // else do the remote thing
274 if (!m_localBackend.IsLocalRegion(destination.RegionHandle))
275 return m_remoteConnector.CloseChildAgent(destination, id);
276
277 return false;
278 }
264 279
265 public bool CloseAgent(GridRegion destination, UUID id) 280 public bool CloseAgent(GridRegion destination, UUID id)
266 { 281 {
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs
index 30ebb21..535a637 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs
@@ -120,6 +120,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
120 return; 120 return;
121 121
122 scene.RegisterModuleInterface<IUserAccountService>(m_UserService); 122 scene.RegisterModuleInterface<IUserAccountService>(m_UserService);
123 scene.RegisterModuleInterface<IUserAccountCacheModule>(m_Cache);
123 } 124 }
124 125
125 public void RemoveRegion(Scene scene) 126 public void RemoveRegion(Scene scene)
@@ -172,6 +173,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
172 return m_UserService.GetUserAccount(scopeID, Email); 173 return m_UserService.GetUserAccount(scopeID, Email);
173 } 174 }
174 175
176 public List<UserAccount> GetUserAccountsWhere(UUID scopeID, string query)
177 {
178 return null;
179 }
180
175 public List<UserAccount> GetUserAccounts(UUID scopeID, string query) 181 public List<UserAccount> GetUserAccounts(UUID scopeID, string query)
176 { 182 {
177 return m_UserService.GetUserAccounts(scopeID, query); 183 return m_UserService.GetUserAccounts(scopeID, query);
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs
index 3321b38..f6b6aeb 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs
@@ -33,6 +33,7 @@ using OpenSim.Region.Framework.Interfaces;
33using OpenSim.Region.Framework.Scenes; 33using OpenSim.Region.Framework.Scenes;
34using OpenSim.Services.Interfaces; 34using OpenSim.Services.Interfaces;
35using OpenSim.Services.Connectors; 35using OpenSim.Services.Connectors;
36using OpenSim.Framework;
36 37
37using OpenMetaverse; 38using OpenMetaverse;
38 39
@@ -101,6 +102,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
101 return; 102 return;
102 103
103 scene.RegisterModuleInterface<IUserAccountService>(this); 104 scene.RegisterModuleInterface<IUserAccountService>(this);
105 scene.RegisterModuleInterface<IUserAccountCacheModule>(m_Cache);
106
107 scene.EventManager.OnNewClient += OnNewClient;
104 } 108 }
105 109
106 public void RemoveRegion(Scene scene) 110 public void RemoveRegion(Scene scene)
@@ -115,6 +119,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
115 return; 119 return;
116 } 120 }
117 121
122 // When a user actually enters the sim, clear them from
123 // cache so the sim will have the current values for
124 // flags, title, etc. And country, don't forget country!
125 private void OnNewClient(IClientAPI client)
126 {
127 m_Cache.Remove(client.Name);
128 }
129
118 #region Overwritten methods from IUserAccountService 130 #region Overwritten methods from IUserAccountService
119 131
120 public override UserAccount GetUserAccount(UUID scopeID, UUID userID) 132 public override UserAccount GetUserAccount(UUID scopeID, UUID userID)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs
index ddef75f..cbe2eaa 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs
@@ -34,7 +34,7 @@ using log4net;
34 34
35namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts 35namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
36{ 36{
37 public class UserAccountCache 37 public class UserAccountCache : IUserAccountCacheModule
38 { 38 {
39 private const double CACHE_EXPIRATION_SECONDS = 120000.0; // 33 hours! 39 private const double CACHE_EXPIRATION_SECONDS = 120000.0; // 33 hours!
40 40
@@ -92,5 +92,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
92 92
93 return null; 93 return null;
94 } 94 }
95
96 public void Remove(string name)
97 {
98 if (!m_NameCache.Contains(name))
99 return;
100
101 UUID uuid = UUID.Zero;
102 if (m_NameCache.TryGetValue(name, out uuid))
103 {
104 m_NameCache.Remove(name);
105 m_UUIDCache.Remove(uuid);
106 }
107 }
95 } 108 }
96} 109}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index 48130e7..f85a917 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -292,6 +292,23 @@ namespace OpenSim.Region.CoreModules.World.Archiver
292 // being no copy/no mod for everyone 292 // being no copy/no mod for everyone
293 lock (part.TaskInventory) 293 lock (part.TaskInventory)
294 { 294 {
295 if (!ResolveUserUuid(part.CreatorID))
296 part.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner;
297
298 if (!ResolveUserUuid(part.OwnerID))
299 part.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
300
301 if (!ResolveUserUuid(part.LastOwnerID))
302 part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
303
304 // And zap any troublesome sit target information
305 part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
306 part.SitTargetPosition = new Vector3(0, 0, 0);
307
308 // Fix ownership/creator of inventory items
309 // Not doing so results in inventory items
310 // being no copy/no mod for everyone
311 part.TaskInventory.LockItemsForRead(true);
295 TaskInventoryDictionary inv = part.TaskInventory; 312 TaskInventoryDictionary inv = part.TaskInventory;
296 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv) 313 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv)
297 { 314 {
@@ -307,6 +324,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
307 if (UserManager != null) 324 if (UserManager != null)
308 UserManager.AddUser(kvp.Value.CreatorID, kvp.Value.CreatorData); 325 UserManager.AddUser(kvp.Value.CreatorID, kvp.Value.CreatorData);
309 } 326 }
327 part.TaskInventory.LockItemsForRead(false);
310 } 328 }
311 } 329 }
312 330
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
index 6a9c3d0..f8f3713 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
@@ -251,18 +251,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver
251 251
252 if (asset != null) 252 if (asset != null)
253 { 253 {
254 if (m_options.ContainsKey("verbose")) 254// m_log.DebugFormat("[ARCHIVER]: Writing asset {0}", id);
255 m_log.InfoFormat("[ARCHIVER]: Writing asset {0}", id);
256
257 m_foundAssetUuids.Add(asset.FullID); 255 m_foundAssetUuids.Add(asset.FullID);
258 256
259 m_assetsArchiver.WriteAsset(PostProcess(asset)); 257 m_assetsArchiver.WriteAsset(PostProcess(asset));
260 } 258 }
261 else 259 else
262 { 260 {
263 if (m_options.ContainsKey("verbose")) 261// m_log.DebugFormat("[ARCHIVER]: Recording asset {0} as not found", id);
264 m_log.InfoFormat("[ARCHIVER]: Recording asset {0} as not found", id);
265
266 m_notFoundAssetUuids.Add(new UUID(id)); 262 m_notFoundAssetUuids.Add(new UUID(id));
267 } 263 }
268 264
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index 3aed6ba..bc76a7c 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -30,6 +30,7 @@ using System.Collections.Generic;
30using System.IO; 30using System.IO;
31using System.Reflection; 31using System.Reflection;
32using System.Security; 32using System.Security;
33using System.Timers;
33using log4net; 34using log4net;
34using Mono.Addins; 35using Mono.Addins;
35using Nini.Config; 36using Nini.Config;
@@ -47,6 +48,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
47 48
48 private delegate void LookupUUIDS(List<UUID> uuidLst); 49 private delegate void LookupUUIDS(List<UUID> uuidLst);
49 50
51 private Timer m_regionChangeTimer = new Timer();
50 public Scene Scene { get; private set; } 52 public Scene Scene { get; private set; }
51 public IUserManagement UserManager { get; private set; } 53 public IUserManagement UserManager { get; private set; }
52 54
@@ -60,8 +62,15 @@ namespace OpenSim.Region.CoreModules.World.Estate
60 62
61 #region Packet Data Responders 63 #region Packet Data Responders
62 64
65 private void clientSendDetailedEstateData(IClientAPI remote_client, UUID invoice)
66 {
67 sendDetailedEstateData(remote_client, invoice);
68 sendEstateLists(remote_client, invoice);
69 }
70
63 private void sendDetailedEstateData(IClientAPI remote_client, UUID invoice) 71 private void sendDetailedEstateData(IClientAPI remote_client, UUID invoice)
64 { 72 {
73 m_log.DebugFormat("[ESTATE]: Invoice is {0}", invoice.ToString());
65 uint sun = 0; 74 uint sun = 0;
66 75
67 if (!Scene.RegionInfo.EstateSettings.UseGlobalTime) 76 if (!Scene.RegionInfo.EstateSettings.UseGlobalTime)
@@ -81,7 +90,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
81 Scene.RegionInfo.RegionSettings.Covenant, 90 Scene.RegionInfo.RegionSettings.Covenant,
82 Scene.RegionInfo.EstateSettings.AbuseEmail, 91 Scene.RegionInfo.EstateSettings.AbuseEmail,
83 estateOwner); 92 estateOwner);
93 }
84 94
95 private void sendEstateLists(IClientAPI remote_client, UUID invoice)
96 {
85 remote_client.SendEstateList(invoice, 97 remote_client.SendEstateList(invoice,
86 (int)Constants.EstateAccessCodex.EstateManagers, 98 (int)Constants.EstateAccessCodex.EstateManagers,
87 Scene.RegionInfo.EstateSettings.EstateManagers, 99 Scene.RegionInfo.EstateSettings.EstateManagers,
@@ -256,7 +268,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
256 timeInSeconds -= 15; 268 timeInSeconds -= 15;
257 } 269 }
258 270
259 restartModule.ScheduleRestart(UUID.Zero, "Region will restart in {0}", times.ToArray(), true); 271 restartModule.ScheduleRestart(UUID.Zero, "Region will restart in {0}", times.ToArray(), false);
260 } 272 }
261 } 273 }
262 274
@@ -463,7 +475,11 @@ namespace OpenSim.Region.CoreModules.World.Estate
463 { 475 {
464 if (!s.IsChildAgent) 476 if (!s.IsChildAgent)
465 { 477 {
466 Scene.TeleportClientHome(user, s.ControllingClient); 478 if (!Scene.TeleportClientHome(user, s.ControllingClient))
479 {
480 s.ControllingClient.Kick("Your access to the region was revoked and TP home failed - you have been logged out.");
481 s.ControllingClient.Close();
482 }
467 } 483 }
468 } 484 }
469 485
@@ -472,7 +488,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
472 { 488 {
473 remote_client.SendAlertMessage("User is already on the region ban list"); 489 remote_client.SendAlertMessage("User is already on the region ban list");
474 } 490 }
475 //m_scene.RegionInfo.regionBanlist.Add(Manager(user); 491 //Scene.RegionInfo.regionBanlist.Add(Manager(user);
476 remote_client.SendBannedUserList(invoice, Scene.RegionInfo.EstateSettings.EstateBans, Scene.RegionInfo.EstateSettings.EstateID); 492 remote_client.SendBannedUserList(invoice, Scene.RegionInfo.EstateSettings.EstateBans, Scene.RegionInfo.EstateSettings.EstateID);
477 } 493 }
478 else 494 else
@@ -527,7 +543,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
527 remote_client.SendAlertMessage("User is not on the region ban list"); 543 remote_client.SendAlertMessage("User is not on the region ban list");
528 } 544 }
529 545
530 //m_scene.RegionInfo.regionBanlist.Add(Manager(user); 546 //Scene.RegionInfo.regionBanlist.Add(Manager(user);
531 remote_client.SendBannedUserList(invoice, Scene.RegionInfo.EstateSettings.EstateBans, Scene.RegionInfo.EstateSettings.EstateID); 547 remote_client.SendBannedUserList(invoice, Scene.RegionInfo.EstateSettings.EstateBans, Scene.RegionInfo.EstateSettings.EstateID);
532 } 548 }
533 else 549 else
@@ -648,7 +664,11 @@ namespace OpenSim.Region.CoreModules.World.Estate
648 ScenePresence s = Scene.GetScenePresence(prey); 664 ScenePresence s = Scene.GetScenePresence(prey);
649 if (s != null) 665 if (s != null)
650 { 666 {
651 Scene.TeleportClientHome(prey, s.ControllingClient); 667 if (!Scene.TeleportClientHome(prey, s.ControllingClient))
668 {
669 s.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out.");
670 s.ControllingClient.Close();
671 }
652 } 672 }
653 } 673 }
654 } 674 }
@@ -667,7 +687,11 @@ namespace OpenSim.Region.CoreModules.World.Estate
667 // Also make sure they are actually in the region 687 // Also make sure they are actually in the region
668 if (p != null && !p.IsChildAgent) 688 if (p != null && !p.IsChildAgent)
669 { 689 {
670 Scene.TeleportClientHome(p.UUID, p.ControllingClient); 690 if (!Scene.TeleportClientHome(p.UUID, p.ControllingClient))
691 {
692 p.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out.");
693 p.ControllingClient.Close();
694 }
671 } 695 }
672 } 696 }
673 }); 697 });
@@ -918,7 +942,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
918 942
919 for (int i = 0; i < uuidarr.Length; i++) 943 for (int i = 0; i < uuidarr.Length; i++)
920 { 944 {
921 // string lookupname = m_scene.CommsManager.UUIDNameRequestString(uuidarr[i]); 945 // string lookupname = Scene.CommsManager.UUIDNameRequestString(uuidarr[i]);
922 946
923 IUserManagement userManager = Scene.RequestModuleInterface<IUserManagement>(); 947 IUserManagement userManager = Scene.RequestModuleInterface<IUserManagement>();
924 if (userManager != null) 948 if (userManager != null)
@@ -1055,6 +1079,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
1055 1079
1056 public void AddRegion(Scene scene) 1080 public void AddRegion(Scene scene)
1057 { 1081 {
1082 m_regionChangeTimer.AutoReset = false;
1083 m_regionChangeTimer.Interval = 2000;
1084 m_regionChangeTimer.Elapsed += RaiseRegionInfoChange;
1085
1058 Scene = scene; 1086 Scene = scene;
1059 Scene.RegisterModuleInterface<IEstateModule>(this); 1087 Scene.RegisterModuleInterface<IEstateModule>(this);
1060 Scene.EventManager.OnNewClient += EventManager_OnNewClient; 1088 Scene.EventManager.OnNewClient += EventManager_OnNewClient;
@@ -1103,7 +1131,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
1103 1131
1104 private void EventManager_OnNewClient(IClientAPI client) 1132 private void EventManager_OnNewClient(IClientAPI client)
1105 { 1133 {
1106 client.OnDetailedEstateDataRequest += sendDetailedEstateData; 1134 client.OnDetailedEstateDataRequest += clientSendDetailedEstateData;
1107 client.OnSetEstateFlagsRequest += estateSetRegionInfoHandler; 1135 client.OnSetEstateFlagsRequest += estateSetRegionInfoHandler;
1108// client.OnSetEstateTerrainBaseTexture += setEstateTerrainBaseTexture; 1136// client.OnSetEstateTerrainBaseTexture += setEstateTerrainBaseTexture;
1109 client.OnSetEstateTerrainDetailTexture += setEstateTerrainBaseTexture; 1137 client.OnSetEstateTerrainDetailTexture += setEstateTerrainBaseTexture;
@@ -1161,11 +1189,15 @@ namespace OpenSim.Region.CoreModules.World.Estate
1161 flags |= RegionFlags.Sandbox; 1189 flags |= RegionFlags.Sandbox;
1162 if (Scene.RegionInfo.EstateSettings.AllowVoice) 1190 if (Scene.RegionInfo.EstateSettings.AllowVoice)
1163 flags |= RegionFlags.AllowVoice; 1191 flags |= RegionFlags.AllowVoice;
1192 if (Scene.RegionInfo.EstateSettings.AllowLandmark)
1193 flags |= RegionFlags.AllowLandmark;
1194 if (Scene.RegionInfo.EstateSettings.AllowSetHome)
1195 flags |= RegionFlags.AllowSetHome;
1196 if (Scene.RegionInfo.EstateSettings.BlockDwell)
1197 flags |= RegionFlags.BlockDwell;
1198 if (Scene.RegionInfo.EstateSettings.ResetHomeOnTeleport)
1199 flags |= RegionFlags.ResetHomeOnTeleport;
1164 1200
1165 // Fudge these to always on, so the menu options activate
1166 //
1167 flags |= RegionFlags.AllowLandmark;
1168 flags |= RegionFlags.AllowSetHome;
1169 1201
1170 // TODO: SkipUpdateInterestList 1202 // TODO: SkipUpdateInterestList
1171 1203
@@ -1206,6 +1238,12 @@ namespace OpenSim.Region.CoreModules.World.Estate
1206 flags |= RegionFlags.ResetHomeOnTeleport; 1238 flags |= RegionFlags.ResetHomeOnTeleport;
1207 if (Scene.RegionInfo.EstateSettings.TaxFree) 1239 if (Scene.RegionInfo.EstateSettings.TaxFree)
1208 flags |= RegionFlags.TaxFree; 1240 flags |= RegionFlags.TaxFree;
1241 if (Scene.RegionInfo.EstateSettings.AllowLandmark)
1242 flags |= RegionFlags.AllowLandmark;
1243 if (Scene.RegionInfo.EstateSettings.AllowParcelChanges)
1244 flags |= RegionFlags.AllowParcelChanges;
1245 if (Scene.RegionInfo.EstateSettings.AllowSetHome)
1246 flags |= RegionFlags.AllowSetHome;
1209 if (Scene.RegionInfo.EstateSettings.DenyMinors) 1247 if (Scene.RegionInfo.EstateSettings.DenyMinors)
1210 flags |= (RegionFlags)(1 << 30); 1248 flags |= (RegionFlags)(1 << 30);
1211 1249
@@ -1226,6 +1264,12 @@ namespace OpenSim.Region.CoreModules.World.Estate
1226 1264
1227 public void TriggerRegionInfoChange() 1265 public void TriggerRegionInfoChange()
1228 { 1266 {
1267 m_regionChangeTimer.Stop();
1268 m_regionChangeTimer.Start();
1269 }
1270
1271 protected void RaiseRegionInfoChange(object sender, ElapsedEventArgs e)
1272 {
1229 ChangeDelegate change = OnRegionInfoChange; 1273 ChangeDelegate change = OnRegionInfoChange;
1230 1274
1231 if (change != null) 1275 if (change != null)
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index 63dec15..4e7c76f 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
@@ -91,11 +91,11 @@ namespace OpenSim.Region.CoreModules.World.Land
91 private int m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1; 91 private int m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1;
92 92
93 private bool m_allowedForcefulBans = true; 93 private bool m_allowedForcefulBans = true;
94 private UUID DefaultGodParcelGroup;
95 private string DefaultGodParcelName;
94 96
95 // caches ExtendedLandData 97 // caches ExtendedLandData
96 private Cache parcelInfoCache; 98 private Cache parcelInfoCache;
97 private Dictionary<UUID, Vector3> forcedPosition =
98 new Dictionary<UUID, Vector3>();
99 99
100 #region INonSharedRegionModule Members 100 #region INonSharedRegionModule Members
101 101
@@ -106,6 +106,12 @@ namespace OpenSim.Region.CoreModules.World.Land
106 106
107 public void Initialise(IConfigSource source) 107 public void Initialise(IConfigSource source)
108 { 108 {
109 IConfig cnf = source.Configs["LandManagement"];
110 if (cnf != null)
111 {
112 DefaultGodParcelGroup = new UUID(cnf.GetString("DefaultAdministratorGroupUUID", UUID.Zero.ToString()));
113 DefaultGodParcelName = cnf.GetString("DefaultAdministratorParcelName", "Default Parcel");
114 }
109 } 115 }
110 116
111 public void AddRegion(Scene scene) 117 public void AddRegion(Scene scene)
@@ -157,13 +163,6 @@ namespace OpenSim.Region.CoreModules.World.Land
157 m_scene.UnregisterModuleCommander(m_commander.Name); 163 m_scene.UnregisterModuleCommander(m_commander.Name);
158 } 164 }
159 165
160// private bool OnVerifyUserConnection(ScenePresence scenePresence, out string reason)
161// {
162// ILandObject nearestParcel = m_scene.GetNearestAllowedParcel(scenePresence.UUID, scenePresence.AbsolutePosition.X, scenePresence.AbsolutePosition.Y);
163// reason = "You are not allowed to enter this sim.";
164// return nearestParcel != null;
165// }
166
167 /// <summary> 166 /// <summary>
168 /// Processes commandline input. Do not call directly. 167 /// Processes commandline input. Do not call directly.
169 /// </summary> 168 /// </summary>
@@ -215,36 +214,6 @@ namespace OpenSim.Region.CoreModules.World.Land
215 214
216 void ClientOnPreAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) 215 void ClientOnPreAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
217 { 216 {
218 //If we are forcing a position for them to go
219 if (forcedPosition.ContainsKey(remoteClient.AgentId))
220 {
221 ScenePresence clientAvatar = m_scene.GetScenePresence(remoteClient.AgentId);
222
223 //Putting the user into flying, both keeps the avatar in fligth when it bumps into something and stopped from going another direction AND
224 //When the avatar walks into a ban line on the ground, it prevents getting stuck
225 agentData.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
226
227
228 //Make sure we stop if they get about to the right place to prevent yoyo and prevents getting stuck on banlines
229 if (Vector3.Distance(clientAvatar.AbsolutePosition, forcedPosition[remoteClient.AgentId]) < .2)
230 {
231 Debug.WriteLine(string.Format("Stopping force position because {0} is close enough to position {1}", forcedPosition[remoteClient.AgentId], clientAvatar.AbsolutePosition));
232 forcedPosition.Remove(remoteClient.AgentId);
233 }
234 //if we are far away, teleport
235 else if (Vector3.Distance(clientAvatar.AbsolutePosition, forcedPosition[remoteClient.AgentId]) > 3)
236 {
237 Debug.WriteLine(string.Format("Teleporting out because {0} is too far from avatar position {1}", forcedPosition[remoteClient.AgentId], clientAvatar.AbsolutePosition));
238 clientAvatar.Teleport(forcedPosition[remoteClient.AgentId]);
239 forcedPosition.Remove(remoteClient.AgentId);
240 }
241 else
242 {
243 //Forces them toward the forced position we want if they aren't there yet
244 agentData.UseClientAgentPosition = true;
245 agentData.ClientAgentPosition = forcedPosition[remoteClient.AgentId];
246 }
247 }
248 } 217 }
249 218
250 public void Close() 219 public void Close()
@@ -363,10 +332,16 @@ namespace OpenSim.Region.CoreModules.World.Land
363 private void ForceAvatarToPosition(ScenePresence avatar, Vector3? position) 332 private void ForceAvatarToPosition(ScenePresence avatar, Vector3? position)
364 { 333 {
365 if (m_scene.Permissions.IsGod(avatar.UUID)) return; 334 if (m_scene.Permissions.IsGod(avatar.UUID)) return;
366 if (position.HasValue) 335
367 { 336 if (!position.HasValue)
368 forcedPosition[avatar.ControllingClient.AgentId] = (Vector3)position; 337 return;
369 } 338
339 bool isFlying = avatar.PhysicsActor.Flying;
340 avatar.RemoveFromPhysicalScene();
341
342 avatar.AbsolutePosition = (Vector3)position;
343
344 avatar.AddToPhysicalScene(isFlying);
370 } 345 }
371 346
372 public void SendYouAreRestrictedNotice(ScenePresence avatar) 347 public void SendYouAreRestrictedNotice(ScenePresence avatar)
@@ -386,29 +361,7 @@ namespace OpenSim.Region.CoreModules.World.Land
386 } 361 }
387 362
388 if (parcelAvatarIsEntering != null) 363 if (parcelAvatarIsEntering != null)
389 { 364 EnforceBans(parcelAvatarIsEntering, avatar);
390 if (avatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT)
391 {
392 if (parcelAvatarIsEntering.IsBannedFromLand(avatar.UUID))
393 {
394 SendYouAreBannedNotice(avatar);
395 ForceAvatarToPosition(avatar, m_scene.GetNearestAllowedPosition(avatar));
396 }
397 else if (parcelAvatarIsEntering.IsRestrictedFromLand(avatar.UUID))
398 {
399 SendYouAreRestrictedNotice(avatar);
400 ForceAvatarToPosition(avatar, m_scene.GetNearestAllowedPosition(avatar));
401 }
402 else
403 {
404 avatar.sentMessageAboutRestrictedParcelFlyingDown = true;
405 }
406 }
407 else
408 {
409 avatar.sentMessageAboutRestrictedParcelFlyingDown = true;
410 }
411 }
412 } 365 }
413 } 366 }
414 367
@@ -480,43 +433,7 @@ namespace OpenSim.Region.CoreModules.World.Land
480 SendOutNearestBanLine(remote_client); 433 SendOutNearestBanLine(remote_client);
481 ILandObject parcel = GetLandObject(clientAvatar.AbsolutePosition.X, clientAvatar.AbsolutePosition.Y); 434 ILandObject parcel = GetLandObject(clientAvatar.AbsolutePosition.X, clientAvatar.AbsolutePosition.Y);
482 if (parcel != null) 435 if (parcel != null)
483 { 436 EnforceBans(parcel, clientAvatar);
484 if (clientAvatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT &&
485 clientAvatar.sentMessageAboutRestrictedParcelFlyingDown)
486 {
487 EventManagerOnAvatarEnteringNewParcel(clientAvatar, parcel.LandData.LocalID,
488 m_scene.RegionInfo.RegionID);
489 //They are going under the safety line!
490 if (!parcel.IsBannedFromLand(clientAvatar.UUID))
491 {
492 clientAvatar.sentMessageAboutRestrictedParcelFlyingDown = false;
493 }
494 }
495 else if (clientAvatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT &&
496 parcel.IsBannedFromLand(clientAvatar.UUID))
497 {
498 //once we've sent the message once, keep going toward the target until we are done
499 if (forcedPosition.ContainsKey(clientAvatar.ControllingClient.AgentId))
500 {
501 SendYouAreBannedNotice(clientAvatar);
502 ForceAvatarToPosition(clientAvatar, m_scene.GetNearestAllowedPosition(clientAvatar));
503 }
504 }
505 else if (parcel.IsRestrictedFromLand(clientAvatar.UUID))
506 {
507 //once we've sent the message once, keep going toward the target until we are done
508 if (forcedPosition.ContainsKey(clientAvatar.ControllingClient.AgentId))
509 {
510 SendYouAreRestrictedNotice(clientAvatar);
511 ForceAvatarToPosition(clientAvatar, m_scene.GetNearestAllowedPosition(clientAvatar));
512 }
513 }
514 else
515 {
516 //when we are finally in a safe place, lets release the forced position lock
517 forcedPosition.Remove(clientAvatar.ControllingClient.AgentId);
518 }
519 }
520 } 437 }
521 } 438 }
522 439
@@ -725,7 +642,7 @@ namespace OpenSim.Region.CoreModules.World.Land
725 int x; 642 int x;
726 int y; 643 int y;
727 644
728 if (x_float >= Constants.RegionSize || x_float < 0 || y_float >= Constants.RegionSize || y_float < 0) 645 if (x_float > Constants.RegionSize || x_float < 0 || y_float > Constants.RegionSize || y_float < 0)
729 return null; 646 return null;
730 647
731 try 648 try
@@ -775,14 +692,13 @@ namespace OpenSim.Region.CoreModules.World.Land
775 { 692 {
776 try 693 try
777 { 694 {
778 return m_landList[m_landIDList[x / 4, y / 4]]; 695 //if (m_landList.ContainsKey(m_landIDList[x / 4, y / 4]))
696 return m_landList[m_landIDList[x / 4, y / 4]];
697 //else
698 // return null;
779 } 699 }
780 catch (IndexOutOfRangeException) 700 catch (IndexOutOfRangeException)
781 { 701 {
782// m_log.WarnFormat(
783// "[LAND MANAGEMENT MODULE]: Tried to retrieve land object from out of bounds co-ordinate ({0},{1}) in {2}",
784// x, y, m_scene.RegionInfo.RegionName);
785
786 return null; 702 return null;
787 } 703 }
788 } 704 }
@@ -1065,6 +981,10 @@ namespace OpenSim.Region.CoreModules.World.Land
1065 //Owner Flag 981 //Owner Flag
1066 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER); 982 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER);
1067 } 983 }
984 else if (currentParcelBlock.LandData.IsGroupOwned && remote_client.IsGroupMember(currentParcelBlock.LandData.GroupID))
985 {
986 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_GROUP);
987 }
1068 else if (currentParcelBlock.LandData.SalePrice > 0 && 988 else if (currentParcelBlock.LandData.SalePrice > 0 &&
1069 (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero || 989 (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero ||
1070 currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId)) 990 currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId))
@@ -1365,18 +1285,31 @@ namespace OpenSim.Region.CoreModules.World.Land
1365 1285
1366 public void EventManagerOnIncomingLandDataFromStorage(List<LandData> data) 1286 public void EventManagerOnIncomingLandDataFromStorage(List<LandData> data)
1367 { 1287 {
1368 for (int i = 0; i < data.Count; i++) 1288 lock (m_landList)
1369 { 1289 {
1370 IncomingLandObjectFromStorage(data[i]); 1290 //Remove all the land objects in the sim and then process our new data
1291 foreach (int n in m_landList.Keys)
1292 {
1293 m_scene.EventManager.TriggerLandObjectRemoved(m_landList[n].LandData.GlobalID);
1294 }
1295 m_landIDList.Initialize();
1296 m_landList.Clear();
1297
1298 for (int i = 0; i < data.Count; i++)
1299 {
1300 IncomingLandObjectFromStorage(data[i]);
1301 }
1371 } 1302 }
1372 } 1303 }
1373 1304
1374 public void IncomingLandObjectFromStorage(LandData data) 1305 public void IncomingLandObjectFromStorage(LandData data)
1375 { 1306 {
1307
1376 ILandObject new_land = new LandObject(data.OwnerID, data.IsGroupOwned, m_scene); 1308 ILandObject new_land = new LandObject(data.OwnerID, data.IsGroupOwned, m_scene);
1377 new_land.LandData = data.Copy(); 1309 new_land.LandData = data.Copy();
1378 new_land.SetLandBitmapFromByteArray(); 1310 new_land.SetLandBitmapFromByteArray();
1379 AddLandObject(new_land); 1311 AddLandObject(new_land);
1312 new_land.SendLandUpdateToAvatarsOverMe();
1380 } 1313 }
1381 1314
1382 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient) 1315 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient)
@@ -1654,6 +1587,322 @@ namespace OpenSim.Region.CoreModules.World.Land
1654 1587
1655 UpdateLandObject(localID, land.LandData); 1588 UpdateLandObject(localID, land.LandData);
1656 } 1589 }
1590
1591 public void ClientOnParcelGodMark(IClientAPI client, UUID god, int landID)
1592 {
1593 ILandObject land = null;
1594 List<ILandObject> Land = ((Scene)client.Scene).LandChannel.AllParcels();
1595 foreach (ILandObject landObject in Land)
1596 {
1597 if (landObject.LandData.LocalID == landID)
1598 {
1599 land = landObject;
1600 }
1601 }
1602 land.DeedToGroup(DefaultGodParcelGroup);
1603 land.LandData.Name = DefaultGodParcelName;
1604 land.SendLandUpdateToAvatarsOverMe();
1605 }
1606
1607 private void ClientOnSimWideDeletes(IClientAPI client, UUID agentID, int flags, UUID targetID)
1608 {
1609 ScenePresence SP;
1610 ((Scene)client.Scene).TryGetScenePresence(client.AgentId, out SP);
1611 List<SceneObjectGroup> returns = new List<SceneObjectGroup>();
1612 if (SP.UserLevel != 0)
1613 {
1614 if (flags == 0) //All parcels, scripted or not
1615 {
1616 ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e)
1617 {
1618 if (e.OwnerID == targetID)
1619 {
1620 returns.Add(e);
1621 }
1622 }
1623 );
1624 }
1625 if (flags == 4) //All parcels, scripted object
1626 {
1627 ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e)
1628 {
1629 if (e.OwnerID == targetID)
1630 {
1631 if (e.scriptScore >= 0.01)
1632 {
1633 returns.Add(e);
1634 }
1635 }
1636 }
1637 );
1638 }
1639 if (flags == 4) //not target parcel, scripted object
1640 {
1641 ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e)
1642 {
1643 if (e.OwnerID == targetID)
1644 {
1645 ILandObject landobject = ((Scene)client.Scene).LandChannel.GetLandObject(e.AbsolutePosition.X, e.AbsolutePosition.Y);
1646 if (landobject.LandData.OwnerID != e.OwnerID)
1647 {
1648 if (e.scriptScore >= 0.01)
1649 {
1650 returns.Add(e);
1651 }
1652 }
1653 }
1654 }
1655 );
1656 }
1657 foreach (SceneObjectGroup ol in returns)
1658 {
1659 ReturnObject(ol, client);
1660 }
1661 }
1662 }
1663 public void ReturnObject(SceneObjectGroup obj, IClientAPI client)
1664 {
1665 SceneObjectGroup[] objs = new SceneObjectGroup[1];
1666 objs[0] = obj;
1667 ((Scene)client.Scene).returnObjects(objs, client.AgentId);
1668 }
1669
1670 Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>();
1671
1672 public void ClientOnParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
1673 {
1674 ScenePresence targetAvatar = null;
1675 ((Scene)client.Scene).TryGetScenePresence(target, out targetAvatar);
1676 ScenePresence parcelManager = null;
1677 ((Scene)client.Scene).TryGetScenePresence(client.AgentId, out parcelManager);
1678 System.Threading.Timer Timer;
1679
1680 if (targetAvatar.UserLevel == 0)
1681 {
1682 ILandObject land = ((Scene)client.Scene).LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y);
1683 if (!((Scene)client.Scene).Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze))
1684 return;
1685 if (flags == 0)
1686 {
1687 targetAvatar.AllowMovement = false;
1688 targetAvatar.ControllingClient.SendAlertMessage(parcelManager.Firstname + " " + parcelManager.Lastname + " has frozen you for 30 seconds. You cannot move or interact with the world.");
1689 parcelManager.ControllingClient.SendAlertMessage("Avatar Frozen.");
1690 System.Threading.TimerCallback timeCB = new System.Threading.TimerCallback(OnEndParcelFrozen);
1691 Timer = new System.Threading.Timer(timeCB, targetAvatar, 30000, 0);
1692 Timers.Add(targetAvatar.UUID, Timer);
1693 }
1694 else
1695 {
1696 targetAvatar.AllowMovement = true;
1697 targetAvatar.ControllingClient.SendAlertMessage(parcelManager.Firstname + " " + parcelManager.Lastname + " has unfrozen you.");
1698 parcelManager.ControllingClient.SendAlertMessage("Avatar Unfrozen.");
1699 Timers.TryGetValue(targetAvatar.UUID, out Timer);
1700 Timers.Remove(targetAvatar.UUID);
1701 Timer.Dispose();
1702 }
1703 }
1704 }
1705 private void OnEndParcelFrozen(object avatar)
1706 {
1707 ScenePresence targetAvatar = (ScenePresence)avatar;
1708 targetAvatar.AllowMovement = true;
1709 System.Threading.Timer Timer;
1710 Timers.TryGetValue(targetAvatar.UUID, out Timer);
1711 Timers.Remove(targetAvatar.UUID);
1712 targetAvatar.ControllingClient.SendAgentAlertMessage("The freeze has worn off; you may go about your business.", false);
1713 }
1714
1715
1716 public void ClientOnParcelEjectUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
1717 {
1718 ScenePresence targetAvatar = null;
1719 ((Scene)client.Scene).TryGetScenePresence(target, out targetAvatar);
1720 ScenePresence parcelManager = null;
1721 ((Scene)client.Scene).TryGetScenePresence(client.AgentId, out parcelManager);
1722 //Just eject
1723 if (flags == 0)
1724 {
1725 if (targetAvatar.UserLevel == 0)
1726 {
1727 ILandObject land = ((Scene)client.Scene).LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y);
1728 if (!((Scene)client.Scene).Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze))
1729 return;
1730
1731 Vector3 position = new Vector3(0, 0, 0);
1732 List<ILandObject> allParcels = new List<ILandObject>();
1733 allParcels = AllParcels();
1734 if (allParcels.Count != 1)
1735 {
1736 foreach (ILandObject parcel in allParcels)
1737 {
1738 if (parcel.LandData.GlobalID != land.LandData.GlobalID)
1739 {
1740 if (parcel.IsEitherBannedOrRestricted(targetAvatar.UUID) != true)
1741 {
1742 for (int x = 1; x <= Constants.RegionSize; x += 2)
1743 {
1744 for (int y = 1; y <= Constants.RegionSize; y += 2)
1745 {
1746 if (parcel.ContainsPoint(x, y))
1747 {
1748 position = new Vector3(x, y, targetAvatar.AbsolutePosition.Z);
1749 targetAvatar.TeleportWithMomentum(position);
1750 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1751 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected.");
1752 return;
1753 }
1754 }
1755 }
1756 }
1757 }
1758 }
1759 }
1760 Vector3 targetVector;
1761 if (targetAvatar.AbsolutePosition.X > targetAvatar.AbsolutePosition.Y)
1762 {
1763 if (targetAvatar.AbsolutePosition.X > .5 * Constants.RegionSize)
1764 {
1765 targetVector = new Vector3(Constants.RegionSize, targetAvatar.AbsolutePosition.Y, targetAvatar.AbsolutePosition.Z); ;
1766 targetAvatar.TeleportWithMomentum(targetVector);
1767 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1768 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected.");
1769 return;
1770 }
1771 else
1772 {
1773 targetVector = new Vector3(0, targetAvatar.AbsolutePosition.Y, targetAvatar.AbsolutePosition.Z); ;
1774 targetAvatar.TeleportWithMomentum(targetVector);
1775 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1776 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected.");
1777 return;
1778 }
1779 }
1780 else
1781 {
1782 if (targetAvatar.AbsolutePosition.Y > .5 * Constants.RegionSize)
1783 {
1784 targetVector = new Vector3(targetAvatar.AbsolutePosition.X, Constants.RegionSize, targetAvatar.AbsolutePosition.Z); ;
1785 targetAvatar.TeleportWithMomentum(targetVector);
1786 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1787 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected.");
1788 return;
1789 }
1790 else
1791 {
1792 targetVector = new Vector3(targetAvatar.AbsolutePosition.X, 0, targetAvatar.AbsolutePosition.Z); ;
1793 targetAvatar.TeleportWithMomentum(targetVector);
1794 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1795 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected.");
1796 return;
1797 }
1798 }
1799 }
1800 }
1801 //Eject and ban
1802 if (flags == 1)
1803 {
1804 if (targetAvatar.UserLevel == 0)
1805 {
1806 ILandObject land = ((Scene)client.Scene).LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y);
1807 if (!((Scene)client.Scene).Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze))
1808 return;
1809
1810 Vector3 position = new Vector3(0, 0, 0);
1811 List<ILandObject> allParcels = new List<ILandObject>();
1812 allParcels = AllParcels();
1813 if (allParcels.Count != 1)
1814 {
1815 foreach (ILandObject parcel in allParcels)
1816 {
1817 if (parcel.LandData.GlobalID != land.LandData.GlobalID)
1818 {
1819 if (parcel.IsEitherBannedOrRestricted(targetAvatar.UUID) != true)
1820 {
1821 for (int x = 1; x <= Constants.RegionSize; x += 2)
1822 {
1823 for (int y = 1; y <= Constants.RegionSize; y += 2)
1824 {
1825 if (parcel.ContainsPoint(x, y))
1826 {
1827 position = new Vector3(x, y, targetAvatar.AbsolutePosition.Z);
1828 targetAvatar.TeleportWithMomentum(position);
1829 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected and banned by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1830 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected and Banned.");
1831 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
1832 entry.AgentID = targetAvatar.UUID;
1833 entry.Flags = AccessList.Ban;
1834 entry.Time = new DateTime();
1835 land.LandData.ParcelAccessList.Add(entry);
1836 return;
1837 }
1838 }
1839 }
1840 }
1841 }
1842 }
1843 }
1844 Vector3 targetVector;
1845 if (targetAvatar.AbsolutePosition.X > targetAvatar.AbsolutePosition.Y)
1846 {
1847 if (targetAvatar.AbsolutePosition.X > .5 * Constants.RegionSize)
1848 {
1849 targetVector = new Vector3(Constants.RegionSize, targetAvatar.AbsolutePosition.Y, targetAvatar.AbsolutePosition.Z); ;
1850 targetAvatar.TeleportWithMomentum(targetVector);
1851 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected and banned by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1852 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected and Banned.");
1853 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
1854 entry.AgentID = targetAvatar.UUID;
1855 entry.Flags = AccessList.Ban;
1856 entry.Time = new DateTime();
1857 land.LandData.ParcelAccessList.Add(entry);
1858 return;
1859 }
1860 else
1861 {
1862 targetVector = new Vector3(0, targetAvatar.AbsolutePosition.Y, targetAvatar.AbsolutePosition.Z); ;
1863 targetAvatar.TeleportWithMomentum(targetVector);
1864 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected and banned by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1865 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected and Banned.");
1866 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
1867 entry.AgentID = targetAvatar.UUID;
1868 entry.Flags = AccessList.Ban;
1869 entry.Time = new DateTime();
1870 land.LandData.ParcelAccessList.Add(entry);
1871 return;
1872 }
1873 }
1874 else
1875 {
1876 if (targetAvatar.AbsolutePosition.Y > .5 * Constants.RegionSize)
1877 {
1878 targetVector = new Vector3(targetAvatar.AbsolutePosition.X, Constants.RegionSize, targetAvatar.AbsolutePosition.Z); ;
1879 targetAvatar.TeleportWithMomentum(targetVector);
1880 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected and banned by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1881 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected and Banned.");
1882 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
1883 entry.AgentID = targetAvatar.UUID;
1884 entry.Flags = AccessList.Ban;
1885 entry.Time = new DateTime();
1886 land.LandData.ParcelAccessList.Add(entry);
1887 return;
1888 }
1889 else
1890 {
1891 targetVector = new Vector3(targetAvatar.AbsolutePosition.X, 0, targetAvatar.AbsolutePosition.Z); ;
1892 targetAvatar.TeleportWithMomentum(targetVector);
1893 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected and banned by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1894 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected and Banned.");
1895 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
1896 entry.AgentID = targetAvatar.UUID;
1897 entry.Flags = AccessList.Ban;
1898 entry.Time = new DateTime();
1899 land.LandData.ParcelAccessList.Add(entry);
1900 return;
1901 }
1902 }
1903 }
1904 }
1905 }
1657 1906
1658 protected void InstallInterfaces() 1907 protected void InstallInterfaces()
1659 { 1908 {
@@ -1716,5 +1965,27 @@ namespace OpenSim.Region.CoreModules.World.Land
1716 1965
1717 MainConsole.Instance.Output(report.ToString()); 1966 MainConsole.Instance.Output(report.ToString());
1718 } 1967 }
1968
1969 public void EnforceBans(ILandObject land, ScenePresence avatar)
1970 {
1971 if (avatar.AbsolutePosition.Z > LandChannel.BAN_LINE_SAFETY_HIEGHT)
1972 return;
1973
1974 if (land.IsEitherBannedOrRestricted(avatar.UUID))
1975 {
1976 if (land.ContainsPoint(Convert.ToInt32(avatar.lastKnownAllowedPosition.X), Convert.ToInt32(avatar.lastKnownAllowedPosition.Y)))
1977 {
1978 Vector3? pos = m_scene.GetNearestAllowedPosition(avatar);
1979 if (pos == null)
1980 m_scene.TeleportClientHome(avatar.UUID, avatar.ControllingClient);
1981 else
1982 ForceAvatarToPosition(avatar, (Vector3)pos);
1983 }
1984 else
1985 {
1986 ForceAvatarToPosition(avatar, avatar.lastKnownAllowedPosition);
1987 }
1988 }
1989 }
1719 } 1990 }
1720} \ No newline at end of file 1991}
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index 560b862..6c9bb10 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -416,11 +416,45 @@ namespace OpenSim.Region.CoreModules.World.Land
416 return false; 416 return false;
417 } 417 }
418 418
419 public bool HasGroupAccess(UUID avatar)
420 {
421 if (LandData.GroupID != UUID.Zero && (LandData.Flags & (uint)ParcelFlags.UseAccessGroup) == (uint)ParcelFlags.UseAccessGroup)
422 {
423 ScenePresence sp;
424 if (!m_scene.TryGetScenePresence(avatar, out sp))
425 {
426 IGroupsModule groupsModule = m_scene.RequestModuleInterface<IGroupsModule>();
427 if (groupsModule == null)
428 return false;
429
430 GroupMembershipData[] membership = groupsModule.GetMembershipData(avatar);
431 if (membership == null || membership.Length == 0)
432 return false;
433
434 foreach (GroupMembershipData d in membership)
435 {
436 if (d.GroupID == LandData.GroupID)
437 return true;
438 }
439 return false;
440 }
441
442 if (!sp.ControllingClient.IsGroupMember(LandData.GroupID))
443 return false;
444
445 return true;
446 }
447 return false;
448 }
449
419 public bool IsBannedFromLand(UUID avatar) 450 public bool IsBannedFromLand(UUID avatar)
420 { 451 {
421 if (m_scene.Permissions.IsAdministrator(avatar)) 452 if (m_scene.Permissions.IsAdministrator(avatar))
422 return false; 453 return false;
423 454
455 if (m_scene.RegionInfo.EstateSettings.IsEstateManager(avatar))
456 return false;
457
424 if ((LandData.Flags & (uint) ParcelFlags.UseBanList) > 0) 458 if ((LandData.Flags & (uint) ParcelFlags.UseBanList) > 0)
425 { 459 {
426 if (LandData.ParcelAccessList.FindIndex( 460 if (LandData.ParcelAccessList.FindIndex(
@@ -442,6 +476,9 @@ namespace OpenSim.Region.CoreModules.World.Land
442 if (m_scene.Permissions.IsAdministrator(avatar)) 476 if (m_scene.Permissions.IsAdministrator(avatar))
443 return false; 477 return false;
444 478
479 if (m_scene.RegionInfo.EstateSettings.IsEstateManager(avatar))
480 return false;
481
445 if ((LandData.Flags & (uint) ParcelFlags.UseAccessList) > 0) 482 if ((LandData.Flags & (uint) ParcelFlags.UseAccessList) > 0)
446 { 483 {
447 if (LandData.ParcelAccessList.FindIndex( 484 if (LandData.ParcelAccessList.FindIndex(
@@ -452,9 +489,13 @@ namespace OpenSim.Region.CoreModules.World.Land
452 return false; 489 return false;
453 }) == -1 && LandData.OwnerID != avatar) 490 }) == -1 && LandData.OwnerID != avatar)
454 { 491 {
455 return true; 492 if (!HasGroupAccess(avatar))
493 {
494 return true;
495 }
456 } 496 }
457 } 497 }
498
458 return false; 499 return false;
459 } 500 }
460 501
diff --git a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
index dca842a..f466194 100644
--- a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
@@ -206,7 +206,7 @@ namespace OpenSim.Region.CoreModules.World.Land
206 if (m_ParcelCounts.TryGetValue(landData.GlobalID, out parcelCounts)) 206 if (m_ParcelCounts.TryGetValue(landData.GlobalID, out parcelCounts))
207 { 207 {
208 UUID landOwner = landData.OwnerID; 208 UUID landOwner = landData.OwnerID;
209 int partCount = obj.Parts.Length; 209 int partCount = obj.GetPartCount();
210 210
211 m_SimwideCounts[landOwner] += partCount; 211 m_SimwideCounts[landOwner] += partCount;
212 if (parcelCounts.Users.ContainsKey(obj.OwnerID)) 212 if (parcelCounts.Users.ContainsKey(obj.OwnerID))
@@ -593,4 +593,4 @@ namespace OpenSim.Region.CoreModules.World.Land
593 } 593 }
594 } 594 }
595 } 595 }
596} \ No newline at end of file 596}
diff --git a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
index be399ff..516189f 100644
--- a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
@@ -179,6 +179,13 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
179 return false; 179 return false;
180 } 180 }
181 181
182 if ((perms & (uint)PermissionMask.Copy) == 0)
183 {
184 if (m_dialogModule != null)
185 m_dialogModule.SendAlertToUser(remoteClient, "This sale has been blocked by the permissions system");
186 return false;
187 }
188
182 AssetBase asset = m_scene.CreateAsset( 189 AssetBase asset = m_scene.CreateAsset(
183 group.GetPartName(localID), 190 group.GetPartName(localID),
184 group.GetPartDescription(localID), 191 group.GetPartDescription(localID),
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
index d7324c6..43b37c7 100644
--- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
@@ -362,7 +362,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
362 362
363 public string Name 363 public string Name
364 { 364 {
365 get { return "PermissionsModule"; } 365 get { return "DefaultPermissionsModule"; }
366 } 366 }
367 367
368 public bool IsSharedModule 368 public bool IsSharedModule
diff --git a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
index 0f37ddd..7f6f4df 100644
--- a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
+++ b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
@@ -28,6 +28,8 @@
28using System; 28using System;
29using System.Reflection; 29using System.Reflection;
30using System.Timers; 30using System.Timers;
31using System.IO;
32using System.Diagnostics;
31using System.Threading; 33using System.Threading;
32using System.Collections.Generic; 34using System.Collections.Generic;
33using log4net; 35using log4net;
@@ -56,13 +58,23 @@ namespace OpenSim.Region.CoreModules.World.Region
56 protected UUID m_Initiator; 58 protected UUID m_Initiator;
57 protected bool m_Notice = false; 59 protected bool m_Notice = false;
58 protected IDialogModule m_DialogModule = null; 60 protected IDialogModule m_DialogModule = null;
61 protected string m_MarkerPath = String.Empty;
59 62
60 public void Initialise(IConfigSource config) 63 public void Initialise(IConfigSource config)
61 { 64 {
65 IConfig restartConfig = config.Configs["RestartModule"];
66 if (restartConfig != null)
67 {
68 m_MarkerPath = restartConfig.GetString("MarkerPath", String.Empty);
69 }
62 } 70 }
63 71
64 public void AddRegion(Scene scene) 72 public void AddRegion(Scene scene)
65 { 73 {
74 if (m_MarkerPath != String.Empty)
75 File.Delete(Path.Combine(m_MarkerPath,
76 scene.RegionInfo.RegionID.ToString()));
77
66 m_Scene = scene; 78 m_Scene = scene;
67 79
68 scene.RegisterModuleInterface<IRestartModule>(this); 80 scene.RegisterModuleInterface<IRestartModule>(this);
@@ -121,6 +133,7 @@ namespace OpenSim.Region.CoreModules.World.Region
121 133
122 if (alerts == null) 134 if (alerts == null)
123 { 135 {
136 CreateMarkerFile();
124 m_Scene.RestartNow(); 137 m_Scene.RestartNow();
125 return; 138 return;
126 } 139 }
@@ -134,6 +147,7 @@ namespace OpenSim.Region.CoreModules.World.Region
134 147
135 if (m_Alerts[0] == 0) 148 if (m_Alerts[0] == 0)
136 { 149 {
150 CreateMarkerFile();
137 m_Scene.RestartNow(); 151 m_Scene.RestartNow();
138 return; 152 return;
139 } 153 }
@@ -147,6 +161,7 @@ namespace OpenSim.Region.CoreModules.World.Region
147 { 161 {
148 if (m_Alerts.Count == 0 || m_Alerts[0] == 0) 162 if (m_Alerts.Count == 0 || m_Alerts[0] == 0)
149 { 163 {
164 CreateMarkerFile();
150 m_Scene.RestartNow(); 165 m_Scene.RestartNow();
151 return 0; 166 return 0;
152 } 167 }
@@ -266,5 +281,25 @@ namespace OpenSim.Region.CoreModules.World.Region
266 281
267 ScheduleRestart(UUID.Zero, args[3], times.ToArray(), notice); 282 ScheduleRestart(UUID.Zero, args[3], times.ToArray(), notice);
268 } 283 }
284
285 protected void CreateMarkerFile()
286 {
287 if (m_MarkerPath == String.Empty)
288 return;
289
290 string path = Path.Combine(m_MarkerPath, m_Scene.RegionInfo.RegionID.ToString());
291 try
292 {
293 string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
294 FileStream fs = File.Create(path);
295 System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
296 Byte[] buf = enc.GetBytes(pidstring);
297 fs.Write(buf, 0, buf.Length);
298 fs.Close();
299 }
300 catch (Exception)
301 {
302 }
303 }
269 } 304 }
270} 305}
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
index 9c7b2fa..2da6458 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
@@ -584,6 +584,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
584 m_scene.PhysicsScene.SetTerrain(m_channel.GetFloatsSerialised()); 584 m_scene.PhysicsScene.SetTerrain(m_channel.GetFloatsSerialised());
585 m_scene.SaveTerrain(); 585 m_scene.SaveTerrain();
586 586
587 m_scene.EventManager.TriggerTerrainUpdate();
588
587 // Clients who look at the map will never see changes after they looked at the map, so i've commented this out. 589 // Clients who look at the map will never see changes after they looked at the map, so i've commented this out.
588 //m_scene.CreateTerrainTexture(true); 590 //m_scene.CreateTerrainTexture(true);
589 } 591 }
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
index 00959b0..56c59bd 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
@@ -86,9 +86,9 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
86 86
87 private void OnMapNameRequest(IClientAPI remoteClient, string mapName, uint flags) 87 private void OnMapNameRequest(IClientAPI remoteClient, string mapName, uint flags)
88 { 88 {
89 if (mapName.Length < 3) 89 if (mapName.Length < 2)
90 { 90 {
91 remoteClient.SendAlertMessage("Use a search string with at least 3 characters"); 91 remoteClient.SendAlertMessage("Use a search string with at least 2 characters");
92 return; 92 return;
93 } 93 }
94 94
@@ -106,7 +106,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
106 else if (regionInfos.Count == 0 && mapName.StartsWith("http://")) 106 else if (regionInfos.Count == 0 && mapName.StartsWith("http://"))
107 remoteClient.SendAlertMessage("Hyperlink could not be established."); 107 remoteClient.SendAlertMessage("Hyperlink could not be established.");
108 108
109 m_log.DebugFormat("[MAPSEARCHMODULE]: search {0} returned {1} regions. Flags={2}", mapName, regionInfos.Count, flags); 109 //m_log.DebugFormat("[MAPSEARCHMODULE]: search {0} returned {1} regions", mapName, regionInfos.Count);
110 List<MapBlockData> blocks = new List<MapBlockData>(); 110 List<MapBlockData> blocks = new List<MapBlockData>();
111 111
112 MapBlockData data; 112 MapBlockData data;
@@ -135,7 +135,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
135 data.Agents = 0; 135 data.Agents = 0;
136 data.Access = 255; 136 data.Access = 255;
137 data.MapImageId = UUID.Zero; 137 data.MapImageId = UUID.Zero;
138 data.Name = ""; // mapName; 138 data.Name = mapName;
139 data.RegionFlags = 0; 139 data.RegionFlags = 0;
140 data.WaterHeight = 0; // not used 140 data.WaterHeight = 0; // not used
141 data.X = 0; 141 data.X = 0;
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
index 6e142bb..ca5529d9 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
@@ -1078,7 +1078,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1078 } 1078 }
1079 else 1079 else
1080 { 1080 {
1081 OSDArray responsearr = new OSDArray(m_scene.GetRootAgentCount()); 1081 OSDArray responsearr = new OSDArray(); // Don't preallocate. MT (m_scene.GetRootAgentCount());
1082 m_scene.ForEachScenePresence(delegate(ScenePresence sp) 1082 m_scene.ForEachScenePresence(delegate(ScenePresence sp)
1083 { 1083 {
1084 OSDMap responsemapdata = new OSDMap(); 1084 OSDMap responsemapdata = new OSDMap();
diff --git a/OpenSim/Region/Examples/SimpleModule/ComplexObject.cs b/OpenSim/Region/Examples/SimpleModule/ComplexObject.cs
index e951bef..7a0ce51 100644
--- a/OpenSim/Region/Examples/SimpleModule/ComplexObject.cs
+++ b/OpenSim/Region/Examples/SimpleModule/ComplexObject.cs
@@ -25,6 +25,7 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System.Collections.Generic;
28using OpenMetaverse; 29using OpenMetaverse;
29using OpenSim.Framework; 30using OpenSim.Framework;
30using OpenSim.Region.Framework.Scenes; 31using OpenSim.Region.Framework.Scenes;
@@ -110,7 +111,7 @@ namespace OpenSim.Region.Examples.SimpleModule
110 { 111 {
111 m_parts.Remove(part.UUID); 112 m_parts.Remove(part.UUID);
112 113
113 remoteClient.SendKillObject(m_regionHandle, part.LocalId); 114 remoteClient.SendKillObject(m_regionHandle, new List<uint>() { part.LocalId} );
114 remoteClient.AddMoney(1); 115 remoteClient.AddMoney(1);
115 remoteClient.SendChatMessage("Poof!", 1, AbsolutePosition, "Party Party", UUID.Zero, (byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully); 116 remoteClient.SendChatMessage("Poof!", 1, AbsolutePosition, "Party Party", UUID.Zero, (byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully);
116 } 117 }
@@ -121,7 +122,7 @@ namespace OpenSim.Region.Examples.SimpleModule
121 { 122 {
122 m_parts.Remove(m_rootPart.UUID); 123 m_parts.Remove(m_rootPart.UUID);
123 m_scene.DeleteSceneObject(this, false); 124 m_scene.DeleteSceneObject(this, false);
124 remoteClient.SendKillObject(m_regionHandle, m_rootPart.LocalId); 125 remoteClient.SendKillObject(m_regionHandle, new List<uint>() { m_rootPart.LocalId });
125 remoteClient.AddMoney(50); 126 remoteClient.AddMoney(50);
126 remoteClient.SendChatMessage("KABLAM!!!", 1, AbsolutePosition, "Groupie Groupie", UUID.Zero, (byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully); 127 remoteClient.SendChatMessage("KABLAM!!!", 1, AbsolutePosition, "Groupie Groupie", UUID.Zero, (byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully);
127 } 128 }
diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
index 56b46d7..cdce36e 100644
--- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
+++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
@@ -79,7 +79,7 @@ namespace OpenSim.Region.Examples.SimpleModule
79 public event DisconnectUser OnDisconnectUser; 79 public event DisconnectUser OnDisconnectUser;
80 public event RequestAvatarProperties OnRequestAvatarProperties; 80 public event RequestAvatarProperties OnRequestAvatarProperties;
81 public event SetAlwaysRun OnSetAlwaysRun; 81 public event SetAlwaysRun OnSetAlwaysRun;
82 82 public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy;
83 public event DeRezObject OnDeRezObject; 83 public event DeRezObject OnDeRezObject;
84 public event Action<IClientAPI> OnRegionHandShakeReply; 84 public event Action<IClientAPI> OnRegionHandShakeReply;
85 public event GenericCall1 OnRequestWearables; 85 public event GenericCall1 OnRequestWearables;
@@ -255,7 +255,7 @@ namespace OpenSim.Region.Examples.SimpleModule
255 public event ClassifiedInfoRequest OnClassifiedInfoRequest; 255 public event ClassifiedInfoRequest OnClassifiedInfoRequest;
256 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate; 256 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate;
257 public event ClassifiedDelete OnClassifiedDelete; 257 public event ClassifiedDelete OnClassifiedDelete;
258 public event ClassifiedDelete OnClassifiedGodDelete; 258 public event ClassifiedGodDelete OnClassifiedGodDelete;
259 259
260 public event EventNotificationAddRequest OnEventNotificationAddRequest; 260 public event EventNotificationAddRequest OnEventNotificationAddRequest;
261 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest; 261 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest;
@@ -429,7 +429,7 @@ namespace OpenSim.Region.Examples.SimpleModule
429 429
430 } 430 }
431 431
432 public virtual void SendKillObject(ulong regionHandle, uint localID) 432 public virtual void SendKillObject(ulong regionHandle, List<uint> localID)
433 { 433 {
434 } 434 }
435 435
@@ -827,6 +827,11 @@ namespace OpenSim.Region.Examples.SimpleModule
827 827
828 public void Close() 828 public void Close()
829 { 829 {
830 Close(true);
831 }
832
833 public void Close(bool sendStop)
834 {
830 } 835 }
831 836
832 public void Start() 837 public void Start()
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index 6cc64c6..788f42b 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>
@@ -113,18 +118,15 @@ namespace OpenSim.Region.Framework.Interfaces
113 /// <summary> 118 /// <summary>
114 /// Update the user inventory to show a detach. 119 /// Update the user inventory to show a detach.
115 /// </summary> 120 /// </summary>
116 /// <param name="itemID">/param> 121 /// <param name="itemID">
117 /// <param name="remoteClient"></param> 122 /// A <see cref="UUID"/>
123 /// </param>
124 /// <param name="remoteClient">
125 /// A <see cref="IClientAPI"/>
126 /// </param>
118 void ShowDetachInUserInventory(UUID itemID, IClientAPI remoteClient); 127 void ShowDetachInUserInventory(UUID itemID, IClientAPI remoteClient);
119 128
120 /// <summary> 129 /// <summary>
121 /// Update the position of an attachment.
122 /// </summary>
123 /// <param name="sog"></param>
124 /// <param name="pos"></param>
125 void UpdateAttachmentPosition(SceneObjectGroup sog, Vector3 pos);
126
127 /// <summary>
128 /// Update the user inventory with a changed attachment 130 /// Update the user inventory with a changed attachment
129 /// </summary> 131 /// </summary>
130 /// <param name="remoteClient"> 132 /// <param name="remoteClient">
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
index 15060fd..4b17b9a 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
@@ -115,6 +115,8 @@ namespace OpenSim.Region.Framework.Interfaces
115 /// <param name="stateSource"></param> 115 /// <param name="stateSource"></param>
116 void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource); 116 void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
117 117
118 ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
119
118 /// <summary> 120 /// <summary>
119 /// Stop a script which is in this prim's inventory. 121 /// Stop a script which is in this prim's inventory.
120 /// </summary> 122 /// </summary>
@@ -229,5 +231,6 @@ namespace OpenSim.Region.Framework.Interfaces
229 /// A <see cref="Dictionary`2"/> 231 /// A <see cref="Dictionary`2"/>
230 /// </returns> 232 /// </returns>
231 Dictionary<UUID, string> GetScriptStates(); 233 Dictionary<UUID, string> GetScriptStates();
234 Dictionary<UUID, string> GetScriptStates(bool oldIDs);
232 } 235 }
233} 236}
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
index 07e97d5..c38ecd9 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
@@ -40,11 +40,11 @@ namespace OpenSim.Region.Framework.Interfaces
40 void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, 40 void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position,
41 Vector3 lookAt, uint teleportFlags); 41 Vector3 lookAt, uint teleportFlags);
42 42
43 bool TeleportHome(UUID id, IClientAPI client);
44
43 void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, 45 void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination,
44 Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq); 46 Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq);
45 47
46 void TeleportHome(UUID id, IClientAPI client);
47
48 bool Cross(ScenePresence agent, bool isFlying); 48 bool Cross(ScenePresence agent, bool isFlying);
49 49
50 void AgentArrivedAtDestination(UUID agent); 50 void AgentArrivedAtDestination(UUID agent);
diff --git a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
index 721f0ee..72e79ed 100644
--- a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
@@ -45,5 +45,7 @@ namespace OpenSim.Region.Framework.Interfaces
45 /// Tell all clients about the current state of the region (terrain textures, water height, etc.). 45 /// Tell all clients about the current state of the region (terrain textures, water height, etc.).
46 /// </summary> 46 /// </summary>
47 void sendRegionHandshakeToAll(); 47 void sendRegionHandshakeToAll();
48 void TriggerEstateInfoChange();
49 void TriggerRegionInfoChange();
48 } 50 }
49} 51}
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/IScriptModule.cs b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
index d9752e6..641e226 100644
--- a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
@@ -51,6 +51,8 @@ namespace OpenSim.Region.Framework.Interfaces
51 51
52 ArrayList GetScriptErrors(UUID itemID); 52 ArrayList GetScriptErrors(UUID itemID);
53 53
54 bool HasScript(UUID itemID, out bool running);
55
54 void SaveAllState(); 56 void SaveAllState();
55 } 57 }
56} 58}
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/Interfaces/IUserAccountCacheModule.cs b/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs
new file mode 100644
index 0000000..d1a4d8e
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs
@@ -0,0 +1,13 @@
1///////////////////////////////////////////////////////////////////
2//
3// (c) Careminster Limited, Melanie Thielker and the Meta7 Team
4//
5// This file is not open source. All rights reserved
6//
7
8using OpenSim.Region.Framework.Scenes;
9
10public interface IUserAccountCacheModule
11{
12 void Remove(string name);
13}
diff --git a/OpenSim/Region/Framework/ModuleLoader.cs b/OpenSim/Region/Framework/ModuleLoader.cs
index 14ecd44..32ee674 100644
--- a/OpenSim/Region/Framework/ModuleLoader.cs
+++ b/OpenSim/Region/Framework/ModuleLoader.cs
@@ -227,7 +227,8 @@ namespace OpenSim.Region.Framework
227 pluginAssembly.FullName, e.Message, e.StackTrace); 227 pluginAssembly.FullName, e.Message, e.StackTrace);
228 228
229 // justincc: Right now this is fatal to really get the user's attention 229 // justincc: Right now this is fatal to really get the user's attention
230 throw e; 230 // TomMeta: WTF? No, how about we /don't/ throw a fatal exception when there's no need to?
231 //throw e;
231 } 232 }
232 } 233 }
233 234
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
index 4865481..9c103cb 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
@@ -53,11 +53,17 @@ namespace OpenSim.Region.Framework.Scenes.Animation
53 { 53 {
54 get { return m_movementAnimation; } 54 get { return m_movementAnimation; }
55 } 55 }
56 protected string m_movementAnimation = "DEFAULT"; 56 // protected string m_movementAnimation = "DEFAULT"; //KF: 'DEFAULT' does not exist!
57 57 protected string m_movementAnimation = "CROUCH"; //KF: CROUCH ensures reliable Av Anim. init.
58 private int m_animTickFall; 58 private int m_animTickFall;
59 private int m_animTickJump; 59// private int m_animTickJump;
60 60 public int m_animTickJump; // ScenePresence has to see this to control +Z force
61 public bool m_jumping = false; // Add for jumping
62 public float m_jumpVelocity = 0f; // Add for jumping
63 private int m_landing = 0; // Add for jumping
64 public bool m_falling = false; // Add for falling
65 private float m_fallHeight; // Add for falling
66
61 /// <value> 67 /// <value>
62 /// The scene presence that this animator applies to 68 /// The scene presence that this animator applies to
63 /// </value> 69 /// </value>
@@ -114,7 +120,9 @@ namespace OpenSim.Region.Framework.Scenes.Animation
114 120
115 public void ResetAnimations() 121 public void ResetAnimations()
116 { 122 {
123Console.WriteLine("ResetA.............");
117 m_animations.Clear(); 124 m_animations.Clear();
125TrySetMovementAnimation("STAND");
118 } 126 }
119 127
120 /// <summary> 128 /// <summary>
@@ -123,8 +131,6 @@ namespace OpenSim.Region.Framework.Scenes.Animation
123 /// </summary> 131 /// </summary>
124 public void TrySetMovementAnimation(string anim) 132 public void TrySetMovementAnimation(string anim)
125 { 133 {
126 //m_log.DebugFormat("Updating movement animation to {0}", anim);
127
128 if (!m_scenePresence.IsChildAgent) 134 if (!m_scenePresence.IsChildAgent)
129 { 135 {
130 if (m_animations.TrySetDefaultAnimation( 136 if (m_animations.TrySetDefaultAnimation(
@@ -142,14 +148,14 @@ namespace OpenSim.Region.Framework.Scenes.Animation
142 /// </summary> 148 /// </summary>
143 public string GetMovementAnimation() 149 public string GetMovementAnimation()
144 { 150 {
145 const float FALL_DELAY = 0.33f; 151//Console.WriteLine("GMA-------"); //##
146 const float PREJUMP_DELAY = 0.25f; 152//#@ const float FALL_DELAY = 0.33f;
147 153 const float FALL_DELAY = 800f; //## mS
154//rm for jumping const float PREJUMP_DELAY = 0.25f;
155 const float PREJUMP_DELAY = 200f; // mS add for jumping
156 const float JUMP_PERIOD = 800f; // mS add for jumping
148 #region Inputs 157 #region Inputs
149 if (m_scenePresence.SitGround) 158
150 {
151 return "SIT_GROUND_CONSTRAINED";
152 }
153 AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags; 159 AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags;
154 PhysicsActor actor = m_scenePresence.PhysicsActor; 160 PhysicsActor actor = m_scenePresence.PhysicsActor;
155 161
@@ -159,11 +165,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
159 Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix); 165 Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix);
160 166
161 // Check control flags 167 // Check control flags
162 bool heldForward = 168 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)); 169 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; 170 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; 171 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; 172 //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; 173 //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; 174 bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS;
@@ -182,8 +187,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
182 187
183 // Is the avatar trying to move? 188 // Is the avatar trying to move?
184// bool moving = (move != Vector3.Zero); 189// bool moving = (move != Vector3.Zero);
185 bool jumping = m_animTickJump != 0; 190// rm for jumping bool jumping = m_animTickJump != 0;
186
187 #endregion Inputs 191 #endregion Inputs
188 192
189 #region Flying 193 #region Flying
@@ -192,6 +196,11 @@ namespace OpenSim.Region.Framework.Scenes.Animation
192 { 196 {
193 m_animTickFall = 0; 197 m_animTickFall = 0;
194 m_animTickJump = 0; 198 m_animTickJump = 0;
199 m_jumping = false; //add for jumping
200 m_falling = true; //add for falling
201 m_jumpVelocity = 0f; //add for jumping
202 actor.Selected = false; //add for jumping flag
203 m_fallHeight = actor.Position.Z; // save latest flying height
195 204
196 if (move.X != 0f || move.Y != 0f) 205 if (move.X != 0f || move.Y != 0f)
197 { 206 {
@@ -203,8 +212,11 @@ namespace OpenSim.Region.Framework.Scenes.Animation
203 } 212 }
204 else if (move.Z < 0f) 213 else if (move.Z < 0f)
205 { 214 {
206 if (actor != null && actor.IsColliding) 215 if (actor != null && actor.IsColliding)
216 { //##
217//Console.WriteLine("LAND FLYING"); // ##
207 return "LAND"; 218 return "LAND";
219 } //#
208 else 220 else
209 return "HOVER_DOWN"; 221 return "HOVER_DOWN";
210 } 222 }
@@ -218,48 +230,127 @@ namespace OpenSim.Region.Framework.Scenes.Animation
218 230
219 #region Falling/Floating/Landing 231 #region Falling/Floating/Landing
220 232
221 if (actor == null || !actor.IsColliding) 233// rm for jumping if (actor == null || !actor.IsColliding)
234 if ((actor == null || !actor.IsColliding) && !m_jumping) // add for jumping
222 { 235 {
223 float fallElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f; 236// rm float fallElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f;
237 float fallElapsed = (float)(Environment.TickCount - m_animTickFall); // add, in mS
224 float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f; 238 float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f;
239//Console.WriteLine("falling t={0} v={1}", fallElapsed, fallVelocity); //##
240
241// rm for fall if (m_animTickFall == 0 || (fallElapsed > FALL_DELAY && fallVelocity >= 0.0f))
242 if (!m_jumping && (fallVelocity < -3.0f) ) m_falling = true; // add for falling and jumping
225 243
226 if (m_animTickFall == 0 || (fallElapsed > FALL_DELAY && fallVelocity >= 0.0f)) 244 if (m_animTickFall == 0 || (fallVelocity >= 0.0f)) // add for jumping
245 // not falling yet or going up
227 { 246 {
228 // Just started falling 247 // reset start of fall time
229 m_animTickFall = Environment.TickCount; 248 m_animTickFall = Environment.TickCount;
230 } 249 }
231 else if (!jumping && fallElapsed > FALL_DELAY) 250// else if (!jumping && fallElapsed > FALL_DELAY)
251 else if (!m_jumping && (fallElapsed > FALL_DELAY) && (fallVelocity < -3.0f) && (m_scenePresence.m_wasFlying)) // add for falling and jumping
232 { 252 {
233 // Falling long enough to trigger the animation 253 // Falling long enough to trigger the animation
254//Console.WriteLine("FALLDOWN"); //##
234 return "FALLDOWN"; 255 return "FALLDOWN";
235 } 256 }
236 else if (m_animTickJump == -1)
237 {
238 m_animTickJump = 0;
239 return "STAND";
240 }
241 257
242 return m_movementAnimation; 258 return m_movementAnimation;
243 } 259 }
244 260
245 #endregion Falling/Floating/Landing 261 #endregion Falling/Floating/Landing
246 262
263
264 #region Jumping // section added for jumping...
265
266 int jumptime;
267 jumptime = Environment.TickCount - m_animTickJump;
268
269
270 if ((move.Z > 0f) && (!m_jumping))
271 {
272//Console.WriteLine("PJ {0}", jumptime); //##
273 // Start jumping, prejump
274 m_animTickFall = 0;
275 m_jumping = true;
276 m_falling = false;
277 actor.Selected = true; // borrowed for jmping flag
278 m_animTickJump = Environment.TickCount;
279 m_jumpVelocity = 0.35f;
280 return "PREJUMP";
281 }
282
283 if(m_jumping)
284 {
285 if ( (jumptime > (JUMP_PERIOD * 1.5f)) && actor.IsColliding)
286 {
287//Console.WriteLine("LA {0}", jumptime); //##
288 // end jumping
289 m_jumping = false;
290 m_falling = false;
291 actor.Selected = false; // borrowed for jumping flag
292 m_jumpVelocity = 0f;
293 m_animTickFall = Environment.TickCount;
294 return "LAND";
295 }
296 else if (jumptime > JUMP_PERIOD)
297 {
298//Console.WriteLine("JD {0}", jumptime); //##
299 // jump down
300 m_jumpVelocity = 0f;
301 return "JUMP";
302 }
303 else if (jumptime > PREJUMP_DELAY)
304 {
305//Console.WriteLine("JU {0}", jumptime); //##
306 // jump up
307 m_jumping = true;
308 m_jumpVelocity = 10f;
309 return "JUMP";
310 }
311 }
312
313 #endregion Jumping // end added section
314
247 #region Ground Movement 315 #region Ground Movement
248 316
249 if (m_movementAnimation == "FALLDOWN") 317 if (m_movementAnimation == "FALLDOWN")
250 { 318 {
319 m_falling = false;
251 m_animTickFall = Environment.TickCount; 320 m_animTickFall = Environment.TickCount;
252
253 // TODO: SOFT_LAND support 321 // TODO: SOFT_LAND support
254 return "LAND"; 322 float fallHeight = m_fallHeight - actor.Position.Z;
323//Console.WriteLine("Hit from {0}", fallHeight); //##
324 if (fallHeight > 15.0f) // add for falling
325 return "STANDUP";
326 else if (fallHeight > 8.0f) // add for falling
327 return "SOFT_LAND"; // add for falling
328 else // add for falling
329 return "LAND"; // add for falling
255 } 330 }
256 else if (m_movementAnimation == "LAND") 331// rm jumping float landElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f;
332// rm jumping if ((m_animTickFall != 0) && (landElapsed <= FALL_DELAY))
333// rm for landing return "LAND";
334 else if ((m_movementAnimation == "LAND") || (m_movementAnimation == "SOFT_LAND") || (m_movementAnimation == "STANDUP"))
257 { 335 {
258 float landElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f; 336 int landElapsed = Environment.TickCount - m_animTickFall; // add for jumping
259 if ((m_animTickFall != 0) && (landElapsed <= FALL_DELAY)) 337 int limit = 1000; // add for jumping
260 return "LAND"; 338 if(m_movementAnimation == "LAND") limit = 350; // add for jumping
261 } 339 // NB if the above is set too long a weird anim reset from some place prevents STAND from being sent to client
262 340
341 if ((m_animTickFall != 0) && (landElapsed <= limit)) // add for jumping
342 {
343//Console.WriteLine("Lelapse {0}", m_movementAnimation); //##
344 return m_movementAnimation;
345 }
346 else
347 {
348//Console.WriteLine("end/STAND"); //##
349 m_fallHeight = actor.Position.Z; // save latest flying height
350 return "STAND";
351 }
352 }
353/* This section removed, replaced by jumping section
263 m_animTickFall = 0; 354 m_animTickFall = 0;
264 355
265 if (move.Z > 0f) 356 if (move.Z > 0f)
@@ -271,7 +362,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
271 m_animTickJump = Environment.TickCount; 362 m_animTickJump = Environment.TickCount;
272 return "PREJUMP"; 363 return "PREJUMP";
273 } 364 }
274 else if (Environment.TickCount - m_animTickJump > PREJUMP_DELAY * 1000.0f) 365 else if (Environment.TickCount - m_animTickJump > PREJUMP_DELAY * 800.0f)
275 { 366 {
276 // Start actual jump 367 // Start actual jump
277 if (m_animTickJump == -1) 368 if (m_animTickJump == -1)
@@ -284,37 +375,40 @@ namespace OpenSim.Region.Framework.Scenes.Animation
284 m_animTickJump = -1; 375 m_animTickJump = -1;
285 return "JUMP"; 376 return "JUMP";
286 } 377 }
287 else
288 return "JUMP";
289 } 378 }
290 else 379 else
291 { 380 {
292 // Not jumping 381 // Not jumping
293 m_animTickJump = 0; 382 m_animTickJump = 0;
294 383 */
295 if (move.X != 0f || move.Y != 0f) 384 // next section moved outside paren. and realigned for jumping
296 { 385 if (move.X != 0f || move.Y != 0f)
297 // Walking / crouchwalking / running 386 {
298 if (move.Z < 0f) 387 m_fallHeight = actor.Position.Z; // save latest flying height
299 return "CROUCHWALK"; 388 m_falling = false; // Add for falling
300 else if (m_scenePresence.SetAlwaysRun) 389 // Walking / crouchwalking / running
301 return "RUN"; 390 if (move.Z < 0f)
302 else 391 return "CROUCHWALK";
303 return "WALK"; 392 else if (m_scenePresence.SetAlwaysRun)
304 } 393 return "RUN";
305 else 394 else
306 { 395 return "WALK";
307 // Not walking
308 if (move.Z < 0f)
309 return "CROUCH";
310 else
311 return "STAND";
312 }
313 } 396 }
314 397// rm for jumping else
398 else if (!m_jumping) // add for jumping
399 {
400 m_falling = false; // Add for falling
401 // Not walking
402 if (move.Z < 0f)
403 return "CROUCH";
404 else
405 return "STAND";
406 }
407 // end section realign for jumping
315 #endregion Ground Movement 408 #endregion Ground Movement
316 409
317 //return m_movementAnimation; 410 m_falling = false; // Add for falling
411 return m_movementAnimation;
318 } 412 }
319 413
320 /// <summary> 414 /// <summary>
@@ -323,7 +417,15 @@ namespace OpenSim.Region.Framework.Scenes.Animation
323 public void UpdateMovementAnimations() 417 public void UpdateMovementAnimations()
324 { 418 {
325 m_movementAnimation = GetMovementAnimation(); 419 m_movementAnimation = GetMovementAnimation();
326 TrySetMovementAnimation(m_movementAnimation); 420/* if (m_movementAnimation == "PREJUMP" && !m_scenePresence.Scene.m_usePreJump)
421 {
422 // This was the previous behavior before PREJUMP
423 TrySetMovementAnimation("JUMP");
424 }
425 else
426 { removed for jumping */
427 TrySetMovementAnimation(m_movementAnimation);
428// rm for jumping }
327 } 429 }
328 430
329 public UUID[] GetAnimationArray() 431 public UUID[] GetAnimationArray()
diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
index 3423542..088839d 100644
--- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
+++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
@@ -104,8 +104,15 @@ namespace OpenSim.Region.Framework.Scenes
104 // better than losing the object for now. 104 // better than losing the object for now.
105 if (permissionToDelete) 105 if (permissionToDelete)
106 { 106 {
107 List<uint> killIDs = new List<uint>();
108
107 foreach (SceneObjectGroup g in objectGroups) 109 foreach (SceneObjectGroup g in objectGroups)
110 {
111 killIDs.Add(g.LocalId);
108 g.DeleteGroupFromScene(false); 112 g.DeleteGroupFromScene(false);
113 }
114
115 m_scene.SendKillObject(killIDs);
109 } 116 }
110 } 117 }
111 118
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index b67937d..3ec4e59 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -55,8 +55,12 @@ namespace OpenSim.Region.Framework.Scenes
55 55
56 public delegate void OnTerrainTickDelegate(); 56 public delegate void OnTerrainTickDelegate();
57 57
58 public delegate void OnTerrainUpdateDelegate();
59
58 public event OnTerrainTickDelegate OnTerrainTick; 60 public event OnTerrainTickDelegate OnTerrainTick;
59 61
62 public event OnTerrainUpdateDelegate OnTerrainUpdate;
63
60 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup); 64 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup);
61 65
62 public event OnBackupDelegate OnBackup; 66 public event OnBackupDelegate OnBackup;
@@ -776,6 +780,26 @@ namespace OpenSim.Region.Framework.Scenes
776 } 780 }
777 } 781 }
778 } 782 }
783 public void TriggerTerrainUpdate()
784 {
785 OnTerrainUpdateDelegate handlerTerrainUpdate = OnTerrainUpdate;
786 if (handlerTerrainUpdate != null)
787 {
788 foreach (OnTerrainUpdateDelegate d in handlerTerrainUpdate.GetInvocationList())
789 {
790 try
791 {
792 d();
793 }
794 catch (Exception e)
795 {
796 m_log.ErrorFormat(
797 "[EVENT MANAGER]: Delegate for TriggerTerrainUpdate failed - continuing. {0} {1}",
798 e.Message, e.StackTrace);
799 }
800 }
801 }
802 }
779 803
780 public void TriggerTerrainTick() 804 public void TriggerTerrainTick()
781 { 805 {
diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
index 4595a29..657df15 100644
--- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs
+++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
@@ -158,7 +158,7 @@ namespace OpenSim.Region.Framework.Scenes
158 158
159 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity) 159 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity)
160 { 160 {
161 uint pqueue = ComputeDistancePriority(client,entity,true); 161 uint pqueue = ComputeDistancePriority(client,entity,false);
162 162
163 ScenePresence presence = m_scene.GetScenePresence(client.AgentId); 163 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
164 if (presence != null) 164 if (presence != null)
@@ -228,7 +228,7 @@ namespace OpenSim.Region.Framework.Scenes
228 228
229 for (int i = 0; i < queues - 1; i++) 229 for (int i = 0; i < queues - 1; i++)
230 { 230 {
231 if (distance < 10 * Math.Pow(2.0,i)) 231 if (distance < 30 * Math.Pow(2.0,i))
232 break; 232 break;
233 pqueue++; 233 pqueue++;
234 } 234 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index f37f94a..c04bbb4 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -99,34 +99,22 @@ namespace OpenSim.Region.Framework.Scenes
99 /// <param name="item"></param> 99 /// <param name="item"></param>
100 public bool AddInventoryItem(InventoryItemBase item) 100 public bool AddInventoryItem(InventoryItemBase item)
101 { 101 {
102 if (UUID.Zero == item.Folder) 102 InventoryFolderBase folder;
103
104 if (item.Folder == UUID.Zero)
103 { 105 {
104 InventoryFolderBase f = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType); 106 folder = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType);
105 if (f != null) 107 if (folder == null)
106 {
107// m_log.DebugFormat(
108// "[LOCAL INVENTORY SERVICES CONNECTOR]: Found folder {0} type {1} for item {2}",
109// f.Name, (AssetType)f.Type, item.Name);
110
111 item.Folder = f.ID;
112 }
113 else
114 { 108 {
115 f = InventoryService.GetRootFolder(item.Owner); 109 folder = InventoryService.GetRootFolder(item.Owner);
116 if (f != null) 110
117 { 111 if (folder == null)
118 item.Folder = f.ID;
119 }
120 else
121 {
122 m_log.WarnFormat(
123 "[AGENT INVENTORY]: Could not find root folder for {0} when trying to add item {1} with no parent folder specified",
124 item.Owner, item.Name);
125 return false; 112 return false;
126 }
127 } 113 }
114
115 item.Folder = folder.ID;
128 } 116 }
129 117
130 if (InventoryService.AddItem(item)) 118 if (InventoryService.AddItem(item))
131 { 119 {
132 int userlevel = 0; 120 int userlevel = 0;
@@ -252,8 +240,7 @@ namespace OpenSim.Region.Framework.Scenes
252 240
253 // Update item with new asset 241 // Update item with new asset
254 item.AssetID = asset.FullID; 242 item.AssetID = asset.FullID;
255 if (group.UpdateInventoryItem(item)) 243 group.UpdateInventoryItem(item);
256 remoteClient.SendAgentAlertMessage("Script saved", false);
257 244
258 part.GetProperties(remoteClient); 245 part.GetProperties(remoteClient);
259 246
@@ -264,12 +251,7 @@ namespace OpenSim.Region.Framework.Scenes
264 { 251 {
265 // Needs to determine which engine was running it and use that 252 // Needs to determine which engine was running it and use that
266 // 253 //
267 part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0); 254 errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 0);
268 errors = part.Inventory.GetScriptErrors(item.ItemID);
269 }
270 else
271 {
272 remoteClient.SendAgentAlertMessage("Script saved", false);
273 } 255 }
274 part.ParentGroup.ResumeScripts(); 256 part.ParentGroup.ResumeScripts();
275 return errors; 257 return errors;
@@ -328,6 +310,7 @@ namespace OpenSim.Region.Framework.Scenes
328 { 310 {
329 if (UUID.Zero == transactionID) 311 if (UUID.Zero == transactionID)
330 { 312 {
313 item.Flags = (item.Flags & ~(uint)255) | (itemUpd.Flags & (uint)255);
331 item.Name = itemUpd.Name; 314 item.Name = itemUpd.Name;
332 item.Description = itemUpd.Description; 315 item.Description = itemUpd.Description;
333 if (item.NextPermissions != (itemUpd.NextPermissions & item.BasePermissions)) 316 if (item.NextPermissions != (itemUpd.NextPermissions & item.BasePermissions))
@@ -706,6 +689,8 @@ namespace OpenSim.Region.Framework.Scenes
706 return; 689 return;
707 } 690 }
708 691
692 if (newName == null) newName = item.Name;
693
709 AssetBase asset = AssetService.Get(item.AssetID.ToString()); 694 AssetBase asset = AssetService.Get(item.AssetID.ToString());
710 695
711 if (asset != null) 696 if (asset != null)
@@ -759,6 +744,24 @@ namespace OpenSim.Region.Framework.Scenes
759 } 744 }
760 745
761 /// <summary> 746 /// <summary>
747 /// Move an item within the agent's inventory, and leave a copy (used in making a new outfit)
748 /// </summary>
749 public void MoveInventoryItemsLeaveCopy(IClientAPI remoteClient, List<InventoryItemBase> items, UUID destfolder)
750 {
751 List<InventoryItemBase> moveitems = new List<InventoryItemBase>();
752 foreach (InventoryItemBase b in items)
753 {
754 CopyInventoryItem(remoteClient, 0, remoteClient.AgentId, b.ID, b.Folder, null);
755 InventoryItemBase n = InventoryService.GetItem(b);
756 n.Folder = destfolder;
757 moveitems.Add(n);
758 remoteClient.SendInventoryItemCreateUpdate(n, 0);
759 }
760
761 MoveInventoryItem(remoteClient, moveitems);
762 }
763
764 /// <summary>
762 /// Move an item within the agent's inventory. 765 /// Move an item within the agent's inventory.
763 /// </summary> 766 /// </summary>
764 /// <param name="remoteClient"></param> 767 /// <param name="remoteClient"></param>
@@ -959,8 +962,12 @@ namespace OpenSim.Region.Framework.Scenes
959 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID) 962 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID)
960 { 963 {
961 SceneObjectPart part = GetSceneObjectPart(localID); 964 SceneObjectPart part = GetSceneObjectPart(localID);
962 SceneObjectGroup group = part.ParentGroup; 965 SceneObjectGroup group = null;
963 if (group != null) 966 if (part != null)
967 {
968 group = part.ParentGroup;
969 }
970 if (part != null && group != null)
964 { 971 {
965 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId)) 972 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId))
966 return; 973 return;
@@ -1196,6 +1203,10 @@ namespace OpenSim.Region.Framework.Scenes
1196 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)) 1203 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0))
1197 return; 1204 return;
1198 1205
1206 bool overrideNoMod = false;
1207 if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) != 0)
1208 overrideNoMod = true;
1209
1199 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0) 1210 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1200 { 1211 {
1201 // object cannot copy items to an object owned by a different owner 1212 // object cannot copy items to an object owned by a different owner
@@ -1205,7 +1216,7 @@ namespace OpenSim.Region.Framework.Scenes
1205 } 1216 }
1206 1217
1207 // must have both move and modify permission to put an item in an object 1218 // must have both move and modify permission to put an item in an object
1208 if ((part.OwnerMask & ((uint)PermissionMask.Move | (uint)PermissionMask.Modify)) == 0) 1219 if (((part.OwnerMask & (uint)PermissionMask.Modify) == 0) && (!overrideNoMod))
1209 { 1220 {
1210 return; 1221 return;
1211 } 1222 }
@@ -1264,6 +1275,14 @@ namespace OpenSim.Region.Framework.Scenes
1264 1275
1265 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items) 1276 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items)
1266 { 1277 {
1278 SceneObjectPart destPart = GetSceneObjectPart(destID);
1279 if (destPart != null) // Move into a prim
1280 {
1281 foreach(UUID itemID in items)
1282 MoveTaskInventoryItem(destID, host, itemID);
1283 return destID; // Prim folder ID == prim ID
1284 }
1285
1267 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID); 1286 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID);
1268 1287
1269 UUID newFolderID = UUID.Random(); 1288 UUID newFolderID = UUID.Random();
@@ -1433,13 +1452,6 @@ namespace OpenSim.Region.Framework.Scenes
1433 { 1452 {
1434 agentTransactions.HandleTaskItemUpdateFromTransaction( 1453 agentTransactions.HandleTaskItemUpdateFromTransaction(
1435 remoteClient, part, transactionID, currentItem); 1454 remoteClient, part, transactionID, currentItem);
1436
1437 if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1438 remoteClient.SendAgentAlertMessage("Notecard saved", false);
1439 else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1440 remoteClient.SendAgentAlertMessage("Script saved", false);
1441 else
1442 remoteClient.SendAgentAlertMessage("Item saved", false);
1443 } 1455 }
1444 1456
1445 // Base ALWAYS has move 1457 // Base ALWAYS has move
@@ -1580,7 +1592,7 @@ namespace OpenSim.Region.Framework.Scenes
1580 return; 1592 return;
1581 1593
1582 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, 1594 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType,
1583 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), 1595 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n\n touch_start(integer num)\n {\n }\n}"),
1584 remoteClient.AgentId); 1596 remoteClient.AgentId);
1585 AssetService.Store(asset); 1597 AssetService.Store(asset);
1586 1598
@@ -1733,23 +1745,32 @@ namespace OpenSim.Region.Framework.Scenes
1733 // build a list of eligible objects 1745 // build a list of eligible objects
1734 List<uint> deleteIDs = new List<uint>(); 1746 List<uint> deleteIDs = new List<uint>();
1735 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); 1747 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
1736 1748 List<SceneObjectGroup> takeGroups = new List<SceneObjectGroup>();
1737 // Start with true for both, then remove the flags if objects
1738 // that we can't derez are part of the selection
1739 bool permissionToTake = true;
1740 bool permissionToTakeCopy = true;
1741 bool permissionToDelete = true;
1742 1749
1743 foreach (uint localID in localIDs) 1750 foreach (uint localID in localIDs)
1744 { 1751 {
1752 // Start with true for both, then remove the flags if objects
1753 // that we can't derez are part of the selection
1754 bool permissionToTake = true;
1755 bool permissionToTakeCopy = true;
1756 bool permissionToDelete = true;
1757
1745 // Invalid id 1758 // Invalid id
1746 SceneObjectPart part = GetSceneObjectPart(localID); 1759 SceneObjectPart part = GetSceneObjectPart(localID);
1747 if (part == null) 1760 if (part == null)
1761 {
1762 //Client still thinks the object exists, kill it
1763 deleteIDs.Add(localID);
1748 continue; 1764 continue;
1765 }
1749 1766
1750 // Already deleted by someone else 1767 // Already deleted by someone else
1751 if (part.ParentGroup == null || part.ParentGroup.IsDeleted) 1768 if (part.ParentGroup == null || part.ParentGroup.IsDeleted)
1769 {
1770 //Client still thinks the object exists, kill it
1771 deleteIDs.Add(localID);
1752 continue; 1772 continue;
1773 }
1753 1774
1754 // Can't delete child prims 1775 // Can't delete child prims
1755 if (part != part.ParentGroup.RootPart) 1776 if (part != part.ParentGroup.RootPart)
@@ -1757,9 +1778,6 @@ namespace OpenSim.Region.Framework.Scenes
1757 1778
1758 SceneObjectGroup grp = part.ParentGroup; 1779 SceneObjectGroup grp = part.ParentGroup;
1759 1780
1760 deleteIDs.Add(localID);
1761 deleteGroups.Add(grp);
1762
1763 if (remoteClient == null) 1781 if (remoteClient == null)
1764 { 1782 {
1765 // Autoreturn has a null client. Nothing else does. So 1783 // Autoreturn has a null client. Nothing else does. So
@@ -1776,80 +1794,104 @@ namespace OpenSim.Region.Framework.Scenes
1776 } 1794 }
1777 else 1795 else
1778 { 1796 {
1779 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) 1797 if (action == DeRezAction.TakeCopy)
1798 {
1799 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId))
1800 permissionToTakeCopy = false;
1801 }
1802 else
1803 {
1780 permissionToTakeCopy = false; 1804 permissionToTakeCopy = false;
1781 1805 }
1782 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) 1806 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
1783 permissionToTake = false; 1807 permissionToTake = false;
1784 1808
1785 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) 1809 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
1786 permissionToDelete = false; 1810 permissionToDelete = false;
1787 } 1811 }
1788 }
1789 1812
1790 // Handle god perms 1813 // Handle god perms
1791 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) 1814 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
1792 { 1815 {
1793 permissionToTake = true; 1816 permissionToTake = true;
1794 permissionToTakeCopy = true; 1817 permissionToTakeCopy = true;
1795 permissionToDelete = true; 1818 permissionToDelete = true;
1796 } 1819 }
1797 1820
1798 // If we're re-saving, we don't even want to delete 1821 // If we're re-saving, we don't even want to delete
1799 if (action == DeRezAction.SaveToExistingUserInventoryItem) 1822 if (action == DeRezAction.SaveToExistingUserInventoryItem)
1800 permissionToDelete = false; 1823 permissionToDelete = false;
1801 1824
1802 // if we want to take a copy, we also don't want to delete 1825 // if we want to take a copy, we also don't want to delete
1803 // Note: after this point, the permissionToTakeCopy flag 1826 // Note: after this point, the permissionToTakeCopy flag
1804 // becomes irrelevant. It already includes the permissionToTake 1827 // becomes irrelevant. It already includes the permissionToTake
1805 // permission and after excluding no copy items here, we can 1828 // permission and after excluding no copy items here, we can
1806 // just use that. 1829 // just use that.
1807 if (action == DeRezAction.TakeCopy) 1830 if (action == DeRezAction.TakeCopy)
1808 { 1831 {
1809 // If we don't have permission, stop right here 1832 // If we don't have permission, stop right here
1810 if (!permissionToTakeCopy) 1833 if (!permissionToTakeCopy)
1811 return; 1834 return;
1812 1835
1813 permissionToTake = true; 1836 permissionToTake = true;
1814 // Don't delete 1837 // Don't delete
1815 permissionToDelete = false; 1838 permissionToDelete = false;
1816 } 1839 }
1817 1840
1818 if (action == DeRezAction.Return) 1841 if (action == DeRezAction.Return)
1819 {
1820 if (remoteClient != null)
1821 { 1842 {
1822 if (Permissions.CanReturnObjects( 1843 if (remoteClient != null)
1823 null,
1824 remoteClient.AgentId,
1825 deleteGroups))
1826 { 1844 {
1827 permissionToTake = true; 1845 if (Permissions.CanReturnObjects(
1828 permissionToDelete = true; 1846 null,
1829 1847 remoteClient.AgentId,
1830 foreach (SceneObjectGroup g in deleteGroups) 1848 deleteGroups))
1831 { 1849 {
1832 AddReturn(g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); 1850 permissionToTake = true;
1851 permissionToDelete = true;
1852
1853 AddReturn(grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return");
1833 } 1854 }
1834 } 1855 }
1856 else // Auto return passes through here with null agent
1857 {
1858 permissionToTake = true;
1859 permissionToDelete = true;
1860 }
1835 } 1861 }
1836 else // Auto return passes through here with null agent 1862
1863 if (permissionToTake && (!permissionToDelete))
1864 takeGroups.Add(grp);
1865
1866 if (permissionToDelete)
1837 { 1867 {
1838 permissionToTake = true; 1868 if (permissionToTake)
1839 permissionToDelete = true; 1869 deleteGroups.Add(grp);
1870 deleteIDs.Add(grp.LocalId);
1840 } 1871 }
1841 } 1872 }
1842 1873
1843 if (permissionToTake) 1874 SendKillObject(deleteIDs);
1875
1876 if (deleteGroups.Count > 0)
1844 { 1877 {
1878 foreach (SceneObjectGroup g in deleteGroups)
1879 deleteIDs.Remove(g.LocalId);
1880
1845 m_asyncSceneObjectDeleter.DeleteToInventory( 1881 m_asyncSceneObjectDeleter.DeleteToInventory(
1846 action, destinationID, deleteGroups, remoteClient, 1882 action, destinationID, deleteGroups, remoteClient,
1847 permissionToDelete); 1883 true);
1884 }
1885 if (takeGroups.Count > 0)
1886 {
1887 m_asyncSceneObjectDeleter.DeleteToInventory(
1888 action, destinationID, takeGroups, remoteClient,
1889 false);
1848 } 1890 }
1849 else if (permissionToDelete) 1891 if (deleteIDs.Count > 0)
1850 { 1892 {
1851 foreach (SceneObjectGroup g in deleteGroups) 1893 foreach (SceneObjectGroup g in deleteGroups)
1852 DeleteSceneObject(g, false); 1894 DeleteSceneObject(g, true);
1853 } 1895 }
1854 } 1896 }
1855 1897
@@ -1901,21 +1943,29 @@ namespace OpenSim.Region.Framework.Scenes
1901 else // oopsies 1943 else // oopsies
1902 item.Folder = UUID.Zero; 1944 item.Folder = UUID.Zero;
1903 1945
1946 // Set up base perms properly
1947 uint permsBase = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify);
1948 permsBase &= grp.RootPart.BaseMask;
1949 permsBase |= (uint)PermissionMask.Move;
1950
1951 // Make sure we don't lock it
1952 grp.RootPart.NextOwnerMask |= (uint)PermissionMask.Move;
1953
1904 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions()) 1954 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions())
1905 { 1955 {
1906 item.BasePermissions = grp.RootPart.NextOwnerMask; 1956 item.BasePermissions = permsBase & grp.RootPart.NextOwnerMask;
1907 item.CurrentPermissions = grp.RootPart.NextOwnerMask; 1957 item.CurrentPermissions = permsBase & grp.RootPart.NextOwnerMask;
1908 item.NextPermissions = grp.RootPart.NextOwnerMask; 1958 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
1909 item.EveryOnePermissions = grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask; 1959 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask;
1910 item.GroupPermissions = grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask; 1960 item.GroupPermissions = permsBase & grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask;
1911 } 1961 }
1912 else 1962 else
1913 { 1963 {
1914 item.BasePermissions = grp.RootPart.BaseMask; 1964 item.BasePermissions = permsBase;
1915 item.CurrentPermissions = grp.RootPart.OwnerMask; 1965 item.CurrentPermissions = permsBase & grp.RootPart.OwnerMask;
1916 item.NextPermissions = grp.RootPart.NextOwnerMask; 1966 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
1917 item.EveryOnePermissions = grp.RootPart.EveryoneMask; 1967 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask;
1918 item.GroupPermissions = grp.RootPart.GroupMask; 1968 item.GroupPermissions = permsBase & grp.RootPart.GroupMask;
1919 } 1969 }
1920 item.CreationDate = Util.UnixTimeSinceEpoch(); 1970 item.CreationDate = Util.UnixTimeSinceEpoch();
1921 1971
@@ -2059,6 +2109,9 @@ namespace OpenSim.Region.Framework.Scenes
2059 2109
2060 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running) 2110 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running)
2061 { 2111 {
2112 if (!Permissions.CanEditScript(itemID, objectID, controllingClient.AgentId))
2113 return;
2114
2062 SceneObjectPart part = GetSceneObjectPart(objectID); 2115 SceneObjectPart part = GetSceneObjectPart(objectID);
2063 if (part == null) 2116 if (part == null)
2064 return; 2117 return;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
index e1fedf4..48beb9c 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
@@ -49,6 +49,7 @@ namespace OpenSim.Region.Framework.Scenes
49 public delegate bool DuplicateObjectHandler(int objectCount, UUID objectID, UUID owner, Scene scene, Vector3 objectPosition); 49 public delegate bool DuplicateObjectHandler(int objectCount, UUID objectID, UUID owner, Scene scene, Vector3 objectPosition);
50 public delegate bool EditObjectHandler(UUID objectID, UUID editorID, Scene scene); 50 public delegate bool EditObjectHandler(UUID objectID, UUID editorID, Scene scene);
51 public delegate bool EditObjectInventoryHandler(UUID objectID, UUID editorID, Scene scene); 51 public delegate bool EditObjectInventoryHandler(UUID objectID, UUID editorID, Scene scene);
52 public delegate bool ViewObjectInventoryHandler(UUID objectID, UUID editorID, Scene scene);
52 public delegate bool MoveObjectHandler(UUID objectID, UUID moverID, Scene scene); 53 public delegate bool MoveObjectHandler(UUID objectID, UUID moverID, Scene scene);
53 public delegate bool ObjectEntryHandler(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene); 54 public delegate bool ObjectEntryHandler(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene);
54 public delegate bool ReturnObjectsHandler(ILandObject land, UUID user, List<SceneObjectGroup> objects, Scene scene); 55 public delegate bool ReturnObjectsHandler(ILandObject land, UUID user, List<SceneObjectGroup> objects, Scene scene);
@@ -116,6 +117,7 @@ namespace OpenSim.Region.Framework.Scenes
116 public event DuplicateObjectHandler OnDuplicateObject; 117 public event DuplicateObjectHandler OnDuplicateObject;
117 public event EditObjectHandler OnEditObject; 118 public event EditObjectHandler OnEditObject;
118 public event EditObjectInventoryHandler OnEditObjectInventory; 119 public event EditObjectInventoryHandler OnEditObjectInventory;
120 public event ViewObjectInventoryHandler OnViewObjectInventory;
119 public event MoveObjectHandler OnMoveObject; 121 public event MoveObjectHandler OnMoveObject;
120 public event ObjectEntryHandler OnObjectEntry; 122 public event ObjectEntryHandler OnObjectEntry;
121 public event ReturnObjectsHandler OnReturnObjects; 123 public event ReturnObjectsHandler OnReturnObjects;
@@ -401,6 +403,21 @@ namespace OpenSim.Region.Framework.Scenes
401 return true; 403 return true;
402 } 404 }
403 405
406 public bool CanViewObjectInventory(UUID objectID, UUID editorID)
407 {
408 ViewObjectInventoryHandler handler = OnViewObjectInventory;
409 if (handler != null)
410 {
411 Delegate[] list = handler.GetInvocationList();
412 foreach (ViewObjectInventoryHandler h in list)
413 {
414 if (h(objectID, editorID, m_scene) == false)
415 return false;
416 }
417 }
418 return true;
419 }
420
404 #endregion 421 #endregion
405 422
406 #region MOVE OBJECT 423 #region MOVE OBJECT
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index bdf3d1d..1575e50 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -93,6 +93,7 @@ namespace OpenSim.Region.Framework.Scenes
93 // TODO: need to figure out how allow client agents but deny 93 // TODO: need to figure out how allow client agents but deny
94 // root agents when ACL denies access to root agent 94 // root agents when ACL denies access to root agent
95 public bool m_strictAccessControl = true; 95 public bool m_strictAccessControl = true;
96 public bool m_seeIntoBannedRegion = false;
96 public int MaxUndoCount = 5; 97 public int MaxUndoCount = 5;
97 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; 98 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet;
98 public bool LoginLock = false; 99 public bool LoginLock = false;
@@ -114,6 +115,7 @@ namespace OpenSim.Region.Framework.Scenes
114 protected ModuleLoader m_moduleLoader; 115 protected ModuleLoader m_moduleLoader;
115 protected AgentCircuitManager m_authenticateHandler; 116 protected AgentCircuitManager m_authenticateHandler;
116 protected SceneCommunicationService m_sceneGridService; 117 protected SceneCommunicationService m_sceneGridService;
118 protected ISnmpModule m_snmpService = null;
117 119
118 protected ISimulationDataService m_SimulationDataService; 120 protected ISimulationDataService m_SimulationDataService;
119 protected IEstateDataService m_EstateDataService; 121 protected IEstateDataService m_EstateDataService;
@@ -170,7 +172,7 @@ namespace OpenSim.Region.Framework.Scenes
170 private int m_update_events = 1; 172 private int m_update_events = 1;
171 private int m_update_backup = 200; 173 private int m_update_backup = 200;
172 private int m_update_terrain = 50; 174 private int m_update_terrain = 50;
173// private int m_update_land = 1; 175 private int m_update_land = 10;
174 private int m_update_coarse_locations = 50; 176 private int m_update_coarse_locations = 50;
175 177
176 private int frameMS; 178 private int frameMS;
@@ -184,6 +186,7 @@ namespace OpenSim.Region.Framework.Scenes
184 private int landMS; 186 private int landMS;
185 private int lastCompletedFrame; 187 private int lastCompletedFrame;
186 188
189 public bool CombineRegions = false;
187 private bool m_physics_enabled = true; 190 private bool m_physics_enabled = true;
188 private bool m_scripts_enabled = true; 191 private bool m_scripts_enabled = true;
189 private string m_defaultScriptEngine; 192 private string m_defaultScriptEngine;
@@ -192,6 +195,8 @@ namespace OpenSim.Region.Framework.Scenes
192 private volatile bool shuttingdown; 195 private volatile bool shuttingdown;
193 196
194 private int m_lastUpdate; 197 private int m_lastUpdate;
198 private int m_lastIncoming;
199 private int m_lastOutgoing;
195 private bool m_firstHeartbeat = true; 200 private bool m_firstHeartbeat = true;
196 201
197 private object m_deleting_scene_object = new object(); 202 private object m_deleting_scene_object = new object();
@@ -244,6 +249,19 @@ namespace OpenSim.Region.Framework.Scenes
244 get { return m_sceneGridService; } 249 get { return m_sceneGridService; }
245 } 250 }
246 251
252 public ISnmpModule SnmpService
253 {
254 get
255 {
256 if (m_snmpService == null)
257 {
258 m_snmpService = RequestModuleInterface<ISnmpModule>();
259 }
260
261 return m_snmpService;
262 }
263 }
264
247 public ISimulationDataService SimulationDataService 265 public ISimulationDataService SimulationDataService
248 { 266 {
249 get 267 get
@@ -572,7 +590,10 @@ namespace OpenSim.Region.Framework.Scenes
572 m_regInfo = regInfo; 590 m_regInfo = regInfo;
573 m_regionHandle = m_regInfo.RegionHandle; 591 m_regionHandle = m_regInfo.RegionHandle;
574 m_regionName = m_regInfo.RegionName; 592 m_regionName = m_regInfo.RegionName;
593 m_datastore = m_regInfo.DataStore;
575 m_lastUpdate = Util.EnvironmentTickCount(); 594 m_lastUpdate = Util.EnvironmentTickCount();
595 m_lastIncoming = 0;
596 m_lastOutgoing = 0;
576 597
577 m_physicalPrim = physicalPrim; 598 m_physicalPrim = physicalPrim;
578 m_seeIntoRegionFromNeighbor = SeeIntoRegionFromNeighbor; 599 m_seeIntoRegionFromNeighbor = SeeIntoRegionFromNeighbor;
@@ -586,6 +607,8 @@ namespace OpenSim.Region.Framework.Scenes
586 #region Region Settings 607 #region Region Settings
587 608
588 // Load region settings 609 // Load region settings
610 m_regInfo.WindlightSettings = SimulationDataService.LoadRegionWindlightSettings(m_regInfo.RegionID);
611
589 m_regInfo.RegionSettings = simDataService.LoadRegionSettings(m_regInfo.RegionID); 612 m_regInfo.RegionSettings = simDataService.LoadRegionSettings(m_regInfo.RegionID);
590 if (estateDataService != null) 613 if (estateDataService != null)
591 m_regInfo.EstateSettings = estateDataService.LoadEstateSettings(m_regInfo.RegionID, false); 614 m_regInfo.EstateSettings = estateDataService.LoadEstateSettings(m_regInfo.RegionID, false);
@@ -663,9 +686,10 @@ namespace OpenSim.Region.Framework.Scenes
663 //Animation states 686 //Animation states
664 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); 687 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
665 // TODO: Change default to true once the feature is supported 688 // TODO: Change default to true once the feature is supported
666 m_usePreJump = startupConfig.GetBoolean("enableprejump", false); 689 m_usePreJump = startupConfig.GetBoolean("enableprejump", true);
667
668 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); 690 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys);
691
692 m_log.DebugFormat("[SCENE]: prejump is {0}", m_usePreJump ? "ON" : "OFF");
669 if (RegionInfo.NonphysPrimMax > 0) 693 if (RegionInfo.NonphysPrimMax > 0)
670 { 694 {
671 m_maxNonphys = RegionInfo.NonphysPrimMax; 695 m_maxNonphys = RegionInfo.NonphysPrimMax;
@@ -697,6 +721,7 @@ namespace OpenSim.Region.Framework.Scenes
697 m_persistAfter *= 10000000; 721 m_persistAfter *= 10000000;
698 722
699 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 723 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
724 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
700 725
701 IConfig packetConfig = m_config.Configs["PacketPool"]; 726 IConfig packetConfig = m_config.Configs["PacketPool"];
702 if (packetConfig != null) 727 if (packetConfig != null)
@@ -706,6 +731,8 @@ namespace OpenSim.Region.Framework.Scenes
706 } 731 }
707 732
708 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 733 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
734 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
735 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
709 736
710 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true); 737 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true);
711 if (m_generateMaptiles) 738 if (m_generateMaptiles)
@@ -730,9 +757,9 @@ namespace OpenSim.Region.Framework.Scenes
730 } 757 }
731 } 758 }
732 } 759 }
733 catch 760 catch (Exception e)
734 { 761 {
735 m_log.Warn("[SCENE]: Failed to load StartupConfig"); 762 m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString());
736 } 763 }
737 764
738 #endregion Region Config 765 #endregion Region Config
@@ -1107,7 +1134,9 @@ namespace OpenSim.Region.Framework.Scenes
1107 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); 1134 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
1108 if (HeartbeatThread != null) 1135 if (HeartbeatThread != null)
1109 { 1136 {
1137 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1110 HeartbeatThread.Abort(); 1138 HeartbeatThread.Abort();
1139 Watchdog.RemoveThread(HeartbeatThread.ManagedThreadId);
1111 HeartbeatThread = null; 1140 HeartbeatThread = null;
1112 } 1141 }
1113 m_lastUpdate = Util.EnvironmentTickCount(); 1142 m_lastUpdate = Util.EnvironmentTickCount();
@@ -1231,9 +1260,6 @@ namespace OpenSim.Region.Framework.Scenes
1231 { 1260 {
1232 while (!shuttingdown) 1261 while (!shuttingdown)
1233 Update(); 1262 Update();
1234
1235 m_lastUpdate = Util.EnvironmentTickCount();
1236 m_firstHeartbeat = false;
1237 } 1263 }
1238 catch (ThreadAbortException) 1264 catch (ThreadAbortException)
1239 { 1265 {
@@ -1339,12 +1365,12 @@ namespace OpenSim.Region.Framework.Scenes
1339 terrainMS = Util.EnvironmentTickCountSubtract(terMS); 1365 terrainMS = Util.EnvironmentTickCountSubtract(terMS);
1340 } 1366 }
1341 1367
1342 //if (Frame % m_update_land == 0) 1368 // if (Frame % m_update_land == 0)
1343 //{ 1369 // {
1344 // int ldMS = Util.EnvironmentTickCount(); 1370 // int ldMS = Util.EnvironmentTickCount();
1345 // UpdateLand(); 1371 // UpdateLand();
1346 // landMS = Util.EnvironmentTickCountSubtract(ldMS); 1372 // landMS = Util.EnvironmentTickCountSubtract(ldMS);
1347 //} 1373 // }
1348 1374
1349 frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS); 1375 frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS);
1350 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS; 1376 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS;
@@ -1426,12 +1452,16 @@ namespace OpenSim.Region.Framework.Scenes
1426 maintc = Util.EnvironmentTickCountSubtract(maintc); 1452 maintc = Util.EnvironmentTickCountSubtract(maintc);
1427 maintc = (int)(m_timespan * 1000) - maintc; 1453 maintc = (int)(m_timespan * 1000) - maintc;
1428 1454
1455
1456 m_lastUpdate = Util.EnvironmentTickCount();
1457 m_firstHeartbeat = false;
1458
1429 if (maintc > 0) 1459 if (maintc > 0)
1430 Thread.Sleep(maintc); 1460 Thread.Sleep(maintc);
1431 1461
1432 // Tell the watchdog that this thread is still alive 1462 // Tell the watchdog that this thread is still alive
1433 Watchdog.UpdateThread(); 1463 Watchdog.UpdateThread();
1434 } 1464 }
1435 1465
1436 public void AddGroupTarget(SceneObjectGroup grp) 1466 public void AddGroupTarget(SceneObjectGroup grp)
1437 { 1467 {
@@ -1447,9 +1477,9 @@ namespace OpenSim.Region.Framework.Scenes
1447 1477
1448 private void CheckAtTargets() 1478 private void CheckAtTargets()
1449 { 1479 {
1450 Dictionary<UUID, SceneObjectGroup>.ValueCollection objs; 1480 List<SceneObjectGroup> objs = new List<SceneObjectGroup>();
1451 lock (m_groupsWithTargets) 1481 lock (m_groupsWithTargets)
1452 objs = m_groupsWithTargets.Values; 1482 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values);
1453 1483
1454 foreach (SceneObjectGroup entry in objs) 1484 foreach (SceneObjectGroup entry in objs)
1455 entry.checkAtTargets(); 1485 entry.checkAtTargets();
@@ -1773,14 +1803,24 @@ namespace OpenSim.Region.Framework.Scenes
1773 /// <returns></returns> 1803 /// <returns></returns>
1774 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 1804 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
1775 { 1805 {
1806
1807 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
1808 Vector3 wpos = Vector3.Zero;
1809 // Check for water surface intersection from above
1810 if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) )
1811 {
1812 float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
1813 wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
1814 wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y));
1815 wpos.Z = wheight;
1816 }
1817
1776 Vector3 pos = Vector3.Zero; 1818 Vector3 pos = Vector3.Zero;
1777 if (RayEndIsIntersection == (byte)1) 1819 if (RayEndIsIntersection == (byte)1)
1778 { 1820 {
1779 pos = RayEnd; 1821 pos = RayEnd;
1780 return pos;
1781 } 1822 }
1782 1823 else if (RayTargetID != UUID.Zero)
1783 if (RayTargetID != UUID.Zero)
1784 { 1824 {
1785 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 1825 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
1786 1826
@@ -1802,7 +1842,7 @@ namespace OpenSim.Region.Framework.Scenes
1802 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 1842 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
1803 1843
1804 // Un-comment out the following line to Get Raytrace results printed to the console. 1844 // Un-comment out the following line to Get Raytrace results printed to the console.
1805 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 1845 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1806 float ScaleOffset = 0.5f; 1846 float ScaleOffset = 0.5f;
1807 1847
1808 // If we hit something 1848 // If we hit something
@@ -1825,13 +1865,10 @@ namespace OpenSim.Region.Framework.Scenes
1825 //pos.Z -= 0.25F; 1865 //pos.Z -= 0.25F;
1826 1866
1827 } 1867 }
1828
1829 return pos;
1830 } 1868 }
1831 else 1869 else
1832 { 1870 {
1833 // We don't have a target here, so we're going to raytrace all the objects in the scene. 1871 // We don't have a target here, so we're going to raytrace all the objects in the scene.
1834
1835 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 1872 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
1836 1873
1837 // Un-comment the following line to print the raytrace results to the console. 1874 // Un-comment the following line to print the raytrace results to the console.
@@ -1840,13 +1877,12 @@ namespace OpenSim.Region.Framework.Scenes
1840 if (ei.HitTF) 1877 if (ei.HitTF)
1841 { 1878 {
1842 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 1879 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1843 } else 1880 }
1881 else
1844 { 1882 {
1845 // fall back to our stupid functionality 1883 // fall back to our stupid functionality
1846 pos = RayEnd; 1884 pos = RayEnd;
1847 } 1885 }
1848
1849 return pos;
1850 } 1886 }
1851 } 1887 }
1852 else 1888 else
@@ -1857,8 +1893,12 @@ namespace OpenSim.Region.Framework.Scenes
1857 //increase height so its above the ground. 1893 //increase height so its above the ground.
1858 //should be getting the normal of the ground at the rez point and using that? 1894 //should be getting the normal of the ground at the rez point and using that?
1859 pos.Z += scale.Z / 2f; 1895 pos.Z += scale.Z / 2f;
1860 return pos; 1896// return pos;
1861 } 1897 }
1898
1899 // check against posible water intercept
1900 if (wpos.Z > pos.Z) pos = wpos;
1901 return pos;
1862 } 1902 }
1863 1903
1864 1904
@@ -1942,7 +1982,10 @@ namespace OpenSim.Region.Framework.Scenes
1942 public bool AddRestoredSceneObject( 1982 public bool AddRestoredSceneObject(
1943 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 1983 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
1944 { 1984 {
1945 return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 1985 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates);
1986 if (result)
1987 sceneObject.IsDeleted = false;
1988 return result;
1946 } 1989 }
1947 1990
1948 /// <summary> 1991 /// <summary>
@@ -2032,6 +2075,15 @@ namespace OpenSim.Region.Framework.Scenes
2032 /// </summary> 2075 /// </summary>
2033 public void DeleteAllSceneObjects() 2076 public void DeleteAllSceneObjects()
2034 { 2077 {
2078 DeleteAllSceneObjects(false);
2079 }
2080
2081 /// <summary>
2082 /// Delete every object from the scene. This does not include attachments worn by avatars.
2083 /// </summary>
2084 public void DeleteAllSceneObjects(bool exceptNoCopy)
2085 {
2086 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
2035 lock (Entities) 2087 lock (Entities)
2036 { 2088 {
2037 EntityBase[] entities = Entities.GetEntities(); 2089 EntityBase[] entities = Entities.GetEntities();
@@ -2040,11 +2092,24 @@ namespace OpenSim.Region.Framework.Scenes
2040 if (e is SceneObjectGroup) 2092 if (e is SceneObjectGroup)
2041 { 2093 {
2042 SceneObjectGroup sog = (SceneObjectGroup)e; 2094 SceneObjectGroup sog = (SceneObjectGroup)e;
2043 if (!sog.IsAttachment) 2095 if (sog != null && !sog.IsAttachment)
2044 DeleteSceneObject((SceneObjectGroup)e, false); 2096 {
2097 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2098 {
2099 DeleteSceneObject((SceneObjectGroup)e, false);
2100 }
2101 else
2102 {
2103 toReturn.Add((SceneObjectGroup)e);
2104 }
2105 }
2045 } 2106 }
2046 } 2107 }
2047 } 2108 }
2109 if (toReturn.Count > 0)
2110 {
2111 returnObjects(toReturn.ToArray(), UUID.Zero);
2112 }
2048 } 2113 }
2049 2114
2050 /// <summary> 2115 /// <summary>
@@ -2093,6 +2158,8 @@ namespace OpenSim.Region.Framework.Scenes
2093 } 2158 }
2094 2159
2095 group.DeleteGroupFromScene(silent); 2160 group.DeleteGroupFromScene(silent);
2161 if (!silent)
2162 SendKillObject(new List<uint>() { group.LocalId });
2096 2163
2097// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2164// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2098 } 2165 }
@@ -2445,10 +2512,17 @@ namespace OpenSim.Region.Framework.Scenes
2445 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2512 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2446 public bool AddSceneObject(SceneObjectGroup sceneObject) 2513 public bool AddSceneObject(SceneObjectGroup sceneObject)
2447 { 2514 {
2515 if (sceneObject.OwnerID == UUID.Zero)
2516 {
2517 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2518 return false;
2519 }
2520
2448 // If the user is banned, we won't let any of their objects 2521 // If the user is banned, we won't let any of their objects
2449 // enter. Period. 2522 // enter. Period.
2450 // 2523 //
2451 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID)) 2524 int flags = GetUserFlags(sceneObject.OwnerID);
2525 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2452 { 2526 {
2453 m_log.Info("[INTERREGION]: Denied prim crossing for " + 2527 m_log.Info("[INTERREGION]: Denied prim crossing for " +
2454 "banned avatar"); 2528 "banned avatar");
@@ -2492,15 +2566,28 @@ namespace OpenSim.Region.Framework.Scenes
2492 2566
2493 if (AttachmentsModule != null) 2567 if (AttachmentsModule != null)
2494 AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false); 2568 AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false);
2569
2570 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was found, attaching", sceneObject.UUID);
2495 } 2571 }
2496 else 2572 else
2497 { 2573 {
2574 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2498 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2575 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2499 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 2576 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2500 } 2577 }
2578 if (sceneObject.OwnerID == UUID.Zero)
2579 {
2580 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
2581 return false;
2582 }
2501 } 2583 }
2502 else 2584 else
2503 { 2585 {
2586 if (sceneObject.OwnerID == UUID.Zero)
2587 {
2588 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
2589 return false;
2590 }
2504 AddRestoredSceneObject(sceneObject, true, false); 2591 AddRestoredSceneObject(sceneObject, true, false);
2505 2592
2506 if (!Permissions.CanObjectEntry(sceneObject.UUID, 2593 if (!Permissions.CanObjectEntry(sceneObject.UUID,
@@ -2530,6 +2617,24 @@ namespace OpenSim.Region.Framework.Scenes
2530 return 2; // StateSource.PrimCrossing 2617 return 2; // StateSource.PrimCrossing
2531 } 2618 }
2532 2619
2620 public int GetUserFlags(UUID user)
2621 {
2622 //Unfortunately the SP approach means that the value is cached until region is restarted
2623 /*
2624 ScenePresence sp;
2625 if (TryGetScenePresence(user, out sp))
2626 {
2627 return sp.UserFlags;
2628 }
2629 else
2630 {
2631 */
2632 UserAccount uac = UserAccountService.GetUserAccount(RegionInfo.ScopeID, user);
2633 if (uac == null)
2634 return 0;
2635 return uac.UserFlags;
2636 //}
2637 }
2533 #endregion 2638 #endregion
2534 2639
2535 #region Add/Remove Avatar Methods 2640 #region Add/Remove Avatar Methods
@@ -2550,6 +2655,7 @@ namespace OpenSim.Region.Framework.Scenes
2550 (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 2655 (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2551 2656
2552 CheckHeartbeat(); 2657 CheckHeartbeat();
2658 ScenePresence presence;
2553 2659
2554 if (GetScenePresence(client.AgentId) == null) // ensure there is no SP here 2660 if (GetScenePresence(client.AgentId) == null) // ensure there is no SP here
2555 { 2661 {
@@ -2573,7 +2679,7 @@ namespace OpenSim.Region.Framework.Scenes
2573 } 2679 }
2574 } 2680 }
2575 2681
2576 if (GetScenePresence(client.AgentId) != null) 2682 if (TryGetScenePresence(client.AgentId, out presence))
2577 { 2683 {
2578 m_LastLogin = Util.EnvironmentTickCount(); 2684 m_LastLogin = Util.EnvironmentTickCount();
2579 2685
@@ -2582,7 +2688,14 @@ namespace OpenSim.Region.Framework.Scenes
2582 2688
2583 EventManager.TriggerOnNewClient(client); 2689 EventManager.TriggerOnNewClient(client);
2584 if (vialogin) 2690 if (vialogin)
2691 {
2585 EventManager.TriggerOnClientLogin(client); 2692 EventManager.TriggerOnClientLogin(client);
2693
2694 // Send initial parcel data
2695 Vector3 pos = presence.AbsolutePosition;
2696 ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y);
2697 land.SendLandUpdateToClient(presence.ControllingClient);
2698 }
2586 } 2699 }
2587 } 2700 }
2588 2701
@@ -2655,19 +2768,12 @@ namespace OpenSim.Region.Framework.Scenes
2655 // and the scene presence and the client, if they exist 2768 // and the scene presence and the client, if they exist
2656 try 2769 try
2657 { 2770 {
2658 // We need to wait for the client to make UDP contact first. 2771 ScenePresence sp = GetScenePresence(agentID);
2659 // It's the UDP contact that creates the scene presence 2772 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2660 ScenePresence sp = WaitGetScenePresence(agentID); 2773
2661 if (sp != null) 2774 if (sp != null)
2662 {
2663 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2664
2665 sp.ControllingClient.Close(); 2775 sp.ControllingClient.Close();
2666 } 2776
2667 else
2668 {
2669 m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID);
2670 }
2671 // BANG! SLASH! 2777 // BANG! SLASH!
2672 m_authenticateHandler.RemoveCircuit(agentID); 2778 m_authenticateHandler.RemoveCircuit(agentID);
2673 2779
@@ -2767,6 +2873,7 @@ namespace OpenSim.Region.Framework.Scenes
2767 client.OnFetchInventory += HandleFetchInventory; 2873 client.OnFetchInventory += HandleFetchInventory;
2768 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 2874 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
2769 client.OnCopyInventoryItem += CopyInventoryItem; 2875 client.OnCopyInventoryItem += CopyInventoryItem;
2876 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
2770 client.OnMoveInventoryItem += MoveInventoryItem; 2877 client.OnMoveInventoryItem += MoveInventoryItem;
2771 client.OnRemoveInventoryItem += RemoveInventoryItem; 2878 client.OnRemoveInventoryItem += RemoveInventoryItem;
2772 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 2879 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -2944,15 +3051,16 @@ namespace OpenSim.Region.Framework.Scenes
2944 /// </summary> 3051 /// </summary>
2945 /// <param name="agentId">The avatar's Unique ID</param> 3052 /// <param name="agentId">The avatar's Unique ID</param>
2946 /// <param name="client">The IClientAPI for the client</param> 3053 /// <param name="client">The IClientAPI for the client</param>
2947 public virtual void TeleportClientHome(UUID agentId, IClientAPI client) 3054 public virtual bool TeleportClientHome(UUID agentId, IClientAPI client)
2948 { 3055 {
2949 if (m_teleportModule != null) 3056 if (m_teleportModule != null)
2950 m_teleportModule.TeleportHome(agentId, client); 3057 return m_teleportModule.TeleportHome(agentId, client);
2951 else 3058 else
2952 { 3059 {
2953 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); 3060 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active");
2954 client.SendTeleportFailed("Unable to perform teleports on this simulator."); 3061 client.SendTeleportFailed("Unable to perform teleports on this simulator.");
2955 } 3062 }
3063 return false;
2956 } 3064 }
2957 3065
2958 /// <summary> 3066 /// <summary>
@@ -3051,6 +3159,16 @@ namespace OpenSim.Region.Framework.Scenes
3051 /// <param name="flags"></param> 3159 /// <param name="flags"></param>
3052 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) 3160 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
3053 { 3161 {
3162 //Add half the avatar's height so that the user doesn't fall through prims
3163 ScenePresence presence;
3164 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3165 {
3166 if (presence.Appearance != null)
3167 {
3168 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3169 }
3170 }
3171
3054 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) 3172 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
3055 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. 3173 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
3056 m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); 3174 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
@@ -3127,7 +3245,9 @@ namespace OpenSim.Region.Framework.Scenes
3127 regions.Remove(RegionInfo.RegionHandle); 3245 regions.Remove(RegionInfo.RegionHandle);
3128 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3246 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3129 } 3247 }
3248 m_log.Debug("[Scene] Beginning ClientClosed");
3130 m_eventManager.TriggerClientClosed(agentID, this); 3249 m_eventManager.TriggerClientClosed(agentID, this);
3250 m_log.Debug("[Scene] Finished ClientClosed");
3131 } 3251 }
3132 catch (NullReferenceException) 3252 catch (NullReferenceException)
3133 { 3253 {
@@ -3135,7 +3255,12 @@ namespace OpenSim.Region.Framework.Scenes
3135 // Avatar is already disposed :/ 3255 // Avatar is already disposed :/
3136 } 3256 }
3137 3257
3258 m_log.Debug("[Scene] Beginning OnRemovePresence");
3138 m_eventManager.TriggerOnRemovePresence(agentID); 3259 m_eventManager.TriggerOnRemovePresence(agentID);
3260 m_log.Debug("[Scene] Finished OnRemovePresence");
3261
3262 if (avatar != null && (!avatar.IsChildAgent))
3263 avatar.SaveChangedAttachments();
3139 3264
3140 if (avatar != null && (!avatar.IsChildAgent)) 3265 if (avatar != null && (!avatar.IsChildAgent))
3141 avatar.SaveChangedAttachments(); 3266 avatar.SaveChangedAttachments();
@@ -3144,7 +3269,7 @@ namespace OpenSim.Region.Framework.Scenes
3144 delegate(IClientAPI client) 3269 delegate(IClientAPI client)
3145 { 3270 {
3146 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway 3271 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway
3147 try { client.SendKillObject(avatar.RegionHandle, avatar.LocalId); } 3272 try { client.SendKillObject(avatar.RegionHandle, new List<uint>() { avatar.LocalId}); }
3148 catch (NullReferenceException) { } 3273 catch (NullReferenceException) { }
3149 }); 3274 });
3150 3275
@@ -3155,8 +3280,11 @@ namespace OpenSim.Region.Framework.Scenes
3155 } 3280 }
3156 3281
3157 // Remove the avatar from the scene 3282 // Remove the avatar from the scene
3283 m_log.Debug("[Scene] Begin RemoveScenePresence");
3158 m_sceneGraph.RemoveScenePresence(agentID); 3284 m_sceneGraph.RemoveScenePresence(agentID);
3285 m_log.Debug("[Scene] Finished RemoveScenePresence. Removing the client manager");
3159 m_clientManager.Remove(agentID); 3286 m_clientManager.Remove(agentID);
3287 m_log.Debug("[Scene] Removed the client manager. Firing avatar.close");
3160 3288
3161 try 3289 try
3162 { 3290 {
@@ -3170,9 +3298,10 @@ namespace OpenSim.Region.Framework.Scenes
3170 { 3298 {
3171 m_log.Error("[SCENE] Scene.cs:RemoveClient exception: " + e.ToString()); 3299 m_log.Error("[SCENE] Scene.cs:RemoveClient exception: " + e.ToString());
3172 } 3300 }
3173 3301 m_log.Debug("[Scene] Done. Firing RemoveCircuit");
3174 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3302 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3175 CleanDroppedAttachments(); 3303 CleanDroppedAttachments();
3304 m_log.Debug("[Scene] The avatar has left the building");
3176 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 3305 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
3177 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); 3306 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
3178 } 3307 }
@@ -3203,18 +3332,24 @@ namespace OpenSim.Region.Framework.Scenes
3203 3332
3204 #region Entities 3333 #region Entities
3205 3334
3206 public void SendKillObject(uint localID) 3335 public void SendKillObject(List<uint> localIDs)
3207 { 3336 {
3208 SceneObjectPart part = GetSceneObjectPart(localID); 3337 List<uint> deleteIDs = new List<uint>();
3209 if (part != null) // It is a prim 3338
3339 foreach (uint localID in localIDs)
3210 { 3340 {
3211 if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid 3341 SceneObjectPart part = GetSceneObjectPart(localID);
3342 if (part != null) // It is a prim
3212 { 3343 {
3213 if (part.ParentGroup.RootPart != part) // Child part 3344 if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid
3214 return; 3345 {
3346 if (part.ParentGroup.RootPart != part) // Child part
3347 continue;
3348 }
3215 } 3349 }
3350 deleteIDs.Add(localID);
3216 } 3351 }
3217 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, localID); }); 3352 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, deleteIDs); });
3218 } 3353 }
3219 3354
3220 #endregion 3355 #endregion
@@ -3232,7 +3367,6 @@ namespace OpenSim.Region.Framework.Scenes
3232 //m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate; 3367 //m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate;
3233 //m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar; 3368 //m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar;
3234 m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid; 3369 m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid;
3235 m_sceneGridService.KiPrimitive += SendKillObject;
3236 m_sceneGridService.OnGetLandData += GetLandData; 3370 m_sceneGridService.OnGetLandData += GetLandData;
3237 } 3371 }
3238 3372
@@ -3241,7 +3375,6 @@ namespace OpenSim.Region.Framework.Scenes
3241 /// </summary> 3375 /// </summary>
3242 public void UnRegisterRegionWithComms() 3376 public void UnRegisterRegionWithComms()
3243 { 3377 {
3244 m_sceneGridService.KiPrimitive -= SendKillObject;
3245 m_sceneGridService.OnLogOffUser -= HandleLogOffUserFromGrid; 3378 m_sceneGridService.OnLogOffUser -= HandleLogOffUserFromGrid;
3246 //m_sceneGridService.OnRemoveKnownRegionFromAvatar -= HandleRemoveKnownRegionsFromAvatar; 3379 //m_sceneGridService.OnRemoveKnownRegionFromAvatar -= HandleRemoveKnownRegionsFromAvatar;
3247 //m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate; 3380 //m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate;
@@ -3321,13 +3454,16 @@ namespace OpenSim.Region.Framework.Scenes
3321 sp = null; 3454 sp = null;
3322 } 3455 }
3323 3456
3324 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3325 3457
3326 //On login test land permisions 3458 //On login test land permisions
3327 if (vialogin) 3459 if (vialogin)
3328 { 3460 {
3329 if (land != null && !TestLandRestrictions(agent, land, out reason)) 3461 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3462 if (cache != null)
3463 cache.Remove(agent.firstname + " " + agent.lastname);
3464 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3330 { 3465 {
3466 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3331 return false; 3467 return false;
3332 } 3468 }
3333 } 3469 }
@@ -3350,8 +3486,13 @@ namespace OpenSim.Region.Framework.Scenes
3350 3486
3351 try 3487 try
3352 { 3488 {
3353 if (!AuthorizeUser(agent, out reason)) 3489 // Always check estate if this is a login. Always
3354 return false; 3490 // check if banned regions are to be blacked out.
3491 if (vialogin || (!m_seeIntoBannedRegion))
3492 {
3493 if (!AuthorizeUser(agent.AgentID, out reason))
3494 return false;
3495 }
3355 } 3496 }
3356 catch (Exception e) 3497 catch (Exception e)
3357 { 3498 {
@@ -3454,6 +3595,8 @@ namespace OpenSim.Region.Framework.Scenes
3454 } 3595 }
3455 } 3596 }
3456 // Honor parcel landing type and position. 3597 // Honor parcel landing type and position.
3598 /*
3599 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3457 if (land != null) 3600 if (land != null)
3458 { 3601 {
3459 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3602 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3461,26 +3604,34 @@ namespace OpenSim.Region.Framework.Scenes
3461 agent.startpos = land.LandData.UserLocation; 3604 agent.startpos = land.LandData.UserLocation;
3462 } 3605 }
3463 } 3606 }
3607 */// This is now handled properly in ScenePresence.MakeRootAgent
3464 } 3608 }
3465 3609
3466 return true; 3610 return true;
3467 } 3611 }
3468 3612
3469 private bool TestLandRestrictions(AgentCircuitData agent, ILandObject land, out string reason) 3613 private bool TestLandRestrictions(UUID agentID, out string reason, ref float posX, ref float posY)
3470 { 3614 {
3471 3615 reason = String.Empty;
3472 bool banned = land.IsBannedFromLand(agent.AgentID); 3616 if (Permissions.IsGod(agentID))
3473 bool restricted = land.IsRestrictedFromLand(agent.AgentID); 3617 return true;
3618
3619 ILandObject land = LandChannel.GetLandObject(posX, posY);
3620 if (land == null)
3621 return false;
3622
3623 bool banned = land.IsBannedFromLand(agentID);
3624 bool restricted = land.IsRestrictedFromLand(agentID);
3474 3625
3475 if (banned || restricted) 3626 if (banned || restricted)
3476 { 3627 {
3477 ILandObject nearestParcel = GetNearestAllowedParcel(agent.AgentID, agent.startpos.X, agent.startpos.Y); 3628 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY);
3478 if (nearestParcel != null) 3629 if (nearestParcel != null)
3479 { 3630 {
3480 //Move agent to nearest allowed 3631 //Move agent to nearest allowed
3481 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); 3632 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel);
3482 agent.startpos.X = newPosition.X; 3633 posX = newPosition.X;
3483 agent.startpos.Y = newPosition.Y; 3634 posY = newPosition.Y;
3484 } 3635 }
3485 else 3636 else
3486 { 3637 {
@@ -3536,19 +3687,19 @@ namespace OpenSim.Region.Framework.Scenes
3536 /// <param name="reason">outputs the reason to this string</param> 3687 /// <param name="reason">outputs the reason to this string</param>
3537 /// <returns>True if the region accepts this agent. False if it does not. False will 3688 /// <returns>True if the region accepts this agent. False if it does not. False will
3538 /// also return a reason.</returns> 3689 /// also return a reason.</returns>
3539 protected virtual bool AuthorizeUser(AgentCircuitData agent, out string reason) 3690 protected virtual bool AuthorizeUser(UUID agentID, out string reason)
3540 { 3691 {
3541 reason = String.Empty; 3692 reason = String.Empty;
3542 3693
3543 if (!m_strictAccessControl) return true; 3694 if (!m_strictAccessControl) return true;
3544 if (Permissions.IsGod(agent.AgentID)) return true; 3695 if (Permissions.IsGod(agentID)) return true;
3545 3696
3546 if (AuthorizationService != null) 3697 if (AuthorizationService != null)
3547 { 3698 {
3548 if (!AuthorizationService.IsAuthorizedForRegion(agent.AgentID.ToString(), RegionInfo.RegionID.ToString(),out reason)) 3699 if (!AuthorizationService.IsAuthorizedForRegion(agentID.ToString(), RegionInfo.RegionID.ToString(),out reason))
3549 { 3700 {
3550 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region", 3701 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} at {1} because the user does not have access to the region",
3551 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3702 agentID, RegionInfo.RegionName);
3552 //reason = String.Format("You are not currently on the access list for {0}",RegionInfo.RegionName); 3703 //reason = String.Format("You are not currently on the access list for {0}",RegionInfo.RegionName);
3553 return false; 3704 return false;
3554 } 3705 }
@@ -3556,10 +3707,26 @@ namespace OpenSim.Region.Framework.Scenes
3556 3707
3557 if (m_regInfo.EstateSettings != null) 3708 if (m_regInfo.EstateSettings != null)
3558 { 3709 {
3559 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID)) 3710 int flags = GetUserFlags(agentID);
3711 if (m_regInfo.EstateSettings.IsBanned(agentID, flags))
3560 { 3712 {
3561 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 3713 //Add some more info to help users
3562 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3714 if (!m_regInfo.EstateSettings.IsBanned(agentID, 32))
3715 {
3716 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} at {1} because the region requires age verification",
3717 agentID, RegionInfo.RegionName);
3718 reason = String.Format("Denied access to region {0}: Region requires age verification", RegionInfo.RegionName);
3719 return false;
3720 }
3721 if (!m_regInfo.EstateSettings.IsBanned(agentID, 4))
3722 {
3723 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} {1} because the region requires payment info on file",
3724 agentID, RegionInfo.RegionName);
3725 reason = String.Format("Denied access to region {0}: Region requires payment info on file", RegionInfo.RegionName);
3726 return false;
3727 }
3728 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} at {3} because the user is on the banlist",
3729 agentID, RegionInfo.RegionName);
3563 reason = String.Format("Denied access to region {0}: You have been banned from that region.", 3730 reason = String.Format("Denied access to region {0}: You have been banned from that region.",
3564 RegionInfo.RegionName); 3731 RegionInfo.RegionName);
3565 return false; 3732 return false;
@@ -3576,7 +3743,7 @@ namespace OpenSim.Region.Framework.Scenes
3576 if (groupsModule != null) 3743 if (groupsModule != null)
3577 { 3744 {
3578 GroupMembershipData[] GroupMembership = 3745 GroupMembershipData[] GroupMembership =
3579 groupsModule.GetMembershipData(agent.AgentID); 3746 groupsModule.GetMembershipData(agentID);
3580 3747
3581 if (GroupMembership != null) 3748 if (GroupMembership != null)
3582 { 3749 {
@@ -3605,44 +3772,16 @@ namespace OpenSim.Region.Framework.Scenes
3605 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!"); 3772 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!");
3606 3773
3607 if (!m_regInfo.EstateSettings.PublicAccess && 3774 if (!m_regInfo.EstateSettings.PublicAccess &&
3608 !m_regInfo.EstateSettings.HasAccess(agent.AgentID) && 3775 !m_regInfo.EstateSettings.HasAccess(agentID) &&
3609 !groupAccess) 3776 !groupAccess)
3610 { 3777 {
3611 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate", 3778 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} at {1} because the user does not have access to the estate",
3612 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3779 agentID, RegionInfo.RegionName);
3613 reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", 3780 reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.",
3614 RegionInfo.RegionName); 3781 RegionInfo.RegionName);
3615 return false; 3782 return false;
3616 } 3783 }
3617 3784
3618 // TODO: estate/region settings are not properly hooked up
3619 // to ILandObject.isRestrictedFromLand()
3620 // if (null != LandChannel)
3621 // {
3622 // // region seems to have local Id of 1
3623 // ILandObject land = LandChannel.GetLandObject(1);
3624 // if (null != land)
3625 // {
3626 // if (land.isBannedFromLand(agent.AgentID))
3627 // {
3628 // m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user has been banned from land",
3629 // agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
3630 // reason = String.Format("Denied access to private region {0}: You are banned from that region.",
3631 // RegionInfo.RegionName);
3632 // return false;
3633 // }
3634
3635 // if (land.isRestrictedFromLand(agent.AgentID))
3636 // {
3637 // m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region",
3638 // agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
3639 // reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.",
3640 // RegionInfo.RegionName);
3641 // return false;
3642 // }
3643 // }
3644 // }
3645
3646 return true; 3785 return true;
3647 } 3786 }
3648 3787
@@ -3746,6 +3885,13 @@ namespace OpenSim.Region.Framework.Scenes
3746 3885
3747 // We have to wait until the viewer contacts this region after receiving EAC. 3886 // We have to wait until the viewer contacts this region after receiving EAC.
3748 // That calls AddNewClient, which finally creates the ScenePresence 3887 // That calls AddNewClient, which finally creates the ScenePresence
3888 int flags = GetUserFlags(cAgentData.AgentID);
3889 if (m_regInfo.EstateSettings.IsBanned(cAgentData.AgentID, flags))
3890 {
3891 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
3892 return false;
3893 }
3894
3749 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 3895 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
3750 if (nearestParcel == null) 3896 if (nearestParcel == null)
3751 { 3897 {
@@ -3761,7 +3907,6 @@ namespace OpenSim.Region.Framework.Scenes
3761 return false; 3907 return false;
3762 } 3908 }
3763 3909
3764
3765 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); 3910 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID);
3766 3911
3767 if (childAgentUpdate != null) 3912 if (childAgentUpdate != null)
@@ -3828,12 +3973,22 @@ namespace OpenSim.Region.Framework.Scenes
3828 return false; 3973 return false;
3829 } 3974 }
3830 3975
3976 public bool IncomingCloseAgent(UUID agentID)
3977 {
3978 return IncomingCloseAgent(agentID, false);
3979 }
3980
3981 public bool IncomingCloseChildAgent(UUID agentID)
3982 {
3983 return IncomingCloseAgent(agentID, true);
3984 }
3985
3831 /// <summary> 3986 /// <summary>
3832 /// Tell a single agent to disconnect from the region. 3987 /// Tell a single agent to disconnect from the region.
3833 /// </summary> 3988 /// </summary>
3834 /// <param name="regionHandle"></param>
3835 /// <param name="agentID"></param> 3989 /// <param name="agentID"></param>
3836 public bool IncomingCloseAgent(UUID agentID) 3990 /// <param name="childOnly"></param>
3991 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
3837 { 3992 {
3838 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 3993 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
3839 3994
@@ -3845,7 +4000,7 @@ namespace OpenSim.Region.Framework.Scenes
3845 { 4000 {
3846 m_sceneGraph.removeUserCount(false); 4001 m_sceneGraph.removeUserCount(false);
3847 } 4002 }
3848 else 4003 else if (!childOnly)
3849 { 4004 {
3850 m_sceneGraph.removeUserCount(true); 4005 m_sceneGraph.removeUserCount(true);
3851 } 4006 }
@@ -3861,9 +4016,12 @@ namespace OpenSim.Region.Framework.Scenes
3861 } 4016 }
3862 else 4017 else
3863 presence.ControllingClient.SendShutdownConnectionNotice(); 4018 presence.ControllingClient.SendShutdownConnectionNotice();
4019 presence.ControllingClient.Close(false);
4020 }
4021 else if (!childOnly)
4022 {
4023 presence.ControllingClient.Close(true);
3864 } 4024 }
3865
3866 presence.ControllingClient.Close();
3867 return true; 4025 return true;
3868 } 4026 }
3869 4027
@@ -4474,34 +4632,66 @@ namespace OpenSim.Region.Framework.Scenes
4474 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID); 4632 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID);
4475 } 4633 }
4476 4634
4477 public int GetHealth() 4635 public int GetHealth(out int flags, out string message)
4478 { 4636 {
4479 // Returns: 4637 // Returns:
4480 // 1 = sim is up and accepting http requests. The heartbeat has 4638 // 1 = sim is up and accepting http requests. The heartbeat has
4481 // stopped and the sim is probably locked up, but a remote 4639 // stopped and the sim is probably locked up, but a remote
4482 // admin restart may succeed 4640 // admin restart may succeed
4483 // 4641 //
4484 // 2 = Sim is up and the heartbeat is running. The sim is likely 4642 // 2 = Sim is up and the heartbeat is running. The sim is likely
4485 // usable for people within and logins _may_ work 4643 // usable for people within
4644 //
4645 // 3 = Sim is up and one packet thread is running. Sim is
4646 // unstable and will not accept new logins
4486 // 4647 //
4487 // 3 = We have seen a new user enter within the past 4 minutes 4648 // 4 = Sim is up and both packet threads are running. Sim is
4649 // likely usable
4650 //
4651 // 5 = We have seen a new user enter within the past 4 minutes
4488 // which can be seen as positive confirmation of sim health 4652 // which can be seen as positive confirmation of sim health
4489 // 4653 //
4654
4655 flags = 0;
4656 message = String.Empty;
4657
4658 CheckHeartbeat();
4659
4660 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
4661 {
4662 // We're still starting
4663 // 0 means "in startup", it can't happen another way, since
4664 // to get here, we must be able to accept http connections
4665 return 0;
4666 }
4667
4490 int health=1; // Start at 1, means we're up 4668 int health=1; // Start at 1, means we're up
4491 4669
4492 if ((Util.EnvironmentTickCountSubtract(m_lastUpdate)) < 1000) 4670 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) < 1000)
4671 {
4493 health+=1; 4672 health+=1;
4494 else 4673 flags |= 1;
4674 }
4675
4676 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 1000)
4677 {
4678 health+=1;
4679 flags |= 2;
4680 }
4681
4682 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 1000)
4683 {
4684 health+=1;
4685 flags |= 4;
4686 }
4687
4688 if (flags != 7)
4495 return health; 4689 return health;
4496 4690
4497 // A login in the last 4 mins? We can't be doing too badly 4691 // A login in the last 4 mins? We can't be doing too badly
4498 // 4692 //
4499 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 4693 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
4500 health++; 4694 health++;
4501 else
4502 return health;
4503
4504 CheckHeartbeat();
4505 4695
4506 return health; 4696 return health;
4507 } 4697 }
@@ -4694,7 +4884,7 @@ namespace OpenSim.Region.Framework.Scenes
4694 if (m_firstHeartbeat) 4884 if (m_firstHeartbeat)
4695 return; 4885 return;
4696 4886
4697 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 2000) 4887 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 10000)
4698 StartTimer(); 4888 StartTimer();
4699 } 4889 }
4700 4890
@@ -5103,10 +5293,28 @@ namespace OpenSim.Region.Framework.Scenes
5103 }); 5293 });
5104 } 5294 }
5105 5295
5106 foreach (SceneObjectGroup grp in objectsToDelete) 5296 if (objectsToDelete.Count > 0)
5107 { 5297 {
5108 m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID); 5298 m_log.DebugFormat("[SCENE]: Starting delete of {0} dropped attachments", objectsToDelete.Count);
5109 DeleteSceneObject(grp, true); 5299 foreach (SceneObjectGroup grp in objectsToDelete)
5300 {
5301 m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
5302 DeleteSceneObject(grp, true);
5303 }
5304 m_log.Debug("[SCENE]: Finished dropped attachment deletion");
5305 }
5306 }
5307
5308 public void ThreadAlive(int threadCode)
5309 {
5310 switch(threadCode)
5311 {
5312 case 1: // Incoming
5313 m_lastIncoming = Util.EnvironmentTickCount();
5314 break;
5315 case 2: // Incoming
5316 m_lastOutgoing = Util.EnvironmentTickCount();
5317 break;
5110 } 5318 }
5111 } 5319 }
5112 5320
@@ -5118,6 +5326,14 @@ namespace OpenSim.Region.Framework.Scenes
5118 // child agent creation, thereby emulating the SL behavior. 5326 // child agent creation, thereby emulating the SL behavior.
5119 public bool QueryAccess(UUID agentID, Vector3 position, out string reason) 5327 public bool QueryAccess(UUID agentID, Vector3 position, out string reason)
5120 { 5328 {
5329 reason = "You are banned from the region";
5330
5331 if (Permissions.IsGod(agentID))
5332 {
5333 reason = String.Empty;
5334 return true;
5335 }
5336
5121 int num = m_sceneGraph.GetNumberOfScenePresences(); 5337 int num = m_sceneGraph.GetNumberOfScenePresences();
5122 5338
5123 if (num >= RegionInfo.RegionSettings.AgentLimit) 5339 if (num >= RegionInfo.RegionSettings.AgentLimit)
@@ -5129,6 +5345,36 @@ namespace OpenSim.Region.Framework.Scenes
5129 } 5345 }
5130 } 5346 }
5131 5347
5348 if (!AuthorizeUser(agentID, out reason))
5349 {
5350 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5351 return false;
5352 }
5353
5354 if (position == Vector3.Zero) // Teleport
5355 {
5356 float posX = 128.0f;
5357 float posY = 128.0f;
5358
5359 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY))
5360 {
5361 // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID);
5362 return false;
5363 }
5364 }
5365 else // Walking
5366 {
5367 ILandObject land = LandChannel.GetLandObject(position.X, position.Y);
5368 if (land == null)
5369 return false;
5370
5371 bool banned = land.IsBannedFromLand(agentID);
5372 bool restricted = land.IsRestrictedFromLand(agentID);
5373
5374 if (banned || restricted)
5375 return false;
5376 }
5377
5132 reason = String.Empty; 5378 reason = String.Empty;
5133 return true; 5379 return true;
5134 } 5380 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index c4547f2..f343bc8 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -136,6 +136,8 @@ namespace OpenSim.Region.Framework.Scenes
136 get { return m_permissions; } 136 get { return m_permissions; }
137 } 137 }
138 138
139 protected string m_datastore;
140
139 /* Used by the loadbalancer plugin on GForge */ 141 /* Used by the loadbalancer plugin on GForge */
140 protected RegionStatus m_regStatus; 142 protected RegionStatus m_regStatus;
141 public RegionStatus RegionStatus 143 public RegionStatus RegionStatus
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index 837e655..19cb0c1 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -44,8 +44,6 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
44 44
45namespace OpenSim.Region.Framework.Scenes 45namespace OpenSim.Region.Framework.Scenes
46{ 46{
47 public delegate void KiPrimitiveDelegate(uint localID);
48
49 public delegate void RemoveKnownRegionsFromAvatarList(UUID avatarID, List<ulong> regionlst); 47 public delegate void RemoveKnownRegionsFromAvatarList(UUID avatarID, List<ulong> regionlst);
50 48
51 /// <summary> 49 /// <summary>
@@ -113,8 +111,6 @@ namespace OpenSim.Region.Framework.Scenes
113// private LogOffUser handlerLogOffUser = null; 111// private LogOffUser handlerLogOffUser = null;
114// private GetLandData handlerGetLandData = null; // OnGetLandData 112// private GetLandData handlerGetLandData = null; // OnGetLandData
115 113
116 public KiPrimitiveDelegate KiPrimitive;
117
118 public SceneCommunicationService() 114 public SceneCommunicationService()
119 { 115 {
120 } 116 }
@@ -168,7 +164,7 @@ namespace OpenSim.Region.Framework.Scenes
168 164
169 if (neighbour != null) 165 if (neighbour != null)
170 { 166 {
171 m_log.DebugFormat("[INTERGRID]: Successfully informed neighbour {0}-{1} that I'm here", x / Constants.RegionSize, y / Constants.RegionSize); 167 // m_log.DebugFormat("[INTERGRID]: Successfully informed neighbour {0}-{1} that I'm here", x / Constants.RegionSize, y / Constants.RegionSize);
172 m_scene.EventManager.TriggerOnRegionUp(neighbour); 168 m_scene.EventManager.TriggerOnRegionUp(neighbour);
173 } 169 }
174 else 170 else
@@ -183,7 +179,7 @@ namespace OpenSim.Region.Framework.Scenes
183 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName); 179 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName);
184 180
185 List<GridRegion> neighbours = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID); 181 List<GridRegion> neighbours = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID);
186 m_log.DebugFormat("[INTERGRID]: Informing {0} neighbours that this region is up", neighbours.Count); 182 //m_log.DebugFormat("[INTERGRID]: Informing {0} neighbours that this region is up", neighbours.Count);
187 foreach (GridRegion n in neighbours) 183 foreach (GridRegion n in neighbours)
188 { 184 {
189 InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync; 185 InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync;
@@ -259,46 +255,42 @@ namespace OpenSim.Region.Framework.Scenes
259 255
260 } 256 }
261 257
262 //public delegate void SendCloseChildAgentDelegate(UUID agentID, ulong regionHandle); 258 public delegate void SendCloseChildAgentDelegate(UUID agentID, ulong regionHandle);
263 //private void SendCloseChildAgentCompleted(IAsyncResult iar)
264 //{
265 // SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState;
266 // icon.EndInvoke(iar);
267 //}
268 259
269 /// <summary> 260 /// <summary>
270 /// Closes a child agent on a given region 261 /// This Closes child agents on neighboring regions
262 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
271 /// </summary> 263 /// </summary>
272 protected void SendCloseChildAgent(UUID agentID, ulong regionHandle) 264 protected void SendCloseChildAgentAsync(UUID agentID, ulong regionHandle)
273 { 265 {
274 266
275 m_log.Debug("[INTERGRID]: Sending close agent to " + regionHandle); 267 //m_log.Debug("[INTERGRID]: Sending close agent to " + regionHandle);
276 // let's do our best, but there's not much we can do if the neighbour doesn't accept. 268 // let's do our best, but there's not much we can do if the neighbour doesn't accept.
277 269
278 //m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID); 270 //m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID);
279 uint x = 0, y = 0; 271 uint x = 0, y = 0;
280 Utils.LongToUInts(regionHandle, out x, out y); 272 Utils.LongToUInts(regionHandle, out x, out y);
281 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y); 273 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);
282 m_scene.SimulationService.CloseAgent(destination, agentID); 274 m_scene.SimulationService.CloseChildAgent(destination, agentID);
275 }
276
277 private void SendCloseChildAgentCompleted(IAsyncResult iar)
278 {
279 SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState;
280 icon.EndInvoke(iar);
283 } 281 }
284 282
285 /// <summary>
286 /// Closes a child agents in a collection of regions. Does so asynchronously
287 /// so that the caller doesn't wait.
288 /// </summary>
289 /// <param name="agentID"></param>
290 /// <param name="regionslst"></param>
291 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst) 283 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst)
292 { 284 {
293 Util.FireAndForget(delegate 285 foreach (ulong handle in regionslst)
294 { 286 {
295 foreach (ulong handle in regionslst) 287 SendCloseChildAgentDelegate d = SendCloseChildAgentAsync;
296 { 288 d.BeginInvoke(agentID, handle,
297 SendCloseChildAgent(agentID, handle); 289 SendCloseChildAgentCompleted,
298 } 290 d);
299 }); 291 }
300 } 292 }
301 293
302 public List<GridRegion> RequestNamedRegions(string name, int maxNumber) 294 public List<GridRegion> RequestNamedRegions(string name, int maxNumber)
303 { 295 {
304 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber); 296 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 a078291..39d4a29 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -43,6 +43,12 @@ namespace OpenSim.Region.Framework.Scenes
43 43
44 public delegate void ObjectDuplicateDelegate(EntityBase original, EntityBase clone); 44 public delegate void ObjectDuplicateDelegate(EntityBase original, EntityBase clone);
45 45
46 public delegate void AttachToBackupDelegate(SceneObjectGroup sog);
47
48 public delegate void DetachFromBackupDelegate(SceneObjectGroup sog);
49
50 public delegate void ChangedBackupDelegate(SceneObjectGroup sog);
51
46 public delegate void ObjectCreateDelegate(EntityBase obj); 52 public delegate void ObjectCreateDelegate(EntityBase obj);
47 53
48 public delegate void ObjectDeleteDelegate(EntityBase obj); 54 public delegate void ObjectDeleteDelegate(EntityBase obj);
@@ -61,6 +67,9 @@ namespace OpenSim.Region.Framework.Scenes
61 private PhysicsCrash handlerPhysicsCrash = null; 67 private PhysicsCrash handlerPhysicsCrash = null;
62 68
63 public event ObjectDuplicateDelegate OnObjectDuplicate; 69 public event ObjectDuplicateDelegate OnObjectDuplicate;
70 public event AttachToBackupDelegate OnAttachToBackup;
71 public event DetachFromBackupDelegate OnDetachFromBackup;
72 public event ChangedBackupDelegate OnChangeBackup;
64 public event ObjectCreateDelegate OnObjectCreate; 73 public event ObjectCreateDelegate OnObjectCreate;
65 public event ObjectDeleteDelegate OnObjectRemove; 74 public event ObjectDeleteDelegate OnObjectRemove;
66 75
@@ -68,7 +77,7 @@ namespace OpenSim.Region.Framework.Scenes
68 77
69 #region Fields 78 #region Fields
70 79
71 protected object m_presenceLock = new object(); 80 protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim();
72 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>(); 81 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>();
73 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>(); 82 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>();
74 83
@@ -135,13 +144,18 @@ namespace OpenSim.Region.Framework.Scenes
135 144
136 protected internal void Close() 145 protected internal void Close()
137 { 146 {
138 lock (m_presenceLock) 147 m_scenePresencesLock.EnterWriteLock();
148 try
139 { 149 {
140 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 150 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
141 List<ScenePresence> newlist = new List<ScenePresence>(); 151 List<ScenePresence> newlist = new List<ScenePresence>();
142 m_scenePresenceMap = newmap; 152 m_scenePresenceMap = newmap;
143 m_scenePresenceArray = newlist; 153 m_scenePresenceArray = newlist;
144 } 154 }
155 finally
156 {
157 m_scenePresencesLock.ExitWriteLock();
158 }
145 159
146 lock (SceneObjectGroupsByFullID) 160 lock (SceneObjectGroupsByFullID)
147 SceneObjectGroupsByFullID.Clear(); 161 SceneObjectGroupsByFullID.Clear();
@@ -273,6 +287,33 @@ namespace OpenSim.Region.Framework.Scenes
273 protected internal bool AddRestoredSceneObject( 287 protected internal bool AddRestoredSceneObject(
274 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 288 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
275 { 289 {
290 if (!m_parentScene.CombineRegions)
291 {
292 // KF: Check for out-of-region, move inside and make static.
293 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
294 sceneObject.RootPart.GroupPosition.Y,
295 sceneObject.RootPart.GroupPosition.Z);
296 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 ||
297 npos.X > Constants.RegionSize ||
298 npos.Y > Constants.RegionSize))
299 {
300 if (npos.X < 0.0) npos.X = 1.0f;
301 if (npos.Y < 0.0) npos.Y = 1.0f;
302 if (npos.Z < 0.0) npos.Z = 0.0f;
303 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
304 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
305
306 foreach (SceneObjectPart part in sceneObject.Parts)
307 {
308 part.GroupPosition = npos;
309 }
310 sceneObject.RootPart.Velocity = Vector3.Zero;
311 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
312 sceneObject.RootPart.Acceleration = Vector3.Zero;
313 sceneObject.RootPart.Velocity = Vector3.Zero;
314 }
315 }
316
276 if (attachToBackup && (!alreadyPersisted)) 317 if (attachToBackup && (!alreadyPersisted))
277 { 318 {
278 sceneObject.ForceInventoryPersistence(); 319 sceneObject.ForceInventoryPersistence();
@@ -486,6 +527,30 @@ namespace OpenSim.Region.Framework.Scenes
486 m_updateList[obj.UUID] = obj; 527 m_updateList[obj.UUID] = obj;
487 } 528 }
488 529
530 public void FireAttachToBackup(SceneObjectGroup obj)
531 {
532 if (OnAttachToBackup != null)
533 {
534 OnAttachToBackup(obj);
535 }
536 }
537
538 public void FireDetachFromBackup(SceneObjectGroup obj)
539 {
540 if (OnDetachFromBackup != null)
541 {
542 OnDetachFromBackup(obj);
543 }
544 }
545
546 public void FireChangeBackup(SceneObjectGroup obj)
547 {
548 if (OnChangeBackup != null)
549 {
550 OnChangeBackup(obj);
551 }
552 }
553
489 /// <summary> 554 /// <summary>
490 /// Process all pending updates 555 /// Process all pending updates
491 /// </summary> 556 /// </summary>
@@ -621,7 +686,8 @@ namespace OpenSim.Region.Framework.Scenes
621 686
622 Entities[presence.UUID] = presence; 687 Entities[presence.UUID] = presence;
623 688
624 lock (m_presenceLock) 689 m_scenePresencesLock.EnterWriteLock();
690 try
625 { 691 {
626 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 692 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
627 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 693 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -645,6 +711,10 @@ namespace OpenSim.Region.Framework.Scenes
645 m_scenePresenceMap = newmap; 711 m_scenePresenceMap = newmap;
646 m_scenePresenceArray = newlist; 712 m_scenePresenceArray = newlist;
647 } 713 }
714 finally
715 {
716 m_scenePresencesLock.ExitWriteLock();
717 }
648 } 718 }
649 719
650 /// <summary> 720 /// <summary>
@@ -659,7 +729,8 @@ namespace OpenSim.Region.Framework.Scenes
659 agentID); 729 agentID);
660 } 730 }
661 731
662 lock (m_presenceLock) 732 m_scenePresencesLock.EnterWriteLock();
733 try
663 { 734 {
664 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 735 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
665 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 736 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -681,6 +752,10 @@ namespace OpenSim.Region.Framework.Scenes
681 m_log.WarnFormat("[SCENEGRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 752 m_log.WarnFormat("[SCENEGRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
682 } 753 }
683 } 754 }
755 finally
756 {
757 m_scenePresencesLock.ExitWriteLock();
758 }
684 } 759 }
685 760
686 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 761 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1363,8 +1438,13 @@ namespace OpenSim.Region.Framework.Scenes
1363 { 1438 {
1364 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1439 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1365 { 1440 {
1366 if (m_parentScene.AttachmentsModule != null) 1441 // Set the new attachment point data in the object
1367 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1442 byte attachmentPoint = group.GetAttachmentPoint();
1443 group.UpdateGroupPosition(pos);
1444 group.RootPart.IsAttachment = false;
1445 group.AbsolutePosition = group.RootPart.AttachedPos;
1446 group.SetAttachmentPoint(attachmentPoint);
1447 group.HasGroupChanged = true;
1368 } 1448 }
1369 else 1449 else
1370 { 1450 {
@@ -1617,10 +1697,13 @@ namespace OpenSim.Region.Framework.Scenes
1617 /// <param name="childPrims"></param> 1697 /// <param name="childPrims"></param>
1618 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) 1698 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
1619 { 1699 {
1700 SceneObjectGroup parentGroup = root.ParentGroup;
1701 if (parentGroup == null) return;
1620 Monitor.Enter(m_updateLock); 1702 Monitor.Enter(m_updateLock);
1703
1621 try 1704 try
1622 { 1705 {
1623 SceneObjectGroup parentGroup = root.ParentGroup; 1706 parentGroup.areUpdatesSuspended = true;
1624 1707
1625 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1708 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1626 if (parentGroup != null) 1709 if (parentGroup != null)
@@ -1632,11 +1715,6 @@ namespace OpenSim.Region.Framework.Scenes
1632 1715
1633 if (child != null) 1716 if (child != null)
1634 { 1717 {
1635 // Make sure no child prim is set for sale
1636 // So that, on delink, no prims are unwittingly
1637 // left for sale and sold off
1638 child.RootPart.ObjectSaleType = 0;
1639 child.RootPart.SalePrice = 10;
1640 childGroups.Add(child); 1718 childGroups.Add(child);
1641 } 1719 }
1642 } 1720 }
@@ -1659,12 +1737,13 @@ namespace OpenSim.Region.Framework.Scenes
1659 // occur on link to invoke this elsewhere (such as object selection) 1737 // occur on link to invoke this elsewhere (such as object selection)
1660 parentGroup.RootPart.CreateSelected = true; 1738 parentGroup.RootPart.CreateSelected = true;
1661 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1739 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1662 parentGroup.HasGroupChanged = true;
1663 parentGroup.ScheduleGroupForFullUpdate();
1664
1665 } 1740 }
1666 finally 1741 finally
1667 { 1742 {
1743 parentGroup.areUpdatesSuspended = false;
1744 parentGroup.HasGroupChanged = true;
1745 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1746 parentGroup.ScheduleGroupForFullUpdate();
1668 Monitor.Exit(m_updateLock); 1747 Monitor.Exit(m_updateLock);
1669 } 1748 }
1670 } 1749 }
@@ -1696,21 +1775,24 @@ namespace OpenSim.Region.Framework.Scenes
1696 1775
1697 SceneObjectGroup group = part.ParentGroup; 1776 SceneObjectGroup group = part.ParentGroup;
1698 if (!affectedGroups.Contains(group)) 1777 if (!affectedGroups.Contains(group))
1778 {
1779 group.areUpdatesSuspended = true;
1699 affectedGroups.Add(group); 1780 affectedGroups.Add(group);
1781 }
1700 } 1782 }
1701 } 1783 }
1702 } 1784 }
1703 1785
1704 foreach (SceneObjectPart child in childParts) 1786 if (childParts.Count > 0)
1705 { 1787 {
1706 // Unlink all child parts from their groups 1788 foreach (SceneObjectPart child in childParts)
1707 // 1789 {
1708 child.ParentGroup.DelinkFromGroup(child, true); 1790 // Unlink all child parts from their groups
1709 1791 //
1710 // These are not in affected groups and will not be 1792 child.ParentGroup.DelinkFromGroup(child, true);
1711 // handled further. Do the honors here. 1793 child.ParentGroup.HasGroupChanged = true;
1712 child.ParentGroup.HasGroupChanged = true; 1794 child.ParentGroup.ScheduleGroupForFullUpdate();
1713 child.ParentGroup.ScheduleGroupForFullUpdate(); 1795 }
1714 } 1796 }
1715 1797
1716 foreach (SceneObjectPart root in rootParts) 1798 foreach (SceneObjectPart root in rootParts)
@@ -1720,56 +1802,68 @@ namespace OpenSim.Region.Framework.Scenes
1720 // However, editing linked parts and unlinking may be different 1802 // However, editing linked parts and unlinking may be different
1721 // 1803 //
1722 SceneObjectGroup group = root.ParentGroup; 1804 SceneObjectGroup group = root.ParentGroup;
1805 group.areUpdatesSuspended = true;
1723 1806
1724 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1807 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1725 int numChildren = newSet.Count; 1808 int numChildren = newSet.Count;
1726 1809
1810 if (numChildren == 1)
1811 break;
1812
1727 // If there are prims left in a link set, but the root is 1813 // If there are prims left in a link set, but the root is
1728 // slated for unlink, we need to do this 1814 // slated for unlink, we need to do this
1815 // Unlink the remaining set
1729 // 1816 //
1730 if (numChildren != 1) 1817 bool sendEventsToRemainder = true;
1731 { 1818 if (numChildren > 1)
1732 // Unlink the remaining set 1819 sendEventsToRemainder = false;
1733 //
1734 bool sendEventsToRemainder = true;
1735 if (numChildren > 1)
1736 sendEventsToRemainder = false;
1737 1820
1738 foreach (SceneObjectPart p in newSet) 1821 foreach (SceneObjectPart p in newSet)
1822 {
1823 if (p != group.RootPart)
1739 { 1824 {
1740 if (p != group.RootPart) 1825 group.DelinkFromGroup(p, sendEventsToRemainder);
1741 group.DelinkFromGroup(p, sendEventsToRemainder); 1826 if (numChildren > 2)
1827 {
1828 p.ParentGroup.areUpdatesSuspended = true;
1829 }
1830 else
1831 {
1832 p.ParentGroup.HasGroupChanged = true;
1833 p.ParentGroup.ScheduleGroupForFullUpdate();
1834 }
1742 } 1835 }
1836 }
1743 1837
1744 // If there is more than one prim remaining, we 1838 // If there is more than one prim remaining, we
1745 // need to re-link 1839 // need to re-link
1840 //
1841 if (numChildren > 2)
1842 {
1843 // Remove old root
1844 //
1845 if (newSet.Contains(root))
1846 newSet.Remove(root);
1847
1848 // Preserve link ordering
1746 // 1849 //
1747 if (numChildren > 2) 1850 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1748 { 1851 {
1749 // Remove old root 1852 return a.LinkNum.CompareTo(b.LinkNum);
1750 // 1853 });
1751 if (newSet.Contains(root))
1752 newSet.Remove(root);
1753
1754 // Preserve link ordering
1755 //
1756 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1757 {
1758 return a.LinkNum.CompareTo(b.LinkNum);
1759 });
1760 1854
1761 // Determine new root 1855 // Determine new root
1762 // 1856 //
1763 SceneObjectPart newRoot = newSet[0]; 1857 SceneObjectPart newRoot = newSet[0];
1764 newSet.RemoveAt(0); 1858 newSet.RemoveAt(0);
1765 1859
1766 foreach (SceneObjectPart newChild in newSet) 1860 foreach (SceneObjectPart newChild in newSet)
1767 newChild.UpdateFlag = 0; 1861 newChild.UpdateFlag = 0;
1768 1862
1769 LinkObjects(newRoot, newSet); 1863 newRoot.ParentGroup.areUpdatesSuspended = true;
1770 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1864 LinkObjects(newRoot, newSet);
1771 affectedGroups.Add(newRoot.ParentGroup); 1865 if (!affectedGroups.Contains(newRoot.ParentGroup))
1772 } 1866 affectedGroups.Add(newRoot.ParentGroup);
1773 } 1867 }
1774 } 1868 }
1775 1869
@@ -1777,8 +1871,14 @@ namespace OpenSim.Region.Framework.Scenes
1777 // 1871 //
1778 foreach (SceneObjectGroup g in affectedGroups) 1872 foreach (SceneObjectGroup g in affectedGroups)
1779 { 1873 {
1874 // Child prims that have been unlinked and deleted will
1875 // return unless the root is deleted. This will remove them
1876 // from the database. They will be rewritten immediately,
1877 // minus the rows for the unlinked child prims.
1878 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1780 g.TriggerScriptChangedEvent(Changed.LINK); 1879 g.TriggerScriptChangedEvent(Changed.LINK);
1781 g.HasGroupChanged = true; // Persist 1880 g.HasGroupChanged = true; // Persist
1881 g.areUpdatesSuspended = false;
1782 g.ScheduleGroupForFullUpdate(); 1882 g.ScheduleGroupForFullUpdate();
1783 } 1883 }
1784 } 1884 }
@@ -1896,9 +1996,6 @@ namespace OpenSim.Region.Framework.Scenes
1896 child.ApplyNextOwnerPermissions(); 1996 child.ApplyNextOwnerPermissions();
1897 } 1997 }
1898 } 1998 }
1899
1900 copy.RootPart.ObjectSaleType = 0;
1901 copy.RootPart.SalePrice = 10;
1902 } 1999 }
1903 2000
1904 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2001 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index 4bca3d0..9f0ac4f 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -69,10 +69,6 @@ namespace OpenSim.Region.Framework.Scenes
69 /// <summary> 69 /// <summary>
70 /// Stop the scripts contained in all the prims in this group 70 /// Stop the scripts contained in all the prims in this group
71 /// </summary> 71 /// </summary>
72 /// <param name="sceneObjectBeingDeleted">
73 /// Should be true if these scripts are being removed because the scene
74 /// object is being deleted. This will prevent spurious updates to the client.
75 /// </param>
76 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 72 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
77 { 73 {
78 SceneObjectPart[] parts = m_parts.GetArray(); 74 SceneObjectPart[] parts = m_parts.GetArray();
@@ -385,6 +381,9 @@ namespace OpenSim.Region.Framework.Scenes
385 381
386 public void ResumeScripts() 382 public void ResumeScripts()
387 { 383 {
384 if (m_scene.RegionInfo.RegionSettings.DisableScripts)
385 return;
386
388 SceneObjectPart[] parts = m_parts.GetArray(); 387 SceneObjectPart[] parts = m_parts.GetArray();
389 for (int i = 0; i < parts.Length; i++) 388 for (int i = 0; i < parts.Length; i++)
390 parts[i].Inventory.ResumeScripts(); 389 parts[i].Inventory.ResumeScripts();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 42ac9aa..482597d 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -29,6 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Drawing; 30using System.Drawing;
31using System.IO; 31using System.IO;
32using System.Diagnostics;
32using System.Linq; 33using System.Linq;
33using System.Threading; 34using System.Threading;
34using System.Xml; 35using System.Xml;
@@ -105,8 +106,29 @@ namespace OpenSim.Region.Framework.Scenes
105 /// since the group's last persistent backup 106 /// since the group's last persistent backup
106 /// </summary> 107 /// </summary>
107 private bool m_hasGroupChanged = false; 108 private bool m_hasGroupChanged = false;
108 private long timeFirstChanged; 109 private long timeFirstChanged = 0;
109 private long timeLastChanged; 110 private long timeLastChanged = 0;
111 private long m_maxPersistTime = 0;
112 private long m_minPersistTime = 0;
113 private Random m_rand;
114 private bool m_suspendUpdates;
115 private List<ScenePresence> m_linkedAvatars = new List<ScenePresence>();
116
117 public bool areUpdatesSuspended
118 {
119 get
120 {
121 return m_suspendUpdates;
122 }
123 set
124 {
125 m_suspendUpdates = value;
126 if (!value)
127 {
128 QueueForUpdateCheck();
129 }
130 }
131 }
110 132
111 public bool HasGroupChanged 133 public bool HasGroupChanged
112 { 134 {
@@ -114,9 +136,39 @@ namespace OpenSim.Region.Framework.Scenes
114 { 136 {
115 if (value) 137 if (value)
116 { 138 {
139 if (m_isBackedUp)
140 {
141 m_scene.SceneGraph.FireChangeBackup(this);
142 }
117 timeLastChanged = DateTime.Now.Ticks; 143 timeLastChanged = DateTime.Now.Ticks;
118 if (!m_hasGroupChanged) 144 if (!m_hasGroupChanged)
119 timeFirstChanged = DateTime.Now.Ticks; 145 timeFirstChanged = DateTime.Now.Ticks;
146 if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null)
147 {
148 if (m_rand == null)
149 {
150 byte[] val = new byte[16];
151 m_rootPart.UUID.ToBytes(val, 0);
152 m_rand = new Random(BitConverter.ToInt32(val, 0));
153 }
154
155 if (m_scene.GetRootAgentCount() == 0)
156 {
157 //If the region is empty, this change has been made by an automated process
158 //and thus we delay the persist time by a random amount between 1.5 and 2.5.
159
160 float factor = 1.5f + (float)(m_rand.NextDouble());
161 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor);
162 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor);
163 }
164 else
165 {
166 //If the region is not empty, we want to obey the minimum and maximum persist times
167 //but add a random factor so we stagger the object persistance a little
168 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5
169 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0
170 }
171 }
120 } 172 }
121 m_hasGroupChanged = value; 173 m_hasGroupChanged = value;
122 174
@@ -131,7 +183,7 @@ namespace OpenSim.Region.Framework.Scenes
131 /// Has the group changed due to an unlink operation? We record this in order to optimize deletion, since 183 /// Has the group changed due to an unlink operation? We record this in order to optimize deletion, since
132 /// an unlinked group currently has to be persisted to the database before we can perform an unlink operation. 184 /// an unlinked group currently has to be persisted to the database before we can perform an unlink operation.
133 /// </summary> 185 /// </summary>
134 public bool HasGroupChangedDueToDelink { get; private set; } 186 public bool HasGroupChangedDueToDelink { get; set; }
135 187
136 private bool isTimeToPersist() 188 private bool isTimeToPersist()
137 { 189 {
@@ -141,8 +193,19 @@ namespace OpenSim.Region.Framework.Scenes
141 return false; 193 return false;
142 if (m_scene.ShuttingDown) 194 if (m_scene.ShuttingDown)
143 return true; 195 return true;
196
197 if (m_minPersistTime == 0 || m_maxPersistTime == 0)
198 {
199 m_maxPersistTime = m_scene.m_persistAfter;
200 m_minPersistTime = m_scene.m_dontPersistBefore;
201 }
202
144 long currentTime = DateTime.Now.Ticks; 203 long currentTime = DateTime.Now.Ticks;
145 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) 204
205 if (timeLastChanged == 0) timeLastChanged = currentTime;
206 if (timeFirstChanged == 0) timeFirstChanged = currentTime;
207
208 if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime)
146 return true; 209 return true;
147 return false; 210 return false;
148 } 211 }
@@ -185,10 +248,10 @@ namespace OpenSim.Region.Framework.Scenes
185 248
186 private bool m_scriptListens_atTarget; 249 private bool m_scriptListens_atTarget;
187 private bool m_scriptListens_notAtTarget; 250 private bool m_scriptListens_notAtTarget;
188
189 private bool m_scriptListens_atRotTarget; 251 private bool m_scriptListens_atRotTarget;
190 private bool m_scriptListens_notAtRotTarget; 252 private bool m_scriptListens_notAtRotTarget;
191 253
254 public bool m_dupeInProgress = false;
192 internal Dictionary<UUID, string> m_savedScriptState; 255 internal Dictionary<UUID, string> m_savedScriptState;
193 256
194 #region Properties 257 #region Properties
@@ -228,7 +291,13 @@ namespace OpenSim.Region.Framework.Scenes
228 public virtual Quaternion Rotation 291 public virtual Quaternion Rotation
229 { 292 {
230 get { return m_rotation; } 293 get { return m_rotation; }
231 set { m_rotation = value; } 294 set {
295 foreach(SceneObjectPart p in m_parts.GetArray())
296 {
297 p.StoreUndoState(UndoType.STATE_GROUP_ROTATION);
298 }
299 m_rotation = value;
300 }
232 } 301 }
233 302
234 public Quaternion GroupRotation 303 public Quaternion GroupRotation
@@ -305,7 +374,11 @@ namespace OpenSim.Region.Framework.Scenes
305 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 374 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
306 } 375 }
307 } 376 }
308 377
378 foreach (SceneObjectPart part in m_parts.GetArray())
379 {
380 part.IgnoreUndoUpdate = true;
381 }
309 if (RootPart.GetStatusSandbox()) 382 if (RootPart.GetStatusSandbox())
310 { 383 {
311 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 384 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -319,10 +392,31 @@ namespace OpenSim.Region.Framework.Scenes
319 return; 392 return;
320 } 393 }
321 } 394 }
322
323 SceneObjectPart[] parts = m_parts.GetArray(); 395 SceneObjectPart[] parts = m_parts.GetArray();
324 for (int i = 0; i < parts.Length; i++) 396 foreach (SceneObjectPart part in parts)
325 parts[i].GroupPosition = val; 397 {
398 part.IgnoreUndoUpdate = false;
399 part.StoreUndoState(UndoType.STATE_GROUP_POSITION);
400 part.GroupPosition = val;
401 if (!m_dupeInProgress)
402 {
403 part.TriggerScriptChangedEvent(Changed.POSITION);
404 }
405 }
406 if (!m_dupeInProgress)
407 {
408 foreach (ScenePresence av in m_linkedAvatars)
409 {
410 SceneObjectPart p;
411 if (m_parts.TryGetValue(av.LinkedPrim, out p))
412 {
413 Vector3 offset = p.GetWorldPosition() - av.ParentPosition;
414 av.AbsolutePosition += offset;
415 av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
416 av.SendAvatarDataToAllAgents();
417 }
418 }
419 }
326 420
327 //if (m_rootPart.PhysActor != null) 421 //if (m_rootPart.PhysActor != null)
328 //{ 422 //{
@@ -481,6 +575,7 @@ namespace OpenSim.Region.Framework.Scenes
481 /// </summary> 575 /// </summary>
482 public SceneObjectGroup() 576 public SceneObjectGroup()
483 { 577 {
578
484 } 579 }
485 580
486 /// <summary> 581 /// <summary>
@@ -497,7 +592,7 @@ namespace OpenSim.Region.Framework.Scenes
497 /// Constructor. This object is added to the scene later via AttachToScene() 592 /// Constructor. This object is added to the scene later via AttachToScene()
498 /// </summary> 593 /// </summary>
499 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 594 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
500 { 595 {
501 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 596 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
502 } 597 }
503 598
@@ -545,6 +640,9 @@ namespace OpenSim.Region.Framework.Scenes
545 /// </summary> 640 /// </summary>
546 public virtual void AttachToBackup() 641 public virtual void AttachToBackup()
547 { 642 {
643 if (IsAttachment) return;
644 m_scene.SceneGraph.FireAttachToBackup(this);
645
548 if (InSceneBackup) 646 if (InSceneBackup)
549 { 647 {
550 //m_log.DebugFormat( 648 //m_log.DebugFormat(
@@ -587,6 +685,9 @@ namespace OpenSim.Region.Framework.Scenes
587 685
588 ApplyPhysics(m_scene.m_physicalPrim); 686 ApplyPhysics(m_scene.m_physicalPrim);
589 687
688 if (RootPart.PhysActor != null)
689 RootPart.Buoyancy = RootPart.Buoyancy;
690
590 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 691 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
591 // for the same object with very different properties. The caller must schedule the update. 692 // for the same object with very different properties. The caller must schedule the update.
592 //ScheduleGroupForFullUpdate(); 693 //ScheduleGroupForFullUpdate();
@@ -660,9 +761,9 @@ namespace OpenSim.Region.Framework.Scenes
660 result.normal = inter.normal; 761 result.normal = inter.normal;
661 result.distance = inter.distance; 762 result.distance = inter.distance;
662 } 763 }
764
663 } 765 }
664 } 766 }
665
666 return result; 767 return result;
667 } 768 }
668 769
@@ -682,17 +783,19 @@ namespace OpenSim.Region.Framework.Scenes
682 minZ = 8192f; 783 minZ = 8192f;
683 784
684 SceneObjectPart[] parts = m_parts.GetArray(); 785 SceneObjectPart[] parts = m_parts.GetArray();
685 for (int i = 0; i < parts.Length; i++) 786 foreach (SceneObjectPart part in parts)
686 { 787 {
687 SceneObjectPart part = parts[i];
688
689 Vector3 worldPos = part.GetWorldPosition(); 788 Vector3 worldPos = part.GetWorldPosition();
690 Vector3 offset = worldPos - AbsolutePosition; 789 Vector3 offset = worldPos - AbsolutePosition;
691 Quaternion worldRot; 790 Quaternion worldRot;
692 if (part.ParentID == 0) 791 if (part.ParentID == 0)
792 {
693 worldRot = part.RotationOffset; 793 worldRot = part.RotationOffset;
794 }
694 else 795 else
796 {
695 worldRot = part.GetWorldRotation(); 797 worldRot = part.GetWorldRotation();
798 }
696 799
697 Vector3 frontTopLeft; 800 Vector3 frontTopLeft;
698 Vector3 frontTopRight; 801 Vector3 frontTopRight;
@@ -704,6 +807,8 @@ namespace OpenSim.Region.Framework.Scenes
704 Vector3 backBottomLeft; 807 Vector3 backBottomLeft;
705 Vector3 backBottomRight; 808 Vector3 backBottomRight;
706 809
810 // Vector3[] corners = new Vector3[8];
811
707 Vector3 orig = Vector3.Zero; 812 Vector3 orig = Vector3.Zero;
708 813
709 frontTopLeft.X = orig.X - (part.Scale.X / 2); 814 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -738,6 +843,38 @@ namespace OpenSim.Region.Framework.Scenes
738 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 843 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
739 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 844 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
740 845
846
847
848 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
849 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
850 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
851 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
852 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
853 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
854 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
855 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
856
857 //for (int i = 0; i < 8; i++)
858 //{
859 // corners[i] = corners[i] * worldRot;
860 // corners[i] += offset;
861
862 // if (corners[i].X > maxX)
863 // maxX = corners[i].X;
864 // if (corners[i].X < minX)
865 // minX = corners[i].X;
866
867 // if (corners[i].Y > maxY)
868 // maxY = corners[i].Y;
869 // if (corners[i].Y < minY)
870 // minY = corners[i].Y;
871
872 // if (corners[i].Z > maxZ)
873 // maxZ = corners[i].Y;
874 // if (corners[i].Z < minZ)
875 // minZ = corners[i].Z;
876 //}
877
741 frontTopLeft = frontTopLeft * worldRot; 878 frontTopLeft = frontTopLeft * worldRot;
742 frontTopRight = frontTopRight * worldRot; 879 frontTopRight = frontTopRight * worldRot;
743 frontBottomLeft = frontBottomLeft * worldRot; 880 frontBottomLeft = frontBottomLeft * worldRot;
@@ -759,6 +896,15 @@ namespace OpenSim.Region.Framework.Scenes
759 backTopLeft += offset; 896 backTopLeft += offset;
760 backTopRight += offset; 897 backTopRight += offset;
761 898
899 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
900 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
901 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
902 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
903 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
904 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
905 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
906 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
907
762 if (frontTopRight.X > maxX) 908 if (frontTopRight.X > maxX)
763 maxX = frontTopRight.X; 909 maxX = frontTopRight.X;
764 if (frontTopLeft.X > maxX) 910 if (frontTopLeft.X > maxX)
@@ -904,15 +1050,20 @@ namespace OpenSim.Region.Framework.Scenes
904 1050
905 public void SaveScriptedState(XmlTextWriter writer) 1051 public void SaveScriptedState(XmlTextWriter writer)
906 { 1052 {
1053 SaveScriptedState(writer, false);
1054 }
1055
1056 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1057 {
907 XmlDocument doc = new XmlDocument(); 1058 XmlDocument doc = new XmlDocument();
908 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1059 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
909 1060
910 SceneObjectPart[] parts = m_parts.GetArray(); 1061 SceneObjectPart[] parts = m_parts.GetArray();
911 for (int i = 0; i < parts.Length; i++) 1062 for (int i = 0; i < parts.Length; i++)
912 { 1063 {
913 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 1064 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
914 foreach (KeyValuePair<UUID, string> kvp in pstates) 1065 foreach (KeyValuePair<UUID, string> kvp in pstates)
915 states.Add(kvp.Key, kvp.Value); 1066 states[kvp.Key] = kvp.Value;
916 } 1067 }
917 1068
918 if (states.Count > 0) 1069 if (states.Count > 0)
@@ -931,6 +1082,118 @@ namespace OpenSim.Region.Framework.Scenes
931 } 1082 }
932 } 1083 }
933 1084
1085 /// <summary>
1086 /// Add the avatar to this linkset (avatar is sat).
1087 /// </summary>
1088 /// <param name="agentID"></param>
1089 public void AddAvatar(UUID agentID)
1090 {
1091 ScenePresence presence;
1092 if (m_scene.TryGetScenePresence(agentID, out presence))
1093 {
1094 if (!m_linkedAvatars.Contains(presence))
1095 {
1096 m_linkedAvatars.Add(presence);
1097 }
1098 }
1099 }
1100
1101 /// <summary>
1102 /// Delete the avatar from this linkset (avatar is unsat).
1103 /// </summary>
1104 /// <param name="agentID"></param>
1105 public void DeleteAvatar(UUID agentID)
1106 {
1107 ScenePresence presence;
1108 if (m_scene.TryGetScenePresence(agentID, out presence))
1109 {
1110 if (m_linkedAvatars.Contains(presence))
1111 {
1112 m_linkedAvatars.Remove(presence);
1113 }
1114 }
1115 }
1116
1117 /// <summary>
1118 /// Returns the list of linked presences (avatars sat on this group)
1119 /// </summary>
1120 /// <param name="agentID"></param>
1121 public List<ScenePresence> GetLinkedAvatars()
1122 {
1123 return m_linkedAvatars;
1124 }
1125
1126 /// <summary>
1127 /// Attach this scene object to the given avatar.
1128 /// </summary>
1129 /// <param name="agentID"></param>
1130 /// <param name="attachmentpoint"></param>
1131 /// <param name="AttachOffset"></param>
1132 public void AttachToAgent(UUID agentID, uint attachmentpoint, Vector3 AttachOffset, bool silent)
1133 {
1134 ScenePresence avatar = m_scene.GetScenePresence(agentID);
1135 if (avatar != null)
1136 {
1137 // don't attach attachments to child agents
1138 if (avatar.IsChildAgent) return;
1139
1140// m_log.DebugFormat("[SOG]: Adding attachment {0} to avatar {1}", Name, avatar.Name);
1141
1142 DetachFromBackup();
1143
1144 // Remove from database and parcel prim count
1145 m_scene.DeleteFromStorage(UUID);
1146 m_scene.EventManager.TriggerParcelPrimCountTainted();
1147
1148 m_rootPart.AttachedAvatar = agentID;
1149
1150 //Anakin Lohner bug #3839
1151 lock (m_parts)
1152 {
1153 foreach (SceneObjectPart p in m_parts.GetArray())
1154 {
1155 p.AttachedAvatar = agentID;
1156 }
1157 }
1158
1159 if (m_rootPart.PhysActor != null)
1160 {
1161 m_scene.PhysicsScene.RemovePrim(m_rootPart.PhysActor);
1162 m_rootPart.PhysActor = null;
1163 }
1164
1165 AbsolutePosition = AttachOffset;
1166 m_rootPart.AttachedPos = AttachOffset;
1167 m_rootPart.IsAttachment = true;
1168
1169 m_rootPart.SetParentLocalId(avatar.LocalId);
1170 SetAttachmentPoint(Convert.ToByte(attachmentpoint));
1171
1172 avatar.AddAttachment(this);
1173
1174 if (!silent)
1175 {
1176 // Killing it here will cause the client to deselect it
1177 // It then reappears on the avatar, deselected
1178 // through the full update below
1179 //
1180 if (IsSelected)
1181 {
1182 m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
1183 }
1184
1185 IsSelected = false; // fudge....
1186 ScheduleGroupForFullUpdate();
1187 }
1188 }
1189 else
1190 {
1191 m_log.WarnFormat(
1192 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1193 UUID, agentID, Scene.RegionInfo.RegionName);
1194 }
1195 }
1196
934 public byte GetAttachmentPoint() 1197 public byte GetAttachmentPoint()
935 { 1198 {
936 return m_rootPart.Shape.State; 1199 return m_rootPart.Shape.State;
@@ -1057,7 +1320,10 @@ namespace OpenSim.Region.Framework.Scenes
1057 public void AddPart(SceneObjectPart part) 1320 public void AddPart(SceneObjectPart part)
1058 { 1321 {
1059 part.SetParent(this); 1322 part.SetParent(this);
1060 part.LinkNum = m_parts.Add(part.UUID, part); 1323 m_parts.Add(part.UUID, part);
1324
1325 part.LinkNum = m_parts.Count;
1326
1061 if (part.LinkNum == 2 && RootPart != null) 1327 if (part.LinkNum == 2 && RootPart != null)
1062 RootPart.LinkNum = 1; 1328 RootPart.LinkNum = 1;
1063 } 1329 }
@@ -1141,7 +1407,7 @@ namespace OpenSim.Region.Framework.Scenes
1141 1407
1142 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient) 1408 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient)
1143 { 1409 {
1144 part.StoreUndoState(); 1410 part.StoreUndoState(UndoType.STATE_PRIM_ALL);
1145 part.OnGrab(offsetPos, remoteClient); 1411 part.OnGrab(offsetPos, remoteClient);
1146 } 1412 }
1147 1413
@@ -1161,6 +1427,11 @@ namespace OpenSim.Region.Framework.Scenes
1161 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1427 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1162 public void DeleteGroupFromScene(bool silent) 1428 public void DeleteGroupFromScene(bool silent)
1163 { 1429 {
1430 // We need to keep track of this state in case this group is still queued for backup.
1431 m_isDeleted = true;
1432
1433 DetachFromBackup();
1434
1164 SceneObjectPart[] parts = m_parts.GetArray(); 1435 SceneObjectPart[] parts = m_parts.GetArray();
1165 for (int i = 0; i < parts.Length; i++) 1436 for (int i = 0; i < parts.Length; i++)
1166 { 1437 {
@@ -1172,13 +1443,11 @@ namespace OpenSim.Region.Framework.Scenes
1172 avatar.StandUp(); 1443 avatar.StandUp();
1173 1444
1174 if (!silent) 1445 if (!silent)
1175 {
1176 part.UpdateFlag = 0; 1446 part.UpdateFlag = 0;
1177 if (part == m_rootPart)
1178 avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1179 }
1180 }); 1447 });
1181 } 1448 }
1449
1450
1182 } 1451 }
1183 1452
1184 public void AddScriptLPS(int count) 1453 public void AddScriptLPS(int count)
@@ -1275,7 +1544,12 @@ namespace OpenSim.Region.Framework.Scenes
1275 1544
1276 public void SetOwnerId(UUID userId) 1545 public void SetOwnerId(UUID userId)
1277 { 1546 {
1278 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1547 ForEachPart(delegate(SceneObjectPart part)
1548 {
1549
1550 part.OwnerID = userId;
1551
1552 });
1279 } 1553 }
1280 1554
1281 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1555 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1307,11 +1581,17 @@ namespace OpenSim.Region.Framework.Scenes
1307 return; 1581 return;
1308 } 1582 }
1309 1583
1584 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1585 return;
1586
1310 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 1587 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1311 // any exception propogate upwards. 1588 // any exception propogate upwards.
1312 try 1589 try
1313 { 1590 {
1314 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 1591 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1592 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
1593 m_scene.LoadingPrims) // Land may not be valid yet
1594
1315 { 1595 {
1316 ILandObject parcel = m_scene.LandChannel.GetLandObject( 1596 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1317 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 1597 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1338,6 +1618,7 @@ namespace OpenSim.Region.Framework.Scenes
1338 } 1618 }
1339 } 1619 }
1340 } 1620 }
1621
1341 } 1622 }
1342 1623
1343 if (m_scene.UseBackup && HasGroupChanged) 1624 if (m_scene.UseBackup && HasGroupChanged)
@@ -1345,6 +1626,20 @@ namespace OpenSim.Region.Framework.Scenes
1345 // don't backup while it's selected or you're asking for changes mid stream. 1626 // don't backup while it's selected or you're asking for changes mid stream.
1346 if (isTimeToPersist() || forcedBackup) 1627 if (isTimeToPersist() || forcedBackup)
1347 { 1628 {
1629 if (m_rootPart.PhysActor != null &&
1630 (!m_rootPart.PhysActor.IsPhysical))
1631 {
1632 // Possible ghost prim
1633 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
1634 {
1635 foreach (SceneObjectPart part in m_parts.GetArray())
1636 {
1637 // Re-set physics actor positions and
1638 // orientations
1639 part.GroupPosition = m_rootPart.GroupPosition;
1640 }
1641 }
1642 }
1348// m_log.DebugFormat( 1643// m_log.DebugFormat(
1349// "[SCENE]: Storing {0}, {1} in {2}", 1644// "[SCENE]: Storing {0}, {1} in {2}",
1350// Name, UUID, m_scene.RegionInfo.RegionName); 1645// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1408,86 +1703,90 @@ namespace OpenSim.Region.Framework.Scenes
1408 /// <returns></returns> 1703 /// <returns></returns>
1409 public SceneObjectGroup Copy(bool userExposed) 1704 public SceneObjectGroup Copy(bool userExposed)
1410 { 1705 {
1411 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); 1706 SceneObjectGroup dupe;
1412 dupe.m_isBackedUp = false; 1707 try
1413 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); 1708 {
1414 1709 m_dupeInProgress = true;
1415 // Warning, The following code related to previousAttachmentStatus is needed so that clones of 1710 dupe = (SceneObjectGroup)MemberwiseClone();
1416 // attachments do not bordercross while they're being duplicated. This is hacktastic! 1711 dupe.m_isBackedUp = false;
1417 // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region! 1712 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
1418 // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state
1419 // (which should be false anyway) set it as an Attachment and then set it's Absolute Position,
1420 // then restore it's attachment state
1421
1422 // This is only necessary when userExposed is false!
1423 1713
1424 bool previousAttachmentStatus = dupe.RootPart.IsAttachment; 1714 // Warning, The following code related to previousAttachmentStatus is needed so that clones of
1425 1715 // attachments do not bordercross while they're being duplicated. This is hacktastic!
1426 if (!userExposed) 1716 // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region!
1427 dupe.RootPart.IsAttachment = true; 1717 // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state
1718 // (which should be false anyway) set it as an Attachment and then set it's Absolute Position,
1719 // then restore it's attachment state
1428 1720
1429 dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); 1721 // This is only necessary when userExposed is false!
1430 1722
1431 if (!userExposed) 1723 bool previousAttachmentStatus = dupe.RootPart.IsAttachment;
1432 {
1433 dupe.RootPart.IsAttachment = previousAttachmentStatus;
1434 }
1435 1724
1436 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); 1725 if (!userExposed)
1437 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; 1726 dupe.RootPart.IsAttachment = true;
1438 1727
1439 if (userExposed) 1728 dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z);
1440 dupe.m_rootPart.TrimPermissions();
1441 1729
1442 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 1730 if (!userExposed)
1443
1444 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1445 { 1731 {
1446 return p1.LinkNum.CompareTo(p2.LinkNum); 1732 dupe.RootPart.IsAttachment = previousAttachmentStatus;
1447 } 1733 }
1448 );
1449 1734
1450 foreach (SceneObjectPart part in partList) 1735 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed);
1451 { 1736 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum;
1452 SceneObjectPart newPart; 1737
1453 if (part.UUID != m_rootPart.UUID) 1738 if (userExposed)
1739 dupe.m_rootPart.TrimPermissions();
1740
1741 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1742
1743 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1744 {
1745 return p1.LinkNum.CompareTo(p2.LinkNum);
1746 }
1747 );
1748
1749 foreach (SceneObjectPart part in partList)
1454 { 1750 {
1455 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); 1751 if (part.UUID != m_rootPart.UUID)
1456 newPart.LinkNum = part.LinkNum; 1752 {
1753 SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
1754
1755 newPart.LinkNum = part.LinkNum;
1756 }
1757
1758 // Need to duplicate the physics actor as well
1759 if (part.PhysActor != null && userExposed)
1760 {
1761 PrimitiveBaseShape pbs = part.Shape;
1762
1763 part.PhysActor
1764 = m_scene.PhysicsScene.AddPrimShape(
1765 string.Format("{0}/{1}", part.Name, part.UUID),
1766 pbs,
1767 part.AbsolutePosition,
1768 part.Scale,
1769 part.RotationOffset,
1770 part.PhysActor.IsPhysical);
1771 part.PhysActor.SetMaterial((int)part.Material);
1772
1773 part.PhysActor.LocalID = part.LocalId;
1774 part.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1775 }
1457 } 1776 }
1458 else 1777 if (userExposed)
1459 { 1778 {
1460 newPart = dupe.m_rootPart; 1779 dupe.UpdateParentIDs();
1461 } 1780 dupe.HasGroupChanged = true;
1781 dupe.AttachToBackup();
1462 1782
1463 // Need to duplicate the physics actor as well 1783 ScheduleGroupForFullUpdate();
1464 if (part.PhysActor != null && userExposed)
1465 {
1466 PrimitiveBaseShape pbs = part.Shape;
1467
1468 newPart.PhysActor
1469 = m_scene.PhysicsScene.AddPrimShape(
1470 part.LocalId,
1471 string.Format("{0}/{1}", part.Name, part.UUID),
1472 pbs,
1473 part.AbsolutePosition,
1474 part.Scale,
1475 part.RotationOffset,
1476 part.PhysActor.IsPhysical);
1477
1478 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1479 } 1784 }
1480 } 1785 }
1481 1786 finally
1482 if (userExposed)
1483 { 1787 {
1484 dupe.UpdateParentIDs(); 1788 m_dupeInProgress = false;
1485 dupe.HasGroupChanged = true;
1486 dupe.AttachToBackup();
1487
1488 ScheduleGroupForFullUpdate();
1489 } 1789 }
1490
1491 return dupe; 1790 return dupe;
1492 } 1791 }
1493 1792
@@ -1632,6 +1931,7 @@ namespace OpenSim.Region.Framework.Scenes
1632 return Vector3.Zero; 1931 return Vector3.Zero;
1633 } 1932 }
1634 1933
1934 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object
1635 public void moveToTarget(Vector3 target, float tau) 1935 public void moveToTarget(Vector3 target, float tau)
1636 { 1936 {
1637 SceneObjectPart rootpart = m_rootPart; 1937 SceneObjectPart rootpart = m_rootPart;
@@ -1671,20 +1971,55 @@ namespace OpenSim.Region.Framework.Scenes
1671 SceneObjectPart rootpart = m_rootPart; 1971 SceneObjectPart rootpart = m_rootPart;
1672 if (rootpart != null) 1972 if (rootpart != null)
1673 { 1973 {
1674 if (rootpart.PhysActor != null) 1974 if (IsAttachment)
1675 { 1975 {
1676 rootpart.PhysActor.PIDActive = false; 1976 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1977 if (avatar != null) avatar.StopMoveToPosition();
1978 }
1979 else
1980 {
1981 if (rootpart.PhysActor != null)
1982 {
1983 rootpart.PhysActor.PIDActive = false;
1984 }
1677 } 1985 }
1678 } 1986 }
1679 } 1987 }
1680 1988
1989 public void rotLookAt(Quaternion target, float strength, float damping)
1990 {
1991 SceneObjectPart rootpart = m_rootPart;
1992 if (rootpart != null)
1993 {
1994 if (IsAttachment)
1995 {
1996 /*
1997 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1998 if (avatar != null)
1999 {
2000 Rotate the Av?
2001 } */
2002 }
2003 else
2004 {
2005 if (rootpart.PhysActor != null)
2006 { // APID must be implemented in your physics system for this to function.
2007 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2008 rootpart.PhysActor.APIDStrength = strength;
2009 rootpart.PhysActor.APIDDamping = damping;
2010 rootpart.PhysActor.APIDActive = true;
2011 }
2012 }
2013 }
2014 }
2015
1681 public void stopLookAt() 2016 public void stopLookAt()
1682 { 2017 {
1683 SceneObjectPart rootpart = m_rootPart; 2018 SceneObjectPart rootpart = m_rootPart;
1684 if (rootpart != null) 2019 if (rootpart != null)
1685 { 2020 {
1686 if (rootpart.PhysActor != null) 2021 if (rootpart.PhysActor != null)
1687 { 2022 { // APID must be implemented in your physics system for this to function.
1688 rootpart.PhysActor.APIDActive = false; 2023 rootpart.PhysActor.APIDActive = false;
1689 } 2024 }
1690 } 2025 }
@@ -1750,6 +2085,8 @@ namespace OpenSim.Region.Framework.Scenes
1750 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2085 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1751 { 2086 {
1752 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2087 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2088 newPart.SetParent(this);
2089
1753 AddPart(newPart); 2090 AddPart(newPart);
1754 2091
1755 SetPartAsNonRoot(newPart); 2092 SetPartAsNonRoot(newPart);
@@ -1898,11 +2235,11 @@ namespace OpenSim.Region.Framework.Scenes
1898 /// Immediately send a full update for this scene object. 2235 /// Immediately send a full update for this scene object.
1899 /// </summary> 2236 /// </summary>
1900 public void SendGroupFullUpdate() 2237 public void SendGroupFullUpdate()
1901 { 2238 {
1902 if (IsDeleted) 2239 if (IsDeleted)
1903 return; 2240 return;
1904 2241
1905// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2242// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
1906 2243
1907 RootPart.SendFullUpdateToAllClients(); 2244 RootPart.SendFullUpdateToAllClients();
1908 2245
@@ -2091,12 +2428,15 @@ namespace OpenSim.Region.Framework.Scenes
2091 part.LinkNum += objectGroup.PrimCount; 2428 part.LinkNum += objectGroup.PrimCount;
2092 } 2429 }
2093 } 2430 }
2431 }
2094 2432
2095 linkPart.LinkNum = 2; 2433 linkPart.LinkNum = 2;
2096 2434
2097 linkPart.SetParent(this); 2435 linkPart.SetParent(this);
2098 linkPart.CreateSelected = true; 2436 linkPart.CreateSelected = true;
2099 2437
2438 lock (m_parts.SyncRoot)
2439 {
2100 //if (linkPart.PhysActor != null) 2440 //if (linkPart.PhysActor != null)
2101 //{ 2441 //{
2102 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2442 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
@@ -2254,6 +2594,8 @@ namespace OpenSim.Region.Framework.Scenes
2254 /// <param name="objectGroup"></param> 2594 /// <param name="objectGroup"></param>
2255 public virtual void DetachFromBackup() 2595 public virtual void DetachFromBackup()
2256 { 2596 {
2597 m_scene.SceneGraph.FireDetachFromBackup(this);
2598
2257 if (m_isBackedUp) 2599 if (m_isBackedUp)
2258 m_scene.EventManager.OnBackup -= ProcessBackup; 2600 m_scene.EventManager.OnBackup -= ProcessBackup;
2259 2601
@@ -2272,7 +2614,8 @@ namespace OpenSim.Region.Framework.Scenes
2272 2614
2273 axPos *= parentRot; 2615 axPos *= parentRot;
2274 part.OffsetPosition = axPos; 2616 part.OffsetPosition = axPos;
2275 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 2617 Vector3 newPos = oldGroupPosition + part.OffsetPosition;
2618 part.GroupPosition = newPos;
2276 part.OffsetPosition = Vector3.Zero; 2619 part.OffsetPosition = Vector3.Zero;
2277 part.RotationOffset = worldRot; 2620 part.RotationOffset = worldRot;
2278 2621
@@ -2283,7 +2626,7 @@ namespace OpenSim.Region.Framework.Scenes
2283 2626
2284 part.LinkNum = linkNum; 2627 part.LinkNum = linkNum;
2285 2628
2286 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 2629 part.OffsetPosition = newPos - AbsolutePosition;
2287 2630
2288 Quaternion rootRotation = m_rootPart.RotationOffset; 2631 Quaternion rootRotation = m_rootPart.RotationOffset;
2289 2632
@@ -2293,7 +2636,7 @@ namespace OpenSim.Region.Framework.Scenes
2293 2636
2294 parentRot = m_rootPart.RotationOffset; 2637 parentRot = m_rootPart.RotationOffset;
2295 oldRot = part.RotationOffset; 2638 oldRot = part.RotationOffset;
2296 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 2639 Quaternion newRot = Quaternion.Inverse(parentRot) * worldRot;
2297 part.RotationOffset = newRot; 2640 part.RotationOffset = newRot;
2298 } 2641 }
2299 2642
@@ -2544,8 +2887,12 @@ namespace OpenSim.Region.Framework.Scenes
2544 } 2887 }
2545 } 2888 }
2546 2889
2890 RootPart.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2547 for (int i = 0; i < parts.Length; i++) 2891 for (int i = 0; i < parts.Length; i++)
2548 parts[i].UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2892 {
2893 if (parts[i] != RootPart)
2894 parts[i].UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2895 }
2549 } 2896 }
2550 } 2897 }
2551 2898
@@ -2558,6 +2905,17 @@ namespace OpenSim.Region.Framework.Scenes
2558 } 2905 }
2559 } 2906 }
2560 2907
2908
2909
2910 /// <summary>
2911 /// Gets the number of parts
2912 /// </summary>
2913 /// <returns></returns>
2914 public int GetPartCount()
2915 {
2916 return Parts.Count();
2917 }
2918
2561 /// <summary> 2919 /// <summary>
2562 /// Update the texture entry for this part 2920 /// Update the texture entry for this part
2563 /// </summary> 2921 /// </summary>
@@ -2619,11 +2977,9 @@ namespace OpenSim.Region.Framework.Scenes
2619 scale.Y = m_scene.m_maxNonphys; 2977 scale.Y = m_scene.m_maxNonphys;
2620 if (scale.Z > m_scene.m_maxNonphys) 2978 if (scale.Z > m_scene.m_maxNonphys)
2621 scale.Z = m_scene.m_maxNonphys; 2979 scale.Z = m_scene.m_maxNonphys;
2622
2623 SceneObjectPart part = GetChildPart(localID); 2980 SceneObjectPart part = GetChildPart(localID);
2624 if (part != null) 2981 if (part != null)
2625 { 2982 {
2626 part.Resize(scale);
2627 if (part.PhysActor != null) 2983 if (part.PhysActor != null)
2628 { 2984 {
2629 if (part.PhysActor.IsPhysical) 2985 if (part.PhysActor.IsPhysical)
@@ -2638,7 +2994,7 @@ namespace OpenSim.Region.Framework.Scenes
2638 part.PhysActor.Size = scale; 2994 part.PhysActor.Size = scale;
2639 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 2995 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2640 } 2996 }
2641 //if (part.UUID != m_rootPart.UUID) 2997 part.Resize(scale);
2642 2998
2643 HasGroupChanged = true; 2999 HasGroupChanged = true;
2644 part.TriggerScriptChangedEvent(Changed.SCALE); 3000 part.TriggerScriptChangedEvent(Changed.SCALE);
@@ -2661,7 +3017,6 @@ namespace OpenSim.Region.Framework.Scenes
2661 SceneObjectPart part = GetChildPart(localID); 3017 SceneObjectPart part = GetChildPart(localID);
2662 if (part != null) 3018 if (part != null)
2663 { 3019 {
2664 part.IgnoreUndoUpdate = true;
2665 if (scale.X > m_scene.m_maxNonphys) 3020 if (scale.X > m_scene.m_maxNonphys)
2666 scale.X = m_scene.m_maxNonphys; 3021 scale.X = m_scene.m_maxNonphys;
2667 if (scale.Y > m_scene.m_maxNonphys) 3022 if (scale.Y > m_scene.m_maxNonphys)
@@ -2698,7 +3053,7 @@ namespace OpenSim.Region.Framework.Scenes
2698 3053
2699 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3054 if (part.PhysActor != null && part.PhysActor.IsPhysical)
2700 { 3055 {
2701 if (oldSize.X * x > m_scene.m_maxPhys) 3056 if (oldSize.X*x > m_scene.m_maxPhys)
2702 { 3057 {
2703 f = m_scene.m_maxPhys / oldSize.X; 3058 f = m_scene.m_maxPhys / oldSize.X;
2704 a = f / x; 3059 a = f / x;
@@ -2706,7 +3061,7 @@ namespace OpenSim.Region.Framework.Scenes
2706 y *= a; 3061 y *= a;
2707 z *= a; 3062 z *= a;
2708 } 3063 }
2709 if (oldSize.Y * y > m_scene.m_maxPhys) 3064 if (oldSize.Y*y > m_scene.m_maxPhys)
2710 { 3065 {
2711 f = m_scene.m_maxPhys / oldSize.Y; 3066 f = m_scene.m_maxPhys / oldSize.Y;
2712 a = f / y; 3067 a = f / y;
@@ -2714,7 +3069,7 @@ namespace OpenSim.Region.Framework.Scenes
2714 y *= a; 3069 y *= a;
2715 z *= a; 3070 z *= a;
2716 } 3071 }
2717 if (oldSize.Z * z > m_scene.m_maxPhys) 3072 if (oldSize.Z*z > m_scene.m_maxPhys)
2718 { 3073 {
2719 f = m_scene.m_maxPhys / oldSize.Z; 3074 f = m_scene.m_maxPhys / oldSize.Z;
2720 a = f / z; 3075 a = f / z;
@@ -2725,7 +3080,7 @@ namespace OpenSim.Region.Framework.Scenes
2725 } 3080 }
2726 else 3081 else
2727 { 3082 {
2728 if (oldSize.X * x > m_scene.m_maxNonphys) 3083 if (oldSize.X*x > m_scene.m_maxNonphys)
2729 { 3084 {
2730 f = m_scene.m_maxNonphys / oldSize.X; 3085 f = m_scene.m_maxNonphys / oldSize.X;
2731 a = f / x; 3086 a = f / x;
@@ -2733,7 +3088,7 @@ namespace OpenSim.Region.Framework.Scenes
2733 y *= a; 3088 y *= a;
2734 z *= a; 3089 z *= a;
2735 } 3090 }
2736 if (oldSize.Y * y > m_scene.m_maxNonphys) 3091 if (oldSize.Y*y > m_scene.m_maxNonphys)
2737 { 3092 {
2738 f = m_scene.m_maxNonphys / oldSize.Y; 3093 f = m_scene.m_maxNonphys / oldSize.Y;
2739 a = f / y; 3094 a = f / y;
@@ -2741,7 +3096,7 @@ namespace OpenSim.Region.Framework.Scenes
2741 y *= a; 3096 y *= a;
2742 z *= a; 3097 z *= a;
2743 } 3098 }
2744 if (oldSize.Z * z > m_scene.m_maxNonphys) 3099 if (oldSize.Z*z > m_scene.m_maxNonphys)
2745 { 3100 {
2746 f = m_scene.m_maxNonphys / oldSize.Z; 3101 f = m_scene.m_maxNonphys / oldSize.Z;
2747 a = f / z; 3102 a = f / z;
@@ -2751,7 +3106,6 @@ namespace OpenSim.Region.Framework.Scenes
2751 } 3106 }
2752 } 3107 }
2753 obPart.IgnoreUndoUpdate = false; 3108 obPart.IgnoreUndoUpdate = false;
2754 obPart.StoreUndoState();
2755 } 3109 }
2756 } 3110 }
2757 } 3111 }
@@ -2759,8 +3113,13 @@ namespace OpenSim.Region.Framework.Scenes
2759 Vector3 prevScale = part.Scale; 3113 Vector3 prevScale = part.Scale;
2760 prevScale.X *= x; 3114 prevScale.X *= x;
2761 prevScale.Y *= y; 3115 prevScale.Y *= y;
2762 prevScale.Z *= z; 3116 prevScale.Z *= z;;
3117
3118 part.IgnoreUndoUpdate = false;
3119 part.StoreUndoState(UndoType.STATE_GROUP_SCALE);
3120 part.IgnoreUndoUpdate = true;
2763 part.Resize(prevScale); 3121 part.Resize(prevScale);
3122 part.IgnoreUndoUpdate = false;
2764 3123
2765 parts = m_parts.GetArray(); 3124 parts = m_parts.GetArray();
2766 for (int i = 0; i < parts.Length; i++) 3125 for (int i = 0; i < parts.Length; i++)
@@ -2769,19 +3128,26 @@ namespace OpenSim.Region.Framework.Scenes
2769 obPart.IgnoreUndoUpdate = true; 3128 obPart.IgnoreUndoUpdate = true;
2770 if (obPart.UUID != m_rootPart.UUID) 3129 if (obPart.UUID != m_rootPart.UUID)
2771 { 3130 {
2772 Vector3 currentpos = new Vector3(obPart.OffsetPosition); 3131 if (obPart.UUID != m_rootPart.UUID)
2773 currentpos.X *= x; 3132 {
2774 currentpos.Y *= y; 3133 obPart.IgnoreUndoUpdate = false;
2775 currentpos.Z *= z; 3134 obPart.StoreUndoState(UndoType.STATE_GROUP_SCALE);
2776 Vector3 newSize = new Vector3(obPart.Scale); 3135 obPart.IgnoreUndoUpdate = true;
2777 newSize.X *= x; 3136
2778 newSize.Y *= y; 3137 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
2779 newSize.Z *= z; 3138 currentpos.X *= x;
2780 obPart.Resize(newSize); 3139 currentpos.Y *= y;
2781 obPart.UpdateOffSet(currentpos); 3140 currentpos.Z *= z;
3141 Vector3 newSize = new Vector3(obPart.Scale);
3142 newSize.X *= x;
3143 newSize.Y *= y;
3144 newSize.Z *= z;
3145 obPart.Resize(newSize);
3146 obPart.UpdateOffSet(currentpos);
3147 }
3148 obPart.IgnoreUndoUpdate = false;
2782 } 3149 }
2783 obPart.IgnoreUndoUpdate = false; 3150 obPart.IgnoreUndoUpdate = false;
2784 obPart.StoreUndoState();
2785 } 3151 }
2786 3152
2787 if (part.PhysActor != null) 3153 if (part.PhysActor != null)
@@ -2791,7 +3157,6 @@ namespace OpenSim.Region.Framework.Scenes
2791 } 3157 }
2792 3158
2793 part.IgnoreUndoUpdate = false; 3159 part.IgnoreUndoUpdate = false;
2794 part.StoreUndoState();
2795 HasGroupChanged = true; 3160 HasGroupChanged = true;
2796 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE); 3161 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
2797 ScheduleGroupForTerseUpdate(); 3162 ScheduleGroupForTerseUpdate();
@@ -2808,14 +3173,11 @@ namespace OpenSim.Region.Framework.Scenes
2808 /// <param name="pos"></param> 3173 /// <param name="pos"></param>
2809 public void UpdateGroupPosition(Vector3 pos) 3174 public void UpdateGroupPosition(Vector3 pos)
2810 { 3175 {
2811 SceneObjectPart[] parts = m_parts.GetArray();
2812 for (int i = 0; i < parts.Length; i++)
2813 parts[i].StoreUndoState();
2814
2815 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 3176 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
2816 { 3177 {
2817 if (IsAttachment) 3178 if (IsAttachment)
2818 { 3179 {
3180 m_rootPart.StoreUndoState(UndoType.STATE_GROUP_POSITION);
2819 m_rootPart.AttachedPos = pos; 3181 m_rootPart.AttachedPos = pos;
2820 } 3182 }
2821 if (RootPart.GetStatusSandbox()) 3183 if (RootPart.GetStatusSandbox())
@@ -2849,7 +3211,7 @@ namespace OpenSim.Region.Framework.Scenes
2849 3211
2850 SceneObjectPart[] parts = m_parts.GetArray(); 3212 SceneObjectPart[] parts = m_parts.GetArray();
2851 for (int i = 0; i < parts.Length; i++) 3213 for (int i = 0; i < parts.Length; i++)
2852 parts[i].StoreUndoState(); 3214 parts[i].StoreUndoState(UndoType.STATE_PRIM_POSITION);
2853 3215
2854 if (part != null) 3216 if (part != null)
2855 { 3217 {
@@ -2874,7 +3236,7 @@ namespace OpenSim.Region.Framework.Scenes
2874 { 3236 {
2875 SceneObjectPart[] parts = m_parts.GetArray(); 3237 SceneObjectPart[] parts = m_parts.GetArray();
2876 for (int i = 0; i < parts.Length; i++) 3238 for (int i = 0; i < parts.Length; i++)
2877 parts[i].StoreUndoState(); 3239 parts[i].StoreUndoState(UndoType.STATE_PRIM_POSITION);
2878 3240
2879 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3241 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
2880 Vector3 oldPos = 3242 Vector3 oldPos =
@@ -2895,10 +3257,27 @@ namespace OpenSim.Region.Framework.Scenes
2895 obPart.OffsetPosition = obPart.OffsetPosition + diff; 3257 obPart.OffsetPosition = obPart.OffsetPosition + diff;
2896 } 3258 }
2897 3259
2898 AbsolutePosition = newPos; 3260 //We have to set undoing here because otherwise an undo state will be saved
3261 if (!m_rootPart.Undoing)
3262 {
3263 m_rootPart.Undoing = true;
3264 AbsolutePosition = newPos;
3265 m_rootPart.Undoing = false;
3266 }
3267 else
3268 {
3269 AbsolutePosition = newPos;
3270 }
2899 3271
2900 HasGroupChanged = true; 3272 HasGroupChanged = true;
2901 ScheduleGroupForTerseUpdate(); 3273 if (m_rootPart.Undoing)
3274 {
3275 ScheduleGroupForFullUpdate();
3276 }
3277 else
3278 {
3279 ScheduleGroupForTerseUpdate();
3280 }
2902 } 3281 }
2903 3282
2904 public void OffsetForNewRegion(Vector3 offset) 3283 public void OffsetForNewRegion(Vector3 offset)
@@ -2918,7 +3297,7 @@ namespace OpenSim.Region.Framework.Scenes
2918 { 3297 {
2919 SceneObjectPart[] parts = m_parts.GetArray(); 3298 SceneObjectPart[] parts = m_parts.GetArray();
2920 for (int i = 0; i < parts.Length; i++) 3299 for (int i = 0; i < parts.Length; i++)
2921 parts[i].StoreUndoState(); 3300 parts[i].StoreUndoState(UndoType.STATE_GROUP_ROTATION);
2922 3301
2923 m_rootPart.UpdateRotation(rot); 3302 m_rootPart.UpdateRotation(rot);
2924 3303
@@ -2942,7 +3321,7 @@ namespace OpenSim.Region.Framework.Scenes
2942 { 3321 {
2943 SceneObjectPart[] parts = m_parts.GetArray(); 3322 SceneObjectPart[] parts = m_parts.GetArray();
2944 for (int i = 0; i < parts.Length; i++) 3323 for (int i = 0; i < parts.Length; i++)
2945 parts[i].StoreUndoState(); 3324 parts[i].StoreUndoState(UndoType.STATE_GROUP_ROTATION);
2946 3325
2947 m_rootPart.UpdateRotation(rot); 3326 m_rootPart.UpdateRotation(rot);
2948 3327
@@ -2967,10 +3346,9 @@ namespace OpenSim.Region.Framework.Scenes
2967 public void UpdateSingleRotation(Quaternion rot, uint localID) 3346 public void UpdateSingleRotation(Quaternion rot, uint localID)
2968 { 3347 {
2969 SceneObjectPart part = GetChildPart(localID); 3348 SceneObjectPart part = GetChildPart(localID);
2970
2971 SceneObjectPart[] parts = m_parts.GetArray(); 3349 SceneObjectPart[] parts = m_parts.GetArray();
2972 for (int i = 0; i < parts.Length; i++) 3350 for (int i = 0; i < parts.Length; i++)
2973 parts[i].StoreUndoState(); 3351 parts[i].StoreUndoState(UndoType.STATE_PRIM_ROTATION);
2974 3352
2975 if (part != null) 3353 if (part != null)
2976 { 3354 {
@@ -2998,15 +3376,24 @@ namespace OpenSim.Region.Framework.Scenes
2998 if (part.UUID == m_rootPart.UUID) 3376 if (part.UUID == m_rootPart.UUID)
2999 { 3377 {
3000 UpdateRootRotation(rot); 3378 UpdateRootRotation(rot);
3001 AbsolutePosition = pos; 3379 if (!m_rootPart.Undoing)
3380 {
3381 m_rootPart.Undoing = true;
3382 AbsolutePosition = pos;
3383 m_rootPart.Undoing = false;
3384 }
3385 else
3386 {
3387 AbsolutePosition = pos;
3388 }
3002 } 3389 }
3003 else 3390 else
3004 { 3391 {
3392 part.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
3005 part.IgnoreUndoUpdate = true; 3393 part.IgnoreUndoUpdate = true;
3006 part.UpdateRotation(rot); 3394 part.UpdateRotation(rot);
3007 part.OffsetPosition = pos; 3395 part.OffsetPosition = pos;
3008 part.IgnoreUndoUpdate = false; 3396 part.IgnoreUndoUpdate = false;
3009 part.StoreUndoState();
3010 } 3397 }
3011 } 3398 }
3012 } 3399 }
@@ -3020,8 +3407,16 @@ namespace OpenSim.Region.Framework.Scenes
3020 Quaternion axRot = rot; 3407 Quaternion axRot = rot;
3021 Quaternion oldParentRot = m_rootPart.RotationOffset; 3408 Quaternion oldParentRot = m_rootPart.RotationOffset;
3022 3409
3023 m_rootPart.StoreUndoState(); 3410 m_rootPart.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
3024 m_rootPart.UpdateRotation(rot); 3411 bool cancelUndo = false;
3412 if (!m_rootPart.Undoing)
3413 {
3414 m_rootPart.Undoing = true;
3415 cancelUndo = true;
3416 }
3417
3418 //Don't use UpdateRotation because it schedules an update prematurely
3419 m_rootPart.RotationOffset = rot;
3025 if (m_rootPart.PhysActor != null) 3420 if (m_rootPart.PhysActor != null)
3026 { 3421 {
3027 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset; 3422 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset;
@@ -3036,28 +3431,22 @@ namespace OpenSim.Region.Framework.Scenes
3036 { 3431 {
3037 prim.IgnoreUndoUpdate = true; 3432 prim.IgnoreUndoUpdate = true;
3038 Vector3 axPos = prim.OffsetPosition; 3433 Vector3 axPos = prim.OffsetPosition;
3434
3039 axPos *= oldParentRot; 3435 axPos *= oldParentRot;
3040 axPos *= Quaternion.Inverse(axRot); 3436 axPos *= Quaternion.Inverse(axRot);
3041 prim.OffsetPosition = axPos; 3437 prim.OffsetPosition = axPos;
3042 Quaternion primsRot = prim.RotationOffset; 3438
3043 Quaternion newRot = primsRot * oldParentRot; 3439 prim.RotationOffset *= Quaternion.Inverse(prim.GetWorldRotation()) * (oldParentRot * prim.RotationOffset);
3044 newRot *= Quaternion.Inverse(axRot); 3440
3045 prim.RotationOffset = newRot; 3441 prim.IgnoreUndoUpdate = false;
3046 prim.ScheduleTerseUpdate();
3047 } 3442 }
3048 } 3443 }
3049 3444 if (cancelUndo == true)
3050 for (int i = 0; i < parts.Length; i++)
3051 { 3445 {
3052 SceneObjectPart childpart = parts[i]; 3446 m_rootPart.Undoing = false;
3053 if (childpart != m_rootPart)
3054 {
3055 childpart.IgnoreUndoUpdate = false;
3056 childpart.StoreUndoState();
3057 }
3058 } 3447 }
3059 3448 HasGroupChanged = true;
3060 m_rootPart.ScheduleTerseUpdate(); 3449 ScheduleGroupForFullUpdate();
3061 } 3450 }
3062 3451
3063 #endregion 3452 #endregion
@@ -3280,7 +3669,6 @@ namespace OpenSim.Region.Framework.Scenes
3280 public float GetMass() 3669 public float GetMass()
3281 { 3670 {
3282 float retmass = 0f; 3671 float retmass = 0f;
3283
3284 SceneObjectPart[] parts = m_parts.GetArray(); 3672 SceneObjectPart[] parts = m_parts.GetArray();
3285 for (int i = 0; i < parts.Length; i++) 3673 for (int i = 0; i < parts.Length; i++)
3286 retmass += parts[i].GetMass(); 3674 retmass += parts[i].GetMass();
@@ -3396,6 +3784,14 @@ namespace OpenSim.Region.Framework.Scenes
3396 SetFromItemID(uuid); 3784 SetFromItemID(uuid);
3397 } 3785 }
3398 3786
3787 public void ResetOwnerChangeFlag()
3788 {
3789 ForEachPart(delegate(SceneObjectPart part)
3790 {
3791 part.ResetOwnerChangeFlag();
3792 });
3793 }
3794
3399 #endregion 3795 #endregion
3400 } 3796 }
3401} 3797}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index c6d8c73..e3744bd 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -61,7 +61,8 @@ namespace OpenSim.Region.Framework.Scenes
61 TELEPORT = 512, 61 TELEPORT = 512,
62 REGION_RESTART = 1024, 62 REGION_RESTART = 1024,
63 MEDIA = 2048, 63 MEDIA = 2048,
64 ANIMATION = 16384 64 ANIMATION = 16384,
65 POSITION = 32768
65 } 66 }
66 67
67 // I don't really know where to put this except here. 68 // I don't really know where to put this except here.
@@ -189,7 +190,15 @@ namespace OpenSim.Region.Framework.Scenes
189 190
190 public UUID FromFolderID; 191 public UUID FromFolderID;
191 192
192 193 // The following two are to hold the attachment data
194 // while an object is inworld
195 [XmlIgnore]
196 public byte AttachPoint = 0;
197
198 [XmlIgnore]
199 public Vector3 AttachOffset = Vector3.Zero;
200
201 [XmlIgnore]
193 public int STATUS_ROTATE_X; 202 public int STATUS_ROTATE_X;
194 203
195 204
@@ -284,6 +293,7 @@ namespace OpenSim.Region.Framework.Scenes
284 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 293 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
285 private Vector3 m_sitTargetPosition; 294 private Vector3 m_sitTargetPosition;
286 private string m_sitAnimation = "SIT"; 295 private string m_sitAnimation = "SIT";
296 private bool m_occupied; // KF if any av is sitting on this prim
287 private string m_text = String.Empty; 297 private string m_text = String.Empty;
288 private string m_touchName = String.Empty; 298 private string m_touchName = String.Empty;
289 private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5); 299 private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5);
@@ -328,6 +338,7 @@ namespace OpenSim.Region.Framework.Scenes
328 protected Vector3 m_lastAcceleration; 338 protected Vector3 m_lastAcceleration;
329 protected Vector3 m_lastAngularVelocity; 339 protected Vector3 m_lastAngularVelocity;
330 protected int m_lastTerseSent; 340 protected int m_lastTerseSent;
341 protected float m_buoyancy = 0.0f;
331 342
332 /// <summary> 343 /// <summary>
333 /// Stores media texture data 344 /// Stores media texture data
@@ -380,7 +391,7 @@ namespace OpenSim.Region.Framework.Scenes
380 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 391 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
381 Quaternion rotationOffset, Vector3 offsetPosition) 392 Quaternion rotationOffset, Vector3 offsetPosition)
382 { 393 {
383 m_name = "Primitive"; 394 m_name = "Object";
384 395
385 Rezzed = DateTime.UtcNow; 396 Rezzed = DateTime.UtcNow;
386 _creationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 397 _creationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
@@ -436,7 +447,7 @@ namespace OpenSim.Region.Framework.Scenes
436 private uint _ownerMask = (uint)PermissionMask.All; 447 private uint _ownerMask = (uint)PermissionMask.All;
437 private uint _groupMask = (uint)PermissionMask.None; 448 private uint _groupMask = (uint)PermissionMask.None;
438 private uint _everyoneMask = (uint)PermissionMask.None; 449 private uint _everyoneMask = (uint)PermissionMask.None;
439 private uint _nextOwnerMask = (uint)PermissionMask.All; 450 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
440 private PrimFlags _flags = PrimFlags.None; 451 private PrimFlags _flags = PrimFlags.None;
441 private DateTime m_expires; 452 private DateTime m_expires;
442 private DateTime m_rezzed; 453 private DateTime m_rezzed;
@@ -535,12 +546,16 @@ namespace OpenSim.Region.Framework.Scenes
535 } 546 }
536 547
537 /// <value> 548 /// <value>
538 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 549 /// Get the inventory list
539 /// </value> 550 /// </value>
540 public TaskInventoryDictionary TaskInventory 551 public TaskInventoryDictionary TaskInventory
541 { 552 {
542 get { return m_inventory.Items; } 553 get {
543 set { m_inventory.Items = value; } 554 return m_inventory.Items;
555 }
556 set {
557 m_inventory.Items = value;
558 }
544 } 559 }
545 560
546 /// <summary> 561 /// <summary>
@@ -680,14 +695,12 @@ namespace OpenSim.Region.Framework.Scenes
680 set { m_LoopSoundSlavePrims = value; } 695 set { m_LoopSoundSlavePrims = value; }
681 } 696 }
682 697
683
684 public Byte[] TextureAnimation 698 public Byte[] TextureAnimation
685 { 699 {
686 get { return m_TextureAnimation; } 700 get { return m_TextureAnimation; }
687 set { m_TextureAnimation = value; } 701 set { m_TextureAnimation = value; }
688 } 702 }
689 703
690
691 public Byte[] ParticleSystem 704 public Byte[] ParticleSystem
692 { 705 {
693 get { return m_particleSystem; } 706 get { return m_particleSystem; }
@@ -724,9 +737,11 @@ namespace OpenSim.Region.Framework.Scenes
724 { 737 {
725 // If this is a linkset, we don't want the physics engine mucking up our group position here. 738 // If this is a linkset, we don't want the physics engine mucking up our group position here.
726 PhysicsActor actor = PhysActor; 739 PhysicsActor actor = PhysActor;
727 if (actor != null && _parentID == 0) 740 if (_parentID == 0)
728 { 741 {
729 m_groupPosition = actor.Position; 742 if (actor != null)
743 m_groupPosition = actor.Position;
744 return m_groupPosition;
730 } 745 }
731 746
732 if (IsAttachment) 747 if (IsAttachment)
@@ -736,12 +751,14 @@ namespace OpenSim.Region.Framework.Scenes
736 return sp.AbsolutePosition; 751 return sp.AbsolutePosition;
737 } 752 }
738 753
754 // use root prim's group position. Physics may have updated it
755 if (ParentGroup.RootPart != this)
756 m_groupPosition = ParentGroup.RootPart.GroupPosition;
739 return m_groupPosition; 757 return m_groupPosition;
740 } 758 }
741 set 759 set
742 { 760 {
743 m_groupPosition = value; 761 m_groupPosition = value;
744
745 PhysicsActor actor = PhysActor; 762 PhysicsActor actor = PhysActor;
746 if (actor != null) 763 if (actor != null)
747 { 764 {
@@ -761,25 +778,13 @@ namespace OpenSim.Region.Framework.Scenes
761 778
762 // Tell the physics engines that this prim changed. 779 // Tell the physics engines that this prim changed.
763 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 780 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
781
764 } 782 }
765 catch (Exception e) 783 catch (Exception e)
766 { 784 {
767 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); 785 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message);
768 } 786 }
769 } 787 }
770
771 // TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too
772 if (m_sitTargetAvatar != UUID.Zero)
773 {
774 if (m_parentGroup != null) // TODO can there be a SOP without a SOG?
775 {
776 ScenePresence avatar;
777 if (m_parentGroup.Scene.TryGetScenePresence(m_sitTargetAvatar, out avatar))
778 {
779 avatar.ParentPosition = GetWorldPosition();
780 }
781 }
782 }
783 } 788 }
784 } 789 }
785 790
@@ -788,7 +793,8 @@ namespace OpenSim.Region.Framework.Scenes
788 get { return m_offsetPosition; } 793 get { return m_offsetPosition; }
789 set 794 set
790 { 795 {
791 StoreUndoState(); 796 Vector3 oldpos = m_offsetPosition;
797 StoreUndoState(UndoType.STATE_PRIM_POSITION);
792 m_offsetPosition = value; 798 m_offsetPosition = value;
793 799
794 if (ParentGroup != null && !ParentGroup.IsDeleted) 800 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -802,7 +808,22 @@ namespace OpenSim.Region.Framework.Scenes
802 // Tell the physics engines that this prim changed. 808 // Tell the physics engines that this prim changed.
803 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 809 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
804 } 810 }
811
812 if (!m_parentGroup.m_dupeInProgress)
813 {
814 List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
815 foreach (ScenePresence av in avs)
816 {
817 if (av.LinkedPrim == m_uuid)
818 {
819 Vector3 offset = (m_offsetPosition - oldpos);
820 av.OffsetPosition += offset;
821 av.SendAvatarDataToAllAgents();
822 }
823 }
824 }
805 } 825 }
826 TriggerScriptChangedEvent(Changed.POSITION);
806 } 827 }
807 } 828 }
808 829
@@ -844,7 +865,7 @@ namespace OpenSim.Region.Framework.Scenes
844 865
845 set 866 set
846 { 867 {
847 StoreUndoState(); 868 StoreUndoState(UndoType.STATE_PRIM_ROTATION);
848 m_rotationOffset = value; 869 m_rotationOffset = value;
849 870
850 PhysicsActor actor = PhysActor; 871 PhysicsActor actor = PhysActor;
@@ -928,7 +949,16 @@ namespace OpenSim.Region.Framework.Scenes
928 /// <summary></summary> 949 /// <summary></summary>
929 public Vector3 Acceleration 950 public Vector3 Acceleration
930 { 951 {
931 get { return m_acceleration; } 952 get
953 {
954 PhysicsActor actor = PhysActor;
955 if (actor != null)
956 {
957 m_acceleration = actor.Acceleration;
958 }
959 return m_acceleration;
960 }
961
932 set { m_acceleration = value; } 962 set { m_acceleration = value; }
933 } 963 }
934 964
@@ -1019,7 +1049,7 @@ namespace OpenSim.Region.Framework.Scenes
1019 get { return m_shape.Scale; } 1049 get { return m_shape.Scale; }
1020 set 1050 set
1021 { 1051 {
1022 StoreUndoState(); 1052 StoreUndoState(UndoType.STATE_PRIM_SCALE);
1023 if (m_shape != null) 1053 if (m_shape != null)
1024 { 1054 {
1025 m_shape.Scale = value; 1055 m_shape.Scale = value;
@@ -1085,11 +1115,10 @@ namespace OpenSim.Region.Framework.Scenes
1085 1115
1086 public Vector3 AbsolutePosition 1116 public Vector3 AbsolutePosition
1087 { 1117 {
1088 get { 1118 get
1089 if (IsAttachment) 1119 {
1090 return GroupPosition; 1120 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1091 1121 }
1092 return m_offsetPosition + m_groupPosition; }
1093 } 1122 }
1094 1123
1095 public SceneObjectGroup ParentGroup 1124 public SceneObjectGroup ParentGroup
@@ -1248,6 +1277,13 @@ namespace OpenSim.Region.Framework.Scenes
1248 _flags = value; 1277 _flags = value;
1249 } 1278 }
1250 } 1279 }
1280
1281 [XmlIgnore]
1282 public bool IsOccupied // KF If an av is sittingon this prim
1283 {
1284 get { return m_occupied; }
1285 set { m_occupied = value; }
1286 }
1251 1287
1252 1288
1253 public UUID SitTargetAvatar 1289 public UUID SitTargetAvatar
@@ -1307,6 +1343,19 @@ namespace OpenSim.Region.Framework.Scenes
1307 set { m_collisionSoundVolume = value; } 1343 set { m_collisionSoundVolume = value; }
1308 } 1344 }
1309 1345
1346 public float Buoyancy
1347 {
1348 get { return m_buoyancy; }
1349 set
1350 {
1351 m_buoyancy = value;
1352 if (PhysActor != null)
1353 {
1354 PhysActor.Buoyancy = value;
1355 }
1356 }
1357 }
1358
1310 #endregion Public Properties with only Get 1359 #endregion Public Properties with only Get
1311 1360
1312 #region Private Methods 1361 #region Private Methods
@@ -1323,14 +1372,6 @@ namespace OpenSim.Region.Framework.Scenes
1323 } 1372 }
1324 } 1373 }
1325 1374
1326 /// <summary>
1327 /// Clear all pending updates of parts to clients
1328 /// </summary>
1329 private void ClearUpdateSchedule()
1330 {
1331 m_updateFlag = 0;
1332 }
1333
1334 private void SendObjectPropertiesToClient(UUID AgentID) 1375 private void SendObjectPropertiesToClient(UUID AgentID)
1335 { 1376 {
1336 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1377 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
@@ -1581,15 +1622,22 @@ namespace OpenSim.Region.Framework.Scenes
1581 // or flexible 1622 // or flexible
1582 if (!isPhantom && !IsAttachment && !(Shape.PathCurve == (byte) Extrusion.Flexible)) 1623 if (!isPhantom && !IsAttachment && !(Shape.PathCurve == (byte) Extrusion.Flexible))
1583 { 1624 {
1584 PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( 1625 try
1585 LocalId, 1626 {
1586 string.Format("{0}/{1}", Name, UUID), 1627 PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape(
1587 Shape, 1628 string.Format("{0}/{1}", Name, UUID),
1588 AbsolutePosition, 1629 Shape,
1589 Scale, 1630 AbsolutePosition,
1590 RotationOffset, 1631 Scale,
1591 RigidBody); 1632 RotationOffset,
1592 1633 RigidBody);
1634 PhysActor.SetMaterial(Material);
1635 }
1636 catch
1637 {
1638 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom.", m_uuid);
1639 PhysActor = null;
1640 }
1593 // Basic Physics returns null.. joy joy joy. 1641 // Basic Physics returns null.. joy joy joy.
1594 if (PhysActor != null) 1642 if (PhysActor != null)
1595 { 1643 {
@@ -1616,7 +1664,7 @@ namespace OpenSim.Region.Framework.Scenes
1616 { 1664 {
1617 m_redo.Clear(); 1665 m_redo.Clear();
1618 } 1666 }
1619 StoreUndoState(); 1667 StoreUndoState(UndoType.STATE_ALL);
1620 } 1668 }
1621 1669
1622 public byte ConvertScriptUintToByte(uint indata) 1670 public byte ConvertScriptUintToByte(uint indata)
@@ -1685,6 +1733,9 @@ namespace OpenSim.Region.Framework.Scenes
1685 1733
1686 // Move afterwards ResetIDs as it clears the localID 1734 // Move afterwards ResetIDs as it clears the localID
1687 dupe.LocalId = localID; 1735 dupe.LocalId = localID;
1736 if(dupe.PhysActor != null)
1737 dupe.PhysActor.LocalID = localID;
1738
1688 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 1739 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1689 dupe._lastOwnerID = OwnerID; 1740 dupe._lastOwnerID = OwnerID;
1690 1741
@@ -1728,7 +1779,7 @@ namespace OpenSim.Region.Framework.Scenes
1728 PrimitiveBaseShape shape = PrimitiveBaseShape.Create(); 1779 PrimitiveBaseShape shape = PrimitiveBaseShape.Create();
1729 part.Shape = shape; 1780 part.Shape = shape;
1730 1781
1731 part.Name = "Primitive"; 1782 part.Name = "Object";
1732 part._ownerID = UUID.Random(); 1783 part._ownerID = UUID.Random();
1733 1784
1734 return part; 1785 return part;
@@ -2081,19 +2132,17 @@ namespace OpenSim.Region.Framework.Scenes
2081 public Vector3 GetWorldPosition() 2132 public Vector3 GetWorldPosition()
2082 { 2133 {
2083 Quaternion parentRot = ParentGroup.RootPart.RotationOffset; 2134 Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
2084
2085 Vector3 axPos = OffsetPosition; 2135 Vector3 axPos = OffsetPosition;
2086
2087 axPos *= parentRot; 2136 axPos *= parentRot;
2088 Vector3 translationOffsetPosition = axPos; 2137 Vector3 translationOffsetPosition = axPos;
2089 2138 if(_parentID == 0)
2090// m_log.DebugFormat("[SCENE OBJECT PART]: Found group pos {0} for part {1}", GroupPosition, Name); 2139 {
2091 2140 return GroupPosition;
2092 Vector3 worldPos = GroupPosition + translationOffsetPosition; 2141 }
2093 2142 else
2094// m_log.DebugFormat("[SCENE OBJECT PART]: Found world pos {0} for part {1}", worldPos, Name); 2143 {
2095 2144 return ParentGroup.AbsolutePosition + translationOffsetPosition; //KF: Fix child prim position
2096 return worldPos; 2145 }
2097 } 2146 }
2098 2147
2099 /// <summary> 2148 /// <summary>
@@ -2750,17 +2799,18 @@ namespace OpenSim.Region.Framework.Scenes
2750 //Trys to fetch sound id from prim's inventory. 2799 //Trys to fetch sound id from prim's inventory.
2751 //Prim's inventory doesn't support non script items yet 2800 //Prim's inventory doesn't support non script items yet
2752 2801
2753 lock (TaskInventory) 2802 TaskInventory.LockItemsForRead(true);
2803
2804 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2754 { 2805 {
2755 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2806 if (item.Value.Name == sound)
2756 { 2807 {
2757 if (item.Value.Name == sound) 2808 soundID = item.Value.ItemID;
2758 { 2809 break;
2759 soundID = item.Value.ItemID;
2760 break;
2761 }
2762 } 2810 }
2763 } 2811 }
2812
2813 TaskInventory.LockItemsForRead(false);
2764 } 2814 }
2765 2815
2766 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp) 2816 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp)
@@ -2820,7 +2870,7 @@ namespace OpenSim.Region.Framework.Scenes
2820 /// <param name="scale"></param> 2870 /// <param name="scale"></param>
2821 public void Resize(Vector3 scale) 2871 public void Resize(Vector3 scale)
2822 { 2872 {
2823 StoreUndoState(); 2873 StoreUndoState(UndoType.STATE_PRIM_SCALE);
2824 m_shape.Scale = scale; 2874 m_shape.Scale = scale;
2825 2875
2826 ParentGroup.HasGroupChanged = true; 2876 ParentGroup.HasGroupChanged = true;
@@ -2829,38 +2879,7 @@ namespace OpenSim.Region.Framework.Scenes
2829 2879
2830 public void RotLookAt(Quaternion target, float strength, float damping) 2880 public void RotLookAt(Quaternion target, float strength, float damping)
2831 { 2881 {
2832 rotLookAt(target, strength, damping); 2882 m_parentGroup.rotLookAt(target, strength, damping); // This calls method in SceneObjectGroup.
2833 }
2834
2835 public void rotLookAt(Quaternion target, float strength, float damping)
2836 {
2837 if (IsAttachment)
2838 {
2839 /*
2840 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2841 if (avatar != null)
2842 {
2843 Rotate the Av?
2844 } */
2845 }
2846 else
2847 {
2848 APIDDamp = damping;
2849 APIDStrength = strength;
2850 APIDTarget = target;
2851 }
2852 }
2853
2854 public void startLookAt(Quaternion rot, float damp, float strength)
2855 {
2856 APIDDamp = damp;
2857 APIDStrength = strength;
2858 APIDTarget = rot;
2859 }
2860
2861 public void stopLookAt()
2862 {
2863 APIDTarget = Quaternion.Identity;
2864 } 2883 }
2865 2884
2866 /// <summary> 2885 /// <summary>
@@ -2872,7 +2891,10 @@ namespace OpenSim.Region.Framework.Scenes
2872 2891
2873 if (m_parentGroup != null) 2892 if (m_parentGroup != null)
2874 { 2893 {
2875 m_parentGroup.QueueForUpdateCheck(); 2894 if (!m_parentGroup.areUpdatesSuspended)
2895 {
2896 m_parentGroup.QueueForUpdateCheck();
2897 }
2876 } 2898 }
2877 2899
2878 int timeNow = Util.UnixTimeSinceEpoch(); 2900 int timeNow = Util.UnixTimeSinceEpoch();
@@ -3089,8 +3111,8 @@ namespace OpenSim.Region.Framework.Scenes
3089 { 3111 {
3090 const float ROTATION_TOLERANCE = 0.01f; 3112 const float ROTATION_TOLERANCE = 0.01f;
3091 const float VELOCITY_TOLERANCE = 0.001f; 3113 const float VELOCITY_TOLERANCE = 0.001f;
3092 const float POSITION_TOLERANCE = 0.05f; 3114 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
3093 const int TIME_MS_TOLERANCE = 3000; 3115 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
3094 3116
3095 if (m_updateFlag == 1) 3117 if (m_updateFlag == 1)
3096 { 3118 {
@@ -3104,7 +3126,7 @@ namespace OpenSim.Region.Framework.Scenes
3104 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 3126 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
3105 { 3127 {
3106 AddTerseUpdateToAllAvatars(); 3128 AddTerseUpdateToAllAvatars();
3107 ClearUpdateSchedule(); 3129
3108 3130
3109 // This causes the Scene to 'poll' physical objects every couple of frames 3131 // This causes the Scene to 'poll' physical objects every couple of frames
3110 // bad, so it's been replaced by an event driven method. 3132 // bad, so it's been replaced by an event driven method.
@@ -3122,16 +3144,18 @@ namespace OpenSim.Region.Framework.Scenes
3122 m_lastAngularVelocity = AngularVelocity; 3144 m_lastAngularVelocity = AngularVelocity;
3123 m_lastTerseSent = Environment.TickCount; 3145 m_lastTerseSent = Environment.TickCount;
3124 } 3146 }
3147 //Moved this outside of the if clause so updates don't get blocked.. *sigh*
3148 m_updateFlag = 0; //Why were we calling a function to do this? Inefficient! *screams*
3125 } 3149 }
3126 else 3150 else
3127 { 3151 {
3128 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes 3152 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes
3129 { 3153 {
3130 AddFullUpdateToAllAvatars(); 3154 AddFullUpdateToAllAvatars();
3131 ClearUpdateSchedule(); 3155 m_updateFlag = 0; //Same here
3132 } 3156 }
3133 } 3157 }
3134 ClearUpdateSchedule(); 3158 m_updateFlag = 0;
3135 } 3159 }
3136 3160
3137 /// <summary> 3161 /// <summary>
@@ -3159,17 +3183,16 @@ namespace OpenSim.Region.Framework.Scenes
3159 if (!UUID.TryParse(sound, out soundID)) 3183 if (!UUID.TryParse(sound, out soundID))
3160 { 3184 {
3161 // search sound file from inventory 3185 // search sound file from inventory
3162 lock (TaskInventory) 3186 TaskInventory.LockItemsForRead(true);
3187 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
3163 { 3188 {
3164 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3189 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
3165 { 3190 {
3166 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3191 soundID = item.Value.ItemID;
3167 { 3192 break;
3168 soundID = item.Value.ItemID;
3169 break;
3170 }
3171 } 3193 }
3172 } 3194 }
3195 TaskInventory.LockItemsForRead(false);
3173 } 3196 }
3174 3197
3175 if (soundID == UUID.Zero) 3198 if (soundID == UUID.Zero)
@@ -3272,14 +3295,6 @@ namespace OpenSim.Region.Framework.Scenes
3272 STATUS_ROTATE_Z = rotate; 3295 STATUS_ROTATE_Z = rotate;
3273 } 3296 }
3274 3297
3275 public void SetBuoyancy(float fvalue)
3276 {
3277 if (PhysActor != null)
3278 {
3279 PhysActor.Buoyancy = fvalue;
3280 }
3281 }
3282
3283 public void SetDieAtEdge(bool p) 3298 public void SetDieAtEdge(bool p)
3284 { 3299 {
3285 if (m_parentGroup == null) 3300 if (m_parentGroup == null)
@@ -3599,7 +3614,7 @@ namespace OpenSim.Region.Framework.Scenes
3599 3614
3600 public void StopLookAt() 3615 public void StopLookAt()
3601 { 3616 {
3602 m_parentGroup.stopLookAt(); 3617 m_parentGroup.stopLookAt(); // This calls method in SceneObjectGroup.
3603 3618
3604 m_parentGroup.ScheduleGroupForTerseUpdate(); 3619 m_parentGroup.ScheduleGroupForTerseUpdate();
3605 } 3620 }
@@ -3626,10 +3641,9 @@ namespace OpenSim.Region.Framework.Scenes
3626 m_parentGroup.ScheduleGroupForTerseUpdate(); 3641 m_parentGroup.ScheduleGroupForTerseUpdate();
3627 //m_parentGroup.ScheduleGroupForFullUpdate(); 3642 //m_parentGroup.ScheduleGroupForFullUpdate();
3628 } 3643 }
3629 3644 public void StoreUndoState(UndoType type)
3630 public void StoreUndoState()
3631 { 3645 {
3632 if (!Undoing) 3646 if (!Undoing && (m_parentGroup == null || m_parentGroup.RootPart == null || !m_parentGroup.RootPart.Undoing))
3633 { 3647 {
3634 if (!IgnoreUndoUpdate) 3648 if (!IgnoreUndoUpdate)
3635 { 3649 {
@@ -3640,17 +3654,25 @@ namespace OpenSim.Region.Framework.Scenes
3640 if (m_undo.Count > 0) 3654 if (m_undo.Count > 0)
3641 { 3655 {
3642 UndoState last = m_undo.Peek(); 3656 UndoState last = m_undo.Peek();
3643 if (last != null) 3657
3644 {
3645 if (last.Compare(this))
3646 return;
3647 }
3648 } 3658 }
3649 3659
3650 if (m_parentGroup.GetSceneMaxUndo() > 0) 3660 if (m_parentGroup.GetSceneMaxUndo() > 0)
3651 { 3661 {
3652 UndoState nUndo = new UndoState(this); 3662 UndoState lastUndo = m_undo.Peek();
3663
3664 UndoState nUndo = new UndoState(this, type);
3653 3665
3666 if (lastUndo != null)
3667 {
3668 TimeSpan ts = DateTime.Now.Subtract(lastUndo.LastUpdated);
3669 if (ts.TotalMilliseconds < 500)
3670 {
3671 //Delete the last entry since it was less than 500 milliseconds ago
3672 nUndo.Merge(lastUndo);
3673 m_undo.Pop();
3674 }
3675 }
3654 m_undo.Push(nUndo); 3676 m_undo.Push(nUndo);
3655 } 3677 }
3656 3678
@@ -4127,11 +4149,13 @@ namespace OpenSim.Region.Framework.Scenes
4127 if (m_undo.Count > 0) 4149 if (m_undo.Count > 0)
4128 { 4150 {
4129 UndoState nUndo = null; 4151 UndoState nUndo = null;
4152 UndoState goback = m_undo.Pop();
4130 if (m_parentGroup.GetSceneMaxUndo() > 0) 4153 if (m_parentGroup.GetSceneMaxUndo() > 0)
4131 { 4154 {
4132 nUndo = new UndoState(this); 4155 nUndo = new UndoState(this, goback.Type);
4133 } 4156 }
4134 UndoState goback = m_undo.Pop(); 4157
4158
4135 if (goback != null) 4159 if (goback != null)
4136 { 4160 {
4137 goback.PlaybackState(this); 4161 goback.PlaybackState(this);
@@ -4146,13 +4170,13 @@ namespace OpenSim.Region.Framework.Scenes
4146 { 4170 {
4147 lock (m_redo) 4171 lock (m_redo)
4148 { 4172 {
4173 UndoState gofwd = m_redo.Pop();
4149 if (m_parentGroup.GetSceneMaxUndo() > 0) 4174 if (m_parentGroup.GetSceneMaxUndo() > 0)
4150 { 4175 {
4151 UndoState nUndo = new UndoState(this); 4176 UndoState nUndo = new UndoState(this, gofwd.Type);
4152 4177
4153 m_undo.Push(nUndo); 4178 m_undo.Push(nUndo);
4154 } 4179 }
4155 UndoState gofwd = m_redo.Pop();
4156 if (gofwd != null) 4180 if (gofwd != null)
4157 gofwd.PlayfwdState(this); 4181 gofwd.PlayfwdState(this);
4158 } 4182 }
@@ -4417,6 +4441,7 @@ namespace OpenSim.Region.Framework.Scenes
4417 Scale, 4441 Scale,
4418 RotationOffset, 4442 RotationOffset,
4419 UsePhysics); 4443 UsePhysics);
4444 PhysActor.SetMaterial(Material);
4420 4445
4421 pa = PhysActor; 4446 pa = PhysActor;
4422 if (pa != null) 4447 if (pa != null)
@@ -4601,8 +4626,9 @@ namespace OpenSim.Region.Framework.Scenes
4601 { 4626 {
4602 m_shape.TextureEntry = textureEntry; 4627 m_shape.TextureEntry = textureEntry;
4603 TriggerScriptChangedEvent(Changed.TEXTURE); 4628 TriggerScriptChangedEvent(Changed.TEXTURE);
4604 4629 m_updateFlag = 1;
4605 ParentGroup.HasGroupChanged = true; 4630 ParentGroup.HasGroupChanged = true;
4631
4606 //This is madness.. 4632 //This is madness..
4607 //ParentGroup.ScheduleGroupForFullUpdate(); 4633 //ParentGroup.ScheduleGroupForFullUpdate();
4608 //This is sparta 4634 //This is sparta
@@ -4835,5 +4861,17 @@ namespace OpenSim.Region.Framework.Scenes
4835 Color color = Color; 4861 Color color = Color;
4836 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 4862 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4837 } 4863 }
4864
4865 public void ResetOwnerChangeFlag()
4866 {
4867 List<UUID> inv = Inventory.GetInventoryList();
4868
4869 foreach (UUID itemID in inv)
4870 {
4871 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
4872 item.OwnerChanged = false;
4873 Inventory.UpdateInventoryItem(item, false, false);
4874 }
4875 }
4838 } 4876 }
4839} 4877}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 3b60f8c..56680df 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -48,6 +48,9 @@ namespace OpenSim.Region.Framework.Scenes
48 private string m_inventoryFileName = String.Empty; 48 private string m_inventoryFileName = String.Empty;
49 private byte[] m_inventoryFileData = new byte[0]; 49 private byte[] m_inventoryFileData = new byte[0];
50 private uint m_inventoryFileNameSerial = 0; 50 private uint m_inventoryFileNameSerial = 0;
51 private bool m_inventoryPrivileged = false;
52
53 private Dictionary<UUID, ArrayList> m_scriptErrors = new Dictionary<UUID, ArrayList>();
51 54
52 /// <value> 55 /// <value>
53 /// The part to which the inventory belongs. 56 /// The part to which the inventory belongs.
@@ -84,11 +87,14 @@ namespace OpenSim.Region.Framework.Scenes
84 /// </value> 87 /// </value>
85 protected internal TaskInventoryDictionary Items 88 protected internal TaskInventoryDictionary Items
86 { 89 {
87 get { return m_items; } 90 get {
91 return m_items;
92 }
88 set 93 set
89 { 94 {
90 m_items = value; 95 m_items = value;
91 m_inventorySerial++; 96 m_inventorySerial++;
97 QueryScriptStates();
92 } 98 }
93 } 99 }
94 100
@@ -120,39 +126,45 @@ namespace OpenSim.Region.Framework.Scenes
120 /// <param name="linkNum">Link number for the part</param> 126 /// <param name="linkNum">Link number for the part</param>
121 public void ResetInventoryIDs() 127 public void ResetInventoryIDs()
122 { 128 {
123 if (null == m_part || null == m_part.ParentGroup) 129 m_items.LockItemsForWrite(true);
124 return; 130
125 131 if (Items.Count == 0)
126 lock (m_items)
127 { 132 {
128 if (0 == m_items.Count) 133 m_items.LockItemsForWrite(false);
129 return; 134 return;
135 }
130 136
131 IList<TaskInventoryItem> items = GetInventoryItems(); 137 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
132 m_items.Clear(); 138 Items.Clear();
133 139
134 foreach (TaskInventoryItem item in items) 140 foreach (TaskInventoryItem item in items)
135 { 141 {
136 item.ResetIDs(m_part.UUID); 142 item.ResetIDs(m_part.UUID);
137 m_items.Add(item.ItemID, item); 143 Items.Add(item.ItemID, item);
138 }
139 } 144 }
145 m_items.LockItemsForWrite(false);
140 } 146 }
141 147
142 public void ResetObjectID() 148 public void ResetObjectID()
143 { 149 {
144 lock (Items) 150 m_items.LockItemsForWrite(true);
151
152 if (Items.Count == 0)
145 { 153 {
146 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 154 m_items.LockItemsForWrite(false);
147 Items.Clear(); 155 return;
148 156 }
149 foreach (TaskInventoryItem item in items) 157
150 { 158 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
151 item.ParentPartID = m_part.UUID; 159 Items.Clear();
152 item.ParentID = m_part.UUID; 160
153 Items.Add(item.ItemID, item); 161 foreach (TaskInventoryItem item in items)
154 } 162 {
163 item.ParentPartID = m_part.UUID;
164 item.ParentID = m_part.UUID;
165 Items.Add(item.ItemID, item);
155 } 166 }
167 m_items.LockItemsForWrite(false);
156 } 168 }
157 169
158 /// <summary> 170 /// <summary>
@@ -161,12 +173,11 @@ namespace OpenSim.Region.Framework.Scenes
161 /// <param name="ownerId"></param> 173 /// <param name="ownerId"></param>
162 public void ChangeInventoryOwner(UUID ownerId) 174 public void ChangeInventoryOwner(UUID ownerId)
163 { 175 {
164 lock (Items) 176 m_items.LockItemsForWrite(true);
177 if (0 == Items.Count)
165 { 178 {
166 if (0 == Items.Count) 179 m_items.LockItemsForWrite(false);
167 { 180 return;
168 return;
169 }
170 } 181 }
171 182
172 HasInventoryChanged = true; 183 HasInventoryChanged = true;
@@ -182,6 +193,7 @@ namespace OpenSim.Region.Framework.Scenes
182 item.PermsGranter = UUID.Zero; 193 item.PermsGranter = UUID.Zero;
183 item.OwnerChanged = true; 194 item.OwnerChanged = true;
184 } 195 }
196 m_items.LockItemsForWrite(false);
185 } 197 }
186 198
187 /// <summary> 199 /// <summary>
@@ -190,12 +202,11 @@ namespace OpenSim.Region.Framework.Scenes
190 /// <param name="groupID"></param> 202 /// <param name="groupID"></param>
191 public void ChangeInventoryGroup(UUID groupID) 203 public void ChangeInventoryGroup(UUID groupID)
192 { 204 {
193 lock (Items) 205 m_items.LockItemsForWrite(true);
206 if (0 == Items.Count)
194 { 207 {
195 if (0 == Items.Count) 208 m_items.LockItemsForWrite(false);
196 { 209 return;
197 return;
198 }
199 } 210 }
200 211
201 // Don't let this set the HasGroupChanged flag for attachments 212 // Don't let this set the HasGroupChanged flag for attachments
@@ -207,12 +218,45 @@ namespace OpenSim.Region.Framework.Scenes
207 m_part.ParentGroup.HasGroupChanged = true; 218 m_part.ParentGroup.HasGroupChanged = true;
208 } 219 }
209 220
210 List<TaskInventoryItem> items = GetInventoryItems(); 221 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
211 foreach (TaskInventoryItem item in items) 222 foreach (TaskInventoryItem item in items)
212 { 223 {
213 if (groupID != item.GroupID) 224 if (groupID != item.GroupID)
225 {
214 item.GroupID = groupID; 226 item.GroupID = groupID;
227 }
215 } 228 }
229 m_items.LockItemsForWrite(false);
230 }
231
232 private void QueryScriptStates()
233 {
234 if (m_part == null || m_part.ParentGroup == null)
235 return;
236
237 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
238 if (engines == null) // No engine at all
239 return;
240
241 Items.LockItemsForRead(true);
242 foreach (TaskInventoryItem item in Items.Values)
243 {
244 if (item.InvType == (int)InventoryType.LSL)
245 {
246 foreach (IScriptModule e in engines)
247 {
248 bool running;
249
250 if (e.HasScript(item.ItemID, out running))
251 {
252 item.ScriptRunning = running;
253 break;
254 }
255 }
256 }
257 }
258
259 Items.LockItemsForRead(false);
216 } 260 }
217 261
218 /// <summary> 262 /// <summary>
@@ -220,9 +264,14 @@ namespace OpenSim.Region.Framework.Scenes
220 /// </summary> 264 /// </summary>
221 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) 265 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
222 { 266 {
223 List<TaskInventoryItem> scripts = GetInventoryScripts(); 267 Items.LockItemsForRead(true);
224 foreach (TaskInventoryItem item in scripts) 268 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
225 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 269 Items.LockItemsForRead(false);
270 foreach (TaskInventoryItem item in items)
271 {
272 if ((int)InventoryType.LSL == item.InvType)
273 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
274 }
226 } 275 }
227 276
228 public ArrayList GetScriptErrors(UUID itemID) 277 public ArrayList GetScriptErrors(UUID itemID)
@@ -255,9 +304,18 @@ namespace OpenSim.Region.Framework.Scenes
255 /// </param> 304 /// </param>
256 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 305 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
257 { 306 {
258 List<TaskInventoryItem> scripts = GetInventoryScripts(); 307 Items.LockItemsForRead(true);
259 foreach (TaskInventoryItem item in scripts) 308 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
260 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted); 309 Items.LockItemsForRead(false);
310
311 foreach (TaskInventoryItem item in items)
312 {
313 if ((int)InventoryType.LSL == item.InvType)
314 {
315 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
316 m_part.RemoveScriptEvents(item.ItemID);
317 }
318 }
261 } 319 }
262 320
263 /// <summary> 321 /// <summary>
@@ -273,7 +331,10 @@ namespace OpenSim.Region.Framework.Scenes
273 // item.Name, item.ItemID, Name, UUID); 331 // item.Name, item.ItemID, Name, UUID);
274 332
275 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) 333 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID))
334 {
335 StoreScriptError(item.ItemID, "no permission");
276 return; 336 return;
337 }
277 338
278 m_part.AddFlag(PrimFlags.Scripted); 339 m_part.AddFlag(PrimFlags.Scripted);
279 340
@@ -282,14 +343,13 @@ namespace OpenSim.Region.Framework.Scenes
282 if (stateSource == 2 && // Prim crossing 343 if (stateSource == 2 && // Prim crossing
283 m_part.ParentGroup.Scene.m_trustBinaries) 344 m_part.ParentGroup.Scene.m_trustBinaries)
284 { 345 {
285 lock (m_items) 346 m_items.LockItemsForWrite(true);
286 { 347 m_items[item.ItemID].PermsMask = 0;
287 m_items[item.ItemID].PermsMask = 0; 348 m_items[item.ItemID].PermsGranter = UUID.Zero;
288 m_items[item.ItemID].PermsGranter = UUID.Zero; 349 m_items.LockItemsForWrite(false);
289 }
290
291 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 350 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
292 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 351 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
352 StoreScriptErrors(item.ItemID, null);
293 m_part.ParentGroup.AddActiveScriptCount(1); 353 m_part.ParentGroup.AddActiveScriptCount(1);
294 m_part.ScheduleFullUpdate(); 354 m_part.ScheduleFullUpdate();
295 return; 355 return;
@@ -298,6 +358,8 @@ namespace OpenSim.Region.Framework.Scenes
298 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 358 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
299 if (null == asset) 359 if (null == asset)
300 { 360 {
361 string msg = String.Format("asset ID {0} could not be found", item.AssetID);
362 StoreScriptError(item.ItemID, msg);
301 m_log.ErrorFormat( 363 m_log.ErrorFormat(
302 "[PRIM INVENTORY]: " + 364 "[PRIM INVENTORY]: " +
303 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", 365 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
@@ -309,15 +371,20 @@ namespace OpenSim.Region.Framework.Scenes
309 if (m_part.ParentGroup.m_savedScriptState != null) 371 if (m_part.ParentGroup.m_savedScriptState != null)
310 RestoreSavedScriptState(item.OldItemID, item.ItemID); 372 RestoreSavedScriptState(item.OldItemID, item.ItemID);
311 373
312 lock (m_items) 374 m_items.LockItemsForWrite(true);
313 { 375
314 m_items[item.ItemID].PermsMask = 0; 376 m_items[item.ItemID].PermsMask = 0;
315 m_items[item.ItemID].PermsGranter = UUID.Zero; 377 m_items[item.ItemID].PermsGranter = UUID.Zero;
316 } 378
379 m_items.LockItemsForWrite(false);
317 380
318 string script = Utils.BytesToString(asset.Data); 381 string script = Utils.BytesToString(asset.Data);
319 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 382 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
320 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 383 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
384 StoreScriptErrors(item.ItemID, null);
385 if (!item.ScriptRunning)
386 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(
387 m_part.LocalId, item.ItemID);
321 m_part.ParentGroup.AddActiveScriptCount(1); 388 m_part.ParentGroup.AddActiveScriptCount(1);
322 m_part.ScheduleFullUpdate(); 389 m_part.ScheduleFullUpdate();
323 } 390 }
@@ -381,21 +448,145 @@ namespace OpenSim.Region.Framework.Scenes
381 448
382 /// <summary> 449 /// <summary>
383 /// Start a script which is in this prim's inventory. 450 /// Start a script which is in this prim's inventory.
451 /// Some processing may occur in the background, but this routine returns asap.
384 /// </summary> 452 /// </summary>
385 /// <param name="itemId"> 453 /// <param name="itemId">
386 /// A <see cref="UUID"/> 454 /// A <see cref="UUID"/>
387 /// </param> 455 /// </param>
388 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 456 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
389 { 457 {
390 TaskInventoryItem item = GetInventoryItem(itemId); 458 lock (m_scriptErrors)
391 if (item != null) 459 {
392 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 460 // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion
461 m_scriptErrors.Remove(itemId);
462 }
463 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
464 }
465
466 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
467 {
468 m_items.LockItemsForRead(true);
469 if (m_items.ContainsKey(itemId))
470 {
471 if (m_items.ContainsKey(itemId))
472 {
473 m_items.LockItemsForRead(false);
474 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource);
475 }
476 else
477 {
478 m_items.LockItemsForRead(false);
479 string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID,
480 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
481 StoreScriptError(itemId, msg);
482 m_log.ErrorFormat(
483 "[PRIM INVENTORY]: " +
484 "Couldn't start script with ID {0} since it {1}", itemId, msg);
485 }
486 }
393 else 487 else
488 {
489 m_items.LockItemsForRead(false);
490 string msg = String.Format("couldn't be found for prim {0}, {1}", m_part.Name, m_part.UUID);
491 StoreScriptError(itemId, msg);
394 m_log.ErrorFormat( 492 m_log.ErrorFormat(
395 "[PRIM INVENTORY]: " + 493 "[PRIM INVENTORY]: " +
396 "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 494 "Couldn't start script with ID {0} since it {1}", itemId, msg);
397 itemId, m_part.Name, m_part.UUID, 495 }
398 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 496
497 }
498
499 /// <summary>
500 /// Start a script which is in this prim's inventory and return any compilation error messages.
501 /// </summary>
502 /// <param name="itemId">
503 /// A <see cref="UUID"/>
504 /// </param>
505 public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
506 {
507 ArrayList errors;
508
509 // Indicate to CreateScriptInstanceInternal() we want it to
510 // post any compilation/loading error messages
511 lock (m_scriptErrors)
512 {
513 m_scriptErrors[itemId] = null;
514 }
515
516 // Perform compilation/loading
517 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
518
519 // Wait for and retrieve any errors
520 lock (m_scriptErrors)
521 {
522 while ((errors = m_scriptErrors[itemId]) == null)
523 {
524 if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000))
525 {
526 m_log.ErrorFormat(
527 "[PRIM INVENTORY]: " +
528 "timedout waiting for script {0} errors", itemId);
529 errors = m_scriptErrors[itemId];
530 if (errors == null)
531 {
532 errors = new ArrayList(1);
533 errors.Add("timedout waiting for errors");
534 }
535 break;
536 }
537 }
538 m_scriptErrors.Remove(itemId);
539 }
540 return errors;
541 }
542
543 // Signal to CreateScriptInstanceEr() that compilation/loading is complete
544 private void StoreScriptErrors(UUID itemId, ArrayList errors)
545 {
546 lock (m_scriptErrors)
547 {
548 // If compilation/loading initiated via CreateScriptInstance(),
549 // it does not want the errors, so just get out
550 if (!m_scriptErrors.ContainsKey(itemId))
551 {
552 return;
553 }
554
555 // Initiated via CreateScriptInstanceEr(), if we know what the
556 // errors are, save them and wake CreateScriptInstanceEr().
557 if (errors != null)
558 {
559 m_scriptErrors[itemId] = errors;
560 System.Threading.Monitor.PulseAll(m_scriptErrors);
561 return;
562 }
563 }
564
565 // Initiated via CreateScriptInstanceEr() but we don't know what
566 // the errors are yet, so retrieve them from the script engine.
567 // This may involve some waiting internal to GetScriptErrors().
568 errors = GetScriptErrors(itemId);
569
570 // Get a default non-null value to indicate success.
571 if (errors == null)
572 {
573 errors = new ArrayList();
574 }
575
576 // Post to CreateScriptInstanceEr() and wake it up
577 lock (m_scriptErrors)
578 {
579 m_scriptErrors[itemId] = errors;
580 System.Threading.Monitor.PulseAll(m_scriptErrors);
581 }
582 }
583
584 // Like StoreScriptErrors(), but just posts a single string message
585 private void StoreScriptError(UUID itemId, string message)
586 {
587 ArrayList errors = new ArrayList(1);
588 errors.Add(message);
589 StoreScriptErrors(itemId, errors);
399 } 590 }
400 591
401 /// <summary> 592 /// <summary>
@@ -408,15 +599,7 @@ namespace OpenSim.Region.Framework.Scenes
408 /// </param> 599 /// </param>
409 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted) 600 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
410 { 601 {
411 bool scriptPresent = false; 602 if (m_items.ContainsKey(itemId))
412
413 lock (m_items)
414 {
415 if (m_items.ContainsKey(itemId))
416 scriptPresent = true;
417 }
418
419 if (scriptPresent)
420 { 603 {
421 if (!sceneObjectBeingDeleted) 604 if (!sceneObjectBeingDeleted)
422 m_part.RemoveScriptEvents(itemId); 605 m_part.RemoveScriptEvents(itemId);
@@ -441,14 +624,16 @@ namespace OpenSim.Region.Framework.Scenes
441 /// <returns></returns> 624 /// <returns></returns>
442 private bool InventoryContainsName(string name) 625 private bool InventoryContainsName(string name)
443 { 626 {
444 lock (m_items) 627 m_items.LockItemsForRead(true);
628 foreach (TaskInventoryItem item in m_items.Values)
445 { 629 {
446 foreach (TaskInventoryItem item in m_items.Values) 630 if (item.Name == name)
447 { 631 {
448 if (item.Name == name) 632 m_items.LockItemsForRead(false);
449 return true; 633 return true;
450 } 634 }
451 } 635 }
636 m_items.LockItemsForRead(false);
452 return false; 637 return false;
453 } 638 }
454 639
@@ -490,8 +675,9 @@ namespace OpenSim.Region.Framework.Scenes
490 /// <param name="item"></param> 675 /// <param name="item"></param>
491 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 676 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
492 { 677 {
493 List<TaskInventoryItem> il = GetInventoryItems(); 678 m_items.LockItemsForRead(true);
494 679 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
680 m_items.LockItemsForRead(false);
495 foreach (TaskInventoryItem i in il) 681 foreach (TaskInventoryItem i in il)
496 { 682 {
497 if (i.Name == item.Name) 683 if (i.Name == item.Name)
@@ -529,14 +715,14 @@ namespace OpenSim.Region.Framework.Scenes
529 item.Name = name; 715 item.Name = name;
530 item.GroupID = m_part.GroupID; 716 item.GroupID = m_part.GroupID;
531 717
532 lock (m_items) 718 m_items.LockItemsForWrite(true);
533 m_items.Add(item.ItemID, item); 719 m_items.Add(item.ItemID, item);
534 720 m_items.LockItemsForWrite(false);
535 if (allowedDrop) 721 if (allowedDrop)
536 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 722 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
537 else 723 else
538 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 724 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
539 725
540 m_inventorySerial++; 726 m_inventorySerial++;
541 //m_inventorySerial += 2; 727 //m_inventorySerial += 2;
542 HasInventoryChanged = true; 728 HasInventoryChanged = true;
@@ -552,15 +738,15 @@ namespace OpenSim.Region.Framework.Scenes
552 /// <param name="items"></param> 738 /// <param name="items"></param>
553 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 739 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
554 { 740 {
555 lock (m_items) 741 m_items.LockItemsForWrite(true);
742 foreach (TaskInventoryItem item in items)
556 { 743 {
557 foreach (TaskInventoryItem item in items) 744 m_items.Add(item.ItemID, item);
558 { 745// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
559 m_items.Add(item.ItemID, item);
560// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
561 }
562 m_inventorySerial++;
563 } 746 }
747 m_items.LockItemsForWrite(false);
748
749 m_inventorySerial++;
564 } 750 }
565 751
566 /// <summary> 752 /// <summary>
@@ -571,10 +757,9 @@ namespace OpenSim.Region.Framework.Scenes
571 public TaskInventoryItem GetInventoryItem(UUID itemId) 757 public TaskInventoryItem GetInventoryItem(UUID itemId)
572 { 758 {
573 TaskInventoryItem item; 759 TaskInventoryItem item;
574 760 m_items.LockItemsForRead(true);
575 lock (m_items) 761 m_items.TryGetValue(itemId, out item);
576 m_items.TryGetValue(itemId, out item); 762 m_items.LockItemsForRead(false);
577
578 return item; 763 return item;
579 } 764 }
580 765
@@ -590,15 +775,16 @@ namespace OpenSim.Region.Framework.Scenes
590 { 775 {
591 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(); 776 IList<TaskInventoryItem> items = new List<TaskInventoryItem>();
592 777
593 lock (m_items) 778 m_items.LockItemsForRead(true);
779
780 foreach (TaskInventoryItem item in m_items.Values)
594 { 781 {
595 foreach (TaskInventoryItem item in m_items.Values) 782 if (item.Name == name)
596 { 783 items.Add(item);
597 if (item.Name == name)
598 items.Add(item);
599 }
600 } 784 }
601 785
786 m_items.LockItemsForRead(false);
787
602 return items; 788 return items;
603 } 789 }
604 790
@@ -617,6 +803,9 @@ namespace OpenSim.Region.Framework.Scenes
617 string xmlData = Utils.BytesToString(rezAsset.Data); 803 string xmlData = Utils.BytesToString(rezAsset.Data);
618 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 804 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
619 805
806 group.RootPart.AttachPoint = group.RootPart.Shape.State;
807 group.RootPart.AttachOffset = group.AbsolutePosition;
808
620 group.ResetIDs(); 809 group.ResetIDs();
621 810
622 SceneObjectPart rootPart = group.GetChildPart(group.UUID); 811 SceneObjectPart rootPart = group.GetChildPart(group.UUID);
@@ -691,8 +880,9 @@ namespace OpenSim.Region.Framework.Scenes
691 880
692 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged) 881 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
693 { 882 {
694 TaskInventoryItem it = GetInventoryItem(item.ItemID); 883 m_items.LockItemsForWrite(true);
695 if (it != null) 884
885 if (m_items.ContainsKey(item.ItemID))
696 { 886 {
697// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name); 887// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name);
698 888
@@ -705,14 +895,10 @@ namespace OpenSim.Region.Framework.Scenes
705 item.GroupID = m_part.GroupID; 895 item.GroupID = m_part.GroupID;
706 896
707 if (item.AssetID == UUID.Zero) 897 if (item.AssetID == UUID.Zero)
708 item.AssetID = it.AssetID; 898 item.AssetID = m_items[item.ItemID].AssetID;
709 899
710 lock (m_items) 900 m_items[item.ItemID] = item;
711 { 901 m_inventorySerial++;
712 m_items[item.ItemID] = item;
713 m_inventorySerial++;
714 }
715
716 if (fireScriptEvents) 902 if (fireScriptEvents)
717 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 903 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
718 904
@@ -721,7 +907,7 @@ namespace OpenSim.Region.Framework.Scenes
721 HasInventoryChanged = true; 907 HasInventoryChanged = true;
722 m_part.ParentGroup.HasGroupChanged = true; 908 m_part.ParentGroup.HasGroupChanged = true;
723 } 909 }
724 910 m_items.LockItemsForWrite(false);
725 return true; 911 return true;
726 } 912 }
727 else 913 else
@@ -732,8 +918,9 @@ namespace OpenSim.Region.Framework.Scenes
732 item.ItemID, m_part.Name, m_part.UUID, 918 item.ItemID, m_part.Name, m_part.UUID,
733 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 919 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
734 } 920 }
735 return false; 921 m_items.LockItemsForWrite(false);
736 922
923 return false;
737 } 924 }
738 925
739 /// <summary> 926 /// <summary>
@@ -744,107 +931,68 @@ namespace OpenSim.Region.Framework.Scenes
744 /// in this prim's inventory.</returns> 931 /// in this prim's inventory.</returns>
745 public int RemoveInventoryItem(UUID itemID) 932 public int RemoveInventoryItem(UUID itemID)
746 { 933 {
747 TaskInventoryItem item = GetInventoryItem(itemID); 934 m_items.LockItemsForRead(true);
748 if (item != null) 935
936 if (m_items.ContainsKey(itemID))
749 { 937 {
750 int type = m_items[itemID].InvType; 938 int type = m_items[itemID].InvType;
939 m_items.LockItemsForRead(false);
751 if (type == 10) // Script 940 if (type == 10) // Script
752 { 941 {
753 m_part.RemoveScriptEvents(itemID);
754 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 942 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
755 } 943 }
944 m_items.LockItemsForWrite(true);
756 m_items.Remove(itemID); 945 m_items.Remove(itemID);
946 m_items.LockItemsForWrite(false);
757 m_inventorySerial++; 947 m_inventorySerial++;
758 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 948 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
759 949
760 HasInventoryChanged = true; 950 HasInventoryChanged = true;
761 m_part.ParentGroup.HasGroupChanged = true; 951 m_part.ParentGroup.HasGroupChanged = true;
762 952
763 if (!ContainsScripts()) 953 int scriptcount = 0;
954 m_items.LockItemsForRead(true);
955 foreach (TaskInventoryItem item in m_items.Values)
956 {
957 if (item.Type == 10)
958 {
959 scriptcount++;
960 }
961 }
962 m_items.LockItemsForRead(false);
963
964
965 if (scriptcount <= 0)
966 {
764 m_part.RemFlag(PrimFlags.Scripted); 967 m_part.RemFlag(PrimFlags.Scripted);
968 }
765 969
766 m_part.ScheduleFullUpdate(); 970 m_part.ScheduleFullUpdate();
767 971
768 return type; 972 return type;
769
770 } 973 }
771 else 974 else
772 { 975 {
976 m_items.LockItemsForRead(false);
773 m_log.ErrorFormat( 977 m_log.ErrorFormat(
774 "[PRIM INVENTORY]: " + 978 "[PRIM INVENTORY]: " +
775 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", 979 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
776 itemID, m_part.Name, m_part.UUID, 980 itemID, m_part.Name, m_part.UUID);
777 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
778 } 981 }
779 982
780 return -1; 983 return -1;
781 } 984 }
782 985
783 private bool CreateInventoryFile() 986 private bool CreateInventoryFileName()
784 { 987 {
785 if (m_inventoryFileName == String.Empty || 988 if (m_inventoryFileName == String.Empty ||
786 m_inventoryFileNameSerial < m_inventorySerial) 989 m_inventoryFileNameSerial < m_inventorySerial)
787 { 990 {
788 // Something changed, we need to create a new file
789 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp"; 991 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp";
790 m_inventoryFileNameSerial = m_inventorySerial; 992 m_inventoryFileNameSerial = m_inventorySerial;
791
792 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
793
794 lock (m_items)
795 {
796 foreach (TaskInventoryItem item in m_items.Values)
797 {
798 UUID ownerID = item.OwnerID;
799 uint everyoneMask = 0;
800 uint baseMask = item.BasePermissions;
801 uint ownerMask = item.CurrentPermissions;
802 uint groupMask = item.GroupPermissions;
803
804 invString.AddItemStart();
805 invString.AddNameValueLine("item_id", item.ItemID.ToString());
806 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
807
808 invString.AddPermissionsStart();
809
810 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
811 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
812 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
813 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
814 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
815
816 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
817 invString.AddNameValueLine("owner_id", ownerID.ToString());
818
819 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
820
821 invString.AddNameValueLine("group_id", item.GroupID.ToString());
822 invString.AddSectionEnd();
823
824 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
825 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]);
826 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]);
827 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
828
829 invString.AddSaleStart();
830 invString.AddNameValueLine("sale_type", "not");
831 invString.AddNameValueLine("sale_price", "0");
832 invString.AddSectionEnd();
833
834 invString.AddNameValueLine("name", item.Name + "|");
835 invString.AddNameValueLine("desc", item.Description + "|");
836
837 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
838 invString.AddSectionEnd();
839 }
840 }
841
842 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
843
844 return true; 993 return true;
845 } 994 }
846 995
847 // No need to recreate, the existing file is fine
848 return false; 996 return false;
849 } 997 }
850 998
@@ -854,26 +1002,99 @@ namespace OpenSim.Region.Framework.Scenes
854 /// <param name="xferManager"></param> 1002 /// <param name="xferManager"></param>
855 public void RequestInventoryFile(IClientAPI client, IXfer xferManager) 1003 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
856 { 1004 {
857 CreateInventoryFile(); 1005 bool changed = CreateInventoryFileName();
1006
1007 bool includeAssets = false;
1008 if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId))
1009 includeAssets = true;
1010
1011 if (m_inventoryPrivileged != includeAssets)
1012 changed = true;
1013
1014 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
1015
1016 Items.LockItemsForRead(true);
858 1017
859 if (m_inventorySerial == 0) // No inventory 1018 if (m_inventorySerial == 0) // No inventory
860 { 1019 {
861 client.SendTaskInventory(m_part.UUID, 0, new byte[0]); 1020 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1021 Items.LockItemsForRead(false);
862 return; 1022 return;
863 } 1023 }
864 1024
865 // In principle, we should only do the rest if the inventory changed; 1025 if (!changed)
866 // by sending m_inventorySerial to the client, it ought to know 1026 {
867 // that nothing changed and that it doesn't need to request the file. 1027 if (m_inventoryFileData.Length > 2)
868 // Unfortunately, it doesn't look like the client optimizes this; 1028 {
869 // the client seems to always come back and request the Xfer, 1029 xferManager.AddNewFile(m_inventoryFileName,
870 // no matter what value m_inventorySerial has. 1030 m_inventoryFileData);
1031 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
1032 Util.StringToBytes256(m_inventoryFileName));
1033
1034 Items.LockItemsForRead(false);
1035 return;
1036 }
1037 }
1038
1039 m_inventoryPrivileged = includeAssets;
1040
1041 foreach (TaskInventoryItem item in m_items.Values)
1042 {
1043 UUID ownerID = item.OwnerID;
1044 uint everyoneMask = 0;
1045 uint baseMask = item.BasePermissions;
1046 uint ownerMask = item.CurrentPermissions;
1047 uint groupMask = item.GroupPermissions;
1048
1049 invString.AddItemStart();
1050 invString.AddNameValueLine("item_id", item.ItemID.ToString());
1051 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
1052
1053 invString.AddPermissionsStart();
1054
1055 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
1056 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
1057 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
1058 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
1059 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
1060
1061 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
1062 invString.AddNameValueLine("owner_id", ownerID.ToString());
1063
1064 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
1065
1066 invString.AddNameValueLine("group_id", item.GroupID.ToString());
1067 invString.AddSectionEnd();
1068
1069 if (includeAssets)
1070 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
1071 else
1072 invString.AddNameValueLine("asset_id", UUID.Zero.ToString());
1073 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]);
1074 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]);
1075 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
1076
1077 invString.AddSaleStart();
1078 invString.AddNameValueLine("sale_type", "not");
1079 invString.AddNameValueLine("sale_price", "0");
1080 invString.AddSectionEnd();
1081
1082 invString.AddNameValueLine("name", item.Name + "|");
1083 invString.AddNameValueLine("desc", item.Description + "|");
1084
1085 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
1086 invString.AddSectionEnd();
1087 }
1088
1089 Items.LockItemsForRead(false);
1090
1091 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
871 1092
872 if (m_inventoryFileData.Length > 2) 1093 if (m_inventoryFileData.Length > 2)
873 // Add the file for Xfer 1094 {
874 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData); 1095 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
1096 }
875 1097
876 // Tell the client we're ready to Xfer the file
877 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial, 1098 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
878 Util.StringToBytes256(m_inventoryFileName)); 1099 Util.StringToBytes256(m_inventoryFileName));
879 } 1100 }
@@ -886,10 +1107,11 @@ namespace OpenSim.Region.Framework.Scenes
886 { 1107 {
887 if (HasInventoryChanged) 1108 if (HasInventoryChanged)
888 { 1109 {
889 HasInventoryChanged = false; 1110 Items.LockItemsForRead(true);
890 List<TaskInventoryItem> items = GetInventoryItems(); 1111 datastore.StorePrimInventory(m_part.UUID, Items.Values);
891 datastore.StorePrimInventory(m_part.UUID, items); 1112 Items.LockItemsForRead(false);
892 1113
1114 HasInventoryChanged = false;
893 } 1115 }
894 } 1116 }
895 1117
@@ -956,82 +1178,63 @@ namespace OpenSim.Region.Framework.Scenes
956 { 1178 {
957 uint mask=0x7fffffff; 1179 uint mask=0x7fffffff;
958 1180
959 lock (m_items) 1181 foreach (TaskInventoryItem item in m_items.Values)
960 { 1182 {
961 foreach (TaskInventoryItem item in m_items.Values) 1183 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1184 mask &= ~((uint)PermissionMask.Copy >> 13);
1185 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1186 mask &= ~((uint)PermissionMask.Transfer >> 13);
1187 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1188 mask &= ~((uint)PermissionMask.Modify >> 13);
1189
1190 if (item.InvType == (int)InventoryType.Object)
962 { 1191 {
963 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1192 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
964 mask &= ~((uint)PermissionMask.Copy >> 13); 1193 mask &= ~((uint)PermissionMask.Copy >> 13);
965 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1194 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
966 mask &= ~((uint)PermissionMask.Transfer >> 13); 1195 mask &= ~((uint)PermissionMask.Transfer >> 13);
967 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) 1196 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
968 mask &= ~((uint)PermissionMask.Modify >> 13); 1197 mask &= ~((uint)PermissionMask.Modify >> 13);
969
970 if (item.InvType != (int)InventoryType.Object)
971 {
972 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
973 mask &= ~((uint)PermissionMask.Copy >> 13);
974 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
975 mask &= ~((uint)PermissionMask.Transfer >> 13);
976 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
977 mask &= ~((uint)PermissionMask.Modify >> 13);
978 }
979 else
980 {
981 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
982 mask &= ~((uint)PermissionMask.Copy >> 13);
983 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
984 mask &= ~((uint)PermissionMask.Transfer >> 13);
985 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
986 mask &= ~((uint)PermissionMask.Modify >> 13);
987 }
988
989 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
990 mask &= ~(uint)PermissionMask.Copy;
991 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
992 mask &= ~(uint)PermissionMask.Transfer;
993 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
994 mask &= ~(uint)PermissionMask.Modify;
995 } 1198 }
1199
1200 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1201 mask &= ~(uint)PermissionMask.Copy;
1202 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1203 mask &= ~(uint)PermissionMask.Transfer;
1204 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1205 mask &= ~(uint)PermissionMask.Modify;
996 } 1206 }
997
998 return mask; 1207 return mask;
999 } 1208 }
1000 1209
1001 public void ApplyNextOwnerPermissions() 1210 public void ApplyNextOwnerPermissions()
1002 { 1211 {
1003 lock (m_items) 1212 foreach (TaskInventoryItem item in m_items.Values)
1004 { 1213 {
1005 foreach (TaskInventoryItem item in m_items.Values) 1214 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
1006 { 1215 {
1007 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) 1216 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1008 { 1217 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
1009 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) 1218 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1010 item.CurrentPermissions &= ~(uint)PermissionMask.Copy; 1219 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
1011 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) 1220 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1012 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; 1221 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1013 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1014 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1015 }
1016 item.CurrentPermissions &= item.NextPermissions;
1017 item.BasePermissions &= item.NextPermissions;
1018 item.EveryonePermissions &= item.NextPermissions;
1019 item.OwnerChanged = true;
1020 item.PermsMask = 0;
1021 item.PermsGranter = UUID.Zero;
1022 } 1222 }
1223 item.OwnerChanged = true;
1224 item.CurrentPermissions &= item.NextPermissions;
1225 item.BasePermissions &= item.NextPermissions;
1226 item.EveryonePermissions &= item.NextPermissions;
1227 item.PermsMask = 0;
1228 item.PermsGranter = UUID.Zero;
1023 } 1229 }
1024 } 1230 }
1025 1231
1026 public void ApplyGodPermissions(uint perms) 1232 public void ApplyGodPermissions(uint perms)
1027 { 1233 {
1028 lock (m_items) 1234 foreach (TaskInventoryItem item in m_items.Values)
1029 { 1235 {
1030 foreach (TaskInventoryItem item in m_items.Values) 1236 item.CurrentPermissions = perms;
1031 { 1237 item.BasePermissions = perms;
1032 item.CurrentPermissions = perms;
1033 item.BasePermissions = perms;
1034 }
1035 } 1238 }
1036 m_inventorySerial++; 1239 m_inventorySerial++;
1037 HasInventoryChanged = true; 1240 HasInventoryChanged = true;
@@ -1039,17 +1242,13 @@ namespace OpenSim.Region.Framework.Scenes
1039 1242
1040 public bool ContainsScripts() 1243 public bool ContainsScripts()
1041 { 1244 {
1042 lock (m_items) 1245 foreach (TaskInventoryItem item in m_items.Values)
1043 { 1246 {
1044 foreach (TaskInventoryItem item in m_items.Values) 1247 if (item.InvType == (int)InventoryType.LSL)
1045 { 1248 {
1046 if (item.InvType == (int)InventoryType.LSL) 1249 return true;
1047 {
1048 return true;
1049 }
1050 } 1250 }
1051 } 1251 }
1052
1053 return false; 1252 return false;
1054 } 1253 }
1055 1254
@@ -1057,11 +1256,8 @@ namespace OpenSim.Region.Framework.Scenes
1057 { 1256 {
1058 List<UUID> ret = new List<UUID>(); 1257 List<UUID> ret = new List<UUID>();
1059 1258
1060 lock (m_items) 1259 foreach (TaskInventoryItem item in m_items.Values)
1061 { 1260 ret.Add(item.ItemID);
1062 foreach (TaskInventoryItem item in m_items.Values)
1063 ret.Add(item.ItemID);
1064 }
1065 1261
1066 return ret; 1262 return ret;
1067 } 1263 }
@@ -1092,6 +1288,11 @@ namespace OpenSim.Region.Framework.Scenes
1092 1288
1093 public Dictionary<UUID, string> GetScriptStates() 1289 public Dictionary<UUID, string> GetScriptStates()
1094 { 1290 {
1291 return GetScriptStates(false);
1292 }
1293
1294 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1295 {
1095 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1296 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1096 1297
1097 if (m_part.ParentGroup.Scene == null) // Group not in a scene 1298 if (m_part.ParentGroup.Scene == null) // Group not in a scene
@@ -1102,25 +1303,35 @@ namespace OpenSim.Region.Framework.Scenes
1102 if (engines == null) // No engine at all 1303 if (engines == null) // No engine at all
1103 return ret; 1304 return ret;
1104 1305
1105 List<TaskInventoryItem> scripts = GetInventoryScripts(); 1306 Items.LockItemsForRead(true);
1106 1307 foreach (TaskInventoryItem item in m_items.Values)
1107 foreach (TaskInventoryItem item in scripts)
1108 { 1308 {
1109 foreach (IScriptModule e in engines) 1309 if (item.InvType == (int)InventoryType.LSL)
1110 { 1310 {
1111 if (e != null) 1311 foreach (IScriptModule e in engines)
1112 { 1312 {
1113 string n = e.GetXMLState(item.ItemID); 1313 if (e != null)
1114 if (n != String.Empty)
1115 { 1314 {
1116 if (!ret.ContainsKey(item.ItemID)) 1315 string n = e.GetXMLState(item.ItemID);
1117 ret[item.ItemID] = n; 1316 if (n != String.Empty)
1118 break; 1317 {
1318 if (oldIDs)
1319 {
1320 if (!ret.ContainsKey(item.OldItemID))
1321 ret[item.OldItemID] = n;
1322 }
1323 else
1324 {
1325 if (!ret.ContainsKey(item.ItemID))
1326 ret[item.ItemID] = n;
1327 }
1328 break;
1329 }
1119 } 1330 }
1120 } 1331 }
1121 } 1332 }
1122 } 1333 }
1123 1334 Items.LockItemsForRead(false);
1124 return ret; 1335 return ret;
1125 } 1336 }
1126 1337
@@ -1130,21 +1341,27 @@ namespace OpenSim.Region.Framework.Scenes
1130 if (engines == null) 1341 if (engines == null)
1131 return; 1342 return;
1132 1343
1133 List<TaskInventoryItem> scripts = GetInventoryScripts();
1134 1344
1135 foreach (TaskInventoryItem item in scripts) 1345 Items.LockItemsForRead(true);
1346
1347 foreach (TaskInventoryItem item in m_items.Values)
1136 { 1348 {
1137 foreach (IScriptModule engine in engines) 1349 if (item.InvType == (int)InventoryType.LSL)
1138 { 1350 {
1139 if (engine != null) 1351 foreach (IScriptModule engine in engines)
1140 { 1352 {
1141 if (item.OwnerChanged) 1353 if (engine != null)
1142 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER }); 1354 {
1143 item.OwnerChanged = false; 1355 if (item.OwnerChanged)
1144 engine.ResumeScript(item.ItemID); 1356 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER });
1357 item.OwnerChanged = false;
1358 engine.ResumeScript(item.ItemID);
1359 }
1145 } 1360 }
1146 } 1361 }
1147 } 1362 }
1363
1364 Items.LockItemsForRead(false);
1148 } 1365 }
1149 } 1366 }
1150} 1367}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 80aafd0..af6f89c 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;
@@ -72,7 +73,7 @@ namespace OpenSim.Region.Framework.Scenes
72// { 73// {
73// m_log.Debug("[ScenePresence] Destructor called"); 74// m_log.Debug("[ScenePresence] Destructor called");
74// } 75// }
75 76
76 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 77 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
77 78
78// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); 79// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes();
@@ -87,7 +88,9 @@ namespace OpenSim.Region.Framework.Scenes
87 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis 88 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis
88 /// issue #1716 89 /// issue #1716
89 /// </summary> 90 /// </summary>
90 private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f); 91// private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f);
92 // Value revised by KF 091121 by comparison with SL.
93 private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f);
91 94
92 public UUID currentParcelUUID = UUID.Zero; 95 public UUID currentParcelUUID = UUID.Zero;
93 96
@@ -110,6 +113,7 @@ namespace OpenSim.Region.Framework.Scenes
110 { 113 {
111 get { return m_attachments; } 114 get { return m_attachments; }
112 } 115 }
116
113 protected List<SceneObjectGroup> m_attachments = new List<SceneObjectGroup>(); 117 protected List<SceneObjectGroup> m_attachments = new List<SceneObjectGroup>();
114 118
115 private Dictionary<UUID, ScriptControllers> scriptedcontrols = new Dictionary<UUID, ScriptControllers>(); 119 private Dictionary<UUID, ScriptControllers> scriptedcontrols = new Dictionary<UUID, ScriptControllers>();
@@ -119,10 +123,12 @@ namespace OpenSim.Region.Framework.Scenes
119 private SceneObjectGroup proxyObjectGroup; 123 private SceneObjectGroup proxyObjectGroup;
120 //private SceneObjectPart proxyObjectPart = null; 124 //private SceneObjectPart proxyObjectPart = null;
121 public Vector3 lastKnownAllowedPosition; 125 public Vector3 lastKnownAllowedPosition;
122 public bool sentMessageAboutRestrictedParcelFlyingDown;
123 public Vector4 CollisionPlane = Vector4.UnitW; 126 public Vector4 CollisionPlane = Vector4.UnitW;
124 127
128 private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation
129 private Vector3 m_avUnscriptedSitPos; // for non-scripted prims
125 private Vector3 m_lastPosition; 130 private Vector3 m_lastPosition;
131 private Vector3 m_lastWorldPosition;
126 private Quaternion m_lastRotation; 132 private Quaternion m_lastRotation;
127 private Vector3 m_lastVelocity; 133 private Vector3 m_lastVelocity;
128 //private int m_lastTerseSent; 134 //private int m_lastTerseSent;
@@ -130,6 +136,11 @@ namespace OpenSim.Region.Framework.Scenes
130 private bool m_updateflag; 136 private bool m_updateflag;
131 private byte m_movementflag; 137 private byte m_movementflag;
132 private Vector3? m_forceToApply; 138 private Vector3? m_forceToApply;
139 private int m_userFlags;
140 public int UserFlags
141 {
142 get { return m_userFlags; }
143 }
133 private TeleportFlags m_teleportFlags; 144 private TeleportFlags m_teleportFlags;
134 public TeleportFlags TeleportFlags 145 public TeleportFlags TeleportFlags
135 { 146 {
@@ -160,9 +171,10 @@ namespace OpenSim.Region.Framework.Scenes
160 private int m_perfMonMS; 171 private int m_perfMonMS;
161 172
162 private bool m_setAlwaysRun; 173 private bool m_setAlwaysRun;
163
164 private bool m_forceFly; 174 private bool m_forceFly;
165 private bool m_flyDisabled; 175 private bool m_flyDisabled;
176 private bool m_flyingOld; // add for fly velocity control
177 public bool m_wasFlying; // add for fly velocity control
166 178
167 private float m_speedModifier = 1.0f; 179 private float m_speedModifier = 1.0f;
168 180
@@ -181,7 +193,8 @@ namespace OpenSim.Region.Framework.Scenes
181 protected RegionInfo m_regionInfo; 193 protected RegionInfo m_regionInfo;
182 protected ulong crossingFromRegion; 194 protected ulong crossingFromRegion;
183 195
184 private readonly Vector3[] Dir_Vectors = new Vector3[9]; 196 private readonly Vector3[] Dir_Vectors = new Vector3[11];
197 private bool m_isNudging = false;
185 198
186 // Position of agent's camera in world (region cordinates) 199 // Position of agent's camera in world (region cordinates)
187 protected Vector3 m_CameraCenter; 200 protected Vector3 m_CameraCenter;
@@ -206,17 +219,25 @@ namespace OpenSim.Region.Framework.Scenes
206 private bool m_autopilotMoving; 219 private bool m_autopilotMoving;
207 private Vector3 m_autoPilotTarget; 220 private Vector3 m_autoPilotTarget;
208 private bool m_sitAtAutoTarget; 221 private bool m_sitAtAutoTarget;
222 private Vector3 m_initialSitTarget = Vector3.Zero; //KF: First estimate of where to sit
209 223
210 private string m_nextSitAnimation = String.Empty; 224 private string m_nextSitAnimation = String.Empty;
211 225
212 //PauPaw:Proper PID Controler for autopilot************ 226 //PauPaw:Proper PID Controler for autopilot************
213 private bool m_moveToPositionInProgress; 227 private bool m_moveToPositionInProgress;
214 private Vector3 m_moveToPositionTarget; 228 private Vector3 m_moveToPositionTarget;
229 private Quaternion m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
215 230
216 private bool m_followCamAuto; 231 private bool m_followCamAuto;
217 232
218 private int m_movementUpdateCount; 233 private int m_movementUpdateCount;
234 private int m_lastColCount = -1; //KF: Look for Collision chnages
235 private int m_updateCount = 0; //KF: Update Anims for a while
236 private static readonly int UPDATE_COUNT = 10; // how many frames to update for
219 private const int NumMovementsBetweenRayCast = 5; 237 private const int NumMovementsBetweenRayCast = 5;
238 private List<uint> m_lastColliders = new List<uint>();
239
240 private object m_syncRoot = new Object();
220 241
221 private bool CameraConstraintActive; 242 private bool CameraConstraintActive;
222 //private int m_moveToPositionStateStatus; 243 //private int m_moveToPositionStateStatus;
@@ -253,7 +274,9 @@ namespace OpenSim.Region.Framework.Scenes
253 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, 274 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
254 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, 275 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
255 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS, 276 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS,
256 DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, 277 DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
278 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
279 DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
257 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG 280 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
258 } 281 }
259 282
@@ -460,7 +483,8 @@ namespace OpenSim.Region.Framework.Scenes
460 get 483 get
461 { 484 {
462 PhysicsActor actor = m_physicsActor; 485 PhysicsActor actor = m_physicsActor;
463 if (actor != null) 486// if (actor != null)
487 if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting!
464 m_pos = actor.Position; 488 m_pos = actor.Position;
465 else 489 else
466 { 490 {
@@ -482,7 +506,7 @@ namespace OpenSim.Region.Framework.Scenes
482 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); 506 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
483 if (part != null) 507 if (part != null)
484 { 508 {
485 return m_parentPosition + (m_pos * part.GetWorldRotation()); 509 return part.AbsolutePosition + (m_pos * part.GetWorldRotation());
486 } 510 }
487 else 511 else
488 { 512 {
@@ -509,7 +533,8 @@ namespace OpenSim.Region.Framework.Scenes
509 } 533 }
510 } 534 }
511 535
512 m_pos = value; 536 if (m_parentID == 0) // KF Do NOT update m_pos here if Av is sitting!
537 m_pos = value;
513 m_parentPosition = Vector3.Zero; 538 m_parentPosition = Vector3.Zero;
514 } 539 }
515 } 540 }
@@ -553,10 +578,39 @@ namespace OpenSim.Region.Framework.Scenes
553 } 578 }
554 } 579 }
555 580
581 public Quaternion OffsetRotation
582 {
583 get { return m_offsetRotation; }
584 set { m_offsetRotation = value; }
585 }
586
556 public Quaternion Rotation 587 public Quaternion Rotation
557 { 588 {
558 get { return m_bodyRot; } 589 get {
559 set { m_bodyRot = value; } 590 if (m_parentID != 0)
591 {
592 if (m_offsetRotation != null)
593 {
594 return m_offsetRotation;
595 }
596 else
597 {
598 return new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
599 }
600
601 }
602 else
603 {
604 return m_bodyRot;
605 }
606 }
607 set {
608 m_bodyRot = value;
609 if (m_parentID != 0)
610 {
611 m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
612 }
613 }
560 } 614 }
561 615
562 public Quaternion PreviousRotation 616 public Quaternion PreviousRotation
@@ -581,11 +635,21 @@ namespace OpenSim.Region.Framework.Scenes
581 635
582 private uint m_parentID; 636 private uint m_parentID;
583 637
638
639 private UUID m_linkedPrim;
640
584 public uint ParentID 641 public uint ParentID
585 { 642 {
586 get { return m_parentID; } 643 get { return m_parentID; }
587 set { m_parentID = value; } 644 set { m_parentID = value; }
588 } 645 }
646
647 public UUID LinkedPrim
648 {
649 get { return m_linkedPrim; }
650 set { m_linkedPrim = value; }
651 }
652
589 public float Health 653 public float Health
590 { 654 {
591 get { return m_health; } 655 get { return m_health; }
@@ -707,7 +771,7 @@ namespace OpenSim.Region.Framework.Scenes
707 CreateSceneViewer(); 771 CreateSceneViewer();
708 m_animator = new ScenePresenceAnimator(this); 772 m_animator = new ScenePresenceAnimator(this);
709 } 773 }
710 774
711 private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this() 775 private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this()
712 { 776 {
713 m_DrawDistance = world.DefaultDrawDistance; 777 m_DrawDistance = world.DefaultDrawDistance;
@@ -722,6 +786,7 @@ namespace OpenSim.Region.Framework.Scenes
722 m_localId = m_scene.AllocateLocalId(); 786 m_localId = m_scene.AllocateLocalId();
723 787
724 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid); 788 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid);
789 m_userFlags = account.UserFlags;
725 790
726 if (account != null) 791 if (account != null)
727 m_userLevel = account.UserLevel; 792 m_userLevel = account.UserLevel;
@@ -740,10 +805,7 @@ namespace OpenSim.Region.Framework.Scenes
740 m_reprioritization_timer.AutoReset = false; 805 m_reprioritization_timer.AutoReset = false;
741 806
742 AdjustKnownSeeds(); 807 AdjustKnownSeeds();
743
744 // TODO: I think, this won't send anything, as we are still a child here...
745 Animator.TrySetMovementAnimation("STAND"); 808 Animator.TrySetMovementAnimation("STAND");
746
747 // we created a new ScenePresence (a new child agent) in a fresh region. 809 // we created a new ScenePresence (a new child agent) in a fresh region.
748 // Request info about all the (root) agents in this region 810 // Request info about all the (root) agents in this region
749 // Note: This won't send data *to* other clients in that region (children don't send) 811 // Note: This won't send data *to* other clients in that region (children don't send)
@@ -794,25 +856,47 @@ namespace OpenSim.Region.Framework.Scenes
794 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT 856 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT
795 Dir_Vectors[4] = Vector3.UnitZ; //UP 857 Dir_Vectors[4] = Vector3.UnitZ; //UP
796 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN 858 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN
797 Dir_Vectors[8] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge 859 Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE
798 Dir_Vectors[6] = Vector3.UnitX*2; //FORWARD 860 Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE
799 Dir_Vectors[7] = -Vector3.UnitX; //BACK 861 Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE
862 Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE
863 Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
800 } 864 }
801 865
802 private Vector3[] GetWalkDirectionVectors() 866 private Vector3[] GetWalkDirectionVectors()
803 { 867 {
804 Vector3[] vector = new Vector3[9]; 868 Vector3[] vector = new Vector3[11];
805 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD 869 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD
806 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK 870 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK
807 vector[2] = Vector3.UnitY; //LEFT 871 vector[2] = Vector3.UnitY; //LEFT
808 vector[3] = -Vector3.UnitY; //RIGHT 872 vector[3] = -Vector3.UnitY; //RIGHT
809 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP 873 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP
810 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN 874 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN
811 vector[8] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge 875 vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE
812 vector[6] = (new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z) * 2); //FORWARD Nudge 876 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE
813 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK Nudge 877 vector[8] = Vector3.UnitY; //LEFT_NUDGE
878 vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
879 vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE
814 return vector; 880 return vector;
815 } 881 }
882
883 private bool[] GetDirectionIsNudge()
884 {
885 bool[] isNudge = new bool[11];
886 isNudge[0] = false; //FORWARD
887 isNudge[1] = false; //BACK
888 isNudge[2] = false; //LEFT
889 isNudge[3] = false; //RIGHT
890 isNudge[4] = false; //UP
891 isNudge[5] = false; //DOWN
892 isNudge[6] = true; //FORWARD_NUDGE
893 isNudge[7] = true; //BACK_NUDGE
894 isNudge[8] = true; //LEFT_NUDGE
895 isNudge[9] = true; //RIGHT_NUDGE
896 isNudge[10] = true; //DOWN_Nudge
897 return isNudge;
898 }
899
816 900
817 #endregion 901 #endregion
818 902
@@ -877,6 +961,62 @@ namespace OpenSim.Region.Framework.Scenes
877 pos.Y = crossedBorder.BorderLine.Z - 1; 961 pos.Y = crossedBorder.BorderLine.Z - 1;
878 } 962 }
879 963
964 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
965 if (land != null)
966 {
967 // If we come in via login, landmark or map, we want to
968 // honor landing points. If we come in via Lure, we want
969 // to ignore them.
970 if ((m_teleportFlags & (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID)) == (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID) ||
971 (m_teleportFlags & TeleportFlags.ViaLandmark) != 0 ||
972 (m_teleportFlags & TeleportFlags.ViaLocation) != 0)
973 {
974 // Don't restrict gods, estate managers, or land owners to
975 // the TP point. This behaviour mimics agni.
976 if (land.LandData.LandingType == (byte)LandingType.LandingPoint &&
977 land.LandData.UserLocation != Vector3.Zero &&
978 GodLevel < 200 &&
979 ((land.LandData.OwnerID != m_uuid &&
980 (!m_scene.Permissions.IsGod(m_uuid)) &&
981 (!m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid))) || (m_teleportFlags & TeleportFlags.ViaLocation) != 0))
982 {
983 pos = land.LandData.UserLocation;
984 }
985 }
986
987 land.SendLandUpdateToClient(ControllingClient);
988 }
989
990 if (pos.X < 0 || pos.Y < 0 || pos.Z < 0)
991 {
992 Vector3 emergencyPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 128);
993
994 if (pos.X < 0)
995 {
996 emergencyPos.X = (int)Constants.RegionSize + pos.X;
997 if (!(pos.Y < 0))
998 emergencyPos.Y = pos.Y;
999 if (!(pos.Z < 0))
1000 emergencyPos.Z = pos.Z;
1001 }
1002 if (pos.Y < 0)
1003 {
1004 emergencyPos.Y = (int)Constants.RegionSize + pos.Y;
1005 if (!(pos.X < 0))
1006 emergencyPos.X = pos.X;
1007 if (!(pos.Z < 0))
1008 emergencyPos.Z = pos.Z;
1009 }
1010 if (pos.Z < 0)
1011 {
1012 emergencyPos.Z = 128;
1013 if (!(pos.Y < 0))
1014 emergencyPos.Y = pos.Y;
1015 if (!(pos.X < 0))
1016 emergencyPos.X = pos.X;
1017 }
1018 }
1019
880 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 1020 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
881 { 1021 {
882 m_log.WarnFormat( 1022 m_log.WarnFormat(
@@ -1022,16 +1162,21 @@ namespace OpenSim.Region.Framework.Scenes
1022 /// <summary> 1162 /// <summary>
1023 /// Removes physics plugin scene representation of this agent if it exists. 1163 /// Removes physics plugin scene representation of this agent if it exists.
1024 /// </summary> 1164 /// </summary>
1025 private void RemoveFromPhysicalScene() 1165 public void RemoveFromPhysicalScene()
1026 { 1166 {
1027 if (PhysicsActor != null) 1167 if (PhysicsActor != null)
1028 { 1168 {
1029 m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients; 1169 try
1030 m_physicsActor.OnOutOfBounds -= OutOfBoundsCall; 1170 {
1031 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor); 1171 m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
1032 m_physicsActor.UnSubscribeEvents(); 1172 m_physicsActor.OnOutOfBounds -= OutOfBoundsCall;
1033 m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate; 1173 m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate;
1034 PhysicsActor = null; 1174 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
1175 m_physicsActor.UnSubscribeEvents();
1176 PhysicsActor = null;
1177 }
1178 catch
1179 { }
1035 } 1180 }
1036 } 1181 }
1037 1182
@@ -1042,11 +1187,13 @@ namespace OpenSim.Region.Framework.Scenes
1042 public void Teleport(Vector3 pos) 1187 public void Teleport(Vector3 pos)
1043 { 1188 {
1044 bool isFlying = false; 1189 bool isFlying = false;
1190
1045 if (m_physicsActor != null) 1191 if (m_physicsActor != null)
1046 isFlying = m_physicsActor.Flying; 1192 isFlying = m_physicsActor.Flying;
1047 1193
1048 RemoveFromPhysicalScene(); 1194 RemoveFromPhysicalScene();
1049 Velocity = Vector3.Zero; 1195 Velocity = Vector3.Zero;
1196 CheckLandingPoint(ref pos);
1050 AbsolutePosition = pos; 1197 AbsolutePosition = pos;
1051 AddToPhysicalScene(isFlying); 1198 AddToPhysicalScene(isFlying);
1052 if (m_appearance != null) 1199 if (m_appearance != null)
@@ -1056,6 +1203,7 @@ namespace OpenSim.Region.Framework.Scenes
1056 } 1203 }
1057 1204
1058 SendTerseUpdateToAllClients(); 1205 SendTerseUpdateToAllClients();
1206
1059 } 1207 }
1060 1208
1061 public void TeleportWithMomentum(Vector3 pos) 1209 public void TeleportWithMomentum(Vector3 pos)
@@ -1065,6 +1213,7 @@ namespace OpenSim.Region.Framework.Scenes
1065 isFlying = m_physicsActor.Flying; 1213 isFlying = m_physicsActor.Flying;
1066 1214
1067 RemoveFromPhysicalScene(); 1215 RemoveFromPhysicalScene();
1216 CheckLandingPoint(ref pos);
1068 AbsolutePosition = pos; 1217 AbsolutePosition = pos;
1069 AddToPhysicalScene(isFlying); 1218 AddToPhysicalScene(isFlying);
1070 if (m_appearance != null) 1219 if (m_appearance != null)
@@ -1275,6 +1424,7 @@ namespace OpenSim.Region.Framework.Scenes
1275 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); 1424 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902");
1276 1425
1277 m_pos = m_LastFinitePos; 1426 m_pos = m_LastFinitePos;
1427
1278 if (!m_pos.IsFinite()) 1428 if (!m_pos.IsFinite())
1279 { 1429 {
1280 m_pos.X = 127f; 1430 m_pos.X = 127f;
@@ -1345,7 +1495,6 @@ namespace OpenSim.Region.Framework.Scenes
1345 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback); 1495 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback);
1346 } 1496 }
1347 } 1497 }
1348
1349 lock (scriptedcontrols) 1498 lock (scriptedcontrols)
1350 { 1499 {
1351 if (scriptedcontrols.Count > 0) 1500 if (scriptedcontrols.Count > 0)
@@ -1360,6 +1509,9 @@ namespace OpenSim.Region.Framework.Scenes
1360 1509
1361 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) 1510 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
1362 { 1511 {
1512 m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.
1513 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
1514
1363 // TODO: This doesn't prevent the user from walking yet. 1515 // TODO: This doesn't prevent the user from walking yet.
1364 // Setting parent ID would fix this, if we knew what value 1516 // Setting parent ID would fix this, if we knew what value
1365 // to use. Or we could add a m_isSitting variable. 1517 // to use. Or we could add a m_isSitting variable.
@@ -1408,12 +1560,20 @@ namespace OpenSim.Region.Framework.Scenes
1408 if (actor.Flying != oldflying) 1560 if (actor.Flying != oldflying)
1409 update_movementflag = true; 1561 update_movementflag = true;
1410 1562
1563 if (m_animator.m_jumping) // add for jumping
1564 update_movementflag = true;
1565
1411 if (q != m_bodyRot) 1566 if (q != m_bodyRot)
1412 { 1567 {
1413 m_bodyRot = q; 1568 m_bodyRot = q;
1414 update_rotation = true; 1569 update_rotation = true;
1415 } 1570 }
1416 1571
1572 //guilty until proven innocent..
1573 bool Nudging = true;
1574 //Basically, if there is at least one non-nudge control then we don't need
1575 //to worry about stopping the avatar
1576
1417 if (m_parentID == 0) 1577 if (m_parentID == 0)
1418 { 1578 {
1419 bool bAllowUpdateMoveToPosition = false; 1579 bool bAllowUpdateMoveToPosition = false;
@@ -1428,9 +1588,12 @@ namespace OpenSim.Region.Framework.Scenes
1428 else 1588 else
1429 dirVectors = Dir_Vectors; 1589 dirVectors = Dir_Vectors;
1430 1590
1431 // The fact that m_movementflag is a byte needs to be fixed 1591 bool[] isNudge = GetDirectionIsNudge();
1432 // it really should be a uint 1592
1433 uint nudgehack = 250; 1593
1594
1595
1596
1434 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) 1597 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
1435 { 1598 {
1436 if (((uint)flags & (uint)DCF) != 0) 1599 if (((uint)flags & (uint)DCF) != 0)
@@ -1440,40 +1603,28 @@ namespace OpenSim.Region.Framework.Scenes
1440 try 1603 try
1441 { 1604 {
1442 agent_control_v3 += dirVectors[i]; 1605 agent_control_v3 += dirVectors[i];
1443 //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]); 1606 if (isNudge[i] == false)
1607 {
1608 Nudging = false;
1609 }
1444 } 1610 }
1445 catch (IndexOutOfRangeException) 1611 catch (IndexOutOfRangeException)
1446 { 1612 {
1447 // Why did I get this? 1613 // Why did I get this?
1448 } 1614 }
1449 1615
1450 if ((m_movementflag & (byte)(uint)DCF) == 0) 1616 if ((m_movementflag & (uint)DCF) == 0)
1451 { 1617 {
1452 if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1453 {
1454 m_movementflag |= (byte)nudgehack;
1455 }
1456 m_movementflag += (byte)(uint)DCF; 1618 m_movementflag += (byte)(uint)DCF;
1457 update_movementflag = true; 1619 update_movementflag = true;
1458 } 1620 }
1459 } 1621 }
1460 else 1622 else
1461 { 1623 {
1462 if ((m_movementflag & (byte)(uint)DCF) != 0 || 1624 if ((m_movementflag & (uint)DCF) != 0)
1463 ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1464 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1465 ) // This or is for Nudge forward
1466 { 1625 {
1467 m_movementflag -= ((byte)(uint)DCF); 1626 m_movementflag -= (byte)(uint)DCF;
1468
1469 update_movementflag = true; 1627 update_movementflag = true;
1470 /*
1471 if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1472 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1473 {
1474 m_log.Debug("Removed Hack flag");
1475 }
1476 */
1477 } 1628 }
1478 else 1629 else
1479 { 1630 {
@@ -1482,7 +1633,6 @@ namespace OpenSim.Region.Framework.Scenes
1482 } 1633 }
1483 i++; 1634 i++;
1484 } 1635 }
1485
1486 //Paupaw:Do Proper PID for Autopilot here 1636 //Paupaw:Do Proper PID for Autopilot here
1487 if (bResetMoveToPosition) 1637 if (bResetMoveToPosition)
1488 { 1638 {
@@ -1494,8 +1644,41 @@ namespace OpenSim.Region.Framework.Scenes
1494 1644
1495 if (bAllowUpdateMoveToPosition && (m_moveToPositionInProgress && !m_autopilotMoving)) 1645 if (bAllowUpdateMoveToPosition && (m_moveToPositionInProgress && !m_autopilotMoving))
1496 { 1646 {
1647/*
1648 bool twoD = false;
1649 bool there = false;
1650 if (Animator != null)
1651 {
1652 switch (Animator.CurrentMovementAnimation)
1653 {
1654 case "STAND":
1655 case "WALK":
1656 case "RUN":
1657 case "CROUCH":
1658 case "CROUCHWALK":
1659 {
1660 twoD = true;
1661 }
1662 break;
1663 }
1664 }
1665
1666 if (twoD)
1667 {
1668*/
1669 Vector3 abspos = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, 0.0f);
1670 Vector3 tgt = new Vector3(m_moveToPositionTarget.X, m_moveToPositionTarget.Y, 0.0f);
1671/* if (Util.GetDistanceTo(abspos, tgt) <= 0.5f) there = true;
1672 }
1673 else
1674 {
1675 if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 0.5f) there = true;
1676 }
1677*/
1497 //Check the error term of the current position in relation to the target position 1678 //Check the error term of the current position in relation to the target position
1498 if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 0.5f) 1679// if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 0.5f)
1680// if (there)
1681 if (Util.GetDistanceTo(abspos, tgt) <= 0.5f)
1499 { 1682 {
1500 // we are close enough to the target 1683 // we are close enough to the target
1501 m_moveToPositionTarget = Vector3.Zero; 1684 m_moveToPositionTarget = Vector3.Zero;
@@ -1512,11 +1695,15 @@ namespace OpenSim.Region.Framework.Scenes
1512 // unknown forces are acting on the avatar and we need to adaptively respond 1695 // unknown forces are acting on the avatar and we need to adaptively respond
1513 // to such forces, but the following simple approach seems to works fine. 1696 // to such forces, but the following simple approach seems to works fine.
1514 Vector3 LocalVectorToTarget3D = 1697 Vector3 LocalVectorToTarget3D =
1515 (m_moveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords 1698// (m_moveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords
1699 (tgt - abspos)
1516 * Matrix4.CreateFromQuaternion(Quaternion.Inverse(bodyRotation)); // change to avatar coords 1700 * Matrix4.CreateFromQuaternion(Quaternion.Inverse(bodyRotation)); // change to avatar coords
1517 // Ignore z component of vector 1701 // Ignore z component of vector
1518 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); 1702 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
1519 LocalVectorToTarget2D.Normalize(); 1703 LocalVectorToTarget2D.Normalize();
1704
1705 //We're not nudging
1706 Nudging = false;
1520 agent_control_v3 += LocalVectorToTarget2D; 1707 agent_control_v3 += LocalVectorToTarget2D;
1521 1708
1522 // update avatar movement flags. the avatar coordinate system is as follows: 1709 // update avatar movement flags. the avatar coordinate system is as follows:
@@ -1607,13 +1794,13 @@ namespace OpenSim.Region.Framework.Scenes
1607 // m_log.DebugFormat( 1794 // m_log.DebugFormat(
1608 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3); 1795 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
1609 1796
1610 AddNewMovement(agent_control_v3, q); 1797 AddNewMovement(agent_control_v3, q, Nudging);
1611 1798
1612 1799
1613 } 1800 }
1614 } 1801 }
1615 1802
1616 if (update_movementflag && ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) == 0) && (m_parentID == 0) && !SitGround) 1803 if (update_movementflag && !SitGround)
1617 Animator.UpdateMovementAnimations(); 1804 Animator.UpdateMovementAnimations();
1618 1805
1619 m_scene.EventManager.TriggerOnClientMovement(this); 1806 m_scene.EventManager.TriggerOnClientMovement(this);
@@ -1628,7 +1815,6 @@ namespace OpenSim.Region.Framework.Scenes
1628 m_sitAtAutoTarget = false; 1815 m_sitAtAutoTarget = false;
1629 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default; 1816 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
1630 //proxy.PCode = (byte)PCode.ParticleSystem; 1817 //proxy.PCode = (byte)PCode.ParticleSystem;
1631
1632 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy); 1818 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy);
1633 proxyObjectGroup.AttachToScene(m_scene); 1819 proxyObjectGroup.AttachToScene(m_scene);
1634 1820
@@ -1647,8 +1833,15 @@ namespace OpenSim.Region.Framework.Scenes
1647// } 1833// }
1648 } 1834 }
1649 1835
1836 public void StopMoveToPosition()
1837 {
1838 m_moveToPositionTarget = Vector3.Zero;
1839 m_moveToPositionInProgress = false;
1840 }
1841
1650 public void DoMoveToPosition(Object sender, string method, List<String> args) 1842 public void DoMoveToPosition(Object sender, string method, List<String> args)
1651 { 1843 {
1844//Console.WriteLine("SP:DoMoveToPosition");
1652 try 1845 try
1653 { 1846 {
1654 float locx = 0f; 1847 float locx = 0f;
@@ -1670,7 +1863,7 @@ namespace OpenSim.Region.Framework.Scenes
1670 } 1863 }
1671 m_moveToPositionInProgress = true; 1864 m_moveToPositionInProgress = true;
1672 m_moveToPositionTarget = new Vector3(locx, locy, locz); 1865 m_moveToPositionTarget = new Vector3(locx, locy, locz);
1673 } 1866 }
1674 catch (Exception ex) 1867 catch (Exception ex)
1675 { 1868 {
1676 //Why did I get this error? 1869 //Why did I get this error?
@@ -1692,7 +1885,7 @@ namespace OpenSim.Region.Framework.Scenes
1692 Velocity = Vector3.Zero; 1885 Velocity = Vector3.Zero;
1693 SendAvatarDataToAllAgents(); 1886 SendAvatarDataToAllAgents();
1694 1887
1695 //HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); 1888 HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ??
1696 } 1889 }
1697 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false); 1890 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false);
1698 m_requestedSitTargetUUID = UUID.Zero; 1891 m_requestedSitTargetUUID = UUID.Zero;
@@ -1729,25 +1922,22 @@ namespace OpenSim.Region.Framework.Scenes
1729 1922
1730 if (m_parentID != 0) 1923 if (m_parentID != 0)
1731 { 1924 {
1732 m_log.Debug("StandupCode Executed"); 1925 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
1733 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
1734 if (part != null) 1926 if (part != null)
1735 { 1927 {
1928 part.TaskInventory.LockItemsForRead(true);
1736 TaskInventoryDictionary taskIDict = part.TaskInventory; 1929 TaskInventoryDictionary taskIDict = part.TaskInventory;
1737 if (taskIDict != null) 1930 if (taskIDict != null)
1738 { 1931 {
1739 lock (taskIDict) 1932 foreach (UUID taskID in taskIDict.Keys)
1740 { 1933 {
1741 foreach (UUID taskID in taskIDict.Keys) 1934 UnRegisterControlEventsToScript(LocalId, taskID);
1742 { 1935 taskIDict[taskID].PermsMask &= ~(
1743 UnRegisterControlEventsToScript(LocalId, taskID); 1936 2048 | //PERMISSION_CONTROL_CAMERA
1744 taskIDict[taskID].PermsMask &= ~( 1937 4); // PERMISSION_TAKE_CONTROLS
1745 2048 | //PERMISSION_CONTROL_CAMERA
1746 4); // PERMISSION_TAKE_CONTROLS
1747 }
1748 } 1938 }
1749
1750 } 1939 }
1940 part.TaskInventory.LockItemsForRead(false);
1751 // Reset sit target. 1941 // Reset sit target.
1752 if (part.GetAvatarOnSitTarget() == UUID) 1942 if (part.GetAvatarOnSitTarget() == UUID)
1753 part.SitTargetAvatar = UUID.Zero; 1943 part.SitTargetAvatar = UUID.Zero;
@@ -1756,16 +1946,55 @@ namespace OpenSim.Region.Framework.Scenes
1756 m_parentPosition = part.GetWorldPosition(); 1946 m_parentPosition = part.GetWorldPosition();
1757 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1947 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1758 } 1948 }
1949 // part.GetWorldRotation() is the rotation of the object being sat on
1950 // Rotation is the sittiing Av's rotation
1951
1952 Quaternion partRot;
1953// if (part.LinkNum == 1)
1954// { // Root prim of linkset
1955// partRot = part.ParentGroup.RootPart.RotationOffset;
1956// }
1957// else
1958// { // single or child prim
1959
1960// }
1961 if (part == null) //CW: Part may be gone. llDie() for example.
1962 {
1963 partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
1964 }
1965 else
1966 {
1967 partRot = part.GetWorldRotation();
1968 }
1759 1969
1970 Quaternion partIRot = Quaternion.Inverse(partRot);
1971
1972 Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
1973 Vector3 avStandUp = new Vector3(0.3f, 0f, 0f) * avatarRot; // 0.3M infront of av
1974
1975
1760 if (m_physicsActor == null) 1976 if (m_physicsActor == null)
1761 { 1977 {
1762 AddToPhysicalScene(false); 1978 AddToPhysicalScene(false);
1763 } 1979 }
1764 1980 //CW: If the part isn't null then we can set the current position
1765 m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight); 1981 if (part != null)
1766 m_parentPosition = Vector3.Zero; 1982 {
1767 1983 Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + ((m_pos - part.OffsetPosition) * partRot); // + av sit offset!
1768 m_parentID = 0; 1984 AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
1985 part.IsOccupied = false;
1986 part.ParentGroup.DeleteAvatar(ControllingClient.AgentId);
1987 }
1988 else
1989 {
1990 //CW: Since the part doesn't exist, a coarse standup position isn't an issue
1991 AbsolutePosition = m_lastWorldPosition;
1992 }
1993
1994 m_parentPosition = Vector3.Zero;
1995 m_parentID = 0;
1996 m_linkedPrim = UUID.Zero;
1997 m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
1769 SendAvatarDataToAllAgents(); 1998 SendAvatarDataToAllAgents();
1770 m_requestedSitTargetID = 0; 1999 m_requestedSitTargetID = 0;
1771 if (m_physicsActor != null && m_appearance != null) 2000 if (m_physicsActor != null && m_appearance != null)
@@ -1774,7 +2003,6 @@ namespace OpenSim.Region.Framework.Scenes
1774 SetHeight(m_appearance.AvatarHeight); 2003 SetHeight(m_appearance.AvatarHeight);
1775 } 2004 }
1776 } 2005 }
1777
1778 Animator.TrySetMovementAnimation("STAND"); 2006 Animator.TrySetMovementAnimation("STAND");
1779 } 2007 }
1780 2008
@@ -1805,13 +2033,9 @@ namespace OpenSim.Region.Framework.Scenes
1805 Vector3 avSitOffSet = part.SitTargetPosition; 2033 Vector3 avSitOffSet = part.SitTargetPosition;
1806 Quaternion avSitOrientation = part.SitTargetOrientation; 2034 Quaternion avSitOrientation = part.SitTargetOrientation;
1807 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 2035 UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
1808 2036 bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero);
1809 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 2037 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1810 bool SitTargetisSet = 2038 if (SitTargetisSet && !SitTargetOccupied)
1811 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 1f &&
1812 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f));
1813
1814 if (SitTargetisSet && SitTargetUnOccupied)
1815 { 2039 {
1816 //switch the target to this prim 2040 //switch the target to this prim
1817 return part; 2041 return part;
@@ -1825,85 +2049,168 @@ namespace OpenSim.Region.Framework.Scenes
1825 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation) 2049 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation)
1826 { 2050 {
1827 bool autopilot = true; 2051 bool autopilot = true;
2052 Vector3 autopilotTarget = new Vector3();
2053 Quaternion sitOrientation = Quaternion.Identity;
1828 Vector3 pos = new Vector3(); 2054 Vector3 pos = new Vector3();
1829 Quaternion sitOrientation = pSitOrientation;
1830 Vector3 cameraEyeOffset = Vector3.Zero; 2055 Vector3 cameraEyeOffset = Vector3.Zero;
1831 Vector3 cameraAtOffset = Vector3.Zero; 2056 Vector3 cameraAtOffset = Vector3.Zero;
1832 bool forceMouselook = false; 2057 bool forceMouselook = false;
1833 2058
1834 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); 2059 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
1835 SceneObjectPart part = FindNextAvailableSitTarget(targetID); 2060 SceneObjectPart part = FindNextAvailableSitTarget(targetID);
1836 if (part != null) 2061 if (part == null) return;
1837 { 2062
1838 // TODO: determine position to sit at based on scene geometry; don't trust offset from client 2063 // TODO: determine position to sit at based on scene geometry; don't trust offset from client
1839 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it 2064 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
1840 2065
1841 // Is a sit target available? 2066 // part is the prim to sit on
1842 Vector3 avSitOffSet = part.SitTargetPosition; 2067 // offset is the world-ref vector distance from that prim center to the click-spot
1843 Quaternion avSitOrientation = part.SitTargetOrientation; 2068 // UUID is the UUID of the Avatar doing the clicking
1844 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 2069
1845 2070 m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation
1846 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 2071
1847 bool SitTargetisSet = 2072 // Is a sit target available?
1848 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && 2073 Vector3 avSitOffSet = part.SitTargetPosition;
1849 ( 2074 Quaternion avSitOrientation = part.SitTargetOrientation;
1850 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 1f // Valid Zero Rotation quaternion 2075
1851 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f && avSitOrientation.W == 0f // W-Z Mapping was invalid at one point 2076 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1852 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 0f // Invalid Quaternion 2077 // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
1853 ) 2078 Quaternion partRot;
1854 )); 2079// if (part.LinkNum == 1)
1855 2080// { // Root prim of linkset
1856 if (SitTargetisSet && SitTargetUnOccupied) 2081// partRot = part.ParentGroup.RootPart.RotationOffset;
1857 { 2082// }
1858 part.SitTargetAvatar = UUID; 2083// else
1859 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); 2084// { // single or child prim
1860 sitOrientation = avSitOrientation; 2085 partRot = part.GetWorldRotation();
1861 autopilot = false; 2086// }
1862 } 2087 Quaternion partIRot = Quaternion.Inverse(partRot);
1863 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 2088//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet);
1864 2089 // Sit analysis rewritten by KF 091125
1865 pos = part.AbsolutePosition + offset; 2090 if (SitTargetisSet) // scipted sit
1866 //if (Math.Abs(part.AbsolutePosition.Z - AbsolutePosition.Z) > 1) 2091 {
1867 //{ 2092 if (!part.IsOccupied)
1868 // offset = pos; 2093 {
1869 //autopilot = false; 2094//Console.WriteLine("Scripted, unoccupied");
1870 //} 2095 part.SitTargetAvatar = UUID; // set that Av will be on it
1871 if (m_physicsActor != null) 2096 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
1872 { 2097
1873 // If we're not using the client autopilot, we're immediately warping the avatar to the location 2098 Quaternion nrot = avSitOrientation;
1874 // We can remove the physicsActor until they stand up. 2099 if (!part.IsRoot)
1875 m_sitAvatarHeight = m_physicsActor.Size.Z;
1876
1877 if (autopilot)
1878 { 2100 {
1879 if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5) 2101 nrot = part.RotationOffset * avSitOrientation;
1880 {
1881 autopilot = false;
1882
1883 RemoveFromPhysicalScene();
1884 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight);
1885 }
1886 } 2102 }
1887 else 2103 sitOrientation = nrot; // Change rotatione to the scripted one
2104 OffsetRotation = nrot;
2105 autopilot = false; // Jump direct to scripted llSitPos()
2106 }
2107 else
2108 {
2109//Console.WriteLine("Scripted, occupied");
2110 return;
2111 }
2112 }
2113 else // Not Scripted
2114 {
2115 if ( (Math.Abs(offset.X) > 0.1f) || (Math.Abs(offset.Y) > 0.1f) ) // Changed 0.5M to 0.1M as they want to be able to sit close together
2116 {
2117 // large prim & offset, ignore if other Avs sitting
2118// offset.Z -= 0.05f;
2119 m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked
2120 autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point
2121
2122//Console.WriteLine(" offset ={0}", offset);
2123//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos);
2124//Console.WriteLine(" autopilotTarget={0}", autopilotTarget);
2125
2126 }
2127 else // small offset
2128 {
2129//Console.WriteLine("Small offset");
2130 if (!part.IsOccupied)
2131 {
2132 m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center
2133 autopilotTarget = part.AbsolutePosition;
2134//Console.WriteLine("UsSmall autopilotTarget={0}", autopilotTarget);
2135 }
2136 else return; // occupied small
2137 } // end large/small
2138 } // end Scripted/not
2139
2140 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2141
2142 cameraAtOffset = part.GetCameraAtOffset();
2143 cameraEyeOffset = part.GetCameraEyeOffset();
2144 forceMouselook = part.GetForceMouselook();
2145 if(cameraAtOffset == Vector3.Zero) cameraAtOffset = new Vector3(0f, 0f, 0.1f); //
2146 if(cameraEyeOffset == Vector3.Zero) cameraEyeOffset = new Vector3(0f, 0f, 0.1f); //
2147
2148 if (m_physicsActor != null)
2149 {
2150 // If we're not using the client autopilot, we're immediately warping the avatar to the location
2151 // We can remove the physicsActor until they stand up.
2152 m_sitAvatarHeight = m_physicsActor.Size.Z;
2153 if (autopilot)
2154 { // its not a scripted sit
2155// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
2156 if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 256.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 256.0f) )
1888 { 2157 {
2158 autopilot = false; // close enough
2159 m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup.
2160 Not using the part's position because returning the AV to the last known standing
2161 position is likely to be more friendly, isn't it? */
1889 RemoveFromPhysicalScene(); 2162 RemoveFromPhysicalScene();
1890 } 2163 Velocity = Vector3.Zero;
2164 AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target
2165 } // else the autopilot will get us close
2166 }
2167 else
2168 { // its a scripted sit
2169 m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup.
2170 I *am* using the part's position this time because we have no real idea how far away
2171 the avatar is from the sit target. */
2172 RemoveFromPhysicalScene();
2173 Velocity = Vector3.Zero;
1891 } 2174 }
1892
1893 cameraAtOffset = part.GetCameraAtOffset();
1894 cameraEyeOffset = part.GetCameraEyeOffset();
1895 forceMouselook = part.GetForceMouselook();
1896 } 2175 }
1897 2176 else return; // physactor is null!
1898 ControllingClient.SendSitResponse(targetID, offset, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); 2177
1899 m_requestedSitTargetUUID = targetID; 2178 Vector3 offsetr; // = offset * partIRot;
2179 // KF: In a linkset, offsetr needs to be relative to the group root! 091208
2180 // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot);
2181 // if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error.
2182 // { // Single, or Root prim of linkset, target is ClickOffset * RootRot
2183 //offsetr = offset * partIRot;
2184//
2185 // }
2186 // else
2187 // { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot)
2188 // offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) +
2189 // (offset * partRot);
2190 // }
2191
2192//Console.WriteLine(" ");
2193//Console.WriteLine("link number ={0}", part.LinkNum);
2194//Console.WriteLine("Prim offset ={0}", part.OffsetPosition );
2195//Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset);
2196//Console.WriteLine("Click offst ={0}", offset);
2197//Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation());
2198//Console.WriteLine("offsetr ={0}", offsetr);
2199//Console.WriteLine("Camera At ={0}", cameraAtOffset);
2200//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
2201
2202 //NOTE: SendSitResponse should be relative to the GROUP *NOT* THE PRIM if we're sitting on a child
2203 ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * part.RotationOffset) + part.OffsetPosition), sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
2204
2205 m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
1900 // This calls HandleAgentSit twice, once from here, and the client calls 2206 // This calls HandleAgentSit twice, once from here, and the client calls
1901 // HandleAgentSit itself after it gets to the location 2207 // HandleAgentSit itself after it gets to the location
1902 // It doesn't get to the location until we've moved them there though 2208 // It doesn't get to the location until we've moved them there though
1903 // which happens in HandleAgentSit :P 2209 // which happens in HandleAgentSit :P
1904 m_autopilotMoving = autopilot; 2210 m_autopilotMoving = autopilot;
1905 m_autoPilotTarget = pos; 2211 m_autoPilotTarget = autopilotTarget;
1906 m_sitAtAutoTarget = autopilot; 2212 m_sitAtAutoTarget = autopilot;
2213 m_initialSitTarget = autopilotTarget;
1907 if (!autopilot) 2214 if (!autopilot)
1908 HandleAgentSit(remoteClient, UUID); 2215 HandleAgentSit(remoteClient, UUID);
1909 } 2216 }
@@ -2198,47 +2505,130 @@ namespace OpenSim.Region.Framework.Scenes
2198 { 2505 {
2199 if (part != null) 2506 if (part != null)
2200 { 2507 {
2508//Console.WriteLine("Link #{0}, Rot {1}", part.LinkNum, part.GetWorldRotation());
2201 if (part.GetAvatarOnSitTarget() == UUID) 2509 if (part.GetAvatarOnSitTarget() == UUID)
2202 { 2510 {
2511//Console.WriteLine("Scripted Sit");
2512 // Scripted sit
2203 Vector3 sitTargetPos = part.SitTargetPosition; 2513 Vector3 sitTargetPos = part.SitTargetPosition;
2204 Quaternion sitTargetOrient = part.SitTargetOrientation; 2514 Quaternion sitTargetOrient = part.SitTargetOrientation;
2205
2206 //Quaternion vq = new Quaternion(sitTargetPos.X, sitTargetPos.Y+0.2f, sitTargetPos.Z+0.2f, 0);
2207 //Quaternion nq = new Quaternion(-sitTargetOrient.X, -sitTargetOrient.Y, -sitTargetOrient.Z, sitTargetOrient.w);
2208
2209 //Quaternion result = (sitTargetOrient * vq) * nq;
2210
2211 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z); 2515 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
2212 m_pos += SIT_TARGET_ADJUSTMENT; 2516 m_pos += SIT_TARGET_ADJUSTMENT;
2517 if (!part.IsRoot)
2518 {
2519 m_pos *= part.RotationOffset;
2520 }
2213 m_bodyRot = sitTargetOrient; 2521 m_bodyRot = sitTargetOrient;
2214 //Rotation = sitTargetOrient;
2215 m_parentPosition = part.AbsolutePosition; 2522 m_parentPosition = part.AbsolutePosition;
2216 2523 part.IsOccupied = true;
2217 //SendTerseUpdateToAllClients(); 2524 part.ParentGroup.AddAvatar(agentID);
2218 } 2525 }
2219 else 2526 else
2220 { 2527 {
2221 m_pos -= part.AbsolutePosition; 2528 // if m_avUnscriptedSitPos is zero then Av sits above center
2529 // Else Av sits at m_avUnscriptedSitPos
2530
2531 // Non-scripted sit by Kitto Flora 21Nov09
2532 // Calculate angle of line from prim to Av
2533 Quaternion partIRot;
2534// if (part.LinkNum == 1)
2535// { // Root prim of linkset
2536// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2537// }
2538// else
2539// { // single or child prim
2540 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2541// }
2542 Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos;
2543 float y_diff = (m_avInitialPos.Y - sitTargetPos.Y);
2544 float x_diff = ( m_avInitialPos.X - sitTargetPos.X);
2545 if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0
2546 if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0
2547 float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff);
2548 // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'.
2549 // Av sits at world euler <0,0, z>, translated by part rotation
2550 m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click
2551
2222 m_parentPosition = part.AbsolutePosition; 2552 m_parentPosition = part.AbsolutePosition;
2223 } 2553 part.IsOccupied = true;
2554 part.ParentGroup.AddAvatar(agentID);
2555 m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation
2556 (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center
2557 (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) +
2558 m_avUnscriptedSitPos; // adds click offset, if any
2559 //Set up raytrace to find top surface of prim
2560 Vector3 size = part.Scale;
2561 float mag = 2.0f; // 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
2562 Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
2563 Vector3 down = new Vector3(0f, 0f, -1f);
2564//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag);
2565 m_scene.PhysicsScene.RaycastWorld(
2566 start, // Vector3 position,
2567 down, // Vector3 direction,
2568 mag, // float length,
2569 SitAltitudeCallback); // retMethod
2570 } // end scripted/not
2224 } 2571 }
2225 else 2572 else // no Av
2226 { 2573 {
2227 return; 2574 return;
2228 } 2575 }
2229 } 2576 }
2230 m_parentID = m_requestedSitTargetID;
2231 2577
2578 //We want our offsets to reference the root prim, not the child we may have sat on
2579 if (!part.IsRoot)
2580 {
2581 m_parentID = part.ParentGroup.RootPart.LocalId;
2582 m_pos += part.OffsetPosition;
2583 }
2584 else
2585 {
2586 m_parentID = m_requestedSitTargetID;
2587 }
2588
2589 m_linkedPrim = part.UUID;
2590 if (part.GetAvatarOnSitTarget() != UUID)
2591 {
2592 m_offsetRotation = m_offsetRotation / part.RotationOffset;
2593 }
2232 Velocity = Vector3.Zero; 2594 Velocity = Vector3.Zero;
2233 RemoveFromPhysicalScene(); 2595 RemoveFromPhysicalScene();
2234
2235 Animator.TrySetMovementAnimation(sitAnimation); 2596 Animator.TrySetMovementAnimation(sitAnimation);
2236 SendAvatarDataToAllAgents(); 2597 SendAvatarDataToAllAgents();
2237 // This may seem stupid, but Our Full updates don't send avatar rotation :P
2238 // So we're also sending a terse update (which has avatar rotation)
2239 // [Update] We do now.
2240 //SendTerseUpdateToAllClients(); 2598 //SendTerseUpdateToAllClients();
2241 } 2599 }
2600
2601 public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal)
2602 {
2603 // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer
2604 // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height.
2605 if(hitYN)
2606 {
2607 // m_pos = Av offset from prim center to make look like on center
2608 // m_parentPosition = Actual center pos of prim
2609 // collisionPoint = spot on prim where we want to sit
2610 // collisionPoint.Z = global sit surface height
2611 SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
2612 Quaternion partIRot;
2613// if (part.LinkNum == 1)
2614/// { // Root prim of linkset
2615// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2616// }
2617// else
2618// { // single or child prim
2619 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2620// }
2621 if (m_initialSitTarget != null)
2622 {
2623 float offZ = collisionPoint.Z - m_initialSitTarget.Z;
2624 Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
2625 //Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
2626 m_pos += offset;
2627 // ControllingClient.SendClearFollowCamProperties(part.UUID);
2628 }
2629
2630 }
2631 } // End SitAltitudeCallback KF.
2242 2632
2243 /// <summary> 2633 /// <summary>
2244 /// Event handler for the 'Always run' setting on the client 2634 /// Event handler for the 'Always run' setting on the client
@@ -2268,12 +2658,13 @@ namespace OpenSim.Region.Framework.Scenes
2268 /// </summary> 2658 /// </summary>
2269 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 2659 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
2270 /// <param name="rotation">The direction in which this avatar should now face. 2660 /// <param name="rotation">The direction in which this avatar should now face.
2271 public void AddNewMovement(Vector3 vec, Quaternion rotation) 2661 public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging)
2272 { 2662 {
2273 if (m_isChildAgent) 2663 if (m_isChildAgent)
2274 { 2664 {
2275 // WHAT??? 2665 // WHAT???
2276 m_log.Debug("[SCENEPRESENCE]: AddNewMovement() called on child agent, making root agent!"); 2666 m_log.Debug("[SCENEPRESENCE]: AddNewMovement() called on child agent");
2667
2277 return; 2668 return;
2278 } 2669 }
2279 2670
@@ -2282,15 +2673,26 @@ namespace OpenSim.Region.Framework.Scenes
2282 Rotation = rotation; 2673 Rotation = rotation;
2283 Vector3 direc = vec * rotation; 2674 Vector3 direc = vec * rotation;
2284 direc.Normalize(); 2675 direc.Normalize();
2676 PhysicsActor actor = m_physicsActor;
2677
2678 if (actor.Flying != m_flyingOld) // add for fly velocity control
2679 {
2680 m_flyingOld = actor.Flying; // add for fly velocity control
2681 if (!actor.Flying) m_wasFlying = true; // add for fly velocity control
2682 }
2683
2684 if (m_physicsActor.IsColliding == true) m_wasFlying = false; // add for fly velocity control
2685
2686 if ((vec.Z == 0f) && !actor.Flying) direc.Z = 0f; // Prevent camera WASD up.
2285 2687
2286 direc *= 0.03f * 128f * m_speedModifier; 2688 direc *= 0.03f * 128f * m_speedModifier;
2287 2689
2288 PhysicsActor actor = m_physicsActor;
2289 if (actor != null) 2690 if (actor != null)
2290 { 2691 {
2291 if (actor.Flying) 2692 if (actor.Flying)
2292 { 2693 {
2293 direc *= 4.0f; 2694// rm speed mod direc *= 4.0f;
2695 direc *= 5.2f; // for speed mod
2294 //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); 2696 //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
2295 //bool colliding = (m_physicsActor.IsColliding==true); 2697 //bool colliding = (m_physicsActor.IsColliding==true);
2296 //if (controlland) 2698 //if (controlland)
@@ -2303,22 +2705,34 @@ namespace OpenSim.Region.Framework.Scenes
2303 // m_log.Info("[AGENT]: Stop FLying"); 2705 // m_log.Info("[AGENT]: Stop FLying");
2304 //} 2706 //}
2305 } 2707 }
2708 if (Animator.m_falling && m_wasFlying) // if falling from flying, disable motion add
2709 {
2710 direc *= 0.0f;
2711 }
2712 /* This jumping section removed to SPA
2306 else if (!actor.Flying && actor.IsColliding) 2713 else if (!actor.Flying && actor.IsColliding)
2307 { 2714 {
2308 if (direc.Z > 2.0f) 2715 if (direc.Z > 2.0f)
2309 { 2716 {
2310 direc.Z *= 3.0f; 2717 if(m_animator.m_animTickJump == -1)
2311 2718 {
2312 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored. 2719 direc.Z *= 3.0f; // jump
2313 Animator.TrySetMovementAnimation("PREJUMP"); 2720 }
2314 Animator.TrySetMovementAnimation("JUMP"); 2721 else
2722 {
2723 direc.Z *= 0.1f; // prejump
2724 }
2725 / * Animations are controlled via GetMovementAnimation() in ScenePresenceAnimator.cs
2726 Animator.TrySetMovementAnimation("PREJUMP");
2727 Animator.TrySetMovementAnimation("JUMP");
2728 * /
2315 } 2729 }
2316 } 2730 } */
2317 } 2731 }
2318 2732
2319 // TODO: Add the force instead of only setting it to support multiple forces per frame? 2733 // TODO: Add the force instead of only setting it to support multiple forces per frame?
2320 m_forceToApply = direc; 2734 m_forceToApply = direc;
2321 2735 m_isNudging = Nudging;
2322 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); 2736 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
2323 } 2737 }
2324 2738
@@ -2367,6 +2781,9 @@ namespace OpenSim.Region.Framework.Scenes
2367 2781
2368 CheckForSignificantMovement(); // sends update to the modules. 2782 CheckForSignificantMovement(); // sends update to the modules.
2369 } 2783 }
2784
2785 //Sending prim updates AFTER the avatar terse updates are sent
2786 SendPrimUpdates();
2370 } 2787 }
2371 2788
2372 #endregion 2789 #endregion
@@ -3182,6 +3599,7 @@ namespace OpenSim.Region.Framework.Scenes
3182 m_callbackURI = cAgent.CallbackURI; 3599 m_callbackURI = cAgent.CallbackURI;
3183 3600
3184 m_pos = cAgent.Position; 3601 m_pos = cAgent.Position;
3602
3185 m_velocity = cAgent.Velocity; 3603 m_velocity = cAgent.Velocity;
3186 m_CameraCenter = cAgent.Center; 3604 m_CameraCenter = cAgent.Center;
3187 m_CameraAtAxis = cAgent.AtAxis; 3605 m_CameraAtAxis = cAgent.AtAxis;
@@ -3270,17 +3688,45 @@ namespace OpenSim.Region.Framework.Scenes
3270 /// </summary> 3688 /// </summary>
3271 public override void UpdateMovement() 3689 public override void UpdateMovement()
3272 { 3690 {
3273 if (m_forceToApply.HasValue) 3691 if (Animator!=null) // add for jumping
3274 { 3692 { // add for jumping
3275 Vector3 force = m_forceToApply.Value; 3693 // if (!m_animator.m_jumping) // add for jumping
3276 3694 // { // add for jumping
3277 m_updateflag = true;
3278 3695
3279 Velocity = force; 3696 if (m_forceToApply.HasValue) // this section realigned
3697 {
3280 3698
3281 m_forceToApply = null; 3699 Vector3 force = m_forceToApply.Value;
3282 } 3700 m_updateflag = true;
3283 } 3701if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
3702 Velocity = force;
3703//Console.WriteLine("UM1 {0}", Velocity);
3704 m_forceToApply = null;
3705 }
3706 else
3707 {
3708 if (m_isNudging)
3709 {
3710 Vector3 force = Vector3.Zero;
3711
3712 m_updateflag = true;
3713if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
3714 Velocity = force;
3715//Console.WriteLine("UM2 {0}", Velocity);
3716 m_isNudging = false;
3717 m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND"
3718 }
3719 else // add for jumping
3720 { // add for jumping
3721 Vector3 force = Vector3.Zero; // add for jumping
3722if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
3723//Console.WriteLine("UM3 {0}", Velocity);
3724 Velocity = force; // add for jumping
3725 }
3726 }
3727 // } // end realign
3728 } // add for jumping
3729 } // add for jumping
3284 3730
3285 /// <summary> 3731 /// <summary>
3286 /// Adds a physical representation of the avatar to the Physics plugin 3732 /// Adds a physical representation of the avatar to the Physics plugin
@@ -3294,10 +3740,8 @@ namespace OpenSim.Region.Framework.Scenes
3294 3740
3295 Vector3 pVec = AbsolutePosition; 3741 Vector3 pVec = AbsolutePosition;
3296 3742
3297 // Old bug where the height was in centimeters instead of meters 3743 m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec,
3298 m_physicsActor = scene.AddAvatar(LocalId, Firstname + "." + Lastname, pVec,
3299 new Vector3(0f, 0f, m_appearance.AvatarHeight), isFlying); 3744 new Vector3(0f, 0f, m_appearance.AvatarHeight), isFlying);
3300
3301 scene.AddPhysicsActorTaint(m_physicsActor); 3745 scene.AddPhysicsActorTaint(m_physicsActor);
3302 //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; 3746 //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
3303 m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; 3747 m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
@@ -3321,18 +3765,29 @@ namespace OpenSim.Region.Framework.Scenes
3321 { 3765 {
3322 if (e == null) 3766 if (e == null)
3323 return; 3767 return;
3324 3768
3325 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 3769 // The Physics Scene will send (spam!) updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3326 // The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3327 // as of this comment the interval is set in AddToPhysicalScene 3770 // as of this comment the interval is set in AddToPhysicalScene
3328 if (Animator!=null) 3771 if (Animator!=null)
3329 Animator.UpdateMovementAnimations(); 3772 {
3773 if (m_updateCount > 0) //KF: DO NOT call UpdateMovementAnimations outside of the m_updateCount wrapper,
3774 { // else its will lock out other animation changes, like ground sit.
3775 Animator.UpdateMovementAnimations();
3776 m_updateCount--;
3777 }
3778 }
3330 3779
3331 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 3780 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
3332 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 3781 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
3333 3782
3334 CollisionPlane = Vector4.UnitW; 3783 CollisionPlane = Vector4.UnitW;
3335 3784
3785 if (m_lastColCount != coldata.Count)
3786 {
3787 m_updateCount = UPDATE_COUNT;
3788 m_lastColCount = coldata.Count;
3789 }
3790
3336 if (coldata.Count != 0 && Animator != null) 3791 if (coldata.Count != 0 && Animator != null)
3337 { 3792 {
3338 switch (Animator.CurrentMovementAnimation) 3793 switch (Animator.CurrentMovementAnimation)
@@ -3362,6 +3817,148 @@ namespace OpenSim.Region.Framework.Scenes
3362 } 3817 }
3363 } 3818 }
3364 3819
3820 List<uint> thisHitColliders = new List<uint>();
3821 List<uint> endedColliders = new List<uint>();
3822 List<uint> startedColliders = new List<uint>();
3823
3824 foreach (uint localid in coldata.Keys)
3825 {
3826 thisHitColliders.Add(localid);
3827 if (!m_lastColliders.Contains(localid))
3828 {
3829 startedColliders.Add(localid);
3830 }
3831 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
3832 }
3833
3834 // calculate things that ended colliding
3835 foreach (uint localID in m_lastColliders)
3836 {
3837 if (!thisHitColliders.Contains(localID))
3838 {
3839 endedColliders.Add(localID);
3840 }
3841 }
3842 //add the items that started colliding this time to the last colliders list.
3843 foreach (uint localID in startedColliders)
3844 {
3845 m_lastColliders.Add(localID);
3846 }
3847 // remove things that ended colliding from the last colliders list
3848 foreach (uint localID in endedColliders)
3849 {
3850 m_lastColliders.Remove(localID);
3851 }
3852
3853 // do event notification
3854 if (startedColliders.Count > 0)
3855 {
3856 ColliderArgs StartCollidingMessage = new ColliderArgs();
3857 List<DetectedObject> colliding = new List<DetectedObject>();
3858 foreach (uint localId in startedColliders)
3859 {
3860 if (localId == 0)
3861 continue;
3862
3863 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3864 string data = "";
3865 if (obj != null)
3866 {
3867 DetectedObject detobj = new DetectedObject();
3868 detobj.keyUUID = obj.UUID;
3869 detobj.nameStr = obj.Name;
3870 detobj.ownerUUID = obj.OwnerID;
3871 detobj.posVector = obj.AbsolutePosition;
3872 detobj.rotQuat = obj.GetWorldRotation();
3873 detobj.velVector = obj.Velocity;
3874 detobj.colliderType = 0;
3875 detobj.groupUUID = obj.GroupID;
3876 colliding.Add(detobj);
3877 }
3878 }
3879
3880 if (colliding.Count > 0)
3881 {
3882 StartCollidingMessage.Colliders = colliding;
3883
3884 foreach (SceneObjectGroup att in Attachments)
3885 Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage);
3886 }
3887 }
3888
3889 if (endedColliders.Count > 0)
3890 {
3891 ColliderArgs EndCollidingMessage = new ColliderArgs();
3892 List<DetectedObject> colliding = new List<DetectedObject>();
3893 foreach (uint localId in endedColliders)
3894 {
3895 if (localId == 0)
3896 continue;
3897
3898 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3899 string data = "";
3900 if (obj != null)
3901 {
3902 DetectedObject detobj = new DetectedObject();
3903 detobj.keyUUID = obj.UUID;
3904 detobj.nameStr = obj.Name;
3905 detobj.ownerUUID = obj.OwnerID;
3906 detobj.posVector = obj.AbsolutePosition;
3907 detobj.rotQuat = obj.GetWorldRotation();
3908 detobj.velVector = obj.Velocity;
3909 detobj.colliderType = 0;
3910 detobj.groupUUID = obj.GroupID;
3911 colliding.Add(detobj);
3912 }
3913 }
3914
3915 if (colliding.Count > 0)
3916 {
3917 EndCollidingMessage.Colliders = colliding;
3918
3919 foreach (SceneObjectGroup att in Attachments)
3920 Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage);
3921 }
3922 }
3923
3924 if (thisHitColliders.Count > 0)
3925 {
3926 ColliderArgs CollidingMessage = new ColliderArgs();
3927 List<DetectedObject> colliding = new List<DetectedObject>();
3928 foreach (uint localId in thisHitColliders)
3929 {
3930 if (localId == 0)
3931 continue;
3932
3933 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3934 string data = "";
3935 if (obj != null)
3936 {
3937 DetectedObject detobj = new DetectedObject();
3938 detobj.keyUUID = obj.UUID;
3939 detobj.nameStr = obj.Name;
3940 detobj.ownerUUID = obj.OwnerID;
3941 detobj.posVector = obj.AbsolutePosition;
3942 detobj.rotQuat = obj.GetWorldRotation();
3943 detobj.velVector = obj.Velocity;
3944 detobj.colliderType = 0;
3945 detobj.groupUUID = obj.GroupID;
3946 colliding.Add(detobj);
3947 }
3948 }
3949
3950 if (colliding.Count > 0)
3951 {
3952 CollidingMessage.Colliders = colliding;
3953
3954 lock (m_attachments)
3955 {
3956 foreach (SceneObjectGroup att in m_attachments)
3957 Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
3958 }
3959 }
3960 }
3961
3365 if (m_invulnerable) 3962 if (m_invulnerable)
3366 return; 3963 return;
3367 3964
@@ -3446,6 +4043,10 @@ namespace OpenSim.Region.Framework.Scenes
3446 { 4043 {
3447 lock (m_attachments) 4044 lock (m_attachments)
3448 { 4045 {
4046 // This may be true when the attachment comes back
4047 // from serialization after login. Clear it.
4048 gobj.IsDeleted = false;
4049
3449 m_attachments.Add(gobj); 4050 m_attachments.Add(gobj);
3450 } 4051 }
3451 } 4052 }
@@ -3787,6 +4388,39 @@ namespace OpenSim.Region.Framework.Scenes
3787 return; 4388 return;
3788 } 4389 }
3789 4390
4391 XmlDocument doc = new XmlDocument();
4392 string stateData = String.Empty;
4393
4394 IAttachmentsService attServ = m_scene.RequestModuleInterface<IAttachmentsService>();
4395 if (attServ != null)
4396 {
4397 m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service");
4398 stateData = attServ.Get(ControllingClient.AgentId.ToString());
4399 if (stateData != String.Empty)
4400 {
4401 try
4402 {
4403 doc.LoadXml(stateData);
4404 }
4405 catch { }
4406 }
4407 }
4408
4409 Dictionary<UUID, string> itemData = new Dictionary<UUID, string>();
4410
4411 XmlNodeList nodes = doc.GetElementsByTagName("Attachment");
4412 if (nodes.Count > 0)
4413 {
4414 foreach (XmlNode n in nodes)
4415 {
4416 XmlElement elem = (XmlElement)n;
4417 string itemID = elem.GetAttribute("ItemID");
4418 string xml = elem.InnerXml;
4419
4420 itemData[new UUID(itemID)] = xml;
4421 }
4422 }
4423
3790 List<AvatarAttachment> attachments = m_appearance.GetAttachments(); 4424 List<AvatarAttachment> attachments = m_appearance.GetAttachments();
3791 foreach (AvatarAttachment attach in attachments) 4425 foreach (AvatarAttachment attach in attachments)
3792 { 4426 {
@@ -3807,7 +4441,30 @@ namespace OpenSim.Region.Framework.Scenes
3807 4441
3808 try 4442 try
3809 { 4443 {
3810 m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p); 4444 string xmlData;
4445 XmlDocument d = new XmlDocument();
4446 UUID asset;
4447 if (itemData.TryGetValue(itemID, out xmlData))
4448 {
4449 d.LoadXml(xmlData);
4450 m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", itemID);
4451
4452 // Rez from inventory
4453 asset
4454 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, d);
4455
4456 }
4457 else
4458 {
4459 // Rez from inventory (with a null doc to let
4460 // CHANGED_OWNER happen)
4461 asset
4462 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, null);
4463 }
4464
4465 m_log.InfoFormat(
4466 "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2}",
4467 p, itemID, asset);
3811 } 4468 }
3812 catch (Exception e) 4469 catch (Exception e)
3813 { 4470 {
@@ -3840,6 +4497,15 @@ namespace OpenSim.Region.Framework.Scenes
3840 m_reprioritization_called = false; 4497 m_reprioritization_called = false;
3841 } 4498 }
3842 } 4499 }
4500
4501 private Vector3 Quat2Euler(Quaternion rot){
4502 float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) ,
4503 (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z)));
4504 float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W)));
4505 float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) ,
4506 (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z)));
4507 return(new Vector3(x,y,z));
4508 }
3843 4509
3844 public void SaveChangedAttachments() 4510 public void SaveChangedAttachments()
3845 { 4511 {
@@ -3863,5 +4529,30 @@ namespace OpenSim.Region.Framework.Scenes
3863 } 4529 }
3864 } 4530 }
3865 } 4531 }
4532
4533 private void CheckLandingPoint(ref Vector3 pos)
4534 {
4535 // Never constrain lures
4536 if ((TeleportFlags & TeleportFlags.ViaLure) != 0)
4537 return;
4538
4539 if (m_scene.RegionInfo.EstateSettings.AllowDirectTeleport)
4540 return;
4541
4542 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
4543
4544 if (land.LandData.LandingType == (byte)LandingType.LandingPoint &&
4545 land.LandData.UserLocation != Vector3.Zero &&
4546 land.LandData.OwnerID != m_uuid &&
4547 (!m_scene.Permissions.IsGod(m_uuid)) &&
4548 (!m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid)))
4549 {
4550 float curr = Vector3.Distance(AbsolutePosition, pos);
4551 if (Vector3.Distance(land.LandData.UserLocation, pos) < curr)
4552 pos = land.LandData.UserLocation;
4553 else
4554 ControllingClient.SendAlertMessage("Can't teleport closer to destination");
4555 }
4556 }
3866 } 4557 }
3867} 4558}
diff --git a/OpenSim/Region/Framework/Scenes/SceneViewer.cs b/OpenSim/Region/Framework/Scenes/SceneViewer.cs
index 7c067ca..1f4ec96 100644
--- a/OpenSim/Region/Framework/Scenes/SceneViewer.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneViewer.cs
@@ -106,7 +106,7 @@ namespace OpenSim.Region.Framework.Scenes
106 g.ScheduleFullUpdateToAvatar(m_presence); 106 g.ScheduleFullUpdateToAvatar(m_presence);
107 } 107 }
108 108
109 while (m_partsUpdateQueue.Count > 0) 109 while (m_partsUpdateQueue.Count != null && m_partsUpdateQueue.Count > 0)
110 { 110 {
111 SceneObjectPart part = m_partsUpdateQueue.Dequeue(); 111 SceneObjectPart part = m_partsUpdateQueue.Dequeue();
112 112
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index fcf7e0c..9174070 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -102,7 +102,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
102 sceneObject.AddPart(part); 102 sceneObject.AddPart(part);
103 part.LinkNum = linkNum; 103 part.LinkNum = linkNum;
104 part.TrimPermissions(); 104 part.TrimPermissions();
105 part.StoreUndoState(); 105 part.StoreUndoState(UndoType.STATE_ALL);
106 reader.Close(); 106 reader.Close();
107 sr.Close(); 107 sr.Close();
108 } 108 }
@@ -236,7 +236,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
236 if (originalLinkNum != 0) 236 if (originalLinkNum != 0)
237 part.LinkNum = originalLinkNum; 237 part.LinkNum = originalLinkNum;
238 238
239 part.StoreUndoState(); 239 part.StoreUndoState(UndoType.STATE_ALL);
240 reader.Close(); 240 reader.Close();
241 sr.Close(); 241 sr.Close();
242 } 242 }
@@ -345,6 +345,8 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
345 m_SOPXmlProcessors.Add("PayPrice2", ProcessPayPrice2); 345 m_SOPXmlProcessors.Add("PayPrice2", ProcessPayPrice2);
346 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3); 346 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3);
347 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4); 347 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4);
348
349 m_SOPXmlProcessors.Add("Buoyancy", ProcessBuoyancy);
348 #endregion 350 #endregion
349 351
350 #region TaskInventoryXmlProcessors initialization 352 #region TaskInventoryXmlProcessors initialization
@@ -734,6 +736,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
734 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty); 736 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty);
735 } 737 }
736 738
739 private static void ProcessBuoyancy(SceneObjectPart obj, XmlTextReader reader)
740 {
741 obj.Buoyancy = (int)reader.ReadElementContentAsFloat("Buoyancy", String.Empty);
742 }
743
737 #endregion 744 #endregion
738 745
739 #region TaskInventoryXmlProcessors 746 #region TaskInventoryXmlProcessors
@@ -1216,6 +1223,8 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1216 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString()); 1223 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString());
1217 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString()); 1224 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString());
1218 1225
1226 writer.WriteElementString("Buoyancy", sop.Buoyancy.ToString());
1227
1219 writer.WriteEndElement(); 1228 writer.WriteEndElement();
1220 } 1229 }
1221 1230
@@ -1500,12 +1509,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1500 { 1509 {
1501 TaskInventoryDictionary tinv = new TaskInventoryDictionary(); 1510 TaskInventoryDictionary tinv = new TaskInventoryDictionary();
1502 1511
1503 if (reader.IsEmptyElement)
1504 {
1505 reader.Read();
1506 return tinv;
1507 }
1508
1509 reader.ReadStartElement(name, String.Empty); 1512 reader.ReadStartElement(name, String.Empty);
1510 1513
1511 while (reader.Name == "TaskInventoryItem") 1514 while (reader.Name == "TaskInventoryItem")
@@ -1548,12 +1551,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1548 1551
1549 PrimitiveBaseShape shape = new PrimitiveBaseShape(); 1552 PrimitiveBaseShape shape = new PrimitiveBaseShape();
1550 1553
1551 if (reader.IsEmptyElement)
1552 {
1553 reader.Read();
1554 return shape;
1555 }
1556
1557 reader.ReadStartElement(name, String.Empty); // Shape 1554 reader.ReadStartElement(name, String.Empty); // Shape
1558 1555
1559 string nodeName = string.Empty; 1556 string nodeName = string.Empty;
diff --git a/OpenSim/Region/Framework/Scenes/UndoState.cs b/OpenSim/Region/Framework/Scenes/UndoState.cs
index 55e407e..f71b507 100644
--- a/OpenSim/Region/Framework/Scenes/UndoState.cs
+++ b/OpenSim/Region/Framework/Scenes/UndoState.cs
@@ -27,48 +27,125 @@
27 27
28using OpenMetaverse; 28using OpenMetaverse;
29using OpenSim.Region.Framework.Interfaces; 29using OpenSim.Region.Framework.Interfaces;
30using System;
30 31
31namespace OpenSim.Region.Framework.Scenes 32namespace OpenSim.Region.Framework.Scenes
32{ 33{
34 [Flags]
35 public enum UndoType
36 {
37 STATE_PRIM_POSITION = 1,
38 STATE_PRIM_ROTATION = 2,
39 STATE_PRIM_SCALE = 4,
40 STATE_PRIM_ALL = 7,
41 STATE_GROUP_POSITION = 8,
42 STATE_GROUP_ROTATION = 16,
43 STATE_GROUP_SCALE = 32,
44 STATE_GROUP_ALL = 56,
45 STATE_ALL = 63
46 }
47
33 public class UndoState 48 public class UndoState
34 { 49 {
35 public Vector3 Position = Vector3.Zero; 50 public Vector3 Position = Vector3.Zero;
36 public Vector3 Scale = Vector3.Zero; 51 public Vector3 Scale = Vector3.Zero;
37 public Quaternion Rotation = Quaternion.Identity; 52 public Quaternion Rotation = Quaternion.Identity;
53 public Vector3 GroupPosition = Vector3.Zero;
54 public Quaternion GroupRotation = Quaternion.Identity;
55 public Vector3 GroupScale = Vector3.Zero;
56 public DateTime LastUpdated = DateTime.Now;
57 public UndoType Type;
38 58
39 public UndoState(SceneObjectPart part) 59 public UndoState(SceneObjectPart part, UndoType type)
40 { 60 {
61 Type = type;
41 if (part != null) 62 if (part != null)
42 { 63 {
43 if (part.ParentID == 0) 64 if (part.ParentID == 0)
44 { 65 {
45 Position = part.ParentGroup.AbsolutePosition; 66 GroupScale = part.ParentGroup.RootPart.Shape.Scale;
67
68 //FUBAR WARNING: Do NOT get the group's absoluteposition here
69 //or you'll experience a loop and/or a stack issue
70 GroupPosition = part.ParentGroup.RootPart.AbsolutePosition;
71 GroupRotation = part.ParentGroup.GroupRotation;
72 Position = part.ParentGroup.RootPart.AbsolutePosition;
46 Rotation = part.RotationOffset; 73 Rotation = part.RotationOffset;
47 Scale = part.Shape.Scale; 74 Scale = part.Shape.Scale;
75 LastUpdated = DateTime.Now;
48 } 76 }
49 else 77 else
50 { 78 {
79 GroupScale = part.Shape.Scale;
80
81 //FUBAR WARNING: Do NOT get the group's absoluteposition here
82 //or you'll experience a loop and/or a stack issue
83 GroupPosition = part.ParentGroup.RootPart.AbsolutePosition;
84 GroupRotation = part.ParentGroup.Rotation;
51 Position = part.OffsetPosition; 85 Position = part.OffsetPosition;
52 Rotation = part.RotationOffset; 86 Rotation = part.RotationOffset;
53 Scale = part.Shape.Scale; 87 Scale = part.Shape.Scale;
88 LastUpdated = DateTime.Now;
54 } 89 }
55 } 90 }
56 } 91 }
57 92 public void Merge(UndoState last)
93 {
94 if ((Type & UndoType.STATE_GROUP_POSITION) == 0 || ((last.Type & UndoType.STATE_GROUP_POSITION) >= (Type & UndoType.STATE_GROUP_POSITION)))
95 {
96 GroupPosition = last.GroupPosition;
97 Position = last.Position;
98 }
99 if ((Type & UndoType.STATE_GROUP_SCALE) == 0 || ((last.Type & UndoType.STATE_GROUP_SCALE) >= (Type & UndoType.STATE_GROUP_SCALE)))
100 {
101 GroupScale = last.GroupScale;
102 Scale = last.Scale;
103 }
104 if ((Type & UndoType.STATE_GROUP_ROTATION) == 0 || ((last.Type & UndoType.STATE_GROUP_ROTATION) >= (Type & UndoType.STATE_GROUP_ROTATION)))
105 {
106 GroupRotation = last.GroupRotation;
107 Rotation = last.Rotation;
108 }
109 if ((Type & UndoType.STATE_PRIM_POSITION) == 0 || ((last.Type & UndoType.STATE_PRIM_POSITION) >= (Type & UndoType.STATE_PRIM_POSITION)))
110 {
111 Position = last.Position;
112 }
113 if ((Type & UndoType.STATE_PRIM_SCALE) == 0 || ((last.Type & UndoType.STATE_PRIM_SCALE) >= (Type & UndoType.STATE_PRIM_SCALE)))
114 {
115 Scale = last.Scale;
116 }
117 if ((Type & UndoType.STATE_PRIM_ROTATION) == 0 || ((last.Type & UndoType.STATE_PRIM_ROTATION) >= (Type & UndoType.STATE_PRIM_ROTATION)))
118 {
119 Rotation = last.Rotation;
120 }
121 Type = Type | last.Type;
122 }
123 public bool Compare(UndoState undo)
124 {
125 if (undo == null || Position == null) return false;
126 if (undo.Position == Position && undo.Rotation == Rotation && undo.Scale == Scale && undo.GroupPosition == GroupPosition && undo.GroupScale == GroupScale && undo.GroupRotation == GroupRotation)
127 {
128 return true;
129 }
130 else
131 {
132 return false;
133 }
134 }
58 public bool Compare(SceneObjectPart part) 135 public bool Compare(SceneObjectPart part)
59 { 136 {
60 if (part != null) 137 if (part != null)
61 { 138 {
62 if (part.ParentID == 0) 139 if (part.ParentID == 0)
63 { 140 {
64 if (Position == part.ParentGroup.AbsolutePosition && Rotation == part.ParentGroup.Rotation) 141 if (Position == part.ParentGroup.RootPart.AbsolutePosition && Rotation == part.ParentGroup.Rotation && GroupPosition == part.ParentGroup.RootPart.AbsolutePosition && part.ParentGroup.Rotation == GroupRotation && part.Shape.Scale == GroupScale)
65 return true; 142 return true;
66 else 143 else
67 return false; 144 return false;
68 } 145 }
69 else 146 else
70 { 147 {
71 if (Position == part.OffsetPosition && Rotation == part.RotationOffset && Scale == part.Shape.Scale) 148 if (Position == part.OffsetPosition && Rotation == part.RotationOffset && Scale == part.Shape.Scale && GroupPosition == part.ParentGroup.RootPart.AbsolutePosition && part.ParentGroup.Rotation == GroupRotation && part.Shape.Scale == GroupScale)
72 return true; 149 return true;
73 else 150 else
74 return false; 151 return false;
@@ -78,62 +155,70 @@ namespace OpenSim.Region.Framework.Scenes
78 return false; 155 return false;
79 } 156 }
80 157
81 public void PlaybackState(SceneObjectPart part) 158 private void RestoreState(SceneObjectPart part)
82 { 159 {
160 bool GroupChange = false;
161 if ((Type & UndoType.STATE_GROUP_POSITION) != 0
162 || (Type & UndoType.STATE_GROUP_ROTATION) != 0
163 || (Type & UndoType.STATE_GROUP_SCALE) != 0)
164 {
165 GroupChange = true;
166 }
167
83 if (part != null) 168 if (part != null)
84 { 169 {
85 part.Undoing = true; 170 part.Undoing = true;
86 171
87 if (part.ParentID == 0) 172 if (part.ParentID == 0 && GroupChange == false)
88 { 173 {
89 if (Position != Vector3.Zero) 174 if (Position != Vector3.Zero)
90 part.ParentGroup.AbsolutePosition = Position; 175
91 part.RotationOffset = Rotation; 176 part.ParentGroup.UpdateSinglePosition(Position, part.LocalId);
177 part.ParentGroup.UpdateSingleRotation(Rotation, part.LocalId);
92 if (Scale != Vector3.Zero) 178 if (Scale != Vector3.Zero)
93 part.Resize(Scale); 179 part.Resize(Scale);
94 part.ParentGroup.ScheduleGroupForTerseUpdate(); 180 part.ParentGroup.ScheduleGroupForTerseUpdate();
95 } 181 }
96 else 182 else
97 { 183 {
98 if (Position != Vector3.Zero) 184 if (GroupChange)
99 part.OffsetPosition = Position; 185 {
100 part.UpdateRotation(Rotation); 186 part.ParentGroup.RootPart.Undoing = true;
101 if (Scale != Vector3.Zero) 187 if (GroupPosition != Vector3.Zero)
102 part.Resize(Scale); part.ScheduleTerseUpdate(); 188 {
189 //Calculate the scale...
190 Vector3 gs = part.Shape.Scale;
191 float scale = GroupScale.Z / gs.Z;
192
193 //Scale first since it can affect our position
194 part.ParentGroup.GroupResize(gs * scale, part.LocalId);
195 part.ParentGroup.AbsolutePosition = GroupPosition;
196 part.ParentGroup.UpdateGroupRotationR(GroupRotation);
197
198 }
199 part.ParentGroup.RootPart.Undoing = false;
200 }
201 else
202 {
203 if (Position != Vector3.Zero) //We can use this for all the updates since all are set
204 {
205 part.OffsetPosition = Position;
206 part.UpdateRotation(Rotation);
207 part.Resize(Scale); part.ScheduleTerseUpdate();
208 }
209 }
103 } 210 }
104 part.Undoing = false; 211 part.Undoing = false;
105 212
106 } 213 }
107 } 214 }
215 public void PlaybackState(SceneObjectPart part)
216 {
217 RestoreState(part);
218 }
108 public void PlayfwdState(SceneObjectPart part) 219 public void PlayfwdState(SceneObjectPart part)
109 { 220 {
110 if (part != null) 221 RestoreState(part);
111 {
112 part.Undoing = true;
113
114 if (part.ParentID == 0)
115 {
116 if (Position != Vector3.Zero)
117 part.ParentGroup.AbsolutePosition = Position;
118 if (Rotation != Quaternion.Identity)
119 part.UpdateRotation(Rotation);
120 if (Scale != Vector3.Zero)
121 part.Resize(Scale);
122 part.ParentGroup.ScheduleGroupForTerseUpdate();
123 }
124 else
125 {
126 if (Position != Vector3.Zero)
127 part.OffsetPosition = Position;
128 if (Rotation != Quaternion.Identity)
129 part.UpdateRotation(Rotation);
130 if (Scale != Vector3.Zero)
131 part.Resize(Scale);
132 part.ScheduleTerseUpdate();
133 }
134 part.Undoing = false;
135
136 }
137 } 222 }
138 } 223 }
139 public class LandUndoState 224 public class LandUndoState
@@ -161,3 +246,4 @@ namespace OpenSim.Region.Framework.Scenes
161 } 246 }
162 } 247 }
163} 248}
249
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index 77b1535..fdfbc78 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -86,10 +86,6 @@ namespace OpenSim.Region.Framework.Scenes
86 /// <param name="assetUuids">The assets gathered</param> 86 /// <param name="assetUuids">The assets gathered</param>
87 public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids) 87 public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids)
88 { 88 {
89 // avoid infinite loops
90 if (assetUuids.ContainsKey(assetUuid))
91 return;
92
93 try 89 try
94 { 90 {
95 assetUuids[assetUuid] = assetType; 91 assetUuids[assetUuid] = assetType;
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index 88db20e..4045507 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -813,6 +813,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
813 public event ObjectOwner OnObjectOwner; 813 public event ObjectOwner OnObjectOwner;
814 public event DirPlacesQuery OnDirPlacesQuery; 814 public event DirPlacesQuery OnDirPlacesQuery;
815 public event DirFindQuery OnDirFindQuery; 815 public event DirFindQuery OnDirFindQuery;
816 public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy;
816 public event DirLandQuery OnDirLandQuery; 817 public event DirLandQuery OnDirLandQuery;
817 public event DirPopularQuery OnDirPopularQuery; 818 public event DirPopularQuery OnDirPopularQuery;
818 public event DirClassifiedQuery OnDirClassifiedQuery; 819 public event DirClassifiedQuery OnDirClassifiedQuery;
@@ -829,7 +830,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
829 public event ClassifiedInfoRequest OnClassifiedInfoRequest; 830 public event ClassifiedInfoRequest OnClassifiedInfoRequest;
830 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate; 831 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate;
831 public event ClassifiedDelete OnClassifiedDelete; 832 public event ClassifiedDelete OnClassifiedDelete;
832 public event ClassifiedDelete OnClassifiedGodDelete; 833 public event ClassifiedGodDelete OnClassifiedGodDelete;
833 public event EventNotificationAddRequest OnEventNotificationAddRequest; 834 public event EventNotificationAddRequest OnEventNotificationAddRequest;
834 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest; 835 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest;
835 public event EventGodDelete OnEventGodDelete; 836 public event EventGodDelete OnEventGodDelete;
@@ -883,6 +884,11 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
883 884
884 public void Close() 885 public void Close()
885 { 886 {
887 Close(true);
888 }
889
890 public void Close(bool sendStop)
891 {
886 Disconnect(); 892 Disconnect();
887 } 893 }
888 894
@@ -937,7 +943,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
937 943
938 } 944 }
939 945
940 public void SendKillObject(ulong regionHandle, uint localID) 946 public void SendKillObject(ulong regionHandle, List<uint> localID)
941 { 947 {
942 948
943 } 949 }
diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
index 42efd67..4f1097e 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
@@ -563,7 +563,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
563 563
564 public Hashtable FreeSwitchSLVoiceGetPreloginHTTPHandler(Hashtable request) 564 public Hashtable FreeSwitchSLVoiceGetPreloginHTTPHandler(Hashtable request)
565 { 565 {
566 m_log.Debug("[FreeSwitchVoice]: FreeSwitchSLVoiceGetPreloginHTTPHandler called"); 566// m_log.Debug("[FreeSwitchVoice] FreeSwitchSLVoiceGetPreloginHTTPHandler called");
567 567
568 Hashtable response = new Hashtable(); 568 Hashtable response = new Hashtable();
569 response["content_type"] = "text/xml"; 569 response["content_type"] = "text/xml";
@@ -714,7 +714,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
714 714
715 public Hashtable FreeSwitchSLVoiceSigninHTTPHandler(Hashtable request) 715 public Hashtable FreeSwitchSLVoiceSigninHTTPHandler(Hashtable request)
716 { 716 {
717 m_log.Debug("[FreeSwitchVoice]: FreeSwitchSLVoiceSigninHTTPHandler called"); 717 //m_log.Debug("[FreeSwitchVoice] FreeSwitchSLVoiceSigninHTTPHandler called");
718// string requestbody = (string)request["body"]; 718// string requestbody = (string)request["body"];
719// string uri = (string)request["uri"]; 719// string uri = (string)request["uri"];
720// string contenttype = (string)request["content-type"]; 720// string contenttype = (string)request["content-type"];
@@ -885,4 +885,4 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
885 885
886 #endregion 886 #endregion
887 } 887 }
888} \ No newline at end of file 888}
diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
index 534bf92..ae902eb 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
@@ -190,7 +190,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
190 break; 190 break;
191 } 191 }
192 192
193 m_vivoxVoiceAccountApi = String.Format("http://{0}/api2", m_vivoxServer); 193 m_vivoxVoiceAccountApi = String.Format("https://{0}/api2", m_vivoxServer);
194 194
195 // Admin interface required values 195 // Admin interface required values
196 if (String.IsNullOrEmpty(m_vivoxServer) || 196 if (String.IsNullOrEmpty(m_vivoxServer) ||
@@ -749,7 +749,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
749 } 749 }
750 750
751 751
752 private static readonly string m_vivoxLoginPath = "http://{0}/api2/viv_signin.php?userid={1}&pwd={2}"; 752 private static readonly string m_vivoxLoginPath = "https://{0}/api2/viv_signin.php?userid={1}&pwd={2}";
753 753
754 /// <summary> 754 /// <summary>
755 /// Perform administrative login for Vivox. 755 /// Perform administrative login for Vivox.
@@ -762,7 +762,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
762 } 762 }
763 763
764 764
765 private static readonly string m_vivoxLogoutPath = "http://{0}/api2/viv_signout.php?auth_token={1}"; 765 private static readonly string m_vivoxLogoutPath = "https://{0}/api2/viv_signout.php?auth_token={1}";
766 766
767 /// <summary> 767 /// <summary>
768 /// Perform administrative logout for Vivox. 768 /// Perform administrative logout for Vivox.
@@ -774,7 +774,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
774 } 774 }
775 775
776 776
777 private static readonly string m_vivoxGetAccountPath = "http://{0}/api2/viv_get_acct.php?auth_token={1}&user_name={2}"; 777 private static readonly string m_vivoxGetAccountPath = "https://{0}/api2/viv_get_acct.php?auth_token={1}&user_name={2}";
778 778
779 /// <summary> 779 /// <summary>
780 /// Retrieve account information for the specified user. 780 /// Retrieve account information for the specified user.
@@ -787,7 +787,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
787 } 787 }
788 788
789 789
790 private static readonly string m_vivoxNewAccountPath = "http://{0}/api2/viv_adm_acct_new.php?username={1}&pwd={2}&auth_token={3}"; 790 private static readonly string m_vivoxNewAccountPath = "https://{0}/api2/viv_adm_acct_new.php?username={1}&pwd={2}&auth_token={3}";
791 791
792 /// <summary> 792 /// <summary>
793 /// Creates a new account. 793 /// Creates a new account.
@@ -802,7 +802,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
802 } 802 }
803 803
804 804
805 private static readonly string m_vivoxPasswordPath = "http://{0}/api2/viv_adm_password.php?user_name={1}&new_pwd={2}&auth_token={3}"; 805 private static readonly string m_vivoxPasswordPath = "https://{0}/api2/viv_adm_password.php?user_name={1}&new_pwd={2}&auth_token={3}";
806 806
807 /// <summary> 807 /// <summary>
808 /// Change the user's password. 808 /// Change the user's password.
@@ -814,7 +814,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
814 } 814 }
815 815
816 816
817 private static readonly string m_vivoxChannelPath = "http://{0}/api2/viv_chan_mod.php?mode={1}&chan_name={2}&auth_token={3}"; 817 private static readonly string m_vivoxChannelPath = "https://{0}/api2/viv_chan_mod.php?mode={1}&chan_name={2}&auth_token={3}";
818 818
819 /// <summary> 819 /// <summary>
820 /// Create a channel. 820 /// Create a channel.
@@ -888,7 +888,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
888 return false; 888 return false;
889 } 889 }
890 890
891 private static readonly string m_vivoxChannelSearchPath = "http://{0}/api2/viv_chan_search.php?cond_channame={1}&auth_token={2}"; 891 private static readonly string m_vivoxChannelSearchPath = "https://{0}/api2/viv_chan_search.php?cond_channame={1}&auth_token={2}";
892 892
893 /// <summary> 893 /// <summary>
894 /// Retrieve a channel. 894 /// Retrieve a channel.
@@ -1032,7 +1032,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
1032 return false; 1032 return false;
1033 } 1033 }
1034 1034
1035 // private static readonly string m_vivoxChannelById = "http://{0}/api2/viv_chan_mod.php?mode={1}&chan_id={2}&auth_token={3}"; 1035 // private static readonly string m_vivoxChannelById = "https://{0}/api2/viv_chan_mod.php?mode={1}&chan_id={2}&auth_token={3}";
1036 1036
1037 // private XmlElement VivoxGetChannelById(string parent, string channelid) 1037 // private XmlElement VivoxGetChannelById(string parent, string channelid)
1038 // { 1038 // {
@@ -1056,7 +1056,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
1056 /// In this case the call handles parent and description as optional values. 1056 /// In this case the call handles parent and description as optional values.
1057 /// </summary> 1057 /// </summary>
1058 1058
1059 private static readonly string m_vivoxChannelDel = "http://{0}/api2/viv_chan_mod.php?mode={1}&chan_id={2}&auth_token={3}"; 1059 private static readonly string m_vivoxChannelDel = "https://{0}/api2/viv_chan_mod.php?mode={1}&chan_id={2}&auth_token={3}";
1060 1060
1061 private XmlElement VivoxDeleteChannel(string parent, string channelid) 1061 private XmlElement VivoxDeleteChannel(string parent, string channelid)
1062 { 1062 {
@@ -1072,7 +1072,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
1072 /// Return information on channels in the given directory 1072 /// Return information on channels in the given directory
1073 /// </summary> 1073 /// </summary>
1074 1074
1075 private static readonly string m_vivoxChannelSearch = "http://{0}/api2/viv_chan_search.php?&cond_chanparent={1}&auth_token={2}"; 1075 private static readonly string m_vivoxChannelSearch = "https://{0}/api2/viv_chan_search.php?&cond_chanparent={1}&auth_token={2}";
1076 1076
1077 private XmlElement VivoxListChildren(string channelid) 1077 private XmlElement VivoxListChildren(string channelid)
1078 { 1078 {
diff --git a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs
index 32659c8..11c87f8 100644
--- a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs
@@ -42,17 +42,22 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcRouterModule
42 public class XmlRpcRouter : IRegionModule, IXmlRpcRouter 42 public class XmlRpcRouter : IRegionModule, IXmlRpcRouter
43 { 43 {
44 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45 45 private bool m_enabled = false;
46 public void Initialise(Scene scene, IConfigSource config) 46 public void Initialise(Scene scene, IConfigSource config)
47 { 47 {
48 IConfig startupConfig = config.Configs["Startup"]; 48 IConfig startupConfig = config.Configs["XMLRPC"];
49 if (startupConfig == null) 49 if (startupConfig == null)
50 return; 50 return;
51 51
52 if (startupConfig.GetString("XmlRpcRouterModule", 52 if (startupConfig.GetString("XmlRpcRouterModule",
53 "XmlRpcRouterModule") == "XmlRpcRouterModule") 53 "") == "XmlRpcRouterModule")
54 { 54 {
55 scene.RegisterModuleInterface<IXmlRpcRouter>(this); 55 scene.RegisterModuleInterface<IXmlRpcRouter>(this);
56 m_enabled = true;
57 }
58 else
59 {
60 m_enabled = false;
56 } 61 }
57 } 62 }
58 63
@@ -76,7 +81,10 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcRouterModule
76 81
77 public void RegisterNewReceiver(IScriptModule scriptEngine, UUID channel, UUID objectID, UUID itemID, string uri) 82 public void RegisterNewReceiver(IScriptModule scriptEngine, UUID channel, UUID objectID, UUID itemID, string uri)
78 { 83 {
79 scriptEngine.PostScriptEvent(itemID, "xmlrpc_uri", new Object[] {uri}); 84 if (m_enabled)
85 {
86 scriptEngine.PostScriptEvent(itemID, "xmlrpc_uri", new Object[] { uri });
87 }
80 } 88 }
81 89
82 public void ScriptRemoved(UUID itemID) 90 public void ScriptRemoved(UUID itemID)
diff --git a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs
index b84a34d..d469548 100644
--- a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs
+++ b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs
@@ -838,6 +838,10 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
838 if (module != null) 838 if (module != null)
839 module.BuyObject(remoteClient, categoryID, localID, saleType, salePrice); 839 module.BuyObject(remoteClient, categoryID, localID, saleType, salePrice);
840 } 840 }
841
842 public void MoveMoney(UUID fromAgentID, UUID toAgentID, int amount, string text)
843 {
844 }
841 } 845 }
842 846
843 public enum TransactionType : int 847 public enum TransactionType : int
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index 15bc1b7..f07ad67 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
@@ -156,7 +156,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
156#pragma warning disable 67 156#pragma warning disable 67
157 public event Action<IClientAPI> OnLogout; 157 public event Action<IClientAPI> OnLogout;
158 public event ObjectPermissions OnObjectPermissions; 158 public event ObjectPermissions OnObjectPermissions;
159 159 public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy;
160 public event MoneyTransferRequest OnMoneyTransferRequest; 160 public event MoneyTransferRequest OnMoneyTransferRequest;
161 public event ParcelBuy OnParcelBuy; 161 public event ParcelBuy OnParcelBuy;
162 public event Action<IClientAPI> OnConnectionClosed; 162 public event Action<IClientAPI> OnConnectionClosed;
@@ -360,7 +360,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
360 public event ClassifiedInfoRequest OnClassifiedInfoRequest; 360 public event ClassifiedInfoRequest OnClassifiedInfoRequest;
361 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate; 361 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate;
362 public event ClassifiedDelete OnClassifiedDelete; 362 public event ClassifiedDelete OnClassifiedDelete;
363 public event ClassifiedDelete OnClassifiedGodDelete; 363 public event ClassifiedGodDelete OnClassifiedGodDelete;
364 364
365 public event EventNotificationAddRequest OnEventNotificationAddRequest; 365 public event EventNotificationAddRequest OnEventNotificationAddRequest;
366 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest; 366 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest;
@@ -519,7 +519,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
519 519
520 } 520 }
521 521
522 public virtual void SendKillObject(ulong regionHandle, uint localID) 522 public virtual void SendKillObject(ulong regionHandle, List<uint> localID)
523 { 523 {
524 } 524 }
525 525
@@ -840,6 +840,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC
840 840
841 public void Close() 841 public void Close()
842 { 842 {
843 Close(true);
844 }
845
846 public void Close(bool sendStop)
847 {
843 } 848 }
844 849
845 public void Start() 850 public void Start()
diff --git a/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs b/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs
index 421da36..2563361 100644
--- a/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs
+++ b/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs
@@ -386,7 +386,7 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
386 m_scene.ForEachClient(delegate(IClientAPI controller) 386 m_scene.ForEachClient(delegate(IClientAPI controller)
387 { 387 {
388 controller.SendKillObject(m_scene.RegionInfo.RegionHandle, 388 controller.SendKillObject(m_scene.RegionInfo.RegionHandle,
389 selectedTree.LocalId); 389 new List<uint>() { selectedTree.LocalId });
390 }); 390 });
391 } 391 }
392 else 392 else
@@ -727,7 +727,7 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
727 m_scene.ForEachClient(delegate(IClientAPI controller) 727 m_scene.ForEachClient(delegate(IClientAPI controller)
728 { 728 {
729 controller.SendKillObject(m_scene.RegionInfo.RegionHandle, 729 controller.SendKillObject(m_scene.RegionInfo.RegionHandle,
730 selectedTree.LocalId); 730 new List<uint>() { selectedTree.LocalId });
731 }); 731 });
732 732
733 break; 733 break;
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..1bce760
--- /dev/null
+++ b/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs
@@ -0,0 +1,1437 @@
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 jumping = false; // add for jumping
94 private bool m_iscolliding = false;
95 private bool m_iscollidingGround = false;
96 private bool m_wascolliding = false;
97 private bool m_wascollidingGround = false;
98 private bool m_iscollidingObj = false;
99 private bool m_alwaysRun = false;
100 private bool m_hackSentFall = false;
101 private bool m_hackSentFly = false;
102 private int m_requestedUpdateFrequency = 0;
103 private Vector3 m_taintPosition = Vector3.Zero;
104 public uint m_localID = 0;
105 public bool m_returnCollisions = false;
106 // taints and their non-tainted counterparts
107 public bool m_isPhysical = false; // the current physical status
108 public bool m_tainted_isPhysical = false; // set when the physical status is tainted (false=not existing in physics engine, true=existing)
109 public float MinimumGroundFlightOffset = 3f;
110
111 private float m_tainted_CAPSULE_LENGTH; // set when the capsule length changes.
112 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
113
114
115 private float m_buoyancy = 0f;
116
117 // private CollisionLocker ode;
118
119 private string m_name = String.Empty;
120
121 private bool[] m_colliderarr = new bool[11];
122 private bool[] m_colliderGroundarr = new bool[11];
123
124 // Default we're a Character
125 private CollisionCategories m_collisionCategories = (CollisionCategories.Character);
126
127 // Default, Collide with Other Geometries, spaces, bodies and characters.
128 private CollisionCategories m_collisionFlags = (CollisionCategories.Geom
129 | CollisionCategories.Space
130 | CollisionCategories.Body
131 | CollisionCategories.Character
132 | CollisionCategories.Land);
133 public IntPtr Body = IntPtr.Zero;
134 private OdeScene _parent_scene;
135 public IntPtr Shell = IntPtr.Zero;
136 public IntPtr Amotor = IntPtr.Zero;
137 public d.Mass ShellMass;
138 public bool collidelock = false;
139
140 public int m_eventsubscription = 0;
141 private CollisionEventUpdate CollisionEventsThisFrame = new CollisionEventUpdate();
142
143 // unique UUID of this character object
144 public UUID m_uuid;
145 public bool bad = false;
146 private Object m_syncRoot = new Object();
147
148 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)
149 {
150 m_uuid = UUID.Random();
151
152 if (pos.IsFinite())
153 {
154 if (pos.Z > 9999999f)
155 {
156 pos.Z = parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
157 }
158 if (pos.Z < -90000f)
159 {
160 pos.Z = parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
161 }
162 _position = pos;
163 m_taintPosition.X = pos.X;
164 m_taintPosition.Y = pos.Y;
165 m_taintPosition.Z = pos.Z;
166 }
167 else
168 {
169 _position = new Vector3(((float)_parent_scene.WorldExtents.X * 0.5f), ((float)_parent_scene.WorldExtents.Y * 0.5f), parent_scene.GetTerrainHeightAtXY(128f, 128f) + 10f);
170 m_taintPosition.X = _position.X;
171 m_taintPosition.Y = _position.Y;
172 m_taintPosition.Z = _position.Z;
173 m_log.Warn("[PHYSICS]: Got NaN Position on Character Create");
174 }
175
176 _parent_scene = parent_scene;
177
178 PID_D = pid_d;
179 PID_P = pid_p;
180 CAPSULE_RADIUS = capsule_radius;
181 m_tensor = tensor;
182 m_density = density;
183 heightFudgeFactor = height_fudge_factor;
184 walkDivisor = walk_divisor;
185 runDivisor = rundivisor;
186
187 // m_StandUpRotation =
188 // new d.Matrix3(0.5f, 0.7071068f, 0.5f, -0.7071068f, 0f, 0.7071068f, 0.5f, -0.7071068f,
189 // 0.5f);
190
191 for (int i = 0; i < 11; i++)
192 {
193 m_colliderarr[i] = false;
194 }
195 CAPSULE_LENGTH = (size.Z * 1.15f) - CAPSULE_RADIUS * 2.0f;
196 //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
197 m_tainted_CAPSULE_LENGTH = CAPSULE_LENGTH;
198
199 m_isPhysical = false; // current status: no ODE information exists
200 m_tainted_isPhysical = true; // new tainted status: need to create ODE information
201
202 _parent_scene.AddPhysicsActorTaint(this);
203
204 m_name = avName;
205 }
206
207 public override int PhysicsActorType
208 {
209 get { return (int) ActorTypes.Agent; }
210 set { return; }
211 }
212
213 /// <summary>
214 /// If this is set, the avatar will move faster
215 /// </summary>
216 public override bool SetAlwaysRun
217 {
218 get { return m_alwaysRun; }
219 set { m_alwaysRun = value; }
220 }
221
222 public override uint LocalID
223 {
224 set { m_localID = value; }
225 }
226
227 public override bool Grabbed
228 {
229 set { return; }
230 }
231
232 public override bool Selected
233 {
234// set { return; }
235 set { jumping = value; } // add for jumping flag
236 }
237
238 public override float Buoyancy
239 {
240 get { return m_buoyancy; }
241 set { m_buoyancy = value; }
242 }
243
244 public override bool FloatOnWater
245 {
246 set { return; }
247 }
248
249 public override bool IsPhysical
250 {
251 get { return false; }
252 set { return; }
253 }
254
255 public override bool ThrottleUpdates
256 {
257 get { return false; }
258 set { return; }
259 }
260
261 public override bool Flying
262 {
263 get { return flying; }
264 set { flying = value; }
265 }
266
267 /// <summary>
268 /// Returns if the avatar is colliding in general.
269 /// This includes the ground and objects and avatar.
270 /// </summary>
271 public override bool IsColliding
272 {
273//#@ get { return m_iscolliding; }
274 get { //##
275//Console.WriteLine(">>>>>>>>>>>> IC get = {0}", m_iscolliding); //##
276 return m_iscolliding; } //##
277 set
278 {
279 int i;
280 int truecount = 0;
281 int falsecount = 0;
282
283 if (m_colliderarr.Length >= 10)
284 {
285 for (i = 0; i < 10; i++)
286 {
287 m_colliderarr[i] = m_colliderarr[i + 1];
288 }
289 }
290 m_colliderarr[10] = value;
291
292 for (i = 0; i < 11; i++)
293 {
294 if (m_colliderarr[i])
295 {
296 truecount++;
297 }
298 else
299 {
300 falsecount++;
301 }
302 }
303
304 // Equal truecounts and false counts means we're colliding with something.
305
306 if (falsecount > 1.2*truecount)
307 {
308 m_iscolliding = false;
309 }
310 else
311 {
312 m_iscolliding = true;
313 }
314// ## Console.WriteLine("IC SET = {0} t{1} f{2} i {3}", value, truecount, falsecount, m_iscolliding);
315 if (m_wascolliding != m_iscolliding)
316 {
317 //base.SendCollisionUpdate(new CollisionEventUpdate());
318 }
319 m_wascolliding = m_iscolliding;
320 }
321 }
322
323 /// <summary>
324 /// Returns if an avatar is colliding with the ground
325 /// </summary>
326 public override bool CollidingGround
327 {
328 get { return m_iscollidingGround; }
329 set
330 {
331 // Collisions against the ground are not really reliable
332 // So, to get a consistant value we have to average the current result over time
333 // Currently we use 1 second = 10 calls to this.
334 int i;
335 int truecount = 0;
336 int falsecount = 0;
337
338 if (m_colliderGroundarr.Length >= 10)
339 {
340 for (i = 0; i < 10; i++)
341 {
342 m_colliderGroundarr[i] = m_colliderGroundarr[i + 1];
343 }
344 }
345 m_colliderGroundarr[10] = value;
346
347 for (i = 0; i < 11; i++)
348 {
349 if (m_colliderGroundarr[i])
350 {
351 truecount++;
352 }
353 else
354 {
355 falsecount++;
356 }
357 }
358
359 // Equal truecounts and false counts means we're colliding with something.
360
361 if (falsecount > 1.2*truecount)
362 {
363 m_iscollidingGround = false;
364 }
365 else
366 {
367 m_iscollidingGround = true;
368 }
369 if (m_wascollidingGround != m_iscollidingGround)
370 {
371 //base.SendCollisionUpdate(new CollisionEventUpdate());
372 }
373 m_wascollidingGround = m_iscollidingGround;
374 }
375 }
376
377 /// <summary>
378 /// Returns if the avatar is colliding with an object
379 /// </summary>
380 public override bool CollidingObj
381 {
382 get { return m_iscollidingObj; }
383 set
384 {
385 m_iscollidingObj = value;
386 if (value)
387 m_pidControllerActive = false;
388 else
389 m_pidControllerActive = true;
390 }
391 }
392
393 /// <summary>
394 /// turn the PID controller on or off.
395 /// The PID Controller will turn on all by itself in many situations
396 /// </summary>
397 /// <param name="status"></param>
398 public void SetPidStatus(bool status)
399 {
400 m_pidControllerActive = status;
401 }
402
403 public override bool Stopped
404 {
405 get { return _zeroFlag; }
406 }
407
408 /// <summary>
409 /// This 'puts' an avatar somewhere in the physics space.
410 /// Not really a good choice unless you 'know' it's a good
411 /// spot otherwise you're likely to orbit the avatar.
412 /// </summary>
413 public override Vector3 Position
414 {
415 get { return _position; }
416 set
417 {
418 if (Body == IntPtr.Zero || Shell == IntPtr.Zero)
419 {
420 if (value.IsFinite())
421 {
422 if (value.Z > 9999999f)
423 {
424 value.Z = _parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
425 }
426 if (value.Z < -90000f)
427 {
428 value.Z = _parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
429 }
430
431 _position.X = value.X;
432 _position.Y = value.Y;
433 _position.Z = value.Z;
434
435 m_taintPosition.X = value.X;
436 m_taintPosition.Y = value.Y;
437 m_taintPosition.Z = value.Z;
438 _parent_scene.AddPhysicsActorTaint(this);
439 }
440 else
441 {
442 m_log.Warn("[PHYSICS]: Got a NaN Position from Scene on a Character");
443 }
444 }
445 }
446 }
447
448 public override Vector3 RotationalVelocity
449 {
450 get { return m_rotationalVelocity; }
451 set { m_rotationalVelocity = value; }
452 }
453
454 /// <summary>
455 /// This property sets the height of the avatar only. We use the height to make sure the avatar stands up straight
456 /// and use it to offset landings properly
457 /// </summary>
458 public override Vector3 Size
459 {
460 get { return new Vector3(CAPSULE_RADIUS * 2, CAPSULE_RADIUS * 2, CAPSULE_LENGTH); }
461 set
462 {
463 if (value.IsFinite())
464 {
465 m_pidControllerActive = true;
466
467 Vector3 SetSize = value;
468 m_tainted_CAPSULE_LENGTH = (SetSize.Z*1.15f) - CAPSULE_RADIUS*2.0f;
469 //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
470
471 Velocity = Vector3.Zero;
472 m_taintPosition = _position; // update the stale taint position
473 _parent_scene.AddPhysicsActorTaint(this);
474 }
475 else
476 {
477 m_log.Warn("[PHYSICS]: Got a NaN Size from Scene on a Character");
478 }
479 }
480 }
481
482 private void AlignAvatarTiltWithCurrentDirectionOfMovement(Vector3 movementVector)
483 {
484 movementVector.Z = 0f;
485 float magnitude = (float)Math.Sqrt((double)(movementVector.X * movementVector.X + movementVector.Y * movementVector.Y));
486 if (magnitude < 0.1f) return;
487
488 // normalize the velocity vector
489 float invMagnitude = 1.0f / magnitude;
490 movementVector.X *= invMagnitude;
491 movementVector.Y *= invMagnitude;
492
493 // if we change the capsule heading too often, the capsule can fall down
494 // therefore we snap movement vector to just 1 of 4 predefined directions (ne, nw, se, sw),
495 // meaning only 4 possible capsule tilt orientations
496 if (movementVector.X > 0)
497 {
498 // east
499 if (movementVector.Y > 0)
500 {
501 // northeast
502 movementVector.X = (float)Math.Sqrt(2.0);
503 movementVector.Y = (float)Math.Sqrt(2.0);
504 }
505 else
506 {
507 // southeast
508 movementVector.X = (float)Math.Sqrt(2.0);
509 movementVector.Y = -(float)Math.Sqrt(2.0);
510 }
511 }
512 else
513 {
514 // west
515 if (movementVector.Y > 0)
516 {
517 // northwest
518 movementVector.X = -(float)Math.Sqrt(2.0);
519 movementVector.Y = (float)Math.Sqrt(2.0);
520 }
521 else
522 {
523 // southwest
524 movementVector.X = -(float)Math.Sqrt(2.0);
525 movementVector.Y = -(float)Math.Sqrt(2.0);
526 }
527 }
528
529
530 // movementVector.Z is zero
531
532 // calculate tilt components based on desired amount of tilt and current (snapped) heading.
533 // the "-" sign is to force the tilt to be OPPOSITE the direction of movement.
534 float xTiltComponent = -movementVector.X * m_tiltMagnitudeWhenProjectedOnXYPlane;
535 float yTiltComponent = -movementVector.Y * m_tiltMagnitudeWhenProjectedOnXYPlane;
536
537 //m_log.Debug("[PHYSICS] changing avatar tilt");
538 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, xTiltComponent);
539 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, xTiltComponent); // must be same as lowstop, else a different, spurious tilt is introduced
540 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, yTiltComponent);
541 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, yTiltComponent); // same as lowstop
542 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, 0f);
543 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0f); // same as lowstop
544 }
545
546 /// <summary>
547 /// This creates the Avatar's physical Surrogate at the position supplied
548 /// </summary>
549 /// <param name="npositionX"></param>
550 /// <param name="npositionY"></param>
551 /// <param name="npositionZ"></param>
552
553 // WARNING: This MUST NOT be called outside of ProcessTaints, else we can have unsynchronized access
554 // to ODE internals. ProcessTaints is called from within thread-locked Simulate(), so it is the only
555 // place that is safe to call this routine AvatarGeomAndBodyCreation.
556 private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ, float tensor)
557 {
558 //CAPSULE_LENGTH = -5;
559 //CAPSULE_RADIUS = -5;
560 int dAMotorEuler = 1;
561 _parent_scene.waitForSpaceUnlock(_parent_scene.space);
562 if (CAPSULE_LENGTH <= 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_LENGTH = 0.01f;
566
567 }
568
569 if (CAPSULE_RADIUS <= 0)
570 {
571 m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
572 CAPSULE_RADIUS = 0.01f;
573
574 }
575
576 if(Shell != IntPtr.Zero)
577 {
578 try
579 {
580 d.GeomDestroy(Shell);
581 }
582 catch (System.AccessViolationException)
583 {
584 m_log.Error("[PHYSICS]: PrimGeom dead");
585 }
586 // Remove any old entries
587//string tShell;
588//_parent_scene.geom_name_map.TryGetValue(Shell, out tShell);
589//Console.WriteLine("**** Remove {0}", tShell);
590 if(_parent_scene.geom_name_map.ContainsKey(Shell)) _parent_scene.geom_name_map.Remove(Shell);
591 if(_parent_scene.actor_name_map.ContainsKey(Shell)) _parent_scene.actor_name_map.Remove(Shell);
592 }
593
594 Shell = d.CreateCapsule(_parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH);
595 _parent_scene.geom_name_map[Shell] = m_name;
596 _parent_scene.actor_name_map[Shell] = (PhysicsActor)this;
597//Console.WriteLine("**** Create {2} Dicts: actor={0} name={1} height={3} rad={4}", _parent_scene.actor_name_map.Count, _parent_scene.geom_name_map.Count, m_name, CAPSULE_LENGTH, CAPSULE_RADIUS);
598
599 d.GeomSetCategoryBits(Shell, (int)m_collisionCategories);
600 d.GeomSetCollideBits(Shell, (int)m_collisionFlags);
601
602 d.MassSetCapsuleTotal(out ShellMass, m_mass, 2, CAPSULE_RADIUS, CAPSULE_LENGTH);
603 Body = d.BodyCreate(_parent_scene.world);
604 d.BodySetPosition(Body, npositionX, npositionY, npositionZ);
605
606 _position.X = npositionX;
607 _position.Y = npositionY;
608 _position.Z = npositionZ;
609
610
611 m_taintPosition.X = npositionX;
612 m_taintPosition.Y = npositionY;
613 m_taintPosition.Z = npositionZ;
614
615 d.BodySetMass(Body, ref ShellMass);
616 d.Matrix3 m_caprot;
617 // 90 Stand up on the cap of the capped cyllinder
618 if (_parent_scene.IsAvCapsuleTilted)
619 {
620 d.RFromAxisAndAngle(out m_caprot, 1, 0, 1, (float)(Math.PI / 2));
621 }
622 else
623 {
624 d.RFromAxisAndAngle(out m_caprot, 0, 0, 1, (float)(Math.PI / 2));
625 }
626
627
628 d.GeomSetRotation(Shell, ref m_caprot);
629 d.BodySetRotation(Body, ref m_caprot);
630
631 d.GeomSetBody(Shell, Body);
632
633
634 // The purpose of the AMotor here is to keep the avatar's physical
635 // surrogate from rotating while moving
636 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero);
637 d.JointAttach(Amotor, Body, IntPtr.Zero);
638 d.JointSetAMotorMode(Amotor, dAMotorEuler);
639 d.JointSetAMotorNumAxes(Amotor, 3);
640 d.JointSetAMotorAxis(Amotor, 0, 0, 1, 0, 0);
641 d.JointSetAMotorAxis(Amotor, 1, 0, 0, 1, 0);
642 d.JointSetAMotorAxis(Amotor, 2, 0, 0, 0, 1);
643 d.JointSetAMotorAngle(Amotor, 0, 0);
644 d.JointSetAMotorAngle(Amotor, 1, 0);
645 d.JointSetAMotorAngle(Amotor, 2, 0);
646
647 // These lowstops and high stops are effectively (no wiggle room)
648 if (_parent_scene.IsAvCapsuleTilted)
649 {
650 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, -0.000000000001f);
651 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0.000000000001f);
652 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, -0.000000000001f);
653 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0.000000000001f);
654 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0.000000000001f);
655 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0.000000000001f);
656 }
657 else
658 {
659 #region Documentation of capsule motor LowStop and HighStop parameters
660 // Intentionally introduce some tilt into the capsule by setting
661 // the motor stops to small epsilon values. This small tilt prevents
662 // the capsule from falling into the terrain; a straight-up capsule
663 // (with -0..0 motor stops) falls into the terrain for reasons yet
664 // to be comprehended in their entirety.
665 #endregion
666 AlignAvatarTiltWithCurrentDirectionOfMovement(Vector3.Zero);
667 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, 0.08f);
668 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0f);
669 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, 0.08f);
670 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0.08f); // must be same as lowstop, else a different, spurious tilt is introduced
671 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0f); // same as lowstop
672 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0.08f); // same as lowstop
673 }
674
675 // Fudge factor is 1f by default, we're setting it to 0. We don't want it to Fudge or the
676 // capped cyllinder will fall over
677 d.JointSetAMotorParam(Amotor, (int)dParam.FudgeFactor, 0f);
678 d.JointSetAMotorParam(Amotor, (int)dParam.FMax, tensor);
679
680 //d.Matrix3 bodyrotation = d.BodyGetRotation(Body);
681 //d.QfromR(
682 //d.Matrix3 checkrotation = new d.Matrix3(0.7071068,0.5, -0.7071068,
683 //
684 //m_log.Info("[PHYSICSAV]: Rotation: " + bodyrotation.M00 + " : " + bodyrotation.M01 + " : " + bodyrotation.M02 + " : " + bodyrotation.M10 + " : " + bodyrotation.M11 + " : " + bodyrotation.M12 + " : " + bodyrotation.M20 + " : " + bodyrotation.M21 + " : " + bodyrotation.M22);
685 //standupStraight();
686 }
687
688 //
689 /// <summary>
690 /// Uses the capped cyllinder volume formula to calculate the avatar's mass.
691 /// This may be used in calculations in the scene/scenepresence
692 /// </summary>
693 public override float Mass
694 {
695 get
696 {
697 float AVvolume = (float) (Math.PI*Math.Pow(CAPSULE_RADIUS, 2)*CAPSULE_LENGTH);
698 return m_density*AVvolume;
699 }
700 }
701 public override void link(PhysicsActor obj)
702 {
703
704 }
705
706 public override void delink()
707 {
708
709 }
710
711 public override void LockAngularMotion(Vector3 axis)
712 {
713
714 }
715
716// This code is very useful. Written by DanX0r. We're just not using it right now.
717// Commented out to prevent a warning.
718//
719// private void standupStraight()
720// {
721// // The purpose of this routine here is to quickly stabilize the Body while it's popped up in the air.
722// // The amotor needs a few seconds to stabilize so without it, the avatar shoots up sky high when you
723// // change appearance and when you enter the simulator
724// // After this routine is done, the amotor stabilizes much quicker
725// d.Vector3 feet;
726// d.Vector3 head;
727// d.BodyGetRelPointPos(Body, 0.0f, 0.0f, -1.0f, out feet);
728// d.BodyGetRelPointPos(Body, 0.0f, 0.0f, 1.0f, out head);
729// float posture = head.Z - feet.Z;
730
731// // restoring force proportional to lack of posture:
732// float servo = (2.5f - posture) * POSTURE_SERVO;
733// d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, servo, 0.0f, 0.0f, 1.0f);
734// d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, -servo, 0.0f, 0.0f, -1.0f);
735// //d.Matrix3 bodyrotation = d.BodyGetRotation(Body);
736// //m_log.Info("[PHYSICSAV]: Rotation: " + bodyrotation.M00 + " : " + bodyrotation.M01 + " : " + bodyrotation.M02 + " : " + bodyrotation.M10 + " : " + bodyrotation.M11 + " : " + bodyrotation.M12 + " : " + bodyrotation.M20 + " : " + bodyrotation.M21 + " : " + bodyrotation.M22);
737// }
738
739 public override Vector3 Force
740 {
741 get { return _target_velocity; }
742 set { return; }
743 }
744
745 public override int VehicleType
746 {
747 get { return 0; }
748 set { return; }
749 }
750
751 public override void VehicleFloatParam(int param, float value)
752 {
753
754 }
755
756 public override void VehicleVectorParam(int param, Vector3 value)
757 {
758
759 }
760
761 public override void VehicleRotationParam(int param, Quaternion rotation)
762 {
763
764 }
765
766 public override void VehicleFlags(int flags, bool remove)
767 {
768 }
769
770 public override void SetVolumeDetect(int param)
771 {
772
773 }
774
775 public override Vector3 CenterOfMass
776 {
777 get { return Vector3.Zero; }
778 }
779
780 public override Vector3 GeometricCenter
781 {
782 get { return Vector3.Zero; }
783 }
784
785 public override PrimitiveBaseShape Shape
786 {
787 set { return; }
788 }
789
790 public override Vector3 Velocity
791 {
792 get {
793 // There's a problem with Vector3.Zero! Don't Use it Here!
794 if (_zeroFlag)
795 return Vector3.Zero;
796 m_lastUpdateSent = false;
797 return _velocity;
798 }
799 set
800 {
801 if (value.IsFinite())
802 {
803 m_pidControllerActive = true;
804 _target_velocity = value;
805 }
806 else
807 {
808 m_log.Warn("[PHYSICS]: Got a NaN velocity from Scene in a Character");
809 }
810 }
811 }
812
813 public override Vector3 Torque
814 {
815 get { return Vector3.Zero; }
816 set { return; }
817 }
818
819 public override float CollisionScore
820 {
821 get { return 0f; }
822 set { }
823 }
824
825 public override bool Kinematic
826 {
827 get { return false; }
828 set { }
829 }
830
831 public override Quaternion Orientation
832 {
833 get { return Quaternion.Identity; }
834 set {
835 //Matrix3 or = Orientation.ToRotationMatrix();
836 //d.Matrix3 ord = new d.Matrix3(or.m00, or.m10, or.m20, or.m01, or.m11, or.m21, or.m02, or.m12, or.m22);
837 //d.BodySetRotation(Body, ref ord);
838 }
839 }
840
841 public override Vector3 Acceleration
842 {
843 get { return _acceleration; }
844 }
845
846 public void SetAcceleration(Vector3 accel)
847 {
848 m_pidControllerActive = true;
849 _acceleration = accel;
850 }
851
852 /// <summary>
853 /// Adds the force supplied to the Target Velocity
854 /// The PID controller takes this target velocity and tries to make it a reality
855 /// </summary>
856 /// <param name="force"></param>
857 public override void AddForce(Vector3 force, bool pushforce)
858 {
859 if (force.IsFinite())
860 {
861 if (pushforce)
862 {
863 m_pidControllerActive = false;
864 force *= 100f;
865//Console.WriteLine("DF 1"); // ##
866 if (!force.ApproxEquals(Vector3.Zero, 0.01f))
867 doForce(force);
868 // If uncommented, things get pushed off world
869 //
870 // m_log.Debug("Push!");
871 // _target_velocity.X += force.X;
872 // _target_velocity.Y += force.Y;
873 // _target_velocity.Z += force.Z;
874 }
875 else
876 {
877 m_pidControllerActive = true;
878 _target_velocity.X += force.X;
879 _target_velocity.Y += force.Y;
880 _target_velocity.Z += force.Z;
881 }
882 }
883 else
884 {
885 m_log.Warn("[PHYSICS]: Got a NaN force applied to a Character");
886 }
887 //m_lastUpdateSent = false;
888 }
889
890 public override void AddAngularForce(Vector3 force, bool pushforce)
891 {
892
893 }
894
895 /// <summary>
896 /// After all of the forces add up with 'add force' we apply them with doForce
897 /// </summary>
898 /// <param name="force"></param>
899 public void doForce(Vector3 force)
900 {
901 if (!collidelock)
902 {
903 d.BodyAddForce(Body, force.X, force.Y, force.Z);
904 //d.BodySetRotation(Body, ref m_StandUpRotation);
905 //standupStraight();
906 d.Vector3 vel = d.BodyGetLinearVel(Body); //##
907//Console.WriteLine("AvVel <{0},{1},{2}>", vel.X, vel.Y, vel.Z); //##
908 }
909 }
910
911 public override void SetMomentum(Vector3 momentum)
912 {
913 }
914
915
916 /// <summary>
917 /// Called from Simulate
918 /// This is the avatar's movement control + PID Controller
919 /// </summary>
920 /// <param name="timeStep"></param>
921 public void Move(float timeStep, List<OdeCharacter> defects)
922 {
923 // no lock; for now it's only called from within Simulate()
924
925 // If the PID Controller isn't active then we set our force
926 // calculating base velocity to the current position
927
928 if (Body == IntPtr.Zero)
929 return;
930
931 if (m_pidControllerActive == false)
932 {
933 _zeroPosition = d.BodyGetPosition(Body);
934 }
935 //PidStatus = true;
936
937 d.Vector3 localpos = d.BodyGetPosition(Body);
938 Vector3 localPos = new Vector3(localpos.X, localpos.Y, localpos.Z);
939
940 if (!localPos.IsFinite())
941 {
942
943 m_log.Warn("[PHYSICS]: Avatar Position is non-finite!");
944 defects.Add(this);
945 // _parent_scene.RemoveCharacter(this);
946
947 // destroy avatar capsule and related ODE data
948 if (Amotor != IntPtr.Zero)
949 {
950 // Kill the Amotor
951 d.JointDestroy(Amotor);
952 Amotor = IntPtr.Zero;
953 }
954
955 //kill the Geometry
956 _parent_scene.waitForSpaceUnlock(_parent_scene.space);
957
958 if (Body != IntPtr.Zero)
959 {
960 //kill the body
961 d.BodyDestroy(Body);
962
963 Body = IntPtr.Zero;
964 }
965
966 if(Shell != IntPtr.Zero)
967 {
968 try
969 {
970 d.GeomDestroy(Shell);
971 }
972 catch (System.AccessViolationException)
973 {
974 m_log.Error("[PHYSICS]: PrimGeom dead");
975 }
976 // Remove any old entries
977//string tShell;
978//_parent_scene.geom_name_map.TryGetValue(Shell, out tShell);
979//Console.WriteLine("**** Remove {0}", tShell);
980
981 if(_parent_scene.geom_name_map.ContainsKey(Shell)) _parent_scene.geom_name_map.Remove(Shell);
982 if(_parent_scene.actor_name_map.ContainsKey(Shell)) _parent_scene.actor_name_map.Remove(Shell);
983 Shell = IntPtr.Zero;
984 }
985
986 return;
987 }
988
989 Vector3 vec = Vector3.Zero;
990 d.Vector3 vel = d.BodyGetLinearVel(Body);
991
992 float movementdivisor = 1f;
993
994 if (!m_alwaysRun)
995 {
996 movementdivisor = walkDivisor;
997 }
998 else
999 {
1000 movementdivisor = runDivisor;
1001 }
1002
1003 // if velocity is zero, use position control; otherwise, velocity control
1004 if (_target_velocity.X == 0.0f && _target_velocity.Y == 0.0f && _target_velocity.Z == 0.0f && m_iscolliding)
1005 {
1006 // keep track of where we stopped. No more slippin' & slidin'
1007 if (!_zeroFlag)
1008 {
1009 _zeroFlag = true;
1010 _zeroPosition = d.BodyGetPosition(Body);
1011 }
1012 if (m_pidControllerActive)
1013 {
1014 // We only want to deactivate the PID Controller if we think we want to have our surrogate
1015 // react to the physics scene by moving it's position.
1016 // Avatar to Avatar collisions
1017 // Prim to avatar collisions
1018
1019 d.Vector3 pos = d.BodyGetPosition(Body);
1020 float errX = _zeroPosition.X - pos.X;
1021 float errY = _zeroPosition.Y - pos.Y;
1022 if( (Math.Abs(errX) > 0.1f) || (Math.Abs(errY) > 0.1f) )
1023 {
1024 vec.X = (_target_velocity.X - vel.X) * (PID_D) + (errX) * (PID_P * 2);
1025 vec.Y = (_target_velocity.Y - vel.Y) * (PID_D) + (errY) * (PID_P * 2);
1026 }
1027 else
1028 { // close, jump to lateral destination
1029 d.BodySetPosition(Body, _zeroPosition.X, _zeroPosition.Y, pos.Z);
1030 }
1031// if (flying)
1032 if (flying || jumping) // add for jumping
1033 {
1034 vec.Z = (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P;
1035 }
1036 }
1037 //PidStatus = true;
1038 }
1039 else
1040 {
1041 m_pidControllerActive = true;
1042 _zeroFlag = false;
1043 if (m_iscolliding && !flying)
1044 {
1045 // We're standing on something
1046 vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D);
1047 vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D);
1048 }
1049 else if (m_iscolliding && flying)
1050 {
1051 // We're flying and colliding with something
1052 vec.X = ((_target_velocity.X/movementdivisor) - vel.X)*(PID_D / 16);
1053 vec.Y = ((_target_velocity.Y/movementdivisor) - vel.Y)*(PID_D / 16);
1054 }
1055 else if (!m_iscolliding && flying)
1056 {
1057 // we're in mid air suspended
1058 vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D/6);
1059 vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D/6);
1060 }
1061
1062 if (m_iscolliding && !flying && _target_velocity.Z > 0.0f)
1063 {
1064 // We're colliding with something and we're not flying but we're moving
1065 // This means we're walking or running.
1066 d.Vector3 pos = d.BodyGetPosition(Body);
1067 vec.Z = (_target_velocity.Z - vel.Z)*PID_D + (_zeroPosition.Z - pos.Z)*PID_P;
1068 if (_target_velocity.X > 0)
1069 {
1070 vec.X = ((_target_velocity.X - vel.X)/1.2f)*PID_D;
1071 }
1072 if (_target_velocity.Y > 0)
1073 {
1074 vec.Y = ((_target_velocity.Y - vel.Y)/1.2f)*PID_D;
1075 }
1076 }
1077 else if (!m_iscolliding && !flying)
1078 {
1079 // we're not colliding and we're not flying so that means we're falling!
1080 // m_iscolliding includes collisions with the ground.
1081
1082 // d.Vector3 pos = d.BodyGetPosition(Body);
1083 if (Math.Abs(_target_velocity.X) > 0)
1084 {
1085 vec.X = ((_target_velocity.X - vel.X)/1.2f)*PID_D;
1086 }
1087 if (Math.Abs(_target_velocity.Y) > 0)
1088 {
1089 vec.Y = ((_target_velocity.Y - vel.Y)/1.2f)*PID_D;
1090 }
1091 }
1092
1093 if (flying)
1094 {
1095 vec.Z = (_target_velocity.Z - vel.Z) * (PID_D);
1096 }
1097 }
1098 if (flying)
1099 {
1100 vec.Z += ((-1 * _parent_scene.gravityz)*m_mass);
1101
1102 //Added for auto fly height. Kitto Flora
1103 //d.Vector3 pos = d.BodyGetPosition(Body);
1104 float target_altitude = _parent_scene.GetTerrainHeightAtXY(_position.X, _position.Y) + MinimumGroundFlightOffset;
1105
1106 if (_position.Z < target_altitude)
1107 {
1108 vec.Z += (target_altitude - _position.Z) * PID_P * 5.0f;
1109 }
1110 // end add Kitto Flora
1111 }
1112 if (vec.IsFinite())
1113 {
1114 if (!vec.ApproxEquals(Vector3.Zero, 0.02f)) // 0.01 allows 0.002 !!
1115 {
1116//Console.WriteLine("DF 2"); // ##
1117
1118 doForce(vec);
1119 if (!_zeroFlag)
1120 {
1121// AlignAvatarTiltWithCurrentDirectionOfMovement(vec);
1122 }
1123 }
1124 }
1125 else
1126 {
1127 m_log.Warn("[PHYSICS]: Got a NaN force vector in Move()");
1128 m_log.Warn("[PHYSICS]: Avatar Position is non-finite!");
1129 defects.Add(this);
1130 // _parent_scene.RemoveCharacter(this);
1131 // destroy avatar capsule and related ODE data
1132 if (Amotor != IntPtr.Zero)
1133 {
1134 // Kill the Amotor
1135 d.JointDestroy(Amotor);
1136 Amotor = IntPtr.Zero;
1137 }
1138 //kill the Geometry
1139 _parent_scene.waitForSpaceUnlock(_parent_scene.space);
1140
1141 if (Body != IntPtr.Zero)
1142 {
1143 //kill the body
1144 d.BodyDestroy(Body);
1145
1146 Body = IntPtr.Zero;
1147 }
1148
1149 if(Shell != IntPtr.Zero)
1150 {
1151 try
1152 {
1153 d.GeomDestroy(Shell);
1154 }
1155 catch (System.AccessViolationException)
1156 {
1157 m_log.Error("[PHYSICS]: PrimGeom dead");
1158 }
1159 // Remove any old entries
1160//string tShell;
1161//_parent_scene.geom_name_map.TryGetValue(Shell, out tShell);
1162//Console.WriteLine("**** Remove {0}", tShell);
1163
1164 if(_parent_scene.geom_name_map.ContainsKey(Shell)) _parent_scene.geom_name_map.Remove(Shell);
1165 if(_parent_scene.actor_name_map.ContainsKey(Shell)) _parent_scene.actor_name_map.Remove(Shell);
1166 Shell = IntPtr.Zero;
1167 }
1168 }
1169 }
1170
1171 /// <summary>
1172 /// Updates the reported position and velocity. This essentially sends the data up to ScenePresence.
1173 /// </summary>
1174 public void UpdatePositionAndVelocity()
1175 {
1176 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
1177 d.Vector3 vec;
1178 try
1179 {
1180 vec = d.BodyGetPosition(Body);
1181 }
1182 catch (NullReferenceException)
1183 {
1184 bad = true;
1185 _parent_scene.BadCharacter(this);
1186 vec = new d.Vector3(_position.X, _position.Y, _position.Z);
1187 base.RaiseOutOfBounds(_position); // Tells ScenePresence that there's a problem!
1188 m_log.WarnFormat("[ODEPLUGIN]: Avatar Null reference for Avatar {0}, physical actor {1}", m_name, m_uuid);
1189 }
1190
1191
1192 // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!)
1193 if (vec.X < 0.0f) vec.X = 0.0f;
1194 if (vec.Y < 0.0f) vec.Y = 0.0f;
1195 if (vec.X > (int)_parent_scene.WorldExtents.X - 0.05f) vec.X = (int)_parent_scene.WorldExtents.X - 0.05f;
1196 if (vec.Y > (int)_parent_scene.WorldExtents.Y - 0.05f) vec.Y = (int)_parent_scene.WorldExtents.Y - 0.05f;
1197
1198 _position.X = vec.X;
1199 _position.Y = vec.Y;
1200 _position.Z = vec.Z;
1201
1202 // Did we move last? = zeroflag
1203 // This helps keep us from sliding all over
1204
1205 if (_zeroFlag)
1206 {
1207 _velocity.X = 0.0f;
1208 _velocity.Y = 0.0f;
1209 _velocity.Z = 0.0f;
1210
1211 // Did we send out the 'stopped' message?
1212 if (!m_lastUpdateSent)
1213 {
1214 m_lastUpdateSent = true;
1215 //base.RequestPhysicsterseUpdate();
1216
1217 }
1218 }
1219 else
1220 {
1221 m_lastUpdateSent = false;
1222 try
1223 {
1224 vec = d.BodyGetLinearVel(Body);
1225 }
1226 catch (NullReferenceException)
1227 {
1228 vec.X = _velocity.X;
1229 vec.Y = _velocity.Y;
1230 vec.Z = _velocity.Z;
1231 }
1232 _velocity.X = (vec.X);
1233 _velocity.Y = (vec.Y);
1234
1235 _velocity.Z = (vec.Z);
1236
1237 if (_velocity.Z < -6 && !m_hackSentFall)
1238 {
1239 m_hackSentFall = true;
1240 m_pidControllerActive = false;
1241 }
1242 else if (flying && !m_hackSentFly)
1243 {
1244 //m_hackSentFly = true;
1245 //base.SendCollisionUpdate(new CollisionEventUpdate());
1246 }
1247 else
1248 {
1249 m_hackSentFly = false;
1250 m_hackSentFall = false;
1251 }
1252 }
1253 }
1254
1255 /// <summary>
1256 /// Cleanup the things we use in the scene.
1257 /// </summary>
1258 public void Destroy()
1259 {
1260 m_tainted_isPhysical = false;
1261 _parent_scene.AddPhysicsActorTaint(this);
1262 }
1263
1264 public override void CrossingFailure()
1265 {
1266 }
1267
1268 public override Vector3 PIDTarget { set { return; } }
1269 public override bool PIDActive { set { return; } }
1270 public override float PIDTau { set { return; } }
1271
1272 public override float PIDHoverHeight { set { return; } }
1273 public override bool PIDHoverActive { set { return; } }
1274 public override PIDHoverType PIDHoverType { set { return; } }
1275 public override float PIDHoverTau { set { return; } }
1276
1277 public override Quaternion APIDTarget{ set { return; } }
1278
1279 public override bool APIDActive{ set { return; } }
1280
1281 public override float APIDStrength{ set { return; } }
1282
1283 public override float APIDDamping{ set { return; } }
1284
1285
1286 public override void SubscribeEvents(int ms)
1287 {
1288 m_requestedUpdateFrequency = ms;
1289 m_eventsubscription = ms;
1290 _parent_scene.addCollisionEventReporting(this);
1291 }
1292 public override void UnSubscribeEvents()
1293 {
1294 _parent_scene.remCollisionEventReporting(this);
1295 m_requestedUpdateFrequency = 0;
1296 m_eventsubscription = 0;
1297 }
1298 public void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
1299 {
1300 if (m_eventsubscription > 0)
1301 {
1302 CollisionEventsThisFrame.addCollider(CollidedWith, contact);
1303 }
1304 }
1305
1306 public void SendCollisions()
1307 {
1308 if (m_eventsubscription > m_requestedUpdateFrequency)
1309 {
1310 if (CollisionEventsThisFrame != null)
1311 {
1312 base.SendCollisionUpdate(CollisionEventsThisFrame);
1313 }
1314 CollisionEventsThisFrame = new CollisionEventUpdate();
1315 m_eventsubscription = 0;
1316 }
1317 }
1318 public override bool SubscribedEvents()
1319 {
1320 if (m_eventsubscription > 0)
1321 return true;
1322 return false;
1323 }
1324
1325 public void ProcessTaints(float timestep)
1326 {
1327 lock (m_syncRoot)
1328 {
1329
1330 if (m_tainted_isPhysical != m_isPhysical)
1331 {
1332 if (m_tainted_isPhysical)
1333 {
1334 // Create avatar capsule and related ODE data
1335 if (!(Shell == IntPtr.Zero && Body == IntPtr.Zero && Amotor == IntPtr.Zero))
1336 {
1337 m_log.Warn("[PHYSICS]: re-creating the following avatar ODE data, even though it already exists - "
1338 + (Shell!=IntPtr.Zero ? "Shell ":"")
1339 + (Body!=IntPtr.Zero ? "Body ":"")
1340 + (Amotor!=IntPtr.Zero ? "Amotor ":""));
1341 }
1342 AvatarGeomAndBodyCreation(_position.X, _position.Y, _position.Z, m_tensor);
1343 _parent_scene.AddCharacter(this);
1344 }
1345 else
1346 {
1347 _parent_scene.RemoveCharacter(this);
1348 // destroy avatar capsule and related ODE data
1349 if (Amotor != IntPtr.Zero)
1350 {
1351 // Kill the Amotor
1352 d.JointDestroy(Amotor);
1353 Amotor = IntPtr.Zero;
1354 }
1355 //kill the Geometry
1356 _parent_scene.waitForSpaceUnlock(_parent_scene.space);
1357
1358 if (Body != IntPtr.Zero)
1359 {
1360 //kill the body
1361 d.BodyDestroy(Body);
1362 Body = IntPtr.Zero;
1363 }
1364
1365 if(Shell != IntPtr.Zero)
1366 {
1367 try
1368 {
1369 d.GeomDestroy(Shell);
1370 }
1371 catch (System.AccessViolationException)
1372 {
1373 m_log.Error("[PHYSICS]: PrimGeom dead");
1374 }
1375 // Remove any old entries
1376 //string tShell;
1377 //_parent_scene.geom_name_map.TryGetValue(Shell, out tShell);
1378 //Console.WriteLine("**** Remove {0}", tShell);
1379
1380 if(_parent_scene.geom_name_map.ContainsKey(Shell)) _parent_scene.geom_name_map.Remove(Shell);
1381 if(_parent_scene.actor_name_map.ContainsKey(Shell)) _parent_scene.actor_name_map.Remove(Shell);
1382 Shell = IntPtr.Zero;
1383 }
1384 }
1385
1386 m_isPhysical = m_tainted_isPhysical;
1387 }
1388
1389 if (m_tainted_CAPSULE_LENGTH != CAPSULE_LENGTH)
1390 {
1391 if (Shell != IntPtr.Zero && Body != IntPtr.Zero && Amotor != IntPtr.Zero)
1392 {
1393
1394 m_pidControllerActive = true;
1395 // no lock needed on _parent_scene.OdeLock because we are called from within the thread lock in OdePlugin's simulate()
1396 d.JointDestroy(Amotor);
1397 float prevCapsule = CAPSULE_LENGTH;
1398 CAPSULE_LENGTH = m_tainted_CAPSULE_LENGTH;
1399 //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
1400 d.BodyDestroy(Body);
1401 AvatarGeomAndBodyCreation(_position.X, _position.Y,
1402 _position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2), m_tensor);
1403 Velocity = Vector3.Zero;
1404 }
1405 else
1406 {
1407 m_log.Warn("[PHYSICS]: trying to change capsule size, but the following ODE data is missing - "
1408 + (Shell==IntPtr.Zero ? "Shell ":"")
1409 + (Body==IntPtr.Zero ? "Body ":"")
1410 + (Amotor==IntPtr.Zero ? "Amotor ":""));
1411 }
1412 }
1413
1414 if (!m_taintPosition.ApproxEquals(_position, 0.05f))
1415 {
1416 if (Body != IntPtr.Zero)
1417 {
1418 d.BodySetPosition(Body, m_taintPosition.X, m_taintPosition.Y, m_taintPosition.Z);
1419
1420 _position.X = m_taintPosition.X;
1421 _position.Y = m_taintPosition.Y;
1422 _position.Z = m_taintPosition.Z;
1423 }
1424 }
1425
1426 }
1427 }
1428
1429 internal void AddCollisionFrameTime(int p)
1430 {
1431 // protect it from overflow crashing
1432 if (m_eventsubscription + p >= int.MaxValue)
1433 m_eventsubscription = 0;
1434 m_eventsubscription += p;
1435 }
1436 }
1437}
diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs
new file mode 100644
index 0000000..7cd2dd1
--- /dev/null
+++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs
@@ -0,0 +1,3873 @@
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_rotateEnable = Vector3.One; // Current setting
68 private Vector3 m_rotateEnableRequest = Vector3.One; // Request from LSL
69 private bool m_rotateEnableUpdate = false;
70 private Vector3 m_lockX;
71 private Vector3 m_lockY;
72 private Vector3 m_lockZ;
73 private IntPtr Amotor = IntPtr.Zero;
74 private IntPtr AmotorX = IntPtr.Zero;
75 private IntPtr AmotorY = IntPtr.Zero;
76 private IntPtr AmotorZ = IntPtr.Zero;
77
78 private Vector3 m_PIDTarget;
79 private float m_PIDTau;
80 private float PID_D = 35f;
81 private float PID_G = 25f;
82 private bool m_usePID = false;
83
84 private Quaternion m_APIDTarget = new Quaternion();
85 private float m_APIDStrength = 0.5f;
86 private float m_APIDDamping = 0.5f;
87 private bool m_useAPID = false;
88 private float m_APIDdamper = 1.0f;
89
90 // These next 7 params apply to llSetHoverHeight(float height, integer water, float tau),
91 // do not confuse with VEHICLE HOVER
92
93 private float m_PIDHoverHeight;
94 private float m_PIDHoverTau;
95 private bool m_useHoverPID;
96 private PIDHoverType m_PIDHoverType = PIDHoverType.Ground;
97 private float m_targetHoverHeight;
98 private float m_groundHeight;
99 private float m_waterHeight;
100 private float m_buoyancy; //m_buoyancy set by llSetBuoyancy()
101
102 // private float m_tensor = 5f;
103 private int body_autodisable_frames = 20;
104
105
106 private const CollisionCategories m_default_collisionFlags = (CollisionCategories.Geom
107 | CollisionCategories.Space
108 | CollisionCategories.Body
109 | CollisionCategories.Character
110 );
111 private bool m_taintshape;
112 private bool m_taintPhysics;
113 private bool m_collidesLand = true;
114 private bool m_collidesWater;
115 public bool m_returnCollisions;
116
117 // Default we're a Geometry
118 private CollisionCategories m_collisionCategories = (CollisionCategories.Geom);
119
120 // Default, Collide with Other Geometries, spaces and Bodies
121 private CollisionCategories m_collisionFlags = m_default_collisionFlags;
122
123 public bool m_taintremove;
124 public bool m_taintdisable;
125 public bool m_disabled;
126 public bool m_taintadd;
127 public bool m_taintselected;
128 public bool m_taintCollidesWater;
129
130 public uint m_localID;
131
132 //public GCHandle gc;
133 private CollisionLocker ode;
134
135 private bool m_meshfailed = false;
136 private bool m_taintforce = false;
137 private bool m_taintaddangularforce = false;
138 private Vector3 m_force;
139 private List<Vector3> m_forcelist = new List<Vector3>();
140 private List<Vector3> m_angularforcelist = new List<Vector3>();
141
142 private IMesh _mesh;
143 private PrimitiveBaseShape _pbs;
144 private OdeScene _parent_scene;
145 public IntPtr m_targetSpace = IntPtr.Zero;
146 public IntPtr prim_geom;
147// public IntPtr prev_geom;
148 public IntPtr _triMeshData;
149
150 private IntPtr _linkJointGroup = IntPtr.Zero;
151 private PhysicsActor _parent;
152 private PhysicsActor m_taintparent;
153
154 private List<OdePrim> childrenPrim = new List<OdePrim>();
155
156 private bool iscolliding;
157 private bool m_isphysical;
158 private bool m_isSelected;
159
160 internal bool m_isVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively
161
162 private bool m_throttleUpdates;
163 private int throttleCounter;
164 public int m_interpenetrationcount;
165 public float m_collisionscore;
166 public int m_roundsUnderMotionThreshold;
167 private int m_crossingfailures;
168
169 public bool outofBounds;
170 private float m_density = 10.000006836f; // Aluminum g/cm3;
171
172 public bool _zeroFlag; // if body has been stopped
173 private bool m_lastUpdateSent;
174
175 public IntPtr Body = IntPtr.Zero;
176 public String m_primName;
177 private Vector3 _target_velocity;
178 public d.Mass pMass;
179
180 public int m_eventsubscription;
181 private CollisionEventUpdate CollisionEventsThisFrame;
182
183 private IntPtr m_linkJoint = IntPtr.Zero;
184
185 public volatile bool childPrim;
186
187 internal int m_material = (int)Material.Wood;
188
189 private int frcount = 0; // Used to limit dynamics debug output to
190 private int revcount = 0; // Reverse motion while > 0
191
192 private IntPtr m_body = IntPtr.Zero;
193
194 // Vehicle properties ============================================================================================
195 private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind
196 // private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier
197 private VehicleFlag m_flags = (VehicleFlag) 0; // Bit settings:
198 // HOVER_TERRAIN_ONLY
199 // HOVER_GLOBAL_HEIGHT
200 // NO_DEFLECTION_UP
201 // HOVER_WATER_ONLY
202 // HOVER_UP_ONLY
203 // LIMIT_MOTOR_UP
204 // LIMIT_ROLL_ONLY
205
206 // Linear properties
207 private Vector3 m_linearMotorDirection = Vector3.Zero; // (was m_linearMotorDirectionLASTSET) the (local) Velocity
208 //requested by LSL
209 private float m_linearMotorTimescale = 0; // Motor Attack rate set by LSL
210 private float m_linearMotorDecayTimescale = 0; // Motor Decay rate set by LSL
211 private Vector3 m_linearFrictionTimescale = Vector3.Zero; // General Friction set by LSL
212
213 private Vector3 m_lLinMotorDVel = Vector3.Zero; // decayed motor
214 private Vector3 m_lLinObjectVel = Vector3.Zero; // local frame object velocity
215 private Vector3 m_wLinObjectVel = Vector3.Zero; // world frame object velocity
216
217 //Angular properties
218 private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor
219
220 private float m_angularMotorTimescale = 0; // motor angular Attack rate set by LSL
221 private float m_angularMotorDecayTimescale = 0; // motor angular Decay rate set by LSL
222 private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular Friction set by LSL
223
224 private Vector3 m_angularMotorDVel = Vector3.Zero; // decayed angular motor
225// private Vector3 m_angObjectVel = Vector3.Zero; // current body angular velocity
226 private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body
227
228 //Deflection properties
229 // private float m_angularDeflectionEfficiency = 0;
230 // private float m_angularDeflectionTimescale = 0;
231 // private float m_linearDeflectionEfficiency = 0;
232 // private float m_linearDeflectionTimescale = 0;
233
234 //Banking properties
235 // private float m_bankingEfficiency = 0;
236 // private float m_bankingMix = 0;
237 // private float m_bankingTimescale = 0;
238
239 //Hover and Buoyancy properties
240 private float m_VhoverHeight = 0f;
241// private float m_VhoverEfficiency = 0f;
242 private float m_VhoverTimescale = 0f;
243 private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height
244 private float m_VehicleBuoyancy = 0f; // Set by VEHICLE_BUOYANCY, for a vehicle.
245 // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity)
246 // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity.
247 // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity.
248
249 //Attractor properties
250 private float m_verticalAttractionEfficiency = 1.0f; // damped
251 private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor.
252
253
254
255
256
257
258 public OdePrim(String primName, OdeScene parent_scene, Vector3 pos, Vector3 size,
259 Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical, CollisionLocker dode)
260 {
261 ode = dode;
262 if (!pos.IsFinite())
263 {
264 pos = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f),
265 parent_scene.GetTerrainHeightAtXY(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f)) + 0.5f);
266 m_log.Warn("[PHYSICS]: Got nonFinite Object create Position");
267 }
268
269 _position = pos;
270 m_taintposition = pos;
271 PID_D = parent_scene.bodyPIDD;
272 PID_G = parent_scene.bodyPIDG;
273 m_density = parent_scene.geomDefaultDensity;
274 // m_tensor = parent_scene.bodyMotorJointMaxforceTensor;
275 body_autodisable_frames = parent_scene.bodyFramesAutoDisable;
276
277
278 prim_geom = IntPtr.Zero;
279// prev_geom = IntPtr.Zero;
280
281 if (!pos.IsFinite())
282 {
283 size = new Vector3(0.5f, 0.5f, 0.5f);
284 m_log.Warn("[PHYSICS]: Got nonFinite Object create Size");
285 }
286
287 if (size.X <= 0) size.X = 0.01f;
288 if (size.Y <= 0) size.Y = 0.01f;
289 if (size.Z <= 0) size.Z = 0.01f;
290
291 _size = size;
292 m_taintsize = _size;
293
294 if (!QuaternionIsFinite(rotation))
295 {
296 rotation = Quaternion.Identity;
297 m_log.Warn("[PHYSICS]: Got nonFinite Object create Rotation");
298 }
299
300 _orientation = rotation;
301 m_taintrot = _orientation;
302 _mesh = mesh;
303 _pbs = pbs;
304
305 _parent_scene = parent_scene;
306 m_targetSpace = (IntPtr)0;
307
308// if (pos.Z < 0)
309 if (pos.Z < parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y))
310 m_isphysical = false;
311 else
312 {
313 m_isphysical = pisPhysical;
314 // If we're physical, we need to be in the master space for now.
315 // linksets *should* be in a space together.. but are not currently
316 if (m_isphysical)
317 m_targetSpace = _parent_scene.space;
318 }
319 m_primName = primName;
320 m_taintadd = true;
321 _parent_scene.AddPhysicsActorTaint(this);
322 // don't do .add() here; old geoms get recycled with the same hash
323 }
324
325 public override int PhysicsActorType
326 {
327 get { return (int) ActorTypes.Prim; }
328 set { return; }
329 }
330
331 public override bool SetAlwaysRun
332 {
333 get { return false; }
334 set { return; }
335 }
336
337 public override uint LocalID
338 {
339 set {
340 //m_log.Info("[PHYSICS]: Setting TrackerID: " + value);
341 m_localID = value; }
342 }
343
344 public override bool Grabbed
345 {
346 set { return; }
347 }
348
349 public override bool Selected
350 {
351 set {
352
353//Console.WriteLine("Sel {0} {1} {2}", m_primName, value, m_isphysical);
354 // This only makes the object not collidable if the object
355 // is physical or the object is modified somehow *IN THE FUTURE*
356 // without this, if an avatar selects prim, they can walk right
357 // through it while it's selected
358 m_collisionscore = 0;
359 if ((m_isphysical && !_zeroFlag) || !value)
360 {
361 m_taintselected = value;
362 _parent_scene.AddPhysicsActorTaint(this);
363 }
364 else
365 {
366 m_taintselected = value;
367 m_isSelected = value;
368 }
369 if(m_isSelected) disableBodySoft();
370 }
371 }
372
373 public override bool IsPhysical
374 {
375 get { return m_isphysical; }
376 set
377 {
378 m_isphysical = value;
379 if (!m_isphysical)
380 { // Zero the remembered last velocity
381 m_lastVelocity = Vector3.Zero;
382 if (m_type != Vehicle.TYPE_NONE) Halt();
383 }
384 }
385 }
386
387 public void setPrimForRemoval()
388 {
389 m_taintremove = true;
390 }
391
392 public override bool Flying
393 {
394 // no flying prims for you
395 get { return false; }
396 set { }
397 }
398
399 public override bool IsColliding
400 {
401 get { return iscolliding; }
402 set { iscolliding = value; }
403 }
404
405 public override bool CollidingGround
406 {
407 get { return false; }
408 set { return; }
409 }
410
411 public override bool CollidingObj
412 {
413 get { return false; }
414 set { return; }
415 }
416
417 public override bool ThrottleUpdates
418 {
419 get { return m_throttleUpdates; }
420 set { m_throttleUpdates = value; }
421 }
422
423 public override bool Stopped
424 {
425 get { return _zeroFlag; }
426 }
427
428 public override Vector3 Position
429 {
430 get { return _position; }
431
432 set { _position = value;
433 //m_log.Info("[PHYSICS]: " + _position.ToString());
434 }
435 }
436
437 public override Vector3 Size
438 {
439 get { return _size; }
440 set
441 {
442 if (value.IsFinite())
443 {
444 _size = value;
445 }
446 else
447 {
448 m_log.Warn("[PHYSICS]: Got NaN Size on object");
449 }
450 }
451 }
452
453 public override float Mass
454 {
455 get { return CalculateMass(); }
456 }
457
458 public override Vector3 Force
459 {
460 //get { return Vector3.Zero; }
461 get { return m_force; }
462 set
463 {
464 if (value.IsFinite())
465 {
466 m_force = value;
467 }
468 else
469 {
470 m_log.Warn("[PHYSICS]: NaN in Force Applied to an Object");
471 }
472 }
473 }
474
475 public override int VehicleType
476 {
477 get { return (int)m_type; }
478 set { ProcessTypeChange((Vehicle)value); }
479 }
480
481 public override void VehicleFloatParam(int param, float value)
482 {
483 ProcessFloatVehicleParam((Vehicle) param, value);
484 }
485
486 public override void VehicleVectorParam(int param, Vector3 value)
487 {
488 ProcessVectorVehicleParam((Vehicle) param, value);
489 }
490
491 public override void VehicleRotationParam(int param, Quaternion rotation)
492 {
493 ProcessRotationVehicleParam((Vehicle) param, rotation);
494 }
495
496 public override void VehicleFlags(int param, bool remove)
497 {
498 ProcessVehicleFlags(param, remove);
499 }
500
501 public override void SetVolumeDetect(int param)
502 {
503 lock (_parent_scene.OdeLock)
504 {
505 m_isVolumeDetect = (param!=0);
506 }
507 }
508
509 public override Vector3 CenterOfMass
510 {
511 get { return Vector3.Zero; }
512 }
513
514 public override Vector3 GeometricCenter
515 {
516 get { return Vector3.Zero; }
517 }
518
519 public override PrimitiveBaseShape Shape
520 {
521 set
522 {
523 _pbs = value;
524 m_taintshape = true;
525 }
526 }
527
528 public override Vector3 Velocity
529 {
530 get
531 {
532 // Averate previous velocity with the new one so
533 // client object interpolation works a 'little' better
534 if (_zeroFlag)
535 return Vector3.Zero;
536
537 Vector3 returnVelocity = Vector3.Zero;
538 returnVelocity.X = (m_lastVelocity.X + _velocity.X)/2;
539 returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y)/2;
540 returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z)/2;
541 return returnVelocity;
542 }
543 set
544 {
545 if (value.IsFinite())
546 {
547 _velocity = value;
548 if (_velocity.ApproxEquals(Vector3.Zero,0.001f))
549 _acceleration = Vector3.Zero;
550
551 m_taintVelocity = value;
552 _parent_scene.AddPhysicsActorTaint(this);
553 }
554 else
555 {
556 m_log.Warn("[PHYSICS]: Got NaN Velocity in Object");
557 }
558
559 }
560 }
561
562 public override Vector3 Torque
563 {
564 get
565 {
566 if (!m_isphysical || Body == IntPtr.Zero)
567 return Vector3.Zero;
568
569 return _torque;
570 }
571
572 set
573 {
574 if (value.IsFinite())
575 {
576 m_taintTorque = value;
577 _parent_scene.AddPhysicsActorTaint(this);
578 }
579 else
580 {
581 m_log.Warn("[PHYSICS]: Got NaN Torque in Object");
582 }
583 }
584 }
585
586 public override float CollisionScore
587 {
588 get { return m_collisionscore; }
589 set { m_collisionscore = value; }
590 }
591
592 public override bool Kinematic
593 {
594 get { return false; }
595 set { }
596 }
597
598 public override Quaternion Orientation
599 {
600 get { return _orientation; }
601 set
602 {
603 if (QuaternionIsFinite(value))
604 {
605 _orientation = value;
606 }
607 else
608 m_log.Warn("[PHYSICS]: Got NaN quaternion Orientation from Scene in Object");
609
610 }
611 }
612
613
614 public override bool FloatOnWater
615 {
616 set {
617 m_taintCollidesWater = value;
618 _parent_scene.AddPhysicsActorTaint(this);
619 }
620 }
621
622 public override void SetMomentum(Vector3 momentum)
623 {
624 }
625
626 public override Vector3 PIDTarget
627 {
628 set
629 {
630 if (value.IsFinite())
631 {
632 m_PIDTarget = value;
633 }
634 else
635 m_log.Warn("[PHYSICS]: Got NaN PIDTarget from Scene on Object");
636 }
637 }
638 public override bool PIDActive { set { m_usePID = value; } }
639 public override float PIDTau { set { m_PIDTau = value; } }
640
641 // For RotLookAt
642 public override Quaternion APIDTarget { set { m_APIDTarget = value; } }
643 public override bool APIDActive { set { m_useAPID = value; } }
644 public override float APIDStrength { set { m_APIDStrength = value; } }
645 public override float APIDDamping { set { m_APIDDamping = value; } }
646
647 public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } }
648 public override bool PIDHoverActive { set { m_useHoverPID = value; } }
649 public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } }
650 public override float PIDHoverTau { set { m_PIDHoverTau = value; } }
651
652 internal static bool QuaternionIsFinite(Quaternion q)
653 {
654 if (Single.IsNaN(q.X) || Single.IsInfinity(q.X))
655 return false;
656 if (Single.IsNaN(q.Y) || Single.IsInfinity(q.Y))
657 return false;
658 if (Single.IsNaN(q.Z) || Single.IsInfinity(q.Z))
659 return false;
660 if (Single.IsNaN(q.W) || Single.IsInfinity(q.W))
661 return false;
662 return true;
663 }
664
665 public override Vector3 Acceleration // client updates read data via here
666 {
667 get
668 {
669 if (_zeroFlag)
670 {
671 return Vector3.Zero;
672 }
673 return _acceleration;
674 }
675 }
676
677
678 public void SetAcceleration(Vector3 accel) // No one calls this, and it would not do anything.
679 {
680 _acceleration = accel;
681 }
682
683 public override void AddForce(Vector3 force, bool pushforce)
684 {
685 if (force.IsFinite())
686 {
687 lock (m_forcelist)
688 m_forcelist.Add(force);
689
690 m_taintforce = true;
691 }
692 else
693 {
694 m_log.Warn("[PHYSICS]: Got Invalid linear force vector from Scene in Object");
695 }
696 //m_log.Info("[PHYSICS]: Added Force:" + force.ToString() + " to prim at " + Position.ToString());
697 }
698
699 public override void AddAngularForce(Vector3 force, bool pushforce)
700 {
701 if (force.IsFinite())
702 {
703 m_angularforcelist.Add(force);
704 m_taintaddangularforce = true;
705 }
706 else
707 {
708 m_log.Warn("[PHYSICS]: Got Invalid Angular force vector from Scene in Object");
709 }
710 }
711
712 public override Vector3 RotationalVelocity
713 {
714 get
715 {
716 return m_rotationalVelocity;
717 }
718 set
719 {
720 if (value.IsFinite())
721 {
722 m_rotationalVelocity = value;
723 }
724 else
725 {
726 m_log.Warn("[PHYSICS]: Got NaN RotationalVelocity in Object");
727 }
728 }
729 }
730
731 public override void CrossingFailure()
732 {
733 m_crossingfailures++;
734 if (m_crossingfailures > _parent_scene.geomCrossingFailuresBeforeOutofbounds)
735 {
736 base.RaiseOutOfBounds(_position);
737 return;
738 }
739 else if (m_crossingfailures == _parent_scene.geomCrossingFailuresBeforeOutofbounds)
740 {
741 m_log.Warn("[PHYSICS]: Too many crossing failures for: " + m_primName);
742 }
743 }
744
745 public override float Buoyancy
746 {
747 get { return m_buoyancy; }
748 set { m_buoyancy = value; }
749 }
750
751 public override void link(PhysicsActor obj)
752 {
753 m_taintparent = obj;
754 }
755
756 public override void delink()
757 {
758 m_taintparent = null;
759 }
760
761 public override void LockAngularMotion(Vector3 axis)
762 {
763 // This is actually ROTATION ENABLE, not a lock.
764 // default is <1,1,1> which is all enabled.
765 // The lock value is updated inside Move(), no point in using the taint system.
766 // OS 'm_taintAngularLock' etc change to m_rotateEnable.
767 if (axis.IsFinite())
768 {
769 axis.X = (axis.X > 0) ? 1f : 0f;
770 axis.Y = (axis.Y > 0) ? 1f : 0f;
771 axis.Z = (axis.Z > 0) ? 1f : 0f;
772 m_log.DebugFormat("[axislock]: <{0},{1},{2}>", axis.X, axis.Y, axis.Z);
773 m_rotateEnableRequest = axis;
774 m_rotateEnableUpdate = true;
775 }
776 else
777 {
778 m_log.Warn("[PHYSICS]: Got NaN locking axis from Scene on Object");
779 }
780 }
781
782
783 public void SetGeom(IntPtr geom)
784 {
785 if(prim_geom != IntPtr.Zero)
786 {
787 // Remove any old entries
788//string tPA;
789//_parent_scene.geom_name_map.TryGetValue(prim_geom, out tPA);
790//Console.WriteLine("**** Remove {0}", tPA);
791 if(_parent_scene.geom_name_map.ContainsKey(prim_geom)) _parent_scene.geom_name_map.Remove(prim_geom);
792 if(_parent_scene.actor_name_map.ContainsKey(prim_geom)) _parent_scene.actor_name_map.Remove(prim_geom);
793 d.GeomDestroy(prim_geom);
794 }
795
796 prim_geom = geom;
797//Console.WriteLine("SetGeom to " + prim_geom + " for " + m_primName);
798 if (prim_geom != IntPtr.Zero)
799 {
800 _parent_scene.geom_name_map[prim_geom] = this.m_primName;
801 _parent_scene.actor_name_map[prim_geom] = (PhysicsActor)this;
802 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
803 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
804//Console.WriteLine("**** Create {2} Dicts: actor={0} name={1}", _parent_scene.actor_name_map.Count, _parent_scene.geom_name_map.Count, this.m_primName);
805 }
806
807 if (childPrim)
808 {
809 if (_parent != null && _parent is OdePrim)
810 {
811 OdePrim parent = (OdePrim)_parent;
812//Console.WriteLine("SetGeom calls ChildSetGeom");
813 parent.ChildSetGeom(this);
814 }
815 }
816 //m_log.Warn("Setting Geom to: " + prim_geom);
817 }
818
819 public void enableBodySoft()
820 {
821 if (!childPrim)
822 {
823 if (m_isphysical && Body != IntPtr.Zero)
824 {
825 d.BodyEnable(Body);
826 if (m_type != Vehicle.TYPE_NONE)
827 Enable(Body, _parent_scene);
828 }
829
830 m_disabled = false;
831 }
832 }
833
834 public void disableBodySoft()
835 {
836 m_disabled = true;
837
838 if (m_isphysical && Body != IntPtr.Zero)
839 {
840 d.BodyDisable(Body);
841 Halt();
842 }
843 }
844
845 public void enableBody()
846 {
847 // Don't enable this body if we're a child prim
848 // this should be taken care of in the parent function not here
849 if (!childPrim)
850 {
851 // Sets the geom to a body
852 Body = d.BodyCreate(_parent_scene.world);
853
854 setMass();
855 d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
856 d.Quaternion myrot = new d.Quaternion();
857 myrot.X = _orientation.X;
858 myrot.Y = _orientation.Y;
859 myrot.Z = _orientation.Z;
860 myrot.W = _orientation.W;
861 d.BodySetQuaternion(Body, ref myrot);
862 d.GeomSetBody(prim_geom, Body);
863 m_collisionCategories |= CollisionCategories.Body;
864 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
865
866 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
867 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
868
869 d.BodySetAutoDisableFlag(Body, true);
870 d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
871
872 // disconnect from world gravity so we can apply buoyancy
873 d.BodySetGravityMode (Body, false);
874
875 m_interpenetrationcount = 0;
876 m_collisionscore = 0;
877 m_disabled = false;
878
879 if (m_type != Vehicle.TYPE_NONE)
880 {
881 Enable(Body, _parent_scene);
882 }
883
884 _parent_scene.addActivePrim(this);
885 }
886 }
887
888 #region Mass Calculation
889
890 private float CalculateMass()
891 {
892 float volume = _size.X * _size.Y * _size.Z; // default
893 float tmp;
894
895 float returnMass = 0;
896 float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f;
897 float hollowVolume = hollowAmount * hollowAmount;
898
899 switch (_pbs.ProfileShape)
900 {
901 case ProfileShape.Square:
902 // default box
903
904 if (_pbs.PathCurve == (byte)Extrusion.Straight)
905 {
906 if (hollowAmount > 0.0)
907 {
908 switch (_pbs.HollowShape)
909 {
910 case HollowShape.Square:
911 case HollowShape.Same:
912 break;
913
914 case HollowShape.Circle:
915
916 hollowVolume *= 0.78539816339f;
917 break;
918
919 case HollowShape.Triangle:
920
921 hollowVolume *= (0.5f * .5f);
922 break;
923
924 default:
925 hollowVolume = 0;
926 break;
927 }
928 volume *= (1.0f - hollowVolume);
929 }
930 }
931
932 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
933 {
934 //a tube
935
936 volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX);
937 tmp= 1.0f -2.0e-2f * (float)(200 - _pbs.PathScaleY);
938 volume -= volume*tmp*tmp;
939
940 if (hollowAmount > 0.0)
941 {
942 hollowVolume *= hollowAmount;
943
944 switch (_pbs.HollowShape)
945 {
946 case HollowShape.Square:
947 case HollowShape.Same:
948 break;
949
950 case HollowShape.Circle:
951 hollowVolume *= 0.78539816339f;;
952 break;
953
954 case HollowShape.Triangle:
955 hollowVolume *= 0.5f * 0.5f;
956 break;
957 default:
958 hollowVolume = 0;
959 break;
960 }
961 volume *= (1.0f - hollowVolume);
962 }
963 }
964
965 break;
966
967 case ProfileShape.Circle:
968
969 if (_pbs.PathCurve == (byte)Extrusion.Straight)
970 {
971 volume *= 0.78539816339f; // elipse base
972
973 if (hollowAmount > 0.0)
974 {
975 switch (_pbs.HollowShape)
976 {
977 case HollowShape.Same:
978 case HollowShape.Circle:
979 break;
980
981 case HollowShape.Square:
982 hollowVolume *= 0.5f * 2.5984480504799f;
983 break;
984
985 case HollowShape.Triangle:
986 hollowVolume *= .5f * 1.27323954473516f;
987 break;
988
989 default:
990 hollowVolume = 0;
991 break;
992 }
993 volume *= (1.0f - hollowVolume);
994 }
995 }
996
997 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
998 {
999 volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX);
1000 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
1001 volume *= (1.0f - tmp * tmp);
1002
1003 if (hollowAmount > 0.0)
1004 {
1005
1006 // calculate the hollow volume by it's shape compared to the prim shape
1007 hollowVolume *= hollowAmount;
1008
1009 switch (_pbs.HollowShape)
1010 {
1011 case HollowShape.Same:
1012 case HollowShape.Circle:
1013 break;
1014
1015 case HollowShape.Square:
1016 hollowVolume *= 0.5f * 2.5984480504799f;
1017 break;
1018
1019 case HollowShape.Triangle:
1020 hollowVolume *= .5f * 1.27323954473516f;
1021 break;
1022
1023 default:
1024 hollowVolume = 0;
1025 break;
1026 }
1027 volume *= (1.0f - hollowVolume);
1028 }
1029 }
1030 break;
1031
1032 case ProfileShape.HalfCircle:
1033 if (_pbs.PathCurve == (byte)Extrusion.Curve1)
1034 {
1035 volume *= 0.52359877559829887307710723054658f;
1036 }
1037 break;
1038
1039 case ProfileShape.EquilateralTriangle:
1040
1041 if (_pbs.PathCurve == (byte)Extrusion.Straight)
1042 {
1043 volume *= 0.32475953f;
1044
1045 if (hollowAmount > 0.0)
1046 {
1047
1048 // calculate the hollow volume by it's shape compared to the prim shape
1049 switch (_pbs.HollowShape)
1050 {
1051 case HollowShape.Same:
1052 case HollowShape.Triangle:
1053 hollowVolume *= .25f;
1054 break;
1055
1056 case HollowShape.Square:
1057 hollowVolume *= 0.499849f * 3.07920140172638f;
1058 break;
1059
1060 case HollowShape.Circle:
1061 // Hollow shape is a perfect cyllinder in respect to the cube's scale
1062 // Cyllinder hollow volume calculation
1063
1064 hollowVolume *= 0.1963495f * 3.07920140172638f;
1065 break;
1066
1067 default:
1068 hollowVolume = 0;
1069 break;
1070 }
1071 volume *= (1.0f - hollowVolume);
1072 }
1073 }
1074 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
1075 {
1076 volume *= 0.32475953f;
1077 volume *= 0.01f * (float)(200 - _pbs.PathScaleX);
1078 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
1079 volume *= (1.0f - tmp * tmp);
1080
1081 if (hollowAmount > 0.0)
1082 {
1083
1084 hollowVolume *= hollowAmount;
1085
1086 switch (_pbs.HollowShape)
1087 {
1088 case HollowShape.Same:
1089 case HollowShape.Triangle:
1090 hollowVolume *= .25f;
1091 break;
1092
1093 case HollowShape.Square:
1094 hollowVolume *= 0.499849f * 3.07920140172638f;
1095 break;
1096
1097 case HollowShape.Circle:
1098
1099 hollowVolume *= 0.1963495f * 3.07920140172638f;
1100 break;
1101
1102 default:
1103 hollowVolume = 0;
1104 break;
1105 }
1106 volume *= (1.0f - hollowVolume);
1107 }
1108 }
1109 break;
1110
1111 default:
1112 break;
1113 }
1114
1115
1116
1117 float taperX1;
1118 float taperY1;
1119 float taperX;
1120 float taperY;
1121 float pathBegin;
1122 float pathEnd;
1123 float profileBegin;
1124 float profileEnd;
1125
1126 if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible)
1127 {
1128 taperX1 = _pbs.PathScaleX * 0.01f;
1129 if (taperX1 > 1.0f)
1130 taperX1 = 2.0f - taperX1;
1131 taperX = 1.0f - taperX1;
1132
1133 taperY1 = _pbs.PathScaleY * 0.01f;
1134 if (taperY1 > 1.0f)
1135 taperY1 = 2.0f - taperY1;
1136 taperY = 1.0f - taperY1;
1137 }
1138 else
1139 {
1140 taperX = _pbs.PathTaperX * 0.01f;
1141 if (taperX < 0.0f)
1142 taperX = -taperX;
1143 taperX1 = 1.0f - taperX;
1144
1145 taperY = _pbs.PathTaperY * 0.01f;
1146 if (taperY < 0.0f)
1147 taperY = -taperY;
1148 taperY1 = 1.0f - taperY;
1149
1150 }
1151
1152
1153 volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
1154
1155 pathBegin = (float)_pbs.PathBegin * 2.0e-5f;
1156 pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f;
1157 volume *= (pathEnd - pathBegin);
1158
1159// this is crude aproximation
1160 profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f;
1161 profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f;
1162 volume *= (profileEnd - profileBegin);
1163
1164 returnMass = m_density * volume;
1165
1166 if (returnMass <= 0)
1167 returnMass = 0.0001f;//ckrinke: Mass must be greater then zero.
1168// else if (returnMass > _parent_scene.maximumMassObject)
1169// returnMass = _parent_scene.maximumMassObject;
1170
1171
1172
1173
1174 // Recursively calculate mass
1175 bool HasChildPrim = false;
1176 lock (childrenPrim)
1177 {
1178 if (childrenPrim.Count > 0)
1179 {
1180 HasChildPrim = true;
1181 }
1182
1183 }
1184 if (HasChildPrim)
1185 {
1186 OdePrim[] childPrimArr = new OdePrim[0];
1187
1188 lock (childrenPrim)
1189 childPrimArr = childrenPrim.ToArray();
1190
1191 for (int i = 0; i < childPrimArr.Length; i++)
1192 {
1193 if (childPrimArr[i] != null && !childPrimArr[i].m_taintremove)
1194 returnMass += childPrimArr[i].CalculateMass();
1195 // failsafe, this shouldn't happen but with OpenSim, you never know :)
1196 if (i > 256)
1197 break;
1198 }
1199 }
1200 if (returnMass > _parent_scene.maximumMassObject)
1201 returnMass = _parent_scene.maximumMassObject;
1202 return returnMass;
1203 }// end CalculateMass
1204
1205 #endregion
1206
1207 public void setMass()
1208 {
1209 if (Body != (IntPtr) 0)
1210 {
1211 float newmass = CalculateMass();
1212
1213 //m_log.Info("[PHYSICS]: New Mass: " + newmass.ToString());
1214
1215 d.MassSetBoxTotal(out pMass, newmass, _size.X, _size.Y, _size.Z);
1216 d.BodySetMass(Body, ref pMass);
1217 }
1218 }
1219
1220 public void disableBody()
1221 {
1222 //this kills the body so things like 'mesh' can re-create it.
1223 lock (this)
1224 {
1225 if (!childPrim)
1226 {
1227 if (Body != IntPtr.Zero)
1228 {
1229 _parent_scene.remActivePrim(this);
1230 m_collisionCategories &= ~CollisionCategories.Body;
1231 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
1232
1233 if (prim_geom != IntPtr.Zero)
1234 {
1235 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1236 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1237 }
1238
1239
1240 d.BodyDestroy(Body);
1241 lock (childrenPrim)
1242 {
1243 if (childrenPrim.Count > 0)
1244 {
1245 foreach (OdePrim prm in childrenPrim)
1246 {
1247 _parent_scene.remActivePrim(prm);
1248 prm.Body = IntPtr.Zero;
1249 }
1250 }
1251 }
1252 Body = IntPtr.Zero;
1253 }
1254 }
1255 else
1256 {
1257 _parent_scene.remActivePrim(this);
1258
1259 m_collisionCategories &= ~CollisionCategories.Body;
1260 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
1261
1262 if (prim_geom != IntPtr.Zero)
1263 {
1264 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1265 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1266 }
1267
1268
1269 Body = IntPtr.Zero;
1270 }
1271 }
1272 m_disabled = true;
1273 m_collisionscore = 0;
1274 }
1275
1276 private static Dictionary<IMesh, IntPtr> m_MeshToTriMeshMap = new Dictionary<IMesh, IntPtr>();
1277
1278 public void setMesh(OdeScene parent_scene, IMesh mesh)
1279 {
1280 // This sleeper is there to moderate how long it takes between
1281 // setting up the mesh and pre-processing it when we get rapid fire mesh requests on a single object
1282
1283 //Thread.Sleep(10);
1284
1285 //Kill Body so that mesh can re-make the geom
1286 if (IsPhysical && Body != IntPtr.Zero)
1287 {
1288 if (childPrim)
1289 {
1290 if (_parent != null)
1291 {
1292 OdePrim parent = (OdePrim)_parent;
1293 parent.ChildDelink(this);
1294 }
1295 }
1296 else
1297 {
1298 disableBody();
1299 }
1300 }
1301 IntPtr vertices, indices;
1302 int vertexCount, indexCount;
1303 int vertexStride, triStride;
1304 mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap
1305 mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage
1306
1307 mesh.releaseSourceMeshData(); // free up the original mesh data to save memory
1308 if (m_MeshToTriMeshMap.ContainsKey(mesh))
1309 {
1310 _triMeshData = m_MeshToTriMeshMap[mesh];
1311 }
1312 else
1313 {
1314 _triMeshData = d.GeomTriMeshDataCreate();
1315
1316 d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride);
1317 d.GeomTriMeshDataPreprocess(_triMeshData);
1318 m_MeshToTriMeshMap[mesh] = _triMeshData;
1319 }
1320
1321 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1322 try
1323 {
1324 // if (prim_geom == IntPtr.Zero) // setGeom takes care of phys engine recreate and prim_geom pointer
1325 // {
1326 SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null));
1327 // }
1328 }
1329 catch (AccessViolationException)
1330 {
1331 m_log.Error("[PHYSICS]: MESH LOCKED");
1332 return;
1333 }
1334
1335
1336 // if (IsPhysical && Body == (IntPtr) 0)
1337 // {
1338 // Recreate the body
1339 // m_interpenetrationcount = 0;
1340 // m_collisionscore = 0;
1341
1342 // enableBody();
1343 // }
1344 }
1345
1346 public void ProcessTaints(float timestep) //=============================================================================
1347 {
1348 if (m_taintadd)
1349 {
1350 changeadd(timestep);
1351 }
1352
1353 if (prim_geom != IntPtr.Zero)
1354 {
1355 if (!_position.ApproxEquals(m_taintposition, 0f))
1356 {
1357 changemove(timestep);
1358 }
1359 if (m_taintrot != _orientation)
1360 {
1361 if(childPrim && IsPhysical) // For physical child prim...
1362 {
1363 rotate(timestep);
1364 // KF: ODE will also rotate the parent prim!
1365 // so rotate the root back to where it was
1366 OdePrim parent = (OdePrim)_parent;
1367 parent.rotate(timestep);
1368 }
1369 else
1370 {
1371 //Just rotate the prim
1372 rotate(timestep);
1373 }
1374 }
1375 //
1376
1377 if (m_taintPhysics != m_isphysical && !(m_taintparent != _parent))
1378 {
1379 changePhysicsStatus(timestep);
1380 }//
1381
1382 if (!_size.ApproxEquals(m_taintsize,0f))
1383 changesize(timestep);
1384 //
1385
1386 if (m_taintshape)
1387 changeshape(timestep);
1388 //
1389
1390 if (m_taintforce)
1391 changeAddForce(timestep);
1392
1393 if (m_taintaddangularforce)
1394 changeAddAngularForce(timestep);
1395
1396 if (!m_taintTorque.ApproxEquals(Vector3.Zero, 0.001f))
1397 changeSetTorque(timestep);
1398
1399 if (m_taintdisable)
1400 changedisable(timestep);
1401
1402 if (m_taintselected != m_isSelected)
1403 changeSelectedStatus(timestep);
1404
1405 if (!m_taintVelocity.ApproxEquals(Vector3.Zero, 0.001f))
1406 changevelocity(timestep);
1407
1408 if (m_taintparent != _parent)
1409 changelink(timestep);
1410
1411 if (m_taintCollidesWater != m_collidesWater)
1412 changefloatonwater(timestep);
1413/* obsolete
1414 if (!m_angularLock.ApproxEquals(m_taintAngularLock,0f))
1415 changeAngularLock(timestep);
1416 */
1417 }
1418 else
1419 {
1420 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.)");
1421 }
1422 }
1423
1424/* obsolete
1425 private void changeAngularLock(float timestep)
1426 {
1427 if (_parent == null)
1428 {
1429 m_angularLock = m_taintAngularLock;
1430 m_angularLockSet = true;
1431 }
1432 }
1433 */
1434 private void changelink(float timestep)
1435 {
1436 // If the newly set parent is not null
1437 // create link
1438 if (_parent == null && m_taintparent != null)
1439 {
1440 if (m_taintparent.PhysicsActorType == (int)ActorTypes.Prim)
1441 {
1442 OdePrim obj = (OdePrim)m_taintparent;
1443 //obj.disableBody();
1444 obj.ParentPrim(this);
1445
1446 /*
1447 if (obj.Body != (IntPtr)0 && Body != (IntPtr)0 && obj.Body != Body)
1448 {
1449 _linkJointGroup = d.JointGroupCreate(0);
1450 m_linkJoint = d.JointCreateFixed(_parent_scene.world, _linkJointGroup);
1451 d.JointAttach(m_linkJoint, obj.Body, Body);
1452 d.JointSetFixed(m_linkJoint);
1453 }
1454 */
1455 }
1456 }
1457 // If the newly set parent is null
1458 // destroy link
1459 else if (_parent != null && m_taintparent == null)
1460 {
1461 if (_parent is OdePrim)
1462 {
1463 OdePrim obj = (OdePrim)_parent;
1464 obj.ChildDelink(this);
1465 childPrim = false;
1466 //_parent = null;
1467 }
1468
1469 /*
1470 if (Body != (IntPtr)0 && _linkJointGroup != (IntPtr)0)
1471 d.JointGroupDestroy(_linkJointGroup);
1472
1473 _linkJointGroup = (IntPtr)0;
1474 m_linkJoint = (IntPtr)0;
1475 */
1476 }
1477
1478 _parent = m_taintparent;
1479 m_taintPhysics = m_isphysical;
1480 }
1481
1482 // I'm the parent
1483 // prim is the child
1484 public void ParentPrim(OdePrim prim)
1485 {
1486 if (this.m_localID != prim.m_localID)
1487 {
1488 if (Body == IntPtr.Zero)
1489 {
1490 Body = d.BodyCreate(_parent_scene.world);
1491 // disconnect from world gravity so we can apply buoyancy
1492 d.BodySetGravityMode (Body, false);
1493
1494 setMass();
1495 }
1496 if (Body != IntPtr.Zero)
1497 {
1498 lock (childrenPrim)
1499 {
1500 if (!childrenPrim.Contains(prim))
1501 {
1502 childrenPrim.Add(prim);
1503
1504 foreach (OdePrim prm in childrenPrim)
1505 {
1506 d.Mass m2;
1507 d.MassSetZero(out m2);
1508 d.MassSetBoxTotal(out m2, prim.CalculateMass(), prm._size.X, prm._size.Y, prm._size.Z);
1509
1510
1511 d.Quaternion quat = new d.Quaternion();
1512 quat.W = prm._orientation.W;
1513 quat.X = prm._orientation.X;
1514 quat.Y = prm._orientation.Y;
1515 quat.Z = prm._orientation.Z;
1516
1517 d.Matrix3 mat = new d.Matrix3();
1518 d.RfromQ(out mat, ref quat);
1519 d.MassRotate(ref m2, ref mat);
1520 d.MassTranslate(ref m2, Position.X - prm.Position.X, Position.Y - prm.Position.Y, Position.Z - prm.Position.Z);
1521 d.MassAdd(ref pMass, ref m2);
1522 }
1523 foreach (OdePrim prm in childrenPrim)
1524 {
1525
1526 prm.m_collisionCategories |= CollisionCategories.Body;
1527 prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1528
1529 if (prm.prim_geom == IntPtr.Zero)
1530 {
1531 m_log.Warn("[PHYSICS]: Unable to link one of the linkset elements. No geom yet");
1532 continue;
1533 }
1534 d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories);
1535 d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags);
1536
1537
1538 d.Quaternion quat = new d.Quaternion();
1539 quat.W = prm._orientation.W;
1540 quat.X = prm._orientation.X;
1541 quat.Y = prm._orientation.Y;
1542 quat.Z = prm._orientation.Z;
1543
1544 d.Matrix3 mat = new d.Matrix3();
1545 d.RfromQ(out mat, ref quat);
1546 if (Body != IntPtr.Zero)
1547 {
1548 d.GeomSetBody(prm.prim_geom, Body);
1549 prm.childPrim = true;
1550 d.GeomSetOffsetWorldPosition(prm.prim_geom, prm.Position.X , prm.Position.Y, prm.Position.Z);
1551 //d.GeomSetOffsetPosition(prim.prim_geom,
1552 // (Position.X - prm.Position.X) - pMass.c.X,
1553 // (Position.Y - prm.Position.Y) - pMass.c.Y,
1554 // (Position.Z - prm.Position.Z) - pMass.c.Z);
1555 d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat);
1556 //d.GeomSetOffsetRotation(prm.prim_geom, ref mat);
1557 d.MassTranslate(ref pMass, -pMass.c.X, -pMass.c.Y, -pMass.c.Z);
1558 d.BodySetMass(Body, ref pMass);
1559 }
1560 else
1561 {
1562 m_log.Debug("[PHYSICS]:I ain't got no boooooooooddy, no body");
1563 }
1564
1565
1566 prm.m_interpenetrationcount = 0;
1567 prm.m_collisionscore = 0;
1568 prm.m_disabled = false;
1569
1570 prm.Body = Body;
1571 _parent_scene.addActivePrim(prm);
1572 }
1573 m_collisionCategories |= CollisionCategories.Body;
1574 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1575
1576 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1577 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1578
1579
1580 d.Quaternion quat2 = new d.Quaternion();
1581 quat2.W = _orientation.W;
1582 quat2.X = _orientation.X;
1583 quat2.Y = _orientation.Y;
1584 quat2.Z = _orientation.Z;
1585
1586 d.Matrix3 mat2 = new d.Matrix3();
1587 d.RfromQ(out mat2, ref quat2);
1588 d.GeomSetBody(prim_geom, Body);
1589 d.GeomSetOffsetWorldPosition(prim_geom, Position.X - pMass.c.X, Position.Y - pMass.c.Y, Position.Z - pMass.c.Z);
1590 //d.GeomSetOffsetPosition(prim.prim_geom,
1591 // (Position.X - prm.Position.X) - pMass.c.X,
1592 // (Position.Y - prm.Position.Y) - pMass.c.Y,
1593 // (Position.Z - prm.Position.Z) - pMass.c.Z);
1594 //d.GeomSetOffsetRotation(prim_geom, ref mat2);
1595 d.MassTranslate(ref pMass, -pMass.c.X, -pMass.c.Y, -pMass.c.Z);
1596 d.BodySetMass(Body, ref pMass);
1597
1598 d.BodySetAutoDisableFlag(Body, true);
1599 d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
1600
1601
1602 m_interpenetrationcount = 0;
1603 m_collisionscore = 0;
1604 m_disabled = false;
1605
1606 d.BodySetPosition(Body, Position.X, Position.Y, Position.Z);
1607 if (m_type != Vehicle.TYPE_NONE) Enable(Body, _parent_scene);
1608 _parent_scene.addActivePrim(this);
1609 }
1610 }
1611 }
1612 }
1613
1614 }
1615
1616 private void ChildSetGeom(OdePrim odePrim)
1617 {
1618 //if (m_isphysical && Body != IntPtr.Zero)
1619 lock (childrenPrim)
1620 {
1621 foreach (OdePrim prm in childrenPrim)
1622 {
1623 //prm.childPrim = true;
1624 prm.disableBody();
1625 //prm.m_taintparent = null;
1626 //prm._parent = null;
1627 //prm.m_taintPhysics = false;
1628 //prm.m_disabled = true;
1629 //prm.childPrim = false;
1630 }
1631 }
1632 disableBody();
1633
1634
1635 if (Body != IntPtr.Zero)
1636 {
1637 _parent_scene.remActivePrim(this);
1638 }
1639
1640 lock (childrenPrim)
1641 {
1642 foreach (OdePrim prm in childrenPrim)
1643 {
1644 ParentPrim(prm);
1645 }
1646 }
1647
1648 }
1649
1650 private void ChildDelink(OdePrim odePrim)
1651 {
1652 // Okay, we have a delinked child.. need to rebuild the body.
1653 lock (childrenPrim)
1654 {
1655 foreach (OdePrim prm in childrenPrim)
1656 {
1657 prm.childPrim = true;
1658 prm.disableBody();
1659 //prm.m_taintparent = null;
1660 //prm._parent = null;
1661 //prm.m_taintPhysics = false;
1662 //prm.m_disabled = true;
1663 //prm.childPrim = false;
1664 }
1665 }
1666 disableBody();
1667
1668 lock (childrenPrim)
1669 {
1670 childrenPrim.Remove(odePrim);
1671 }
1672
1673 if (Body != IntPtr.Zero)
1674 {
1675 _parent_scene.remActivePrim(this);
1676 }
1677
1678 lock (childrenPrim)
1679 {
1680 foreach (OdePrim prm in childrenPrim)
1681 {
1682 ParentPrim(prm);
1683 }
1684 }
1685 }
1686
1687 private void changeSelectedStatus(float timestep)
1688 {
1689 if (m_taintselected)
1690 {
1691 m_collisionCategories = CollisionCategories.Selected;
1692 m_collisionFlags = (CollisionCategories.Sensor | CollisionCategories.Space);
1693
1694 // We do the body disable soft twice because 'in theory' a collision could have happened
1695 // in between the disabling and the collision properties setting
1696 // which would wake the physical body up from a soft disabling and potentially cause it to fall
1697 // through the ground.
1698
1699 // NOTE FOR JOINTS: this doesn't always work for jointed assemblies because if you select
1700 // just one part of the assembly, the rest of the assembly is non-selected and still simulating,
1701 // so that causes the selected part to wake up and continue moving.
1702
1703 // even if you select all parts of a jointed assembly, it is not guaranteed that the entire
1704 // assembly will stop simulating during the selection, because of the lack of atomicity
1705 // of select operations (their processing could be interrupted by a thread switch, causing
1706 // simulation to continue before all of the selected object notifications trickle down to
1707 // the physics engine).
1708
1709 // e.g. we select 100 prims that are connected by joints. non-atomically, the first 50 are
1710 // selected and disabled. then, due to a thread switch, the selection processing is
1711 // interrupted and the physics engine continues to simulate, so the last 50 items, whose
1712 // selection was not yet processed, continues to simulate. this wakes up ALL of the
1713 // first 50 again. then the last 50 are disabled. then the first 50, which were just woken
1714 // up, start simulating again, which in turn wakes up the last 50.
1715
1716 if (m_isphysical)
1717 {
1718 disableBodySoft();
1719 }
1720
1721 if (prim_geom != IntPtr.Zero)
1722 {
1723 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1724 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1725 }
1726
1727 if (m_isphysical)
1728 {
1729 disableBodySoft();
1730 }
1731 if (Body != IntPtr.Zero)
1732 {
1733 d.BodySetLinearVel(Body, 0f, 0f, 0f);
1734 d.BodySetForce(Body, 0f, 0f, 0f);
1735 d.BodySetAngularVel (Body, 0.0f, 0.0f, 0.0f);
1736 d.BodySetTorque (Body, 0.0f, 0.0f, 0.0f);
1737 }
1738
1739 }
1740 else
1741 {
1742 m_collisionCategories = CollisionCategories.Geom;
1743
1744 if (m_isphysical)
1745 m_collisionCategories |= CollisionCategories.Body;
1746
1747 m_collisionFlags = m_default_collisionFlags;
1748
1749 if (m_collidesLand)
1750 m_collisionFlags |= CollisionCategories.Land;
1751 if (m_collidesWater)
1752 m_collisionFlags |= CollisionCategories.Water;
1753
1754 if (prim_geom != IntPtr.Zero)
1755 {
1756 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1757 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1758 }
1759 if (Body != IntPtr.Zero)
1760 {
1761 d.BodySetLinearVel(Body, 0f, 0f, 0f);
1762 d.BodySetForce(Body, 0f, 0f, 0f);
1763 d.BodySetAngularVel (Body, 0.0f, 0.0f, 0.0f);
1764 d.BodySetTorque (Body, 0.0f, 0.0f, 0.0f);
1765 }
1766
1767 if (m_isphysical)
1768 {
1769 if (Body != IntPtr.Zero)
1770 {
1771 enableBodySoft();
1772 }
1773 }
1774 }
1775
1776 resetCollisionAccounting();
1777 m_isSelected = m_taintselected;
1778 }//end changeSelectedStatus
1779
1780 public void ResetTaints()
1781 {
1782 m_taintposition = _position;
1783 m_taintrot = _orientation;
1784 m_taintPhysics = m_isphysical;
1785 m_taintselected = m_isSelected;
1786 m_taintsize = _size;
1787 m_taintshape = false;
1788 m_taintforce = false;
1789 m_taintdisable = false;
1790 m_taintVelocity = Vector3.Zero;
1791 }
1792
1793 public void CreateGeom(IntPtr m_targetSpace, IMesh _mesh)
1794 {
1795 if (_mesh != null) // Special - make mesh
1796 {
1797 setMesh(_parent_scene, _mesh);
1798 }
1799 else // not a mesh
1800 {
1801 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) // special profile??
1802 {
1803 if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) // Equi-size
1804 {
1805 if (((_size.X / 2f) > 0f)) // Has size
1806 {
1807 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1808 try
1809 {
1810 SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2));
1811 }
1812 catch (AccessViolationException)
1813 {
1814 m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
1815 ode.dunlock(_parent_scene.world);
1816 return;
1817 }
1818 }
1819 else
1820 {
1821 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1822 try
1823 {
1824 SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
1825 }
1826 catch (AccessViolationException)
1827 {
1828 m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
1829 ode.dunlock(_parent_scene.world);
1830 return;
1831 }
1832 }
1833 }
1834 else // not equi-size
1835 {
1836 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1837 try
1838 {
1839 SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
1840 }
1841 catch (AccessViolationException)
1842 {
1843 m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
1844 ode.dunlock(_parent_scene.world);
1845 return;
1846 }
1847 }
1848 }
1849
1850 else // not special profile
1851 {
1852 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1853 try
1854 {
1855 SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
1856 }
1857 catch (AccessViolationException)
1858 {
1859 m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
1860 ode.dunlock(_parent_scene.world);
1861 return;
1862 }
1863 }
1864 }
1865 }
1866
1867 public void changeadd(float timestep)
1868 {
1869 int[] iprimspaceArrItem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
1870 IntPtr targetspace = _parent_scene.calculateSpaceForGeom(_position);
1871
1872 if (targetspace == IntPtr.Zero)
1873 targetspace = _parent_scene.createprimspace(iprimspaceArrItem[0], iprimspaceArrItem[1]);
1874
1875 m_targetSpace = targetspace;
1876
1877 if (_mesh == null && m_meshfailed == false)
1878 {
1879 if (_parent_scene.needsMeshing(_pbs))
1880 {
1881 // Don't need to re-enable body.. it's done in SetMesh
1882 try
1883 {
1884 _mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size, _parent_scene.meshSculptLOD, IsPhysical);
1885 }
1886 catch
1887 {
1888 //Don't continuously try to mesh prims when meshing has failed
1889 m_meshfailed = true;
1890 }
1891 // createmesh returns null when it's a shape that isn't a cube.
1892 // m_log.Debug(m_localID);
1893 }
1894 }
1895
1896
1897 lock (_parent_scene.OdeLock)
1898 {
1899 CreateGeom(m_targetSpace, _mesh);
1900
1901 if (prim_geom != IntPtr.Zero)
1902 {
1903 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1904 d.Quaternion myrot = new d.Quaternion();
1905 myrot.X = _orientation.X;
1906 myrot.Y = _orientation.Y;
1907 myrot.Z = _orientation.Z;
1908 myrot.W = _orientation.W;
1909 d.GeomSetQuaternion(prim_geom, ref myrot);
1910 }
1911
1912 if (m_isphysical && Body == IntPtr.Zero)
1913 {
1914 enableBody();
1915 }
1916 }
1917
1918 changeSelectedStatus(timestep);
1919
1920 m_taintadd = false;
1921 }
1922
1923 public void changemove(float timestep)
1924 {
1925 if (m_isphysical)
1926 {
1927// if (!m_disabled && !m_taintremove && !childPrim) After one edit m_disabled is sometimes set, disabling further edits!
1928 if (!m_taintremove && !childPrim)
1929 {
1930 if (Body == IntPtr.Zero)
1931 enableBody();
1932 //Prim auto disable after 20 frames,
1933 //if you move it, re-enable the prim manually.
1934 if (_parent != null)
1935 {
1936 if (m_linkJoint != IntPtr.Zero)
1937 {
1938 d.JointDestroy(m_linkJoint);
1939 m_linkJoint = IntPtr.Zero;
1940 }
1941 }
1942 if (Body != IntPtr.Zero)
1943 {
1944 d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
1945
1946 if (_parent != null)
1947 {
1948 OdePrim odParent = (OdePrim)_parent;
1949 if (Body != (IntPtr)0 && odParent.Body != (IntPtr)0 && Body != odParent.Body)
1950 {
1951// KF: Fixed Joints were removed? Anyway - this Console.WriteLine does not show up, so routine is not used??
1952Console.WriteLine("ODEPrim JointCreateFixed !!!");
1953 m_linkJoint = d.JointCreateFixed(_parent_scene.world, _linkJointGroup);
1954 d.JointAttach(m_linkJoint, Body, odParent.Body);
1955 d.JointSetFixed(m_linkJoint);
1956 }
1957 }
1958 d.BodyEnable(Body);
1959 if (m_type != Vehicle.TYPE_NONE)
1960 {
1961 Enable(Body, _parent_scene);
1962 }
1963 }
1964 else
1965 {
1966 m_log.Warn("[PHYSICS]: Body Still null after enableBody(). This is a crash scenario.");
1967 }
1968 }
1969 //else
1970 // {
1971 //m_log.Debug("[BUG]: race!");
1972 //}
1973 }
1974 else
1975 {
1976 // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
1977 // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
1978 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1979
1980 IntPtr tempspace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position, m_targetSpace);
1981 m_targetSpace = tempspace;
1982
1983 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1984 if (prim_geom != IntPtr.Zero)
1985 {
1986 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1987
1988 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1989 d.SpaceAdd(m_targetSpace, prim_geom);
1990 }
1991 }
1992
1993 changeSelectedStatus(timestep);
1994
1995 resetCollisionAccounting();
1996 m_taintposition = _position;
1997 }
1998
1999
2000
2001 public void rotate(float timestep)
2002 {
2003 d.Quaternion myrot = new d.Quaternion();
2004 myrot.X = _orientation.X;
2005 myrot.Y = _orientation.Y;
2006 myrot.Z = _orientation.Z;
2007 myrot.W = _orientation.W;
2008 if (Body != IntPtr.Zero)
2009 {
2010 // KF: If this is a root prim do BodySet
2011 d.BodySetQuaternion(Body, ref myrot);
2012 }
2013 else
2014 {
2015 // daughter prim, do Geom set
2016 d.GeomSetQuaternion(prim_geom, ref myrot);
2017 }
2018
2019 resetCollisionAccounting();
2020 m_taintrot = _orientation;
2021 }
2022
2023 private void resetCollisionAccounting()
2024 {
2025 m_collisionscore = 0;
2026 m_interpenetrationcount = 0;
2027 m_disabled = false;
2028 }
2029
2030 public void changedisable(float timestep)
2031 {
2032 m_disabled = true;
2033 if (Body != IntPtr.Zero)
2034 {
2035 d.BodyDisable(Body);
2036 Body = IntPtr.Zero;
2037 }
2038
2039 m_taintdisable = false;
2040 }
2041
2042 public void changePhysicsStatus(float timestep)
2043 {
2044 if (m_isphysical == true)
2045 {
2046 if (Body == IntPtr.Zero)
2047 {
2048 if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim)
2049 {
2050 changeshape(2f);
2051 }
2052 else
2053 {
2054 enableBody();
2055 }
2056 }
2057 }
2058 else
2059 {
2060 if (Body != IntPtr.Zero)
2061 {
2062 if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim)
2063 {
2064 _mesh = null;
2065 changeadd(2f);
2066 }
2067 if (childPrim)
2068 {
2069 if (_parent != null)
2070 {
2071 OdePrim parent = (OdePrim)_parent;
2072 parent.ChildDelink(this);
2073 }
2074 }
2075 else
2076 {
2077 disableBody();
2078 }
2079 }
2080 }
2081
2082 changeSelectedStatus(timestep);
2083
2084 resetCollisionAccounting();
2085 m_taintPhysics = m_isphysical;
2086 }
2087
2088 public void changesize(float timestamp)
2089 {
2090
2091 string oldname = _parent_scene.geom_name_map[prim_geom];
2092
2093 if (_size.X <= 0) _size.X = 0.01f;
2094 if (_size.Y <= 0) _size.Y = 0.01f;
2095 if (_size.Z <= 0) _size.Z = 0.01f;
2096
2097 // Cleanup of old prim geometry
2098 if (_mesh != null)
2099 {
2100 // Cleanup meshing here
2101 }
2102 //kill body to rebuild
2103 if (IsPhysical && Body != IntPtr.Zero)
2104 {
2105 if (childPrim)
2106 {
2107 if (_parent != null)
2108 {
2109 OdePrim parent = (OdePrim)_parent;
2110 parent.ChildDelink(this);
2111 }
2112 }
2113 else
2114 {
2115 disableBody();
2116 }
2117 }
2118 if (d.SpaceQuery(m_targetSpace, prim_geom))
2119 {
2120 _parent_scene.waitForSpaceUnlock(m_targetSpace);
2121 d.SpaceRemove(m_targetSpace, prim_geom);
2122 }
2123 // we don't need to do space calculation because the client sends a position update also.
2124
2125 // Construction of new prim
2126 if (_parent_scene.needsMeshing(_pbs) && m_meshfailed == false)
2127 {
2128 float meshlod = _parent_scene.meshSculptLOD;
2129
2130 if (IsPhysical)
2131 meshlod = _parent_scene.MeshSculptphysicalLOD;
2132 // Don't need to re-enable body.. it's done in SetMesh
2133
2134 IMesh mesh = null;
2135
2136 try
2137 {
2138 if (_parent_scene.needsMeshing(_pbs))
2139 mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical);
2140 }
2141 catch
2142 {
2143 m_meshfailed = true;
2144 }
2145
2146 //IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical);
2147 CreateGeom(m_targetSpace, mesh);
2148
2149
2150 }
2151 else
2152 {
2153 _mesh = null;
2154 CreateGeom(m_targetSpace, _mesh);
2155 }
2156
2157 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2158 d.Quaternion myrot = new d.Quaternion();
2159 myrot.X = _orientation.X;
2160 myrot.Y = _orientation.Y;
2161 myrot.Z = _orientation.Z;
2162 myrot.W = _orientation.W;
2163 d.GeomSetQuaternion(prim_geom, ref myrot);
2164
2165 //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
2166 if (IsPhysical && Body == IntPtr.Zero && !childPrim)
2167 {
2168 // Re creates body on size.
2169 // EnableBody also does setMass()
2170 enableBody();
2171 d.BodyEnable(Body);
2172 }
2173
2174 _parent_scene.geom_name_map[prim_geom] = oldname;
2175
2176 changeSelectedStatus(timestamp);
2177 if (childPrim)
2178 {
2179 if (_parent is OdePrim)
2180 {
2181 OdePrim parent = (OdePrim)_parent;
2182 parent.ChildSetGeom(this);
2183 }
2184 }
2185 resetCollisionAccounting();
2186 m_taintsize = _size;
2187 }
2188
2189
2190
2191 public void changefloatonwater(float timestep)
2192 {
2193 m_collidesWater = m_taintCollidesWater;
2194
2195 if (prim_geom != IntPtr.Zero)
2196 {
2197 if (m_collidesWater)
2198 {
2199 m_collisionFlags |= CollisionCategories.Water;
2200 }
2201 else
2202 {
2203 m_collisionFlags &= ~CollisionCategories.Water;
2204 }
2205 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
2206 }
2207 }
2208
2209 public void changeshape(float timestamp)
2210 {
2211 string oldname = _parent_scene.geom_name_map[prim_geom];
2212
2213 // Cleanup of old prim geometry and Bodies
2214 if (IsPhysical && Body != IntPtr.Zero)
2215 {
2216 if (childPrim)
2217 {
2218 if (_parent != null)
2219 {
2220 OdePrim parent = (OdePrim)_parent;
2221 parent.ChildDelink(this);
2222 }
2223 }
2224 else
2225 {
2226 disableBody();
2227 }
2228 }
2229
2230
2231 // we don't need to do space calculation because the client sends a position update also.
2232 if (_size.X <= 0) _size.X = 0.01f;
2233 if (_size.Y <= 0) _size.Y = 0.01f;
2234 if (_size.Z <= 0) _size.Z = 0.01f;
2235 // Construction of new prim
2236
2237 if (_parent_scene.needsMeshing(_pbs) && m_meshfailed == false)
2238 {
2239 // Don't need to re-enable body.. it's done in SetMesh
2240 float meshlod = _parent_scene.meshSculptLOD;
2241
2242 if (IsPhysical)
2243 meshlod = _parent_scene.MeshSculptphysicalLOD;
2244 try
2245 {
2246 IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical);
2247 CreateGeom(m_targetSpace, mesh);
2248 }
2249 catch
2250 {
2251 m_meshfailed = true;
2252 }
2253 // createmesh returns null when it doesn't mesh.
2254 }
2255 else
2256 {
2257 _mesh = null;
2258 CreateGeom(m_targetSpace, null);
2259 }
2260
2261 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2262 d.Quaternion myrot = new d.Quaternion();
2263 //myrot.W = _orientation.w;
2264 myrot.W = _orientation.W;
2265 myrot.X = _orientation.X;
2266 myrot.Y = _orientation.Y;
2267 myrot.Z = _orientation.Z;
2268 d.GeomSetQuaternion(prim_geom, ref myrot);
2269
2270 //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
2271 if (IsPhysical && Body == IntPtr.Zero)
2272 {
2273 // Re creates body on size.
2274 // EnableBody also does setMass()
2275 enableBody();
2276 if (Body != IntPtr.Zero)
2277 {
2278 d.BodyEnable(Body);
2279 }
2280 }
2281 _parent_scene.geom_name_map[prim_geom] = oldname;
2282
2283 changeSelectedStatus(timestamp);
2284 if (childPrim)
2285 {
2286 if (_parent is OdePrim)
2287 {
2288 OdePrim parent = (OdePrim)_parent;
2289 parent.ChildSetGeom(this);
2290 }
2291 }
2292 resetCollisionAccounting();
2293 m_taintshape = false;
2294 }
2295
2296 public void changeAddForce(float timestamp)
2297 {
2298 if (!m_isSelected)
2299 {
2300 lock (m_forcelist)
2301 {
2302 //m_log.Info("[PHYSICS]: dequeing forcelist");
2303 if (IsPhysical)
2304 {
2305 Vector3 iforce = Vector3.Zero;
2306 int i = 0;
2307 try
2308 {
2309 for (i = 0; i < m_forcelist.Count; i++)
2310 {
2311
2312 iforce = iforce + (m_forcelist[i] * 100);
2313 }
2314 }
2315 catch (IndexOutOfRangeException)
2316 {
2317 m_forcelist = new List<Vector3>();
2318 m_collisionscore = 0;
2319 m_interpenetrationcount = 0;
2320 m_taintforce = false;
2321 return;
2322 }
2323 catch (ArgumentOutOfRangeException)
2324 {
2325 m_forcelist = new List<Vector3>();
2326 m_collisionscore = 0;
2327 m_interpenetrationcount = 0;
2328 m_taintforce = false;
2329 return;
2330 }
2331 d.BodyEnable(Body);
2332
2333 d.BodyAddForce(Body, iforce.X, iforce.Y, iforce.Z);
2334 }
2335 m_forcelist.Clear();
2336 }
2337
2338 m_collisionscore = 0;
2339 m_interpenetrationcount = 0;
2340 }
2341
2342 m_taintforce = false;
2343
2344 }
2345
2346
2347
2348 public void changeSetTorque(float timestamp)
2349 {
2350 if (!m_isSelected)
2351 {
2352 if (IsPhysical && Body != IntPtr.Zero)
2353 {
2354 d.BodySetTorque(Body, m_taintTorque.X, m_taintTorque.Y, m_taintTorque.Z);
2355 }
2356 }
2357
2358 m_taintTorque = Vector3.Zero;
2359 }
2360
2361 public void changeAddAngularForce(float timestamp)
2362 {
2363 if (!m_isSelected)
2364 {
2365 lock (m_angularforcelist)
2366 {
2367 //m_log.Info("[PHYSICS]: dequeing forcelist");
2368 if (IsPhysical)
2369 {
2370 Vector3 iforce = Vector3.Zero;
2371 for (int i = 0; i < m_angularforcelist.Count; i++)
2372 {
2373 iforce = iforce + (m_angularforcelist[i] * 100);
2374 }
2375 d.BodyEnable(Body);
2376 d.BodyAddTorque(Body, iforce.X, iforce.Y, iforce.Z);
2377
2378 }
2379 m_angularforcelist.Clear();
2380 }
2381
2382 m_collisionscore = 0;
2383 m_interpenetrationcount = 0;
2384 }
2385
2386 m_taintaddangularforce = false;
2387 }
2388
2389 private void changevelocity(float timestep)
2390 {
2391 if (!m_isSelected)
2392 {
2393 Thread.Sleep(20);
2394 if (IsPhysical)
2395 {
2396 if (Body != IntPtr.Zero)
2397 d.BodySetLinearVel(Body, m_taintVelocity.X, m_taintVelocity.Y, m_taintVelocity.Z);
2398 }
2399
2400 //resetCollisionAccounting();
2401 }
2402 m_taintVelocity = Vector3.Zero;
2403 }
2404
2405 public void UpdatePositionAndVelocity()
2406 {
2407 return; // moved to the Move () method
2408 }
2409
2410 public d.Mass FromMatrix4(Matrix4 pMat, ref d.Mass obj)
2411 {
2412 obj.I.M00 = pMat[0, 0];
2413 obj.I.M01 = pMat[0, 1];
2414 obj.I.M02 = pMat[0, 2];
2415 obj.I.M10 = pMat[1, 0];
2416 obj.I.M11 = pMat[1, 1];
2417 obj.I.M12 = pMat[1, 2];
2418 obj.I.M20 = pMat[2, 0];
2419 obj.I.M21 = pMat[2, 1];
2420 obj.I.M22 = pMat[2, 2];
2421 return obj;
2422 }
2423
2424 public override void SubscribeEvents(int ms)
2425 {
2426 m_eventsubscription = ms;
2427 _parent_scene.addCollisionEventReporting(this);
2428 }
2429
2430 public override void UnSubscribeEvents()
2431 {
2432 _parent_scene.remCollisionEventReporting(this);
2433 m_eventsubscription = 0;
2434 }
2435
2436 public void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
2437 {
2438 if (CollisionEventsThisFrame == null)
2439 CollisionEventsThisFrame = new CollisionEventUpdate();
2440 CollisionEventsThisFrame.addCollider(CollidedWith, contact);
2441 }
2442
2443 public void SendCollisions()
2444 {
2445 if (CollisionEventsThisFrame == null)
2446 return;
2447
2448 base.SendCollisionUpdate(CollisionEventsThisFrame);
2449
2450 if (CollisionEventsThisFrame.m_objCollisionList.Count == 0)
2451 CollisionEventsThisFrame = null;
2452 else
2453 CollisionEventsThisFrame = new CollisionEventUpdate();
2454 }
2455
2456 public override bool SubscribedEvents()
2457 {
2458 if (m_eventsubscription > 0)
2459 return true;
2460 return false;
2461 }
2462
2463 public static Matrix4 Inverse(Matrix4 pMat)
2464 {
2465 if (determinant3x3(pMat) == 0)
2466 {
2467 return Matrix4.Identity; // should probably throw an error. singluar matrix inverse not possible
2468 }
2469
2470
2471
2472 return (Adjoint(pMat) / determinant3x3(pMat));
2473 }
2474
2475 public static Matrix4 Adjoint(Matrix4 pMat)
2476 {
2477 Matrix4 adjointMatrix = new Matrix4();
2478 for (int i=0; i<4; i++)
2479 {
2480 for (int j=0; j<4; j++)
2481 {
2482 Matrix4SetValue(ref adjointMatrix, i, j, (float)(Math.Pow(-1, i + j) * (determinant3x3(Minor(pMat, i, j)))));
2483 }
2484 }
2485
2486 adjointMatrix = Transpose(adjointMatrix);
2487 return adjointMatrix;
2488 }
2489
2490 public static Matrix4 Minor(Matrix4 matrix, int iRow, int iCol)
2491 {
2492 Matrix4 minor = new Matrix4();
2493 int m = 0, n = 0;
2494 for (int i = 0; i < 4; i++)
2495 {
2496 if (i == iRow)
2497 continue;
2498 n = 0;
2499 for (int j = 0; j < 4; j++)
2500 {
2501 if (j == iCol)
2502 continue;
2503 Matrix4SetValue(ref minor, m,n, matrix[i, j]);
2504 n++;
2505 }
2506 m++;
2507 }
2508 return minor;
2509 }
2510
2511 public static Matrix4 Transpose(Matrix4 pMat)
2512 {
2513 Matrix4 transposeMatrix = new Matrix4();
2514 for (int i = 0; i < 4; i++)
2515 for (int j = 0; j < 4; j++)
2516 Matrix4SetValue(ref transposeMatrix, i, j, pMat[j, i]);
2517 return transposeMatrix;
2518 }
2519
2520 public static void Matrix4SetValue(ref Matrix4 pMat, int r, int c, float val)
2521 {
2522 switch (r)
2523 {
2524 case 0:
2525 switch (c)
2526 {
2527 case 0:
2528 pMat.M11 = val;
2529 break;
2530 case 1:
2531 pMat.M12 = val;
2532 break;
2533 case 2:
2534 pMat.M13 = val;
2535 break;
2536 case 3:
2537 pMat.M14 = val;
2538 break;
2539 }
2540
2541 break;
2542 case 1:
2543 switch (c)
2544 {
2545 case 0:
2546 pMat.M21 = val;
2547 break;
2548 case 1:
2549 pMat.M22 = val;
2550 break;
2551 case 2:
2552 pMat.M23 = val;
2553 break;
2554 case 3:
2555 pMat.M24 = val;
2556 break;
2557 }
2558
2559 break;
2560 case 2:
2561 switch (c)
2562 {
2563 case 0:
2564 pMat.M31 = val;
2565 break;
2566 case 1:
2567 pMat.M32 = val;
2568 break;
2569 case 2:
2570 pMat.M33 = val;
2571 break;
2572 case 3:
2573 pMat.M34 = val;
2574 break;
2575 }
2576
2577 break;
2578 case 3:
2579 switch (c)
2580 {
2581 case 0:
2582 pMat.M41 = val;
2583 break;
2584 case 1:
2585 pMat.M42 = val;
2586 break;
2587 case 2:
2588 pMat.M43 = val;
2589 break;
2590 case 3:
2591 pMat.M44 = val;
2592 break;
2593 }
2594
2595 break;
2596 }
2597 }
2598 private static float determinant3x3(Matrix4 pMat)
2599 {
2600 float det = 0;
2601 float diag1 = pMat[0, 0]*pMat[1, 1]*pMat[2, 2];
2602 float diag2 = pMat[0, 1]*pMat[2, 1]*pMat[2, 0];
2603 float diag3 = pMat[0, 2]*pMat[1, 0]*pMat[2, 1];
2604 float diag4 = pMat[2, 0]*pMat[1, 1]*pMat[0, 2];
2605 float diag5 = pMat[2, 1]*pMat[1, 2]*pMat[0, 0];
2606 float diag6 = pMat[2, 2]*pMat[1, 0]*pMat[0, 1];
2607
2608 det = diag1 + diag2 + diag3 - (diag4 + diag5 + diag6);
2609 return det;
2610
2611 }
2612
2613 private static void DMassCopy(ref d.Mass src, ref d.Mass dst)
2614 {
2615 dst.c.W = src.c.W;
2616 dst.c.X = src.c.X;
2617 dst.c.Y = src.c.Y;
2618 dst.c.Z = src.c.Z;
2619 dst.mass = src.mass;
2620 dst.I.M00 = src.I.M00;
2621 dst.I.M01 = src.I.M01;
2622 dst.I.M02 = src.I.M02;
2623 dst.I.M10 = src.I.M10;
2624 dst.I.M11 = src.I.M11;
2625 dst.I.M12 = src.I.M12;
2626 dst.I.M20 = src.I.M20;
2627 dst.I.M21 = src.I.M21;
2628 dst.I.M22 = src.I.M22;
2629 }
2630
2631 public override void SetMaterial(int pMaterial)
2632 {
2633 m_material = pMaterial;
2634 }
2635
2636 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
2637 {
2638 switch (pParam)
2639 {
2640 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
2641 if (pValue < 0.01f) pValue = 0.01f;
2642 // m_angularDeflectionEfficiency = pValue;
2643 break;
2644 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
2645 if (pValue < 0.1f) pValue = 0.1f;
2646 // m_angularDeflectionTimescale = pValue;
2647 break;
2648 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
2649 if (pValue < 0.3f) pValue = 0.3f;
2650 m_angularMotorDecayTimescale = pValue;
2651 break;
2652 case Vehicle.ANGULAR_MOTOR_TIMESCALE:
2653 if (pValue < 0.3f) pValue = 0.3f;
2654 m_angularMotorTimescale = pValue;
2655 break;
2656 case Vehicle.BANKING_EFFICIENCY:
2657 if (pValue < 0.01f) pValue = 0.01f;
2658 // m_bankingEfficiency = pValue;
2659 break;
2660 case Vehicle.BANKING_MIX:
2661 if (pValue < 0.01f) pValue = 0.01f;
2662 // m_bankingMix = pValue;
2663 break;
2664 case Vehicle.BANKING_TIMESCALE:
2665 if (pValue < 0.01f) pValue = 0.01f;
2666 // m_bankingTimescale = pValue;
2667 break;
2668 case Vehicle.BUOYANCY:
2669 if (pValue < -1f) pValue = -1f;
2670 if (pValue > 1f) pValue = 1f;
2671 m_VehicleBuoyancy = pValue;
2672 break;
2673// case Vehicle.HOVER_EFFICIENCY:
2674// if (pValue < 0f) pValue = 0f;
2675// if (pValue > 1f) pValue = 1f;
2676// m_VhoverEfficiency = pValue;
2677// break;
2678 case Vehicle.HOVER_HEIGHT:
2679 m_VhoverHeight = pValue;
2680 break;
2681 case Vehicle.HOVER_TIMESCALE:
2682 if (pValue < 0.1f) pValue = 0.1f;
2683 m_VhoverTimescale = pValue;
2684 break;
2685 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
2686 if (pValue < 0.01f) pValue = 0.01f;
2687 // m_linearDeflectionEfficiency = pValue;
2688 break;
2689 case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
2690 if (pValue < 0.01f) pValue = 0.01f;
2691 // m_linearDeflectionTimescale = pValue;
2692 break;
2693 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
2694 if (pValue < 0.3f) pValue = 0.3f;
2695 m_linearMotorDecayTimescale = pValue;
2696 break;
2697 case Vehicle.LINEAR_MOTOR_TIMESCALE:
2698 if (pValue < 0.1f) pValue = 0.1f;
2699 m_linearMotorTimescale = pValue;
2700 break;
2701 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
2702 if (pValue < 0.1f) pValue = 0.1f; // Less goes unstable
2703 if (pValue > 1.0f) pValue = 1.0f;
2704 m_verticalAttractionEfficiency = pValue;
2705 break;
2706 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
2707 if (pValue < 0.1f) pValue = 0.1f;
2708 m_verticalAttractionTimescale = pValue;
2709 break;
2710
2711 // These are vector properties but the engine lets you use a single float value to
2712 // set all of the components to the same value
2713 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
2714 if (pValue > 30f) pValue = 30f;
2715 if (pValue < 0.1f) pValue = 0.1f;
2716 m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
2717 break;
2718 case Vehicle.ANGULAR_MOTOR_DIRECTION:
2719 m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
2720 UpdateAngDecay();
2721 break;
2722 case Vehicle.LINEAR_FRICTION_TIMESCALE:
2723 if (pValue < 0.1f) pValue = 0.1f;
2724 m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
2725 break;
2726 case Vehicle.LINEAR_MOTOR_DIRECTION:
2727 m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
2728 UpdateLinDecay();
2729 break;
2730 case Vehicle.LINEAR_MOTOR_OFFSET:
2731 // m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
2732 break;
2733
2734 }
2735
2736 }//end ProcessFloatVehicleParam
2737
2738 internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue)
2739 {
2740 switch (pParam)
2741 {
2742 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
2743 if (pValue.X > 30f) pValue.X = 30f;
2744 if (pValue.X < 0.1f) pValue.X = 0.1f;
2745 if (pValue.Y > 30f) pValue.Y = 30f;
2746 if (pValue.Y < 0.1f) pValue.Y = 0.1f;
2747 if (pValue.Z > 30f) pValue.Z = 30f;
2748 if (pValue.Z < 0.1f) pValue.Z = 0.1f;
2749 m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
2750 break;
2751 case Vehicle.ANGULAR_MOTOR_DIRECTION:
2752 m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
2753 // Limit requested angular speed to 2 rps= 4 pi rads/sec
2754 if(m_angularMotorDirection.X > 12.56f) m_angularMotorDirection.X = 12.56f;
2755 if(m_angularMotorDirection.X < - 12.56f) m_angularMotorDirection.X = - 12.56f;
2756 if(m_angularMotorDirection.Y > 12.56f) m_angularMotorDirection.Y = 12.56f;
2757 if(m_angularMotorDirection.Y < - 12.56f) m_angularMotorDirection.Y = - 12.56f;
2758 if(m_angularMotorDirection.Z > 12.56f) m_angularMotorDirection.Z = 12.56f;
2759 if(m_angularMotorDirection.Z < - 12.56f) m_angularMotorDirection.Z = - 12.56f;
2760 UpdateAngDecay();
2761 break;
2762 case Vehicle.LINEAR_FRICTION_TIMESCALE:
2763 if (pValue.X < 0.1f) pValue.X = 0.1f;
2764 if (pValue.Y < 0.1f) pValue.Y = 0.1f;
2765 if (pValue.Z < 0.1f) pValue.Z = 0.1f;
2766 m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
2767 break;
2768 case Vehicle.LINEAR_MOTOR_DIRECTION:
2769 m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); // velocity requested by LSL, for max limiting
2770 UpdateLinDecay();
2771 break;
2772 case Vehicle.LINEAR_MOTOR_OFFSET:
2773 // m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z);
2774 break;
2775 }
2776
2777 }//end ProcessVectorVehicleParam
2778
2779 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
2780 {
2781 switch (pParam)
2782 {
2783 case Vehicle.REFERENCE_FRAME:
2784 // m_referenceFrame = pValue;
2785 break;
2786 }
2787
2788 }//end ProcessRotationVehicleParam
2789
2790 internal void ProcessVehicleFlags(int pParam, bool remove)
2791 {
2792 if (remove)
2793 {
2794 m_flags &= ~((VehicleFlag)pParam);
2795 }
2796 else
2797 {
2798 m_flags |= (VehicleFlag)pParam;
2799 }
2800 }
2801
2802 internal void ProcessTypeChange(Vehicle pType)
2803 {
2804 // Set Defaults For Type
2805 m_type = pType;
2806 switch (pType)
2807 {
2808 case Vehicle.TYPE_SLED:
2809 m_linearFrictionTimescale = new Vector3(30, 1, 1000);
2810 m_angularFrictionTimescale = new Vector3(30, 30, 30);
2811// m_lLinMotorVel = Vector3.Zero;
2812 m_linearMotorTimescale = 1000;
2813 m_linearMotorDecayTimescale = 120;
2814 m_angularMotorDirection = Vector3.Zero;
2815 m_angularMotorDVel = Vector3.Zero;
2816 m_angularMotorTimescale = 1000;
2817 m_angularMotorDecayTimescale = 120;
2818 m_VhoverHeight = 0;
2819// m_VhoverEfficiency = 1;
2820 m_VhoverTimescale = 10;
2821 m_VehicleBuoyancy = 0;
2822 // m_linearDeflectionEfficiency = 1;
2823 // m_linearDeflectionTimescale = 1;
2824 // m_angularDeflectionEfficiency = 1;
2825 // m_angularDeflectionTimescale = 1000;
2826 // m_bankingEfficiency = 0;
2827 // m_bankingMix = 1;
2828 // m_bankingTimescale = 10;
2829 // m_referenceFrame = Quaternion.Identity;
2830 m_flags &=
2831 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
2832 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
2833 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
2834 break;
2835 case Vehicle.TYPE_CAR:
2836 m_linearFrictionTimescale = new Vector3(100, 2, 1000);
2837 m_angularFrictionTimescale = new Vector3(30, 30, 30); // was 1000, but sl max frict time is 30.
2838// m_lLinMotorVel = Vector3.Zero;
2839 m_linearMotorTimescale = 1;
2840 m_linearMotorDecayTimescale = 60;
2841 m_angularMotorDirection = Vector3.Zero;
2842 m_angularMotorDVel = Vector3.Zero;
2843 m_angularMotorTimescale = 1;
2844 m_angularMotorDecayTimescale = 0.8f;
2845 m_VhoverHeight = 0;
2846// m_VhoverEfficiency = 0;
2847 m_VhoverTimescale = 1000;
2848 m_VehicleBuoyancy = 0;
2849 // // m_linearDeflectionEfficiency = 1;
2850 // // m_linearDeflectionTimescale = 2;
2851 // // m_angularDeflectionEfficiency = 0;
2852 // m_angularDeflectionTimescale = 10;
2853 m_verticalAttractionEfficiency = 1f;
2854 m_verticalAttractionTimescale = 10f;
2855 // m_bankingEfficiency = -0.2f;
2856 // m_bankingMix = 1;
2857 // m_bankingTimescale = 1;
2858 // m_referenceFrame = Quaternion.Identity;
2859 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
2860 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.HOVER_UP_ONLY |
2861 VehicleFlag.LIMIT_MOTOR_UP);
2862 break;
2863 case Vehicle.TYPE_BOAT:
2864 m_linearFrictionTimescale = new Vector3(10, 3, 2);
2865 m_angularFrictionTimescale = new Vector3(10,10,10);
2866// m_lLinMotorVel = Vector3.Zero;
2867 m_linearMotorTimescale = 5;
2868 m_linearMotorDecayTimescale = 60;
2869 m_angularMotorDirection = Vector3.Zero;
2870 m_angularMotorDVel = Vector3.Zero;
2871 m_angularMotorTimescale = 4;
2872 m_angularMotorDecayTimescale = 4;
2873 m_VhoverHeight = 0;
2874// m_VhoverEfficiency = 0.5f;
2875 m_VhoverTimescale = 2;
2876 m_VehicleBuoyancy = 1;
2877 // m_linearDeflectionEfficiency = 0.5f;
2878 // m_linearDeflectionTimescale = 3;
2879 // m_angularDeflectionEfficiency = 0.5f;
2880 // m_angularDeflectionTimescale = 5;
2881 m_verticalAttractionEfficiency = 0.5f;
2882 m_verticalAttractionTimescale = 5f;
2883 // m_bankingEfficiency = -0.3f;
2884 // m_bankingMix = 0.8f;
2885 // m_bankingTimescale = 1;
2886 // m_referenceFrame = Quaternion.Identity;
2887 m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.LIMIT_ROLL_ONLY |
2888 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
2889 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY |
2890 VehicleFlag.LIMIT_MOTOR_UP);
2891 break;
2892 case Vehicle.TYPE_AIRPLANE:
2893 m_linearFrictionTimescale = new Vector3(200, 10, 5);
2894 m_angularFrictionTimescale = new Vector3(20, 20, 20);
2895// m_lLinMotorVel = Vector3.Zero;
2896 m_linearMotorTimescale = 2;
2897 m_linearMotorDecayTimescale = 60;
2898 m_angularMotorDirection = Vector3.Zero;
2899 m_angularMotorDVel = Vector3.Zero;
2900 m_angularMotorTimescale = 4;
2901 m_angularMotorDecayTimescale = 4;
2902 m_VhoverHeight = 0;
2903// m_VhoverEfficiency = 0.5f;
2904 m_VhoverTimescale = 1000;
2905 m_VehicleBuoyancy = 0;
2906 // m_linearDeflectionEfficiency = 0.5f;
2907 // m_linearDeflectionTimescale = 3;
2908 // m_angularDeflectionEfficiency = 1;
2909 // m_angularDeflectionTimescale = 2;
2910 m_verticalAttractionEfficiency = 0.9f;
2911 m_verticalAttractionTimescale = 2f;
2912 // m_bankingEfficiency = 1;
2913 // m_bankingMix = 0.7f;
2914 // m_bankingTimescale = 2;
2915 // m_referenceFrame = Quaternion.Identity;
2916 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
2917 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
2918 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
2919 break;
2920 case Vehicle.TYPE_BALLOON:
2921 m_linearFrictionTimescale = new Vector3(5, 5, 5);
2922 m_angularFrictionTimescale = new Vector3(10, 10, 10);
2923 m_linearMotorTimescale = 5;
2924 m_linearMotorDecayTimescale = 60;
2925 m_angularMotorDirection = Vector3.Zero;
2926 m_angularMotorDVel = Vector3.Zero;
2927 m_angularMotorTimescale = 6;
2928 m_angularMotorDecayTimescale = 10;
2929 m_VhoverHeight = 5;
2930// m_VhoverEfficiency = 0.8f;
2931 m_VhoverTimescale = 10;
2932 m_VehicleBuoyancy = 1;
2933 // m_linearDeflectionEfficiency = 0;
2934 // m_linearDeflectionTimescale = 5;
2935 // m_angularDeflectionEfficiency = 0;
2936 // m_angularDeflectionTimescale = 5;
2937 m_verticalAttractionEfficiency = 1f;
2938 m_verticalAttractionTimescale = 100f;
2939 // m_bankingEfficiency = 0;
2940 // m_bankingMix = 0.7f;
2941 // m_bankingTimescale = 5;
2942 // m_referenceFrame = Quaternion.Identity;
2943 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
2944 VehicleFlag.HOVER_UP_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
2945 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
2946 break;
2947
2948 }
2949 }//end SetDefaultsForType
2950
2951 internal void Enable(IntPtr pBody, OdeScene pParentScene)
2952 {
2953 if (m_type == Vehicle.TYPE_NONE)
2954 return;
2955
2956 m_body = pBody;
2957 }
2958
2959
2960 internal void Halt()
2961 { // Kill all motions, when non-physical
2962 // m_linearMotorDirection = Vector3.Zero;
2963 m_lLinMotorDVel = Vector3.Zero;
2964 m_lLinObjectVel = Vector3.Zero;
2965 m_wLinObjectVel = Vector3.Zero;
2966 m_angularMotorDirection = Vector3.Zero;
2967 m_lastAngularVelocity = Vector3.Zero;
2968 m_angularMotorDVel = Vector3.Zero;
2969 _acceleration = Vector3.Zero;
2970 }
2971
2972 private void UpdateLinDecay()
2973 {
2974// if (Math.Abs(m_linearMotorDirection.X) > Math.Abs(m_lLinMotorDVel.X)) m_lLinMotorDVel.X = m_linearMotorDirection.X;
2975// if (Math.Abs(m_linearMotorDirection.Y) > Math.Abs(m_lLinMotorDVel.Y)) m_lLinMotorDVel.Y = m_linearMotorDirection.Y;
2976// if (Math.Abs(m_linearMotorDirection.Z) > Math.Abs(m_lLinMotorDVel.Z)) m_lLinMotorDVel.Z = m_linearMotorDirection.Z;
2977 m_lLinMotorDVel.X = m_linearMotorDirection.X;
2978 m_lLinMotorDVel.Y = m_linearMotorDirection.Y;
2979 m_lLinMotorDVel.Z = m_linearMotorDirection.Z;
2980 } // else let the motor decay on its own
2981
2982 private void UpdateAngDecay()
2983 {
2984// if (Math.Abs(m_angularMotorDirection.X) > Math.Abs(m_angularMotorDVel.X)) m_angularMotorDVel.X = m_angularMotorDirection.X;
2985// if (Math.Abs(m_angularMotorDirection.Y) > Math.Abs(m_angularMotorDVel.Y)) m_angularMotorDVel.Y = m_angularMotorDirection.Y;
2986// if (Math.Abs(m_angularMotorDirection.Z) > Math.Abs(m_angularMotorDVel.Z)) m_angularMotorDVel.Z = m_angularMotorDirection.Z;
2987 m_angularMotorDVel.X = m_angularMotorDirection.X;
2988 m_angularMotorDVel.Y = m_angularMotorDirection.Y;
2989 m_angularMotorDVel.Z = m_angularMotorDirection.Z;
2990 } // else let the motor decay on its own
2991
2992 public void Move(float timestep)
2993 {
2994 float fx = 0;
2995 float fy = 0;
2996 float fz = 0;
2997 Vector3 linvel; // velocity applied, including any reversal
2998 int outside = 0;
2999
3000 // If geomCrossingFailuresBeforeOutofbounds is set to 0 in OpenSim.ini then phys objects bounce off region borders.
3001 // This is a temp patch until proper region crossing is developed.
3002
3003 int failureLimit = _parent_scene.geomCrossingFailuresBeforeOutofbounds;
3004 float fence = _parent_scene.geomRegionFence;
3005
3006 frcount++; // used to limit debug comment output
3007 if (frcount > 50)
3008 frcount = 0;
3009
3010 if(revcount > 0) revcount--;
3011
3012 if (IsPhysical && (Body != IntPtr.Zero) && !m_isSelected && !childPrim) // Only move root prims.
3013 {
3014 // Old public void UpdatePositionAndVelocity(), more accuratley calculated here
3015 bool lastZeroFlag = _zeroFlag; // was it stopped
3016
3017 d.Vector3 vec = d.BodyGetPosition(Body);
3018 Vector3 l_position = Vector3.Zero;
3019 l_position.X = vec.X;
3020 l_position.Y = vec.Y;
3021 l_position.Z = vec.Z;
3022 m_lastposition = _position;
3023 _position = l_position;
3024
3025 d.Quaternion ori = d.BodyGetQuaternion(Body);
3026 // Quaternion l_orientation = Quaternion.Identity;
3027 _orientation.X = ori.X;
3028 _orientation.Y = ori.Y;
3029 _orientation.Z = ori.Z;
3030 _orientation.W = ori.W;
3031 m_lastorientation = _orientation;
3032
3033 d.Vector3 vel = d.BodyGetLinearVel(Body);
3034 m_lastVelocity = _velocity;
3035 _velocity.X = vel.X;
3036 _velocity.Y = vel.Y;
3037 _velocity.Z = vel.Z;
3038 _acceleration = ((_velocity - m_lastVelocity) / timestep);
3039
3040 d.Vector3 torque = d.BodyGetTorque(Body);
3041 _torque = new Vector3(torque.X, torque.Y, torque.Z);
3042
3043 base.RequestPhysicsterseUpdate();
3044
3045//Console.WriteLine("Move {0} at {1}", m_primName, l_position);
3046
3047 // Check if outside region
3048 // In Scene.cs/CrossPrimGroupIntoNewRegion the object is checked for 0.1M from border!
3049 if (l_position.X > ((float)_parent_scene.WorldExtents.X - fence))
3050 {
3051 l_position.X = ((float)_parent_scene.WorldExtents.X - fence);
3052 outside = 1;
3053 }
3054
3055 if (l_position.X < fence)
3056 {
3057 l_position.X = fence;
3058 outside = 2;
3059 }
3060 if (l_position.Y > ((float)_parent_scene.WorldExtents.Y - fence))
3061 {
3062 l_position.Y = ((float)_parent_scene.WorldExtents.Y - fence);
3063 outside = 3;
3064 }
3065
3066 if (l_position.Y < fence)
3067 {
3068 l_position.Y = fence;
3069 outside = 4;
3070 }
3071
3072 if (outside > 0)
3073 {
3074
3075//Console.WriteLine("Border {0} fence={1}", l_position, fence);
3076 if (fence > 0.0f) // bounce object off boundary
3077 {
3078 if (revcount == 0)
3079 {
3080 if (outside < 3)
3081 {
3082 _velocity.X = -_velocity.X;
3083 }
3084 else
3085 {
3086 _velocity.Y = -_velocity.Y;
3087 }
3088 if (m_type != Vehicle.TYPE_NONE) Halt();
3089 _position = l_position;
3090 m_taintposition = _position;
3091 m_lastVelocity = _velocity;
3092 _acceleration = Vector3.Zero;
3093 d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
3094 d.BodySetLinearVel(Body, _velocity.X, _velocity.Y, _velocity.Z);
3095 base.RequestPhysicsterseUpdate();
3096
3097 revcount = 25; // wait for object to move away from border
3098 }
3099 } // else old crossing mode
3100 else if (m_crossingfailures < failureLimit)
3101 { // keep trying to cross?
3102 _position = l_position;
3103 //_parent_scene.remActivePrim(this);
3104 if (_parent == null) base.RequestPhysicsterseUpdate();
3105 return; // Dont process any other motion?
3106 }
3107 else
3108 { // Too many tries
3109 if (_parent == null) base.RaiseOutOfBounds(l_position);
3110 return; // Dont process any other motion?
3111 } // end various methods
3112 } // end outside region horizontally
3113
3114
3115 if (l_position.Z < 0)
3116 {
3117 // This is so prim that get lost underground don't fall forever and suck up
3118 //
3119 // Sim resources and memory.
3120 // Disables the prim's movement physics....
3121 // It's a hack and will generate a console message if it fails.
3122
3123 //IsPhysical = false;
3124 if (_parent == null) base.RaiseOutOfBounds(_position);
3125
3126
3127 _acceleration.X = 0; // This stuff may stop client display but it has no
3128 _acceleration.Y = 0; // effect on the object in phys engine!
3129 _acceleration.Z = 0;
3130
3131 _velocity.X = 0;
3132 _velocity.Y = 0;
3133 _velocity.Z = 0;
3134 m_lastVelocity = Vector3.Zero;
3135 m_rotationalVelocity.X = 0;
3136 m_rotationalVelocity.Y = 0;
3137 m_rotationalVelocity.Z = 0;
3138
3139 if (_parent == null) base.RequestPhysicsterseUpdate();
3140
3141 m_throttleUpdates = false;
3142 throttleCounter = 0;
3143 _zeroFlag = true;
3144 //outofBounds = true;
3145 } // end neg Z check
3146
3147 // Is it moving?
3148 /* if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02)
3149 && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02)
3150 && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02) */
3151 if ( (Vector3.Mag(_velocity) < 0.01) && // moving very slowly
3152 (Vector3.Mag(_velocity) < Vector3.Mag(m_lastVelocity)) && // decelerating
3153 (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, _orientation)) < 0.0001) ) // spinning very slowly
3154 {
3155 _zeroFlag = true;
3156 m_throttleUpdates = false;
3157 }
3158 else
3159 {
3160 //m_log.Debug(Math.Abs(m_lastposition.X - l_position.X).ToString());
3161 _zeroFlag = false;
3162 m_lastUpdateSent = false;
3163 //m_throttleUpdates = false;
3164 }
3165
3166 if (_zeroFlag)
3167 { // Its stopped
3168 _velocity.X = 0.0f;
3169 _velocity.Y = 0.0f;
3170 // _velocity.Z = 0.0f;
3171
3172 _acceleration.X = 0;
3173 _acceleration.Y = 0;
3174 // _acceleration.Z = 0;
3175
3176 m_rotationalVelocity.X = 0;
3177 m_rotationalVelocity.Y = 0;
3178 m_rotationalVelocity.Z = 0;
3179 // Stop it in the phys engine
3180 d.BodySetLinearVel(Body, 0.0f, 0.0f, _velocity.Z);
3181 d.BodySetAngularVel (Body, 0.0f, 0.0f, 0.0f);
3182 d.BodySetForce(Body, 0f, 0f, 0f);
3183
3184 if (!m_lastUpdateSent)
3185 {
3186 m_throttleUpdates = false;
3187 throttleCounter = 0;
3188 if (_parent == null)
3189 {
3190 base.RequestPhysicsterseUpdate();
3191 }
3192
3193 m_lastUpdateSent = true;
3194 }
3195 }
3196 else
3197 { // Its moving
3198 if (lastZeroFlag != _zeroFlag)
3199 {
3200 if (_parent == null)
3201 {
3202 base.RequestPhysicsterseUpdate();
3203 }
3204 }
3205 m_lastUpdateSent = false;
3206 if (!m_throttleUpdates || throttleCounter > _parent_scene.geomUpdatesPerThrottledUpdate)
3207 {
3208 if (_parent == null)
3209 {
3210 base.RequestPhysicsterseUpdate();
3211 }
3212 }
3213 else
3214 {
3215 throttleCounter++;
3216 }
3217 }
3218 m_lastposition = l_position;
3219
3220 /// End UpdatePositionAndVelocity insert
3221
3222
3223 // Rotation lock =====================================
3224 if(m_rotateEnableUpdate)
3225 {
3226 // Snapshot current angles, set up Amotor(s)
3227 m_rotateEnableUpdate = false;
3228 m_rotateEnable = m_rotateEnableRequest;
3229//Console.WriteLine("RotEnable {0} = {1}",m_primName, m_rotateEnable);
3230
3231 if (Amotor != IntPtr.Zero)
3232 {
3233 d.JointDestroy(Amotor);
3234 Amotor = IntPtr.Zero;
3235//Console.WriteLine("Old Amotor Destroyed");
3236 }
3237
3238 if (!m_rotateEnable.ApproxEquals(Vector3.One, 0.003f))
3239 { // not all are enabled
3240 d.Quaternion r = d.BodyGetQuaternion(Body);
3241 Quaternion locrot = new Quaternion(r.X, r.Y, r.Z, r.W);
3242 // extract the axes vectors
3243 Vector3 vX = new Vector3(1f,0f,0f);
3244 Vector3 vY = new Vector3(0f,1f,0f);
3245 Vector3 vZ = new Vector3(0f,0f,1f);
3246 vX = vX * locrot;
3247 vY = vY * locrot;
3248 vZ = vZ * locrot;
3249 // snapshot the current angle vectors
3250 m_lockX = vX;
3251 m_lockY = vY;
3252 m_lockZ = vZ;
3253 // m_lockRot = locrot;
3254 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero);
3255 d.JointAttach(Amotor, Body, IntPtr.Zero);
3256 d.JointSetAMotorMode(Amotor, 0); // User mode??
3257//Console.WriteLine("New Amotor Created for {0}", m_primName);
3258
3259 float axisnum = 3; // how many to lock
3260 axisnum = (axisnum - (m_rotateEnable.X + m_rotateEnable.Y + m_rotateEnable.Z));
3261 d.JointSetAMotorNumAxes(Amotor,(int)axisnum);
3262//Console.WriteLine("AxisNum={0}",(int)axisnum);
3263
3264 int i = 0;
3265
3266 if (m_rotateEnable.X == 0)
3267 {
3268 d.JointSetAMotorAxis(Amotor, i, 0, m_lockX.X, m_lockX.Y, m_lockX.Z);
3269//Console.WriteLine("AxisX {0} set to {1}", i, m_lockX);
3270 i++;
3271 }
3272
3273 if (m_rotateEnable.Y == 0)
3274 {
3275 d.JointSetAMotorAxis(Amotor, i, 0, m_lockY.X, m_lockY.Y, m_lockY.Z);
3276//Console.WriteLine("AxisY {0} set to {1}", i, m_lockY);
3277 i++;
3278 }
3279
3280 if (m_rotateEnable.Z == 0)
3281 {
3282 d.JointSetAMotorAxis(Amotor, i, 0, m_lockZ.X, m_lockZ.Y, m_lockZ.Z);
3283//Console.WriteLine("AxisZ {0} set to {1}", i, m_lockZ);
3284 i++;
3285 }
3286
3287 // These lowstops and high stops are effectively (no wiggle room)
3288 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, 0f);
3289 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, 0f);
3290 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, 0f);
3291 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0f);
3292 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0f);
3293 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0f);
3294 d.JointSetAMotorParam(Amotor, (int) dParam.Vel, 0f);
3295 d.JointSetAMotorParam(Amotor, (int) dParam.Vel3, 0f);
3296 d.JointSetAMotorParam(Amotor, (int) dParam.Vel2, 0f);
3297 d.JointSetAMotorParam(Amotor, (int)dParam.StopCFM, 0f);
3298 d.JointSetAMotorParam(Amotor, (int)dParam.StopCFM3, 0f);
3299 d.JointSetAMotorParam(Amotor, (int)dParam.StopCFM2, 0f);
3300 } // else none are locked
3301 } // end Rotation Update
3302
3303
3304 // VEHICLE processing ==========================================
3305 if (m_type != Vehicle.TYPE_NONE)
3306 {
3307 // get body attitude
3308 d.Quaternion rot = d.BodyGetQuaternion(Body);
3309 Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object
3310 Quaternion irotq = Quaternion.Inverse(rotq);
3311
3312 // VEHICLE Linear Motion
3313 d.Vector3 velnow = d.BodyGetLinearVel(Body); // this is in world frame
3314 Vector3 vel_now = new Vector3(velnow.X, velnow.Y, velnow.Z);
3315 m_lLinObjectVel = vel_now * irotq;
3316 if (m_linearMotorDecayTimescale < 300.0f) //setting of 300 or more disables decay rate
3317 {
3318 if ( Vector3.Mag(m_lLinMotorDVel) < 1.0f)
3319 {
3320 float decayfactor = m_linearMotorDecayTimescale/timestep;
3321 Vector3 decayAmount = (m_lLinMotorDVel/decayfactor);
3322 m_lLinMotorDVel -= decayAmount;
3323 }
3324 else
3325 {
3326 float decayfactor = 3.0f - (0.57f * (float)Math.Log((double)(m_linearMotorDecayTimescale)));
3327 Vector3 decel = Vector3.Normalize(m_lLinMotorDVel) * decayfactor * timestep;
3328 m_lLinMotorDVel -= decel;
3329 }
3330 if (m_lLinMotorDVel.ApproxEquals(Vector3.Zero, 0.01f))
3331 {
3332 m_lLinMotorDVel = Vector3.Zero;
3333 }
3334
3335 /* else
3336 {
3337 if (Math.Abs(m_lLinMotorDVel.X) < Math.Abs(m_lLinObjectVel.X)) m_lLinObjectVel.X = m_lLinMotorDVel.X;
3338 if (Math.Abs(m_lLinMotorDVel.Y) < Math.Abs(m_lLinObjectVel.Y)) m_lLinObjectVel.Y = m_lLinMotorDVel.Y;
3339 if (Math.Abs(m_lLinMotorDVel.Z) < Math.Abs(m_lLinObjectVel.Z)) m_lLinObjectVel.Z = m_lLinMotorDVel.Z;
3340 } */
3341 } // end linear motor decay
3342
3343 if ( (! m_lLinMotorDVel.ApproxEquals(Vector3.Zero, 0.01f)) || (! m_lLinObjectVel.ApproxEquals(Vector3.Zero, 0.01f)) )
3344 {
3345 if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body);
3346 if (m_linearMotorTimescale < 300.0f)
3347 {
3348 Vector3 attack_error = m_lLinMotorDVel - m_lLinObjectVel;
3349 float linfactor = m_linearMotorTimescale/timestep;
3350 Vector3 attackAmount = (attack_error/linfactor) * 1.3f;
3351 m_lLinObjectVel += attackAmount;
3352 }
3353 if (m_linearFrictionTimescale.X < 300.0f)
3354 {
3355 float fricfactor = m_linearFrictionTimescale.X / timestep;
3356 float fricX = m_lLinObjectVel.X / fricfactor;
3357 m_lLinObjectVel.X -= fricX;
3358 }
3359 if (m_linearFrictionTimescale.Y < 300.0f)
3360 {
3361 float fricfactor = m_linearFrictionTimescale.Y / timestep;
3362 float fricY = m_lLinObjectVel.Y / fricfactor;
3363 m_lLinObjectVel.Y -= fricY;
3364 }
3365 if (m_linearFrictionTimescale.Z < 300.0f)
3366 {
3367 float fricfactor = m_linearFrictionTimescale.Z / timestep;
3368 float fricZ = m_lLinObjectVel.Z / fricfactor;
3369 m_lLinObjectVel.Z -= fricZ;
3370 }
3371 }
3372 m_wLinObjectVel = m_lLinObjectVel * rotq;
3373
3374 // Gravity and Buoyancy
3375 Vector3 grav = Vector3.Zero;
3376 if(m_VehicleBuoyancy < 1.0f)
3377 {
3378 // There is some gravity, make a gravity force vector
3379 // that is applied after object velocity.
3380 d.Mass objMass;
3381 d.BodyGetMass(Body, out objMass);
3382 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
3383 grav.Z = _parent_scene.gravityz * objMass.mass * (1f - m_VehicleBuoyancy); // Applied later as a force
3384 } // else its 1.0, no gravity.
3385
3386 // Hovering
3387 if( (m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
3388 {
3389 // We should hover, get the target height
3390 d.Vector3 pos = d.BodyGetPosition(Body);
3391 if((m_flags & VehicleFlag.HOVER_WATER_ONLY) == VehicleFlag.HOVER_WATER_ONLY)
3392 {
3393 m_VhoverTargetHeight = _parent_scene.GetWaterLevel() + m_VhoverHeight;
3394 }
3395 else if((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) == VehicleFlag.HOVER_TERRAIN_ONLY)
3396 {
3397 m_VhoverTargetHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight;
3398 }
3399 else if((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) == VehicleFlag.HOVER_GLOBAL_HEIGHT)
3400 {
3401 m_VhoverTargetHeight = m_VhoverHeight;
3402 }
3403
3404 if((m_flags & VehicleFlag.HOVER_UP_ONLY) == VehicleFlag.HOVER_UP_ONLY)
3405 {
3406 // If body is aready heigher, use its height as target height
3407 if(pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z;
3408 }
3409
3410// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped
3411// m_VhoverTimescale = 0f; // time to acheive height
3412// timestep is time since last frame,in secs
3413 float herr0 = pos.Z - m_VhoverTargetHeight;
3414 // Replace Vertical speed with correction figure if significant
3415 if(Math.Abs(herr0) > 0.01f )
3416 {
3417 //? d.Mass objMass;
3418 //? d.BodyGetMass(Body, out objMass);
3419 m_wLinObjectVel.Z = - ( (herr0 * timestep * 50.0f) / m_VhoverTimescale);
3420 //KF: m_VhoverEfficiency is not yet implemented
3421 }
3422 else
3423 {
3424 m_wLinObjectVel.Z = 0f;
3425 }
3426 }
3427 else
3428 { // not hovering
3429 if (m_wLinObjectVel.Z == 0f)
3430 { // Gravity rules
3431 m_wLinObjectVel.Z = vel_now.Z;
3432 } // else the motor has it
3433 }
3434 linvel = m_wLinObjectVel;
3435
3436 // Vehicle Linear Motion done =======================================
3437 // Apply velocity
3438 d.BodySetLinearVel(Body, linvel.X, linvel.Y, linvel.Z);
3439 // apply gravity force
3440 d.BodyAddForce(Body, grav.X, grav.Y, grav.Z);
3441//if(frcount == 0) Console.WriteLine("Vel={0} Force={1}",linvel , grav);
3442 // end MoveLinear()
3443
3444
3445 // MoveAngular
3446 /*
3447 private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor
3448
3449 private float m_angularMotorTimescale = 0; // motor angular Attack rate set by LSL
3450 private float m_angularMotorDecayTimescale = 0; // motor angular Decay rate set by LSL
3451 private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular Friction set by LSL
3452
3453 private Vector3 m_angularMotorDVel = Vector3.Zero; // decayed angular motor
3454 private Vector3 m_angObjectVel = Vector3.Zero; // what was last applied to body
3455 */
3456//if(frcount == 0) Console.WriteLine("MoveAngular ");
3457
3458 d.Vector3 angularObjectVel = d.BodyGetAngularVel(Body);
3459 Vector3 angObjectVel = new Vector3(angularObjectVel.X, angularObjectVel.Y, angularObjectVel.Z);
3460 angObjectVel = angObjectVel * irotq; // ============ Converts to LOCAL rotation
3461
3462//if(frcount == 0) Console.WriteLine("V0 = {0}", angObjectVel);
3463
3464 // Decay Angular Motor 1. In SL this also depends on attack rate! decay ~= 23/Attack.
3465 float atk_decayfactor = 23.0f / (m_angularMotorTimescale * timestep);
3466 m_angularMotorDVel -= m_angularMotorDVel / atk_decayfactor;
3467 // Decay Angular Motor 2.
3468 if (m_angularMotorDecayTimescale < 300.0f)
3469 {
3470 if ( Vector3.Mag(m_angularMotorDVel) < 1.0f)
3471 {
3472 float decayfactor = (m_angularMotorDecayTimescale)/timestep;
3473 Vector3 decayAmount = (m_angularMotorDVel/decayfactor);
3474 m_angularMotorDVel -= decayAmount;
3475 }
3476 else
3477 {
3478 Vector3 decel = Vector3.Normalize(m_angularMotorDVel) * timestep / m_angularMotorDecayTimescale;
3479 m_angularMotorDVel -= decel;
3480 }
3481
3482 if (m_angularMotorDVel.ApproxEquals(Vector3.Zero, 0.01f))
3483 {
3484 m_angularMotorDVel = Vector3.Zero;
3485 }
3486 else
3487 {
3488 if (Math.Abs(m_angularMotorDVel.X) < Math.Abs(angObjectVel.X)) angObjectVel.X = m_angularMotorDVel.X;
3489 if (Math.Abs(m_angularMotorDVel.Y) < Math.Abs(angObjectVel.Y)) angObjectVel.Y = m_angularMotorDVel.Y;
3490 if (Math.Abs(m_angularMotorDVel.Z) < Math.Abs(angObjectVel.Z)) angObjectVel.Z = m_angularMotorDVel.Z;
3491 }
3492 } // end decay angular motor
3493//if(frcount == 0) Console.WriteLine("MotorDvel {0} Obj {1}", m_angularMotorDVel, angObjectVel);
3494
3495//if(frcount == 0) Console.WriteLine("VA = {0}", angObjectVel);
3496
3497 if ( (! m_angularMotorDVel.ApproxEquals(Vector3.Zero, 0.01f)) || (! angObjectVel.ApproxEquals(Vector3.Zero, 0.01f)) )
3498 { // if motor or object have motion
3499 if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body);
3500
3501 if (m_angularMotorTimescale < 300.0f)
3502 {
3503 Vector3 attack_error = m_angularMotorDVel - angObjectVel;
3504 float angfactor = m_angularMotorTimescale/timestep;
3505 Vector3 attackAmount = (attack_error/angfactor);
3506 angObjectVel += attackAmount;
3507//if(frcount == 0) Console.WriteLine("Accel {0} Attk {1}",FrAaccel, attackAmount);
3508//if(frcount == 0) Console.WriteLine("V2+= {0}", angObjectVel);
3509 }
3510
3511 angObjectVel.X -= angObjectVel.X / (m_angularFrictionTimescale.X * 0.7f / timestep);
3512 angObjectVel.Y -= angObjectVel.Y / (m_angularFrictionTimescale.Y * 0.7f / timestep);
3513 angObjectVel.Z -= angObjectVel.Z / (m_angularFrictionTimescale.Z * 0.7f / timestep);
3514 } // else no signif. motion
3515
3516//if(frcount == 0) Console.WriteLine("Dmotor {0} Obj {1}", m_angularMotorDVel, angObjectVel);
3517 // Bank section tba
3518 // Deflection section tba
3519//if(frcount == 0) Console.WriteLine("V3 = {0}", angObjectVel);
3520
3521
3522 /* // Rotation Axis Disables:
3523 if (!m_angularEnable.ApproxEquals(Vector3.One, 0.003f))
3524 {
3525 if (m_angularEnable.X == 0)
3526 angObjectVel.X = 0f;
3527 if (m_angularEnable.Y == 0)
3528 angObjectVel.Y = 0f;
3529 if (m_angularEnable.Z == 0)
3530 angObjectVel.Z = 0f;
3531 }
3532 */
3533 angObjectVel = angObjectVel * rotq; // ================ Converts to WORLD rotation
3534
3535 // Vertical attractor section
3536 Vector3 vertattr = Vector3.Zero;
3537
3538 if(m_verticalAttractionTimescale < 300)
3539 {
3540 float VAservo = 1.0f / (m_verticalAttractionTimescale * timestep);
3541 // make a vector pointing up
3542 Vector3 verterr = Vector3.Zero;
3543 verterr.Z = 1.0f;
3544 // rotate it to Body Angle
3545 verterr = verterr * rotq;
3546 // 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.
3547 // 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
3548 // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body.
3549
3550 if (verterr.Z < 0.0f)
3551 { // Deflection from vertical exceeds 90-degrees. This method will ensure stable return to
3552 // vertical, BUT for some reason a z-rotation is imparted to the object. TBI.
3553//Console.WriteLine("InvertFlip");
3554 verterr.X = 2.0f - verterr.X;
3555 verterr.Y = 2.0f - verterr.Y;
3556 }
3557 verterr *= 0.5f;
3558 // verterror is 0 (no error) to +/- 1 (max error at 180-deg tilt)
3559 Vector3 xyav = angObjectVel;
3560 xyav.Z = 0.0f;
3561 if ((!xyav.ApproxEquals(Vector3.Zero, 0.001f)) || (verterr.Z < 0.49f))
3562 {
3563 // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so
3564 // Change Body angular velocity X based on Y, and Y based on X. Z is not changed.
3565 vertattr.X = verterr.Y;
3566 vertattr.Y = - verterr.X;
3567 vertattr.Z = 0f;
3568//if(frcount == 0) Console.WriteLine("VAerr=" + verterr);
3569
3570 // scaling appears better usingsquare-law
3571 float damped = m_verticalAttractionEfficiency * m_verticalAttractionEfficiency;
3572 float bounce = 1.0f - damped;
3573 // 0 = crit damp, 1 = bouncy
3574 float oavz = angObjectVel.Z; // retain z velocity
3575 // time-scaled correction, which sums, therefore is bouncy:
3576 angObjectVel = (angObjectVel + (vertattr * VAservo * 0.0333f)) * bounce;
3577 // damped, good @ < 90:
3578 angObjectVel = angObjectVel + (vertattr * VAservo * 0.0667f * damped);
3579 angObjectVel.Z = oavz;
3580//if(frcount == 0) Console.WriteLine("VA+");
3581//Console.WriteLine("VAttr {0} OAvel {1}", vertattr, angObjectVel);
3582 }
3583 else
3584 {
3585 // else error is very small
3586 angObjectVel.X = 0f;
3587 angObjectVel.Y = 0f;
3588//if(frcount == 0) Console.WriteLine("VA0");
3589 }
3590 } // else vertical attractor is off
3591//if(frcount == 0) Console.WriteLine("V1 = {0}", angObjectVel);
3592
3593
3594 m_lastAngularVelocity = angObjectVel;
3595 // apply Angular Velocity to body
3596 d.BodySetAngularVel (Body, m_lastAngularVelocity.X, m_lastAngularVelocity.Y, m_lastAngularVelocity.Z);
3597//if(frcount == 0) Console.WriteLine("V4 = {0}", m_lastAngularVelocity);
3598
3599 } // end VEHICLES
3600 else
3601 {
3602 // Dyamics (NON-'VEHICLES') are dealt with here ================================================================
3603
3604 if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); // KF add 161009
3605
3606 /// Dynamics Buoyancy
3607 //KF: m_buoyancy is set by llSetBuoyancy() and is for non-vehicle.
3608 // m_buoyancy: (unlimited value) <0=Falls fast; 0=1g; 1=0g; >1 = floats up
3609 // NB Prims in ODE are no subject to global gravity
3610 // This should only affect gravity operations
3611
3612 float m_mass = CalculateMass();
3613 // calculate z-force due togravity on object.
3614 fz = _parent_scene.gravityz * (1.0f - m_buoyancy) * m_mass; // force = acceleration * mass
3615 if ((m_usePID) && (m_PIDTau > 0.0f)) // Dynamics llMoveToTarget.
3616 {
3617 fz = 0; // llMoveToTarget ignores gravity.
3618 // it also ignores mass of object, and any physical resting on it.
3619 // Vector3 m_PIDTarget is where we are going
3620 // float m_PIDTau is time to get there
3621 fx = 0;
3622 fy = 0;
3623 d.Vector3 pos = d.BodyGetPosition(Body);
3624 Vector3 error = new Vector3(
3625 (m_PIDTarget.X - pos.X),
3626 (m_PIDTarget.Y - pos.Y),
3627 (m_PIDTarget.Z - pos.Z));
3628 if (error.ApproxEquals(Vector3.Zero,0.01f))
3629 { // Very close, Jump there and quit move
3630
3631 d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z);
3632 _target_velocity = Vector3.Zero;
3633 d.BodySetLinearVel(Body, _target_velocity.X, _target_velocity.Y, _target_velocity.Z);
3634 d.BodySetForce(Body, 0f, 0f, 0f);
3635 }
3636 else
3637 {
3638 float scale = 50.0f * timestep / m_PIDTau;
3639 if ((error.ApproxEquals(Vector3.Zero,0.5f)) && (_target_velocity != Vector3.Zero))
3640 {
3641 // Nearby, quit update of velocity
3642 }
3643 else
3644 { // Far, calc damped velocity
3645 _target_velocity = error * scale;
3646 }
3647 d.BodySetLinearVel(Body, _target_velocity.X, _target_velocity.Y, _target_velocity.Z);
3648 }
3649 } // end PID MoveToTarget
3650
3651
3652 /// Dynamics Hover ===================================================================================
3653 // Hover PID Controller can only run if the PIDcontroller is not in use.
3654 if (m_useHoverPID && !m_usePID)
3655 {
3656//Console.WriteLine("Hover " + m_primName);
3657
3658 // If we're using the PID controller, then we have no gravity
3659 fz = (-1 * _parent_scene.gravityz) * m_mass;
3660
3661 // no lock; for now it's only called from within Simulate()
3662
3663 // If the PID Controller isn't active then we set our force
3664 // calculating base velocity to the current position
3665
3666 if ((m_PIDTau < 1))
3667 {
3668 PID_G = PID_G / m_PIDTau;
3669 }
3670
3671 if ((PID_G - m_PIDTau) <= 0)
3672 {
3673 PID_G = m_PIDTau + 1;
3674 }
3675
3676
3677 // Where are we, and where are we headed?
3678 d.Vector3 pos = d.BodyGetPosition(Body);
3679// d.Vector3 vel = d.BodyGetLinearVel(Body);
3680
3681
3682 // Non-Vehicles have a limited set of Hover options.
3683 // determine what our target height really is based on HoverType
3684 switch (m_PIDHoverType)
3685 {
3686 case PIDHoverType.Ground:
3687 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y);
3688 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
3689 break;
3690 case PIDHoverType.GroundAndWater:
3691 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y);
3692 m_waterHeight = _parent_scene.GetWaterLevel();
3693 if (m_groundHeight > m_waterHeight)
3694 {
3695 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
3696 }
3697 else
3698 {
3699 m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight;
3700 }
3701 break;
3702
3703 } // end switch (m_PIDHoverType)
3704
3705
3706 _target_velocity =
3707 new Vector3(0.0f, 0.0f,
3708 (m_targetHoverHeight - pos.Z) * ((PID_G - m_PIDHoverTau) * timestep)
3709 );
3710
3711 // if velocity is zero, use position control; otherwise, velocity control
3712
3713 if (_target_velocity.ApproxEquals(Vector3.Zero, 0.1f))
3714 {
3715 // keep track of where we stopped. No more slippin' & slidin'
3716
3717 // We only want to deactivate the PID Controller if we think we want to have our surrogate
3718 // react to the physics scene by moving it's position.
3719 // Avatar to Avatar collisions
3720 // Prim to avatar collisions
3721 d.Vector3 dlinvel = vel;
3722 d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight);
3723 d.BodySetLinearVel(Body, dlinvel.X, dlinvel.Y, dlinvel.Z);
3724 d.BodyAddForce(Body, 0, 0, fz);
3725 //KF this prevents furthur motions return;
3726 }
3727 else
3728 {
3729 _zeroFlag = false;
3730
3731 // We're flying and colliding with something
3732 fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass);
3733 }
3734 } // end m_useHoverPID && !m_usePID
3735
3736
3737 /// Dynamics Apply Forces ===================================================================================
3738 fx *= m_mass;
3739 fy *= m_mass;
3740 //fz *= m_mass;
3741 fx += m_force.X;
3742 fy += m_force.Y;
3743 fz += m_force.Z;
3744
3745 //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString());
3746 if (fx != 0 || fy != 0 || fz != 0)
3747 {
3748 //m_taintdisable = true;
3749 //base.RaiseOutOfBounds(Position);
3750 //d.BodySetLinearVel(Body, fx, fy, 0f);
3751 if (!d.BodyIsEnabled(Body))
3752 {
3753 // A physical body at rest on a surface will auto-disable after a while,
3754 // this appears to re-enable it incase the surface it is upon vanishes,
3755 // and the body should fall again.
3756 d.BodySetLinearVel(Body, 0f, 0f, 0f);
3757 d.BodySetForce(Body, 0f, 0f, 0f);
3758 enableBodySoft();
3759 }
3760
3761 // 35x10 = 350n times the mass per second applied maximum.
3762 float nmax = 35f * m_mass;
3763 float nmin = -35f * m_mass;
3764
3765
3766 if (fx > nmax)
3767 fx = nmax;
3768 if (fx < nmin)
3769 fx = nmin;
3770 if (fy > nmax)
3771 fy = nmax;
3772 if (fy < nmin)
3773 fy = nmin;
3774 d.BodyAddForce(Body, fx, fy, fz);
3775 } // end apply forces
3776 } // end Vehicle/Dynamics
3777
3778 /// RotLookAt / LookAt =================================================================================
3779 if (m_useAPID)
3780 {
3781 // RotLookAt, apparently overrides all other rotation sources. Inputs:
3782 // Quaternion m_APIDTarget
3783 // float m_APIDStrength // From SL experiments, this is the time to get there
3784 // float m_APIDDamping // From SL experiments, this is damping, 1.0 = damped, 0.1 = wobbly
3785 // Also in SL the mass of the object has no effect on time to get there.
3786 // Factors:
3787 // get present body rotation
3788 float limit = 1.0f;
3789 float rscaler = 50f; // adjusts rotation damping time
3790 float lscaler = 10f; // adjusts linear damping time in llLookAt
3791 float RLAservo = 0f;
3792 Vector3 diff_axis;
3793 float diff_angle;
3794 d.Quaternion rot = d.BodyGetQuaternion(Body); // prim present rotation
3795 Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W);
3796 Quaternion rtarget = new Quaternion();
3797
3798 if(m_APIDTarget.W == -99.9f)
3799 {
3800 // this is really a llLookAt(), x,y,z is the target vector
3801 Vector3 target = new Vector3(m_APIDTarget.X, m_APIDTarget.Y, m_APIDTarget.Z);
3802 Vector3 ospin = new Vector3(1.0f, 0.0f, 0.0f) * rotq;
3803 Vector3 error = new Vector3(0.0f, 0.0f, 0.0f);
3804 float twopi = 2.0f * (float)Math.PI;
3805 Vector3 dir = target - _position;
3806 dir.Normalize();
3807 float tzrot = (float)Math.Atan2(dir.Y, dir.X);
3808 float txy = (float)Math.Sqrt((dir.X * dir.X) + (dir.Y * dir.Y));
3809 float terot = (float)Math.Atan2(dir.Z, txy);
3810 float ozrot = (float)Math.Atan2(ospin.Y, ospin.X);
3811 float oxy = (float)Math.Sqrt((ospin.X * ospin.X) + (ospin.Y * ospin.Y));
3812 float oerot = (float)Math.Atan2(ospin.Z, oxy);
3813 float ra = 2.0f * ((rotq.W * rotq.X) + (rotq.Y * rotq.Z));
3814 float rb = 1.0f - 2.0f * ((rotq.Y * rotq.Y)+(rotq.X * rotq.X));
3815 float roll = (float)Math.Atan2(ra, rb);
3816 float errorz = tzrot - ozrot;
3817 if(errorz > (float)Math.PI) errorz -= twopi;
3818 else if(errorz < -(float)Math.PI) errorz += twopi;
3819 float errory = oerot - terot;
3820 if(errory > (float)Math.PI) errory -= twopi;
3821 else if(errory < -(float)Math.PI) errory += twopi;
3822 diff_angle = Math.Abs(errorz) + Math.Abs(errory) + Math.Abs(roll);
3823 if(diff_angle > 0.01f * m_APIDdamper)
3824 {
3825 m_APIDdamper = 1.0f;
3826 RLAservo = timestep / m_APIDStrength * rscaler;
3827 errorz *= RLAservo;
3828 errory *= RLAservo;
3829 error.X = -roll * 8.0f;
3830 error.Y = errory;
3831 error.Z = errorz;
3832 error *= rotq;
3833 d.BodySetAngularVel (Body, error.X, error.Y, error.Z);
3834 }
3835 else
3836 {
3837 d.BodySetAngularVel (Body, 0.0f, 0.0f, 0.0f);
3838 m_APIDdamper = 2.0f;
3839 }
3840 }
3841 else
3842 {
3843 // this is a llRotLookAt()
3844 rtarget = m_APIDTarget;
3845
3846 Quaternion rot_diff = Quaternion.Inverse(rotq) * rtarget; // difference to desired rot
3847 rot_diff.GetAxisAngle(out diff_axis, out diff_angle); // convert to axis to point at & error angle
3848//if(frcount == 0) Console.WriteLine("axis {0} angle {1}",diff_axis * 57.3f, diff_angle);
3849
3850 // diff_axis.Normalize(); it already is!
3851 if(diff_angle > 0.01f * m_APIDdamper) // diff_angle is always +ve // if there is enough error
3852 {
3853 m_APIDdamper = 1.0f;
3854 Vector3 rotforce = new Vector3(diff_axis.X, diff_axis.Y, diff_axis.Z);
3855 rotforce = rotforce * rotq;
3856 if(diff_angle > limit) diff_angle = limit; // cap the rotate rate
3857 RLAservo = timestep / m_APIDStrength * lscaler;
3858 rotforce = rotforce * RLAservo * diff_angle ;
3859 d.BodySetAngularVel (Body, rotforce.X, rotforce.Y, rotforce.Z);
3860//Console.WriteLine("axis= " + diff_axis + " angle= " + diff_angle + "servo= " + RLAservo);
3861 }
3862 else
3863 { // close enough
3864 d.BodySetAngularVel (Body, 0.0f, 0.0f, 0.0f);
3865 m_APIDdamper = 2.0f;
3866 }
3867 } // end llLookAt/llRotLookAt
3868//if(frcount == 0) Console.WriteLine("mass= " + m_mass + " servo= " + RLAservo + " angle= " + diff_angle);
3869 } // end m_useAPID
3870 } // end root prims
3871 } // end Move()
3872 } // end class
3873}
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..a622745
--- /dev/null
+++ b/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs
@@ -0,0 +1,3847 @@
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 float geomRegionFence = 0.0f;
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 ContactCopy; // local copy that can be modified
268 private d.Contact TerrainContact;
269 private d.Contact AvatarStaticprimContact; // was 'contact'
270 private d.Contact AvatarMovementprimContact;
271 private d.Contact AvatarMovementTerrainContact;
272 private d.Contact WaterContact;
273 private d.Contact[,] m_materialContacts;
274
275//Ckrinke: Comment out until used. We declare it, initialize it, but do not use it
276//Ckrinke private int m_randomizeWater = 200;
277 private int m_physicsiterations = 10;
278 private const float m_SkipFramesAtms = 0.40f; // Drop frames gracefully at a 400 ms lag
279 private readonly PhysicsActor PANull = new NullPhysicsActor();
280 private float step_time = 0.0f;
281//Ckrinke: Comment out until used. We declare it, initialize it, but do not use it
282//Ckrinke private int ms = 0;
283 public IntPtr world;
284 //private bool returncollisions = false;
285 // private uint obj1LocalID = 0;
286 private uint obj2LocalID = 0;
287 //private int ctype = 0;
288 private OdeCharacter cc1;
289 private OdePrim cp1;
290 private OdeCharacter cc2;
291 private OdePrim cp2;
292 //private int cStartStop = 0;
293 //private string cDictKey = "";
294
295 public IntPtr space;
296
297 //private IntPtr tmpSpace;
298 // split static geometry collision handling into spaces of 30 meters
299 public IntPtr[,] staticPrimspace;
300
301 public Object OdeLock;
302
303 public IMesher mesher;
304
305 private IConfigSource m_config;
306
307 public bool physics_logging = false;
308 public int physics_logging_interval = 0;
309 public bool physics_logging_append_existing_logfile = false;
310
311 public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f);
312 public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f);
313
314 // TODO: unused: private uint heightmapWidth = m_regionWidth + 1;
315 // TODO: unused: private uint heightmapHeight = m_regionHeight + 1;
316 // TODO: unused: private uint heightmapWidthSamples;
317 // TODO: unused: private uint heightmapHeightSamples;
318
319 private volatile int m_global_contactcount = 0;
320
321 private Vector3 m_worldOffset = Vector3.Zero;
322 public Vector2 WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize);
323 private PhysicsScene m_parentScene = null;
324
325 private ODERayCastRequestManager m_rayCastManager;
326
327 /// <summary>
328 /// Initiailizes the scene
329 /// Sets many properties that ODE requires to be stable
330 /// These settings need to be tweaked 'exactly' right or weird stuff happens.
331 /// </summary>
332 public OdeScene(CollisionLocker dode, string sceneIdentifier)
333 {
334 m_log
335 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.ToString() + "." + sceneIdentifier);
336
337 OdeLock = new Object();
338 ode = dode;
339 nearCallback = near;
340 triCallback = TriCallback;
341 triArrayCallback = TriArrayCallback;
342 m_rayCastManager = new ODERayCastRequestManager(this);
343 lock (OdeLock)
344 {
345 // Create the world and the first space
346 world = d.WorldCreate();
347 space = d.HashSpaceCreate(IntPtr.Zero);
348
349
350 contactgroup = d.JointGroupCreate(0);
351 //contactgroup
352
353 d.WorldSetAutoDisableFlag(world, false);
354 #if USE_DRAWSTUFF
355
356 Thread viewthread = new Thread(new ParameterizedThreadStart(startvisualization));
357 viewthread.Start();
358 #endif
359 }
360
361
362 _watermap = new float[258 * 258];
363
364 // Zero out the prim spaces array (we split our space into smaller spaces so
365 // we can hit test less.
366 }
367
368#if USE_DRAWSTUFF
369 public void startvisualization(object o)
370 {
371 ds.Functions fn;
372 fn.version = ds.VERSION;
373 fn.start = new ds.CallbackFunction(start);
374 fn.step = new ds.CallbackFunction(step);
375 fn.command = new ds.CallbackFunction(command);
376 fn.stop = null;
377 fn.path_to_textures = "./textures";
378 string[] args = new string[0];
379 ds.SimulationLoop(args.Length, args, 352, 288, ref fn);
380 }
381#endif
382
383 // Initialize the mesh plugin
384 public override void Initialise(IMesher meshmerizer, IConfigSource config)
385 {
386 mesher = meshmerizer;
387 m_config = config;
388 // Defaults
389
390 if (Environment.OSVersion.Platform == PlatformID.Unix)
391 {
392 avPIDD = 3200.0f;
393 avPIDP = 1400.0f;
394 avStandupTensor = 2000000f;
395 }
396 else
397 {
398 avPIDD = 2200.0f;
399 avPIDP = 900.0f;
400 avStandupTensor = 550000f;
401 }
402
403 int contactsPerCollision = 80;
404
405 if (m_config != null)
406 {
407 IConfig physicsconfig = m_config.Configs["ODEPhysicsSettings"];
408 if (physicsconfig != null)
409 {
410 gravityx = physicsconfig.GetFloat("world_gravityx", 0f);
411 gravityy = physicsconfig.GetFloat("world_gravityy", 0f);
412 gravityz = physicsconfig.GetFloat("world_gravityz", -9.8f);
413
414 worldHashspaceLow = physicsconfig.GetInt("world_hashspace_size_low", -4);
415 worldHashspaceHigh = physicsconfig.GetInt("world_hashspace_size_high", 128);
416
417 metersInSpace = physicsconfig.GetFloat("meters_in_small_space", 29.9f);
418 smallHashspaceLow = physicsconfig.GetInt("small_hashspace_size_low", -4);
419 smallHashspaceHigh = physicsconfig.GetInt("small_hashspace_size_high", 66);
420
421 contactsurfacelayer = physicsconfig.GetFloat("world_contact_surface_layer", 0.001f);
422
423 nmTerrainContactFriction = physicsconfig.GetFloat("nm_terraincontact_friction", 255.0f);
424 nmTerrainContactBounce = physicsconfig.GetFloat("nm_terraincontact_bounce", 0.1f);
425 nmTerrainContactERP = physicsconfig.GetFloat("nm_terraincontact_erp", 0.1025f);
426
427 mTerrainContactFriction = physicsconfig.GetFloat("m_terraincontact_friction", 75f);
428 mTerrainContactBounce = physicsconfig.GetFloat("m_terraincontact_bounce", 0.05f);
429 mTerrainContactERP = physicsconfig.GetFloat("m_terraincontact_erp", 0.05025f);
430
431 nmAvatarObjectContactFriction = physicsconfig.GetFloat("objectcontact_friction", 250f);
432 nmAvatarObjectContactBounce = physicsconfig.GetFloat("objectcontact_bounce", 0.2f);
433
434 mAvatarObjectContactFriction = physicsconfig.GetFloat("m_avatarobjectcontact_friction", 75f);
435 mAvatarObjectContactBounce = physicsconfig.GetFloat("m_avatarobjectcontact_bounce", 0.1f);
436
437 ODE_STEPSIZE = physicsconfig.GetFloat("world_stepsize", 0.020f);
438 m_physicsiterations = physicsconfig.GetInt("world_internal_steps_without_collisions", 10);
439
440 avDensity = physicsconfig.GetFloat("av_density", 80f);
441 avHeightFudgeFactor = physicsconfig.GetFloat("av_height_fudge_factor", 0.52f);
442 avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", 1.3f);
443 avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", 0.8f);
444 avCapRadius = physicsconfig.GetFloat("av_capsule_radius", 0.37f);
445 avCapsuleTilted = physicsconfig.GetBoolean("av_capsule_tilted", false);
446
447 contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80);
448
449 geomContactPointsStartthrottle = physicsconfig.GetInt("geom_contactpoints_start_throttling", 3);
450 geomUpdatesPerThrottledUpdate = physicsconfig.GetInt("geom_updates_before_throttled_update", 15);
451 geomCrossingFailuresBeforeOutofbounds = physicsconfig.GetInt("geom_crossing_failures_before_outofbounds", 5);
452 geomRegionFence = physicsconfig.GetFloat("region_border_fence", 0.0f);
453
454 geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", 10.000006836f);
455 bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", 20);
456
457 bodyPIDD = physicsconfig.GetFloat("body_pid_derivative", 35f);
458 bodyPIDG = physicsconfig.GetFloat("body_pid_gain", 25f);
459
460 forceSimplePrimMeshing = physicsconfig.GetBoolean("force_simple_prim_meshing", forceSimplePrimMeshing);
461 meshSculptedPrim = physicsconfig.GetBoolean("mesh_sculpted_prim", true);
462 meshSculptLOD = physicsconfig.GetFloat("mesh_lod", 32f);
463 MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f);
464 m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false);
465
466 if (Environment.OSVersion.Platform == PlatformID.Unix)
467 {
468 avPIDD = physicsconfig.GetFloat("av_pid_derivative_linux", 2200.0f);
469 avPIDP = physicsconfig.GetFloat("av_pid_proportional_linux", 900.0f);
470 avStandupTensor = physicsconfig.GetFloat("av_capsule_standup_tensor_linux", 550000f);
471 bodyMotorJointMaxforceTensor = physicsconfig.GetFloat("body_motor_joint_maxforce_tensor_linux", 5f);
472 }
473 else
474 {
475 avPIDD = physicsconfig.GetFloat("av_pid_derivative_win", 2200.0f);
476 avPIDP = physicsconfig.GetFloat("av_pid_proportional_win", 900.0f);
477 avStandupTensor = physicsconfig.GetFloat("av_capsule_standup_tensor_win", 550000f);
478 bodyMotorJointMaxforceTensor = physicsconfig.GetFloat("body_motor_joint_maxforce_tensor_win", 5f);
479 }
480
481 physics_logging = physicsconfig.GetBoolean("physics_logging", false);
482 physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0);
483 physics_logging_append_existing_logfile = physicsconfig.GetBoolean("physics_logging_append_existing_logfile", false);
484
485 m_NINJA_physics_joints_enabled = physicsconfig.GetBoolean("use_NINJA_physics_joints", false);
486 minimumGroundFlightOffset = physicsconfig.GetFloat("minimum_ground_flight_offset", 3f);
487 maximumMassObject = physicsconfig.GetFloat("maximum_mass_object", 10000.01f);
488 }
489 }
490
491 contacts = new d.ContactGeom[contactsPerCollision];
492
493 staticPrimspace = new IntPtr[(int)(300 / metersInSpace), (int)(300 / metersInSpace)];
494
495 // Avatar static on a Prim parameters
496 AvatarStaticprimContact.surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
497 AvatarStaticprimContact.surface.mu = 255.0f;
498 AvatarStaticprimContact.surface.bounce = 0.0f;
499 AvatarStaticprimContact.surface.soft_cfm = 0.0f;
500 AvatarStaticprimContact.surface.soft_erp = 0.30f; // If this is too small static Av will fall through a sloping prim. 1.0 prevents fall-thru
501
502 // Avatar moving on a Prim parameters
503 AvatarMovementprimContact.surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
504 AvatarMovementprimContact.surface.mu = 255.0f;
505 AvatarMovementprimContact.surface.bounce = 0.0f;
506 AvatarMovementprimContact.surface.soft_cfm = 0.0f; // if this is 0.01 then prims become phantom to Avs!
507 AvatarMovementprimContact.surface.soft_erp = 0.3f;
508
509 // Static Avatar on Terrain parameters
510 // Keeps Avatar in place better
511 TerrainContact.surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
512 TerrainContact.surface.mu = 255.0f;
513 TerrainContact.surface.bounce = 0.0f;
514 TerrainContact.surface.soft_cfm = 0.0f;
515 TerrainContact.surface.soft_erp = 0.05f;
516
517 // Moving Avatar on Terrain parameters
518 AvatarMovementTerrainContact.surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
519 AvatarMovementTerrainContact.surface.mu = 75f;
520 AvatarMovementTerrainContact.surface.bounce = 0.0f;
521 AvatarMovementTerrainContact.surface.soft_cfm = 0.0f;
522 AvatarMovementTerrainContact.surface.soft_erp = 0.05f;
523
524 // Avatar or prim the the water, this may not be used, possibly water is same as air?
525 WaterContact.surface.mode |= (d.ContactFlags.SoftERP | d.ContactFlags.SoftCFM);
526 WaterContact.surface.mu = 0.0f; // No friction
527 WaterContact.surface.bounce = 0.0f; // No bounce
528 WaterContact.surface.soft_cfm = 0.010f;
529 WaterContact.surface.soft_erp = 0.010f;
530
531
532 // Prim static or moving on a prim, depends on material type
533 m_materialContacts = new d.Contact[7,2];
534 // V 1 = Sliding; 0 = static or fell onto
535 m_materialContacts[(int)Material.Stone, 0] = new d.Contact();
536 m_materialContacts[(int)Material.Stone, 0].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
537 m_materialContacts[(int)Material.Stone, 0].surface.mu = 60f; // friction, 1 = slippery, 255 = no slip
538 m_materialContacts[(int)Material.Stone, 0].surface.bounce = 0.0f;
539 m_materialContacts[(int)Material.Stone, 0].surface.soft_cfm = 0.0f;
540 m_materialContacts[(int)Material.Stone, 0].surface.soft_erp = 0.50f; // erp also changes friction, more erp=less friction
541
542 m_materialContacts[(int)Material.Stone, 1] = new d.Contact();
543 m_materialContacts[(int)Material.Stone, 1].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
544 m_materialContacts[(int)Material.Stone, 1].surface.mu = 40f;
545 m_materialContacts[(int)Material.Stone, 1].surface.bounce = 0.0f;
546 m_materialContacts[(int)Material.Stone, 1].surface.soft_cfm = 0.0f;
547 m_materialContacts[(int)Material.Stone, 1].surface.soft_erp = 0.50f;
548
549 m_materialContacts[(int)Material.Metal, 0] = new d.Contact();
550 m_materialContacts[(int)Material.Metal, 0].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
551 m_materialContacts[(int)Material.Metal, 0].surface.mu = 15f;
552 m_materialContacts[(int)Material.Metal, 0].surface.bounce = 0.2f;
553 m_materialContacts[(int)Material.Metal, 0].surface.soft_cfm = 0.0f;
554 m_materialContacts[(int)Material.Metal, 0].surface.soft_erp = 0.50f;
555
556 m_materialContacts[(int)Material.Metal, 1] = new d.Contact();
557 m_materialContacts[(int)Material.Metal, 1].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
558 m_materialContacts[(int)Material.Metal, 1].surface.mu = 10f;
559 m_materialContacts[(int)Material.Metal, 1].surface.bounce = 0.2f;
560 m_materialContacts[(int)Material.Metal, 1].surface.soft_cfm = 0.0f;
561 m_materialContacts[(int)Material.Metal, 1].surface.soft_erp = 0.50f;
562
563 m_materialContacts[(int)Material.Glass, 0] = new d.Contact();
564 m_materialContacts[(int)Material.Glass, 0].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
565 m_materialContacts[(int)Material.Glass, 0].surface.mu = 7.5f;
566 m_materialContacts[(int)Material.Glass, 0].surface.bounce = 0.0f;
567 m_materialContacts[(int)Material.Glass, 0].surface.soft_cfm = 0.0f;
568 m_materialContacts[(int)Material.Glass, 0].surface.soft_erp = 0.50f;
569
570 m_materialContacts[(int)Material.Glass, 1] = new d.Contact();
571 m_materialContacts[(int)Material.Glass, 1].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
572 m_materialContacts[(int)Material.Glass, 1].surface.mu = 5f;
573 m_materialContacts[(int)Material.Glass, 1].surface.bounce = 0.0f;
574 m_materialContacts[(int)Material.Glass, 1].surface.soft_cfm = 0.0f;
575 m_materialContacts[(int)Material.Glass, 1].surface.soft_erp = 0.50f;
576
577 m_materialContacts[(int)Material.Wood, 0] = new d.Contact();
578 m_materialContacts[(int)Material.Wood, 0].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
579 m_materialContacts[(int)Material.Wood, 0].surface.mu = 45f;
580 m_materialContacts[(int)Material.Wood, 0].surface.bounce = 0.1f;
581 m_materialContacts[(int)Material.Wood, 0].surface.soft_cfm = 0.0f;
582 m_materialContacts[(int)Material.Wood, 0].surface.soft_erp = 0.50f;
583
584 m_materialContacts[(int)Material.Wood, 1] = new d.Contact();
585 m_materialContacts[(int)Material.Wood, 1].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
586 m_materialContacts[(int)Material.Wood, 1].surface.mu = 30f;
587 m_materialContacts[(int)Material.Wood, 1].surface.bounce = 0.1f;
588 m_materialContacts[(int)Material.Wood, 1].surface.soft_cfm = 0.0f;
589 m_materialContacts[(int)Material.Wood, 1].surface.soft_erp = 0.50f;
590
591 m_materialContacts[(int)Material.Flesh, 0] = new d.Contact();
592 m_materialContacts[(int)Material.Flesh, 0].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
593 m_materialContacts[(int)Material.Flesh, 0].surface.mu = 150f;
594 m_materialContacts[(int)Material.Flesh, 0].surface.bounce = 0.0f;
595 m_materialContacts[(int)Material.Flesh, 0].surface.soft_cfm = 0.0f;
596 m_materialContacts[(int)Material.Flesh, 0].surface.soft_erp = 0.50f;
597
598 m_materialContacts[(int)Material.Flesh, 1] = new d.Contact();
599 m_materialContacts[(int)Material.Flesh, 1].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
600 m_materialContacts[(int)Material.Flesh, 1].surface.mu = 100f;
601 m_materialContacts[(int)Material.Flesh, 1].surface.bounce = 0.0f;
602 m_materialContacts[(int)Material.Flesh, 1].surface.soft_cfm = 0.0f;
603 m_materialContacts[(int)Material.Flesh, 1].surface.soft_erp = 0.50f;
604
605 m_materialContacts[(int)Material.Plastic, 0] = new d.Contact();
606 m_materialContacts[(int)Material.Plastic, 0].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
607 m_materialContacts[(int)Material.Plastic, 0].surface.mu = 30f;
608 m_materialContacts[(int)Material.Plastic, 0].surface.bounce = 0.2f;
609 m_materialContacts[(int)Material.Plastic, 0].surface.soft_cfm = 0.0f;
610 m_materialContacts[(int)Material.Plastic, 0].surface.soft_erp = 0.50f;
611
612 m_materialContacts[(int)Material.Plastic, 1] = new d.Contact();
613 m_materialContacts[(int)Material.Plastic, 1].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
614 m_materialContacts[(int)Material.Plastic, 1].surface.mu = 20f;
615 m_materialContacts[(int)Material.Plastic, 1].surface.bounce = 0.2f;
616 m_materialContacts[(int)Material.Plastic, 1].surface.soft_cfm = 0.0f;
617 m_materialContacts[(int)Material.Plastic, 1].surface.soft_erp = 0.50f;
618
619 m_materialContacts[(int)Material.Rubber, 0] = new d.Contact();
620 m_materialContacts[(int)Material.Rubber, 0].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
621 m_materialContacts[(int)Material.Rubber, 0].surface.mu = 150f;
622 m_materialContacts[(int)Material.Rubber, 0].surface.bounce = 0.7f;
623 m_materialContacts[(int)Material.Rubber, 0].surface.soft_cfm = 0.0f;
624 m_materialContacts[(int)Material.Rubber, 0].surface.soft_erp = 0.50f;
625
626 m_materialContacts[(int)Material.Rubber, 1] = new d.Contact();
627 m_materialContacts[(int)Material.Rubber, 1].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
628 m_materialContacts[(int)Material.Rubber, 1].surface.mu = 100f;
629 m_materialContacts[(int)Material.Rubber, 1].surface.bounce = 0.7f;
630 m_materialContacts[(int)Material.Rubber, 1].surface.soft_cfm = 0.0f;
631 m_materialContacts[(int)Material.Rubber, 1].surface.soft_erp = 0.50f;
632
633 d.HashSpaceSetLevels(space, worldHashspaceLow, worldHashspaceHigh);
634
635 // Set the gravity,, don't disable things automatically (we set it explicitly on some things)
636
637 d.WorldSetGravity(world, gravityx, gravityy, gravityz);
638 d.WorldSetContactSurfaceLayer(world, contactsurfacelayer);
639
640
641 d.WorldSetLinearDampingThreshold(world, 256f);
642 d.WorldSetLinearDamping(world, 256f);
643// d.WorldSetLinearDampingThreshold(world, 0.01f);
644// d.WorldSetLinearDamping(world, 0.1f);
645 d.WorldSetAngularDampingThreshold(world, 256f);
646 d.WorldSetAngularDamping(world, 256f);
647 d.WorldSetMaxAngularSpeed(world, 256f);
648
649 // Set how many steps we go without running collision testing
650 // This is in addition to the step size.
651 // Essentially Steps * m_physicsiterations
652 d.WorldSetQuickStepNumIterations(world, m_physicsiterations);
653 //d.WorldSetContactMaxCorrectingVel(world, 1000.0f);
654
655
656
657 for (int i = 0; i < staticPrimspace.GetLength(0); i++)
658 {
659 for (int j = 0; j < staticPrimspace.GetLength(1); j++)
660 {
661 staticPrimspace[i, j] = IntPtr.Zero;
662 }
663 }
664 }
665
666 internal void waitForSpaceUnlock(IntPtr space)
667 {
668 //if (space != IntPtr.Zero)
669 //while (d.SpaceLockQuery(space)) { } // Wait and do nothing
670 }
671
672 /// <summary>
673 /// Debug space message for printing the space that a prim/avatar is in.
674 /// </summary>
675 /// <param name="pos"></param>
676 /// <returns>Returns which split up space the given position is in.</returns>
677 public string whichspaceamIin(Vector3 pos)
678 {
679 return calculateSpaceForGeom(pos).ToString();
680 }
681
682 #region Collision Detection
683
684 /// <summary>
685 /// This is our near callback. A geometry is near a body
686 /// </summary>
687 /// <param name="space">The space that contains the geoms. Remember, spaces are also geoms</param>
688 /// <param name="g1">a geometry or space</param>
689 /// <param name="g2">another geometry or space</param>
690 private void near(IntPtr space, IntPtr g1, IntPtr g2)
691 {
692 // no lock here! It's invoked from within Simulate(), which is thread-locked
693
694 // Test if we're colliding a geom with a space.
695 // If so we have to drill down into the space recursively
696//Console.WriteLine("near -----------"); //##
697 if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2))
698 {
699 if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
700 return;
701
702 // Separating static prim geometry spaces.
703 // We'll be calling near recursivly if one
704 // of them is a space to find all of the
705 // contact points in the space
706 try
707 {
708 d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
709 }
710 catch (AccessViolationException)
711 {
712 m_log.Warn("[PHYSICS]: Unable to collide test a space");
713 return;
714 }
715 //Colliding a space or a geom with a space or a geom. so drill down
716
717 //Collide all geoms in each space..
718 //if (d.GeomIsSpace(g1)) d.SpaceCollide(g1, IntPtr.Zero, nearCallback);
719 //if (d.GeomIsSpace(g2)) d.SpaceCollide(g2, IntPtr.Zero, nearCallback);
720 return;
721 }
722
723 if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
724 return;
725
726 IntPtr b1 = d.GeomGetBody(g1);
727 IntPtr b2 = d.GeomGetBody(g2);
728
729 // d.GeomClassID id = d.GeomGetClass(g1);
730
731 String name1 = null;
732 String name2 = null;
733
734 if (!geom_name_map.TryGetValue(g1, out name1))
735 {
736 name1 = "null";
737 }
738 if (!geom_name_map.TryGetValue(g2, out name2))
739 {
740 name2 = "null";
741 }
742
743 //if (id == d.GeomClassId.TriMeshClass)
744 //{
745 // m_log.InfoFormat("near: A collision was detected between {1} and {2}", 0, name1, name2);
746 //m_log.Debug("near: A collision was detected between {1} and {2}", 0, name1, name2);
747 //}
748
749 // Figure out how many contact points we have
750 int count = 0;
751 try
752 {
753 // Colliding Geom To Geom
754 // This portion of the function 'was' blatantly ripped off from BoxStack.cs
755
756 if (g1 == g2)
757 return; // Can't collide with yourself
758
759 if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
760 return;
761
762 lock (contacts)
763 {
764 count = d.Collide(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf);
765 if (count > contacts.Length)
766 m_log.Error("[PHYSICS]: Got " + count + " contacts when we asked for a maximum of " + contacts.Length);
767 }
768 }
769 catch (SEHException)
770 {
771 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.");
772 ode.drelease(world);
773 base.TriggerPhysicsBasedRestart();
774 }
775 catch (Exception e)
776 {
777 m_log.WarnFormat("[PHYSICS]: Unable to collide test an object: {0}", e.Message);
778 return;
779 }
780
781 PhysicsActor p1;
782 PhysicsActor p2;
783
784 if (!actor_name_map.TryGetValue(g1, out p1))
785 {
786 p1 = PANull;
787 }
788
789 if (!actor_name_map.TryGetValue(g2, out p2))
790 {
791 p2 = PANull;
792 }
793
794 ContactPoint maxDepthContact = new ContactPoint();
795 if (p1.CollisionScore + count >= float.MaxValue)
796 p1.CollisionScore = 0;
797 p1.CollisionScore += count;
798
799 if (p2.CollisionScore + count >= float.MaxValue)
800 p2.CollisionScore = 0;
801 p2.CollisionScore += count;
802 for (int i = 0; i < count; i++)
803 {
804 d.ContactGeom curContact = contacts[i];
805
806 if (curContact.depth > maxDepthContact.PenetrationDepth)
807 {
808 maxDepthContact = new ContactPoint(
809 new Vector3(curContact.pos.X, curContact.pos.Y, curContact.pos.Z),
810 new Vector3(curContact.normal.X, curContact.normal.Y, curContact.normal.Z),
811 curContact.depth
812 );
813 }
814
815 //m_log.Warn("[CCOUNT]: " + count);
816 IntPtr joint;
817 // If we're colliding with terrain, use 'TerrainContact' instead of AvatarStaticprimContact.
818 // allows us to have different settings
819
820 // We only need to test p2 for 'jump crouch purposes'
821 if (p2 is OdeCharacter && p1.PhysicsActorType == (int)ActorTypes.Prim)
822 {
823 // Testing if the collision is at the feet of the avatar
824
825 //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));
826//#@ if ((p2.Position.Z - curContact.pos.Z) > (p2.Size.Z * 0.6f))
827//#@ p2.IsColliding = true;
828 if ((p2.Position.Z - curContact.pos.Z) > (p2.Size.Z * 0.6f)){ //##
829 p2.IsColliding = true; //##
830 }else{
831
832 } //##
833 }
834 else
835 {
836 p2.IsColliding = true;
837 }
838
839 //if ((framecount % m_returncollisions) == 0)
840
841 switch (p1.PhysicsActorType)
842 {
843 case (int)ActorTypes.Agent:
844 p2.CollidingObj = true;
845 break;
846 case (int)ActorTypes.Prim:
847 if (p2.Velocity.LengthSquared() > 0.0f)
848 p2.CollidingObj = true;
849 break;
850 case (int)ActorTypes.Unknown:
851 p2.CollidingGround = true;
852 break;
853 default:
854 p2.CollidingGround = true;
855 break;
856 }
857
858 // we don't want prim or avatar to explode
859
860 #region InterPenetration Handling - Unintended physics explosions
861# region disabled code1
862
863 if (curContact.depth >= 0.08f)
864 {
865 //This is disabled at the moment only because it needs more tweaking
866 //It will eventually be uncommented
867 /*
868 if (AvatarStaticprimContact.depth >= 1.00f)
869 {
870 //m_log.Debug("[PHYSICS]: " + AvatarStaticprimContact.depth.ToString());
871 }
872
873 //If you interpenetrate a prim with an agent
874 if ((p2.PhysicsActorType == (int) ActorTypes.Agent &&
875 p1.PhysicsActorType == (int) ActorTypes.Prim) ||
876 (p1.PhysicsActorType == (int) ActorTypes.Agent &&
877 p2.PhysicsActorType == (int) ActorTypes.Prim))
878 {
879
880 //AvatarStaticprimContact.depth = AvatarStaticprimContact.depth * 4.15f;
881 /*
882 if (p2.PhysicsActorType == (int) ActorTypes.Agent)
883 {
884 p2.CollidingObj = true;
885 AvatarStaticprimContact.depth = 0.003f;
886 p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 2.5f);
887 OdeCharacter character = (OdeCharacter) p2;
888 character.SetPidStatus(true);
889 AvatarStaticprimContact.pos = new d.Vector3(AvatarStaticprimContact.pos.X + (p1.Size.X / 2), AvatarStaticprimContact.pos.Y + (p1.Size.Y / 2), AvatarStaticprimContact.pos.Z + (p1.Size.Z / 2));
890
891 }
892 else
893 {
894
895 //AvatarStaticprimContact.depth = 0.0000000f;
896 }
897 if (p1.PhysicsActorType == (int) ActorTypes.Agent)
898 {
899
900 p1.CollidingObj = true;
901 AvatarStaticprimContact.depth = 0.003f;
902 p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 2.5f);
903 AvatarStaticprimContact.pos = new d.Vector3(AvatarStaticprimContact.pos.X + (p2.Size.X / 2), AvatarStaticprimContact.pos.Y + (p2.Size.Y / 2), AvatarStaticprimContact.pos.Z + (p2.Size.Z / 2));
904 OdeCharacter character = (OdeCharacter)p1;
905 character.SetPidStatus(true);
906 }
907 else
908 {
909
910 //AvatarStaticprimContact.depth = 0.0000000f;
911 }
912
913
914
915 }
916*/
917 // If you interpenetrate a prim with another prim
918 /*
919 if (p1.PhysicsActorType == (int) ActorTypes.Prim && p2.PhysicsActorType == (int) ActorTypes.Prim)
920 {
921 #region disabledcode2
922 //OdePrim op1 = (OdePrim)p1;
923 //OdePrim op2 = (OdePrim)p2;
924 //op1.m_collisionscore++;
925 //op2.m_collisionscore++;
926
927 //if (op1.m_collisionscore > 8000 || op2.m_collisionscore > 8000)
928 //{
929 //op1.m_taintdisable = true;
930 //AddPhysicsActorTaint(p1);
931 //op2.m_taintdisable = true;
932 //AddPhysicsActorTaint(p2);
933 //}
934
935 //if (AvatarStaticprimContact.depth >= 0.25f)
936 //{
937 // Don't collide, one or both prim will expld.
938
939 //op1.m_interpenetrationcount++;
940 //op2.m_interpenetrationcount++;
941 //interpenetrations_before_disable = 200;
942 //if (op1.m_interpenetrationcount >= interpenetrations_before_disable)
943 //{
944 //op1.m_taintdisable = true;
945 //AddPhysicsActorTaint(p1);
946 //}
947 //if (op2.m_interpenetrationcount >= interpenetrations_before_disable)
948 //{
949 // op2.m_taintdisable = true;
950 //AddPhysicsActorTaint(p2);
951 //}
952
953 //AvatarStaticprimContact.depth = AvatarStaticprimContact.depth / 8f;
954 //AvatarStaticprimContact.normal = new d.Vector3(0, 0, 1);
955 //}
956 //if (op1.m_disabled || op2.m_disabled)
957 //{
958 //Manually disabled objects stay disabled
959 //AvatarStaticprimContact.depth = 0f;
960 //}
961 #endregion
962 }
963 */
964#endregion
965 if (curContact.depth >= 1.00f)
966 {
967 //m_log.Info("[P]: " + AvatarStaticprimContact.depth.ToString());
968 if ((p2.PhysicsActorType == (int) ActorTypes.Agent &&
969 p1.PhysicsActorType == (int) ActorTypes.Unknown) ||
970 (p1.PhysicsActorType == (int) ActorTypes.Agent &&
971 p2.PhysicsActorType == (int) ActorTypes.Unknown))
972 {
973 if (p2.PhysicsActorType == (int) ActorTypes.Agent)
974 {
975 if (p2 is OdeCharacter)
976 {
977 OdeCharacter character = (OdeCharacter) p2;
978
979 //p2.CollidingObj = true;
980 curContact.depth = 0.00000003f;
981 p2.Velocity = p2.Velocity + new Vector3(0f, 0f, 0.5f);
982 curContact.pos =
983 new d.Vector3(curContact.pos.X + (p1.Size.X/2),
984 curContact.pos.Y + (p1.Size.Y/2),
985 curContact.pos.Z + (p1.Size.Z/2));
986 character.SetPidStatus(true);
987 }
988 }
989
990
991 if (p1.PhysicsActorType == (int) ActorTypes.Agent)
992 {
993 if (p1 is OdeCharacter)
994 {
995 OdeCharacter character = (OdeCharacter) p1;
996
997 //p2.CollidingObj = true;
998 curContact.depth = 0.00000003f;
999 p1.Velocity = p1.Velocity + new Vector3(0f, 0f, 0.5f);
1000 curContact.pos =
1001 new d.Vector3(curContact.pos.X + (p1.Size.X/2),
1002 curContact.pos.Y + (p1.Size.Y/2),
1003 curContact.pos.Z + (p1.Size.Z/2));
1004 character.SetPidStatus(true);
1005 }
1006 }
1007 }
1008 }
1009 }
1010
1011 #endregion
1012
1013 // Logic for collision handling
1014 // Note, that if *all* contacts are skipped (VolumeDetect)
1015 // The prim still detects (and forwards) collision events but
1016 // appears to be phantom for the world
1017 Boolean skipThisContact = false;
1018
1019 if ((p1 is OdePrim) && (((OdePrim)p1).m_isVolumeDetect))
1020 skipThisContact = true; // No collision on volume detect prims
1021
1022 if (!skipThisContact && (p2 is OdePrim) && (((OdePrim)p2).m_isVolumeDetect))
1023 skipThisContact = true; // No collision on volume detect prims
1024
1025 if (!skipThisContact && curContact.depth < 0f)
1026 skipThisContact = true;
1027
1028 if (!skipThisContact && checkDupe(curContact, p2.PhysicsActorType))
1029 skipThisContact = true;
1030
1031 const int maxContactsbeforedeath = 4000;
1032 joint = IntPtr.Zero;
1033
1034 if (!skipThisContact)
1035 {
1036 // Add contact joints with materials params----------------------------------
1037 // p1 is what is being hit, p2 is the physical object doing the hitting
1038 int material = (int) Material.Wood;
1039 int movintYN = 0; // 1 = Sliding; 0 = static or fell onto
1040 if (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f) movintYN = 1;
1041
1042 // If we're colliding against terrain
1043 if (name1 == "Terrain" || name2 == "Terrain")
1044 {
1045 // If we're moving
1046 if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && (movintYN == 1))
1047 {
1048 //$ Av walk/run on terrain (not falling) Use the Avatar movement terrain contact
1049 AvatarMovementTerrainContact.geom = curContact;
1050 _perloopContact.Add(curContact);
1051 if (m_global_contactcount < maxContactsbeforedeath)
1052 {
1053 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementTerrainContact);
1054 m_global_contactcount++;
1055 }
1056 }
1057 else
1058 {
1059 if (p2.PhysicsActorType == (int)ActorTypes.Agent)
1060 {
1061 //$ Av standing on terrain, Use the non moving Avata terrain contact
1062 TerrainContact.geom = curContact;
1063 _perloopContact.Add(curContact);
1064 if (m_global_contactcount < maxContactsbeforedeath)
1065 {
1066 joint = d.JointCreateContact(world, contactgroup, ref TerrainContact);
1067 m_global_contactcount++;
1068 }
1069 }
1070 else
1071 {
1072 if (p2.PhysicsActorType == (int)ActorTypes.Prim && p1.PhysicsActorType == (int)ActorTypes.Prim)
1073 {
1074 //& THIS NEVER HAPPENS? prim prim contact In terrain contact?
1075 // int pj294950 = 0;
1076 // prim terrain contact
1077
1078 if (p2 is OdePrim)
1079 material = ((OdePrim)p2).m_material;
1080 //m_log.DebugFormat("Material: {0}", material);
1081 m_materialContacts[material, movintYN].geom = curContact;
1082 _perloopContact.Add(curContact);
1083
1084 if (m_global_contactcount < maxContactsbeforedeath)
1085 {
1086 joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, movintYN]);
1087 m_global_contactcount++;
1088
1089 }
1090
1091 }
1092 else
1093 {
1094 //$ prim on terrain contact
1095 if (p2 is OdePrim)
1096 material = ((OdePrim)p2).m_material;
1097 //m_log.DebugFormat("Material: {0}", material);
1098 m_materialContacts[material, movintYN].geom = curContact;
1099 _perloopContact.Add(curContact);
1100
1101 ContactCopy = m_materialContacts[material, movintYN];
1102 if(movintYN == 1)
1103 {
1104 // prevent excessive slide on terrain
1105 ContactCopy.surface.mu = m_materialContacts[material, movintYN].surface.mu * 30.0f;
1106 }
1107
1108 if (m_global_contactcount < maxContactsbeforedeath)
1109 {
1110 joint = d.JointCreateContact(world, contactgroup, ref ContactCopy);
1111 m_global_contactcount++;
1112 }
1113 }
1114 }
1115 }
1116 }
1117 else if (name1 == "Water" || name2 == "Water")
1118 {
1119 //$ This never happens! Perhaps water is treated like air?
1120 /*
1121 if ((p2.PhysicsActorType == (int) ActorTypes.Prim))
1122 {
1123 }
1124 else
1125 {
1126 }
1127 */
1128 //WaterContact.surface.soft_cfm = 0.0000f;
1129 //WaterContact.surface.soft_erp = 0.00000f;
1130 if (curContact.depth > 0.1f)
1131 {
1132 curContact.depth *= 52;
1133 //AvatarStaticprimContact.normal = new d.Vector3(0, 0, 1);
1134 //AvatarStaticprimContact.pos = new d.Vector3(0, 0, contact.pos.Z - 5f);
1135 }
1136 WaterContact.geom = curContact;
1137 _perloopContact.Add(curContact);
1138 if (m_global_contactcount < maxContactsbeforedeath)
1139 {
1140 joint = d.JointCreateContact(world, contactgroup, ref WaterContact);
1141 m_global_contactcount++;
1142 }
1143 //m_log.Info("[PHYSICS]: Prim Water Contact" + AvatarStaticprimContact.depth);
1144 }
1145 else
1146 {
1147
1148 // no terrain and no water, we're colliding with prim or avatar
1149 // check if we're moving
1150 if ((p2.PhysicsActorType == (int)ActorTypes.Agent))
1151 {
1152 //$ Avatar on Prim or other Avatar
1153 if (movintYN == 1)
1154 {
1155 // Use the AV Movement / prim contact
1156 AvatarMovementprimContact.geom = curContact;
1157 _perloopContact.Add(curContact);
1158 if (m_global_contactcount < maxContactsbeforedeath)
1159 {
1160 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementprimContact);
1161 m_global_contactcount++;
1162 }
1163 }
1164 else
1165 {
1166 // Use the Av non movement / prim contact
1167 AvatarStaticprimContact.geom = curContact;
1168 _perloopContact.Add(curContact);
1169 ContactCopy = AvatarStaticprimContact; // local copy so we can change locally
1170
1171 if (m_global_contactcount < maxContactsbeforedeath)
1172 {
1173 if (curContact.depth > 0.2)
1174 { // embedded, eject slowly
1175 ContactCopy.surface.soft_erp = 0.1f;
1176 ContactCopy.surface.soft_cfm = 0.1f;
1177 }
1178 else
1179 { // keep on the surface
1180 ContactCopy.surface.soft_erp = 0.3f;
1181 ContactCopy.surface.soft_cfm = 0.0f;
1182 }
1183 joint = d.JointCreateContact(world, contactgroup, ref ContactCopy);
1184 m_global_contactcount++;
1185 }
1186 }
1187 }
1188 else if (p2.PhysicsActorType == (int)ActorTypes.Prim)
1189 {
1190 //$ Prim on Prim
1191 //p1.PhysicsActorType
1192
1193 if (p2 is OdePrim) material = ((OdePrim)p2).m_material;
1194 //m_log.DebugFormat("Material: {0}", material);
1195
1196 m_materialContacts[material, movintYN].geom = curContact;
1197 _perloopContact.Add(curContact);
1198
1199 if (m_global_contactcount < maxContactsbeforedeath)
1200 {
1201 joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, movintYN]);
1202 m_global_contactcount++;
1203 }
1204 }
1205 }
1206
1207 if (m_global_contactcount < maxContactsbeforedeath && joint != IntPtr.Zero) // stack collide!
1208 {
1209 d.JointAttach(joint, b1, b2);
1210 m_global_contactcount++;
1211 }
1212
1213 }
1214 collision_accounting_events(p1, p2, maxDepthContact);
1215 if (count > geomContactPointsStartthrottle)
1216 {
1217 // If there are more then 3 contact points, it's likely
1218 // that we've got a pile of objects, so ...
1219 // We don't want to send out hundreds of terse updates over and over again
1220 // so lets throttle them and send them again after it's somewhat sorted out.
1221 p2.ThrottleUpdates = true;
1222 }
1223 //m_log.Debug(count.ToString());
1224 //m_log.Debug("near: A collision was detected between {1} and {2}", 0, name1, name2);
1225 } // end for i.. loop
1226 } // end near
1227
1228 private bool checkDupe(d.ContactGeom contactGeom, int atype)
1229 {
1230 bool result = false;
1231 //return result;
1232 if (!m_filterCollisions)
1233 return false;
1234
1235 ActorTypes at = (ActorTypes)atype;
1236 lock (_perloopContact)
1237 {
1238 foreach (d.ContactGeom contact in _perloopContact)
1239 {
1240 //if ((contact.g1 == contactGeom.g1 && contact.g2 == contactGeom.g2))
1241 //{
1242 // || (contact.g2 == contactGeom.g1 && contact.g1 == contactGeom.g2)
1243 if (at == ActorTypes.Agent)
1244 {
1245 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)
1246 {
1247
1248 if (Math.Abs(contact.depth - contactGeom.depth) < 0.052f)
1249 {
1250 //contactGeom.depth *= .00005f;
1251 //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth));
1252 // 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));
1253 result = true;
1254 break;
1255 }
1256 else
1257 {
1258 //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth));
1259 }
1260 }
1261 else
1262 {
1263 //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));
1264 //int i = 0;
1265 }
1266 }
1267 else if (at == ActorTypes.Prim)
1268 {
1269 //d.AABB aabb1 = new d.AABB();
1270 //d.AABB aabb2 = new d.AABB();
1271
1272 //d.GeomGetAABB(contactGeom.g2, out aabb2);
1273 //d.GeomGetAABB(contactGeom.g1, out aabb1);
1274 //aabb1.
1275 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)
1276 {
1277 if (contactGeom.normal.X == contact.normal.X && contactGeom.normal.Y == contact.normal.Y && contactGeom.normal.Z == contact.normal.Z)
1278 {
1279 if (Math.Abs(contact.depth - contactGeom.depth) < 0.272f)
1280 {
1281 result = true;
1282 break;
1283 }
1284 }
1285 //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth));
1286 //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));
1287 }
1288
1289 }
1290
1291 //}
1292
1293 }
1294 }
1295 return result;
1296 }
1297
1298 private void collision_accounting_events(PhysicsActor p1, PhysicsActor p2, ContactPoint contact)
1299 {
1300 // obj1LocalID = 0;
1301 //returncollisions = false;
1302 obj2LocalID = 0;
1303 //ctype = 0;
1304 //cStartStop = 0;
1305 if (!p2.SubscribedEvents() && !p1.SubscribedEvents())
1306 return;
1307
1308 switch ((ActorTypes)p2.PhysicsActorType)
1309 {
1310 case ActorTypes.Agent:
1311 cc2 = (OdeCharacter)p2;
1312
1313 // obj1LocalID = cc2.m_localID;
1314 switch ((ActorTypes)p1.PhysicsActorType)
1315 {
1316 case ActorTypes.Agent:
1317 cc1 = (OdeCharacter)p1;
1318 obj2LocalID = cc1.m_localID;
1319 cc1.AddCollisionEvent(cc2.m_localID, contact);
1320 //ctype = (int)CollisionCategories.Character;
1321
1322 //if (cc1.CollidingObj)
1323 //cStartStop = (int)StatusIndicators.Generic;
1324 //else
1325 //cStartStop = (int)StatusIndicators.Start;
1326
1327 //returncollisions = true;
1328 break;
1329 case ActorTypes.Prim:
1330 if (p1 is OdePrim)
1331 {
1332 cp1 = (OdePrim) p1;
1333 obj2LocalID = cp1.m_localID;
1334 cp1.AddCollisionEvent(cc2.m_localID, contact);
1335 }
1336 //ctype = (int)CollisionCategories.Geom;
1337
1338 //if (cp1.CollidingObj)
1339 //cStartStop = (int)StatusIndicators.Generic;
1340 //else
1341 //cStartStop = (int)StatusIndicators.Start;
1342
1343 //returncollisions = true;
1344 break;
1345
1346 case ActorTypes.Ground:
1347 case ActorTypes.Unknown:
1348 obj2LocalID = 0;
1349 //ctype = (int)CollisionCategories.Land;
1350 //returncollisions = true;
1351 break;
1352 }
1353
1354 cc2.AddCollisionEvent(obj2LocalID, contact);
1355 break;
1356 case ActorTypes.Prim:
1357
1358 if (p2 is OdePrim)
1359 {
1360 cp2 = (OdePrim) p2;
1361
1362 // obj1LocalID = cp2.m_localID;
1363 switch ((ActorTypes) p1.PhysicsActorType)
1364 {
1365 case ActorTypes.Agent:
1366 if (p1 is OdeCharacter)
1367 {
1368 cc1 = (OdeCharacter) p1;
1369 obj2LocalID = cc1.m_localID;
1370 cc1.AddCollisionEvent(cp2.m_localID, contact);
1371 //ctype = (int)CollisionCategories.Character;
1372
1373 //if (cc1.CollidingObj)
1374 //cStartStop = (int)StatusIndicators.Generic;
1375 //else
1376 //cStartStop = (int)StatusIndicators.Start;
1377 //returncollisions = true;
1378 }
1379 break;
1380 case ActorTypes.Prim:
1381
1382 if (p1 is OdePrim)
1383 {
1384 cp1 = (OdePrim) p1;
1385 obj2LocalID = cp1.m_localID;
1386 cp1.AddCollisionEvent(cp2.m_localID, contact);
1387 //ctype = (int)CollisionCategories.Geom;
1388
1389 //if (cp1.CollidingObj)
1390 //cStartStop = (int)StatusIndicators.Generic;
1391 //else
1392 //cStartStop = (int)StatusIndicators.Start;
1393
1394 //returncollisions = true;
1395 }
1396 break;
1397
1398 case ActorTypes.Ground:
1399 case ActorTypes.Unknown:
1400 obj2LocalID = 0;
1401 //ctype = (int)CollisionCategories.Land;
1402
1403 //returncollisions = true;
1404 break;
1405 }
1406
1407 cp2.AddCollisionEvent(obj2LocalID, contact);
1408 }
1409 break;
1410 }
1411 //if (returncollisions)
1412 //{
1413
1414 //lock (m_storedCollisions)
1415 //{
1416 //cDictKey = obj1LocalID.ToString() + obj2LocalID.ToString() + cStartStop.ToString() + ctype.ToString();
1417 //if (m_storedCollisions.ContainsKey(cDictKey))
1418 //{
1419 //sCollisionData objd = m_storedCollisions[cDictKey];
1420 //objd.NumberOfCollisions += 1;
1421 //objd.lastframe = framecount;
1422 //m_storedCollisions[cDictKey] = objd;
1423 //}
1424 //else
1425 //{
1426 //sCollisionData objd = new sCollisionData();
1427 //objd.ColliderLocalId = obj1LocalID;
1428 //objd.CollidedWithLocalId = obj2LocalID;
1429 //objd.CollisionType = ctype;
1430 //objd.NumberOfCollisions = 1;
1431 //objd.lastframe = framecount;
1432 //objd.StatusIndicator = cStartStop;
1433 //m_storedCollisions.Add(cDictKey, objd);
1434 //}
1435 //}
1436 // }
1437 }
1438
1439 public int TriArrayCallback(IntPtr trimesh, IntPtr refObject, int[] triangleIndex, int triCount)
1440 {
1441 /* String name1 = null;
1442 String name2 = null;
1443
1444 if (!geom_name_map.TryGetValue(trimesh, out name1))
1445 {
1446 name1 = "null";
1447 }
1448 if (!geom_name_map.TryGetValue(refObject, out name2))
1449 {
1450 name2 = "null";
1451 }
1452
1453 m_log.InfoFormat("TriArrayCallback: A collision was detected between {1} and {2}", 0, name1, name2);
1454 */
1455 return 1;
1456 }
1457
1458 public int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex)
1459 {
1460 String name1 = null;
1461 String name2 = null;
1462
1463 if (!geom_name_map.TryGetValue(trimesh, out name1))
1464 {
1465 name1 = "null";
1466 }
1467
1468 if (!geom_name_map.TryGetValue(refObject, out name2))
1469 {
1470 name2 = "null";
1471 }
1472
1473 // m_log.InfoFormat("TriCallback: A collision was detected between {1} and {2}. Index was {3}", 0, name1, name2, triangleIndex);
1474
1475 d.Vector3 v0 = new d.Vector3();
1476 d.Vector3 v1 = new d.Vector3();
1477 d.Vector3 v2 = new d.Vector3();
1478
1479 d.GeomTriMeshGetTriangle(trimesh, 0, ref v0, ref v1, ref v2);
1480 // 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);
1481
1482 return 1;
1483 }
1484
1485 /// <summary>
1486 /// This is our collision testing routine in ODE
1487 /// </summary>
1488 /// <param name="timeStep"></param>
1489 private void collision_optimized(float timeStep)
1490 {
1491 _perloopContact.Clear();
1492
1493 lock (_characters)
1494 {
1495 foreach (OdeCharacter chr in _characters)
1496 {
1497 // Reset the collision values to false
1498 // since we don't know if we're colliding yet
1499
1500 // For some reason this can happen. Don't ask...
1501 //
1502 if (chr == null)
1503 continue;
1504
1505 if (chr.Shell == IntPtr.Zero || chr.Body == IntPtr.Zero)
1506 continue;
1507
1508 chr.IsColliding = false;
1509 chr.CollidingGround = false;
1510 chr.CollidingObj = false;
1511
1512 // test the avatar's geometry for collision with the space
1513 // This will return near and the space that they are the closest to
1514 // And we'll run this again against the avatar and the space segment
1515 // This will return with a bunch of possible objects in the space segment
1516 // and we'll run it again on all of them.
1517 try
1518 {
1519 d.SpaceCollide2(space, chr.Shell, IntPtr.Zero, nearCallback);
1520 }
1521 catch (AccessViolationException)
1522 {
1523 m_log.Warn("[PHYSICS]: Unable to space collide");
1524 }
1525 //float terrainheight = GetTerrainHeightAtXY(chr.Position.X, chr.Position.Y);
1526 //if (chr.Position.Z + (chr.Velocity.Z * timeStep) < terrainheight + 10)
1527 //{
1528 //chr.Position.Z = terrainheight + 10.0f;
1529 //forcedZ = true;
1530 //}
1531 }
1532 }
1533
1534 lock (_activeprims)
1535 {
1536 List<OdePrim> removeprims = null;
1537 foreach (OdePrim chr in _activeprims)
1538 {
1539 if (chr.Body != IntPtr.Zero && d.BodyIsEnabled(chr.Body) && (!chr.m_disabled))
1540 {
1541 try
1542 {
1543 lock (chr)
1544 {
1545 if (space != IntPtr.Zero && chr.prim_geom != IntPtr.Zero && chr.m_taintremove == false)
1546 {
1547 d.SpaceCollide2(space, chr.prim_geom, IntPtr.Zero, nearCallback);
1548 }
1549 else
1550 {
1551 if (removeprims == null)
1552 {
1553 removeprims = new List<OdePrim>();
1554 }
1555 removeprims.Add(chr);
1556 /// Commented this because it triggers on every bullet
1557 //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!");
1558 }
1559 }
1560 }
1561 catch (AccessViolationException)
1562 {
1563 m_log.Warn("[PHYSICS]: Unable to space collide");
1564 }
1565 }
1566 }
1567 if (removeprims != null)
1568 {
1569 foreach (OdePrim chr in removeprims)
1570 {
1571 _activeprims.Remove(chr);
1572 }
1573 }
1574 }
1575
1576 _perloopContact.Clear();
1577 }
1578
1579 #endregion
1580
1581 public override void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents)
1582 {
1583 m_worldOffset = offset;
1584 WorldExtents = new Vector2(extents.X, extents.Y);
1585 m_parentScene = pScene;
1586
1587 }
1588
1589 // Recovered for use by fly height. Kitto Flora
1590 public float GetTerrainHeightAtXY(float x, float y)
1591 {
1592
1593 int offsetX = ((int)(x / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
1594 int offsetY = ((int)(y / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
1595
1596 IntPtr heightFieldGeom = IntPtr.Zero;
1597
1598 if (RegionTerrain.TryGetValue(new Vector3(offsetX,offsetY,0), out heightFieldGeom))
1599 {
1600 if (heightFieldGeom != IntPtr.Zero)
1601 {
1602 if (TerrainHeightFieldHeights.ContainsKey(heightFieldGeom))
1603 {
1604
1605 int index;
1606
1607
1608 if ((int)x > WorldExtents.X || (int)y > WorldExtents.Y ||
1609 (int)x < 0.001f || (int)y < 0.001f)
1610 return 0;
1611
1612 x = x - offsetX;
1613 y = y - offsetY;
1614
1615 index = (int)((int)x * ((int)Constants.RegionSize + 2) + (int)y);
1616
1617 if (index < TerrainHeightFieldHeights[heightFieldGeom].Length)
1618 {
1619 //m_log.DebugFormat("x{0} y{1} = {2}", x, y, (float)TerrainHeightFieldHeights[heightFieldGeom][index]);
1620 return (float)TerrainHeightFieldHeights[heightFieldGeom][index];
1621 }
1622
1623 else
1624 return 0f;
1625 }
1626 else
1627 {
1628 return 0f;
1629 }
1630
1631 }
1632 else
1633 {
1634 return 0f;
1635 }
1636
1637 }
1638 else
1639 {
1640 return 0f;
1641 }
1642
1643
1644 }
1645// End recovered. Kitto Flora
1646
1647 public void addCollisionEventReporting(PhysicsActor obj)
1648 {
1649 lock (_collisionEventPrim)
1650 {
1651 if (!_collisionEventPrim.Contains(obj))
1652 _collisionEventPrim.Add(obj);
1653 }
1654 }
1655
1656 public void remCollisionEventReporting(PhysicsActor obj)
1657 {
1658 lock (_collisionEventPrim)
1659 {
1660 if (!_collisionEventPrim.Contains(obj))
1661 _collisionEventPrim.Remove(obj);
1662 }
1663 }
1664
1665 #region Add/Remove Entities
1666
1667 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying)
1668 {
1669 Vector3 pos;
1670 pos.X = position.X;
1671 pos.Y = position.Y;
1672 pos.Z = position.Z;
1673 OdeCharacter newAv = new OdeCharacter(avName, this, pos, ode, size, avPIDD, avPIDP, avCapRadius, avStandupTensor, avDensity, avHeightFudgeFactor, avMovementDivisorWalk, avMovementDivisorRun);
1674 newAv.Flying = isFlying;
1675 newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset;
1676
1677 return newAv;
1678 }
1679
1680 public void AddCharacter(OdeCharacter chr)
1681 {
1682 lock (_characters)
1683 {
1684 if (!_characters.Contains(chr))
1685 {
1686 _characters.Add(chr);
1687 if (chr.bad)
1688 m_log.DebugFormat("[PHYSICS] Added BAD actor {0} to characters list", chr.m_uuid);
1689 }
1690 }
1691 }
1692
1693 public void RemoveCharacter(OdeCharacter chr)
1694 {
1695 lock (_characters)
1696 {
1697 if (_characters.Contains(chr))
1698 {
1699 _characters.Remove(chr);
1700 }
1701 }
1702 }
1703 public void BadCharacter(OdeCharacter chr)
1704 {
1705 lock (_badCharacter)
1706 {
1707 if (!_badCharacter.Contains(chr))
1708 _badCharacter.Add(chr);
1709 }
1710 }
1711
1712 public override void RemoveAvatar(PhysicsActor actor)
1713 {
1714 //m_log.Debug("[PHYSICS]:ODELOCK");
1715 ((OdeCharacter) actor).Destroy();
1716
1717 }
1718
1719 private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation,
1720 IMesh mesh, PrimitiveBaseShape pbs, bool isphysical)
1721 {
1722
1723 Vector3 pos = position;
1724 Vector3 siz = size;
1725 Quaternion rot = rotation;
1726
1727 OdePrim newPrim;
1728 lock (OdeLock)
1729 {
1730 newPrim = new OdePrim(name, this, pos, siz, rot, mesh, pbs, isphysical, ode);
1731
1732 lock (_prims)
1733 _prims.Add(newPrim);
1734 }
1735
1736 return newPrim;
1737 }
1738
1739 public void addActivePrim(OdePrim activatePrim)
1740 {
1741 // adds active prim.. (ones that should be iterated over in collisions_optimized
1742 lock (_activeprims)
1743 {
1744 if (!_activeprims.Contains(activatePrim))
1745 _activeprims.Add(activatePrim);
1746 //else
1747 // m_log.Warn("[PHYSICS]: Double Entry in _activeprims detected, potential crash immenent");
1748 }
1749 }
1750
1751 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
1752 Vector3 size, Quaternion rotation) //To be removed
1753 {
1754 return AddPrimShape(primName, pbs, position, size, rotation, false);
1755 }
1756
1757 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
1758 Vector3 size, Quaternion rotation, bool isPhysical)
1759 {
1760 PhysicsActor result;
1761 IMesh mesh = null;
1762
1763 if (needsMeshing(pbs))
1764 mesh = mesher.CreateMesh(primName, pbs, size, 32f, isPhysical);
1765
1766 result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical);
1767
1768 return result;
1769 }
1770
1771 public override float TimeDilation
1772 {
1773 get { return m_timeDilation; }
1774 }
1775
1776 public override bool SupportsNINJAJoints
1777 {
1778 get { return m_NINJA_physics_joints_enabled; }
1779 }
1780
1781 // internal utility function: must be called within a lock (OdeLock)
1782 private void InternalAddActiveJoint(PhysicsJoint joint)
1783 {
1784 activeJoints.Add(joint);
1785 SOPName_to_activeJoint.Add(joint.ObjectNameInScene, joint);
1786 }
1787
1788 // internal utility function: must be called within a lock (OdeLock)
1789 private void InternalAddPendingJoint(OdePhysicsJoint joint)
1790 {
1791 pendingJoints.Add(joint);
1792 SOPName_to_pendingJoint.Add(joint.ObjectNameInScene, joint);
1793 }
1794
1795 // internal utility function: must be called within a lock (OdeLock)
1796 private void InternalRemovePendingJoint(PhysicsJoint joint)
1797 {
1798 pendingJoints.Remove(joint);
1799 SOPName_to_pendingJoint.Remove(joint.ObjectNameInScene);
1800 }
1801
1802 // internal utility function: must be called within a lock (OdeLock)
1803 private void InternalRemoveActiveJoint(PhysicsJoint joint)
1804 {
1805 activeJoints.Remove(joint);
1806 SOPName_to_activeJoint.Remove(joint.ObjectNameInScene);
1807 }
1808
1809 public override void DumpJointInfo()
1810 {
1811 string hdr = "[NINJA] JOINTINFO: ";
1812 foreach (PhysicsJoint j in pendingJoints)
1813 {
1814 m_log.Debug(hdr + " pending joint, Name: " + j.ObjectNameInScene + " raw parms:" + j.RawParams);
1815 }
1816 m_log.Debug(hdr + pendingJoints.Count + " total pending joints");
1817 foreach (string jointName in SOPName_to_pendingJoint.Keys)
1818 {
1819 m_log.Debug(hdr + " pending joints dict contains Name: " + jointName);
1820 }
1821 m_log.Debug(hdr + SOPName_to_pendingJoint.Keys.Count + " total pending joints dict entries");
1822 foreach (PhysicsJoint j in activeJoints)
1823 {
1824 m_log.Debug(hdr + " active joint, Name: " + j.ObjectNameInScene + " raw parms:" + j.RawParams);
1825 }
1826 m_log.Debug(hdr + activeJoints.Count + " total active joints");
1827 foreach (string jointName in SOPName_to_activeJoint.Keys)
1828 {
1829 m_log.Debug(hdr + " active joints dict contains Name: " + jointName);
1830 }
1831 m_log.Debug(hdr + SOPName_to_activeJoint.Keys.Count + " total active joints dict entries");
1832
1833 m_log.Debug(hdr + " Per-body joint connectivity information follows.");
1834 m_log.Debug(hdr + joints_connecting_actor.Keys.Count + " bodies are connected by joints.");
1835 foreach (string actorName in joints_connecting_actor.Keys)
1836 {
1837 m_log.Debug(hdr + " Actor " + actorName + " has the following joints connecting it");
1838 foreach (PhysicsJoint j in joints_connecting_actor[actorName])
1839 {
1840 m_log.Debug(hdr + " * joint Name: " + j.ObjectNameInScene + " raw parms:" + j.RawParams);
1841 }
1842 m_log.Debug(hdr + joints_connecting_actor[actorName].Count + " connecting joints total for this actor");
1843 }
1844 }
1845
1846 public override void RequestJointDeletion(string ObjectNameInScene)
1847 {
1848 lock (externalJointRequestsLock)
1849 {
1850 if (!requestedJointsToBeDeleted.Contains(ObjectNameInScene)) // forbid same deletion request from entering twice to prevent spurious deletions processed asynchronously
1851 {
1852 requestedJointsToBeDeleted.Add(ObjectNameInScene);
1853 }
1854 }
1855 }
1856
1857 private void DeleteRequestedJoints()
1858 {
1859 List<string> myRequestedJointsToBeDeleted;
1860 lock (externalJointRequestsLock)
1861 {
1862 // make a local copy of the shared list for processing (threading issues)
1863 myRequestedJointsToBeDeleted = new List<string>(requestedJointsToBeDeleted);
1864 }
1865
1866 foreach (string jointName in myRequestedJointsToBeDeleted)
1867 {
1868 lock (OdeLock)
1869 {
1870 //m_log.Debug("[NINJA] trying to deleting requested joint " + jointName);
1871 if (SOPName_to_activeJoint.ContainsKey(jointName) || SOPName_to_pendingJoint.ContainsKey(jointName))
1872 {
1873 OdePhysicsJoint joint = null;
1874 if (SOPName_to_activeJoint.ContainsKey(jointName))
1875 {
1876 joint = SOPName_to_activeJoint[jointName] as OdePhysicsJoint;
1877 InternalRemoveActiveJoint(joint);
1878 }
1879 else if (SOPName_to_pendingJoint.ContainsKey(jointName))
1880 {
1881 joint = SOPName_to_pendingJoint[jointName] as OdePhysicsJoint;
1882 InternalRemovePendingJoint(joint);
1883 }
1884
1885 if (joint != null)
1886 {
1887 //m_log.Debug("joint.BodyNames.Count is " + joint.BodyNames.Count + " and contents " + joint.BodyNames);
1888 for (int iBodyName = 0; iBodyName < 2; iBodyName++)
1889 {
1890 string bodyName = joint.BodyNames[iBodyName];
1891 if (bodyName != "NULL")
1892 {
1893 joints_connecting_actor[bodyName].Remove(joint);
1894 if (joints_connecting_actor[bodyName].Count == 0)
1895 {
1896 joints_connecting_actor.Remove(bodyName);
1897 }
1898 }
1899 }
1900
1901 DoJointDeactivated(joint);
1902 if (joint.jointID != IntPtr.Zero)
1903 {
1904 d.JointDestroy(joint.jointID);
1905 joint.jointID = IntPtr.Zero;
1906 //DoJointErrorMessage(joint, "successfully destroyed joint " + jointName);
1907 }
1908 else
1909 {
1910 //m_log.Warn("[NINJA] Ignoring re-request to destroy joint " + jointName);
1911 }
1912 }
1913 else
1914 {
1915 // DoJointErrorMessage(joint, "coult not find joint to destroy based on name " + jointName);
1916 }
1917 }
1918 else
1919 {
1920 // DoJointErrorMessage(joint, "WARNING - joint removal failed, joint " + jointName);
1921 }
1922 }
1923 }
1924
1925 // remove processed joints from the shared list
1926 lock (externalJointRequestsLock)
1927 {
1928 foreach (string jointName in myRequestedJointsToBeDeleted)
1929 {
1930 requestedJointsToBeDeleted.Remove(jointName);
1931 }
1932 }
1933 }
1934
1935 // for pending joints we don't know if their associated bodies exist yet or not.
1936 // the joint is actually created during processing of the taints
1937 private void CreateRequestedJoints()
1938 {
1939 List<PhysicsJoint> myRequestedJointsToBeCreated;
1940 lock (externalJointRequestsLock)
1941 {
1942 // make a local copy of the shared list for processing (threading issues)
1943 myRequestedJointsToBeCreated = new List<PhysicsJoint>(requestedJointsToBeCreated);
1944 }
1945
1946 foreach (PhysicsJoint joint in myRequestedJointsToBeCreated)
1947 {
1948 lock (OdeLock)
1949 {
1950 if (SOPName_to_pendingJoint.ContainsKey(joint.ObjectNameInScene) && SOPName_to_pendingJoint[joint.ObjectNameInScene] != null)
1951 {
1952 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);
1953 continue;
1954 }
1955 if (SOPName_to_activeJoint.ContainsKey(joint.ObjectNameInScene) && SOPName_to_activeJoint[joint.ObjectNameInScene] != null)
1956 {
1957 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);
1958 continue;
1959 }
1960
1961 InternalAddPendingJoint(joint as OdePhysicsJoint);
1962
1963 if (joint.BodyNames.Count >= 2)
1964 {
1965 for (int iBodyName = 0; iBodyName < 2; iBodyName++)
1966 {
1967 string bodyName = joint.BodyNames[iBodyName];
1968 if (bodyName != "NULL")
1969 {
1970 if (!joints_connecting_actor.ContainsKey(bodyName))
1971 {
1972 joints_connecting_actor.Add(bodyName, new List<PhysicsJoint>());
1973 }
1974 joints_connecting_actor[bodyName].Add(joint);
1975 }
1976 }
1977 }
1978 }
1979 }
1980
1981 // remove processed joints from shared list
1982 lock (externalJointRequestsLock)
1983 {
1984 foreach (PhysicsJoint joint in myRequestedJointsToBeCreated)
1985 {
1986 requestedJointsToBeCreated.Remove(joint);
1987 }
1988 }
1989
1990 }
1991
1992 // public function to add an request for joint creation
1993 // this joint will just be added to a waiting list that is NOT processed during the main
1994 // Simulate() loop (to avoid deadlocks). After Simulate() is finished, we handle unprocessed joint requests.
1995
1996 public override PhysicsJoint RequestJointCreation(string objectNameInScene, PhysicsJointType jointType, Vector3 position,
1997 Quaternion rotation, string parms, List<string> bodyNames, string trackedBodyName, Quaternion localRotation)
1998
1999 {
2000
2001 OdePhysicsJoint joint = new OdePhysicsJoint();
2002 joint.ObjectNameInScene = objectNameInScene;
2003 joint.Type = jointType;
2004 joint.Position = position;
2005 joint.Rotation = rotation;
2006 joint.RawParams = parms;
2007 joint.BodyNames = new List<string>(bodyNames);
2008 joint.TrackedBodyName = trackedBodyName;
2009 joint.LocalRotation = localRotation;
2010 joint.jointID = IntPtr.Zero;
2011 joint.ErrorMessageCount = 0;
2012
2013 lock (externalJointRequestsLock)
2014 {
2015 if (!requestedJointsToBeCreated.Contains(joint)) // forbid same creation request from entering twice
2016 {
2017 requestedJointsToBeCreated.Add(joint);
2018 }
2019 }
2020 return joint;
2021 }
2022
2023 private void RemoveAllJointsConnectedToActor(PhysicsActor actor)
2024 {
2025 //m_log.Debug("RemoveAllJointsConnectedToActor: start");
2026 if (actor.SOPName != null && joints_connecting_actor.ContainsKey(actor.SOPName) && joints_connecting_actor[actor.SOPName] != null)
2027 {
2028
2029 List<PhysicsJoint> jointsToRemove = new List<PhysicsJoint>();
2030 //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)
2031 foreach (PhysicsJoint j in joints_connecting_actor[actor.SOPName])
2032 {
2033 jointsToRemove.Add(j);
2034 }
2035 foreach (PhysicsJoint j in jointsToRemove)
2036 {
2037 //m_log.Debug("RemoveAllJointsConnectedToActor: about to request deletion of " + j.ObjectNameInScene);
2038 RequestJointDeletion(j.ObjectNameInScene);
2039 //m_log.Debug("RemoveAllJointsConnectedToActor: done request deletion of " + j.ObjectNameInScene);
2040 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)
2041 }
2042 }
2043 }
2044
2045 public override void RemoveAllJointsConnectedToActorThreadLocked(PhysicsActor actor)
2046 {
2047 //m_log.Debug("RemoveAllJointsConnectedToActorThreadLocked: start");
2048 lock (OdeLock)
2049 {
2050 //m_log.Debug("RemoveAllJointsConnectedToActorThreadLocked: got lock");
2051 RemoveAllJointsConnectedToActor(actor);
2052 }
2053 }
2054
2055 // normally called from within OnJointMoved, which is called from within a lock (OdeLock)
2056 public override Vector3 GetJointAnchor(PhysicsJoint joint)
2057 {
2058 Debug.Assert(joint.IsInPhysicsEngine);
2059 d.Vector3 pos = new d.Vector3();
2060
2061 if (!(joint is OdePhysicsJoint))
2062 {
2063 DoJointErrorMessage(joint, "warning: non-ODE joint requesting anchor: " + joint.ObjectNameInScene);
2064 }
2065 else
2066 {
2067 OdePhysicsJoint odeJoint = (OdePhysicsJoint)joint;
2068 switch (odeJoint.Type)
2069 {
2070 case PhysicsJointType.Ball:
2071 d.JointGetBallAnchor(odeJoint.jointID, out pos);
2072 break;
2073 case PhysicsJointType.Hinge:
2074 d.JointGetHingeAnchor(odeJoint.jointID, out pos);
2075 break;
2076 }
2077 }
2078 return new Vector3(pos.X, pos.Y, pos.Z);
2079 }
2080
2081 // normally called from within OnJointMoved, which is called from within a lock (OdeLock)
2082 // WARNING: ODE sometimes returns <0,0,0> as the joint axis! Therefore this function
2083 // appears to be unreliable. Fortunately we can compute the joint axis ourselves by
2084 // keeping track of the joint's original orientation relative to one of the involved bodies.
2085 public override Vector3 GetJointAxis(PhysicsJoint joint)
2086 {
2087 Debug.Assert(joint.IsInPhysicsEngine);
2088 d.Vector3 axis = new d.Vector3();
2089
2090 if (!(joint is OdePhysicsJoint))
2091 {
2092 DoJointErrorMessage(joint, "warning: non-ODE joint requesting anchor: " + joint.ObjectNameInScene);
2093 }
2094 else
2095 {
2096 OdePhysicsJoint odeJoint = (OdePhysicsJoint)joint;
2097 switch (odeJoint.Type)
2098 {
2099 case PhysicsJointType.Ball:
2100 DoJointErrorMessage(joint, "warning - axis requested for ball joint: " + joint.ObjectNameInScene);
2101 break;
2102 case PhysicsJointType.Hinge:
2103 d.JointGetHingeAxis(odeJoint.jointID, out axis);
2104 break;
2105 }
2106 }
2107 return new Vector3(axis.X, axis.Y, axis.Z);
2108 }
2109
2110
2111 public void remActivePrim(OdePrim deactivatePrim)
2112 {
2113 lock (_activeprims)
2114 {
2115 _activeprims.Remove(deactivatePrim);
2116 }
2117 }
2118
2119 public override void RemovePrim(PhysicsActor prim)
2120 {
2121 if (prim is OdePrim)
2122 {
2123 lock (OdeLock)
2124 {
2125 OdePrim p = (OdePrim) prim;
2126
2127 p.setPrimForRemoval();
2128 AddPhysicsActorTaint(prim);
2129 //RemovePrimThreadLocked(p);
2130 }
2131 }
2132 }
2133
2134 /// <summary>
2135 /// This is called from within simulate but outside the locked portion
2136 /// We need to do our own locking here
2137 /// Essentially, we need to remove the prim from our space segment, whatever segment it's in.
2138 ///
2139 /// If there are no more prim in the segment, we need to empty (spacedestroy)the segment and reclaim memory
2140 /// that the space was using.
2141 /// </summary>
2142 /// <param name="prim"></param>
2143 public void RemovePrimThreadLocked(OdePrim prim)
2144 {
2145//Console.WriteLine("RemovePrimThreadLocked " + prim.m_primName);
2146 lock (prim)
2147 {
2148 remCollisionEventReporting(prim);
2149 lock (ode)
2150 {
2151 if (prim.prim_geom != IntPtr.Zero)
2152 {
2153 prim.ResetTaints();
2154
2155 if (prim.IsPhysical)
2156 {
2157 prim.disableBody();
2158 if (prim.childPrim)
2159 {
2160 prim.childPrim = false;
2161 prim.Body = IntPtr.Zero;
2162 prim.m_disabled = true;
2163 prim.IsPhysical = false;
2164 }
2165
2166
2167 }
2168 // we don't want to remove the main space
2169
2170 // If the geometry is in the targetspace, remove it from the target space
2171 //m_log.Warn(prim.m_targetSpace);
2172
2173 //if (prim.m_targetSpace != IntPtr.Zero)
2174 //{
2175 //if (d.SpaceQuery(prim.m_targetSpace, prim.prim_geom))
2176 //{
2177
2178 //if (d.GeomIsSpace(prim.m_targetSpace))
2179 //{
2180 //waitForSpaceUnlock(prim.m_targetSpace);
2181 //d.SpaceRemove(prim.m_targetSpace, prim.prim_geom);
2182 prim.m_targetSpace = IntPtr.Zero;
2183 //}
2184 //else
2185 //{
2186 // m_log.Info("[Physics]: Invalid Scene passed to 'removeprim from scene':" +
2187 //((OdePrim)prim).m_targetSpace.ToString());
2188 //}
2189
2190 //}
2191 //}
2192 //m_log.Warn(prim.prim_geom);
2193 try
2194 {
2195 if (prim.prim_geom != IntPtr.Zero)
2196 {
2197
2198//string tPA;
2199//geom_name_map.TryGetValue(prim.prim_geom, out tPA);
2200//Console.WriteLine("**** Remove {0}", tPA);
2201 if(geom_name_map.ContainsKey(prim.prim_geom)) geom_name_map.Remove(prim.prim_geom);
2202 if(actor_name_map.ContainsKey(prim.prim_geom)) actor_name_map.Remove(prim.prim_geom);
2203 d.GeomDestroy(prim.prim_geom);
2204 prim.prim_geom = IntPtr.Zero;
2205 }
2206 else
2207 {
2208 m_log.Warn("[PHYSICS]: Unable to remove prim from physics scene");
2209 }
2210 }
2211 catch (AccessViolationException)
2212 {
2213 m_log.Info("[PHYSICS]: Couldn't remove prim from physics scene, it was already be removed.");
2214 }
2215 lock (_prims)
2216 _prims.Remove(prim);
2217
2218 //If there are no more geometries in the sub-space, we don't need it in the main space anymore
2219 //if (d.SpaceGetNumGeoms(prim.m_targetSpace) == 0)
2220 //{
2221 //if (prim.m_targetSpace != null)
2222 //{
2223 //if (d.GeomIsSpace(prim.m_targetSpace))
2224 //{
2225 //waitForSpaceUnlock(prim.m_targetSpace);
2226 //d.SpaceRemove(space, prim.m_targetSpace);
2227 // free up memory used by the space.
2228 //d.SpaceDestroy(prim.m_targetSpace);
2229 //int[] xyspace = calculateSpaceArrayItemFromPos(prim.Position);
2230 //resetSpaceArrayItemToZero(xyspace[0], xyspace[1]);
2231 //}
2232 //else
2233 //{
2234 //m_log.Info("[Physics]: Invalid Scene passed to 'removeprim from scene':" +
2235 //((OdePrim) prim).m_targetSpace.ToString());
2236 //}
2237 //}
2238 //}
2239
2240 if (SupportsNINJAJoints)
2241 {
2242 RemoveAllJointsConnectedToActorThreadLocked(prim);
2243 }
2244 }
2245 }
2246 }
2247 }
2248
2249 #endregion
2250
2251 #region Space Separation Calculation
2252
2253 /// <summary>
2254 /// Takes a space pointer and zeros out the array we're using to hold the spaces
2255 /// </summary>
2256 /// <param name="pSpace"></param>
2257 public void resetSpaceArrayItemToZero(IntPtr pSpace)
2258 {
2259 for (int x = 0; x < staticPrimspace.GetLength(0); x++)
2260 {
2261 for (int y = 0; y < staticPrimspace.GetLength(1); y++)
2262 {
2263 if (staticPrimspace[x, y] == pSpace)
2264 staticPrimspace[x, y] = IntPtr.Zero;
2265 }
2266 }
2267 }
2268
2269 public void resetSpaceArrayItemToZero(int arrayitemX, int arrayitemY)
2270 {
2271 staticPrimspace[arrayitemX, arrayitemY] = IntPtr.Zero;
2272 }
2273
2274 /// <summary>
2275 /// Called when a static prim moves. Allocates a space for the prim based on its position
2276 /// </summary>
2277 /// <param name="geom">the pointer to the geom that moved</param>
2278 /// <param name="pos">the position that the geom moved to</param>
2279 /// <param name="currentspace">a pointer to the space it was in before it was moved.</param>
2280 /// <returns>a pointer to the new space it's in</returns>
2281 public IntPtr recalculateSpaceForGeom(IntPtr geom, Vector3 pos, IntPtr currentspace)
2282 {
2283 // Called from setting the Position and Size of an ODEPrim so
2284 // it's already in locked space.
2285
2286 // we don't want to remove the main space
2287 // we don't need to test physical here because this function should
2288 // never be called if the prim is physical(active)
2289
2290 // All physical prim end up in the root space
2291 //Thread.Sleep(20);
2292 if (currentspace != space)
2293 {
2294 //m_log.Info("[SPACE]: C:" + currentspace.ToString() + " g:" + geom.ToString());
2295 //if (currentspace == IntPtr.Zero)
2296 //{
2297 //int adfadf = 0;
2298 //}
2299 if (d.SpaceQuery(currentspace, geom) && currentspace != IntPtr.Zero)
2300 {
2301 if (d.GeomIsSpace(currentspace))
2302 {
2303 waitForSpaceUnlock(currentspace);
2304 d.SpaceRemove(currentspace, geom);
2305 }
2306 else
2307 {
2308 m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + currentspace +
2309 " Geom:" + geom);
2310 }
2311 }
2312 else
2313 {
2314 IntPtr sGeomIsIn = d.GeomGetSpace(geom);
2315 if (sGeomIsIn != IntPtr.Zero)
2316 {
2317 if (d.GeomIsSpace(currentspace))
2318 {
2319 waitForSpaceUnlock(sGeomIsIn);
2320 d.SpaceRemove(sGeomIsIn, geom);
2321 }
2322 else
2323 {
2324 m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" +
2325 sGeomIsIn + " Geom:" + geom);
2326 }
2327 }
2328 }
2329
2330 //If there are no more geometries in the sub-space, we don't need it in the main space anymore
2331 if (d.SpaceGetNumGeoms(currentspace) == 0)
2332 {
2333 if (currentspace != IntPtr.Zero)
2334 {
2335 if (d.GeomIsSpace(currentspace))
2336 {
2337 waitForSpaceUnlock(currentspace);
2338 waitForSpaceUnlock(space);
2339 d.SpaceRemove(space, currentspace);
2340 // free up memory used by the space.
2341
2342 //d.SpaceDestroy(currentspace);
2343 resetSpaceArrayItemToZero(currentspace);
2344 }
2345 else
2346 {
2347 m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" +
2348 currentspace + " Geom:" + geom);
2349 }
2350 }
2351 }
2352 }
2353 else
2354 {
2355 // this is a physical object that got disabled. ;.;
2356 if (currentspace != IntPtr.Zero && geom != IntPtr.Zero)
2357 {
2358 if (d.SpaceQuery(currentspace, geom))
2359 {
2360 if (d.GeomIsSpace(currentspace))
2361 {
2362 waitForSpaceUnlock(currentspace);
2363 d.SpaceRemove(currentspace, geom);
2364 }
2365 else
2366 {
2367 m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" +
2368 currentspace + " Geom:" + geom);
2369 }
2370 }
2371 else
2372 {
2373 IntPtr sGeomIsIn = d.GeomGetSpace(geom);
2374 if (sGeomIsIn != IntPtr.Zero)
2375 {
2376 if (d.GeomIsSpace(sGeomIsIn))
2377 {
2378 waitForSpaceUnlock(sGeomIsIn);
2379 d.SpaceRemove(sGeomIsIn, geom);
2380 }
2381 else
2382 {
2383 m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" +
2384 sGeomIsIn + " Geom:" + geom);
2385 }
2386 }
2387 }
2388 }
2389 }
2390
2391 // The routines in the Position and Size sections do the 'inserting' into the space,
2392 // so all we have to do is make sure that the space that we're putting the prim into
2393 // is in the 'main' space.
2394 int[] iprimspaceArrItem = calculateSpaceArrayItemFromPos(pos);
2395 IntPtr newspace = calculateSpaceForGeom(pos);
2396
2397 if (newspace == IntPtr.Zero)
2398 {
2399 newspace = createprimspace(iprimspaceArrItem[0], iprimspaceArrItem[1]);
2400 d.HashSpaceSetLevels(newspace, smallHashspaceLow, smallHashspaceHigh);
2401 }
2402
2403 return newspace;
2404 }
2405
2406 /// <summary>
2407 /// Creates a new space at X Y
2408 /// </summary>
2409 /// <param name="iprimspaceArrItemX"></param>
2410 /// <param name="iprimspaceArrItemY"></param>
2411 /// <returns>A pointer to the created space</returns>
2412 public IntPtr createprimspace(int iprimspaceArrItemX, int iprimspaceArrItemY)
2413 {
2414 // creating a new space for prim and inserting it into main space.
2415 staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY] = d.HashSpaceCreate(IntPtr.Zero);
2416 d.GeomSetCategoryBits(staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY], (int)CollisionCategories.Space);
2417 waitForSpaceUnlock(space);
2418 d.SpaceSetSublevel(space, 1);
2419 d.SpaceAdd(space, staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY]);
2420 return staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY];
2421 }
2422
2423 /// <summary>
2424 /// Calculates the space the prim should be in by its position
2425 /// </summary>
2426 /// <param name="pos"></param>
2427 /// <returns>a pointer to the space. This could be a new space or reused space.</returns>
2428 public IntPtr calculateSpaceForGeom(Vector3 pos)
2429 {
2430 int[] xyspace = calculateSpaceArrayItemFromPos(pos);
2431 //m_log.Info("[Physics]: Attempting to use arrayItem: " + xyspace[0].ToString() + "," + xyspace[1].ToString());
2432 return staticPrimspace[xyspace[0], xyspace[1]];
2433 }
2434
2435 /// <summary>
2436 /// Holds the space allocation logic
2437 /// </summary>
2438 /// <param name="pos"></param>
2439 /// <returns>an array item based on the position</returns>
2440 public int[] calculateSpaceArrayItemFromPos(Vector3 pos)
2441 {
2442 int[] returnint = new int[2];
2443
2444 returnint[0] = (int) (pos.X/metersInSpace);
2445
2446 if (returnint[0] > ((int) (259f/metersInSpace)))
2447 returnint[0] = ((int) (259f/metersInSpace));
2448 if (returnint[0] < 0)
2449 returnint[0] = 0;
2450
2451 returnint[1] = (int) (pos.Y/metersInSpace);
2452 if (returnint[1] > ((int) (259f/metersInSpace)))
2453 returnint[1] = ((int) (259f/metersInSpace));
2454 if (returnint[1] < 0)
2455 returnint[1] = 0;
2456
2457 return returnint;
2458 }
2459
2460 #endregion
2461
2462 /// <summary>
2463 /// Routine to figure out if we need to mesh this prim with our mesher
2464 /// </summary>
2465 /// <param name="pbs"></param>
2466 /// <returns></returns>
2467 public bool needsMeshing(PrimitiveBaseShape pbs)
2468 {
2469 // most of this is redundant now as the mesher will return null if it cant mesh a prim
2470 // but we still need to check for sculptie meshing being enabled so this is the most
2471 // convenient place to do it for now...
2472
2473 // //if (pbs.PathCurve == (byte)Primitive.PathCurve.Circle && pbs.ProfileCurve == (byte)Primitive.ProfileCurve.Circle && pbs.PathScaleY <= 0.75f)
2474 // //m_log.Debug("needsMeshing: " + " pathCurve: " + pbs.PathCurve.ToString() + " profileCurve: " + pbs.ProfileCurve.ToString() + " pathScaleY: " + Primitive.UnpackPathScale(pbs.PathScaleY).ToString());
2475 int iPropertiesNotSupportedDefault = 0;
2476
2477 if (pbs.SculptEntry && !meshSculptedPrim)
2478 {
2479#if SPAM
2480 m_log.Warn("NonMesh");
2481#endif
2482 return false;
2483 }
2484
2485 // 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
2486 if (!forceSimplePrimMeshing)
2487 {
2488 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
2489 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
2490 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
2491 {
2492
2493 if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
2494 && pbs.ProfileHollow == 0
2495 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
2496 && pbs.PathBegin == 0 && pbs.PathEnd == 0
2497 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
2498 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
2499 && pbs.PathShearX == 0 && pbs.PathShearY == 0)
2500 {
2501#if SPAM
2502 m_log.Warn("NonMesh");
2503#endif
2504 return false;
2505 }
2506 }
2507 }
2508
2509 if (pbs.ProfileHollow != 0)
2510 iPropertiesNotSupportedDefault++;
2511
2512 if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
2513 iPropertiesNotSupportedDefault++;
2514
2515 if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
2516 iPropertiesNotSupportedDefault++;
2517
2518 if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
2519 iPropertiesNotSupportedDefault++;
2520
2521 if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
2522 iPropertiesNotSupportedDefault++;
2523
2524 if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
2525 iPropertiesNotSupportedDefault++;
2526
2527 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))
2528 iPropertiesNotSupportedDefault++;
2529
2530 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte) Extrusion.Curve1)
2531 iPropertiesNotSupportedDefault++;
2532
2533 // test for torus
2534 if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
2535 {
2536 if (pbs.PathCurve == (byte)Extrusion.Curve1)
2537 {
2538 iPropertiesNotSupportedDefault++;
2539 }
2540 }
2541 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
2542 {
2543 if (pbs.PathCurve == (byte)Extrusion.Straight)
2544 {
2545 iPropertiesNotSupportedDefault++;
2546 }
2547
2548 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
2549 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
2550 {
2551 iPropertiesNotSupportedDefault++;
2552 }
2553 }
2554 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
2555 {
2556 if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
2557 {
2558 iPropertiesNotSupportedDefault++;
2559 }
2560 }
2561 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
2562 {
2563 if (pbs.PathCurve == (byte)Extrusion.Straight)
2564 {
2565 iPropertiesNotSupportedDefault++;
2566 }
2567 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
2568 {
2569 iPropertiesNotSupportedDefault++;
2570 }
2571 }
2572
2573
2574 if (iPropertiesNotSupportedDefault == 0)
2575 {
2576#if SPAM
2577 m_log.Warn("NonMesh");
2578#endif
2579 return false;
2580 }
2581#if SPAM
2582 m_log.Debug("Mesh");
2583#endif
2584 return true;
2585 }
2586
2587 /// <summary>
2588 /// Called after our prim properties are set Scale, position etc.
2589 /// We use this event queue like method to keep changes to the physical scene occuring in the threadlocked mutex
2590 /// This assures us that we have no race conditions
2591 /// </summary>
2592 /// <param name="prim"></param>
2593 public override void AddPhysicsActorTaint(PhysicsActor prim)
2594 {
2595
2596 if (prim is OdePrim)
2597 {
2598 OdePrim taintedprim = ((OdePrim) prim);
2599 lock (_taintedPrimLock)
2600 {
2601 if (!(_taintedPrimH.Contains(taintedprim)))
2602 {
2603//Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.m_primName);
2604 _taintedPrimH.Add(taintedprim); // HashSet for searching
2605 _taintedPrimL.Add(taintedprim); // List for ordered readout
2606 }
2607 }
2608 return;
2609 }
2610 else if (prim is OdeCharacter)
2611 {
2612 OdeCharacter taintedchar = ((OdeCharacter)prim);
2613 lock (_taintedActors)
2614 {
2615 if (!(_taintedActors.Contains(taintedchar)))
2616 {
2617 _taintedActors.Add(taintedchar);
2618 if (taintedchar.bad)
2619 m_log.DebugFormat("[PHYSICS]: Added BAD actor {0} to tainted actors", taintedchar.m_uuid);
2620 }
2621 }
2622 }
2623 }
2624
2625 /// <summary>
2626 /// This is our main simulate loop
2627 /// It's thread locked by a Mutex in the scene.
2628 /// It holds Collisions, it instructs ODE to step through the physical reactions
2629 /// It moves the objects around in memory
2630 /// It calls the methods that report back to the object owners.. (scenepresence, SceneObjectGroup)
2631 /// </summary>
2632 /// <param name="timeStep"></param>
2633 /// <returns></returns>
2634 public override float Simulate(float timeStep)
2635 {
2636 if (framecount >= int.MaxValue)
2637 framecount = 0;
2638 //if (m_worldOffset != Vector3.Zero)
2639 // return 0;
2640
2641 framecount++;
2642
2643 DateTime now = DateTime.UtcNow;
2644 TimeSpan SinceLastFrame = now - m_lastframe;
2645 m_lastframe = now;
2646 float realtime = (float)SinceLastFrame.TotalSeconds;
2647// Console.WriteLine("ts={0} rt={1}", timeStep, realtime);
2648 timeStep = realtime;
2649
2650 // float fps = 1.0f / realtime;
2651 float fps = 0.0f; // number of ODE steps in this Simulate step
2652 //m_log.Info(timeStep.ToString());
2653 step_time += timeStep;
2654
2655 // If We're loaded down by something else,
2656 // or debugging with the Visual Studio project on pause
2657 // skip a few frames to catch up gracefully.
2658 // without shooting the physicsactors all over the place
2659
2660 if (step_time >= m_SkipFramesAtms)
2661 {
2662 // Instead of trying to catch up, it'll do 5 physics frames only
2663 step_time = ODE_STEPSIZE;
2664 m_physicsiterations = 5;
2665 }
2666 else
2667 {
2668 m_physicsiterations = 10;
2669 }
2670
2671 if (SupportsNINJAJoints)
2672 {
2673 DeleteRequestedJoints(); // this must be outside of the lock (OdeLock) to avoid deadlocks
2674 CreateRequestedJoints(); // this must be outside of the lock (OdeLock) to avoid deadlocks
2675 }
2676
2677 lock (OdeLock)
2678 {
2679 // Process 10 frames if the sim is running normal..
2680 // process 5 frames if the sim is running slow
2681 //try
2682 //{
2683 //d.WorldSetQuickStepNumIterations(world, m_physicsiterations);
2684 //}
2685 //catch (StackOverflowException)
2686 //{
2687 // m_log.Error("[PHYSICS]: The operating system wasn't able to allocate enough memory for the simulation. Restarting the sim.");
2688 // ode.drelease(world);
2689 //base.TriggerPhysicsBasedRestart();
2690 //}
2691
2692 int i = 0;
2693
2694 // Figure out the Frames Per Second we're going at.
2695 //(step_time == 0.004f, there's 250 of those per second. Times the step time/step size
2696
2697 // fps = (step_time / ODE_STEPSIZE) * 1000;
2698 // HACK: Using a time dilation of 1.0 to debug rubberbanding issues
2699 //m_timeDilation = Math.Min((step_time / ODE_STEPSIZE) / (0.09375f / ODE_STEPSIZE), 1.0f);
2700
2701 // step_time = 0.09375f;
2702
2703 while (step_time > 0.0f)
2704 {
2705 //lock (ode)
2706 //{
2707 //if (!ode.lockquery())
2708 //{
2709 // ode.dlock(world);
2710 try
2711 {
2712 // Insert, remove Characters
2713 bool processedtaints = false;
2714
2715 lock (_taintedActors)
2716 {
2717 if (_taintedActors.Count > 0)
2718 {
2719 foreach (OdeCharacter character in _taintedActors)
2720 {
2721
2722 character.ProcessTaints(ODE_STEPSIZE);
2723
2724 processedtaints = true;
2725 //character.m_collisionscore = 0;
2726 }
2727
2728 if (processedtaints)
2729 _taintedActors.Clear();
2730 }
2731 } // end lock _taintedActors
2732
2733 // Modify other objects in the scene.
2734 processedtaints = false;
2735
2736 lock (_taintedPrimLock)
2737 {
2738 foreach (OdePrim prim in _taintedPrimL)
2739 {
2740 if (prim.m_taintremove)
2741 {
2742 //Console.WriteLine("Simulate calls RemovePrimThreadLocked");
2743 RemovePrimThreadLocked(prim);
2744 }
2745 else
2746 {
2747 //Console.WriteLine("Simulate calls ProcessTaints");
2748 prim.ProcessTaints(ODE_STEPSIZE);
2749 }
2750 processedtaints = true;
2751 prim.m_collisionscore = 0;
2752
2753 // This loop can block up the Heartbeat for a very long time on large regions.
2754 // We need to let the Watchdog know that the Heartbeat is not dead
2755 // NOTE: This is currently commented out, but if things like OAR loading are
2756 // timing the heartbeat out we will need to uncomment it
2757 //Watchdog.UpdateThread();
2758 }
2759
2760 if (SupportsNINJAJoints)
2761 {
2762 // Create pending joints, if possible
2763
2764 // joints can only be processed after ALL bodies are processed (and exist in ODE), since creating
2765 // a joint requires specifying the body id of both involved bodies
2766 if (pendingJoints.Count > 0)
2767 {
2768 List<PhysicsJoint> successfullyProcessedPendingJoints = new List<PhysicsJoint>();
2769 //DoJointErrorMessage(joints_connecting_actor, "taint: " + pendingJoints.Count + " pending joints");
2770 foreach (PhysicsJoint joint in pendingJoints)
2771 {
2772 //DoJointErrorMessage(joint, "taint: time to create joint with parms: " + joint.RawParams);
2773 string[] jointParams = joint.RawParams.Split(" ".ToCharArray(),
2774 System.StringSplitOptions.RemoveEmptyEntries);
2775 List<IntPtr> jointBodies = new List<IntPtr>();
2776 bool allJointBodiesAreReady = true;
2777 foreach (string jointParam in jointParams)
2778 {
2779 if (jointParam == "NULL")
2780 {
2781 //DoJointErrorMessage(joint, "attaching NULL joint to world");
2782 jointBodies.Add(IntPtr.Zero);
2783 }
2784 else
2785 {
2786 //DoJointErrorMessage(joint, "looking for prim name: " + jointParam);
2787 bool foundPrim = false;
2788 lock (_prims)
2789 {
2790 foreach (OdePrim prim in _prims) // FIXME: inefficient
2791 {
2792 if (prim.SOPName == jointParam)
2793 {
2794 //DoJointErrorMessage(joint, "found for prim name: " + jointParam);
2795 if (prim.IsPhysical && prim.Body != IntPtr.Zero)
2796 {
2797 jointBodies.Add(prim.Body);
2798 foundPrim = true;
2799 break;
2800 }
2801 else
2802 {
2803 DoJointErrorMessage(joint, "prim name " + jointParam +
2804 " exists but is not (yet) physical; deferring joint creation. " +
2805 "IsPhysical property is " + prim.IsPhysical +
2806 " and body is " + prim.Body);
2807 foundPrim = false;
2808 break;
2809 }
2810 }
2811 }
2812 }
2813 if (foundPrim)
2814 {
2815 // all is fine
2816 }
2817 else
2818 {
2819 allJointBodiesAreReady = false;
2820 break;
2821 }
2822 }
2823 }
2824 if (allJointBodiesAreReady)
2825 {
2826 //DoJointErrorMessage(joint, "allJointBodiesAreReady for " + joint.ObjectNameInScene + " with parms " + joint.RawParams);
2827 if (jointBodies[0] == jointBodies[1])
2828 {
2829 DoJointErrorMessage(joint, "ERROR: joint cannot be created; the joint bodies are the same, body1==body2. Raw body is " + jointBodies[0] + ". raw parms: " + joint.RawParams);
2830 }
2831 else
2832 {
2833 switch (joint.Type)
2834 {
2835 case PhysicsJointType.Ball:
2836 {
2837 IntPtr odeJoint;
2838 //DoJointErrorMessage(joint, "ODE creating ball joint ");
2839 odeJoint = d.JointCreateBall(world, IntPtr.Zero);
2840 //DoJointErrorMessage(joint, "ODE attaching ball joint: " + odeJoint + " with b1:" + jointBodies[0] + " b2:" + jointBodies[1]);
2841 d.JointAttach(odeJoint, jointBodies[0], jointBodies[1]);
2842 //DoJointErrorMessage(joint, "ODE setting ball anchor: " + odeJoint + " to vec:" + joint.Position);
2843 d.JointSetBallAnchor(odeJoint,
2844 joint.Position.X,
2845 joint.Position.Y,
2846 joint.Position.Z);
2847 //DoJointErrorMessage(joint, "ODE joint setting OK");
2848 //DoJointErrorMessage(joint, "The ball joint's bodies are here: b0: ");
2849 //DoJointErrorMessage(joint, "" + (jointBodies[0] != IntPtr.Zero ? "" + d.BodyGetPosition(jointBodies[0]) : "fixed environment"));
2850 //DoJointErrorMessage(joint, "The ball joint's bodies are here: b1: ");
2851 //DoJointErrorMessage(joint, "" + (jointBodies[1] != IntPtr.Zero ? "" + d.BodyGetPosition(jointBodies[1]) : "fixed environment"));
2852
2853 if (joint is OdePhysicsJoint)
2854 {
2855 ((OdePhysicsJoint)joint).jointID = odeJoint;
2856 }
2857 else
2858 {
2859 DoJointErrorMessage(joint, "WARNING: non-ode joint in ODE!");
2860 }
2861 }
2862 break;
2863 case PhysicsJointType.Hinge:
2864 {
2865 IntPtr odeJoint;
2866 //DoJointErrorMessage(joint, "ODE creating hinge joint ");
2867 odeJoint = d.JointCreateHinge(world, IntPtr.Zero);
2868 //DoJointErrorMessage(joint, "ODE attaching hinge joint: " + odeJoint + " with b1:" + jointBodies[0] + " b2:" + jointBodies[1]);
2869 d.JointAttach(odeJoint, jointBodies[0], jointBodies[1]);
2870 //DoJointErrorMessage(joint, "ODE setting hinge anchor: " + odeJoint + " to vec:" + joint.Position);
2871 d.JointSetHingeAnchor(odeJoint,
2872 joint.Position.X,
2873 joint.Position.Y,
2874 joint.Position.Z);
2875 // We use the orientation of the x-axis of the joint's coordinate frame
2876 // as the axis for the hinge.
2877
2878 // Therefore, we must get the joint's coordinate frame based on the
2879 // joint.Rotation field, which originates from the orientation of the
2880 // joint's proxy object in the scene.
2881
2882 // The joint's coordinate frame is defined as the transformation matrix
2883 // that converts a vector from joint-local coordinates into world coordinates.
2884 // World coordinates are defined as the XYZ coordinate system of the sim,
2885 // as shown in the top status-bar of the viewer.
2886
2887 // Once we have the joint's coordinate frame, we extract its X axis (AtAxis)
2888 // and use that as the hinge axis.
2889
2890 //joint.Rotation.Normalize();
2891 Matrix4 proxyFrame = Matrix4.CreateFromQuaternion(joint.Rotation);
2892
2893 // Now extract the X axis of the joint's coordinate frame.
2894
2895 // Do not try to use proxyFrame.AtAxis or you will become mired in the
2896 // tar pit of transposed, inverted, and generally messed-up orientations.
2897 // (In other words, Matrix4.AtAxis() is borked.)
2898 // Vector3 jointAxis = proxyFrame.AtAxis; <--- this path leadeth to madness
2899
2900 // Instead, compute the X axis of the coordinate frame by transforming
2901 // the (1,0,0) vector. At least that works.
2902
2903 //m_log.Debug("PHY: making axis: complete matrix is " + proxyFrame);
2904 Vector3 jointAxis = Vector3.Transform(Vector3.UnitX, proxyFrame);
2905 //m_log.Debug("PHY: making axis: hinge joint axis is " + jointAxis);
2906 //DoJointErrorMessage(joint, "ODE setting hinge axis: " + odeJoint + " to vec:" + jointAxis);
2907 d.JointSetHingeAxis(odeJoint,
2908 jointAxis.X,
2909 jointAxis.Y,
2910 jointAxis.Z);
2911 //d.JointSetHingeParam(odeJoint, (int)dParam.CFM, 0.1f);
2912 if (joint is OdePhysicsJoint)
2913 {
2914 ((OdePhysicsJoint)joint).jointID = odeJoint;
2915 }
2916 else
2917 {
2918 DoJointErrorMessage(joint, "WARNING: non-ode joint in ODE!");
2919 }
2920 }
2921 break;
2922 }
2923 successfullyProcessedPendingJoints.Add(joint);
2924 }
2925 }
2926 else
2927 {
2928 DoJointErrorMessage(joint, "joint could not yet be created; still pending");
2929 }
2930 }
2931 foreach (PhysicsJoint successfullyProcessedJoint in successfullyProcessedPendingJoints)
2932 {
2933 //DoJointErrorMessage(successfullyProcessedJoint, "finalizing succesfully procsssed joint " + successfullyProcessedJoint.ObjectNameInScene + " parms " + successfullyProcessedJoint.RawParams);
2934 //DoJointErrorMessage(successfullyProcessedJoint, "removing from pending");
2935 InternalRemovePendingJoint(successfullyProcessedJoint);
2936 //DoJointErrorMessage(successfullyProcessedJoint, "adding to active");
2937 InternalAddActiveJoint(successfullyProcessedJoint);
2938 //DoJointErrorMessage(successfullyProcessedJoint, "done");
2939 }
2940 }
2941 } // end SupportsNINJAJoints
2942
2943 if (processedtaints)
2944//Console.WriteLine("Simulate calls Clear of _taintedPrim list");
2945 _taintedPrimH.Clear(); // ??? if this only ???
2946 _taintedPrimL.Clear();
2947 } // end lock _taintedPrimLock
2948
2949 // Move characters
2950 lock (_characters)
2951 {
2952 List<OdeCharacter> defects = new List<OdeCharacter>();
2953 foreach (OdeCharacter actor in _characters)
2954 {
2955 if (actor != null)
2956 actor.Move(ODE_STEPSIZE, defects);
2957 }
2958 if (0 != defects.Count)
2959 {
2960 foreach (OdeCharacter defect in defects)
2961 {
2962 RemoveCharacter(defect);
2963 }
2964 }
2965 } // end lock _characters
2966
2967 // Move other active objects
2968 lock (_activeprims)
2969 {
2970 foreach (OdePrim prim in _activeprims)
2971 {
2972 prim.m_collisionscore = 0;
2973 prim.Move(ODE_STEPSIZE);
2974 }
2975 } // end lock _activeprims
2976
2977 //if ((framecount % m_randomizeWater) == 0)
2978 // randomizeWater(waterlevel);
2979
2980 //int RayCastTimeMS = m_rayCastManager.ProcessQueuedRequests();
2981 m_rayCastManager.ProcessQueuedRequests();
2982
2983 collision_optimized(ODE_STEPSIZE);
2984
2985 lock (_collisionEventPrim)
2986 {
2987 foreach (PhysicsActor obj in _collisionEventPrim)
2988 {
2989 if (obj == null)
2990 continue;
2991
2992 switch ((ActorTypes)obj.PhysicsActorType)
2993 {
2994 case ActorTypes.Agent:
2995 OdeCharacter cobj = (OdeCharacter)obj;
2996 cobj.AddCollisionFrameTime(100);
2997 cobj.SendCollisions();
2998 break;
2999 case ActorTypes.Prim:
3000 OdePrim pobj = (OdePrim)obj;
3001 pobj.SendCollisions();
3002 break;
3003 }
3004 }
3005 } // end lock _collisionEventPrim
3006
3007 //if (m_global_contactcount > 5)
3008 //{
3009 // m_log.DebugFormat("[PHYSICS]: Contacts:{0}", m_global_contactcount);
3010 //}
3011
3012 m_global_contactcount = 0;
3013
3014 d.WorldQuickStep(world, ODE_STEPSIZE);
3015 d.JointGroupEmpty(contactgroup);
3016 fps++;
3017 //ode.dunlock(world);
3018 } // end try
3019 catch (Exception e)
3020 {
3021 m_log.ErrorFormat("[PHYSICS]: {0}, {1}, {2}", e.Message, e.TargetSite, e);
3022 ode.dunlock(world);
3023 }
3024
3025 step_time -= ODE_STEPSIZE;
3026 i++;
3027 //}
3028 //else
3029 //{
3030 //fps = 0;
3031 //}
3032 //}
3033 } // end while (step_time > 0.0f)
3034
3035 lock (_characters)
3036 {
3037 foreach (OdeCharacter actor in _characters)
3038 {
3039 if (actor != null)
3040 {
3041 if (actor.bad)
3042 m_log.WarnFormat("[PHYSICS]: BAD Actor {0} in _characters list was not removed?", actor.m_uuid);
3043 actor.UpdatePositionAndVelocity();
3044 }
3045 }
3046 }
3047
3048 lock (_badCharacter)
3049 {
3050 if (_badCharacter.Count > 0)
3051 {
3052 foreach (OdeCharacter chr in _badCharacter)
3053 {
3054 RemoveCharacter(chr);
3055 }
3056 _badCharacter.Clear();
3057 }
3058 }
3059
3060 lock (_activeprims)
3061 {
3062 //if (timeStep < 0.2f)
3063 {
3064 foreach (OdePrim actor in _activeprims)
3065 {
3066 if (actor.IsPhysical && (d.BodyIsEnabled(actor.Body) || !actor._zeroFlag))
3067 {
3068 actor.UpdatePositionAndVelocity();
3069
3070 if (SupportsNINJAJoints)
3071 {
3072 // If an actor moved, move its joint proxy objects as well.
3073 // There seems to be an event PhysicsActor.OnPositionUpdate that could be used
3074 // for this purpose but it is never called! So we just do the joint
3075 // movement code here.
3076
3077 if (actor.SOPName != null &&
3078 joints_connecting_actor.ContainsKey(actor.SOPName) &&
3079 joints_connecting_actor[actor.SOPName] != null &&
3080 joints_connecting_actor[actor.SOPName].Count > 0)
3081 {
3082 foreach (PhysicsJoint affectedJoint in joints_connecting_actor[actor.SOPName])
3083 {
3084 if (affectedJoint.IsInPhysicsEngine)
3085 {
3086 DoJointMoved(affectedJoint);
3087 }
3088 else
3089 {
3090 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);
3091 }
3092 }
3093 }
3094 }
3095 }
3096 }
3097 }
3098 } // end lock _activeprims
3099
3100 //DumpJointInfo();
3101
3102 // Finished with all sim stepping. If requested, dump world state to file for debugging.
3103 // TODO: This call to the export function is already inside lock (OdeLock) - but is an extra lock needed?
3104 // TODO: This overwrites all dump files in-place. Should this be a growing logfile, or separate snapshots?
3105 if (physics_logging && (physics_logging_interval>0) && (framecount % physics_logging_interval == 0))
3106 {
3107 string fname = "state-" + world.ToString() + ".DIF"; // give each physics world a separate filename
3108 string prefix = "world" + world.ToString(); // prefix for variable names in exported .DIF file
3109
3110 if (physics_logging_append_existing_logfile)
3111 {
3112 string header = "-------------- START OF PHYSICS FRAME " + framecount.ToString() + " --------------";
3113 TextWriter fwriter = File.AppendText(fname);
3114 fwriter.WriteLine(header);
3115 fwriter.Close();
3116 }
3117 d.WorldExportDIF(world, fname, physics_logging_append_existing_logfile, prefix);
3118 }
3119 } // end lock OdeLock
3120
3121 return fps * 1000.0f; //NB This is a FRAME COUNT, not a time! AND is divide by 1000 in SimStatusReporter!
3122 } // end Simulate
3123
3124 public override void GetResults()
3125 {
3126 }
3127
3128 public override bool IsThreaded
3129 {
3130 // for now we won't be multithreaded
3131 get { return (false); }
3132 }
3133
3134 #region ODE Specific Terrain Fixes
3135 public float[] ResizeTerrain512NearestNeighbour(float[] heightMap)
3136 {
3137 float[] returnarr = new float[262144];
3138 float[,] resultarr = new float[(int)WorldExtents.X, (int)WorldExtents.Y];
3139
3140 // Filling out the array into its multi-dimensional components
3141 for (int y = 0; y < WorldExtents.Y; y++)
3142 {
3143 for (int x = 0; x < WorldExtents.X; x++)
3144 {
3145 resultarr[y, x] = heightMap[y * (int)WorldExtents.Y + x];
3146 }
3147 }
3148
3149 // Resize using Nearest Neighbour
3150
3151 // This particular way is quick but it only works on a multiple of the original
3152
3153 // The idea behind this method can be described with the following diagrams
3154 // second pass and third pass happen in the same loop really.. just separated
3155 // them to show what this does.
3156
3157 // First Pass
3158 // ResultArr:
3159 // 1,1,1,1,1,1
3160 // 1,1,1,1,1,1
3161 // 1,1,1,1,1,1
3162 // 1,1,1,1,1,1
3163 // 1,1,1,1,1,1
3164 // 1,1,1,1,1,1
3165
3166 // Second Pass
3167 // ResultArr2:
3168 // 1,,1,,1,,1,,1,,1,
3169 // ,,,,,,,,,,
3170 // 1,,1,,1,,1,,1,,1,
3171 // ,,,,,,,,,,
3172 // 1,,1,,1,,1,,1,,1,
3173 // ,,,,,,,,,,
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 // Third pass fills in the blanks
3181 // ResultArr2:
3182 // 1,1,1,1,1,1,1,1,1,1,1,1
3183 // 1,1,1,1,1,1,1,1,1,1,1,1
3184 // 1,1,1,1,1,1,1,1,1,1,1,1
3185 // 1,1,1,1,1,1,1,1,1,1,1,1
3186 // 1,1,1,1,1,1,1,1,1,1,1,1
3187 // 1,1,1,1,1,1,1,1,1,1,1,1
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
3194 // X,Y = .
3195 // X+1,y = ^
3196 // X,Y+1 = *
3197 // X+1,Y+1 = #
3198
3199 // Filling in like this;
3200 // .*
3201 // ^#
3202 // 1st .
3203 // 2nd *
3204 // 3rd ^
3205 // 4th #
3206 // on single loop.
3207
3208 float[,] resultarr2 = new float[512, 512];
3209 for (int y = 0; y < WorldExtents.Y; y++)
3210 {
3211 for (int x = 0; x < WorldExtents.X; x++)
3212 {
3213 resultarr2[y * 2, x * 2] = resultarr[y, x];
3214
3215 if (y < WorldExtents.Y)
3216 {
3217 resultarr2[(y * 2) + 1, x * 2] = resultarr[y, x];
3218 }
3219 if (x < WorldExtents.X)
3220 {
3221 resultarr2[y * 2, (x * 2) + 1] = resultarr[y, x];
3222 }
3223 if (x < WorldExtents.X && y < WorldExtents.Y)
3224 {
3225 resultarr2[(y * 2) + 1, (x * 2) + 1] = resultarr[y, x];
3226 }
3227 }
3228 }
3229
3230 //Flatten out the array
3231 int i = 0;
3232 for (int y = 0; y < 512; y++)
3233 {
3234 for (int x = 0; x < 512; x++)
3235 {
3236 if (resultarr2[y, x] <= 0)
3237 returnarr[i] = 0.0000001f;
3238 else
3239 returnarr[i] = resultarr2[y, x];
3240
3241 i++;
3242 }
3243 }
3244
3245 return returnarr;
3246 }
3247
3248 public float[] ResizeTerrain512Interpolation(float[] heightMap)
3249 {
3250 float[] returnarr = new float[262144];
3251 float[,] resultarr = new float[512,512];
3252
3253 // Filling out the array into its multi-dimensional components
3254 for (int y = 0; y < 256; y++)
3255 {
3256 for (int x = 0; x < 256; x++)
3257 {
3258 resultarr[y, x] = heightMap[y * 256 + x];
3259 }
3260 }
3261
3262 // Resize using interpolation
3263
3264 // This particular way is quick but it only works on a multiple of the original
3265
3266 // The idea behind this method can be described with the following diagrams
3267 // second pass and third pass happen in the same loop really.. just separated
3268 // them to show what this does.
3269
3270 // First Pass
3271 // ResultArr:
3272 // 1,1,1,1,1,1
3273 // 1,1,1,1,1,1
3274 // 1,1,1,1,1,1
3275 // 1,1,1,1,1,1
3276 // 1,1,1,1,1,1
3277 // 1,1,1,1,1,1
3278
3279 // Second Pass
3280 // ResultArr2:
3281 // 1,,1,,1,,1,,1,,1,
3282 // ,,,,,,,,,,
3283 // 1,,1,,1,,1,,1,,1,
3284 // ,,,,,,,,,,
3285 // 1,,1,,1,,1,,1,,1,
3286 // ,,,,,,,,,,
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 // Third pass fills in the blanks
3294 // ResultArr2:
3295 // 1,1,1,1,1,1,1,1,1,1,1,1
3296 // 1,1,1,1,1,1,1,1,1,1,1,1
3297 // 1,1,1,1,1,1,1,1,1,1,1,1
3298 // 1,1,1,1,1,1,1,1,1,1,1,1
3299 // 1,1,1,1,1,1,1,1,1,1,1,1
3300 // 1,1,1,1,1,1,1,1,1,1,1,1
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
3307 // X,Y = .
3308 // X+1,y = ^
3309 // X,Y+1 = *
3310 // X+1,Y+1 = #
3311
3312 // Filling in like this;
3313 // .*
3314 // ^#
3315 // 1st .
3316 // 2nd *
3317 // 3rd ^
3318 // 4th #
3319 // on single loop.
3320
3321 float[,] resultarr2 = new float[512,512];
3322 for (int y = 0; y < (int)Constants.RegionSize; y++)
3323 {
3324 for (int x = 0; x < (int)Constants.RegionSize; x++)
3325 {
3326 resultarr2[y*2, x*2] = resultarr[y, x];
3327
3328 if (y < (int)Constants.RegionSize)
3329 {
3330 if (y + 1 < (int)Constants.RegionSize)
3331 {
3332 if (x + 1 < (int)Constants.RegionSize)
3333 {
3334 resultarr2[(y*2) + 1, x*2] = ((resultarr[y, x] + resultarr[y + 1, x] +
3335 resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4);
3336 }
3337 else
3338 {
3339 resultarr2[(y*2) + 1, x*2] = ((resultarr[y, x] + resultarr[y + 1, x])/2);
3340 }
3341 }
3342 else
3343 {
3344 resultarr2[(y*2) + 1, x*2] = resultarr[y, x];
3345 }
3346 }
3347 if (x < (int)Constants.RegionSize)
3348 {
3349 if (x + 1 < (int)Constants.RegionSize)
3350 {
3351 if (y + 1 < (int)Constants.RegionSize)
3352 {
3353 resultarr2[y*2, (x*2) + 1] = ((resultarr[y, x] + resultarr[y + 1, x] +
3354 resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4);
3355 }
3356 else
3357 {
3358 resultarr2[y*2, (x*2) + 1] = ((resultarr[y, x] + resultarr[y, x + 1])/2);
3359 }
3360 }
3361 else
3362 {
3363 resultarr2[y*2, (x*2) + 1] = resultarr[y, x];
3364 }
3365 }
3366 if (x < (int)Constants.RegionSize && y < (int)Constants.RegionSize)
3367 {
3368 if ((x + 1 < (int)Constants.RegionSize) && (y + 1 < (int)Constants.RegionSize))
3369 {
3370 resultarr2[(y*2) + 1, (x*2) + 1] = ((resultarr[y, x] + resultarr[y + 1, x] +
3371 resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4);
3372 }
3373 else
3374 {
3375 resultarr2[(y*2) + 1, (x*2) + 1] = resultarr[y, x];
3376 }
3377 }
3378 }
3379 }
3380 //Flatten out the array
3381 int i = 0;
3382 for (int y = 0; y < 512; y++)
3383 {
3384 for (int x = 0; x < 512; x++)
3385 {
3386 if (Single.IsNaN(resultarr2[y, x]) || Single.IsInfinity(resultarr2[y, x]))
3387 {
3388 m_log.Warn("[PHYSICS]: Non finite heightfield element detected. Setting it to 0");
3389 resultarr2[y, x] = 0;
3390 }
3391 returnarr[i] = resultarr2[y, x];
3392 i++;
3393 }
3394 }
3395
3396 return returnarr;
3397 }
3398
3399 #endregion
3400
3401 public override void SetTerrain(float[] heightMap)
3402 {
3403 if (m_worldOffset != Vector3.Zero && m_parentScene != null)
3404 {
3405 if (m_parentScene is OdeScene)
3406 {
3407 ((OdeScene)m_parentScene).SetTerrain(heightMap, m_worldOffset);
3408 }
3409 }
3410 else
3411 {
3412 SetTerrain(heightMap, m_worldOffset);
3413 }
3414 }
3415
3416 public void SetTerrain(float[] heightMap, Vector3 pOffset)
3417 {
3418
3419 uint regionsize = (uint) Constants.RegionSize; // visible region size eg. 256(M)
3420
3421 uint heightmapWidth = regionsize + 1; // ODE map size 257 x 257 (Meters) (1 extra
3422 uint heightmapHeight = regionsize + 1;
3423
3424 uint heightmapWidthSamples = (uint)regionsize + 2; // Sample file size, 258 x 258 samples
3425 uint heightmapHeightSamples = (uint)regionsize + 2;
3426
3427 // Array of height samples for ODE
3428 float[] _heightmap;
3429 _heightmap = new float[(heightmapWidthSamples * heightmapHeightSamples)]; // loaded samples 258 x 258
3430
3431 // Other ODE parameters
3432 const float scale = 1.0f;
3433 const float offset = 0.0f;
3434 const float thickness = 2.0f; // Was 0.2f, Larger appears to prevent Av fall-through
3435 const int wrap = 0;
3436
3437 float hfmin = 2000f;
3438 float hfmax = -2000f;
3439 float minele = 0.0f; // Dont allow -ve heights
3440
3441 uint x = 0;
3442 uint y = 0;
3443 uint xx = 0;
3444 uint yy = 0;
3445
3446 // load the height samples array from the heightMap
3447 for ( x = 0; x < heightmapWidthSamples; x++) // 0 to 257
3448 {
3449 for ( y = 0; y < heightmapHeightSamples; y++) // 0 to 257
3450 {
3451 xx = x - 1;
3452 if (xx < 0) xx = 0;
3453 if (xx > (regionsize - 1)) xx = regionsize - 1;
3454
3455 yy = y - 1;
3456 if (yy < 0) yy = 0;
3457 if (yy > (regionsize - 1)) yy = regionsize - 1;
3458 // Input xx = 0 0 1 2 ..... 254 255 255 256 total in
3459 // Output x = 0 1 2 3 ..... 255 256 257 258 total out
3460 float val= heightMap[(yy * regionsize) + xx]; // input from heightMap, <0-255 * 256> <0-255>
3461 if (val < minele) val = minele;
3462 _heightmap[x * (regionsize + 2) + y] = val; // samples output to _heightmap, <0-257 * 258> <0-257>
3463 hfmin = (val < hfmin) ? val : hfmin;
3464 hfmax = (val > hfmax) ? val : hfmax;
3465 }
3466 }
3467
3468 lock (OdeLock)
3469 {
3470 IntPtr GroundGeom = IntPtr.Zero;
3471 if (RegionTerrain.TryGetValue(pOffset, out GroundGeom))
3472 {
3473 RegionTerrain.Remove(pOffset);
3474 if (GroundGeom != IntPtr.Zero)
3475 {
3476 if (TerrainHeightFieldHeights.ContainsKey(GroundGeom))
3477 {
3478 TerrainHeightFieldHeights.Remove(GroundGeom);
3479 }
3480 d.SpaceRemove(space, GroundGeom);
3481 d.GeomDestroy(GroundGeom);
3482 }
3483 }
3484 IntPtr HeightmapData = d.GeomHeightfieldDataCreate();
3485 d.GeomHeightfieldDataBuildSingle(HeightmapData, _heightmap, 0,
3486 heightmapWidth, heightmapHeight, (int)heightmapWidthSamples,
3487 (int)heightmapHeightSamples, scale, offset, thickness, wrap);
3488 d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1);
3489 GroundGeom = d.CreateHeightfield(space, HeightmapData, 1);
3490 if (GroundGeom != IntPtr.Zero)
3491 {
3492 d.GeomSetCategoryBits(GroundGeom, (int)(CollisionCategories.Land));
3493 d.GeomSetCollideBits(GroundGeom, (int)(CollisionCategories.Space));
3494 }
3495 geom_name_map[GroundGeom] = "Terrain";
3496
3497 d.Matrix3 R = new d.Matrix3();
3498
3499 Quaternion q1 = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 1.5707f);
3500 Quaternion q2 = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), 1.5707f);
3501 //Axiom.Math.Quaternion q3 = Axiom.Math.Quaternion.FromAngleAxis(3.14f, new Axiom.Math.Vector3(0, 0, 1));
3502
3503 q1 = q1 * q2;
3504 //q1 = q1 * q3;
3505 Vector3 v3;
3506 float angle;
3507 q1.GetAxisAngle(out v3, out angle);
3508
3509 d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle);
3510 d.GeomSetRotation(GroundGeom, ref R);
3511 d.GeomSetPosition(GroundGeom, (pOffset.X + (regionsize * 0.5f)) - 0.5f, (pOffset.Y + (regionsize * 0.5f)) - 0.5f, 0);
3512 IntPtr testGround = IntPtr.Zero;
3513 if (RegionTerrain.TryGetValue(pOffset, out testGround))
3514 {
3515 RegionTerrain.Remove(pOffset);
3516 }
3517 RegionTerrain.Add(pOffset, GroundGeom, GroundGeom);
3518 TerrainHeightFieldHeights.Add(GroundGeom,_heightmap);
3519 }
3520 }
3521
3522 public override void DeleteTerrain()
3523 {
3524 }
3525
3526 public float GetWaterLevel()
3527 {
3528 return waterlevel;
3529 }
3530
3531 public override bool SupportsCombining()
3532 {
3533 return true;
3534 }
3535
3536 public override void UnCombine(PhysicsScene pScene)
3537 {
3538 IntPtr localGround = IntPtr.Zero;
3539// float[] localHeightfield;
3540 bool proceed = false;
3541 List<IntPtr> geomDestroyList = new List<IntPtr>();
3542
3543 lock (OdeLock)
3544 {
3545 if (RegionTerrain.TryGetValue(Vector3.Zero, out localGround))
3546 {
3547 foreach (IntPtr geom in TerrainHeightFieldHeights.Keys)
3548 {
3549 if (geom == localGround)
3550 {
3551// localHeightfield = TerrainHeightFieldHeights[geom];
3552 proceed = true;
3553 }
3554 else
3555 {
3556 geomDestroyList.Add(geom);
3557 }
3558 }
3559
3560 if (proceed)
3561 {
3562 m_worldOffset = Vector3.Zero;
3563 WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize);
3564 m_parentScene = null;
3565
3566 foreach (IntPtr g in geomDestroyList)
3567 {
3568 // removingHeightField needs to be done or the garbage collector will
3569 // collect the terrain data before we tell ODE to destroy it causing
3570 // memory corruption
3571 if (TerrainHeightFieldHeights.ContainsKey(g))
3572 {
3573// float[] removingHeightField = TerrainHeightFieldHeights[g];
3574 TerrainHeightFieldHeights.Remove(g);
3575
3576 if (RegionTerrain.ContainsKey(g))
3577 {
3578 RegionTerrain.Remove(g);
3579 }
3580
3581 d.GeomDestroy(g);
3582 //removingHeightField = new float[0];
3583 }
3584 }
3585
3586 }
3587 else
3588 {
3589 m_log.Warn("[PHYSICS]: Couldn't proceed with UnCombine. Region has inconsistant data.");
3590
3591 }
3592 }
3593 }
3594 }
3595
3596 public override void SetWaterLevel(float baseheight)
3597 {
3598 waterlevel = baseheight;
3599 randomizeWater(waterlevel);
3600 }
3601
3602 public void randomizeWater(float baseheight)
3603 {
3604 const uint heightmapWidth = m_regionWidth + 2;
3605 const uint heightmapHeight = m_regionHeight + 2;
3606 const uint heightmapWidthSamples = m_regionWidth + 2;
3607 const uint heightmapHeightSamples = m_regionHeight + 2;
3608 const float scale = 1.0f;
3609 const float offset = 0.0f;
3610 const float thickness = 2.9f;
3611 const int wrap = 0;
3612
3613 for (int i = 0; i < (258 * 258); i++)
3614 {
3615 _watermap[i] = (baseheight-0.1f) + ((float)fluidRandomizer.Next(1,9) / 10f);
3616 // m_log.Info((baseheight - 0.1f) + ((float)fluidRandomizer.Next(1, 9) / 10f));
3617 }
3618
3619 lock (OdeLock)
3620 {
3621 if (WaterGeom != IntPtr.Zero)
3622 {
3623 d.SpaceRemove(space, WaterGeom);
3624 }
3625 IntPtr HeightmapData = d.GeomHeightfieldDataCreate();
3626 d.GeomHeightfieldDataBuildSingle(HeightmapData, _watermap, 0, heightmapWidth, heightmapHeight,
3627 (int)heightmapWidthSamples, (int)heightmapHeightSamples, scale,
3628 offset, thickness, wrap);
3629 d.GeomHeightfieldDataSetBounds(HeightmapData, m_regionWidth, m_regionHeight);
3630 WaterGeom = d.CreateHeightfield(space, HeightmapData, 1);
3631 if (WaterGeom != IntPtr.Zero)
3632 {
3633 d.GeomSetCategoryBits(WaterGeom, (int)(CollisionCategories.Water));
3634 d.GeomSetCollideBits(WaterGeom, (int)(CollisionCategories.Space));
3635
3636 }
3637 geom_name_map[WaterGeom] = "Water";
3638
3639 d.Matrix3 R = new d.Matrix3();
3640
3641 Quaternion q1 = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 1.5707f);
3642 Quaternion q2 = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), 1.5707f);
3643 //Axiom.Math.Quaternion q3 = Axiom.Math.Quaternion.FromAngleAxis(3.14f, new Axiom.Math.Vector3(0, 0, 1));
3644
3645 q1 = q1 * q2;
3646 //q1 = q1 * q3;
3647 Vector3 v3;
3648 float angle;
3649 q1.GetAxisAngle(out v3, out angle);
3650
3651 d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle);
3652 d.GeomSetRotation(WaterGeom, ref R);
3653 d.GeomSetPosition(WaterGeom, 128, 128, 0);
3654
3655 }
3656
3657 }
3658
3659 public override void Dispose()
3660 {
3661 m_rayCastManager.Dispose();
3662 m_rayCastManager = null;
3663
3664 lock (OdeLock)
3665 {
3666 lock (_prims)
3667 {
3668 foreach (OdePrim prm in _prims)
3669 {
3670 RemovePrim(prm);
3671 }
3672 }
3673
3674 //foreach (OdeCharacter act in _characters)
3675 //{
3676 //RemoveAvatar(act);
3677 //}
3678 d.WorldDestroy(world);
3679 //d.CloseODE();
3680 }
3681 }
3682 public override Dictionary<uint, float> GetTopColliders()
3683 {
3684 Dictionary<uint, float> returncolliders = new Dictionary<uint, float>();
3685 int cnt = 0;
3686 lock (_prims)
3687 {
3688 foreach (OdePrim prm in _prims)
3689 {
3690 if (prm.CollisionScore > 0)
3691 {
3692 returncolliders.Add(prm.m_localID, prm.CollisionScore);
3693 cnt++;
3694 prm.CollisionScore = 0f;
3695 if (cnt > 25)
3696 {
3697 break;
3698 }
3699 }
3700 }
3701 }
3702 return returncolliders;
3703 }
3704
3705 public override bool SupportsRayCast()
3706 {
3707 return true;
3708 }
3709
3710 public override void RaycastWorld(Vector3 position, Vector3 direction, float length, RaycastCallback retMethod)
3711 {
3712 if (retMethod != null)
3713 {
3714 m_rayCastManager.QueueRequest(position, direction, length, retMethod);
3715 }
3716 }
3717
3718#if USE_DRAWSTUFF
3719 // Keyboard callback
3720 public void command(int cmd)
3721 {
3722 IntPtr geom;
3723 d.Mass mass;
3724 d.Vector3 sides = new d.Vector3(d.RandReal() * 0.5f + 0.1f, d.RandReal() * 0.5f + 0.1f, d.RandReal() * 0.5f + 0.1f);
3725
3726
3727
3728 Char ch = Char.ToLower((Char)cmd);
3729 switch ((Char)ch)
3730 {
3731 case 'w':
3732 try
3733 {
3734 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));
3735
3736 xyz.X += rotate.X; xyz.Y += rotate.Y; xyz.Z += rotate.Z;
3737 ds.SetViewpoint(ref xyz, ref hpr);
3738 }
3739 catch (ArgumentException)
3740 { hpr.X = 0; }
3741 break;
3742
3743 case 'a':
3744 hpr.X++;
3745 ds.SetViewpoint(ref xyz, ref hpr);
3746 break;
3747
3748 case 's':
3749 try
3750 {
3751 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));
3752
3753 xyz.X += rotate2.X; xyz.Y += rotate2.Y; xyz.Z += rotate2.Z;
3754 ds.SetViewpoint(ref xyz, ref hpr);
3755 }
3756 catch (ArgumentException)
3757 { hpr.X = 0; }
3758 break;
3759 case 'd':
3760 hpr.X--;
3761 ds.SetViewpoint(ref xyz, ref hpr);
3762 break;
3763 case 'r':
3764 xyz.Z++;
3765 ds.SetViewpoint(ref xyz, ref hpr);
3766 break;
3767 case 'f':
3768 xyz.Z--;
3769 ds.SetViewpoint(ref xyz, ref hpr);
3770 break;
3771 case 'e':
3772 xyz.Y++;
3773 ds.SetViewpoint(ref xyz, ref hpr);
3774 break;
3775 case 'q':
3776 xyz.Y--;
3777 ds.SetViewpoint(ref xyz, ref hpr);
3778 break;
3779 }
3780 }
3781
3782 public void step(int pause)
3783 {
3784
3785 ds.SetColor(1.0f, 1.0f, 0.0f);
3786 ds.SetTexture(ds.Texture.Wood);
3787 lock (_prims)
3788 {
3789 foreach (OdePrim prm in _prims)
3790 {
3791 //IntPtr body = d.GeomGetBody(prm.prim_geom);
3792 if (prm.prim_geom != IntPtr.Zero)
3793 {
3794 d.Vector3 pos;
3795 d.GeomCopyPosition(prm.prim_geom, out pos);
3796 //d.BodyCopyPosition(body, out pos);
3797
3798 d.Matrix3 R;
3799 d.GeomCopyRotation(prm.prim_geom, out R);
3800 //d.BodyCopyRotation(body, out R);
3801
3802
3803 d.Vector3 sides = new d.Vector3();
3804 sides.X = prm.Size.X;
3805 sides.Y = prm.Size.Y;
3806 sides.Z = prm.Size.Z;
3807
3808 ds.DrawBox(ref pos, ref R, ref sides);
3809 }
3810 }
3811 }
3812 ds.SetColor(1.0f, 0.0f, 0.0f);
3813 lock (_characters)
3814 {
3815 foreach (OdeCharacter chr in _characters)
3816 {
3817 if (chr.Shell != IntPtr.Zero)
3818 {
3819 IntPtr body = d.GeomGetBody(chr.Shell);
3820
3821 d.Vector3 pos;
3822 d.GeomCopyPosition(chr.Shell, out pos);
3823 //d.BodyCopyPosition(body, out pos);
3824
3825 d.Matrix3 R;
3826 d.GeomCopyRotation(chr.Shell, out R);
3827 //d.BodyCopyRotation(body, out R);
3828
3829 ds.DrawCapsule(ref pos, ref R, chr.Size.Z, 0.35f);
3830 d.Vector3 sides = new d.Vector3();
3831 sides.X = 0.5f;
3832 sides.Y = 0.5f;
3833 sides.Z = 0.5f;
3834
3835 ds.DrawBox(ref pos, ref R, ref sides);
3836 }
3837 }
3838 }
3839 }
3840
3841 public void start(int unused)
3842 {
3843 ds.SetViewpoint(ref xyz, ref hpr);
3844 }
3845#endif
3846 }
3847}
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 6b74e74..0e7dd81 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
@@ -1215,7 +1215,6 @@ namespace OpenSim.Region.Physics.OdePlugin
1215 1215
1216 public override float APIDDamping{ set { return; } } 1216 public override float APIDDamping{ set { return; } }
1217 1217
1218
1219 public override void SubscribeEvents(int ms) 1218 public override void SubscribeEvents(int ms)
1220 { 1219 {
1221 m_requestedUpdateFrequency = ms; 1220 m_requestedUpdateFrequency = ms;
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
index c91658e..243e2d7 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
@@ -572,8 +572,8 @@ namespace OpenSim.Region.Physics.OdePlugin
572 break; 572 break;
573 573
574 case HollowShape.Circle: 574 case HollowShape.Circle:
575 // Hollow shape is a perfect cyllinder in respect to the cube's scale 575 // Hollow shape is a perfect cylinder in respect to the cube's scale
576 // Cyllinder hollow volume calculation 576 // Cylinder hollow volume calculation
577 577
578 hollowVolume *= 0.1963495f * 3.07920140172638f; 578 hollowVolume *= 0.1963495f * 3.07920140172638f;
579 break; 579 break;
@@ -2819,7 +2819,7 @@ Console.WriteLine(" JointCreateFixed");
2819 } 2819 }
2820 public override bool PIDActive { set { m_usePID = value; } } 2820 public override bool PIDActive { set { m_usePID = value; } }
2821 public override float PIDTau { set { m_PIDTau = value; } } 2821 public override float PIDTau { set { m_PIDTau = value; } }
2822 2822
2823 public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } } 2823 public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } }
2824 public override bool PIDHoverActive { set { m_useHoverPID = value; } } 2824 public override bool PIDHoverActive { set { m_useHoverPID = value; } }
2825 public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } } 2825 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 4a24c7d..3edc3a2 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/AsyncCommandManager.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
index ee32755..61e4934 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
@@ -248,6 +248,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
248 248
249 } 249 }
250 250
251 public static void StateChange(IScriptEngine engine, uint localID, UUID itemID)
252 {
253 // Remove a specific script
254
255 // Remove dataserver events
256 m_Dataserver[engine].RemoveEvents(localID, itemID);
257
258 IWorldComm comms = engine.World.RequestModuleInterface<IWorldComm>();
259 if (comms != null)
260 comms.DeleteListener(itemID);
261
262 IXMLRPC xmlrpc = engine.World.RequestModuleInterface<IXMLRPC>();
263 xmlrpc.DeleteChannels(itemID);
264 xmlrpc.CancelSRDRequests(itemID);
265
266 // Remove Sensors
267 m_SensorRepeat[engine].UnSetSenseRepeaterEvents(localID, itemID);
268
269 }
270
251 public static Object[] GetSerializationData(IScriptEngine engine, UUID itemID) 271 public static Object[] GetSerializationData(IScriptEngine engine, UUID itemID)
252 { 272 {
253 List<Object> data = new List<Object>(); 273 List<Object> data = new List<Object>();
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs
new file mode 100644
index 0000000..489c1c6
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs
@@ -0,0 +1,118 @@
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.Reflection;
30using System.Collections;
31using System.Collections.Generic;
32using System.Runtime.Remoting.Lifetime;
33using OpenMetaverse;
34using Nini.Config;
35using OpenSim;
36using OpenSim.Framework;
37using OpenSim.Region.CoreModules.World.LightShare;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Region.ScriptEngine.Shared;
41using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
42using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
43using OpenSim.Region.ScriptEngine.Interfaces;
44using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces;
45using OpenSim.Services.Interfaces;
46
47using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
48using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
49using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
50using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
51using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
52using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
53using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
54
55namespace OpenSim.Region.ScriptEngine.Shared.Api
56{
57 [Serializable]
58 public class CM_Api : MarshalByRefObject, ICM_Api, IScriptApi
59 {
60 internal IScriptEngine m_ScriptEngine;
61 internal SceneObjectPart m_host;
62 internal uint m_localID;
63 internal UUID m_itemID;
64 internal bool m_CMFunctionsEnabled = false;
65
66 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID)
67 {
68 m_ScriptEngine = ScriptEngine;
69 m_host = host;
70 m_localID = localID;
71 m_itemID = itemID;
72
73 if (m_ScriptEngine.Config.GetBoolean("AllowCareminsterFunctions", false))
74 m_CMFunctionsEnabled = true;
75 }
76
77 public override Object InitializeLifetimeService()
78 {
79 ILease lease = (ILease)base.InitializeLifetimeService();
80
81 if (lease.CurrentState == LeaseState.Initial)
82 {
83 lease.InitialLeaseTime = TimeSpan.FromMinutes(0);
84 // lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0);
85 // lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0);
86 }
87 return lease;
88 }
89
90 public Scene World
91 {
92 get { return m_ScriptEngine.World; }
93 }
94
95 public string cmDetectedCountry(int number)
96 {
97 m_host.AddScriptLPS(1);
98 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, number);
99 if (detectedParams == null)
100 return String.Empty;
101 return detectedParams.Country;
102 }
103
104 public string cmGetAgentCountry(LSL_Key key)
105 {
106 if (!World.Permissions.IsGod(m_host.OwnerID))
107 return String.Empty;
108
109 UUID uuid;
110
111 if (!UUID.TryParse(key, out uuid))
112 return String.Empty;
113
114 UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
115 return account.UserCountry;
116 }
117 }
118}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index ce7d97c..3f48080 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -28,10 +28,12 @@
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;
34using System.Text.RegularExpressions; 35using System.Text.RegularExpressions;
36using System.Timers;
35using Nini.Config; 37using Nini.Config;
36using log4net; 38using log4net;
37using OpenMetaverse; 39using OpenMetaverse;
@@ -44,6 +46,7 @@ using OpenSim.Region.CoreModules.World.Land;
44using OpenSim.Region.CoreModules.World.Terrain; 46using OpenSim.Region.CoreModules.World.Terrain;
45using OpenSim.Region.Framework.Interfaces; 47using OpenSim.Region.Framework.Interfaces;
46using OpenSim.Region.Framework.Scenes; 48using OpenSim.Region.Framework.Scenes;
49using OpenSim.Region.Framework.Scenes.Serialization;
47using OpenSim.Region.Framework.Scenes.Animation; 50using OpenSim.Region.Framework.Scenes.Animation;
48using OpenSim.Region.Physics.Manager; 51using OpenSim.Region.Physics.Manager;
49using OpenSim.Region.ScriptEngine.Shared; 52using OpenSim.Region.ScriptEngine.Shared;
@@ -65,6 +68,7 @@ using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
65using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; 68using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
66using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; 69using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
67using System.Reflection; 70using System.Reflection;
71using Timer = System.Timers.Timer;
68 72
69namespace OpenSim.Region.ScriptEngine.Shared.Api 73namespace OpenSim.Region.ScriptEngine.Shared.Api
70{ 74{
@@ -81,7 +85,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
81 /// </summary> 85 /// </summary>
82 public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi 86 public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi
83 { 87 {
84 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 88// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
85 protected IScriptEngine m_ScriptEngine; 89 protected IScriptEngine m_ScriptEngine;
86 protected SceneObjectPart m_host; 90 protected SceneObjectPart m_host;
87 protected uint m_localID; 91 protected uint m_localID;
@@ -99,16 +103,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
99 protected int m_notecardLineReadCharsMax = 255; 103 protected int m_notecardLineReadCharsMax = 255;
100 protected int m_scriptConsoleChannel = 0; 104 protected int m_scriptConsoleChannel = 0;
101 protected bool m_scriptConsoleChannelEnabled = false; 105 protected bool m_scriptConsoleChannelEnabled = false;
106 protected bool m_debuggerSafe = false;
102 protected IUrlModule m_UrlModule = null; 107 protected IUrlModule m_UrlModule = null;
103 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = 108 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache =
104 new Dictionary<UUID, UserInfoCacheEntry>(); 109 new Dictionary<UUID, UserInfoCacheEntry>();
105 110
111 protected Timer m_ShoutSayTimer;
112 protected int m_SayShoutCount = 0;
113
106 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) 114 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID)
107 { 115 {
116 m_ShoutSayTimer = new Timer(1000);
117 m_ShoutSayTimer.Elapsed += SayShoutTimerElapsed;
118 m_ShoutSayTimer.AutoReset = true;
119 m_ShoutSayTimer.Start();
120
108 m_ScriptEngine = ScriptEngine; 121 m_ScriptEngine = ScriptEngine;
109 m_host = host; 122 m_host = host;
110 m_localID = localID; 123 m_localID = localID;
111 m_itemID = itemID; 124 m_itemID = itemID;
125 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
112 126
113 m_ScriptDelayFactor = 127 m_ScriptDelayFactor =
114 m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f); 128 m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f);
@@ -161,6 +175,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
161 get { return m_ScriptEngine.World; } 175 get { return m_ScriptEngine.World; }
162 } 176 }
163 177
178 [DebuggerNonUserCode]
164 public void state(string newState) 179 public void state(string newState)
165 { 180 {
166 m_ScriptEngine.SetState(m_itemID, newState); 181 m_ScriptEngine.SetState(m_itemID, newState);
@@ -170,6 +185,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
170 /// Reset the named script. The script must be present 185 /// Reset the named script. The script must be present
171 /// in the same prim. 186 /// in the same prim.
172 /// </summary> 187 /// </summary>
188 [DebuggerNonUserCode]
173 public void llResetScript() 189 public void llResetScript()
174 { 190 {
175 m_host.AddScriptLPS(1); 191 m_host.AddScriptLPS(1);
@@ -226,9 +242,62 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
226 } 242 }
227 } 243 }
228 244
245 public List<ScenePresence> GetLinkAvatars(int linkType)
246 {
247 List<ScenePresence> ret = new List<ScenePresence>();
248 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
249 return ret;
250
251 List<ScenePresence> avs = m_host.ParentGroup.GetLinkedAvatars();
252
253 switch (linkType)
254 {
255 case ScriptBaseClass.LINK_SET:
256 return avs;
257
258 case ScriptBaseClass.LINK_ROOT:
259 return ret;
260
261 case ScriptBaseClass.LINK_ALL_OTHERS:
262 return avs;
263
264 case ScriptBaseClass.LINK_ALL_CHILDREN:
265 return avs;
266
267 case ScriptBaseClass.LINK_THIS:
268 return ret;
269
270 default:
271 if (linkType < 0)
272 return ret;
273
274 int partCount = m_host.ParentGroup.GetPartCount();
275
276 if (linkType <= partCount)
277 {
278 return ret;
279 }
280 else
281 {
282 linkType = linkType - partCount;
283 if (linkType > avs.Count)
284 {
285 return ret;
286 }
287 else
288 {
289 ret.Add(avs[linkType-1]);
290 return ret;
291 }
292 }
293 }
294 }
295
229 public List<SceneObjectPart> GetLinkParts(int linkType) 296 public List<SceneObjectPart> GetLinkParts(int linkType)
230 { 297 {
231 List<SceneObjectPart> ret = new List<SceneObjectPart>(); 298 List<SceneObjectPart> ret = new List<SceneObjectPart>();
299 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
300 return ret;
232 ret.Add(m_host); 301 ret.Add(m_host);
233 302
234 switch (linkType) 303 switch (linkType)
@@ -288,40 +357,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
288 protected UUID InventorySelf() 357 protected UUID InventorySelf()
289 { 358 {
290 UUID invItemID = new UUID(); 359 UUID invItemID = new UUID();
291 360 bool unlock = false;
292 lock (m_host.TaskInventory) 361 if (!m_host.TaskInventory.IsReadLockedByMe())
293 { 362 {
294 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 363 m_host.TaskInventory.LockItemsForRead(true);
364 unlock = true;
365 }
366 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
367 {
368 if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID)
295 { 369 {
296 if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID) 370 invItemID = inv.Key;
297 { 371 break;
298 invItemID = inv.Key;
299 break;
300 }
301 } 372 }
302 } 373 }
303 374 if (unlock)
375 {
376 m_host.TaskInventory.LockItemsForRead(false);
377 }
304 return invItemID; 378 return invItemID;
305 } 379 }
306 380
307 protected UUID InventoryKey(string name, int type) 381 protected UUID InventoryKey(string name, int type)
308 { 382 {
309 m_host.AddScriptLPS(1); 383 m_host.AddScriptLPS(1);
310 384 m_host.TaskInventory.LockItemsForRead(true);
311 lock (m_host.TaskInventory) 385
386 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
312 { 387 {
313 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 388 if (inv.Value.Name == name)
314 { 389 {
315 if (inv.Value.Name == name) 390 m_host.TaskInventory.LockItemsForRead(false);
391
392 if (inv.Value.Type != type)
316 { 393 {
317 if (inv.Value.Type != type) 394 return UUID.Zero;
318 return UUID.Zero;
319
320 return inv.Value.AssetID;
321 } 395 }
396
397 return inv.Value.AssetID;
322 } 398 }
323 } 399 }
324 400
401 m_host.TaskInventory.LockItemsForRead(false);
325 return UUID.Zero; 402 return UUID.Zero;
326 } 403 }
327 404
@@ -329,17 +406,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
329 { 406 {
330 m_host.AddScriptLPS(1); 407 m_host.AddScriptLPS(1);
331 408
332 lock (m_host.TaskInventory) 409
410 m_host.TaskInventory.LockItemsForRead(true);
411
412 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
333 { 413 {
334 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 414 if (inv.Value.Name == name)
335 { 415 {
336 if (inv.Value.Name == name) 416 m_host.TaskInventory.LockItemsForRead(false);
337 { 417 return inv.Value.AssetID;
338 return inv.Value.AssetID;
339 }
340 } 418 }
341 } 419 }
342 420
421 m_host.TaskInventory.LockItemsForRead(false);
422
423
343 return UUID.Zero; 424 return UUID.Zero;
344 } 425 }
345 426
@@ -481,26 +562,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
481 562
482 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke 563 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
483 564
484 // Old implementation of llRot2Euler. Normalization not required as Atan2 function will 565 // Utility function for llRot2Euler
485 // only return values >= -PI (-180 degrees) and <= PI (180 degrees). 566
567 // normalize an angle between -PI and PI (-180 to +180 degrees)
568 protected double NormalizeAngle(double angle)
569 {
570 if (angle > -Math.PI && angle < Math.PI)
571 return angle;
572
573 int numPis = (int)(Math.PI / angle);
574 double remainder = angle - Math.PI * numPis;
575 if (numPis % 2 == 1)
576 return Math.PI - angle;
577 return remainder;
578 }
486 579
487 public LSL_Vector llRot2Euler(LSL_Rotation r) 580 public LSL_Vector llRot2Euler(LSL_Rotation q1)
488 { 581 {
489 m_host.AddScriptLPS(1); 582 m_host.AddScriptLPS(1);
490 //This implementation is from http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions. ckrinke 583 LSL_Vector eul = new LSL_Vector();
491 LSL_Rotation t = new LSL_Rotation(r.x * r.x, r.y * r.y, r.z * r.z, r.s * r.s); 584
492 double m = (t.x + t.y + t.z + t.s); 585 double sqw = q1.s*q1.s;
493 if (m == 0) return new LSL_Vector(); 586 double sqx = q1.x*q1.x;
494 double n = 2 * (r.y * r.s + r.x * r.z); 587 double sqy = q1.z*q1.z;
495 double p = m * m - n * n; 588 double sqz = q1.y*q1.y;
496 if (p > 0) 589 double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
497 return new LSL_Vector(Math.Atan2(2.0 * (r.x * r.s - r.y * r.z), (-t.x - t.y + t.z + t.s)), 590 double test = q1.x*q1.z + q1.y*q1.s;
498 Math.Atan2(n, Math.Sqrt(p)), 591 if (test > 0.4999*unit) { // singularity at north pole
499 Math.Atan2(2.0 * (r.z * r.s - r.x * r.y), (t.x - t.y - t.z + t.s))); 592 eul.z = 2 * Math.Atan2(q1.x,q1.s);
500 else if (n > 0) 593 eul.y = Math.PI/2;
501 return new LSL_Vector(0.0, Math.PI * 0.5, Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)); 594 eul.x = 0;
502 else 595 return eul;
503 return new LSL_Vector(0.0, -Math.PI * 0.5, Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)); 596 }
597 if (test < -0.4999*unit) { // singularity at south pole
598 eul.z = -2 * Math.Atan2(q1.x,q1.s);
599 eul.y = -Math.PI/2;
600 eul.x = 0;
601 return eul;
602 }
603 eul.z = Math.Atan2(2*q1.z*q1.s-2*q1.x*q1.y , sqx - sqy - sqz + sqw);
604 eul.y = Math.Asin(2*test/unit);
605 eul.x = Math.Atan2(2*q1.x*q1.s-2*q1.z*q1.y , -sqx + sqy - sqz + sqw);
606 return eul;
504 } 607 }
505 608
506 /* From wiki: 609 /* From wiki:
@@ -702,77 +805,76 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
702 { 805 {
703 //A and B should both be normalized 806 //A and B should both be normalized
704 m_host.AddScriptLPS(1); 807 m_host.AddScriptLPS(1);
705 LSL_Rotation rotBetween; 808 /* This method is more accurate than the SL one, and thus causes problems
706 // Check for zero vectors. If either is zero, return zero rotation. Otherwise, 809 for scripts that deal with the SL inaccuracy around 180-degrees -.- .._.
707 // continue calculation. 810
708 if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f)) 811 double dotProduct = LSL_Vector.Dot(a, b);
812 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
813 double magProduct = LSL_Vector.Mag(a) * LSL_Vector.Mag(b);
814 double angle = Math.Acos(dotProduct / magProduct);
815 LSL_Vector axis = LSL_Vector.Norm(crossProduct);
816 double s = Math.Sin(angle / 2);
817
818 double x = axis.x * s;
819 double y = axis.y * s;
820 double z = axis.z * s;
821 double w = Math.Cos(angle / 2);
822
823 if (Double.IsNaN(x) || Double.IsNaN(y) || Double.IsNaN(z) || Double.IsNaN(w))
824 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
825
826 return new LSL_Rotation((float)x, (float)y, (float)z, (float)w);
827 */
828
829 // This method mimics the 180 errors found in SL
830 // See www.euclideanspace.com... angleBetween
831 LSL_Vector vec_a = a;
832 LSL_Vector vec_b = b;
833
834 // Eliminate zero length
835 LSL_Float vec_a_mag = LSL_Vector.Mag(vec_a);
836 LSL_Float vec_b_mag = LSL_Vector.Mag(vec_b);
837 if (vec_a_mag < 0.00001 ||
838 vec_b_mag < 0.00001)
709 { 839 {
710 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); 840 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
711 } 841 }
712 else 842
843 // Normalize
844 vec_a = llVecNorm(vec_a);
845 vec_b = llVecNorm(vec_b);
846
847 // Calculate axis and rotation angle
848 LSL_Vector axis = vec_a % vec_b;
849 LSL_Float cos_theta = vec_a * vec_b;
850
851 // Check if parallel
852 if (cos_theta > 0.99999)
713 { 853 {
714 a = LSL_Vector.Norm(a); 854 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
715 b = LSL_Vector.Norm(b); 855 }
716 double dotProduct = LSL_Vector.Dot(a, b); 856
717 // There are two degenerate cases possible. These are for vectors 180 or 857 // Check if anti-parallel
718 // 0 degrees apart. These have to be detected and handled individually. 858 else if (cos_theta < -0.99999)
719 // 859 {
720 // Check for vectors 180 degrees apart. 860 LSL_Vector orthog_axis = new LSL_Vector(1.0, 0.0, 0.0) - (vec_a.x / (vec_a * vec_a) * vec_a);
721 // A dot product of -1 would mean the angle between vectors is 180 degrees. 861 if (LSL_Vector.Mag(orthog_axis) < 0.000001) orthog_axis = new LSL_Vector(0.0, 0.0, 1.0);
722 if (dotProduct < -0.9999999f) 862 return new LSL_Rotation((float)orthog_axis.x, (float)orthog_axis.y, (float)orthog_axis.z, 0.0);
723 { 863 }
724 // First assume X axis is orthogonal to the vectors. 864 else // other rotation
725 LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f); 865 {
726 orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a)); 866 LSL_Float theta = (LSL_Float)Math.Acos(cos_theta) * 0.5f;
727 // Check for near zero vector. A very small non-zero number here will create 867 axis = llVecNorm(axis);
728 // a rotation in an undesired direction. 868 double x, y, z, s, t;
729 if (LSL_Vector.Mag(orthoVector) > 0.0001) 869 s = Math.Cos(theta);
730 { 870 t = Math.Sin(theta);
731 rotBetween = new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f); 871 x = axis.x * t;
732 } 872 y = axis.y * t;
733 // If the magnitude of the vector was near zero, then assume the X axis is not 873 z = axis.z * t;
734 // orthogonal and use the Z axis instead. 874 return new LSL_Rotation(x,y,z,s);
735 else
736 {
737 // Set 180 z rotation.
738 rotBetween = new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f);
739 }
740 }
741 // Check for parallel vectors.
742 // A dot product of 1 would mean the angle between vectors is 0 degrees.
743 else if (dotProduct > 0.9999999f)
744 {
745 // Set zero rotation.
746 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
747 }
748 else
749 {
750 // All special checks have been performed so get the axis of rotation.
751 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
752 // Quarternion s value is the length of the unit vector + dot product.
753 double qs = 1.0 + dotProduct;
754 rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs);
755 // Normalize the rotation.
756 double mag = LSL_Rotation.Mag(rotBetween);
757 // We shouldn't have to worry about a divide by zero here. The qs value will be
758 // non-zero because we already know if we're here, then the dotProduct is not -1 so
759 // qs will not be zero. Also, we've already handled the input vectors being zero so the
760 // crossProduct vector should also not be zero.
761 rotBetween.x = rotBetween.x / mag;
762 rotBetween.y = rotBetween.y / mag;
763 rotBetween.z = rotBetween.z / mag;
764 rotBetween.s = rotBetween.s / mag;
765 // Check for undefined values and set zero rotation if any found. This code might not actually be required
766 // any longer since zero vectors are checked for at the top.
767 if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) || Double.IsNaN(rotBetween.s))
768 {
769 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
770 }
771 }
772 } 875 }
773 return rotBetween;
774 } 876 }
775 877
776 public void llWhisper(int channelID, string text) 878 public void llWhisper(int channelID, string text)
777 { 879 {
778 m_host.AddScriptLPS(1); 880 m_host.AddScriptLPS(1);
@@ -792,6 +894,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
792 { 894 {
793 m_host.AddScriptLPS(1); 895 m_host.AddScriptLPS(1);
794 896
897 if (channelID == 0)
898 m_SayShoutCount++;
899
900 if (m_SayShoutCount >= 11)
901 ScriptSleep(2000);
902
795 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel)) 903 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel))
796 { 904 {
797 Console.WriteLine(text); 905 Console.WriteLine(text);
@@ -814,6 +922,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
814 { 922 {
815 m_host.AddScriptLPS(1); 923 m_host.AddScriptLPS(1);
816 924
925 if (channelID == 0)
926 m_SayShoutCount++;
927
928 if (m_SayShoutCount >= 11)
929 ScriptSleep(2000);
930
817 if (text.Length > 1023) 931 if (text.Length > 1023)
818 text = text.Substring(0, 1023); 932 text = text.Substring(0, 1023);
819 933
@@ -1096,10 +1210,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1096 return detectedParams.TouchUV; 1210 return detectedParams.TouchUV;
1097 } 1211 }
1098 1212
1213 [DebuggerNonUserCode]
1099 public virtual void llDie() 1214 public virtual void llDie()
1100 { 1215 {
1101 m_host.AddScriptLPS(1); 1216 m_host.AddScriptLPS(1);
1102 throw new SelfDeleteException(); 1217 if (!m_host.IsAttachment) throw new SelfDeleteException();
1103 } 1218 }
1104 1219
1105 public LSL_Float llGround(LSL_Vector offset) 1220 public LSL_Float llGround(LSL_Vector offset)
@@ -1172,6 +1287,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1172 1287
1173 public void llSetStatus(int status, int value) 1288 public void llSetStatus(int status, int value)
1174 { 1289 {
1290 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
1291 return;
1175 m_host.AddScriptLPS(1); 1292 m_host.AddScriptLPS(1);
1176 1293
1177 int statusrotationaxis = 0; 1294 int statusrotationaxis = 0;
@@ -1402,6 +1519,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1402 { 1519 {
1403 m_host.AddScriptLPS(1); 1520 m_host.AddScriptLPS(1);
1404 1521
1522 SetColor(m_host, color, face);
1523 }
1524
1525 protected void SetColor(SceneObjectPart part, LSL_Vector color, int face)
1526 {
1527 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1528 return;
1529
1530 Primitive.TextureEntry tex = part.Shape.Textures;
1531 Color4 texcolor;
1532 if (face >= 0 && face < GetNumberOfSides(part))
1533 {
1534 texcolor = tex.CreateFace((uint)face).RGBA;
1535 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1536 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1537 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1538 tex.FaceTextures[face].RGBA = texcolor;
1539 part.UpdateTexture(tex);
1540 return;
1541 }
1542 else if (face == ScriptBaseClass.ALL_SIDES)
1543 {
1544 for (uint i = 0; i < GetNumberOfSides(part); i++)
1545 {
1546 if (tex.FaceTextures[i] != null)
1547 {
1548 texcolor = tex.FaceTextures[i].RGBA;
1549 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1550 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1551 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1552 tex.FaceTextures[i].RGBA = texcolor;
1553 }
1554 texcolor = tex.DefaultTexture.RGBA;
1555 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1556 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1557 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1558 tex.DefaultTexture.RGBA = texcolor;
1559 }
1560 part.UpdateTexture(tex);
1561 return;
1562 }
1563
1405 if (face == ScriptBaseClass.ALL_SIDES) 1564 if (face == ScriptBaseClass.ALL_SIDES)
1406 face = SceneObjectPart.ALL_SIDES; 1565 face = SceneObjectPart.ALL_SIDES;
1407 1566
@@ -1410,6 +1569,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1410 1569
1411 public void SetTexGen(SceneObjectPart part, int face,int style) 1570 public void SetTexGen(SceneObjectPart part, int face,int style)
1412 { 1571 {
1572 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1573 return;
1574
1413 Primitive.TextureEntry tex = part.Shape.Textures; 1575 Primitive.TextureEntry tex = part.Shape.Textures;
1414 MappingType textype; 1576 MappingType textype;
1415 textype = MappingType.Default; 1577 textype = MappingType.Default;
@@ -1440,6 +1602,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1440 1602
1441 public void SetGlow(SceneObjectPart part, int face, float glow) 1603 public void SetGlow(SceneObjectPart part, int face, float glow)
1442 { 1604 {
1605 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1606 return;
1607
1443 Primitive.TextureEntry tex = part.Shape.Textures; 1608 Primitive.TextureEntry tex = part.Shape.Textures;
1444 if (face >= 0 && face < GetNumberOfSides(part)) 1609 if (face >= 0 && face < GetNumberOfSides(part))
1445 { 1610 {
@@ -1465,6 +1630,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1465 1630
1466 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump) 1631 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump)
1467 { 1632 {
1633 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1634 return;
1468 1635
1469 Shininess sval = new Shininess(); 1636 Shininess sval = new Shininess();
1470 1637
@@ -1515,6 +1682,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1515 1682
1516 public void SetFullBright(SceneObjectPart part, int face, bool bright) 1683 public void SetFullBright(SceneObjectPart part, int face, bool bright)
1517 { 1684 {
1685 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1686 return;
1687
1518 Primitive.TextureEntry tex = part.Shape.Textures; 1688 Primitive.TextureEntry tex = part.Shape.Textures;
1519 if (face >= 0 && face < GetNumberOfSides(part)) 1689 if (face >= 0 && face < GetNumberOfSides(part))
1520 { 1690 {
@@ -1575,13 +1745,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1575 m_host.AddScriptLPS(1); 1745 m_host.AddScriptLPS(1);
1576 1746
1577 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1747 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1578 1748 if (parts.Count > 0)
1579 foreach (SceneObjectPart part in parts) 1749 {
1580 SetAlpha(part, alpha, face); 1750 try
1751 {
1752 parts[0].ParentGroup.areUpdatesSuspended = true;
1753 foreach (SceneObjectPart part in parts)
1754 SetAlpha(part, alpha, face);
1755 }
1756 finally
1757 {
1758 parts[0].ParentGroup.areUpdatesSuspended = false;
1759 }
1760 }
1581 } 1761 }
1582 1762
1583 protected void SetAlpha(SceneObjectPart part, double alpha, int face) 1763 protected void SetAlpha(SceneObjectPart part, double alpha, int face)
1584 { 1764 {
1765 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1766 return;
1767
1585 Primitive.TextureEntry tex = part.Shape.Textures; 1768 Primitive.TextureEntry tex = part.Shape.Textures;
1586 Color4 texcolor; 1769 Color4 texcolor;
1587 if (face >= 0 && face < GetNumberOfSides(part)) 1770 if (face >= 0 && face < GetNumberOfSides(part))
@@ -1627,7 +1810,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1627 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction, 1810 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction,
1628 float wind, float tension, LSL_Vector Force) 1811 float wind, float tension, LSL_Vector Force)
1629 { 1812 {
1630 if (part == null) 1813 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1631 return; 1814 return;
1632 1815
1633 if (flexi) 1816 if (flexi)
@@ -1662,7 +1845,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1662 /// <param name="falloff"></param> 1845 /// <param name="falloff"></param>
1663 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff) 1846 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
1664 { 1847 {
1665 if (part == null) 1848 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1666 return; 1849 return;
1667 1850
1668 if (light) 1851 if (light)
@@ -1739,15 +1922,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1739 m_host.AddScriptLPS(1); 1922 m_host.AddScriptLPS(1);
1740 1923
1741 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1924 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1742 1925 if (parts.Count > 0)
1743 foreach (SceneObjectPart part in parts) 1926 {
1744 SetTexture(part, texture, face); 1927 try
1745 1928 {
1929 parts[0].ParentGroup.areUpdatesSuspended = true;
1930 foreach (SceneObjectPart part in parts)
1931 SetTexture(part, texture, face);
1932 }
1933 finally
1934 {
1935 parts[0].ParentGroup.areUpdatesSuspended = false;
1936 }
1937 }
1746 ScriptSleep(200); 1938 ScriptSleep(200);
1747 } 1939 }
1748 1940
1749 protected void SetTexture(SceneObjectPart part, string texture, int face) 1941 protected void SetTexture(SceneObjectPart part, string texture, int face)
1750 { 1942 {
1943 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1944 return;
1945
1751 UUID textureID = new UUID(); 1946 UUID textureID = new UUID();
1752 1947
1753 textureID = InventoryKey(texture, (int)AssetType.Texture); 1948 textureID = InventoryKey(texture, (int)AssetType.Texture);
@@ -1792,6 +1987,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1792 1987
1793 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face) 1988 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face)
1794 { 1989 {
1990 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1991 return;
1992
1795 Primitive.TextureEntry tex = part.Shape.Textures; 1993 Primitive.TextureEntry tex = part.Shape.Textures;
1796 if (face >= 0 && face < GetNumberOfSides(part)) 1994 if (face >= 0 && face < GetNumberOfSides(part))
1797 { 1995 {
@@ -1828,6 +2026,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1828 2026
1829 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face) 2027 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face)
1830 { 2028 {
2029 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2030 return;
2031
1831 Primitive.TextureEntry tex = part.Shape.Textures; 2032 Primitive.TextureEntry tex = part.Shape.Textures;
1832 if (face >= 0 && face < GetNumberOfSides(part)) 2033 if (face >= 0 && face < GetNumberOfSides(part))
1833 { 2034 {
@@ -1864,6 +2065,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1864 2065
1865 protected void RotateTexture(SceneObjectPart part, double rotation, int face) 2066 protected void RotateTexture(SceneObjectPart part, double rotation, int face)
1866 { 2067 {
2068 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2069 return;
2070
1867 Primitive.TextureEntry tex = part.Shape.Textures; 2071 Primitive.TextureEntry tex = part.Shape.Textures;
1868 if (face >= 0 && face < GetNumberOfSides(part)) 2072 if (face >= 0 && face < GetNumberOfSides(part))
1869 { 2073 {
@@ -1932,10 +2136,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1932 return end; 2136 return end;
1933 } 2137 }
1934 2138
1935 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos) 2139 protected LSL_Vector GetSetPosTarget(SceneObjectPart part, LSL_Vector targetPos, LSL_Vector fromPos)
1936 { 2140 {
2141 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2142 return fromPos;
2143
1937 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) 2144 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
1938 LSL_Vector currentPos = GetPartLocalPos(part); 2145
1939 2146
1940 float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y); 2147 float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y);
1941 bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true); 2148 bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true);
@@ -1944,14 +2151,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1944 { 2151 {
1945 if ((targetPos.z < ground) && disable_underground_movement && m_host.AttachmentPoint == 0) 2152 if ((targetPos.z < ground) && disable_underground_movement && m_host.AttachmentPoint == 0)
1946 targetPos.z = ground; 2153 targetPos.z = ground;
2154 }
2155 LSL_Vector real_vec = SetPosAdjust(fromPos, targetPos);
2156
2157 return real_vec;
2158 }
2159
2160 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos)
2161 {
2162 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2163 return;
2164
2165 LSL_Vector currentPos = GetPartLocalPos(part);
2166 LSL_Vector toPos = GetSetPosTarget(part, targetPos, currentPos);
2167
2168 if (part.ParentGroup.RootPart == part)
2169 {
1947 SceneObjectGroup parent = part.ParentGroup; 2170 SceneObjectGroup parent = part.ParentGroup;
1948 LSL_Vector real_vec = SetPosAdjust(currentPos, targetPos); 2171 parent.UpdateGroupPosition(new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z));
1949 parent.UpdateGroupPosition(new Vector3((float)real_vec.x, (float)real_vec.y, (float)real_vec.z));
1950 } 2172 }
1951 else 2173 else
1952 { 2174 {
1953 LSL_Vector rel_vec = SetPosAdjust(currentPos, targetPos); 2175 part.OffsetPosition = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z);
1954 part.OffsetPosition = new Vector3((float)rel_vec.x, (float)rel_vec.y, (float)rel_vec.z);
1955 SceneObjectGroup parent = part.ParentGroup; 2176 SceneObjectGroup parent = part.ParentGroup;
1956 parent.HasGroupChanged = true; 2177 parent.HasGroupChanged = true;
1957 parent.ScheduleGroupForTerseUpdate(); 2178 parent.ScheduleGroupForTerseUpdate();
@@ -2002,9 +2223,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2002 m_host.AddScriptLPS(1); 2223 m_host.AddScriptLPS(1);
2003 2224
2004 // try to let this work as in SL... 2225 // try to let this work as in SL...
2005 if (m_host.ParentID == 0) 2226 if (m_host.LinkNum < 2)
2006 { 2227 {
2007 // special case: If we are root, rotate complete SOG to new rotation 2228 // Special case: If we are root, rotate complete SOG to new
2229 // rotation.
2230 // We are root if the link number is 0 (single prim) or 1
2231 // (root prim). ParentID may be nonzero in attachments and
2232 // using it would cause attachments and HUDs to rotate
2233 // to the wrong positions.
2008 SetRot(m_host, Rot2Quaternion(rot)); 2234 SetRot(m_host, Rot2Quaternion(rot));
2009 } 2235 }
2010 else 2236 else
@@ -2033,6 +2259,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2033 2259
2034 protected void SetRot(SceneObjectPart part, Quaternion rot) 2260 protected void SetRot(SceneObjectPart part, Quaternion rot)
2035 { 2261 {
2262 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2263 return;
2264
2036 part.UpdateRotation(rot); 2265 part.UpdateRotation(rot);
2037 // Update rotation does not move the object in the physics scene if it's a linkset. 2266 // Update rotation does not move the object in the physics scene if it's a linkset.
2038 2267
@@ -2652,12 +2881,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2652 2881
2653 m_host.AddScriptLPS(1); 2882 m_host.AddScriptLPS(1);
2654 2883
2884 m_host.TaskInventory.LockItemsForRead(true);
2655 TaskInventoryItem item = m_host.TaskInventory[invItemID]; 2885 TaskInventoryItem item = m_host.TaskInventory[invItemID];
2656 2886 m_host.TaskInventory.LockItemsForRead(false);
2657 lock (m_host.TaskInventory)
2658 {
2659 item = m_host.TaskInventory[invItemID];
2660 }
2661 2887
2662 if (item.PermsGranter == UUID.Zero) 2888 if (item.PermsGranter == UUID.Zero)
2663 return 0; 2889 return 0;
@@ -2732,6 +2958,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2732 if (dist > m_ScriptDistanceFactor * 10.0f) 2958 if (dist > m_ScriptDistanceFactor * 10.0f)
2733 return; 2959 return;
2734 2960
2961 //Clone is thread-safe
2735 TaskInventoryDictionary partInventory = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 2962 TaskInventoryDictionary partInventory = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
2736 2963
2737 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in partInventory) 2964 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in partInventory)
@@ -2794,6 +3021,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2794 3021
2795 public void llLookAt(LSL_Vector target, double strength, double damping) 3022 public void llLookAt(LSL_Vector target, double strength, double damping)
2796 { 3023 {
3024 /*
2797 m_host.AddScriptLPS(1); 3025 m_host.AddScriptLPS(1);
2798 // Determine where we are looking from 3026 // Determine where we are looking from
2799 LSL_Vector from = llGetPos(); 3027 LSL_Vector from = llGetPos();
@@ -2813,10 +3041,54 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2813 // the angles of rotation in radians into rotation value 3041 // the angles of rotation in radians into rotation value
2814 3042
2815 LSL_Types.Quaternion rot = llEuler2Rot(angle); 3043 LSL_Types.Quaternion rot = llEuler2Rot(angle);
2816 Quaternion rotation = new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s); 3044
2817 m_host.startLookAt(rotation, (float)damping, (float)strength); 3045 // This would only work if your physics system contains an APID controller:
3046 // Quaternion rotation = new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s);
3047 // m_host.startLookAt(rotation, (float)damping, (float)strength);
3048
2818 // Orient the object to the angle calculated 3049 // Orient the object to the angle calculated
2819 //llSetRot(rot); 3050 llSetRot(rot);
3051 */
3052
3053 //The above code, while nice, doesn't replicate the behaviour of SL and tends to "roll" the object.
3054 //There's probably a smarter way of doing this, my rotation math-fu is weak.
3055 // http://bugs.meta7.com/view.php?id=28
3056 // - Tom
3057
3058 /* And the following does not do the job either. It has to be performed inside the ODE glue-code. -.- .._.
3059 LSL_Rotation newrot = llGetRot() * llRotBetween(new LSL_Vector(1.0d, 0.0d, 0.0d) * llGetRot(), new LSL_Vector(0.0d, 0.0d, -1.0d));
3060 llSetRot(newrot * llRotBetween(new LSL_Vector(0.0d,0.0d,1.0d) * newrot, target - llGetPos()));
3061 */
3062 if (m_host.PhysActor != null && !m_host.PhysActor.IsPhysical)
3063 {
3064 // Part is non-phys, convert this to a llSetRot()
3065 Vector3 tgt = new Vector3((float)target.x, (float)target.y, (float)target.z);
3066 Vector3 dir = tgt - m_host.GroupPosition;
3067 dir.Normalize();
3068 float tzrot = (float)Math.Atan2(dir.Y, dir.X);
3069 float txy = (float)Math.Sqrt((dir.X * dir.X) + (dir.Y * dir.Y));
3070 float terot = (float)Math.Atan2(-dir.Z, txy);
3071 LSL_Vector az = new LSL_Vector(0.0f, 0.0f, tzrot);
3072 LSL_Vector ae = new LSL_Vector(0.0f, terot, 0.0f);
3073 LSL_Types.Quaternion spin = llEuler2Rot(az);
3074 LSL_Types.Quaternion rot = llEuler2Rot(ae) * spin;
3075 llSetRot(rot);
3076 }
3077 else
3078 {
3079 // Physical, send the target vector to RotLookAt method inside a 'rotation', the .w -99.9 value indicates it is really a LookAt.
3080 Quaternion q = new Quaternion((float)target.x, (float)target.y, (float)target.z, -99.9f);
3081 m_host.RotLookAt(q, (float)strength, (float)damping);
3082 }
3083
3084 }
3085
3086 public void llRotLookAt(LSL_Rotation target, double strength, double damping)
3087 {
3088 m_host.AddScriptLPS(1);
3089// NotImplemented("llRotLookAt");
3090 m_host.RotLookAt(Rot2Quaternion(target), (float)strength, (float)damping);
3091
2820 } 3092 }
2821 3093
2822 public void llStopLookAt() 3094 public void llStopLookAt()
@@ -2865,13 +3137,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2865 { 3137 {
2866 TaskInventoryItem item; 3138 TaskInventoryItem item;
2867 3139
2868 lock (m_host.TaskInventory) 3140 m_host.TaskInventory.LockItemsForRead(true);
3141 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2869 { 3142 {
2870 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3143 m_host.TaskInventory.LockItemsForRead(false);
2871 return; 3144 return;
2872 else
2873 item = m_host.TaskInventory[InventorySelf()];
2874 } 3145 }
3146 else
3147 {
3148 item = m_host.TaskInventory[InventorySelf()];
3149 }
3150 m_host.TaskInventory.LockItemsForRead(false);
2875 3151
2876 if (item.PermsGranter != UUID.Zero) 3152 if (item.PermsGranter != UUID.Zero)
2877 { 3153 {
@@ -2893,13 +3169,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2893 { 3169 {
2894 TaskInventoryItem item; 3170 TaskInventoryItem item;
2895 3171
3172 m_host.TaskInventory.LockItemsForRead(true);
2896 lock (m_host.TaskInventory) 3173 lock (m_host.TaskInventory)
2897 { 3174 {
3175
2898 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3176 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3177 {
3178 m_host.TaskInventory.LockItemsForRead(false);
2899 return; 3179 return;
3180 }
2900 else 3181 else
3182 {
2901 item = m_host.TaskInventory[InventorySelf()]; 3183 item = m_host.TaskInventory[InventorySelf()];
3184 }
2902 } 3185 }
3186 m_host.TaskInventory.LockItemsForRead(false);
2903 3187
2904 m_host.AddScriptLPS(1); 3188 m_host.AddScriptLPS(1);
2905 3189
@@ -2931,18 +3215,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2931 { 3215 {
2932 m_host.AddScriptLPS(1); 3216 m_host.AddScriptLPS(1);
2933 3217
2934 if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
2935 return;
2936
2937 TaskInventoryItem item; 3218 TaskInventoryItem item;
2938 3219
2939 lock (m_host.TaskInventory) 3220 m_host.TaskInventory.LockItemsForRead(true);
3221
3222 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2940 { 3223 {
2941 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3224 m_host.TaskInventory.LockItemsForRead(false);
2942 return; 3225 return;
2943 else
2944 item = m_host.TaskInventory[InventorySelf()];
2945 } 3226 }
3227 else
3228 {
3229 item = m_host.TaskInventory[InventorySelf()];
3230 }
3231
3232 m_host.TaskInventory.LockItemsForRead(false);
2946 3233
2947 if (item.PermsGranter != m_host.OwnerID) 3234 if (item.PermsGranter != m_host.OwnerID)
2948 return; 3235 return;
@@ -2953,10 +3240,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2953 3240
2954 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 3241 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
2955 3242
2956 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; 3243 grp.AttachToAgent(m_host.OwnerID, (uint)attachment, Vector3.Zero, false);
2957 if (attachmentsModule != null)
2958 attachmentsModule.AttachObject(presence.ControllingClient,
2959 grp, (uint)attachment, false);
2960 } 3244 }
2961 } 3245 }
2962 3246
@@ -2969,13 +3253,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2969 3253
2970 TaskInventoryItem item; 3254 TaskInventoryItem item;
2971 3255
2972 lock (m_host.TaskInventory) 3256 m_host.TaskInventory.LockItemsForRead(true);
3257
3258 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2973 { 3259 {
2974 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3260 m_host.TaskInventory.LockItemsForRead(false);
2975 return; 3261 return;
2976 else
2977 item = m_host.TaskInventory[InventorySelf()];
2978 } 3262 }
3263 else
3264 {
3265 item = m_host.TaskInventory[InventorySelf()];
3266 }
3267 m_host.TaskInventory.LockItemsForRead(false);
3268
2979 3269
2980 if (item.PermsGranter != m_host.OwnerID) 3270 if (item.PermsGranter != m_host.OwnerID)
2981 return; 3271 return;
@@ -3022,6 +3312,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3022 3312
3023 public void llInstantMessage(string user, string message) 3313 public void llInstantMessage(string user, string message)
3024 { 3314 {
3315 UUID result;
3316 if (!UUID.TryParse(user, out result))
3317 {
3318 ShoutError("An invalid key was passed to llInstantMessage");
3319 ScriptSleep(2000);
3320 return;
3321 }
3322
3323
3025 m_host.AddScriptLPS(1); 3324 m_host.AddScriptLPS(1);
3026 3325
3027 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. 3326 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
@@ -3036,14 +3335,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3036 UUID friendTransactionID = UUID.Random(); 3335 UUID friendTransactionID = UUID.Random();
3037 3336
3038 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); 3337 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
3039 3338
3040 GridInstantMessage msg = new GridInstantMessage(); 3339 GridInstantMessage msg = new GridInstantMessage();
3041 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; 3340 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid;
3042 msg.toAgentID = new Guid(user); // toAgentID.Guid; 3341 msg.toAgentID = new Guid(user); // toAgentID.Guid;
3043 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here 3342 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here
3044// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message); 3343// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message);
3045// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString()); 3344// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString());
3046 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; 3345// DateTime dt = DateTime.UtcNow;
3346//
3347// // Ticks from UtcNow, but make it look like local. Evil, huh?
3348// dt = DateTime.SpecifyKind(dt, DateTimeKind.Local);
3349//
3350// try
3351// {
3352// // Convert that to the PST timezone
3353// TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
3354// dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo);
3355// }
3356// catch
3357// {
3358// // No logging here, as it could be VERY spammy
3359// }
3360//
3361// // And make it look local again to fool the unix time util
3362// dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
3363
3364 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
3365
3047 //if (client != null) 3366 //if (client != null)
3048 //{ 3367 //{
3049 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName; 3368 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
@@ -3057,12 +3376,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3057 msg.message = message.Substring(0, 1024); 3376 msg.message = message.Substring(0, 1024);
3058 else 3377 else
3059 msg.message = message; 3378 msg.message = message;
3060 msg.dialog = (byte)19; // messgage from script ??? // dialog; 3379 msg.dialog = (byte)19; // MessageFromObject
3061 msg.fromGroup = false;// fromGroup; 3380 msg.fromGroup = false;// fromGroup;
3062 msg.offline = (byte)0; //offline; 3381 msg.offline = (byte)0; //offline;
3063 msg.ParentEstateID = 0; //ParentEstateID; 3382 msg.ParentEstateID = World.RegionInfo.EstateSettings.EstateID;
3064 msg.Position = new Vector3(m_host.AbsolutePosition); 3383 msg.Position = new Vector3(m_host.AbsolutePosition);
3065 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; 3384 msg.RegionID = World.RegionInfo.RegionID.Guid;
3066 msg.binaryBucket 3385 msg.binaryBucket
3067 = Util.StringToBytes256( 3386 = Util.StringToBytes256(
3068 "{0}/{1}/{2}/{3}", 3387 "{0}/{1}/{2}/{3}",
@@ -3090,7 +3409,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3090 } 3409 }
3091 3410
3092 emailModule.SendEmail(m_host.UUID, address, subject, message); 3411 emailModule.SendEmail(m_host.UUID, address, subject, message);
3093 ScriptSleep(20000); 3412 ScriptSleep(15000);
3094 } 3413 }
3095 3414
3096 public void llGetNextEmail(string address, string subject) 3415 public void llGetNextEmail(string address, string subject)
@@ -3134,7 +3453,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3134 { 3453 {
3135 if (!m_host.ParentGroup.IsDeleted) 3454 if (!m_host.ParentGroup.IsDeleted)
3136 { 3455 {
3137 m_host.ParentGroup.RootPart.SetBuoyancy((float)buoyancy); 3456 m_host.ParentGroup.RootPart.Buoyancy = (float)buoyancy;
3138 } 3457 }
3139 } 3458 }
3140 } 3459 }
@@ -3192,13 +3511,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3192 m_host.AddScriptLPS(1); 3511 m_host.AddScriptLPS(1);
3193 } 3512 }
3194 3513
3195 public void llRotLookAt(LSL_Rotation target, double strength, double damping)
3196 {
3197 m_host.AddScriptLPS(1);
3198 Quaternion rot = new Quaternion((float)target.x, (float)target.y, (float)target.z, (float)target.s);
3199 m_host.RotLookAt(rot, (float)strength, (float)damping);
3200 }
3201
3202 public LSL_Integer llStringLength(string str) 3514 public LSL_Integer llStringLength(string str)
3203 { 3515 {
3204 m_host.AddScriptLPS(1); 3516 m_host.AddScriptLPS(1);
@@ -3222,14 +3534,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3222 3534
3223 TaskInventoryItem item; 3535 TaskInventoryItem item;
3224 3536
3225 lock (m_host.TaskInventory) 3537 m_host.TaskInventory.LockItemsForRead(true);
3538 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3226 { 3539 {
3227 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3540 m_host.TaskInventory.LockItemsForRead(false);
3228 return; 3541 return;
3229 else
3230 item = m_host.TaskInventory[InventorySelf()];
3231 } 3542 }
3232 3543 else
3544 {
3545 item = m_host.TaskInventory[InventorySelf()];
3546 }
3547 m_host.TaskInventory.LockItemsForRead(false);
3233 if (item.PermsGranter == UUID.Zero) 3548 if (item.PermsGranter == UUID.Zero)
3234 return; 3549 return;
3235 3550
@@ -3259,13 +3574,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3259 3574
3260 TaskInventoryItem item; 3575 TaskInventoryItem item;
3261 3576
3262 lock (m_host.TaskInventory) 3577 m_host.TaskInventory.LockItemsForRead(true);
3578 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3263 { 3579 {
3264 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3580 m_host.TaskInventory.LockItemsForRead(false);
3265 return; 3581 return;
3266 else
3267 item = m_host.TaskInventory[InventorySelf()];
3268 } 3582 }
3583 else
3584 {
3585 item = m_host.TaskInventory[InventorySelf()];
3586 }
3587 m_host.TaskInventory.LockItemsForRead(false);
3588
3269 3589
3270 if (item.PermsGranter == UUID.Zero) 3590 if (item.PermsGranter == UUID.Zero)
3271 return; 3591 return;
@@ -3330,10 +3650,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3330 3650
3331 TaskInventoryItem item; 3651 TaskInventoryItem item;
3332 3652
3333 lock (m_host.TaskInventory) 3653
3654 m_host.TaskInventory.LockItemsForRead(true);
3655 if (!m_host.TaskInventory.ContainsKey(invItemID))
3656 {
3657 m_host.TaskInventory.LockItemsForRead(false);
3658 return;
3659 }
3660 else
3334 { 3661 {
3335 item = m_host.TaskInventory[invItemID]; 3662 item = m_host.TaskInventory[invItemID];
3336 } 3663 }
3664 m_host.TaskInventory.LockItemsForRead(false);
3337 3665
3338 if (agentID == UUID.Zero || perm == 0) // Releasing permissions 3666 if (agentID == UUID.Zero || perm == 0) // Releasing permissions
3339 { 3667 {
@@ -3361,15 +3689,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3361 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | 3689 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
3362 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3690 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3363 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3691 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3692 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3364 ScriptBaseClass.PERMISSION_ATTACH; 3693 ScriptBaseClass.PERMISSION_ATTACH;
3365 3694
3366 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3695 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3367 { 3696 {
3368 lock (m_host.TaskInventory) 3697 m_host.TaskInventory.LockItemsForWrite(true);
3369 { 3698 m_host.TaskInventory[invItemID].PermsGranter = agentID;
3370 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3699 m_host.TaskInventory[invItemID].PermsMask = perm;
3371 m_host.TaskInventory[invItemID].PermsMask = perm; 3700 m_host.TaskInventory.LockItemsForWrite(false);
3372 }
3373 3701
3374 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3702 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3375 "run_time_permissions", new Object[] { 3703 "run_time_permissions", new Object[] {
@@ -3379,28 +3707,44 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3379 return; 3707 return;
3380 } 3708 }
3381 } 3709 }
3382 else if (m_host.SitTargetAvatar == agentID) // Sitting avatar 3710 else
3383 { 3711 {
3384 // When agent is sitting, certain permissions are implicit if requested from sitting agent 3712 bool sitting = false;
3385 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3713 if (m_host.SitTargetAvatar == agentID)
3386 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3714 {
3387 ScriptBaseClass.PERMISSION_TRACK_CAMERA | 3715 sitting = true;
3388 ScriptBaseClass.PERMISSION_TAKE_CONTROLS; 3716 }
3717 else
3718 {
3719 foreach (SceneObjectPart p in m_host.ParentGroup.Parts)
3720 {
3721 if (p.SitTargetAvatar == agentID)
3722 sitting = true;
3723 }
3724 }
3389 3725
3390 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3726 if (sitting)
3391 { 3727 {
3392 lock (m_host.TaskInventory) 3728 // When agent is sitting, certain permissions are implicit if requested from sitting agent
3729 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3730 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3731 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3732 ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
3733
3734 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3393 { 3735 {
3736 m_host.TaskInventory.LockItemsForWrite(true);
3394 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3737 m_host.TaskInventory[invItemID].PermsGranter = agentID;
3395 m_host.TaskInventory[invItemID].PermsMask = perm; 3738 m_host.TaskInventory[invItemID].PermsMask = perm;
3396 } 3739 m_host.TaskInventory.LockItemsForWrite(false);
3397 3740
3398 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3741 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3399 "run_time_permissions", new Object[] { 3742 "run_time_permissions", new Object[] {
3400 new LSL_Integer(perm) }, 3743 new LSL_Integer(perm) },
3401 new DetectParams[0])); 3744 new DetectParams[0]));
3402 3745
3403 return; 3746 return;
3747 }
3404 } 3748 }
3405 } 3749 }
3406 3750
@@ -3414,11 +3758,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3414 3758
3415 if (!m_waitingForScriptAnswer) 3759 if (!m_waitingForScriptAnswer)
3416 { 3760 {
3417 lock (m_host.TaskInventory) 3761 m_host.TaskInventory.LockItemsForWrite(true);
3418 { 3762 m_host.TaskInventory[invItemID].PermsGranter = agentID;
3419 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3763 m_host.TaskInventory[invItemID].PermsMask = 0;
3420 m_host.TaskInventory[invItemID].PermsMask = 0; 3764 m_host.TaskInventory.LockItemsForWrite(false);
3421 }
3422 3765
3423 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; 3766 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
3424 m_waitingForScriptAnswer=true; 3767 m_waitingForScriptAnswer=true;
@@ -3453,10 +3796,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3453 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) 3796 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
3454 llReleaseControls(); 3797 llReleaseControls();
3455 3798
3456 lock (m_host.TaskInventory) 3799
3457 { 3800 m_host.TaskInventory.LockItemsForWrite(true);
3458 m_host.TaskInventory[invItemID].PermsMask = answer; 3801 m_host.TaskInventory[invItemID].PermsMask = answer;
3459 } 3802 m_host.TaskInventory.LockItemsForWrite(false);
3803
3460 3804
3461 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3805 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3462 "run_time_permissions", new Object[] { 3806 "run_time_permissions", new Object[] {
@@ -3468,16 +3812,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3468 { 3812 {
3469 m_host.AddScriptLPS(1); 3813 m_host.AddScriptLPS(1);
3470 3814
3471 lock (m_host.TaskInventory) 3815 m_host.TaskInventory.LockItemsForRead(true);
3816
3817 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3472 { 3818 {
3473 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 3819 if (item.Type == 10 && item.ItemID == m_itemID)
3474 { 3820 {
3475 if (item.Type == 10 && item.ItemID == m_itemID) 3821 m_host.TaskInventory.LockItemsForRead(false);
3476 { 3822 return item.PermsGranter.ToString();
3477 return item.PermsGranter.ToString();
3478 }
3479 } 3823 }
3480 } 3824 }
3825 m_host.TaskInventory.LockItemsForRead(false);
3481 3826
3482 return UUID.Zero.ToString(); 3827 return UUID.Zero.ToString();
3483 } 3828 }
@@ -3486,19 +3831,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3486 { 3831 {
3487 m_host.AddScriptLPS(1); 3832 m_host.AddScriptLPS(1);
3488 3833
3489 lock (m_host.TaskInventory) 3834 m_host.TaskInventory.LockItemsForRead(true);
3835
3836 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3490 { 3837 {
3491 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 3838 if (item.Type == 10 && item.ItemID == m_itemID)
3492 { 3839 {
3493 if (item.Type == 10 && item.ItemID == m_itemID) 3840 int perms = item.PermsMask;
3494 { 3841 if (m_automaticLinkPermission)
3495 int perms = item.PermsMask; 3842 perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS;
3496 if (m_automaticLinkPermission) 3843 m_host.TaskInventory.LockItemsForRead(false);
3497 perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS; 3844 return perms;
3498 return perms;
3499 }
3500 } 3845 }
3501 } 3846 }
3847 m_host.TaskInventory.LockItemsForRead(false);
3502 3848
3503 return 0; 3849 return 0;
3504 } 3850 }
@@ -3520,9 +3866,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3520 public void llSetLinkColor(int linknumber, LSL_Vector color, int face) 3866 public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
3521 { 3867 {
3522 List<SceneObjectPart> parts = GetLinkParts(linknumber); 3868 List<SceneObjectPart> parts = GetLinkParts(linknumber);
3523 3869 if (parts.Count > 0)
3524 foreach (SceneObjectPart part in parts) 3870 {
3525 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); 3871 try
3872 {
3873 parts[0].ParentGroup.areUpdatesSuspended = true;
3874 foreach (SceneObjectPart part in parts)
3875 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face);
3876 }
3877 finally
3878 {
3879 parts[0].ParentGroup.areUpdatesSuspended = false;
3880 }
3881 }
3526 } 3882 }
3527 3883
3528 public void llCreateLink(string target, int parent) 3884 public void llCreateLink(string target, int parent)
@@ -3535,11 +3891,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3535 return; 3891 return;
3536 3892
3537 TaskInventoryItem item; 3893 TaskInventoryItem item;
3538 lock (m_host.TaskInventory) 3894 m_host.TaskInventory.LockItemsForRead(true);
3539 { 3895 item = m_host.TaskInventory[invItemID];
3540 item = m_host.TaskInventory[invItemID]; 3896 m_host.TaskInventory.LockItemsForRead(false);
3541 } 3897
3542
3543 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 3898 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
3544 && !m_automaticLinkPermission) 3899 && !m_automaticLinkPermission)
3545 { 3900 {
@@ -3556,11 +3911,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3556 3911
3557 if (targetPart.ParentGroup.RootPart.AttachmentPoint != 0) 3912 if (targetPart.ParentGroup.RootPart.AttachmentPoint != 0)
3558 return; // Fail silently if attached 3913 return; // Fail silently if attached
3914
3915 if (targetPart.ParentGroup.RootPart.OwnerID != m_host.ParentGroup.RootPart.OwnerID)
3916 return;
3917
3559 SceneObjectGroup parentPrim = null, childPrim = null; 3918 SceneObjectGroup parentPrim = null, childPrim = null;
3560 3919
3561 if (targetPart != null) 3920 if (targetPart != null)
3562 { 3921 {
3563 if (parent != 0) { 3922 if (parent != 0)
3923 {
3564 parentPrim = m_host.ParentGroup; 3924 parentPrim = m_host.ParentGroup;
3565 childPrim = targetPart.ParentGroup; 3925 childPrim = targetPart.ParentGroup;
3566 } 3926 }
@@ -3592,16 +3952,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3592 m_host.AddScriptLPS(1); 3952 m_host.AddScriptLPS(1);
3593 UUID invItemID = InventorySelf(); 3953 UUID invItemID = InventorySelf();
3594 3954
3595 lock (m_host.TaskInventory) 3955 m_host.TaskInventory.LockItemsForRead(true);
3596 {
3597 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 3956 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
3598 && !m_automaticLinkPermission) 3957 && !m_automaticLinkPermission)
3599 { 3958 {
3600 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!"); 3959 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
3960 m_host.TaskInventory.LockItemsForRead(false);
3601 return; 3961 return;
3602 } 3962 }
3603 } 3963 m_host.TaskInventory.LockItemsForRead(false);
3604 3964
3605 if (linknum < ScriptBaseClass.LINK_THIS) 3965 if (linknum < ScriptBaseClass.LINK_THIS)
3606 return; 3966 return;
3607 3967
@@ -3640,10 +4000,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3640 // Restructuring Multiple Prims. 4000 // Restructuring Multiple Prims.
3641 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts); 4001 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
3642 parts.Remove(parentPrim.RootPart); 4002 parts.Remove(parentPrim.RootPart);
3643 foreach (SceneObjectPart part in parts) 4003 if (parts.Count > 0)
3644 { 4004 {
3645 parentPrim.DelinkFromGroup(part.LocalId, true); 4005 try
4006 {
4007 parts[0].ParentGroup.areUpdatesSuspended = true;
4008 foreach (SceneObjectPart part in parts)
4009 {
4010 parentPrim.DelinkFromGroup(part.LocalId, true);
4011 }
4012 }
4013 finally
4014 {
4015 parts[0].ParentGroup.areUpdatesSuspended = false;
4016 }
3646 } 4017 }
4018
3647 parentPrim.HasGroupChanged = true; 4019 parentPrim.HasGroupChanged = true;
3648 parentPrim.ScheduleGroupForFullUpdate(); 4020 parentPrim.ScheduleGroupForFullUpdate();
3649 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 4021 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
@@ -3652,11 +4024,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3652 { 4024 {
3653 SceneObjectPart newRoot = parts[0]; 4025 SceneObjectPart newRoot = parts[0];
3654 parts.Remove(newRoot); 4026 parts.Remove(newRoot);
3655 foreach (SceneObjectPart part in parts) 4027
4028 try
3656 { 4029 {
3657 part.UpdateFlag = 0; 4030 parts[0].ParentGroup.areUpdatesSuspended = true;
3658 newRoot.ParentGroup.LinkToGroup(part.ParentGroup); 4031 foreach (SceneObjectPart part in parts)
4032 {
4033 part.UpdateFlag = 0;
4034 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
4035 }
3659 } 4036 }
4037 finally
4038 {
4039 parts[0].ParentGroup.areUpdatesSuspended = false;
4040 }
4041
4042
3660 newRoot.ParentGroup.HasGroupChanged = true; 4043 newRoot.ParentGroup.HasGroupChanged = true;
3661 newRoot.ParentGroup.ScheduleGroupForFullUpdate(); 4044 newRoot.ParentGroup.ScheduleGroupForFullUpdate();
3662 } 4045 }
@@ -3676,6 +4059,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3676 public void llBreakAllLinks() 4059 public void llBreakAllLinks()
3677 { 4060 {
3678 m_host.AddScriptLPS(1); 4061 m_host.AddScriptLPS(1);
4062
4063 UUID invItemID = InventorySelf();
4064
4065 TaskInventoryItem item;
4066 m_host.TaskInventory.LockItemsForRead(true);
4067 item = m_host.TaskInventory[invItemID];
4068 m_host.TaskInventory.LockItemsForRead(false);
4069
4070 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4071 && !m_automaticLinkPermission)
4072 {
4073 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
4074 return;
4075 }
4076
3679 SceneObjectGroup parentPrim = m_host.ParentGroup; 4077 SceneObjectGroup parentPrim = m_host.ParentGroup;
3680 if (parentPrim.RootPart.AttachmentPoint != 0) 4078 if (parentPrim.RootPart.AttachmentPoint != 0)
3681 return; // Fail silently if attached 4079 return; // Fail silently if attached
@@ -3702,6 +4100,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3702 } 4100 }
3703 else 4101 else
3704 { 4102 {
4103 if (linknum > m_host.ParentGroup.PrimCount || (linknum == 1 && m_host.ParentGroup.PrimCount == 1))
4104 {
4105 linknum -= (m_host.ParentGroup.PrimCount) + 1;
4106
4107 if (linknum < 0)
4108 return UUID.Zero.ToString();
4109
4110 List<ScenePresence> avatars = GetLinkAvatars(ScriptBaseClass.LINK_SET);
4111 if (avatars.Count > linknum)
4112 {
4113 return avatars[linknum].UUID.ToString();
4114 }
4115 }
3705 return UUID.Zero.ToString(); 4116 return UUID.Zero.ToString();
3706 } 4117 }
3707 } 4118 }
@@ -3778,17 +4189,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3778 m_host.AddScriptLPS(1); 4189 m_host.AddScriptLPS(1);
3779 int count = 0; 4190 int count = 0;
3780 4191
3781 lock (m_host.TaskInventory) 4192 m_host.TaskInventory.LockItemsForRead(true);
4193 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3782 { 4194 {
3783 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4195 if (inv.Value.Type == type || type == -1)
3784 { 4196 {
3785 if (inv.Value.Type == type || type == -1) 4197 count = count + 1;
3786 {
3787 count = count + 1;
3788 }
3789 } 4198 }
3790 } 4199 }
3791 4200
4201 m_host.TaskInventory.LockItemsForRead(false);
3792 return count; 4202 return count;
3793 } 4203 }
3794 4204
@@ -3797,16 +4207,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3797 m_host.AddScriptLPS(1); 4207 m_host.AddScriptLPS(1);
3798 ArrayList keys = new ArrayList(); 4208 ArrayList keys = new ArrayList();
3799 4209
3800 lock (m_host.TaskInventory) 4210 m_host.TaskInventory.LockItemsForRead(true);
4211 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3801 { 4212 {
3802 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4213 if (inv.Value.Type == type || type == -1)
3803 { 4214 {
3804 if (inv.Value.Type == type || type == -1) 4215 keys.Add(inv.Value.Name);
3805 {
3806 keys.Add(inv.Value.Name);
3807 }
3808 } 4216 }
3809 } 4217 }
4218 m_host.TaskInventory.LockItemsForRead(false);
3810 4219
3811 if (keys.Count == 0) 4220 if (keys.Count == 0)
3812 { 4221 {
@@ -3843,25 +4252,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3843 } 4252 }
3844 4253
3845 // move the first object found with this inventory name 4254 // move the first object found with this inventory name
3846 lock (m_host.TaskInventory) 4255 m_host.TaskInventory.LockItemsForRead(true);
4256 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3847 { 4257 {
3848 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4258 if (inv.Value.Name == inventory)
3849 { 4259 {
3850 if (inv.Value.Name == inventory) 4260 found = true;
3851 { 4261 objId = inv.Key;
3852 found = true; 4262 assetType = inv.Value.Type;
3853 objId = inv.Key; 4263 objName = inv.Value.Name;
3854 assetType = inv.Value.Type; 4264 break;
3855 objName = inv.Value.Name;
3856 break;
3857 }
3858 } 4265 }
3859 } 4266 }
4267 m_host.TaskInventory.LockItemsForRead(false);
3860 4268
3861 if (!found) 4269 if (!found)
3862 { 4270 {
3863 llSay(0, String.Format("Could not find object '{0}'", inventory)); 4271 llSay(0, String.Format("Could not find object '{0}'", inventory));
3864 throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory)); 4272 return;
4273// throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
3865 } 4274 }
3866 4275
3867 // check if destination is an object 4276 // check if destination is an object
@@ -3887,6 +4296,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3887 return; 4296 return;
3888 } 4297 }
3889 } 4298 }
4299
3890 // destination is an avatar 4300 // destination is an avatar
3891 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId); 4301 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId);
3892 4302
@@ -3909,26 +4319,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3909 bucket); 4319 bucket);
3910 if (m_TransferModule != null) 4320 if (m_TransferModule != null)
3911 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 4321 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
4322
4323 //This delay should only occur when giving inventory to avatars.
3912 ScriptSleep(3000); 4324 ScriptSleep(3000);
3913 } 4325 }
3914 } 4326 }
3915 4327
4328 [DebuggerNonUserCode]
3916 public void llRemoveInventory(string name) 4329 public void llRemoveInventory(string name)
3917 { 4330 {
3918 m_host.AddScriptLPS(1); 4331 m_host.AddScriptLPS(1);
3919 4332
3920 lock (m_host.TaskInventory) 4333 List<TaskInventoryItem> inv;
4334 try
3921 { 4335 {
3922 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4336 m_host.TaskInventory.LockItemsForRead(true);
4337 inv = new List<TaskInventoryItem>(m_host.TaskInventory.Values);
4338 }
4339 finally
4340 {
4341 m_host.TaskInventory.LockItemsForRead(false);
4342 }
4343 foreach (TaskInventoryItem item in inv)
4344 {
4345 if (item.Name == name)
3923 { 4346 {
3924 if (item.Name == name) 4347 if (item.ItemID == m_itemID)
3925 { 4348 throw new ScriptDeleteException();
3926 if (item.ItemID == m_itemID) 4349 else
3927 throw new ScriptDeleteException(); 4350 m_host.Inventory.RemoveInventoryItem(item.ItemID);
3928 else 4351 return;
3929 m_host.Inventory.RemoveInventoryItem(item.ItemID);
3930 return;
3931 }
3932 } 4352 }
3933 } 4353 }
3934 } 4354 }
@@ -3963,112 +4383,122 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3963 { 4383 {
3964 m_host.AddScriptLPS(1); 4384 m_host.AddScriptLPS(1);
3965 4385
3966 UUID uuid = (UUID)id; 4386 UUID uuid;
3967 PresenceInfo pinfo = null; 4387 if (UUID.TryParse(id, out uuid))
3968 UserAccount account;
3969
3970 UserInfoCacheEntry ce;
3971 if (!m_userInfoCache.TryGetValue(uuid, out ce))
3972 { 4388 {
3973 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); 4389 PresenceInfo pinfo = null;
3974 if (account == null) 4390 UserAccount account;
4391
4392 UserInfoCacheEntry ce;
4393 if (!m_userInfoCache.TryGetValue(uuid, out ce))
3975 { 4394 {
3976 m_userInfoCache[uuid] = null; // Cache negative 4395 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
3977 return UUID.Zero.ToString(); 4396 if (account == null)
3978 } 4397 {
4398 m_userInfoCache[uuid] = null; // Cache negative
4399 return UUID.Zero.ToString();
4400 }
3979 4401
3980 4402
3981 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); 4403 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
3982 if (pinfos != null && pinfos.Length > 0) 4404 if (pinfos != null && pinfos.Length > 0)
3983 {
3984 foreach (PresenceInfo p in pinfos)
3985 { 4405 {
3986 if (p.RegionID != UUID.Zero) 4406 foreach (PresenceInfo p in pinfos)
3987 { 4407 {
3988 pinfo = p; 4408 if (p.RegionID != UUID.Zero)
4409 {
4410 pinfo = p;
4411 }
3989 } 4412 }
3990 } 4413 }
3991 }
3992 4414
3993 ce = new UserInfoCacheEntry(); 4415 ce = new UserInfoCacheEntry();
3994 ce.time = Util.EnvironmentTickCount(); 4416 ce.time = Util.EnvironmentTickCount();
3995 ce.account = account; 4417 ce.account = account;
3996 ce.pinfo = pinfo; 4418 ce.pinfo = pinfo;
3997 } 4419 m_userInfoCache[uuid] = ce;
3998 else 4420 }
3999 { 4421 else
4000 if (ce == null) 4422 {
4001 return UUID.Zero.ToString(); 4423 if (ce == null)
4424 return UUID.Zero.ToString();
4002 4425
4003 account = ce.account; 4426 account = ce.account;
4004 pinfo = ce.pinfo; 4427 pinfo = ce.pinfo;
4005 } 4428 }
4006 4429
4007 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000) 4430 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000)
4008 {
4009 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4010 if (pinfos != null && pinfos.Length > 0)
4011 { 4431 {
4012 foreach (PresenceInfo p in pinfos) 4432 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4433 if (pinfos != null && pinfos.Length > 0)
4013 { 4434 {
4014 if (p.RegionID != UUID.Zero) 4435 foreach (PresenceInfo p in pinfos)
4015 { 4436 {
4016 pinfo = p; 4437 if (p.RegionID != UUID.Zero)
4438 {
4439 pinfo = p;
4440 }
4017 } 4441 }
4018 } 4442 }
4019 } 4443 else
4020 else 4444 pinfo = null;
4021 pinfo = null;
4022 4445
4023 ce.time = Util.EnvironmentTickCount(); 4446 ce.time = Util.EnvironmentTickCount();
4024 ce.pinfo = pinfo; 4447 ce.pinfo = pinfo;
4025 } 4448 }
4026 4449
4027 string reply = String.Empty; 4450 string reply = String.Empty;
4028 4451
4029 switch (data) 4452 switch (data)
4030 { 4453 {
4031 case 1: // DATA_ONLINE (0|1) 4454 case 1: // DATA_ONLINE (0|1)
4032 if (pinfo != null && pinfo.RegionID != UUID.Zero) 4455 if (pinfo != null && pinfo.RegionID != UUID.Zero)
4033 reply = "1"; 4456 reply = "1";
4034 else 4457 else
4035 reply = "0"; 4458 reply = "0";
4036 break; 4459 break;
4037 case 2: // DATA_NAME (First Last) 4460 case 2: // DATA_NAME (First Last)
4038 reply = account.FirstName + " " + account.LastName; 4461 reply = account.FirstName + " " + account.LastName;
4039 break; 4462 break;
4040 case 3: // DATA_BORN (YYYY-MM-DD) 4463 case 3: // DATA_BORN (YYYY-MM-DD)
4041 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); 4464 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
4042 born = born.AddSeconds(account.Created); 4465 born = born.AddSeconds(account.Created);
4043 reply = born.ToString("yyyy-MM-dd"); 4466 reply = born.ToString("yyyy-MM-dd");
4044 break; 4467 break;
4045 case 4: // DATA_RATING (0,0,0,0,0,0) 4468 case 4: // DATA_RATING (0,0,0,0,0,0)
4046 reply = "0,0,0,0,0,0"; 4469 reply = "0,0,0,0,0,0";
4047 break; 4470 break;
4048 case 8: // DATA_PAYINFO (0|1|2|3) 4471 case 8: // DATA_PAYINFO (0|1|2|3)
4049 reply = "0"; 4472 reply = "0";
4050 break; 4473 break;
4051 default: 4474 default:
4052 return UUID.Zero.ToString(); // Raise no event 4475 return UUID.Zero.ToString(); // Raise no event
4053 } 4476 }
4054 4477
4055 UUID rq = UUID.Random(); 4478 UUID rq = UUID.Random();
4056 4479
4057 UUID tid = AsyncCommands. 4480 UUID tid = AsyncCommands.
4058 DataserverPlugin.RegisterRequest(m_localID, 4481 DataserverPlugin.RegisterRequest(m_localID,
4059 m_itemID, rq.ToString()); 4482 m_itemID, rq.ToString());
4060 4483
4061 AsyncCommands. 4484 AsyncCommands.
4062 DataserverPlugin.DataserverReply(rq.ToString(), reply); 4485 DataserverPlugin.DataserverReply(rq.ToString(), reply);
4063 4486
4064 ScriptSleep(100); 4487 ScriptSleep(100);
4065 return tid.ToString(); 4488 return tid.ToString();
4489 }
4490 else
4491 {
4492 ShoutError("Invalid UUID passed to llRequestAgentData.");
4493 }
4494 return "";
4066 } 4495 }
4067 4496
4068 public LSL_String llRequestInventoryData(string name) 4497 public LSL_String llRequestInventoryData(string name)
4069 { 4498 {
4070 m_host.AddScriptLPS(1); 4499 m_host.AddScriptLPS(1);
4071 4500
4501 //Clone is thread safe
4072 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 4502 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
4073 4503
4074 foreach (TaskInventoryItem item in itemDictionary.Values) 4504 foreach (TaskInventoryItem item in itemDictionary.Values)
@@ -4122,6 +4552,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4122 ScenePresence presence = World.GetScenePresence(agentId); 4552 ScenePresence presence = World.GetScenePresence(agentId);
4123 if (presence != null) 4553 if (presence != null)
4124 { 4554 {
4555 // agent must not be a god
4556 if (presence.UserLevel >= 200) return;
4557
4125 // agent must be over the owners land 4558 // agent must be over the owners land
4126 if (m_host.OwnerID == World.LandChannel.GetLandObject( 4559 if (m_host.OwnerID == World.LandChannel.GetLandObject(
4127 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) 4560 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
@@ -4144,7 +4577,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4144 UUID av = new UUID(); 4577 UUID av = new UUID();
4145 if (!UUID.TryParse(agent,out av)) 4578 if (!UUID.TryParse(agent,out av))
4146 { 4579 {
4147 LSLError("First parameter to llDialog needs to be a key"); 4580 //LSLError("First parameter to llDialog needs to be a key");
4148 return; 4581 return;
4149 } 4582 }
4150 4583
@@ -4181,17 +4614,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4181 UUID soundId = UUID.Zero; 4614 UUID soundId = UUID.Zero;
4182 if (!UUID.TryParse(impact_sound, out soundId)) 4615 if (!UUID.TryParse(impact_sound, out soundId))
4183 { 4616 {
4184 lock (m_host.TaskInventory) 4617 m_host.TaskInventory.LockItemsForRead(true);
4618 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
4185 { 4619 {
4186 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4620 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound)
4187 { 4621 {
4188 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound) 4622 soundId = item.AssetID;
4189 { 4623 break;
4190 soundId = item.AssetID;
4191 break;
4192 }
4193 } 4624 }
4194 } 4625 }
4626 m_host.TaskInventory.LockItemsForRead(false);
4195 } 4627 }
4196 m_host.CollisionSound = soundId; 4628 m_host.CollisionSound = soundId;
4197 m_host.CollisionSoundVolume = (float)impact_volume; 4629 m_host.CollisionSoundVolume = (float)impact_volume;
@@ -4231,6 +4663,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4231 UUID partItemID; 4663 UUID partItemID;
4232 foreach (SceneObjectPart part in parts) 4664 foreach (SceneObjectPart part in parts)
4233 { 4665 {
4666 //Clone is thread safe
4234 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); 4667 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
4235 4668
4236 foreach (TaskInventoryItem item in itemsDictionary.Values) 4669 foreach (TaskInventoryItem item in itemsDictionary.Values)
@@ -4445,17 +4878,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4445 4878
4446 m_host.AddScriptLPS(1); 4879 m_host.AddScriptLPS(1);
4447 4880
4448 lock (m_host.TaskInventory) 4881 m_host.TaskInventory.LockItemsForRead(true);
4882 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
4449 { 4883 {
4450 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4884 if (item.Type == 10 && item.ItemID == m_itemID)
4451 { 4885 {
4452 if (item.Type == 10 && item.ItemID == m_itemID) 4886 result = item.Name!=null?item.Name:String.Empty;
4453 { 4887 break;
4454 result = item.Name != null ? item.Name : String.Empty;
4455 break;
4456 }
4457 } 4888 }
4458 } 4889 }
4890 m_host.TaskInventory.LockItemsForRead(false);
4459 4891
4460 return result; 4892 return result;
4461 } 4893 }
@@ -4624,23 +5056,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4624 { 5056 {
4625 m_host.AddScriptLPS(1); 5057 m_host.AddScriptLPS(1);
4626 5058
4627 lock (m_host.TaskInventory) 5059 m_host.TaskInventory.LockItemsForRead(true);
5060 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
4628 { 5061 {
4629 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 5062 if (inv.Value.Name == name)
4630 { 5063 {
4631 if (inv.Value.Name == name) 5064 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
4632 { 5065 {
4633 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) 5066 m_host.TaskInventory.LockItemsForRead(false);
4634 { 5067 return inv.Value.AssetID.ToString();
4635 return inv.Value.AssetID.ToString(); 5068 }
4636 } 5069 else
4637 else 5070 {
4638 { 5071 m_host.TaskInventory.LockItemsForRead(false);
4639 return UUID.Zero.ToString(); 5072 return UUID.Zero.ToString();
4640 }
4641 } 5073 }
4642 } 5074 }
4643 } 5075 }
5076 m_host.TaskInventory.LockItemsForRead(false);
4644 5077
4645 return UUID.Zero.ToString(); 5078 return UUID.Zero.ToString();
4646 } 5079 }
@@ -4793,14 +5226,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4793 { 5226 {
4794 m_host.AddScriptLPS(1); 5227 m_host.AddScriptLPS(1);
4795 5228
4796 if (src == null) 5229 return src.Length;
4797 {
4798 return 0;
4799 }
4800 else
4801 {
4802 return src.Length;
4803 }
4804 } 5230 }
4805 5231
4806 public LSL_Integer llList2Integer(LSL_List src, int index) 5232 public LSL_Integer llList2Integer(LSL_List src, int index)
@@ -4846,7 +5272,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4846 else if (src.Data[index] is LSL_Float) 5272 else if (src.Data[index] is LSL_Float)
4847 return Convert.ToDouble(((LSL_Float) src.Data[index]).value); 5273 return Convert.ToDouble(((LSL_Float) src.Data[index]).value);
4848 else if (src.Data[index] is LSL_String) 5274 else if (src.Data[index] is LSL_String)
4849 return Convert.ToDouble(((LSL_String) src.Data[index]).m_string); 5275 {
5276 string str = ((LSL_String) src.Data[index]).m_string;
5277 Match m = Regex.Match(str, "^\\s*(-?\\+?[,0-9]+\\.?[0-9]*)");
5278 if (m != Match.Empty)
5279 {
5280 str = m.Value;
5281 double d = 0.0;
5282 if (!Double.TryParse(str, out d))
5283 return 0.0;
5284
5285 return d;
5286 }
5287 return 0.0;
5288 }
4850 return Convert.ToDouble(src.Data[index]); 5289 return Convert.ToDouble(src.Data[index]);
4851 } 5290 }
4852 catch (FormatException) 5291 catch (FormatException)
@@ -5050,7 +5489,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5050 } 5489 }
5051 } 5490 }
5052 5491
5053 result.Add(src.Substring(start,length).Trim()); 5492 result.Add(new LSL_String(src.Substring(start,length).Trim()));
5054 5493
5055 return result; 5494 return result;
5056 } 5495 }
@@ -5119,7 +5558,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5119 } 5558 }
5120 } 5559 }
5121 } 5560 }
5122 else { 5561 else
5562 {
5123 object[] array = new object[src.Length]; 5563 object[] array = new object[src.Length];
5124 Array.Copy(src.Data, 0, array, 0, src.Length); 5564 Array.Copy(src.Data, 0, array, 0, src.Length);
5125 result = new LSL_List(array); 5565 result = new LSL_List(array);
@@ -5570,10 +6010,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5570 m_host.AddScriptLPS(1); 6010 m_host.AddScriptLPS(1);
5571 6011
5572 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6012 List<SceneObjectPart> parts = GetLinkParts(linknumber);
5573 6013 if (parts.Count > 0)
5574 foreach (var part in parts)
5575 { 6014 {
5576 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); 6015 try
6016 {
6017 parts[0].ParentGroup.areUpdatesSuspended = true;
6018 foreach (var part in parts)
6019 {
6020 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6021 }
6022 }
6023 finally
6024 {
6025 parts[0].ParentGroup.areUpdatesSuspended = false;
6026 }
5577 } 6027 }
5578 } 6028 }
5579 6029
@@ -5627,6 +6077,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5627 ScriptSleep(5000); 6077 ScriptSleep(5000);
5628 } 6078 }
5629 6079
6080 public LSL_List llParseString2List(string str, LSL_List separators, LSL_List in_spacers)
6081 {
6082 return ParseString2List(str, separators, in_spacers, false);
6083 }
6084
5630 public LSL_Integer llOverMyLand(string id) 6085 public LSL_Integer llOverMyLand(string id)
5631 { 6086 {
5632 m_host.AddScriptLPS(1); 6087 m_host.AddScriptLPS(1);
@@ -5827,7 +6282,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5827 return m_host.ParentGroup.RootPart.AttachmentPoint; 6282 return m_host.ParentGroup.RootPart.AttachmentPoint;
5828 } 6283 }
5829 6284
5830 public LSL_Integer llGetFreeMemory() 6285 public virtual LSL_Integer llGetFreeMemory()
5831 { 6286 {
5832 m_host.AddScriptLPS(1); 6287 m_host.AddScriptLPS(1);
5833 // Make scripts designed for LSO happy 6288 // Make scripts designed for LSO happy
@@ -5944,7 +6399,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5944 SetParticleSystem(m_host, rules); 6399 SetParticleSystem(m_host, rules);
5945 } 6400 }
5946 6401
5947 private void SetParticleSystem(SceneObjectPart part, LSL_List rules) { 6402 private void SetParticleSystem(SceneObjectPart part, LSL_List rules)
6403 {
5948 6404
5949 6405
5950 if (rules.Length == 0) 6406 if (rules.Length == 0)
@@ -6138,14 +6594,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6138 6594
6139 protected UUID GetTaskInventoryItem(string name) 6595 protected UUID GetTaskInventoryItem(string name)
6140 { 6596 {
6141 lock (m_host.TaskInventory) 6597 m_host.TaskInventory.LockItemsForRead(true);
6598 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6142 { 6599 {
6143 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 6600 if (inv.Value.Name == name)
6144 { 6601 {
6145 if (inv.Value.Name == name) 6602 m_host.TaskInventory.LockItemsForRead(false);
6146 return inv.Key; 6603 return inv.Key;
6147 } 6604 }
6148 } 6605 }
6606 m_host.TaskInventory.LockItemsForRead(false);
6149 6607
6150 return UUID.Zero; 6608 return UUID.Zero;
6151 } 6609 }
@@ -6395,13 +6853,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6395 UUID av = new UUID(); 6853 UUID av = new UUID();
6396 if (!UUID.TryParse(avatar,out av)) 6854 if (!UUID.TryParse(avatar,out av))
6397 { 6855 {
6398 LSLError("First parameter to llDialog needs to be a key"); 6856 //LSLError("First parameter to llDialog needs to be a key");
6399 return; 6857 return;
6400 } 6858 }
6401 if (buttons.Length < 1) 6859 if (buttons.Length < 1)
6402 { 6860 {
6403 LSLError("No less than 1 button can be shown"); 6861 buttons.Add("OK");
6404 return;
6405 } 6862 }
6406 if (buttons.Length > 12) 6863 if (buttons.Length > 12)
6407 { 6864 {
@@ -6418,7 +6875,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6418 } 6875 }
6419 if (buttons.Data[i].ToString().Length > 24) 6876 if (buttons.Data[i].ToString().Length > 24)
6420 { 6877 {
6421 LSLError("button label cannot be longer than 24 characters"); 6878 llWhisper(ScriptBaseClass.DEBUG_CHANNEL, "button label cannot be longer than 24 characters");
6422 return; 6879 return;
6423 } 6880 }
6424 buts[i] = buttons.Data[i].ToString(); 6881 buts[i] = buttons.Data[i].ToString();
@@ -6482,22 +6939,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6482 } 6939 }
6483 6940
6484 // copy the first script found with this inventory name 6941 // copy the first script found with this inventory name
6485 lock (m_host.TaskInventory) 6942 TaskInventoryItem scriptItem = null;
6943 m_host.TaskInventory.LockItemsForRead(true);
6944 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6486 { 6945 {
6487 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 6946 if (inv.Value.Name == name)
6488 { 6947 {
6489 if (inv.Value.Name == name) 6948 // make sure the object is a script
6949 if (10 == inv.Value.Type)
6490 { 6950 {
6491 // make sure the object is a script 6951 found = true;
6492 if (10 == inv.Value.Type) 6952 srcId = inv.Key;
6493 { 6953 scriptItem = inv.Value;
6494 found = true; 6954 break;
6495 srcId = inv.Key;
6496 break;
6497 }
6498 } 6955 }
6499 } 6956 }
6500 } 6957 }
6958 m_host.TaskInventory.LockItemsForRead(false);
6501 6959
6502 if (!found) 6960 if (!found)
6503 { 6961 {
@@ -6505,8 +6963,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6505 return; 6963 return;
6506 } 6964 }
6507 6965
6508 // the rest of the permission checks are done in RezScript, so check the pin there as well 6966 SceneObjectPart dest = World.GetSceneObjectPart(destId);
6509 World.RezScript(srcId, m_host, destId, pin, running, start_param); 6967 if (dest != null)
6968 {
6969 if ((scriptItem.BasePermissions & (uint)PermissionMask.Transfer) != 0 || dest.ParentGroup.RootPart.OwnerID == m_host.ParentGroup.RootPart.OwnerID)
6970 {
6971 // the rest of the permission checks are done in RezScript, so check the pin there as well
6972 World.RezScript(srcId, m_host, destId, pin, running, start_param);
6973
6974 if ((scriptItem.BasePermissions & (uint)PermissionMask.Copy) == 0)
6975 m_host.Inventory.RemoveInventoryItem(srcId);
6976 }
6977 }
6510 // this will cause the delay even if the script pin or permissions were wrong - seems ok 6978 // this will cause the delay even if the script pin or permissions were wrong - seems ok
6511 ScriptSleep(3000); 6979 ScriptSleep(3000);
6512 } 6980 }
@@ -6569,18 +7037,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6569 public LSL_String llMD5String(string src, int nonce) 7037 public LSL_String llMD5String(string src, int nonce)
6570 { 7038 {
6571 m_host.AddScriptLPS(1); 7039 m_host.AddScriptLPS(1);
6572 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString())); 7040 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString()), Encoding.UTF8);
6573 } 7041 }
6574 7042
6575 public LSL_String llSHA1String(string src) 7043 public LSL_String llSHA1String(string src)
6576 { 7044 {
6577 m_host.AddScriptLPS(1); 7045 m_host.AddScriptLPS(1);
6578 return Util.SHA1Hash(src).ToLower(); 7046 return Util.SHA1Hash(src, Encoding.UTF8).ToLower();
6579 } 7047 }
6580 7048
6581 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist) 7049 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist)
6582 { 7050 {
6583 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7051 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7052 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7053 return shapeBlock;
6584 7054
6585 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && 7055 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
6586 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && 7056 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
@@ -6656,6 +7126,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6656 7126
6657 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte fudge) 7127 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte fudge)
6658 { 7128 {
7129 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7130 return;
7131
6659 ObjectShapePacket.ObjectDataBlock shapeBlock; 7132 ObjectShapePacket.ObjectDataBlock shapeBlock;
6660 7133
6661 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist); 7134 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist);
@@ -6705,6 +7178,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6705 7178
6706 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte fudge) 7179 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte fudge)
6707 { 7180 {
7181 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7182 return;
7183
6708 ObjectShapePacket.ObjectDataBlock shapeBlock; 7184 ObjectShapePacket.ObjectDataBlock shapeBlock;
6709 7185
6710 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist); 7186 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist);
@@ -6747,6 +7223,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6747 7223
6748 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) 7224 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)
6749 { 7225 {
7226 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7227 return;
7228
6750 ObjectShapePacket.ObjectDataBlock shapeBlock; 7229 ObjectShapePacket.ObjectDataBlock shapeBlock;
6751 7230
6752 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist); 7231 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist);
@@ -6873,6 +7352,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6873 7352
6874 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type) 7353 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type)
6875 { 7354 {
7355 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7356 return;
7357
6876 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7358 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
6877 UUID sculptId; 7359 UUID sculptId;
6878 7360
@@ -6888,13 +7370,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6888 shapeBlock.PathScaleX = 100; 7370 shapeBlock.PathScaleX = 100;
6889 shapeBlock.PathScaleY = 150; 7371 shapeBlock.PathScaleY = 150;
6890 7372
6891 if (type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_CYLINDER && 7373 if ((type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_CYLINDER) == 0 &&
6892 type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_PLANE && 7374 (type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_PLANE) == 0 &&
6893 type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE && 7375 (type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE) == 0 &&
6894 type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS) 7376 (type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS) == 0)
6895 { 7377 {
6896 // default 7378 // default
6897 type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE; 7379 type = type | (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
6898 } 7380 }
6899 7381
6900 // retain pathcurve 7382 // retain pathcurve
@@ -6913,32 +7395,87 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6913 ScriptSleep(200); 7395 ScriptSleep(200);
6914 } 7396 }
6915 7397
6916 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) 7398 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
6917 { 7399 {
6918 m_host.AddScriptLPS(1); 7400 m_host.AddScriptLPS(1);
6919 7401
6920 List<SceneObjectPart> parts = GetLinkParts(linknumber); 7402 List<SceneObjectPart> parts = GetLinkParts(linknumber);
7403 List<ScenePresence> avatars = GetLinkAvatars(linknumber);
7404 if (parts.Count>0)
7405 {
7406 try
7407 {
7408 parts[0].ParentGroup.areUpdatesSuspended = true;
7409 foreach (SceneObjectPart part in parts)
7410 SetPrimParams(part, rules);
7411 }
7412 finally
7413 {
7414 parts[0].ParentGroup.areUpdatesSuspended = false;
7415 }
7416 }
7417 if (avatars.Count > 0)
7418 {
7419 foreach (ScenePresence avatar in avatars)
7420 SetPrimParams(avatar, rules);
7421 }
7422 }
6921 7423
6922 foreach (SceneObjectPart part in parts) 7424 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
6923 SetPrimParams(part, rules); 7425 {
6924 7426 llSetLinkPrimitiveParamsFast(linknumber, rules);
6925 ScriptSleep(200); 7427 ScriptSleep(200);
6926 } 7428 }
6927 7429
6928 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) 7430 protected void SetPrimParams(ScenePresence av, LSL_List rules)
6929 { 7431 {
6930 m_host.AddScriptLPS(1); 7432 //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset.
7433 //We only support PRIM_POSITION and PRIM_ROTATION
6931 7434
6932 List<SceneObjectPart> parts = GetLinkParts(linknumber); 7435 int idx = 0;
6933 7436
6934 foreach (SceneObjectPart part in parts) 7437 while (idx < rules.Length)
6935 SetPrimParams(part, rules); 7438 {
7439 int code = rules.GetLSLIntegerItem(idx++);
7440
7441 int remain = rules.Length - idx;
7442
7443
7444
7445 switch (code)
7446 {
7447 case (int)ScriptBaseClass.PRIM_POSITION:
7448 if (remain < 1)
7449 return;
7450 LSL_Vector v;
7451 v = rules.GetVector3Item(idx++);
7452 av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
7453 av.SendAvatarDataToAllAgents();
7454
7455 break;
7456
7457 case (int)ScriptBaseClass.PRIM_ROTATION:
7458 if (remain < 1)
7459 return;
7460 LSL_Rotation r;
7461 r = rules.GetQuaternionItem(idx++);
7462 av.OffsetRotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
7463 av.SendAvatarDataToAllAgents();
7464 break;
7465 }
7466 }
6936 } 7467 }
6937 7468
6938 protected void SetPrimParams(SceneObjectPart part, LSL_List rules) 7469 protected void SetPrimParams(SceneObjectPart part, LSL_List rules)
6939 { 7470 {
7471 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7472 return;
7473
6940 int idx = 0; 7474 int idx = 0;
6941 7475
7476 bool positionChanged = false;
7477 LSL_Vector currentPosition = GetPartLocalPos(part);
7478
6942 while (idx < rules.Length) 7479 while (idx < rules.Length)
6943 { 7480 {
6944 int code = rules.GetLSLIntegerItem(idx++); 7481 int code = rules.GetLSLIntegerItem(idx++);
@@ -6947,7 +7484,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6947 7484
6948 int face; 7485 int face;
6949 LSL_Vector v; 7486 LSL_Vector v;
6950 7487
6951 switch (code) 7488 switch (code)
6952 { 7489 {
6953 case (int)ScriptBaseClass.PRIM_POSITION: 7490 case (int)ScriptBaseClass.PRIM_POSITION:
@@ -6955,7 +7492,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6955 return; 7492 return;
6956 7493
6957 v=rules.GetVector3Item(idx++); 7494 v=rules.GetVector3Item(idx++);
6958 SetPos(part, v); 7495 positionChanged = true;
7496 currentPosition = GetSetPosTarget(part, v, currentPosition);
6959 7497
6960 break; 7498 break;
6961 case (int)ScriptBaseClass.PRIM_SIZE: 7499 case (int)ScriptBaseClass.PRIM_SIZE:
@@ -7323,6 +7861,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7323 break; 7861 break;
7324 } 7862 }
7325 } 7863 }
7864
7865 if (positionChanged)
7866 {
7867 if (part.ParentGroup.RootPart == part)
7868 {
7869 SceneObjectGroup parent = part.ParentGroup;
7870 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
7871 }
7872 else
7873 {
7874 part.OffsetPosition = new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z);
7875 SceneObjectGroup parent = part.ParentGroup;
7876 parent.HasGroupChanged = true;
7877 parent.ScheduleGroupForTerseUpdate();
7878 }
7879 }
7326 } 7880 }
7327 7881
7328 public LSL_String llStringToBase64(string str) 7882 public LSL_String llStringToBase64(string str)
@@ -7471,13 +8025,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7471 public LSL_Integer llGetNumberOfPrims() 8025 public LSL_Integer llGetNumberOfPrims()
7472 { 8026 {
7473 m_host.AddScriptLPS(1); 8027 m_host.AddScriptLPS(1);
7474 int avatarCount = 0; 8028 int avatarCount = m_host.ParentGroup.GetLinkedAvatars().Count;
7475 World.ForEachScenePresence(delegate(ScenePresence presence) 8029
7476 {
7477 if (!presence.IsChildAgent && presence.ParentID != 0 && m_host.ParentGroup.HasChildPrim(presence.ParentID))
7478 avatarCount++;
7479 });
7480
7481 return m_host.ParentGroup.PrimCount + avatarCount; 8030 return m_host.ParentGroup.PrimCount + avatarCount;
7482 } 8031 }
7483 8032
@@ -7493,55 +8042,98 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7493 m_host.AddScriptLPS(1); 8042 m_host.AddScriptLPS(1);
7494 UUID objID = UUID.Zero; 8043 UUID objID = UUID.Zero;
7495 LSL_List result = new LSL_List(); 8044 LSL_List result = new LSL_List();
8045
8046 // If the ID is not valid, return null result
7496 if (!UUID.TryParse(obj, out objID)) 8047 if (!UUID.TryParse(obj, out objID))
7497 { 8048 {
7498 result.Add(new LSL_Vector()); 8049 result.Add(new LSL_Vector());
7499 result.Add(new LSL_Vector()); 8050 result.Add(new LSL_Vector());
7500 return result; 8051 return result;
7501 } 8052 }
8053
8054 // Check if this is an attached prim. If so, replace
8055 // the UUID with the avatar UUID and report it's bounding box
8056 SceneObjectPart part = World.GetSceneObjectPart(objID);
8057 if (part != null && part.ParentGroup.IsAttachment)
8058 objID = part.ParentGroup.RootPart.AttachedAvatar;
8059
8060 // Find out if this is an avatar ID. If so, return it's box
7502 ScenePresence presence = World.GetScenePresence(objID); 8061 ScenePresence presence = World.GetScenePresence(objID);
7503 if (presence != null) 8062 if (presence != null)
7504 { 8063 {
7505 if (presence.ParentID == 0) // not sat on an object 8064 // As per LSL Wiki, there is no difference between sitting
8065 // and standing avatar since server 1.36
8066 LSL_Vector lower;
8067 LSL_Vector upper;
8068 if (presence.Animator.Animations.DefaultAnimation.AnimID
8069 == AnimationSet.Animations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
7506 { 8070 {
7507 LSL_Vector lower; 8071 // This is for ground sitting avatars
7508 LSL_Vector upper; 8072 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7509 if (presence.Animator.Animations.DefaultAnimation.AnimID 8073 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7510 == AnimationSet.Animations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) 8074 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7511 {
7512 // This is for ground sitting avatars
7513 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7514 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7515 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7516 }
7517 else
7518 {
7519 // This is for standing/flying avatars
7520 float height = presence.Appearance.AvatarHeight / 2.0f;
7521 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7522 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7523 }
7524 result.Add(lower);
7525 result.Add(upper);
7526 return result;
7527 } 8075 }
7528 else 8076 else
7529 { 8077 {
7530 // sitting on an object so we need the bounding box of that 8078 // This is for standing/flying avatars
7531 // which should include the avatar so set the UUID to the 8079 float height = presence.Appearance.AvatarHeight / 2.0f;
7532 // UUID of the object the avatar is sat on and allow it to fall through 8080 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7533 // to processing an object 8081 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7534 SceneObjectPart p = World.GetSceneObjectPart(presence.ParentID);
7535 objID = p.UUID;
7536 } 8082 }
8083
8084 // Adjust to the documented error offsets (see LSL Wiki)
8085 lower += new LSL_Vector(0.05f, 0.05f, 0.05f);
8086 upper -= new LSL_Vector(0.05f, 0.05f, 0.05f);
8087
8088 if (lower.x > upper.x)
8089 lower.x = upper.x;
8090 if (lower.y > upper.y)
8091 lower.y = upper.y;
8092 if (lower.z > upper.z)
8093 lower.z = upper.z;
8094
8095 result.Add(lower);
8096 result.Add(upper);
8097 return result;
7537 } 8098 }
7538 SceneObjectPart part = World.GetSceneObjectPart(objID); 8099
8100 part = World.GetSceneObjectPart(objID);
7539 // Currently only works for single prims without a sitting avatar 8101 // Currently only works for single prims without a sitting avatar
7540 if (part != null) 8102 if (part != null)
7541 { 8103 {
7542 Vector3 halfSize = part.Scale / 2.0f; 8104 float minX;
7543 LSL_Vector lower = new LSL_Vector(halfSize.X * -1.0f, halfSize.Y * -1.0f, halfSize.Z * -1.0f); 8105 float maxX;
7544 LSL_Vector upper = new LSL_Vector(halfSize.X, halfSize.Y, halfSize.Z); 8106 float minY;
8107 float maxY;
8108 float minZ;
8109 float maxZ;
8110
8111 // This BBox is in sim coordinates, with the offset being
8112 // a contained point.
8113 Vector3[] offsets = Scene.GetCombinedBoundingBox(new List<SceneObjectGroup> { part.ParentGroup },
8114 out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
8115
8116 minX -= offsets[0].X;
8117 maxX -= offsets[0].X;
8118 minY -= offsets[0].Y;
8119 maxY -= offsets[0].Y;
8120 minZ -= offsets[0].Z;
8121 maxZ -= offsets[0].Z;
8122
8123 LSL_Vector lower;
8124 LSL_Vector upper;
8125
8126 // Adjust to the documented error offsets (see LSL Wiki)
8127 lower = new LSL_Vector(minX + 0.05f, minY + 0.05f, minZ + 0.05f);
8128 upper = new LSL_Vector(maxX - 0.05f, maxY - 0.05f, maxZ - 0.05f);
8129
8130 if (lower.x > upper.x)
8131 lower.x = upper.x;
8132 if (lower.y > upper.y)
8133 lower.y = upper.y;
8134 if (lower.z > upper.z)
8135 lower.z = upper.z;
8136
7545 result.Add(lower); 8137 result.Add(lower);
7546 result.Add(upper); 8138 result.Add(upper);
7547 return result; 8139 return result;
@@ -7621,13 +8213,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7621 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X, 8213 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X,
7622 part.AbsolutePosition.Y, 8214 part.AbsolutePosition.Y,
7623 part.AbsolutePosition.Z); 8215 part.AbsolutePosition.Z);
7624 // For some reason, the part.AbsolutePosition.* values do not change if the
7625 // linkset is rotated; they always reflect the child prim's world position
7626 // as though the linkset is unrotated. This is incompatible behavior with SL's
7627 // implementation, so will break scripts imported from there (not to mention it
7628 // makes it more difficult to determine a child prim's actual inworld position).
7629 if (part.ParentID != 0)
7630 v = ((v - llGetRootPosition()) * llGetRootRotation()) + llGetRootPosition();
7631 res.Add(v); 8216 res.Add(v);
7632 break; 8217 break;
7633 8218
@@ -7788,56 +8373,92 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7788 case (int)ScriptBaseClass.PRIM_BUMP_SHINY: 8373 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
7789 if (remain < 1) 8374 if (remain < 1)
7790 return res; 8375 return res;
7791 8376 face = (int)rules.GetLSLIntegerItem(idx++);
7792 face=(int)rules.GetLSLIntegerItem(idx++);
7793 8377
7794 tex = part.Shape.Textures; 8378 tex = part.Shape.Textures;
8379 int shiny;
7795 if (face == ScriptBaseClass.ALL_SIDES) 8380 if (face == ScriptBaseClass.ALL_SIDES)
7796 { 8381 {
7797 for (face = 0; face < GetNumberOfSides(part); face++) 8382 for (face = 0; face < GetNumberOfSides(part); face++)
7798 { 8383 {
7799 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8384 Shininess shinyness = tex.GetFace((uint)face).Shiny;
7800 // Convert Shininess to PRIM_SHINY_* 8385 if (shinyness == Shininess.High)
7801 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8386 {
7802 // PRIM_BUMP_* 8387 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
7803 res.Add(new LSL_Integer((int)texface.Bump)); 8388 }
8389 else if (shinyness == Shininess.Medium)
8390 {
8391 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8392 }
8393 else if (shinyness == Shininess.Low)
8394 {
8395 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8396 }
8397 else
8398 {
8399 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8400 }
8401 res.Add(new LSL_Integer(shiny));
8402 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
7804 } 8403 }
7805 } 8404 }
7806 else 8405 else
7807 { 8406 {
7808 if (face >= 0 && face < GetNumberOfSides(part)) 8407 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8408 if (shinyness == Shininess.High)
7809 { 8409 {
7810 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8410 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
7811 // Convert Shininess to PRIM_SHINY_* 8411 }
7812 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8412 else if (shinyness == Shininess.Medium)
7813 // PRIM_BUMP_* 8413 {
7814 res.Add(new LSL_Integer((int)texface.Bump)); 8414 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8415 }
8416 else if (shinyness == Shininess.Low)
8417 {
8418 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8419 }
8420 else
8421 {
8422 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
7815 } 8423 }
8424 res.Add(new LSL_Integer(shiny));
8425 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
7816 } 8426 }
7817 break; 8427 break;
7818 8428
7819 case (int)ScriptBaseClass.PRIM_FULLBRIGHT: 8429 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
7820 if (remain < 1) 8430 if (remain < 1)
7821 return res; 8431 return res;
7822 8432 face = (int)rules.GetLSLIntegerItem(idx++);
7823 face=(int)rules.GetLSLIntegerItem(idx++);
7824 8433
7825 tex = part.Shape.Textures; 8434 tex = part.Shape.Textures;
8435 int fullbright;
7826 if (face == ScriptBaseClass.ALL_SIDES) 8436 if (face == ScriptBaseClass.ALL_SIDES)
7827 { 8437 {
7828 for (face = 0; face < GetNumberOfSides(part); face++) 8438 for (face = 0; face < GetNumberOfSides(part); face++)
7829 { 8439 {
7830 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8440 if (tex.GetFace((uint)face).Fullbright == true)
7831 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 8441 {
8442 fullbright = ScriptBaseClass.TRUE;
8443 }
8444 else
8445 {
8446 fullbright = ScriptBaseClass.FALSE;
8447 }
8448 res.Add(new LSL_Integer(fullbright));
7832 } 8449 }
7833 } 8450 }
7834 else 8451 else
7835 { 8452 {
7836 if (face >= 0 && face < GetNumberOfSides(part)) 8453 if (tex.GetFace((uint)face).Fullbright == true)
7837 { 8454 {
7838 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8455 fullbright = ScriptBaseClass.TRUE;
7839 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 8456 }
8457 else
8458 {
8459 fullbright = ScriptBaseClass.FALSE;
7840 } 8460 }
8461 res.Add(new LSL_Integer(fullbright));
7841 } 8462 }
7842 break; 8463 break;
7843 8464
@@ -7859,27 +8480,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7859 break; 8480 break;
7860 8481
7861 case (int)ScriptBaseClass.PRIM_TEXGEN: 8482 case (int)ScriptBaseClass.PRIM_TEXGEN:
8483 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
7862 if (remain < 1) 8484 if (remain < 1)
7863 return res; 8485 return res;
7864 8486 face = (int)rules.GetLSLIntegerItem(idx++);
7865 face=(int)rules.GetLSLIntegerItem(idx++);
7866 8487
7867 tex = part.Shape.Textures; 8488 tex = part.Shape.Textures;
7868 if (face == ScriptBaseClass.ALL_SIDES) 8489 if (face == ScriptBaseClass.ALL_SIDES)
7869 { 8490 {
7870 for (face = 0; face < GetNumberOfSides(part); face++) 8491 for (face = 0; face < GetNumberOfSides(part); face++)
7871 { 8492 {
7872 MappingType texgen = tex.GetFace((uint)face).TexMapType; 8493 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
7873 // Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc. 8494 {
7874 res.Add(new LSL_Integer((uint)texgen >> 1)); 8495 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8496 }
8497 else
8498 {
8499 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8500 }
7875 } 8501 }
7876 } 8502 }
7877 else 8503 else
7878 { 8504 {
7879 if (face >= 0 && face < GetNumberOfSides(part)) 8505 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8506 {
8507 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8508 }
8509 else
7880 { 8510 {
7881 MappingType texgen = tex.GetFace((uint)face).TexMapType; 8511 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
7882 res.Add(new LSL_Integer((uint)texgen >> 1));
7883 } 8512 }
7884 } 8513 }
7885 break; 8514 break;
@@ -7902,28 +8531,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7902 case (int)ScriptBaseClass.PRIM_GLOW: 8531 case (int)ScriptBaseClass.PRIM_GLOW:
7903 if (remain < 1) 8532 if (remain < 1)
7904 return res; 8533 return res;
7905 8534 face = (int)rules.GetLSLIntegerItem(idx++);
7906 face=(int)rules.GetLSLIntegerItem(idx++);
7907 8535
7908 tex = part.Shape.Textures; 8536 tex = part.Shape.Textures;
8537 float primglow;
7909 if (face == ScriptBaseClass.ALL_SIDES) 8538 if (face == ScriptBaseClass.ALL_SIDES)
7910 { 8539 {
7911 for (face = 0; face < GetNumberOfSides(part); face++) 8540 for (face = 0; face < GetNumberOfSides(part); face++)
7912 { 8541 {
7913 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8542 primglow = tex.GetFace((uint)face).Glow;
7914 res.Add(new LSL_Float(texface.Glow)); 8543 res.Add(new LSL_Float(primglow));
7915 } 8544 }
7916 } 8545 }
7917 else 8546 else
7918 { 8547 {
7919 if (face >= 0 && face < GetNumberOfSides(part)) 8548 primglow = tex.GetFace((uint)face).Glow;
7920 { 8549 res.Add(new LSL_Float(primglow));
7921 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
7922 res.Add(new LSL_Float(texface.Glow));
7923 }
7924 } 8550 }
7925 break; 8551 break;
7926
7927 case (int)ScriptBaseClass.PRIM_TEXT: 8552 case (int)ScriptBaseClass.PRIM_TEXT:
7928 Color4 textColor = part.GetTextColor(); 8553 Color4 textColor = part.GetTextColor();
7929 res.Add(part.Text); 8554 res.Add(part.Text);
@@ -8472,8 +9097,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8472 // The function returns an ordered list 9097 // The function returns an ordered list
8473 // representing the tokens found in the supplied 9098 // representing the tokens found in the supplied
8474 // sources string. If two successive tokenizers 9099 // sources string. If two successive tokenizers
8475 // are encountered, then a NULL entry is added 9100 // are encountered, then a null-string entry is
8476 // to the list. 9101 // added to the list.
8477 // 9102 //
8478 // It is a precondition that the source and 9103 // It is a precondition that the source and
8479 // toekizer lisst are non-null. If they are null, 9104 // toekizer lisst are non-null. If they are null,
@@ -8481,7 +9106,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8481 // while their lengths are being determined. 9106 // while their lengths are being determined.
8482 // 9107 //
8483 // A small amount of working memoryis required 9108 // A small amount of working memoryis required
8484 // of approximately 8*#tokenizers. 9109 // of approximately 8*#tokenizers + 8*srcstrlen.
8485 // 9110 //
8486 // There are many ways in which this function 9111 // There are many ways in which this function
8487 // can be implemented, this implementation is 9112 // can be implemented, this implementation is
@@ -8497,155 +9122,124 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8497 // and eliminates redundant tokenizers as soon 9122 // and eliminates redundant tokenizers as soon
8498 // as is possible. 9123 // as is possible.
8499 // 9124 //
8500 // The implementation tries to avoid any copying 9125 // The implementation tries to minimize temporary
8501 // of arrays or other objects. 9126 // garbage generation.
8502 // </remarks> 9127 // </remarks>
8503 9128
8504 private LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls) 9129 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8505 { 9130 {
8506 int beginning = 0; 9131 return ParseString2List(src, separators, spacers, true);
8507 int srclen = src.Length; 9132 }
8508 int seplen = separators.Length;
8509 object[] separray = separators.Data;
8510 int spclen = spacers.Length;
8511 object[] spcarray = spacers.Data;
8512 int mlen = seplen+spclen;
8513
8514 int[] offset = new int[mlen+1];
8515 bool[] active = new bool[mlen];
8516
8517 int best;
8518 int j;
8519
8520 // Initial capacity reduces resize cost
8521 9133
8522 LSL_List tokens = new LSL_List(); 9134 private LSL_List ParseString2List(string src, LSL_List separators, LSL_List spacers, bool keepNulls)
9135 {
9136 int srclen = src.Length;
9137 int seplen = separators.Length;
9138 object[] separray = separators.Data;
9139 int spclen = spacers.Length;
9140 object[] spcarray = spacers.Data;
9141 int dellen = 0;
9142 string[] delarray = new string[seplen+spclen];
8523 9143
8524 // All entries are initially valid 9144 int outlen = 0;
9145 string[] outarray = new string[srclen*2+1];
8525 9146
8526 for (int i = 0; i < mlen; i++) 9147 int i, j;
8527 active[i] = true; 9148 string d;
8528 9149
8529 offset[mlen] = srclen; 9150 m_host.AddScriptLPS(1);
8530 9151
8531 while (beginning < srclen) 9152 /*
9153 * Convert separator and spacer lists to C# strings.
9154 * Also filter out null strings so we don't hang.
9155 */
9156 for (i = 0; i < seplen; i ++)
8532 { 9157 {
9158 d = separray[i].ToString();
9159 if (d.Length > 0)
9160 {
9161 delarray[dellen++] = d;
9162 }
9163 }
9164 seplen = dellen;
8533 9165
8534 best = mlen; // as bad as it gets 9166 for (i = 0; i < spclen; i ++)
9167 {
9168 d = spcarray[i].ToString();
9169 if (d.Length > 0)
9170 {
9171 delarray[dellen++] = d;
9172 }
9173 }
8535 9174
8536 // Scan for separators 9175 /*
9176 * Scan through source string from beginning to end.
9177 */
9178 for (i = 0;;)
9179 {
8537 9180
8538 for (j = 0; j < seplen; j++) 9181 /*
9182 * Find earliest delimeter in src starting at i (if any).
9183 */
9184 int earliestDel = -1;
9185 int earliestSrc = srclen;
9186 string earliestStr = null;
9187 for (j = 0; j < dellen; j ++)
8539 { 9188 {
8540 if (separray[j].ToString() == String.Empty) 9189 d = delarray[j];
8541 active[j] = false; 9190 if (d != null)
8542
8543 if (active[j])
8544 { 9191 {
8545 // scan all of the markers 9192 int index = src.IndexOf(d, i);
8546 if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1) 9193 if (index < 0)
8547 { 9194 {
8548 // not present at all 9195 delarray[j] = null; // delim nowhere in src, don't check it anymore
8549 active[j] = false;
8550 } 9196 }
8551 else 9197 else if (index < earliestSrc)
8552 { 9198 {
8553 // present and correct 9199 earliestSrc = index; // where delimeter starts in source string
8554 if (offset[j] < offset[best]) 9200 earliestDel = j; // where delimeter is in delarray[]
8555 { 9201 earliestStr = d; // the delimeter string from delarray[]
8556 // closest so far 9202 if (index == i) break; // can't do any better than found at beg of string
8557 best = j;
8558 if (offset[best] == beginning)
8559 break;
8560 }
8561 } 9203 }
8562 } 9204 }
8563 } 9205 }
8564 9206
8565 // Scan for spacers 9207 /*
8566 9208 * Output source string starting at i through start of earliest delimeter.
8567 if (offset[best] != beginning) 9209 */
9210 if (keepNulls || (earliestSrc > i))
8568 { 9211 {
8569 for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) 9212 outarray[outlen++] = src.Substring(i, earliestSrc - i);
8570 {
8571 if (spcarray[j-seplen].ToString() == String.Empty)
8572 active[j] = false;
8573
8574 if (active[j])
8575 {
8576 // scan all of the markers
8577 if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1)
8578 {
8579 // not present at all
8580 active[j] = false;
8581 }
8582 else
8583 {
8584 // present and correct
8585 if (offset[j] < offset[best])
8586 {
8587 // closest so far
8588 best = j;
8589 }
8590 }
8591 }
8592 }
8593 } 9213 }
8594 9214
8595 // This is the normal exit from the scanning loop 9215 /*
9216 * If no delimeter found at or after i, we're done scanning.
9217 */
9218 if (earliestDel < 0) break;
8596 9219
8597 if (best == mlen) 9220 /*
9221 * If delimeter was a spacer, output the spacer.
9222 */
9223 if (earliestDel >= seplen)
8598 { 9224 {
8599 // no markers were found on this pass 9225 outarray[outlen++] = earliestStr;
8600 // so we're pretty much done
8601 if ((keepNulls) || ((!keepNulls) && (srclen - beginning) > 0))
8602 tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning)));
8603 break;
8604 } 9226 }
8605 9227
8606 // Otherwise we just add the newly delimited token 9228 /*
8607 // and recalculate where the search should continue. 9229 * Look at rest of src string following delimeter.
8608 if ((keepNulls) || ((!keepNulls) && (offset[best] - beginning) > 0)) 9230 */
8609 tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning))); 9231 i = earliestSrc + earliestStr.Length;
8610
8611 if (best < seplen)
8612 {
8613 beginning = offset[best] + (separray[best].ToString()).Length;
8614 }
8615 else
8616 {
8617 beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
8618 string str = spcarray[best - seplen].ToString();
8619 if ((keepNulls) || ((!keepNulls) && (str.Length > 0)))
8620 tokens.Add(new LSL_String(str));
8621 }
8622 } 9232 }
8623 9233
8624 // This an awkward an not very intuitive boundary case. If the 9234 /*
8625 // last substring is a tokenizer, then there is an implied trailing 9235 * Make up an exact-sized output array suitable for an LSL_List object.
8626 // null list entry. Hopefully the single comparison will not be too 9236 */
8627 // arduous. Alternatively the 'break' could be replced with a return 9237 object[] outlist = new object[outlen];
8628 // but that's shabby programming. 9238 for (i = 0; i < outlen; i ++)
8629
8630 if ((beginning == srclen) && (keepNulls))
8631 { 9239 {
8632 if (srclen != 0) 9240 outlist[i] = new LSL_String(outarray[i]);
8633 tokens.Add(new LSL_String(""));
8634 } 9241 }
8635 9242 return new LSL_List(outlist);
8636 return tokens;
8637 }
8638
8639 public LSL_List llParseString2List(string src, LSL_List separators, LSL_List spacers)
8640 {
8641 m_host.AddScriptLPS(1);
8642 return this.ParseString(src, separators, spacers, false);
8643 }
8644
8645 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8646 {
8647 m_host.AddScriptLPS(1);
8648 return this.ParseString(src, separators, spacers, true);
8649 } 9243 }
8650 9244
8651 public LSL_Integer llGetObjectPermMask(int mask) 9245 public LSL_Integer llGetObjectPermMask(int mask)
@@ -8722,28 +9316,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8722 { 9316 {
8723 m_host.AddScriptLPS(1); 9317 m_host.AddScriptLPS(1);
8724 9318
8725 lock (m_host.TaskInventory) 9319 m_host.TaskInventory.LockItemsForRead(true);
9320 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
8726 { 9321 {
8727 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9322 if (inv.Value.Name == item)
8728 { 9323 {
8729 if (inv.Value.Name == item) 9324 m_host.TaskInventory.LockItemsForRead(false);
9325 switch (mask)
8730 { 9326 {
8731 switch (mask) 9327 case 0:
8732 { 9328 return (int)inv.Value.BasePermissions;
8733 case 0: 9329 case 1:
8734 return (int)inv.Value.BasePermissions; 9330 return (int)inv.Value.CurrentPermissions;
8735 case 1: 9331 case 2:
8736 return (int)inv.Value.CurrentPermissions; 9332 return (int)inv.Value.GroupPermissions;
8737 case 2: 9333 case 3:
8738 return (int)inv.Value.GroupPermissions; 9334 return (int)inv.Value.EveryonePermissions;
8739 case 3: 9335 case 4:
8740 return (int)inv.Value.EveryonePermissions; 9336 return (int)inv.Value.NextPermissions;
8741 case 4:
8742 return (int)inv.Value.NextPermissions;
8743 }
8744 } 9337 }
8745 } 9338 }
8746 } 9339 }
9340 m_host.TaskInventory.LockItemsForRead(false);
8747 9341
8748 return -1; 9342 return -1;
8749 } 9343 }
@@ -8790,16 +9384,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8790 { 9384 {
8791 m_host.AddScriptLPS(1); 9385 m_host.AddScriptLPS(1);
8792 9386
8793 lock (m_host.TaskInventory) 9387 m_host.TaskInventory.LockItemsForRead(true);
9388 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
8794 { 9389 {
8795 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9390 if (inv.Value.Name == item)
8796 { 9391 {
8797 if (inv.Value.Name == item) 9392 m_host.TaskInventory.LockItemsForRead(false);
8798 { 9393 return inv.Value.CreatorID.ToString();
8799 return inv.Value.CreatorID.ToString();
8800 }
8801 } 9394 }
8802 } 9395 }
9396 m_host.TaskInventory.LockItemsForRead(false);
8803 9397
8804 llSay(0, "No item name '" + item + "'"); 9398 llSay(0, "No item name '" + item + "'");
8805 9399
@@ -8947,7 +9541,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8947 } 9541 }
8948 9542
8949 /// <summary> 9543 /// <summary>
8950 /// illListReplaceList removes the sub-list defined by the inclusive indices 9544 /// llListReplaceList removes the sub-list defined by the inclusive indices
8951 /// start and end and inserts the src list in its place. The inclusive 9545 /// start and end and inserts the src list in its place. The inclusive
8952 /// nature of the indices means that at least one element must be deleted 9546 /// nature of the indices means that at least one element must be deleted
8953 /// if the indices are within the bounds of the existing list. I.e. 2,2 9547 /// if the indices are within the bounds of the existing list. I.e. 2,2
@@ -9004,16 +9598,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9004 // based upon end. Note that if end exceeds the upper 9598 // based upon end. Note that if end exceeds the upper
9005 // bound in this case, the entire destination list 9599 // bound in this case, the entire destination list
9006 // is removed. 9600 // is removed.
9007 else 9601 else if (start == 0)
9008 { 9602 {
9009 if (end + 1 < dest.Length) 9603 if (end + 1 < dest.Length)
9010 {
9011 return src + dest.GetSublist(end + 1, -1); 9604 return src + dest.GetSublist(end + 1, -1);
9012 }
9013 else 9605 else
9014 {
9015 return src; 9606 return src;
9016 } 9607 }
9608 else // Start < 0
9609 {
9610 if (end + 1 < dest.Length)
9611 return dest.GetSublist(end + 1, -1);
9612 else
9613 return new LSL_List();
9017 } 9614 }
9018 } 9615 }
9019 // Finally, if start > end, we strip away a prefix and 9616 // Finally, if start > end, we strip away a prefix and
@@ -9064,17 +9661,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9064 int width = 0; 9661 int width = 0;
9065 int height = 0; 9662 int height = 0;
9066 9663
9067 ParcelMediaCommandEnum? commandToSend = null; 9664 uint commandToSend = 0;
9068 float time = 0.0f; // default is from start 9665 float time = 0.0f; // default is from start
9069 9666
9070 ScenePresence presence = null; 9667 ScenePresence presence = null;
9071 9668
9072 for (int i = 0; i < commandList.Data.Length; i++) 9669 for (int i = 0; i < commandList.Data.Length; i++)
9073 { 9670 {
9074 ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i]; 9671 uint command = (uint)(commandList.GetLSLIntegerItem(i));
9075 switch (command) 9672 switch (command)
9076 { 9673 {
9077 case ParcelMediaCommandEnum.Agent: 9674 case (uint)ParcelMediaCommandEnum.Agent:
9078 // we send only to one agent 9675 // we send only to one agent
9079 if ((i + 1) < commandList.Length) 9676 if ((i + 1) < commandList.Length)
9080 { 9677 {
@@ -9091,25 +9688,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9091 } 9688 }
9092 break; 9689 break;
9093 9690
9094 case ParcelMediaCommandEnum.Loop: 9691 case (uint)ParcelMediaCommandEnum.Loop:
9095 loop = 1; 9692 loop = 1;
9096 commandToSend = command; 9693 commandToSend = command;
9097 update = true; //need to send the media update packet to set looping 9694 update = true; //need to send the media update packet to set looping
9098 break; 9695 break;
9099 9696
9100 case ParcelMediaCommandEnum.Play: 9697 case (uint)ParcelMediaCommandEnum.Play:
9101 loop = 0; 9698 loop = 0;
9102 commandToSend = command; 9699 commandToSend = command;
9103 update = true; //need to send the media update packet to make sure it doesn't loop 9700 update = true; //need to send the media update packet to make sure it doesn't loop
9104 break; 9701 break;
9105 9702
9106 case ParcelMediaCommandEnum.Pause: 9703 case (uint)ParcelMediaCommandEnum.Pause:
9107 case ParcelMediaCommandEnum.Stop: 9704 case (uint)ParcelMediaCommandEnum.Stop:
9108 case ParcelMediaCommandEnum.Unload: 9705 case (uint)ParcelMediaCommandEnum.Unload:
9109 commandToSend = command; 9706 commandToSend = command;
9110 break; 9707 break;
9111 9708
9112 case ParcelMediaCommandEnum.Url: 9709 case (uint)ParcelMediaCommandEnum.Url:
9113 if ((i + 1) < commandList.Length) 9710 if ((i + 1) < commandList.Length)
9114 { 9711 {
9115 if (commandList.Data[i + 1] is LSL_String) 9712 if (commandList.Data[i + 1] is LSL_String)
@@ -9122,7 +9719,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9122 } 9719 }
9123 break; 9720 break;
9124 9721
9125 case ParcelMediaCommandEnum.Texture: 9722 case (uint)ParcelMediaCommandEnum.Texture:
9126 if ((i + 1) < commandList.Length) 9723 if ((i + 1) < commandList.Length)
9127 { 9724 {
9128 if (commandList.Data[i + 1] is LSL_String) 9725 if (commandList.Data[i + 1] is LSL_String)
@@ -9135,7 +9732,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9135 } 9732 }
9136 break; 9733 break;
9137 9734
9138 case ParcelMediaCommandEnum.Time: 9735 case (uint)ParcelMediaCommandEnum.Time:
9139 if ((i + 1) < commandList.Length) 9736 if ((i + 1) < commandList.Length)
9140 { 9737 {
9141 if (commandList.Data[i + 1] is LSL_Float) 9738 if (commandList.Data[i + 1] is LSL_Float)
@@ -9147,7 +9744,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9147 } 9744 }
9148 break; 9745 break;
9149 9746
9150 case ParcelMediaCommandEnum.AutoAlign: 9747 case (uint)ParcelMediaCommandEnum.AutoAlign:
9151 if ((i + 1) < commandList.Length) 9748 if ((i + 1) < commandList.Length)
9152 { 9749 {
9153 if (commandList.Data[i + 1] is LSL_Integer) 9750 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9161,7 +9758,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9161 } 9758 }
9162 break; 9759 break;
9163 9760
9164 case ParcelMediaCommandEnum.Type: 9761 case (uint)ParcelMediaCommandEnum.Type:
9165 if ((i + 1) < commandList.Length) 9762 if ((i + 1) < commandList.Length)
9166 { 9763 {
9167 if (commandList.Data[i + 1] is LSL_String) 9764 if (commandList.Data[i + 1] is LSL_String)
@@ -9174,7 +9771,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9174 } 9771 }
9175 break; 9772 break;
9176 9773
9177 case ParcelMediaCommandEnum.Desc: 9774 case (uint)ParcelMediaCommandEnum.Desc:
9178 if ((i + 1) < commandList.Length) 9775 if ((i + 1) < commandList.Length)
9179 { 9776 {
9180 if (commandList.Data[i + 1] is LSL_String) 9777 if (commandList.Data[i + 1] is LSL_String)
@@ -9187,7 +9784,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9187 } 9784 }
9188 break; 9785 break;
9189 9786
9190 case ParcelMediaCommandEnum.Size: 9787 case (uint)ParcelMediaCommandEnum.Size:
9191 if ((i + 2) < commandList.Length) 9788 if ((i + 2) < commandList.Length)
9192 { 9789 {
9193 if (commandList.Data[i + 1] is LSL_Integer) 9790 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9257,7 +9854,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9257 } 9854 }
9258 } 9855 }
9259 9856
9260 if (commandToSend != null) 9857 if (commandToSend != 0)
9261 { 9858 {
9262 // the commandList contained a start/stop/... command, too 9859 // the commandList contained a start/stop/... command, too
9263 if (presence == null) 9860 if (presence == null)
@@ -9294,7 +9891,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9294 9891
9295 if (aList.Data[i] != null) 9892 if (aList.Data[i] != null)
9296 { 9893 {
9297 switch ((ParcelMediaCommandEnum) aList.Data[i]) 9894 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString()))
9298 { 9895 {
9299 case ParcelMediaCommandEnum.Url: 9896 case ParcelMediaCommandEnum.Url:
9300 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL)); 9897 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL));
@@ -9337,16 +9934,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9337 { 9934 {
9338 m_host.AddScriptLPS(1); 9935 m_host.AddScriptLPS(1);
9339 9936
9340 lock (m_host.TaskInventory) 9937 m_host.TaskInventory.LockItemsForRead(true);
9938 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9341 { 9939 {
9342 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9940 if (inv.Value.Name == name)
9343 { 9941 {
9344 if (inv.Value.Name == name) 9942 m_host.TaskInventory.LockItemsForRead(false);
9345 { 9943 return inv.Value.Type;
9346 return inv.Value.Type;
9347 }
9348 } 9944 }
9349 } 9945 }
9946 m_host.TaskInventory.LockItemsForRead(false);
9350 9947
9351 return -1; 9948 return -1;
9352 } 9949 }
@@ -9357,15 +9954,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9357 9954
9358 if (quick_pay_buttons.Data.Length < 4) 9955 if (quick_pay_buttons.Data.Length < 4)
9359 { 9956 {
9360 LSLError("List must have at least 4 elements"); 9957 int x;
9361 return; 9958 for (x=quick_pay_buttons.Data.Length; x<= 4; x++)
9959 {
9960 quick_pay_buttons.Add(ScriptBaseClass.PAY_HIDE);
9961 }
9362 } 9962 }
9363 m_host.ParentGroup.RootPart.PayPrice[0]=price; 9963 int[] nPrice = new int[5];
9364 9964 nPrice[0] = price;
9365 m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; 9965 nPrice[1] = quick_pay_buttons.GetLSLIntegerItem(0);
9366 m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; 9966 nPrice[2] = quick_pay_buttons.GetLSLIntegerItem(1);
9367 m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; 9967 nPrice[3] = quick_pay_buttons.GetLSLIntegerItem(2);
9368 m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; 9968 nPrice[4] = quick_pay_buttons.GetLSLIntegerItem(3);
9969 m_host.ParentGroup.RootPart.PayPrice = nPrice;
9369 m_host.ParentGroup.HasGroupChanged = true; 9970 m_host.ParentGroup.HasGroupChanged = true;
9370 } 9971 }
9371 9972
@@ -9377,17 +9978,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9377 if (invItemID == UUID.Zero) 9978 if (invItemID == UUID.Zero)
9378 return new LSL_Vector(); 9979 return new LSL_Vector();
9379 9980
9380 lock (m_host.TaskInventory) 9981 m_host.TaskInventory.LockItemsForRead(true);
9982 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
9381 { 9983 {
9382 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) 9984 m_host.TaskInventory.LockItemsForRead(false);
9383 return new LSL_Vector(); 9985 return new LSL_Vector();
9986 }
9384 9987
9385 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) 9988 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
9386 { 9989 {
9387 ShoutError("No permissions to track the camera"); 9990 ShoutError("No permissions to track the camera");
9388 return new LSL_Vector(); 9991 m_host.TaskInventory.LockItemsForRead(false);
9389 } 9992 return new LSL_Vector();
9390 } 9993 }
9994 m_host.TaskInventory.LockItemsForRead(false);
9391 9995
9392 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 9996 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
9393 if (presence != null) 9997 if (presence != null)
@@ -9405,17 +10009,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9405 if (invItemID == UUID.Zero) 10009 if (invItemID == UUID.Zero)
9406 return new LSL_Rotation(); 10010 return new LSL_Rotation();
9407 10011
9408 lock (m_host.TaskInventory) 10012 m_host.TaskInventory.LockItemsForRead(true);
10013 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
9409 { 10014 {
9410 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) 10015 m_host.TaskInventory.LockItemsForRead(false);
9411 return new LSL_Rotation(); 10016 return new LSL_Rotation();
9412
9413 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
9414 {
9415 ShoutError("No permissions to track the camera");
9416 return new LSL_Rotation();
9417 }
9418 } 10017 }
10018 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
10019 {
10020 ShoutError("No permissions to track the camera");
10021 m_host.TaskInventory.LockItemsForRead(false);
10022 return new LSL_Rotation();
10023 }
10024 m_host.TaskInventory.LockItemsForRead(false);
9419 10025
9420 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10026 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
9421 if (presence != null) 10027 if (presence != null)
@@ -9477,8 +10083,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9477 { 10083 {
9478 m_host.AddScriptLPS(1); 10084 m_host.AddScriptLPS(1);
9479 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, 0); 10085 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, 0);
9480 if (detectedParams == null) return; // only works on the first detected avatar 10086 if (detectedParams == null)
9481 10087 {
10088 if (m_host.IsAttachment == true)
10089 {
10090 detectedParams = new DetectParams();
10091 detectedParams.Key = m_host.OwnerID;
10092 }
10093 else
10094 {
10095 return;
10096 }
10097 }
10098
9482 ScenePresence avatar = World.GetScenePresence(detectedParams.Key); 10099 ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
9483 if (avatar != null) 10100 if (avatar != null)
9484 { 10101 {
@@ -9486,6 +10103,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9486 new Vector3((float)pos.x, (float)pos.y, (float)pos.z), 10103 new Vector3((float)pos.x, (float)pos.y, (float)pos.z),
9487 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z)); 10104 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z));
9488 } 10105 }
10106
9489 ScriptSleep(1000); 10107 ScriptSleep(1000);
9490 } 10108 }
9491 10109
@@ -9578,14 +10196,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9578 if (objectID == UUID.Zero) return; 10196 if (objectID == UUID.Zero) return;
9579 10197
9580 UUID agentID; 10198 UUID agentID;
9581 lock (m_host.TaskInventory) 10199 m_host.TaskInventory.LockItemsForRead(true);
9582 { 10200 // we need the permission first, to know which avatar we want to set the camera for
9583 // we need the permission first, to know which avatar we want to set the camera for 10201 agentID = m_host.TaskInventory[invItemID].PermsGranter;
9584 agentID = m_host.TaskInventory[invItemID].PermsGranter;
9585 10202
9586 if (agentID == UUID.Zero) return; 10203 if (agentID == UUID.Zero)
9587 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return; 10204 {
10205 m_host.TaskInventory.LockItemsForRead(false);
10206 return;
9588 } 10207 }
10208 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0)
10209 {
10210 m_host.TaskInventory.LockItemsForRead(false);
10211 return;
10212 }
10213 m_host.TaskInventory.LockItemsForRead(false);
9589 10214
9590 ScenePresence presence = World.GetScenePresence(agentID); 10215 ScenePresence presence = World.GetScenePresence(agentID);
9591 10216
@@ -9594,12 +10219,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9594 10219
9595 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>(); 10220 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
9596 object[] data = rules.Data; 10221 object[] data = rules.Data;
9597 for (int i = 0; i < data.Length; ++i) { 10222 for (int i = 0; i < data.Length; ++i)
10223 {
9598 int type = Convert.ToInt32(data[i++].ToString()); 10224 int type = Convert.ToInt32(data[i++].ToString());
9599 if (i >= data.Length) break; // odd number of entries => ignore the last 10225 if (i >= data.Length) break; // odd number of entries => ignore the last
9600 10226
9601 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3) 10227 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
9602 switch (type) { 10228 switch (type)
10229 {
9603 case ScriptBaseClass.CAMERA_FOCUS: 10230 case ScriptBaseClass.CAMERA_FOCUS:
9604 case ScriptBaseClass.CAMERA_FOCUS_OFFSET: 10231 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
9605 case ScriptBaseClass.CAMERA_POSITION: 10232 case ScriptBaseClass.CAMERA_POSITION:
@@ -9635,12 +10262,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9635 10262
9636 // we need the permission first, to know which avatar we want to clear the camera for 10263 // we need the permission first, to know which avatar we want to clear the camera for
9637 UUID agentID; 10264 UUID agentID;
9638 lock (m_host.TaskInventory) 10265 m_host.TaskInventory.LockItemsForRead(true);
10266 agentID = m_host.TaskInventory[invItemID].PermsGranter;
10267 if (agentID == UUID.Zero)
9639 { 10268 {
9640 agentID = m_host.TaskInventory[invItemID].PermsGranter; 10269 m_host.TaskInventory.LockItemsForRead(false);
9641 if (agentID == UUID.Zero) return; 10270 return;
9642 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return;
9643 } 10271 }
10272 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0)
10273 {
10274 m_host.TaskInventory.LockItemsForRead(false);
10275 return;
10276 }
10277 m_host.TaskInventory.LockItemsForRead(false);
9644 10278
9645 ScenePresence presence = World.GetScenePresence(agentID); 10279 ScenePresence presence = World.GetScenePresence(agentID);
9646 10280
@@ -9707,19 +10341,65 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9707 public LSL_String llXorBase64StringsCorrect(string str1, string str2) 10341 public LSL_String llXorBase64StringsCorrect(string str1, string str2)
9708 { 10342 {
9709 m_host.AddScriptLPS(1); 10343 m_host.AddScriptLPS(1);
9710 string ret = String.Empty; 10344
9711 string src1 = llBase64ToString(str1); 10345 if (str1 == String.Empty)
9712 string src2 = llBase64ToString(str2); 10346 return String.Empty;
9713 int c = 0; 10347 if (str2 == String.Empty)
9714 for (int i = 0; i < src1.Length; i++) 10348 return str1;
10349
10350 int len = str2.Length;
10351 if ((len % 4) != 0) // LL is EVIL!!!!
10352 {
10353 while (str2.EndsWith("="))
10354 str2 = str2.Substring(0, str2.Length - 1);
10355
10356 len = str2.Length;
10357 int mod = len % 4;
10358
10359 if (mod == 1)
10360 str2 = str2.Substring(0, str2.Length - 1);
10361 else if (mod == 2)
10362 str2 += "==";
10363 else if (mod == 3)
10364 str2 += "=";
10365 }
10366
10367 byte[] data1;
10368 byte[] data2;
10369 try
9715 { 10370 {
9716 ret += (char) (src1[i] ^ src2[c]); 10371 data1 = Convert.FromBase64String(str1);
10372 data2 = Convert.FromBase64String(str2);
10373 }
10374 catch (Exception)
10375 {
10376 return new LSL_String(String.Empty);
10377 }
10378
10379 byte[] d2 = new Byte[data1.Length];
10380 int pos = 0;
10381
10382 if (data1.Length <= data2.Length)
10383 {
10384 Array.Copy(data2, 0, d2, 0, data1.Length);
10385 }
10386 else
10387 {
10388 while (pos < data1.Length)
10389 {
10390 len = data1.Length - pos;
10391 if (len > data2.Length)
10392 len = data2.Length;
9717 10393
9718 c++; 10394 Array.Copy(data2, 0, d2, pos, len);
9719 if (c >= src2.Length) 10395 pos += len;
9720 c = 0; 10396 }
9721 } 10397 }
9722 return llStringToBase64(ret); 10398
10399 for (pos = 0 ; pos < data1.Length ; pos++ )
10400 data1[pos] ^= d2[pos];
10401
10402 return Convert.ToBase64String(data1);
9723 } 10403 }
9724 10404
9725 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body) 10405 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
@@ -9778,12 +10458,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9778 Regex r = new Regex(authregex); 10458 Regex r = new Regex(authregex);
9779 int[] gnums = r.GetGroupNumbers(); 10459 int[] gnums = r.GetGroupNumbers();
9780 Match m = r.Match(url); 10460 Match m = r.Match(url);
9781 if (m.Success) { 10461 if (m.Success)
9782 for (int i = 1; i < gnums.Length; i++) { 10462 {
10463 for (int i = 1; i < gnums.Length; i++)
10464 {
9783 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]]; 10465 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]];
9784 //CaptureCollection cc = g.Captures; 10466 //CaptureCollection cc = g.Captures;
9785 } 10467 }
9786 if (m.Groups.Count == 5) { 10468 if (m.Groups.Count == 5)
10469 {
9787 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString()))); 10470 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString())));
9788 url = m.Groups[1].ToString() + m.Groups[4].ToString(); 10471 url = m.Groups[1].ToString() + m.Groups[4].ToString();
9789 } 10472 }
@@ -9895,7 +10578,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9895 { 10578 {
9896 foreach (KeyValuePair<UUID, int> detectedParams in land.GetLandObjectOwners()) 10579 foreach (KeyValuePair<UUID, int> detectedParams in land.GetLandObjectOwners())
9897 { 10580 {
9898 ret.Add(detectedParams.Key.ToString()); 10581 ret.Add(new LSL_String(detectedParams.Key.ToString()));
9899 ret.Add(detectedParams.Value); 10582 ret.Add(detectedParams.Value);
9900 } 10583 }
9901 } 10584 }
@@ -10064,15 +10747,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10064 10747
10065 internal UUID ScriptByName(string name) 10748 internal UUID ScriptByName(string name)
10066 { 10749 {
10067 lock (m_host.TaskInventory) 10750 m_host.TaskInventory.LockItemsForRead(true);
10751
10752 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
10068 { 10753 {
10069 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 10754 if (item.Type == 10 && item.Name == name)
10070 { 10755 {
10071 if (item.Type == 10 && item.Name == name) 10756 m_host.TaskInventory.LockItemsForRead(false);
10072 return item.ItemID; 10757 return item.ItemID;
10073 } 10758 }
10074 } 10759 }
10075 10760
10761 m_host.TaskInventory.LockItemsForRead(false);
10762
10076 return UUID.Zero; 10763 return UUID.Zero;
10077 } 10764 }
10078 10765
@@ -10113,6 +10800,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10113 { 10800 {
10114 m_host.AddScriptLPS(1); 10801 m_host.AddScriptLPS(1);
10115 10802
10803 //Clone is thread safe
10116 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 10804 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10117 10805
10118 UUID assetID = UUID.Zero; 10806 UUID assetID = UUID.Zero;
@@ -10175,6 +10863,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10175 { 10863 {
10176 m_host.AddScriptLPS(1); 10864 m_host.AddScriptLPS(1);
10177 10865
10866 //Clone is thread safe
10178 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 10867 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10179 10868
10180 UUID assetID = UUID.Zero; 10869 UUID assetID = UUID.Zero;
@@ -10255,15 +10944,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10255 return GetLinkPrimitiveParams(obj, rules); 10944 return GetLinkPrimitiveParams(obj, rules);
10256 } 10945 }
10257 10946
10258 public void print(string str) 10947 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
10259 { 10948 {
10260 // yes, this is a real LSL function. See: http://wiki.secondlife.com/wiki/Print 10949 List<SceneObjectPart> parts = GetLinkParts(link);
10261 IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_itemID, "OSSL"); 10950 if (parts.Count < 1)
10262 if (ossl != null) 10951 return 0;
10263 { 10952
10264 ossl.CheckThreatLevel(ThreatLevel.High, "print"); 10953 return GetNumberOfSides(parts[0]);
10265 m_log.Info("LSL print():" + str);
10266 }
10267 } 10954 }
10268 10955
10269 private string Name2Username(string name) 10956 private string Name2Username(string name)
@@ -10309,6 +10996,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10309 return rq.ToString(); 10996 return rq.ToString();
10310 } 10997 }
10311 10998
10999 private void SayShoutTimerElapsed(Object sender, ElapsedEventArgs args)
11000 {
11001 m_SayShoutCount = 0;
11002 }
11003
10312 #region Not Implemented 11004 #region Not Implemented
10313 // 11005 //
10314 // Listing the unimplemented lsl functions here, please move 11006 // Listing the unimplemented lsl functions here, please move
@@ -10335,11 +11027,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10335 11027
10336 } 11028 }
10337 11029
10338 public void llGetUsedMemory() 11030 public virtual LSL_Integer llGetUsedMemory()
10339 { 11031 {
10340 m_host.AddScriptLPS(1); 11032 m_host.AddScriptLPS(1);
10341 NotImplemented("llGetUsedMemory"); 11033 NotImplemented("llGetUsedMemory");
10342 11034 return 0;
10343 } 11035 }
10344 11036
10345 public void llRegionSayTo( LSL_Key target, LSL_Integer channel, LSL_String msg ) 11037 public void llRegionSayTo( LSL_Key target, LSL_Integer channel, LSL_String msg )
@@ -10352,14 +11044,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10352 public void llScriptProfiler( LSL_Integer flags ) 11044 public void llScriptProfiler( LSL_Integer flags )
10353 { 11045 {
10354 m_host.AddScriptLPS(1); 11046 m_host.AddScriptLPS(1);
10355 NotImplemented("llScriptProfiler"); 11047 //NotImplemented("llScriptProfiler");
10356 11048
10357 } 11049 }
10358 11050
10359 public void llSetSoundQueueing(int queue) 11051 public void llSetSoundQueueing(int queue)
10360 { 11052 {
10361 m_host.AddScriptLPS(1); 11053 m_host.AddScriptLPS(1);
10362 NotImplemented("llSetSoundQueueing");
10363 } 11054 }
10364 11055
10365 public void llCollisionSprite(string impact_sprite) 11056 public void llCollisionSprite(string impact_sprite)
@@ -10371,7 +11062,56 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10371 public void llGodLikeRezObject(string inventory, LSL_Vector pos) 11062 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
10372 { 11063 {
10373 m_host.AddScriptLPS(1); 11064 m_host.AddScriptLPS(1);
10374 NotImplemented("llGodLikeRezObject"); 11065
11066 if (!World.Permissions.IsGod(m_host.OwnerID))
11067 NotImplemented("llGodLikeRezObject");
11068
11069 AssetBase rezAsset = World.AssetService.Get(inventory);
11070 if (rezAsset == null)
11071 {
11072 llSay(0, "Asset not found");
11073 return;
11074 }
11075
11076 SceneObjectGroup group = null;
11077
11078 try
11079 {
11080 string xmlData = Utils.BytesToString(rezAsset.Data);
11081 group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
11082 }
11083 catch
11084 {
11085 llSay(0, "Asset not found");
11086 return;
11087 }
11088
11089 if (group == null)
11090 {
11091 llSay(0, "Asset not found");
11092 return;
11093 }
11094
11095 group.RootPart.AttachPoint = group.RootPart.Shape.State;
11096 group.RootPart.AttachOffset = group.AbsolutePosition;
11097
11098 group.ResetIDs();
11099
11100 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
11101 World.AddNewSceneObject(group, true, llpos, Quaternion.Identity, Vector3.Zero);
11102 group.CreateScriptInstances(0, true, World.DefaultScriptEngine, 3);
11103 group.ScheduleGroupForFullUpdate();
11104
11105 // objects rezzed with this method are die_at_edge by default.
11106 group.RootPart.SetDieAtEdge(true);
11107
11108 group.ResumeScripts();
11109
11110 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
11111 "object_rez", new Object[] {
11112 new LSL_String(
11113 group.RootPart.UUID.ToString()) },
11114 new DetectParams[0]));
10375 } 11115 }
10376 11116
10377 #endregion 11117 #endregion
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 64931d0..39e1a27 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -129,6 +129,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
129 internal ThreatLevel m_MaxThreatLevel = ThreatLevel.VeryLow; 129 internal ThreatLevel m_MaxThreatLevel = ThreatLevel.VeryLow;
130 internal float m_ScriptDelayFactor = 1.0f; 130 internal float m_ScriptDelayFactor = 1.0f;
131 internal float m_ScriptDistanceFactor = 1.0f; 131 internal float m_ScriptDistanceFactor = 1.0f;
132 internal bool m_debuggerSafe = false;
132 internal Dictionary<string, FunctionPerms > m_FunctionPerms = new Dictionary<string, FunctionPerms >(); 133 internal Dictionary<string, FunctionPerms > m_FunctionPerms = new Dictionary<string, FunctionPerms >();
133 134
134 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) 135 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID)
@@ -137,6 +138,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
137 m_host = host; 138 m_host = host;
138 m_localID = localID; 139 m_localID = localID;
139 m_itemID = itemID; 140 m_itemID = itemID;
141 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
140 142
141 if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false)) 143 if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false))
142 m_OSFunctionsEnabled = true; 144 m_OSFunctionsEnabled = true;
@@ -195,7 +197,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
195 197
196 internal void OSSLError(string msg) 198 internal void OSSLError(string msg)
197 { 199 {
198 throw new Exception("OSSL Runtime Error: " + msg); 200 if (m_debuggerSafe)
201 {
202 OSSLShoutError(msg);
203 }
204 else
205 {
206 throw new Exception("OSSL Runtime Error: " + msg);
207 }
199 } 208 }
200 209
201 private void InitLSL() 210 private void InitLSL()
@@ -831,18 +840,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
831 if (target != null) 840 if (target != null)
832 { 841 {
833 UUID animID=UUID.Zero; 842 UUID animID=UUID.Zero;
834 lock (m_host.TaskInventory) 843 m_host.TaskInventory.LockItemsForRead(true);
844 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
835 { 845 {
836 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 846 if (inv.Value.Name == animation)
837 { 847 {
838 if (inv.Value.Name == animation) 848 if (inv.Value.Type == (int)AssetType.Animation)
839 { 849 animID = inv.Value.AssetID;
840 if (inv.Value.Type == (int)AssetType.Animation) 850 continue;
841 animID = inv.Value.AssetID;
842 continue;
843 }
844 } 851 }
845 } 852 }
853 m_host.TaskInventory.LockItemsForRead(false);
846 if (animID == UUID.Zero) 854 if (animID == UUID.Zero)
847 target.Animator.AddAnimation(animation, m_host.UUID); 855 target.Animator.AddAnimation(animation, m_host.UUID);
848 else 856 else
@@ -864,18 +872,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
864 if (target != null) 872 if (target != null)
865 { 873 {
866 UUID animID=UUID.Zero; 874 UUID animID=UUID.Zero;
867 lock (m_host.TaskInventory) 875 m_host.TaskInventory.LockItemsForRead(true);
876 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
868 { 877 {
869 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 878 if (inv.Value.Name == animation)
870 { 879 {
871 if (inv.Value.Name == animation) 880 if (inv.Value.Type == (int)AssetType.Animation)
872 { 881 animID = inv.Value.AssetID;
873 if (inv.Value.Type == (int)AssetType.Animation) 882 continue;
874 animID = inv.Value.AssetID;
875 continue;
876 }
877 } 883 }
878 } 884 }
885 m_host.TaskInventory.LockItemsForRead(false);
879 886
880 if (animID == UUID.Zero) 887 if (animID == UUID.Zero)
881 target.Animator.RemoveAnimation(animation); 888 target.Animator.RemoveAnimation(animation);
@@ -1768,6 +1775,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1768 1775
1769 if (!UUID.TryParse(name, out assetID)) 1776 if (!UUID.TryParse(name, out assetID))
1770 { 1777 {
1778 m_host.TaskInventory.LockItemsForRead(true);
1771 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 1779 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
1772 { 1780 {
1773 if (item.Type == 7 && item.Name == name) 1781 if (item.Type == 7 && item.Name == name)
@@ -1775,6 +1783,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1775 assetID = item.AssetID; 1783 assetID = item.AssetID;
1776 } 1784 }
1777 } 1785 }
1786 m_host.TaskInventory.LockItemsForRead(false);
1778 } 1787 }
1779 1788
1780 if (assetID == UUID.Zero) 1789 if (assetID == UUID.Zero)
@@ -1821,6 +1830,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1821 1830
1822 if (!UUID.TryParse(name, out assetID)) 1831 if (!UUID.TryParse(name, out assetID))
1823 { 1832 {
1833 m_host.TaskInventory.LockItemsForRead(true);
1824 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 1834 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
1825 { 1835 {
1826 if (item.Type == 7 && item.Name == name) 1836 if (item.Type == 7 && item.Name == name)
@@ -1828,6 +1838,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1828 assetID = item.AssetID; 1838 assetID = item.AssetID;
1829 } 1839 }
1830 } 1840 }
1841 m_host.TaskInventory.LockItemsForRead(false);
1831 } 1842 }
1832 1843
1833 if (assetID == UUID.Zero) 1844 if (assetID == UUID.Zero)
@@ -1878,6 +1889,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1878 1889
1879 if (!UUID.TryParse(name, out assetID)) 1890 if (!UUID.TryParse(name, out assetID))
1880 { 1891 {
1892 m_host.TaskInventory.LockItemsForRead(true);
1881 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 1893 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
1882 { 1894 {
1883 if (item.Type == 7 && item.Name == name) 1895 if (item.Type == 7 && item.Name == name)
@@ -1885,6 +1897,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1885 assetID = item.AssetID; 1897 assetID = item.AssetID;
1886 } 1898 }
1887 } 1899 }
1900 m_host.TaskInventory.LockItemsForRead(false);
1888 } 1901 }
1889 1902
1890 if (assetID == UUID.Zero) 1903 if (assetID == UUID.Zero)
@@ -2364,9 +2377,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2364 { 2377 {
2365 if (avatar.IsChildAgent == false) 2378 if (avatar.IsChildAgent == false)
2366 { 2379 {
2367 result.Add(avatar.UUID); 2380 result.Add(new LSL_Key(avatar.UUID.ToString()));
2368 result.Add(avatar.AbsolutePosition); 2381 result.Add(new LSL_Vector(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z));
2369 result.Add(avatar.Name); 2382 result.Add(new LSL_String(avatar.Name));
2370 } 2383 }
2371 } 2384 }
2372 }); 2385 });
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
index e53a61a..d695a0c 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
@@ -205,7 +205,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
205 // Is the sensor type is AGENT and not SCRIPTED then include agents 205 // Is the sensor type is AGENT and not SCRIPTED then include agents
206 if ((ts.type & (AGENT | AGENT_BY_USERNAME)) != 0 && (ts.type & SCRIPTED) == 0) 206 if ((ts.type & (AGENT | AGENT_BY_USERNAME)) != 0 && (ts.type & SCRIPTED) == 0)
207 { 207 {
208 sensedEntities.AddRange(doAgentSensor(ts)); 208 sensedEntities.AddRange(doAgentSensor(ts));
209 } 209 }
210 210
211 // If SCRIPTED or PASSIVE or ACTIVE check objects 211 // If SCRIPTED or PASSIVE or ACTIVE check objects
@@ -302,13 +302,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
302 float dy; 302 float dy;
303 float dz; 303 float dz;
304 304
305 Quaternion q = SensePoint.RotationOffset; 305// Quaternion q = SensePoint.RotationOffset;
306 Quaternion q = SensePoint.GetWorldRotation(); // non-attached prim Sensor *always* uses World rotation!
306 if (SensePoint.ParentGroup.RootPart.IsAttachment) 307 if (SensePoint.ParentGroup.RootPart.IsAttachment)
307 { 308 {
308 // In attachments, the sensor cone always orients with the 309 // In attachments, the sensor cone always orients with the
309 // avatar rotation. This may include a nonzero elevation if 310 // avatar rotation. This may include a nonzero elevation if
310 // in mouselook. 311 // in mouselook.
311 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.RootPart.AttachedAvatar); 312 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.RootPart.AttachedAvatar);
313 fromRegionPos = avatar.AbsolutePosition;
312 q = avatar.Rotation; 314 q = avatar.Rotation;
313 } 315 }
314 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); 316 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W);
@@ -428,7 +430,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
428 // In attachments, the sensor cone always orients with the 430 // In attachments, the sensor cone always orients with the
429 // avatar rotation. This may include a nonzero elevation if 431 // avatar rotation. This may include a nonzero elevation if
430 // in mouselook. 432 // in mouselook.
433
431 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.RootPart.AttachedAvatar); 434 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.RootPart.AttachedAvatar);
435 fromRegionPos = avatar.AbsolutePosition;
432 q = avatar.Rotation; 436 q = avatar.Rotation;
433 } 437 }
434 438
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
new file mode 100644
index 0000000..ab215f3
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs
@@ -0,0 +1,46 @@
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.Collections;
29using OpenSim.Region.ScriptEngine.Interfaces;
30
31using key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
32using rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
33using vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
34using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
35using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
36using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
37using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
38
39namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
40{
41 public interface ICM_Api
42 {
43 string cmDetectedCountry(int num);
44 string cmGetAgentCountry(key key);
45 }
46}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
index 654ea81..ce13d6b 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
@@ -121,6 +121,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
121 LSL_Float llGetEnergy(); 121 LSL_Float llGetEnergy();
122 LSL_Vector llGetForce(); 122 LSL_Vector llGetForce();
123 LSL_Integer llGetFreeMemory(); 123 LSL_Integer llGetFreeMemory();
124 LSL_Integer llGetUsedMemory();
124 LSL_Integer llGetFreeURLs(); 125 LSL_Integer llGetFreeURLs();
125 LSL_Vector llGetGeometricCenter(); 126 LSL_Vector llGetGeometricCenter();
126 LSL_Float llGetGMTclock(); 127 LSL_Float llGetGMTclock();
@@ -402,7 +403,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
402 LSL_Vector llWind(LSL_Vector offset); 403 LSL_Vector llWind(LSL_Vector offset);
403 LSL_String llXorBase64Strings(string str1, string str2); 404 LSL_String llXorBase64Strings(string str1, string str2);
404 LSL_String llXorBase64StringsCorrect(string str1, string str2); 405 LSL_String llXorBase64StringsCorrect(string str1, string str2);
405 void print(string str); 406 LSL_Integer llGetLinkNumberOfSides(LSL_Integer link);
406 407
407 void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); 408 void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
408 LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules); 409 LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index 63007c6..c08ad3b 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -83,7 +83,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
83 // Avatar Info Commands 83 // Avatar Info Commands
84 string osGetAgentIP(string agent); 84 string osGetAgentIP(string agent);
85 LSL_List osGetAgents(); 85 LSL_List osGetAgents();
86 86
87 // Teleport commands 87 // Teleport commands
88 void osTeleportAgent(string agent, string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat); 88 void osTeleportAgent(string agent, string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat);
89 void osTeleportAgent(string agent, int regionX, int regionY, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat); 89 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
new file mode 100644
index 0000000..4132dfa
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs
@@ -0,0 +1,71 @@
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.Runtime.Remoting.Lifetime;
30using System.Threading;
31using System.Reflection;
32using System.Collections;
33using System.Collections.Generic;
34using OpenSim.Framework;
35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.ScriptEngine.Interfaces;
37using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces;
38using integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
39using vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
40using rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
41using key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
42using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
43using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
44using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
45using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
46
47namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
48{
49 public partial class ScriptBaseClass : MarshalByRefObject
50 {
51 public ICM_Api m_CM_Functions;
52
53 public void ApiTypeCM(IScriptApi api)
54 {
55 if (!(api is ICM_Api))
56 return;
57
58 m_CM_Functions = (ICM_Api)api;
59 }
60
61 public string cmDetectedCountry(int num)
62 {
63 return m_CM_Functions.cmDetectedCountry(num);
64 }
65
66 public string cmGetAgentCountry(key key)
67 {
68 return m_CM_Functions.cmGetAgentCountry(key);
69 }
70 }
71}
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 9377cda..5f94ff5 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
@@ -281,6 +281,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
281 public const int CHANGED_REGION_START = 1024; //LL Changed the constant from CHANGED_REGION_RESTART 281 public const int CHANGED_REGION_START = 1024; //LL Changed the constant from CHANGED_REGION_RESTART
282 public const int CHANGED_MEDIA = 2048; 282 public const int CHANGED_MEDIA = 2048;
283 public const int CHANGED_ANIMATION = 16384; 283 public const int CHANGED_ANIMATION = 16384;
284 public const int CHANGED_POSITION = 32768;
284 public const int TYPE_INVALID = 0; 285 public const int TYPE_INVALID = 0;
285 public const int TYPE_INTEGER = 1; 286 public const int TYPE_INTEGER = 1;
286 public const int TYPE_FLOAT = 2; 287 public const int TYPE_FLOAT = 2;
@@ -374,6 +375,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
374 public const int PRIM_SCULPT_TYPE_TORUS = 2; 375 public const int PRIM_SCULPT_TYPE_TORUS = 2;
375 public const int PRIM_SCULPT_TYPE_PLANE = 3; 376 public const int PRIM_SCULPT_TYPE_PLANE = 3;
376 public const int PRIM_SCULPT_TYPE_CYLINDER = 4; 377 public const int PRIM_SCULPT_TYPE_CYLINDER = 4;
378 public const int PRIM_SCULPT_FLAG_INVERT = 64;
379 public const int PRIM_SCULPT_FLAG_MIRROR = 128;
377 380
378 public const int MASK_BASE = 0; 381 public const int MASK_BASE = 0;
379 public const int MASK_OWNER = 1; 382 public const int MASK_OWNER = 1;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
index 303d75e..7d7e54e 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();
@@ -459,6 +461,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
459 return m_LSL_Functions.llGetFreeMemory(); 461 return m_LSL_Functions.llGetFreeMemory();
460 } 462 }
461 463
464 public LSL_Integer llGetUsedMemory()
465 {
466 return m_LSL_Functions.llGetUsedMemory();
467 }
468
462 public LSL_Integer llGetFreeURLs() 469 public LSL_Integer llGetFreeURLs()
463 { 470 {
464 return m_LSL_Functions.llGetFreeURLs(); 471 return m_LSL_Functions.llGetFreeURLs();
@@ -1868,9 +1875,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1868 return m_LSL_Functions.llClearPrimMedia(face); 1875 return m_LSL_Functions.llClearPrimMedia(face);
1869 } 1876 }
1870 1877
1871 public void print(string str) 1878 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
1872 { 1879 {
1873 m_LSL_Functions.print(str); 1880 return m_LSL_Functions.llGetLinkNumberOfSides(link);
1874 } 1881 }
1875 } 1882 }
1876} 1883}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs
index 143b497..2e27f16 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs
@@ -72,9 +72,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
72 { 72 {
73 return m_LS_Functions.lsSetWindlightSceneTargeted(rules, target); 73 return m_LS_Functions.lsSetWindlightSceneTargeted(rules, target);
74 } 74 }
75
75 public void lsClearWindlightScene() 76 public void lsClearWindlightScene()
76 { 77 {
77 m_LS_Functions.lsClearWindlightScene(); 78 m_LS_Functions.lsClearWindlightScene();
78 } 79 }
80
81 public LSL_List cmGetWindlightScene(LSL_List rules)
82 {
83 return m_LS_Functions.lsGetWindlightScene(rules);
84 }
85
86 public int cmSetWindlightScene(LSL_List rules)
87 {
88 return m_LS_Functions.lsSetWindlightScene(rules);
89 }
90
91 public int cmSetWindlightSceneTargeted(LSL_List rules, key target)
92 {
93 return m_LS_Functions.lsSetWindlightSceneTargeted(rules, target);
94 }
95
96 public void cmClearWindlightScene()
97 {
98 m_LS_Functions.lsClearWindlightScene();
99 }
79 } 100 }
80} 101}
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/Helpers.cs b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
index 3575889..e9edf6c 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
@@ -35,6 +35,7 @@ using OpenMetaverse;
35using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Region.CoreModules; 36using OpenSim.Region.CoreModules;
37using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Services.Interfaces;
38 39
39namespace OpenSim.Region.ScriptEngine.Shared 40namespace OpenSim.Region.ScriptEngine.Shared
40{ 41{
@@ -95,6 +96,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
95 Type = 0; 96 Type = 0;
96 Velocity = new LSL_Types.Vector3(); 97 Velocity = new LSL_Types.Vector3();
97 initializeSurfaceTouch(); 98 initializeSurfaceTouch();
99 Country = String.Empty;
98 } 100 }
99 101
100 public UUID Key; 102 public UUID Key;
@@ -126,6 +128,8 @@ namespace OpenSim.Region.ScriptEngine.Shared
126 private int touchFace; 128 private int touchFace;
127 public int TouchFace { get { return touchFace; } } 129 public int TouchFace { get { return touchFace; } }
128 130
131 public string Country;
132
129 // This can be done in two places including the constructor 133 // This can be done in two places including the constructor
130 // so be carefull what gets added here 134 // so be carefull what gets added here
131 private void initializeSurfaceTouch() 135 private void initializeSurfaceTouch()
@@ -173,6 +177,10 @@ namespace OpenSim.Region.ScriptEngine.Shared
173 return; 177 return;
174 178
175 Name = presence.Firstname + " " + presence.Lastname; 179 Name = presence.Firstname + " " + presence.Lastname;
180 UserAccount account = scene.UserAccountService.GetUserAccount(scene.RegionInfo.ScopeID, Key);
181 if (account != null)
182 Country = account.UserCountry;
183
176 Owner = Key; 184 Owner = Key;
177 Position = new LSL_Types.Vector3( 185 Position = new LSL_Types.Vector3(
178 presence.AbsolutePosition.X, 186 presence.AbsolutePosition.X,
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index 783791f..9548253 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;
@@ -55,7 +56,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
55{ 56{
56 public class ScriptInstance : MarshalByRefObject, IScriptInstance 57 public class ScriptInstance : MarshalByRefObject, IScriptInstance
57 { 58 {
58 // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 59 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
59 60
60 private IScriptEngine m_Engine; 61 private IScriptEngine m_Engine;
61 private IScriptWorkItem m_CurrentResult = null; 62 private IScriptWorkItem m_CurrentResult = null;
@@ -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();
@@ -271,9 +271,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
271 //RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass); 271 //RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass);
272// lease.Register(this); 272// lease.Register(this);
273 } 273 }
274 catch (Exception) 274 catch (Exception e)
275 { 275 {
276 // m_log.ErrorFormat("[Script] Error loading assembly {0}\n"+e.ToString(), assembly); 276 m_log.ErrorFormat("[Script] Error loading assembly {0}\n"+e.ToString(), assembly);
277 throw;
277 } 278 }
278 279
279 try 280 try
@@ -434,14 +435,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
434 { 435 {
435 int permsMask; 436 int permsMask;
436 UUID permsGranter; 437 UUID permsGranter;
437 lock (part.TaskInventory) 438 part.TaskInventory.LockItemsForRead(true);
439 if (!part.TaskInventory.ContainsKey(m_ItemID))
438 { 440 {
439 if (!part.TaskInventory.ContainsKey(m_ItemID)) 441 part.TaskInventory.LockItemsForRead(false);
440 return; 442 return;
441
442 permsGranter = part.TaskInventory[m_ItemID].PermsGranter;
443 permsMask = part.TaskInventory[m_ItemID].PermsMask;
444 } 443 }
444 permsGranter = part.TaskInventory[m_ItemID].PermsGranter;
445 permsMask = part.TaskInventory[m_ItemID].PermsMask;
446 part.TaskInventory.LockItemsForRead(false);
445 447
446 if ((permsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0) 448 if ((permsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)
447 { 449 {
@@ -550,6 +552,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
550 return true; 552 return true;
551 } 553 }
552 554
555 [DebuggerNonUserCode] //Prevents the debugger from farting in this function
553 public void SetState(string state) 556 public void SetState(string state)
554 { 557 {
555 if (state == State) 558 if (state == State)
@@ -561,7 +564,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
561 new DetectParams[0])); 564 new DetectParams[0]));
562 PostEvent(new EventParams("state_entry", new Object[0], 565 PostEvent(new EventParams("state_entry", new Object[0],
563 new DetectParams[0])); 566 new DetectParams[0]));
564 567
565 throw new EventAbortException(); 568 throw new EventAbortException();
566 } 569 }
567 570
@@ -644,14 +647,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
644 /// <returns></returns> 647 /// <returns></returns>
645 public object EventProcessor() 648 public object EventProcessor()
646 { 649 {
647 if (m_Suspended) 650 EventParams data = null;
648 return 0;
649 651
650 lock (m_Script) 652 lock (m_EventQueue)
651 { 653 {
652 EventParams data = null; 654 if (m_Suspended)
655 return 0;
653 656
654 lock (m_EventQueue) 657 lock (m_Script)
655 { 658 {
656 data = (EventParams) m_EventQueue.Dequeue(); 659 data = (EventParams) m_EventQueue.Dequeue();
657 if (data == null) // Shouldn't happen 660 if (data == null) // Shouldn't happen
@@ -677,6 +680,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
677 if (data.EventName == "collision") 680 if (data.EventName == "collision")
678 m_CollisionInQueue = false; 681 m_CollisionInQueue = false;
679 } 682 }
683 }
684 lock(m_Script)
685 {
680 686
681 //m_log.DebugFormat("[XENGINE]: Processing event {0} for {1}", data.EventName, this); 687 //m_log.DebugFormat("[XENGINE]: Processing event {0} for {1}", data.EventName, this);
682 688
@@ -833,6 +839,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
833 new Object[0], new DetectParams[0])); 839 new Object[0], new DetectParams[0]));
834 } 840 }
835 841
842 [DebuggerNonUserCode] //Stops the VS debugger from farting in this function
836 public void ApiResetScript() 843 public void ApiResetScript()
837 { 844 {
838 // bool running = Running; 845 // bool running = Running;
@@ -864,10 +871,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
864 871
865 public Dictionary<string, object> GetVars() 872 public Dictionary<string, object> GetVars()
866 { 873 {
867 if (m_Script != null) 874 return m_Script.GetVars();
868 return m_Script.GetVars();
869 else
870 return new Dictionary<string, object>();
871 } 875 }
872 876
873 public void SetVars(Dictionary<string, object> vars) 877 public void SetVars(Dictionary<string, object> vars)
diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
index 461b473..6bfee91 100644
--- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
@@ -83,19 +83,19 @@ namespace OpenSim.Region.ScriptEngine.Shared
83 83
84 public override string ToString() 84 public override string ToString()
85 { 85 {
86 string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000}>", x, y, z); 86 string s=String.Format("<{0:0.000000}, {1:0.000000}, {2:0.000000}>", x, y, z);
87 return s; 87 return s;
88 } 88 }
89 89
90 public static explicit operator LSLString(Vector3 vec) 90 public static explicit operator LSLString(Vector3 vec)
91 { 91 {
92 string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000}>", vec.x, vec.y, vec.z); 92 string s=String.Format("<{0:0.000000}, {1:0.000000}, {2:0.000000}>", vec.x, vec.y, vec.z);
93 return new LSLString(s); 93 return new LSLString(s);
94 } 94 }
95 95
96 public static explicit operator string(Vector3 vec) 96 public static explicit operator string(Vector3 vec)
97 { 97 {
98 string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000}>", vec.x, vec.y, vec.z); 98 string s=String.Format("<{0:0.000000}, {1:0.000000}, {2:0.000000}>", vec.x, vec.y, vec.z);
99 return s; 99 return s;
100 } 100 }
101 101
@@ -342,19 +342,19 @@ namespace OpenSim.Region.ScriptEngine.Shared
342 342
343 public override string ToString() 343 public override string ToString()
344 { 344 {
345 string st=String.Format(Culture.FormatProvider, "<{0:0.000000},{1:0.000000},{2:0.000000},{3:0.000000}>", x, y, z, s); 345 string st=String.Format(Culture.FormatProvider, "<{0:0.000000}, {1:0.000000}, {2:0.000000}, {3:0.000000}>", x, y, z, s);
346 return st; 346 return st;
347 } 347 }
348 348
349 public static explicit operator string(Quaternion r) 349 public static explicit operator string(Quaternion r)
350 { 350 {
351 string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000},{3:0.000000}>", r.x, r.y, r.z, r.s); 351 string s=String.Format("<{0:0.000000}, {1:0.000000}, {2:0.000000}, {3:0.000000}>", r.x, r.y, r.z, r.s);
352 return s; 352 return s;
353 } 353 }
354 354
355 public static explicit operator LSLString(Quaternion r) 355 public static explicit operator LSLString(Quaternion r)
356 { 356 {
357 string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000},{3:0.000000}>", r.x, r.y, r.z, r.s); 357 string s=String.Format("<{0:0.000000}, {1:0.000000}, {2:0.000000}, {3:0.000000}>", r.x, r.y, r.z, r.s);
358 return new LSLString(s); 358 return new LSLString(s);
359 } 359 }
360 360
@@ -459,6 +459,8 @@ namespace OpenSim.Region.ScriptEngine.Shared
459 size += 64; 459 size += 64;
460 else if (o is int) 460 else if (o is int)
461 size += 4; 461 size += 4;
462 else if (o is uint)
463 size += 4;
462 else if (o is string) 464 else if (o is string)
463 size += ((string)o).Length; 465 size += ((string)o).Length;
464 else if (o is float) 466 else if (o is float)
@@ -613,24 +615,16 @@ namespace OpenSim.Region.ScriptEngine.Shared
613 615
614 public static bool operator ==(list a, list b) 616 public static bool operator ==(list a, list b)
615 { 617 {
616 int la = -1; 618 int la = a.Length;
617 int lb = -1; 619 int lb = b.Length;
618 try { la = a.Length; }
619 catch (NullReferenceException) { }
620 try { lb = b.Length; }
621 catch (NullReferenceException) { }
622 620
623 return la == lb; 621 return la == lb;
624 } 622 }
625 623
626 public static bool operator !=(list a, list b) 624 public static bool operator !=(list a, list b)
627 { 625 {
628 int la = -1; 626 int la = a.Length;
629 int lb = -1; 627 int lb = b.Length;
630 try { la = a.Length; }
631 catch (NullReferenceException) { }
632 try {lb = b.Length;}
633 catch (NullReferenceException) { }
634 628
635 return la != lb; 629 return la != lb;
636 } 630 }
@@ -1064,7 +1058,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
1064 { 1058 {
1065 list ret = new list(); 1059 list ret = new list();
1066 double entry; 1060 double entry;
1067 for (int i = 0; i < src.Data.Length - 1; i++) 1061 for (int i = 0; i < src.Data.Length; i++)
1068 { 1062 {
1069 if (double.TryParse(src.Data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry)) 1063 if (double.TryParse(src.Data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry))
1070 { 1064 {
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index d253c6a..4f3432d 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 =
@@ -124,6 +127,71 @@ namespace OpenSim.Region.ScriptEngine.XEngine
124 IWorkItemResult m_CurrentCompile = null; 127 IWorkItemResult m_CurrentCompile = null;
125 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>(); 128 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>();
126 129
130 private void lockScriptsForRead(bool locked)
131 {
132 if (locked)
133 {
134 if (m_scriptsLock.RecursiveReadCount > 0)
135 {
136 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.");
137 m_scriptsLock.ExitReadLock();
138 }
139 if (m_scriptsLock.RecursiveWriteCount > 0)
140 {
141 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
142 m_scriptsLock.ExitWriteLock();
143 }
144
145 while (!m_scriptsLock.TryEnterReadLock(60000))
146 {
147 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.");
148 if (m_scriptsLock.IsWriteLockHeld)
149 {
150 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
151 }
152 }
153 }
154 else
155 {
156 if (m_scriptsLock.RecursiveReadCount > 0)
157 {
158 m_scriptsLock.ExitReadLock();
159 }
160 }
161 }
162 private void lockScriptsForWrite(bool locked)
163 {
164 if (locked)
165 {
166 if (m_scriptsLock.RecursiveReadCount > 0)
167 {
168 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.");
169 m_scriptsLock.ExitReadLock();
170 }
171 if (m_scriptsLock.RecursiveWriteCount > 0)
172 {
173 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
174 m_scriptsLock.ExitWriteLock();
175 }
176
177 while (!m_scriptsLock.TryEnterWriteLock(60000))
178 {
179 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.");
180 if (m_scriptsLock.IsWriteLockHeld)
181 {
182 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
183 }
184 }
185 }
186 else
187 {
188 if (m_scriptsLock.RecursiveWriteCount > 0)
189 {
190 m_scriptsLock.ExitWriteLock();
191 }
192 }
193 }
194
127 public string ScriptEngineName 195 public string ScriptEngineName
128 { 196 {
129 get { return "XEngine"; } 197 get { return "XEngine"; }
@@ -269,43 +337,45 @@ namespace OpenSim.Region.ScriptEngine.XEngine
269 337
270 public void RemoveRegion(Scene scene) 338 public void RemoveRegion(Scene scene)
271 { 339 {
272 lock (m_Scripts) 340 lockScriptsForRead(true);
341 foreach (IScriptInstance instance in m_Scripts.Values)
273 { 342 {
274 foreach (IScriptInstance instance in m_Scripts.Values) 343 // Force a final state save
344 //
345 if (m_Assemblies.ContainsKey(instance.AssetID))
275 { 346 {
276 // Force a final state save 347 string assembly = m_Assemblies[instance.AssetID];
277 // 348 instance.SaveState(assembly);
278 if (m_Assemblies.ContainsKey(instance.AssetID)) 349 }
279 {
280 string assembly = m_Assemblies[instance.AssetID];
281 instance.SaveState(assembly);
282 }
283 350
284 // Clear the event queue and abort the instance thread 351 // Clear the event queue and abort the instance thread
285 // 352 //
286 instance.ClearQueue(); 353 instance.ClearQueue();
287 instance.Stop(0); 354 instance.Stop(0);
288 355
289 // Release events, timer, etc 356 // Release events, timer, etc
290 // 357 //
291 instance.DestroyScriptInstance(); 358 instance.DestroyScriptInstance();
292 359
293 // Unload scripts and app domains 360 // Unload scripts and app domains
294 // Must be done explicitly because they have infinite 361 // Must be done explicitly because they have infinite
295 // lifetime 362 // lifetime
296 // 363 //
297 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 364 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
298 if (m_DomainScripts[instance.AppDomain].Count == 0) 365 if (m_DomainScripts[instance.AppDomain].Count == 0)
299 { 366 {
300 m_DomainScripts.Remove(instance.AppDomain); 367 m_DomainScripts.Remove(instance.AppDomain);
301 UnloadAppDomain(instance.AppDomain); 368 UnloadAppDomain(instance.AppDomain);
302 }
303 } 369 }
304 m_Scripts.Clear();
305 m_PrimObjects.Clear();
306 m_Assemblies.Clear();
307 m_DomainScripts.Clear();
308 } 370 }
371 lockScriptsForRead(false);
372 lockScriptsForWrite(true);
373 m_Scripts.Clear();
374 lockScriptsForWrite(false);
375 m_PrimObjects.Clear();
376 m_Assemblies.Clear();
377 m_DomainScripts.Clear();
378
309 lock (m_ScriptEngines) 379 lock (m_ScriptEngines)
310 { 380 {
311 m_ScriptEngines.Remove(this); 381 m_ScriptEngines.Remove(this);
@@ -364,22 +434,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
364 434
365 List<IScriptInstance> instances = new List<IScriptInstance>(); 435 List<IScriptInstance> instances = new List<IScriptInstance>();
366 436
367 lock (m_Scripts) 437 lockScriptsForRead(true);
368 { 438 foreach (IScriptInstance instance in m_Scripts.Values)
369 foreach (IScriptInstance instance in m_Scripts.Values)
370 instances.Add(instance); 439 instances.Add(instance);
371 } 440 lockScriptsForRead(false);
372 441
373 foreach (IScriptInstance i in instances) 442 foreach (IScriptInstance i in instances)
374 { 443 {
375 string assembly = String.Empty; 444 string assembly = String.Empty;
376 445
377 lock (m_Scripts) 446
378 {
379 if (!m_Assemblies.ContainsKey(i.AssetID)) 447 if (!m_Assemblies.ContainsKey(i.AssetID))
380 continue; 448 continue;
381 assembly = m_Assemblies[i.AssetID]; 449 assembly = m_Assemblies[i.AssetID];
382 } 450
383 451
384 i.SaveState(assembly); 452 i.SaveState(assembly);
385 } 453 }
@@ -713,92 +781,95 @@ namespace OpenSim.Region.ScriptEngine.XEngine
713 } 781 }
714 782
715 ScriptInstance instance = null; 783 ScriptInstance instance = null;
716 lock (m_Scripts) 784 // Create the object record
785 lockScriptsForRead(true);
786 if ((!m_Scripts.ContainsKey(itemID)) ||
787 (m_Scripts[itemID].AssetID != assetID))
717 { 788 {
718 // Create the object record 789 lockScriptsForRead(false);
719 790
720 if ((!m_Scripts.ContainsKey(itemID)) || 791 UUID appDomain = assetID;
721 (m_Scripts[itemID].AssetID != assetID))
722 {
723 UUID appDomain = assetID;
724 792
725 if (part.ParentGroup.IsAttachment) 793 if (part.ParentGroup.IsAttachment)
726 appDomain = part.ParentGroup.RootPart.UUID; 794 appDomain = part.ParentGroup.RootPart.UUID;
727 795
728 if (!m_AppDomains.ContainsKey(appDomain)) 796 if (!m_AppDomains.ContainsKey(appDomain))
797 {
798 try
729 { 799 {
730 try 800 AppDomainSetup appSetup = new AppDomainSetup();
731 { 801 appSetup.PrivateBinPath = Path.Combine(
732 AppDomainSetup appSetup = new AppDomainSetup(); 802 m_ScriptEnginesPath,
733 appSetup.PrivateBinPath = Path.Combine( 803 m_Scene.RegionInfo.RegionID.ToString());
734 m_ScriptEnginesPath, 804
735 m_Scene.RegionInfo.RegionID.ToString()); 805 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
736 806 Evidence evidence = new Evidence(baseEvidence);
737 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 807
738 Evidence evidence = new Evidence(baseEvidence); 808 AppDomain sandbox;
739 809 if (m_AppDomainLoading)
740 AppDomain sandbox; 810 sandbox = AppDomain.CreateDomain(
741 if (m_AppDomainLoading) 811 m_Scene.RegionInfo.RegionID.ToString(),
742 sandbox = AppDomain.CreateDomain( 812 evidence, appSetup);
743 m_Scene.RegionInfo.RegionID.ToString(), 813 else
744 evidence, appSetup); 814 sandbox = AppDomain.CurrentDomain;
745 else 815
746 sandbox = AppDomain.CurrentDomain; 816 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
747 817 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
748 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); 818 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
749 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); 819 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
750 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet"); 820 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
751 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet); 821 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
752 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement); 822 //sandbox.SetAppDomainPolicy(sandboxPolicy);
753 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup; 823
754 //sandbox.SetAppDomainPolicy(sandboxPolicy); 824 m_AppDomains[appDomain] = sandbox;
755 825
756 m_AppDomains[appDomain] = sandbox; 826 m_AppDomains[appDomain].AssemblyResolve +=
757 827 new ResolveEventHandler(
758 m_AppDomains[appDomain].AssemblyResolve += 828 AssemblyResolver.OnAssemblyResolve);
759 new ResolveEventHandler( 829 m_DomainScripts[appDomain] = new List<UUID>();
760 AssemblyResolver.OnAssemblyResolve); 830 }
761 m_DomainScripts[appDomain] = new List<UUID>(); 831 catch (Exception e)
762 } 832 {
763 catch (Exception e) 833 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
834 m_ScriptErrorMessage += "Exception creating app domain:\n";
835 m_ScriptFailCount++;
836 lock (m_AddingAssemblies)
764 { 837 {
765 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); 838 m_AddingAssemblies[assembly]--;
766 m_ScriptErrorMessage += "Exception creating app domain:\n";
767 m_ScriptFailCount++;
768 lock (m_AddingAssemblies)
769 {
770 m_AddingAssemblies[assembly]--;
771 }
772 return false;
773 } 839 }
840 return false;
774 } 841 }
775 m_DomainScripts[appDomain].Add(itemID); 842 }
776 843 m_DomainScripts[appDomain].Add(itemID);
777 instance = new ScriptInstance(this, part, 844
778 itemID, assetID, assembly, 845 instance = new ScriptInstance(this, part,
779 m_AppDomains[appDomain], 846 itemID, assetID, assembly,
780 part.ParentGroup.RootPart.Name, 847 m_AppDomains[appDomain],
781 item.Name, startParam, postOnRez, 848 part.ParentGroup.RootPart.Name,
782 stateSource, m_MaxScriptQueue); 849 item.Name, startParam, postOnRez,
783 850 stateSource, m_MaxScriptQueue);
784 m_log.DebugFormat( 851
852 m_log.DebugFormat(
785 "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}", 853 "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
786 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, 854 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
787 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); 855 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
788 856
789 if (presence != null) 857 if (presence != null)
790 { 858 {
791 ShowScriptSaveResponse(item.OwnerID, 859 ShowScriptSaveResponse(item.OwnerID,
792 assetID, "Compile successful", true); 860 assetID, "Compile successful", true);
793 }
794
795 instance.AppDomain = appDomain;
796 instance.LineMap = linemap;
797
798 m_Scripts[itemID] = instance;
799 } 861 }
800 }
801 862
863 instance.AppDomain = appDomain;
864 instance.LineMap = linemap;
865 lockScriptsForWrite(true);
866 m_Scripts[itemID] = instance;
867 lockScriptsForWrite(false);
868 }
869 else
870 {
871 lockScriptsForRead(false);
872 }
802 lock (m_PrimObjects) 873 lock (m_PrimObjects)
803 { 874 {
804 if (!m_PrimObjects.ContainsKey(localID)) 875 if (!m_PrimObjects.ContainsKey(localID))
@@ -817,9 +888,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
817 m_AddingAssemblies[assembly]--; 888 m_AddingAssemblies[assembly]--;
818 } 889 }
819 890
820 if (instance != null) 891 if (instance!=null)
821 instance.Init(); 892 instance.Init();
822 893
823 return true; 894 return true;
824 } 895 }
825 896
@@ -832,20 +903,23 @@ namespace OpenSim.Region.ScriptEngine.XEngine
832 m_CompileDict.Remove(itemID); 903 m_CompileDict.Remove(itemID);
833 } 904 }
834 905
835 IScriptInstance instance = null; 906 lockScriptsForRead(true);
836 907 // Do we even have it?
837 lock (m_Scripts) 908 if (!m_Scripts.ContainsKey(itemID))
838 { 909 {
839 // Do we even have it? 910 lockScriptsForRead(false);
840 if (!m_Scripts.ContainsKey(itemID)) 911 return;
841 return;
842
843 instance=m_Scripts[itemID];
844 m_Scripts.Remove(itemID);
845 } 912 }
913
846 914
915 IScriptInstance instance=m_Scripts[itemID];
916 lockScriptsForRead(false);
917 lockScriptsForWrite(true);
918 m_Scripts.Remove(itemID);
919 lockScriptsForWrite(false);
847 instance.ClearQueue(); 920 instance.ClearQueue();
848 instance.Stop(0); 921 instance.Stop(0);
922
849// bool objectRemoved = false; 923// bool objectRemoved = false;
850 924
851 lock (m_PrimObjects) 925 lock (m_PrimObjects)
@@ -881,11 +955,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
881 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 955 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
882 if (handlerObjectRemoved != null) 956 if (handlerObjectRemoved != null)
883 { 957 {
884 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID); 958 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
885 handlerObjectRemoved(part.UUID); 959 handlerObjectRemoved(part.UUID);
886 } 960 }
887 961
888 962 CleanAssemblies();
963
889 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 964 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
890 if (handlerScriptRemoved != null) 965 if (handlerScriptRemoved != null)
891 handlerScriptRemoved(itemID); 966 handlerScriptRemoved(itemID);
@@ -1027,7 +1102,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1027 return false; 1102 return false;
1028 1103
1029 uuids = m_PrimObjects[localID]; 1104 uuids = m_PrimObjects[localID];
1030 } 1105
1031 1106
1032 foreach (UUID itemID in uuids) 1107 foreach (UUID itemID in uuids)
1033 { 1108 {
@@ -1045,6 +1120,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1045 result = true; 1120 result = true;
1046 } 1121 }
1047 } 1122 }
1123 }
1048 1124
1049 return result; 1125 return result;
1050 } 1126 }
@@ -1144,12 +1220,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1144 private IScriptInstance GetInstance(UUID itemID) 1220 private IScriptInstance GetInstance(UUID itemID)
1145 { 1221 {
1146 IScriptInstance instance; 1222 IScriptInstance instance;
1147 lock (m_Scripts) 1223 lockScriptsForRead(true);
1224 if (!m_Scripts.ContainsKey(itemID))
1148 { 1225 {
1149 if (!m_Scripts.ContainsKey(itemID)) 1226 lockScriptsForRead(false);
1150 return null; 1227 return null;
1151 instance = m_Scripts[itemID];
1152 } 1228 }
1229 instance = m_Scripts[itemID];
1230 lockScriptsForRead(false);
1153 return instance; 1231 return instance;
1154 } 1232 }
1155 1233
@@ -1173,6 +1251,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1173 return false; 1251 return false;
1174 } 1252 }
1175 1253
1254 [DebuggerNonUserCode]
1176 public void ApiResetScript(UUID itemID) 1255 public void ApiResetScript(UUID itemID)
1177 { 1256 {
1178 IScriptInstance instance = GetInstance(itemID); 1257 IScriptInstance instance = GetInstance(itemID);
@@ -1224,6 +1303,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1224 return UUID.Zero; 1303 return UUID.Zero;
1225 } 1304 }
1226 1305
1306 [DebuggerNonUserCode]
1227 public void SetState(UUID itemID, string newState) 1307 public void SetState(UUID itemID, string newState)
1228 { 1308 {
1229 IScriptInstance instance = GetInstance(itemID); 1309 IScriptInstance instance = GetInstance(itemID);
@@ -1244,11 +1324,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1244 { 1324 {
1245 List<IScriptInstance> instances = new List<IScriptInstance>(); 1325 List<IScriptInstance> instances = new List<IScriptInstance>();
1246 1326
1247 lock (m_Scripts) 1327 lockScriptsForRead(true);
1248 { 1328 foreach (IScriptInstance instance in m_Scripts.Values)
1249 foreach (IScriptInstance instance in m_Scripts.Values)
1250 instances.Add(instance); 1329 instances.Add(instance);
1251 } 1330 lockScriptsForRead(false);
1252 1331
1253 foreach (IScriptInstance i in instances) 1332 foreach (IScriptInstance i in instances)
1254 { 1333 {
@@ -1620,5 +1699,17 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1620 1699
1621 instance.Resume(); 1700 instance.Resume();
1622 } 1701 }
1702
1703 public bool HasScript(UUID itemID, out bool running)
1704 {
1705 running = true;
1706
1707 IScriptInstance instance = GetInstance(itemID);
1708 if (instance == null)
1709 return false;
1710
1711 running = instance.Running;
1712 return true;
1713 }
1623 } 1714 }
1624} 1715}