aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/Application/Application.cs8
-rw-r--r--OpenSim/Region/Application/OpenSim.cs236
-rw-r--r--OpenSim/Region/Application/OpenSimBase.cs25
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs53
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs102
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs13
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/FetchInventory2Module.cs3
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs12
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs4
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs4
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/NewFileAgentInventoryVariablePriceModule.cs93
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs14
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs16
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs4
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs4
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs9
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs5
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs55
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs199
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs175
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs3
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs3
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/TestLLUDPServer.cs9
-rw-r--r--OpenSim/Region/ClientStack/RegionApplicationBase.cs17
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs15
-rw-r--r--OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs10
-rw-r--r--OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs553
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs473
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs35
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs1
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs17
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs189
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs33
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs59
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs92
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs124
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs7
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs14
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs10
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs1100
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs269
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs126
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs5
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs80
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs7
-rw-r--r--OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs116
-rw-r--r--OpenSim/Region/CoreModules/LightShare/EnvironmentModule.cs224
-rw-r--r--OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml1
-rw-r--r--OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs24
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs26
-rw-r--r--OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs9
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs3
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/AuthorizationService.cs4
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs35
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs28
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs15
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/LocalNeighbourServiceConnector.cs6
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs13
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs219
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs16
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs26
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs121
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs20
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/AssetsDearchiver.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs67
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs12
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs17
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs35
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs9
-rw-r--r--OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs1
-rw-r--r--OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs328
-rw-r--r--OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs53
-rw-r--r--OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs155
-rw-r--r--OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Sound/SoundModule.cs7
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs103
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs21
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/TIFF.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs28
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs35
-rw-r--r--OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs389
-rw-r--r--OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs (renamed from OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs)88
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs28
-rw-r--r--OpenSim/Region/DataSnapshot/DataRequestHandler.cs4
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs33
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityInventory.cs69
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs23
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEnvironmentModule.cs36
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEstateModule.cs3
-rw-r--r--OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs10
-rw-r--r--OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs48
-rw-r--r--OpenSim/Region/Framework/Interfaces/INPCModule.cs44
-rw-r--r--OpenSim/Region/Framework/Interfaces/IRegionCombinerModule.cs59
-rw-r--r--OpenSim/Region/Framework/Interfaces/IScenePresence.cs10
-rw-r--r--OpenSim/Region/Framework/Interfaces/IScriptModule.cs18
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs20
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs20
-rw-r--r--OpenSim/Region/Framework/Interfaces/IUrlModule.cs1
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs19
-rw-r--r--OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs12
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs49
-rw-r--r--OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs9
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs78
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Permissions.cs17
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs830
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs12
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs26
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs61
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs28
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs253
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs200
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs367
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs569
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs20
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs45
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneXmlLoader.cs72
-rw-r--r--OpenSim/Region/Framework/Scenes/SimStatsReporter.cs300
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/BorderTests.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs8
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs33
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs34
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectScriptTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs154
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs130
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs23
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs34
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs478
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs17
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs21
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs195
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs17
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs56
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs54
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs4
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs3
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs500
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs430
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs498
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs5
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/Minimodule/SPAvatar.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs5
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs77
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs68
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs10
-rw-r--r--OpenSim/Region/OptionalModules/World/WorldView/WorldViewModule.cs15
-rw-r--r--OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs42
-rw-r--r--OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPrim.cs315
-rw-r--r--OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs41
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs102
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs11
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs29
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs23
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsScene.cs14
-rw-r--r--OpenSim/Region/Physics/Meshing/PrimMesher.cs326
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODECharacter.cs10
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODEPrim.cs472
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdeScene.cs452
-rw-r--r--OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs444
-rw-r--r--OpenSim/Region/RegionCombinerModule/RegionConnections.cs37
-rw-r--r--OpenSim/Region/ScriptEngine/Interfaces/IScriptApi.cs19
-rw-r--r--OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs10
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/ApiManager.cs41
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs15
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs10
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs1412
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs12
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs12
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs439
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Listener.cs8
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs25
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs7
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs42
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs35
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs54
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs8
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs50
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptSerializer.cs11
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs8
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs142
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs9
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs24
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs231
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs20
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs8
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs385
-rw-r--r--OpenSim/Region/UserStatistics/WebStatsModule.cs170
214 files changed, 12578 insertions, 5856 deletions
diff --git a/OpenSim/Region/Application/Application.cs b/OpenSim/Region/Application/Application.cs
index c130038..ebfebc4 100644
--- a/OpenSim/Region/Application/Application.cs
+++ b/OpenSim/Region/Application/Application.cs
@@ -92,9 +92,14 @@ namespace OpenSim
92 m_log.Info("[OPENSIM MAIN]: configured log4net using default OpenSim.exe.config"); 92 m_log.Info("[OPENSIM MAIN]: configured log4net using default OpenSim.exe.config");
93 } 93 }
94 94
95 m_log.DebugFormat( 95 m_log.InfoFormat(
96 "[OPENSIM MAIN]: System Locale is {0}", System.Threading.Thread.CurrentThread.CurrentCulture); 96 "[OPENSIM MAIN]: System Locale is {0}", System.Threading.Thread.CurrentThread.CurrentCulture);
97 97
98 string monoThreadsPerCpu = System.Environment.GetEnvironmentVariable("MONO_THREADS_PER_CPU");
99
100 m_log.InfoFormat(
101 "[OPENSIM MAIN]: Environment variable MONO_THREADS_PER_CPU is {0}", monoThreadsPerCpu ?? "unset");
102
98 // Increase the number of IOCP threads available. Mono defaults to a tragically low number 103 // Increase the number of IOCP threads available. Mono defaults to a tragically low number
99 int workerThreads, iocpThreads; 104 int workerThreads, iocpThreads;
100 System.Threading.ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads); 105 System.Threading.ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads);
@@ -109,7 +114,6 @@ namespace OpenSim
109 114
110 // Check if the system is compatible with OpenSimulator. 115 // Check if the system is compatible with OpenSimulator.
111 // Ensures that the minimum system requirements are met 116 // Ensures that the minimum system requirements are met
112 m_log.Info("Performing compatibility checks... \n");
113 string supported = String.Empty; 117 string supported = String.Empty;
114 if (Util.IsEnvironmentSupported(ref supported)) 118 if (Util.IsEnvironmentSupported(ref supported))
115 { 119 {
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index fb1e831..e6b57c2 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Diagnostics;
31using System.IO; 32using System.IO;
32using System.Reflection; 33using System.Reflection;
33using System.Text; 34using System.Text;
@@ -69,6 +70,7 @@ namespace OpenSim
69 private Regex m_consolePromptRegex = new Regex(@"([^\\])\\(\w)", RegexOptions.Compiled); 70 private Regex m_consolePromptRegex = new Regex(@"([^\\])\\(\w)", RegexOptions.Compiled);
70 71
71 private string m_timedScript = "disabled"; 72 private string m_timedScript = "disabled";
73 private int m_timeInterval = 1200;
72 private Timer m_scriptTimer; 74 private Timer m_scriptTimer;
73 75
74 public OpenSim(IConfigSource configSource) : base(configSource) 76 public OpenSim(IConfigSource configSource) : base(configSource)
@@ -98,6 +100,10 @@ namespace OpenSim
98 m_consolePort = (uint)networkConfig.GetInt("console_port", 0); 100 m_consolePort = (uint)networkConfig.GetInt("console_port", 0);
99 101
100 m_timedScript = startupConfig.GetString("timer_Script", "disabled"); 102 m_timedScript = startupConfig.GetString("timer_Script", "disabled");
103 if (m_timedScript != "disabled")
104 {
105 m_timeInterval = startupConfig.GetInt("timer_Interval", 1200);
106 }
101 107
102 if (m_logFileAppender != null) 108 if (m_logFileAppender != null)
103 { 109 {
@@ -138,7 +144,7 @@ namespace OpenSim
138 m_log.Info("===================================================================="); 144 m_log.Info("====================================================================");
139 m_log.Info("========================= STARTING OPENSIM ========================="); 145 m_log.Info("========================= STARTING OPENSIM =========================");
140 m_log.Info("===================================================================="); 146 m_log.Info("====================================================================");
141 147
142 //m_log.InfoFormat("[OPENSIM MAIN]: GC Is Server GC: {0}", GCSettings.IsServerGC.ToString()); 148 //m_log.InfoFormat("[OPENSIM MAIN]: GC Is Server GC: {0}", GCSettings.IsServerGC.ToString());
143 // http://msdn.microsoft.com/en-us/library/bb384202.aspx 149 // http://msdn.microsoft.com/en-us/library/bb384202.aspx
144 //GCSettings.LatencyMode = GCLatencyMode.Batch; 150 //GCSettings.LatencyMode = GCLatencyMode.Batch;
@@ -215,7 +221,7 @@ namespace OpenSim
215 { 221 {
216 m_scriptTimer = new Timer(); 222 m_scriptTimer = new Timer();
217 m_scriptTimer.Enabled = true; 223 m_scriptTimer.Enabled = true;
218 m_scriptTimer.Interval = 1200*1000; 224 m_scriptTimer.Interval = m_timeInterval*1000;
219 m_scriptTimer.Elapsed += RunAutoTimerScript; 225 m_scriptTimer.Elapsed += RunAutoTimerScript;
220 } 226 }
221 } 227 }
@@ -225,12 +231,14 @@ namespace OpenSim
225 /// </summary> 231 /// </summary>
226 private void RegisterConsoleCommands() 232 private void RegisterConsoleCommands()
227 { 233 {
228 m_console.Commands.AddCommand("Regions", false, "force update", 234 MainServer.RegisterHttpConsoleCommands(m_console);
235
236 m_console.Commands.AddCommand("Objects", false, "force update",
229 "force update", 237 "force update",
230 "Force the update of all objects on clients", 238 "Force the update of all objects on clients",
231 HandleForceUpdate); 239 HandleForceUpdate);
232 240
233 m_console.Commands.AddCommand("Comms", false, "debug packet", 241 m_console.Commands.AddCommand("Debug", false, "debug packet",
234 "debug packet <level> [<avatar-first-name> <avatar-last-name>]", 242 "debug packet <level> [<avatar-first-name> <avatar-last-name>]",
235 "Turn on packet debugging", 243 "Turn on packet debugging",
236 "If level > 255 then all incoming and outgoing packets are logged.\n" 244 "If level > 255 then all incoming and outgoing packets are logged.\n"
@@ -242,17 +250,9 @@ namespace OpenSim
242 + "If an avatar name is given then only packets from that avatar are logged", 250 + "If an avatar name is given then only packets from that avatar are logged",
243 Debug); 251 Debug);
244 252
245 m_console.Commands.AddCommand("Comms", false, "debug http", 253 m_console.Commands.AddCommand("Debug", false, "debug teleport", "debug teleport", "Toggle teleport route debugging", Debug);
246 "debug http <level>",
247 "Turn on inbound http request debugging for everything except the event queue (see debug eq).",
248 "If level >= 2 then the handler used to service the request is logged.\n"
249 + "If level >= 1 then incoming HTTP requests are logged.\n"
250 + "If level <= 0 then no extra http logging is done.\n",
251 Debug);
252 254
253 m_console.Commands.AddCommand("Comms", false, "debug teleport", "debug teleport", "Toggle teleport route debugging", Debug); 255 m_console.Commands.AddCommand("Debug", false, "debug scene",
254
255 m_console.Commands.AddCommand("Regions", false, "debug scene",
256 "debug scene <scripting> <collisions> <physics>", 256 "debug scene <scripting> <collisions> <physics>",
257 "Turn on scene debugging", Debug); 257 "Turn on scene debugging", Debug);
258 258
@@ -306,7 +306,7 @@ namespace OpenSim
306 + " If this is not given then the oar is saved to region.oar in the current directory.", 306 + " If this is not given then the oar is saved to region.oar in the current directory.",
307 SaveOar); 307 SaveOar);
308 308
309 m_console.Commands.AddCommand("Regions", false, "edit scale", 309 m_console.Commands.AddCommand("Objects", false, "edit scale",
310 "edit scale <name> <x> <y> <z>", 310 "edit scale <name> <x> <y> <z>",
311 "Change the scale of a named prim", HandleEditScale); 311 "Change the scale of a named prim", HandleEditScale);
312 312
@@ -349,7 +349,7 @@ namespace OpenSim
349 "show ratings", 349 "show ratings",
350 "Show rating data", HandleShow); 350 "Show rating data", HandleShow);
351 351
352 m_console.Commands.AddCommand("Regions", false, "backup", 352 m_console.Commands.AddCommand("Objects", false, "backup",
353 "backup", 353 "backup",
354 "Persist currently unsaved object changes immediately instead of waiting for the normal persistence call.", RunCommand); 354 "Persist currently unsaved object changes immediately instead of waiting for the normal persistence call.", RunCommand);
355 355
@@ -409,10 +409,6 @@ namespace OpenSim
409 m_console.Commands.AddCommand("General", false, "modules unload", 409 m_console.Commands.AddCommand("General", false, "modules unload",
410 "modules unload <name>", 410 "modules unload <name>",
411 "Unload a module", HandleModules); 411 "Unload a module", HandleModules);
412
413 m_console.Commands.AddCommand("Regions", false, "kill uuid",
414 "kill uuid <UUID>",
415 "Kill an object by UUID", KillUUID);
416 } 412 }
417 413
418 public override void ShutdownSpecific() 414 public override void ShutdownSpecific()
@@ -437,12 +433,16 @@ namespace OpenSim
437 } 433 }
438 } 434 }
439 435
440 private void WatchdogTimeoutHandler(System.Threading.Thread thread, int lastTick) 436 private void WatchdogTimeoutHandler(Watchdog.ThreadWatchdogInfo twi)
441 { 437 {
442 int now = Environment.TickCount & Int32.MaxValue; 438 int now = Environment.TickCount & Int32.MaxValue;
443 439
444 m_log.ErrorFormat("[WATCHDOG]: Timeout detected for thread \"{0}\". ThreadState={1}. Last tick was {2}ms ago", 440 m_log.ErrorFormat(
445 thread.Name, thread.ThreadState, now - lastTick); 441 "[WATCHDOG]: Timeout detected for thread \"{0}\". ThreadState={1}. Last tick was {2}ms ago. {3}",
442 twi.Thread.Name,
443 twi.Thread.ThreadState,
444 now - twi.LastTick,
445 twi.AlarmMethod != null ? string.Format("Data: {0}", twi.AlarmMethod()) : "");
446 } 446 }
447 447
448 #region Console Commands 448 #region Console Commands
@@ -481,10 +481,10 @@ namespace OpenSim
481 else 481 else
482 presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n"); 482 presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n");
483 483
484 // ...and close on our side
485 presence.Scene.IncomingCloseAgent(presence.UUID); 484 presence.Scene.IncomingCloseAgent(presence.UUID);
486 } 485 }
487 } 486 }
487
488 MainConsole.Instance.Output(""); 488 MainConsole.Instance.Output("");
489 } 489 }
490 490
@@ -618,10 +618,11 @@ namespace OpenSim
618 return; 618 return;
619 } 619 }
620 620
621 PopulateRegionEstateInfo(regInfo); 621 bool changed = PopulateRegionEstateInfo(regInfo);
622 IScene scene; 622 IScene scene;
623 CreateRegion(regInfo, true, out scene); 623 CreateRegion(regInfo, true, out scene);
624 regInfo.EstateSettings.Save(); 624 if (changed)
625 regInfo.EstateSettings.Save();
625 } 626 }
626 627
627 /// <summary> 628 /// <summary>
@@ -903,21 +904,6 @@ namespace OpenSim
903 904
904 break; 905 break;
905 906
906 case "http":
907 if (args.Length == 3)
908 {
909 int newDebug;
910 if (int.TryParse(args[2], out newDebug))
911 {
912 MainServer.Instance.DebugLevel = newDebug;
913 MainConsole.Instance.OutputFormat("Debug http level set to {0}", newDebug);
914 break;
915 }
916 }
917
918 MainConsole.Instance.Output("Usage: debug http 0..2");
919 break;
920
921 case "scene": 907 case "scene":
922 if (args.Length == 4) 908 if (args.Length == 4)
923 { 909 {
@@ -969,8 +955,7 @@ namespace OpenSim
969 if (showParams.Length > 1 && showParams[1] == "full") 955 if (showParams.Length > 1 && showParams[1] == "full")
970 { 956 {
971 agents = m_sceneManager.GetCurrentScenePresences(); 957 agents = m_sceneManager.GetCurrentScenePresences();
972 } 958 } else
973 else
974 { 959 {
975 agents = m_sceneManager.GetCurrentSceneAvatars(); 960 agents = m_sceneManager.GetCurrentSceneAvatars();
976 } 961 }
@@ -979,7 +964,8 @@ namespace OpenSim
979 964
980 MainConsole.Instance.Output( 965 MainConsole.Instance.Output(
981 String.Format("{0,-16} {1,-16} {2,-37} {3,-11} {4,-16} {5,-30}", "Firstname", "Lastname", 966 String.Format("{0,-16} {1,-16} {2,-37} {3,-11} {4,-16} {5,-30}", "Firstname", "Lastname",
982 "Agent ID", "Root/Child", "Region", "Position")); 967 "Agent ID", "Root/Child", "Region", "Position")
968 );
983 969
984 foreach (ScenePresence presence in agents) 970 foreach (ScenePresence presence in agents)
985 { 971 {
@@ -989,8 +975,7 @@ namespace OpenSim
989 if (regionInfo == null) 975 if (regionInfo == null)
990 { 976 {
991 regionName = "Unresolvable"; 977 regionName = "Unresolvable";
992 } 978 } else
993 else
994 { 979 {
995 regionName = regionInfo.RegionName; 980 regionName = regionInfo.RegionName;
996 } 981 }
@@ -1003,43 +988,19 @@ namespace OpenSim
1003 presence.UUID, 988 presence.UUID,
1004 presence.IsChildAgent ? "Child" : "Root", 989 presence.IsChildAgent ? "Child" : "Root",
1005 regionName, 990 regionName,
1006 presence.AbsolutePosition.ToString())); 991 presence.AbsolutePosition.ToString())
992 );
1007 } 993 }
1008 994
1009 MainConsole.Instance.Output(String.Empty); 995 MainConsole.Instance.Output(String.Empty);
1010 break; 996 break;
1011 997
1012 case "connections": 998 case "connections":
1013 System.Text.StringBuilder connections = new System.Text.StringBuilder("Connections:\n"); 999 HandleShowConnections();
1014 m_sceneManager.ForEachScene(
1015 delegate(Scene scene)
1016 {
1017 scene.ForEachClient(
1018 delegate(IClientAPI client)
1019 {
1020 connections.AppendFormat("{0}: {1} ({2}) from {3} on circuit {4}\n",
1021 scene.RegionInfo.RegionName, client.Name, client.AgentId, client.RemoteEndPoint, client.CircuitCode);
1022 }
1023 );
1024 }
1025 );
1026
1027 MainConsole.Instance.Output(connections.ToString());
1028 break; 1000 break;
1029 1001
1030 case "circuits": 1002 case "circuits":
1031 System.Text.StringBuilder acd = new System.Text.StringBuilder("Agent Circuits:\n"); 1003 HandleShowCircuits();
1032 m_sceneManager.ForEachScene(
1033 delegate(Scene scene)
1034 {
1035 //this.HttpServer.
1036 acd.AppendFormat("{0}:\n", scene.RegionInfo.RegionName);
1037 foreach (AgentCircuitData aCircuit in scene.AuthenticateHandler.GetAgentCircuits().Values)
1038 acd.AppendFormat("\t{0} {1} ({2})\n", aCircuit.firstname, aCircuit.lastname, (aCircuit.child ? "Child" : "Root"));
1039 }
1040 );
1041
1042 MainConsole.Instance.Output(acd.ToString());
1043 break; 1004 break;
1044 1005
1045 case "http-handlers": 1006 case "http-handlers":
@@ -1077,17 +1038,29 @@ namespace OpenSim
1077 } 1038 }
1078 1039
1079 m_sceneManager.ForEachScene( 1040 m_sceneManager.ForEachScene(
1080 delegate(Scene scene) 1041 delegate(Scene scene) {
1042 m_log.Error("The currently loaded modules in " + scene.RegionInfo.RegionName + " are:");
1043 foreach (IRegionModule module in scene.Modules.Values)
1081 { 1044 {
1082 m_log.Error("The currently loaded modules in " + scene.RegionInfo.RegionName + " are:"); 1045 if (!module.IsSharedModule)
1083 foreach (IRegionModule module in scene.Modules.Values)
1084 { 1046 {
1085 if (!module.IsSharedModule) 1047 m_log.Error("Region Module: " + module.Name);
1086 {
1087 m_log.Error("Region Module: " + module.Name);
1088 }
1089 } 1048 }
1090 }); 1049 }
1050 }
1051 );
1052
1053 m_sceneManager.ForEachScene(
1054 delegate(Scene scene) {
1055 MainConsole.Instance.Output("Loaded new region modules in" + scene.RegionInfo.RegionName + " are:");
1056 foreach (IRegionModuleBase module in scene.RegionModules.Values)
1057 {
1058 Type type = module.GetType().GetInterface("ISharedRegionModule");
1059 string module_type = type != null ? "Shared" : "Non-Shared";
1060 MainConsole.Instance.OutputFormat("New Region Module ({0}): {1}", module_type, module.Name);
1061 }
1062 }
1063 );
1091 1064
1092 MainConsole.Instance.Output(""); 1065 MainConsole.Instance.Output("");
1093 break; 1066 break;
@@ -1132,6 +1105,53 @@ namespace OpenSim
1132 } 1105 }
1133 } 1106 }
1134 1107
1108 private void HandleShowCircuits()
1109 {
1110 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
1111 cdt.AddColumn("Region", 20);
1112 cdt.AddColumn("Avatar name", 24);
1113 cdt.AddColumn("Type", 5);
1114 cdt.AddColumn("Code", 10);
1115 cdt.AddColumn("IP", 16);
1116 cdt.AddColumn("Viewer Name", 24);
1117
1118 m_sceneManager.ForEachScene(
1119 s =>
1120 {
1121 foreach (AgentCircuitData aCircuit in s.AuthenticateHandler.GetAgentCircuits().Values)
1122 cdt.AddRow(
1123 s.Name,
1124 aCircuit.Name,
1125 aCircuit.child ? "child" : "root",
1126 aCircuit.circuitcode.ToString(),
1127 aCircuit.IPAddress.ToString(),
1128 aCircuit.Viewer);
1129 });
1130
1131 MainConsole.Instance.Output(cdt.ToString());
1132 }
1133
1134 private void HandleShowConnections()
1135 {
1136 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
1137 cdt.AddColumn("Region", 20);
1138 cdt.AddColumn("Avatar name", 24);
1139 cdt.AddColumn("Circuit code", 12);
1140 cdt.AddColumn("Endpoint", 23);
1141 cdt.AddColumn("Active?", 7);
1142
1143 m_sceneManager.ForEachScene(
1144 s => s.ForEachClient(
1145 c => cdt.AddRow(
1146 s.Name,
1147 c.Name,
1148 c.RemoteEndPoint.ToString(),
1149 c.CircuitCode.ToString(),
1150 c.IsActive.ToString())));
1151
1152 MainConsole.Instance.Output(cdt.ToString());
1153 }
1154
1135 /// <summary> 1155 /// <summary>
1136 /// Use XML2 format to serialize data to a file 1156 /// Use XML2 format to serialize data to a file
1137 /// </summary> 1157 /// </summary>
@@ -1299,58 +1319,6 @@ namespace OpenSim
1299 return result; 1319 return result;
1300 } 1320 }
1301 1321
1302 /// <summary>
1303 /// Kill an object given its UUID.
1304 /// </summary>
1305 /// <param name="cmdparams"></param>
1306 protected void KillUUID(string module, string[] cmdparams)
1307 {
1308 if (cmdparams.Length > 2)
1309 {
1310 UUID id = UUID.Zero;
1311 SceneObjectGroup grp = null;
1312 Scene sc = null;
1313
1314 if (!UUID.TryParse(cmdparams[2], out id))
1315 {
1316 MainConsole.Instance.Output("[KillUUID]: Error bad UUID format!");
1317 return;
1318 }
1319
1320 m_sceneManager.ForEachScene(
1321 delegate(Scene scene)
1322 {
1323 SceneObjectPart part = scene.GetSceneObjectPart(id);
1324 if (part == null)
1325 return;
1326
1327 grp = part.ParentGroup;
1328 sc = scene;
1329 });
1330
1331 if (grp == null)
1332 {
1333 MainConsole.Instance.Output(String.Format("[KillUUID]: Given UUID {0} not found!", id));
1334 }
1335 else
1336 {
1337 MainConsole.Instance.Output(String.Format("[KillUUID]: Found UUID {0} in scene {1}", id, sc.RegionInfo.RegionName));
1338 try
1339 {
1340 sc.DeleteSceneObject(grp, false);
1341 }
1342 catch (Exception e)
1343 {
1344 m_log.ErrorFormat("[KillUUID]: Error while removing objects from scene: " + e);
1345 }
1346 }
1347 }
1348 else
1349 {
1350 MainConsole.Instance.Output("[KillUUID]: Usage: kill uuid <UUID>");
1351 }
1352 }
1353
1354 #endregion 1322 #endregion
1355 } 1323 }
1356} 1324}
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index ddc7f10..76ac246 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -232,7 +232,7 @@ namespace OpenSim
232 232
233 base.StartupSpecific(); 233 base.StartupSpecific();
234 234
235 m_stats = StatsManager.StartCollectingSimExtraStats(); 235 m_stats = StatsManager.SimExtraStats;
236 236
237 // Create a ModuleLoader instance 237 // Create a ModuleLoader instance
238 m_moduleLoader = new ModuleLoader(m_config.Source); 238 m_moduleLoader = new ModuleLoader(m_config.Source);
@@ -437,7 +437,7 @@ namespace OpenSim
437 scene.LoadPrimsFromStorage(regionInfo.originRegionID); 437 scene.LoadPrimsFromStorage(regionInfo.originRegionID);
438 438
439 // TODO : Try setting resource for region xstats here on scene 439 // TODO : Try setting resource for region xstats here on scene
440 MainServer.Instance.AddStreamHandler(new Region.Framework.Scenes.RegionStatsHandler(regionInfo)); 440 MainServer.Instance.AddStreamHandler(new RegionStatsHandler(regionInfo));
441 441
442 scene.loadAllLandObjectsFromStorage(regionInfo.originRegionID); 442 scene.loadAllLandObjectsFromStorage(regionInfo.originRegionID);
443 scene.EventManager.TriggerParcelPrimCountUpdate(); 443 scene.EventManager.TriggerParcelPrimCountUpdate();
@@ -856,6 +856,9 @@ namespace OpenSim
856 return Util.UTF8.GetBytes("OK"); 856 return Util.UTF8.GetBytes("OK");
857 } 857 }
858 858
859 public string Name { get { return "SimStatus"; } }
860 public string Description { get { return "Simulator Status"; } }
861
859 public string ContentType 862 public string ContentType
860 { 863 {
861 get { return "text/plain"; } 864 get { return "text/plain"; }
@@ -880,6 +883,9 @@ namespace OpenSim
880 { 883 {
881 OpenSimBase m_opensim; 884 OpenSimBase m_opensim;
882 string osXStatsURI = String.Empty; 885 string osXStatsURI = String.Empty;
886
887 public string Name { get { return "XSimStatus"; } }
888 public string Description { get { return "Simulator XStatus"; } }
883 889
884 public XSimStatusHandler(OpenSimBase sim) 890 public XSimStatusHandler(OpenSimBase sim)
885 { 891 {
@@ -920,6 +926,9 @@ namespace OpenSim
920 { 926 {
921 OpenSimBase m_opensim; 927 OpenSimBase m_opensim;
922 string osUXStatsURI = String.Empty; 928 string osUXStatsURI = String.Empty;
929
930 public string Name { get { return "UXSimStatus"; } }
931 public string Description { get { return "Simulator UXStatus"; } }
923 932
924 public UXSimStatusHandler(OpenSimBase sim) 933 public UXSimStatusHandler(OpenSimBase sim)
925 { 934 {
@@ -1051,13 +1060,13 @@ namespace OpenSim
1051 /// Load the estate information for the provided RegionInfo object. 1060 /// Load the estate information for the provided RegionInfo object.
1052 /// </summary> 1061 /// </summary>
1053 /// <param name="regInfo"></param> 1062 /// <param name="regInfo"></param>
1054 public void PopulateRegionEstateInfo(RegionInfo regInfo) 1063 public bool PopulateRegionEstateInfo(RegionInfo regInfo)
1055 { 1064 {
1056 if (EstateDataService != null) 1065 if (EstateDataService != null)
1057 regInfo.EstateSettings = EstateDataService.LoadEstateSettings(regInfo.RegionID, false); 1066 regInfo.EstateSettings = EstateDataService.LoadEstateSettings(regInfo.RegionID, false);
1058 1067
1059 if (regInfo.EstateSettings.EstateID != 0) 1068 if (regInfo.EstateSettings.EstateID != 0)
1060 return; 1069 return false; // estate info in the database did not change
1061 1070
1062 m_log.WarnFormat("[ESTATE] Region {0} is not part of an estate.", regInfo.RegionName); 1071 m_log.WarnFormat("[ESTATE] Region {0} is not part of an estate.", regInfo.RegionName);
1063 1072
@@ -1092,7 +1101,7 @@ namespace OpenSim
1092 } 1101 }
1093 1102
1094 if (defaultEstateJoined) 1103 if (defaultEstateJoined)
1095 return; 1104 return true; // need to update the database
1096 else 1105 else
1097 m_log.ErrorFormat( 1106 m_log.ErrorFormat(
1098 "[OPENSIM BASE]: Joining default estate {0} failed", defaultEstateName); 1107 "[OPENSIM BASE]: Joining default estate {0} failed", defaultEstateName);
@@ -1154,8 +1163,10 @@ namespace OpenSim
1154 MainConsole.Instance.Output("Joining the estate failed. Please try again."); 1163 MainConsole.Instance.Output("Joining the estate failed. Please try again.");
1155 } 1164 }
1156 } 1165 }
1157 } 1166 }
1158 } 1167
1168 return true; // need to update the database
1169 }
1159 } 1170 }
1160 1171
1161 public class OpenSimConfigSource 1172 public class OpenSimConfigSource
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
index ef6dedb..d397893 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
@@ -158,7 +158,9 @@ namespace OpenSim.Region.ClientStack.Linden
158 try 158 try
159 { 159 {
160 // the root of all evil 160 // the root of all evil
161 m_HostCapsObj.RegisterHandler("SEED", new RestStreamHandler("POST", capsBase + m_requestPath, SeedCapRequest)); 161 m_HostCapsObj.RegisterHandler(
162 "SEED", new RestStreamHandler("POST", capsBase + m_requestPath, SeedCapRequest, "SEED", null));
163
162 m_log.DebugFormat( 164 m_log.DebugFormat(
163 "[CAPS]: Registered seed capability {0} for {1}", capsBase + m_requestPath, m_HostCapsObj.AgentID); 165 "[CAPS]: Registered seed capability {0} for {1}", capsBase + m_requestPath, m_HostCapsObj.AgentID);
164 166
@@ -166,7 +168,10 @@ namespace OpenSim.Region.ClientStack.Linden
166 // new LLSDStreamhandler<OSDMapRequest, OSDMapLayerResponse>("POST", 168 // new LLSDStreamhandler<OSDMapRequest, OSDMapLayerResponse>("POST",
167 // capsBase + m_mapLayerPath, 169 // capsBase + m_mapLayerPath,
168 // GetMapLayer); 170 // GetMapLayer);
169 IRequestHandler req = new RestStreamHandler("POST", capsBase + m_notecardTaskUpdatePath, ScriptTaskInventory); 171 IRequestHandler req
172 = new RestStreamHandler(
173 "POST", capsBase + m_notecardTaskUpdatePath, ScriptTaskInventory, "UpdateScript", null);
174
170 m_HostCapsObj.RegisterHandler("UpdateScriptTaskInventory", req); 175 m_HostCapsObj.RegisterHandler("UpdateScriptTaskInventory", req);
171 m_HostCapsObj.RegisterHandler("UpdateScriptTask", req); 176 m_HostCapsObj.RegisterHandler("UpdateScriptTask", req);
172 } 177 }
@@ -181,14 +186,22 @@ namespace OpenSim.Region.ClientStack.Linden
181 try 186 try
182 { 187 {
183 // I don't think this one works... 188 // I don't think this one works...
184 m_HostCapsObj.RegisterHandler("NewFileAgentInventory", new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDAssetUploadResponse>("POST", 189 m_HostCapsObj.RegisterHandler(
185 capsBase + m_newInventory, 190 "NewFileAgentInventory",
186 NewAgentInventoryRequest)); 191 new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDAssetUploadResponse>(
187 IRequestHandler req = new RestStreamHandler("POST", capsBase + m_notecardUpdatePath, NoteCardAgentInventory); 192 "POST",
193 capsBase + m_newInventory,
194 NewAgentInventoryRequest,
195 "NewFileAgentInventory",
196 null));
197
198 IRequestHandler req
199 = new RestStreamHandler(
200 "POST", capsBase + m_notecardUpdatePath, NoteCardAgentInventory, "Update*", null);
201
188 m_HostCapsObj.RegisterHandler("UpdateNotecardAgentInventory", req); 202 m_HostCapsObj.RegisterHandler("UpdateNotecardAgentInventory", req);
189 m_HostCapsObj.RegisterHandler("UpdateScriptAgentInventory", req); 203 m_HostCapsObj.RegisterHandler("UpdateScriptAgentInventory", req);
190 m_HostCapsObj.RegisterHandler("UpdateScriptAgent", req); 204 m_HostCapsObj.RegisterHandler("UpdateScriptAgent", req);
191 m_HostCapsObj.RegisterHandler("CopyInventoryFromNotecard", new RestStreamHandler("POST", capsBase + m_copyFromNotecardPath, CopyInventoryFromNotecard));
192 IRequestHandler getObjectPhysicsDataHandler = new RestStreamHandler("POST", capsBase + m_getObjectPhysicsDataPath, GetObjectPhysicsData); 205 IRequestHandler getObjectPhysicsDataHandler = new RestStreamHandler("POST", capsBase + m_getObjectPhysicsDataPath, GetObjectPhysicsData);
193 m_HostCapsObj.RegisterHandler("GetObjectPhysicsData", getObjectPhysicsDataHandler); 206 m_HostCapsObj.RegisterHandler("GetObjectPhysicsData", getObjectPhysicsDataHandler);
194 IRequestHandler getObjectCostHandler = new RestStreamHandler("POST", capsBase + m_getObjectCostPath, GetObjectCost); 207 IRequestHandler getObjectCostHandler = new RestStreamHandler("POST", capsBase + m_getObjectCostPath, GetObjectCost);
@@ -197,6 +210,12 @@ namespace OpenSim.Region.ClientStack.Linden
197 m_HostCapsObj.RegisterHandler("ResourceCostSelected", ResourceCostSelectedHandler); 210 m_HostCapsObj.RegisterHandler("ResourceCostSelected", ResourceCostSelectedHandler);
198 211
199 212
213
214 m_HostCapsObj.RegisterHandler(
215 "CopyInventoryFromNotecard",
216 new RestStreamHandler(
217 "POST", capsBase + m_copyFromNotecardPath, CopyInventoryFromNotecard, "CopyInventoryFromNotecard", null));
218
200 // As of RC 1.22.9 of the Linden client this is 219 // As of RC 1.22.9 of the Linden client this is
201 // supported 220 // supported
202 221
@@ -245,7 +264,10 @@ namespace OpenSim.Region.ClientStack.Linden
245 264
246 if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint)) 265 if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint))
247 { 266 {
248 m_log.DebugFormat("[CAPS]: Unauthorized CAPS client"); 267 m_log.DebugFormat(
268 "[CAPS]: Unauthorized CAPS client {0} from {1}",
269 m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint);
270
249 return string.Empty; 271 return string.Empty;
250 } 272 }
251 273
@@ -296,7 +318,9 @@ namespace OpenSim.Region.ClientStack.Linden
296 m_dumpAssetsToFile); 318 m_dumpAssetsToFile);
297 uploader.OnUpLoad += TaskScriptUpdated; 319 uploader.OnUpLoad += TaskScriptUpdated;
298 320
299 m_HostCapsObj.HttpListener.AddStreamHandler(new BinaryStreamHandler("POST", capsBase + uploaderPath, uploader.uploaderCaps)); 321 m_HostCapsObj.HttpListener.AddStreamHandler(
322 new BinaryStreamHandler(
323 "POST", capsBase + uploaderPath, uploader.uploaderCaps, "TaskInventoryScriptUpdater", null));
300 324
301 string protocol = "http://"; 325 string protocol = "http://";
302 326
@@ -423,8 +447,14 @@ namespace OpenSim.Region.ClientStack.Linden
423 AssetUploader uploader = 447 AssetUploader uploader =
424 new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type, 448 new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type,
425 llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile); 449 llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile);
450
426 m_HostCapsObj.HttpListener.AddStreamHandler( 451 m_HostCapsObj.HttpListener.AddStreamHandler(
427 new BinaryStreamHandler("POST", capsBase + uploaderPath, uploader.uploaderCaps)); 452 new BinaryStreamHandler(
453 "POST",
454 capsBase + uploaderPath,
455 uploader.uploaderCaps,
456 "NewAgentInventoryRequest",
457 m_HostCapsObj.AgentID.ToString()));
428 458
429 string protocol = "http://"; 459 string protocol = "http://";
430 460
@@ -740,7 +770,8 @@ namespace OpenSim.Region.ClientStack.Linden
740 uploader.OnUpLoad += ItemUpdated; 770 uploader.OnUpLoad += ItemUpdated;
741 771
742 m_HostCapsObj.HttpListener.AddStreamHandler( 772 m_HostCapsObj.HttpListener.AddStreamHandler(
743 new BinaryStreamHandler("POST", capsBase + uploaderPath, uploader.uploaderCaps)); 773 new BinaryStreamHandler(
774 "POST", capsBase + uploaderPath, uploader.uploaderCaps, "NoteCardAgentInventory", null));
744 775
745 string protocol = "http://"; 776 string protocol = "http://";
746 777
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
index 016ed97..ebfe687 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
@@ -106,13 +106,14 @@ namespace OpenSim.Region.ClientStack.Linden
106 scene.EventManager.OnRegisterCaps += OnRegisterCaps; 106 scene.EventManager.OnRegisterCaps += OnRegisterCaps;
107 107
108 MainConsole.Instance.Commands.AddCommand( 108 MainConsole.Instance.Commands.AddCommand(
109 "Comms", 109 "Debug",
110 false, 110 false,
111 "debug eq", 111 "debug eq",
112 "debug eq [0|1]", 112 "debug eq [0|1|2]",
113 "Turn on event queue debugging", 113 "Turn on event queue debugging"
114 "debug eq 1 will turn on event queue debugging. This will log all outgoing event queue messages to clients.\n" 114 + "<= 0 - turns off all event queue logging"
115 + "debug eq 0 will turn off event queue debugging.", 115 + ">= 1 - turns on outgoing event logging"
116 + ">= 2 - turns on poll notification",
116 HandleDebugEq); 117 HandleDebugEq);
117 } 118 }
118 else 119 else
@@ -235,19 +236,19 @@ namespace OpenSim.Region.ClientStack.Linden
235// ClientClosed(client.AgentId); 236// ClientClosed(client.AgentId);
236// } 237// }
237 238
238 private void ClientClosed(UUID AgentID, Scene scene) 239 private void ClientClosed(UUID agentID, Scene scene)
239 { 240 {
240// m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", AgentID, m_scene.RegionInfo.RegionName); 241// m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName);
241 242
242 int count = 0; 243 int count = 0;
243 while (queues.ContainsKey(AgentID) && queues[AgentID].Count > 0 && count++ < 5) 244 while (queues.ContainsKey(agentID) && queues[agentID].Count > 0 && count++ < 5)
244 { 245 {
245 Thread.Sleep(1000); 246 Thread.Sleep(1000);
246 } 247 }
247 248
248 lock (queues) 249 lock (queues)
249 { 250 {
250 queues.Remove(AgentID); 251 queues.Remove(agentID);
251 } 252 }
252 253
253 List<UUID> removeitems = new List<UUID>(); 254 List<UUID> removeitems = new List<UUID>();
@@ -256,7 +257,7 @@ namespace OpenSim.Region.ClientStack.Linden
256 foreach (UUID ky in m_AvatarQueueUUIDMapping.Keys) 257 foreach (UUID ky in m_AvatarQueueUUIDMapping.Keys)
257 { 258 {
258// m_log.DebugFormat("[EVENTQUEUE]: Found key {0} in m_AvatarQueueUUIDMapping while looking for {1}", ky, AgentID); 259// m_log.DebugFormat("[EVENTQUEUE]: Found key {0} in m_AvatarQueueUUIDMapping while looking for {1}", ky, AgentID);
259 if (ky == AgentID) 260 if (ky == agentID)
260 { 261 {
261 removeitems.Add(ky); 262 removeitems.Add(ky);
262 } 263 }
@@ -267,7 +268,12 @@ namespace OpenSim.Region.ClientStack.Linden
267 UUID eventQueueGetUuid = m_AvatarQueueUUIDMapping[ky]; 268 UUID eventQueueGetUuid = m_AvatarQueueUUIDMapping[ky];
268 m_AvatarQueueUUIDMapping.Remove(ky); 269 m_AvatarQueueUUIDMapping.Remove(ky);
269 270
270 MainServer.Instance.RemovePollServiceHTTPHandler("","/CAPS/EQG/" + eventQueueGetUuid.ToString() + "/"); 271 string eqgPath = GenerateEqgCapPath(eventQueueGetUuid);
272 MainServer.Instance.RemovePollServiceHTTPHandler("", eqgPath);
273
274// m_log.DebugFormat(
275// "[EVENT QUEUE GET MODULE]: Removed EQG handler {0} for {1} in {2}",
276// eqgPath, agentID, m_scene.RegionInfo.RegionName);
271 } 277 }
272 } 278 }
273 279
@@ -281,7 +287,7 @@ namespace OpenSim.Region.ClientStack.Linden
281 { 287 {
282 searchval = m_QueueUUIDAvatarMapping[ky]; 288 searchval = m_QueueUUIDAvatarMapping[ky];
283 289
284 if (searchval == AgentID) 290 if (searchval == agentID)
285 { 291 {
286 removeitems.Add(ky); 292 removeitems.Add(ky);
287 } 293 }
@@ -305,6 +311,15 @@ namespace OpenSim.Region.ClientStack.Linden
305 //} 311 //}
306 } 312 }
307 313
314 /// <summary>
315 /// Generate an Event Queue Get handler path for the given eqg uuid.
316 /// </summary>
317 /// <param name='eqgUuid'></param>
318 private string GenerateEqgCapPath(UUID eqgUuid)
319 {
320 return string.Format("/CAPS/EQG/{0}/", eqgUuid);
321 }
322
308 public void OnRegisterCaps(UUID agentID, Caps caps) 323 public void OnRegisterCaps(UUID agentID, Caps caps)
309 { 324 {
310 // Register an event queue for the client 325 // Register an event queue for the client
@@ -316,8 +331,7 @@ namespace OpenSim.Region.ClientStack.Linden
316 // Let's instantiate a Queue for this agent right now 331 // Let's instantiate a Queue for this agent right now
317 TryGetQueue(agentID); 332 TryGetQueue(agentID);
318 333
319 string capsBase = "/CAPS/EQG/"; 334 UUID eventQueueGetUUID;
320 UUID EventQueueGetUUID = UUID.Zero;
321 335
322 lock (m_AvatarQueueUUIDMapping) 336 lock (m_AvatarQueueUUIDMapping)
323 { 337 {
@@ -325,43 +339,49 @@ namespace OpenSim.Region.ClientStack.Linden
325 if (m_AvatarQueueUUIDMapping.ContainsKey(agentID)) 339 if (m_AvatarQueueUUIDMapping.ContainsKey(agentID))
326 { 340 {
327 //m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID!"); 341 //m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID!");
328 EventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID]; 342 eventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID];
329 } 343 }
330 else 344 else
331 { 345 {
332 EventQueueGetUUID = UUID.Random(); 346 eventQueueGetUUID = UUID.Random();
333 //m_log.DebugFormat("[EVENTQUEUE]: Using random UUID!"); 347 //m_log.DebugFormat("[EVENTQUEUE]: Using random UUID!");
334 } 348 }
335 } 349 }
336 350
337 lock (m_QueueUUIDAvatarMapping) 351 lock (m_QueueUUIDAvatarMapping)
338 { 352 {
339 if (!m_QueueUUIDAvatarMapping.ContainsKey(EventQueueGetUUID)) 353 if (!m_QueueUUIDAvatarMapping.ContainsKey(eventQueueGetUUID))
340 m_QueueUUIDAvatarMapping.Add(EventQueueGetUUID, agentID); 354 m_QueueUUIDAvatarMapping.Add(eventQueueGetUUID, agentID);
341 } 355 }
342 356
343 lock (m_AvatarQueueUUIDMapping) 357 lock (m_AvatarQueueUUIDMapping)
344 { 358 {
345 if (!m_AvatarQueueUUIDMapping.ContainsKey(agentID)) 359 if (!m_AvatarQueueUUIDMapping.ContainsKey(agentID))
346 m_AvatarQueueUUIDMapping.Add(agentID, EventQueueGetUUID); 360 m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID);
347 } 361 }
348 362
363 string eventQueueGetPath = GenerateEqgCapPath(eventQueueGetUUID);
364
349 // Register this as a caps handler 365 // Register this as a caps handler
350 // FIXME: Confusingly, we need to register separate as a capability so that the client is told about 366 // FIXME: Confusingly, we need to register separate as a capability so that the client is told about
351 // EventQueueGet when it receive capability information, but then we replace the rest handler immediately 367 // EventQueueGet when it receive capability information, but then we replace the rest handler immediately
352 // afterwards with the poll service. So for now, we'll pass a null instead to simplify code reading, but 368 // afterwards with the poll service. So for now, we'll pass a null instead to simplify code reading, but
353 // really it should be possible to directly register the poll handler as a capability. 369 // really it should be possible to directly register the poll handler as a capability.
354 caps.RegisterHandler("EventQueueGet", 370 caps.RegisterHandler("EventQueueGet", new RestHTTPHandler("POST", eventQueueGetPath, null));
355 new RestHTTPHandler("POST", capsBase + EventQueueGetUUID.ToString() + "/", null));
356// delegate(Hashtable m_dhttpMethod) 371// delegate(Hashtable m_dhttpMethod)
357// { 372// {
358// return ProcessQueue(m_dhttpMethod, agentID, caps); 373// return ProcessQueue(m_dhttpMethod, agentID, caps);
359// })); 374// }));
360 375
361 // This will persist this beyond the expiry of the caps handlers 376 // This will persist this beyond the expiry of the caps handlers
377 // TODO: Add EventQueueGet name/description for diagnostics
362 MainServer.Instance.AddPollServiceHTTPHandler( 378 MainServer.Instance.AddPollServiceHTTPHandler(
363 capsBase + EventQueueGetUUID.ToString() + "/", 379 eventQueueGetPath,
364 new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, agentID,1000)); // 1 sec timeout 380 new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, agentID, 1000));
381
382// m_log.DebugFormat(
383// "[EVENT QUEUE GET MODULE]: Registered EQG handler {0} for {1} in {2}",
384// eventQueueGetPath, agentID, m_scene.RegionInfo.RegionName);
365 385
366 Random rnd = new Random(Environment.TickCount); 386 Random rnd = new Random(Environment.TickCount);
367 lock (m_ids) 387 lock (m_ids)
@@ -384,9 +404,25 @@ namespace OpenSim.Region.ClientStack.Linden
384 return false; 404 return false;
385 } 405 }
386 406
407 /// <summary>
408 /// Logs a debug line for an outbound event queue message if appropriate.
409 /// </summary>
410 /// <param name='element'>Element containing message</param>
411 private void LogOutboundDebugMessage(OSD element, UUID agentId)
412 {
413 if (element is OSDMap)
414 {
415 OSDMap ev = (OSDMap)element;
416 m_log.DebugFormat(
417 "Eq OUT {0,-30} to {1,-20} {2,-20}",
418 ev["message"], m_scene.GetScenePresence(agentId).Name, m_scene.RegionInfo.RegionName);
419 }
420 }
421
387 public Hashtable GetEvents(UUID requestID, UUID pAgentId, string request) 422 public Hashtable GetEvents(UUID requestID, UUID pAgentId, string request)
388 { 423 {
389// m_log.DebugFormat("[EVENT QUEUE GET MODULE]: Invoked GetEvents() for {0}", pAgentId); 424 if (DebugLevel >= 2)
425 m_log.DebugFormat("POLLED FOR EQ MESSAGES BY {0} in {1}", pAgentId, m_scene.RegionInfo.RegionName);
390 426
391 Queue<OSD> queue = TryGetQueue(pAgentId); 427 Queue<OSD> queue = TryGetQueue(pAgentId);
392 OSD element; 428 OSD element;
@@ -410,13 +446,8 @@ namespace OpenSim.Region.ClientStack.Linden
410 } 446 }
411 else 447 else
412 { 448 {
413 if (DebugLevel > 0 && element is OSDMap) 449 if (DebugLevel > 0)
414 { 450 LogOutboundDebugMessage(element, pAgentId);
415 OSDMap ev = (OSDMap)element;
416 m_log.DebugFormat(
417 "[EVENT QUEUE GET MODULE]: Eq OUT {0} to {1}",
418 ev["message"], m_scene.GetScenePresence(pAgentId).Name);
419 }
420 451
421 array.Add(element); 452 array.Add(element);
422 453
@@ -426,13 +457,8 @@ namespace OpenSim.Region.ClientStack.Linden
426 { 457 {
427 element = queue.Dequeue(); 458 element = queue.Dequeue();
428 459
429 if (DebugLevel > 0 && element is OSDMap) 460 if (DebugLevel > 0)
430 { 461 LogOutboundDebugMessage(element, pAgentId);
431 OSDMap ev = (OSDMap)element;
432 m_log.DebugFormat(
433 "[EVENT QUEUE GET MODULE]: Eq OUT {0} to {1}",
434 ev["message"], m_scene.GetScenePresence(pAgentId).Name);
435 }
436 462
437 array.Add(element); 463 array.Add(element);
438 thisID++; 464 thisID++;
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
index a5209b7..cd70410 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
@@ -51,7 +51,16 @@ namespace OpenSim.Region.ClientStack.Linden.Tests
51 [SetUp] 51 [SetUp]
52 public void SetUp() 52 public void SetUp()
53 { 53 {
54 MainServer.Instance = new BaseHttpServer(9999, false, 9998, ""); 54 uint port = 9999;
55 uint sslPort = 9998;
56
57 // This is an unfortunate bit of clean up we have to do because MainServer manages things through static
58 // variables and the VM is not restarted between tests.
59 MainServer.RemoveHttpServer(port);
60
61 BaseHttpServer server = new BaseHttpServer(port, false, sslPort, "");
62 MainServer.AddHttpServer(server);
63 MainServer.Instance = server;
55 64
56 IConfigSource config = new IniConfigSource(); 65 IConfigSource config = new IniConfigSource();
57 config.AddConfig("Startup"); 66 config.AddConfig("Startup");
@@ -60,7 +69,7 @@ namespace OpenSim.Region.ClientStack.Linden.Tests
60 CapabilitiesModule capsModule = new CapabilitiesModule(); 69 CapabilitiesModule capsModule = new CapabilitiesModule();
61 EventQueueGetModule eqgModule = new EventQueueGetModule(); 70 EventQueueGetModule eqgModule = new EventQueueGetModule();
62 71
63 m_scene = SceneHelpers.SetupScene(); 72 m_scene = new SceneHelpers().SetupScene();
64 SceneHelpers.SetupSceneModules(m_scene, config, capsModule, eqgModule); 73 SceneHelpers.SetupSceneModules(m_scene, config, capsModule, eqgModule);
65 } 74 }
66 75
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/FetchInventory2Module.cs b/OpenSim/Region/ClientStack/Linden/Caps/FetchInventory2Module.cs
index 14501c7..cb5afcc 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/FetchInventory2Module.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/FetchInventory2Module.cs
@@ -132,7 +132,8 @@ namespace OpenSim.Region.ClientStack.Linden
132 capUrl = "/CAPS/" + UUID.Random(); 132 capUrl = "/CAPS/" + UUID.Random();
133 133
134 IRequestHandler reqHandler 134 IRequestHandler reqHandler
135 = new RestStreamHandler("POST", capUrl, m_fetchHandler.FetchInventoryRequest); 135 = new RestStreamHandler(
136 "POST", capUrl, m_fetchHandler.FetchInventoryRequest, capName, agentID.ToString());
136 137
137 caps.RegisterHandler(capName, reqHandler); 138 caps.RegisterHandler(capName, reqHandler);
138 } 139 }
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
index e7bd2e7..0d7b1fc 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
@@ -120,11 +120,13 @@ namespace OpenSim.Region.ClientStack.Linden
120 { 120 {
121// m_log.DebugFormat("[GETMESH]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); 121// m_log.DebugFormat("[GETMESH]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName);
122 GetMeshHandler gmeshHandler = new GetMeshHandler(m_AssetService); 122 GetMeshHandler gmeshHandler = new GetMeshHandler(m_AssetService);
123 IRequestHandler reqHandler = new RestHTTPHandler("GET", "/CAPS/" + UUID.Random(), 123 IRequestHandler reqHandler
124 delegate(Hashtable m_dhttpMethod) 124 = new RestHTTPHandler(
125 { 125 "GET",
126 return gmeshHandler.ProcessGetMesh(m_dhttpMethod, UUID.Zero, null); 126 "/CAPS/" + UUID.Random(),
127 }); 127 httpMethod => gmeshHandler.ProcessGetMesh(httpMethod, UUID.Zero, null),
128 "GetMesh",
129 agentID.ToString());
128 130
129 caps.RegisterHandler("GetMesh", reqHandler); 131 caps.RegisterHandler("GetMesh", reqHandler);
130 } 132 }
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
index fffcee2..5ae9cc3 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
@@ -130,7 +130,9 @@ namespace OpenSim.Region.ClientStack.Linden
130 if (m_URL == "localhost") 130 if (m_URL == "localhost")
131 { 131 {
132// m_log.DebugFormat("[GETTEXTURE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); 132// m_log.DebugFormat("[GETTEXTURE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName);
133 caps.RegisterHandler("GetTexture", new GetTextureHandler("/CAPS/" + capID + "/", m_assetService)); 133 caps.RegisterHandler(
134 "GetTexture",
135 new GetTextureHandler("/CAPS/" + capID + "/", m_assetService, "GetTexture", agentID.ToString()));
134 } 136 }
135 else 137 else
136 { 138 {
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs
index 18c7eae..44a6883 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs
@@ -117,7 +117,9 @@ namespace OpenSim.Region.ClientStack.Linden
117 117
118 public void RegisterCaps(UUID agentID, Caps caps) 118 public void RegisterCaps(UUID agentID, Caps caps)
119 { 119 {
120 IRequestHandler reqHandler = new RestHTTPHandler("GET", "/CAPS/" + UUID.Random(), MeshUploadFlag); 120 IRequestHandler reqHandler
121 = new RestHTTPHandler("GET", "/CAPS/" + UUID.Random(), MeshUploadFlag, "MeshUploadFlag", agentID.ToString());
122
121 caps.RegisterHandler("MeshUploadFlag", reqHandler); 123 caps.RegisterHandler("MeshUploadFlag", reqHandler);
122 m_agentID = agentID; 124 m_agentID = agentID;
123 } 125 }
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/NewFileAgentInventoryVariablePriceModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/NewFileAgentInventoryVariablePriceModule.cs
index 91872c5..52c4f44 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/NewFileAgentInventoryVariablePriceModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/NewFileAgentInventoryVariablePriceModule.cs
@@ -115,67 +115,66 @@ namespace OpenSim.Region.ClientStack.Linden
115 UUID capID = UUID.Random(); 115 UUID capID = UUID.Random();
116 116
117// m_log.Debug("[NEW FILE AGENT INVENTORY VARIABLE PRICE]: /CAPS/" + capID); 117// m_log.Debug("[NEW FILE AGENT INVENTORY VARIABLE PRICE]: /CAPS/" + capID);
118 caps.RegisterHandler("NewFileAgentInventoryVariablePrice", 118 caps.RegisterHandler(
119 119 "NewFileAgentInventoryVariablePrice",
120 new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDNewFileAngentInventoryVariablePriceReplyResponse>("POST", 120 new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDNewFileAngentInventoryVariablePriceReplyResponse>(
121 "/CAPS/" + capID.ToString(), 121 "POST",
122 delegate(LLSDAssetUploadRequest req) 122 "/CAPS/" + capID.ToString(),
123 { 123 req => NewAgentInventoryRequest(req, agentID),
124 return NewAgentInventoryRequest(req,agentID); 124 "NewFileAgentInventoryVariablePrice",
125 })); 125 agentID.ToString()));
126
127 } 126 }
128 127
129 #endregion 128 #endregion
130 129
131 public LLSDNewFileAngentInventoryVariablePriceReplyResponse NewAgentInventoryRequest(LLSDAssetUploadRequest llsdRequest, UUID agentID) 130 public LLSDNewFileAngentInventoryVariablePriceReplyResponse NewAgentInventoryRequest(LLSDAssetUploadRequest llsdRequest, UUID agentID)
132 { 131 {
133
134 //TODO: The Mesh uploader uploads many types of content. If you're going to implement a Money based limit 132 //TODO: The Mesh uploader uploads many types of content. If you're going to implement a Money based limit
135 // You need to be aware of this and 133 // you need to be aware of this
136
137 134
138 //if (llsdRequest.asset_type == "texture" || 135 //if (llsdRequest.asset_type == "texture" ||
139 // llsdRequest.asset_type == "animation" || 136 // llsdRequest.asset_type == "animation" ||
140 // llsdRequest.asset_type == "sound") 137 // llsdRequest.asset_type == "sound")
141 // { 138 // {
142 // check user level 139 // check user level
143 ScenePresence avatar = null;
144 IClientAPI client = null;
145 m_scene.TryGetScenePresence(agentID, out avatar);
146 140
147 if (avatar != null) 141 ScenePresence avatar = null;
142 IClientAPI client = null;
143 m_scene.TryGetScenePresence(agentID, out avatar);
144
145 if (avatar != null)
146 {
147 client = avatar.ControllingClient;
148
149 if (avatar.UserLevel < m_levelUpload)
148 { 150 {
149 client = avatar.ControllingClient; 151 if (client != null)
150 152 client.SendAgentAlertMessage("Unable to upload asset. Insufficient permissions.", false);
151 if (avatar.UserLevel < m_levelUpload) 153
152 { 154 LLSDNewFileAngentInventoryVariablePriceReplyResponse errorResponse = new LLSDNewFileAngentInventoryVariablePriceReplyResponse();
153 if (client != null) 155 errorResponse.rsvp = "";
154 client.SendAgentAlertMessage("Unable to upload asset. Insufficient permissions.", false); 156 errorResponse.state = "error";
155 157 return errorResponse;
156 LLSDNewFileAngentInventoryVariablePriceReplyResponse errorResponse = new LLSDNewFileAngentInventoryVariablePriceReplyResponse();
157 errorResponse.rsvp = "";
158 errorResponse.state = "error";
159 return errorResponse;
160 }
161 } 158 }
159 }
162 160
163 // check funds 161 // check funds
164 IMoneyModule mm = m_scene.RequestModuleInterface<IMoneyModule>(); 162 IMoneyModule mm = m_scene.RequestModuleInterface<IMoneyModule>();
165 163
166 if (mm != null) 164 if (mm != null)
165 {
166 if (!mm.UploadCovered(agentID, mm.UploadCharge))
167 { 167 {
168 if (!mm.UploadCovered(agentID, mm.UploadCharge)) 168 if (client != null)
169 { 169 client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false);
170 if (client != null) 170
171 client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false); 171 LLSDNewFileAngentInventoryVariablePriceReplyResponse errorResponse = new LLSDNewFileAngentInventoryVariablePriceReplyResponse();
172 172 errorResponse.rsvp = "";
173 LLSDNewFileAngentInventoryVariablePriceReplyResponse errorResponse = new LLSDNewFileAngentInventoryVariablePriceReplyResponse(); 173 errorResponse.state = "error";
174 errorResponse.rsvp = ""; 174 return errorResponse;
175 errorResponse.state = "error";
176 return errorResponse;
177 }
178 } 175 }
176 }
177
179 // } 178 // }
180 179
181 string assetName = llsdRequest.name; 180 string assetName = llsdRequest.name;
@@ -189,8 +188,14 @@ namespace OpenSim.Region.ClientStack.Linden
189 AssetUploader uploader = 188 AssetUploader uploader =
190 new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type, 189 new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type,
191 llsdRequest.asset_type, capsBase + uploaderPath, MainServer.Instance, m_dumpAssetsToFile); 190 llsdRequest.asset_type, capsBase + uploaderPath, MainServer.Instance, m_dumpAssetsToFile);
191
192 MainServer.Instance.AddStreamHandler( 192 MainServer.Instance.AddStreamHandler(
193 new BinaryStreamHandler("POST", capsBase + uploaderPath, uploader.uploaderCaps)); 193 new BinaryStreamHandler(
194 "POST",
195 capsBase + uploaderPath,
196 uploader.uploaderCaps,
197 "NewFileAgentInventoryVariablePrice",
198 agentID.ToString()));
194 199
195 string protocol = "http://"; 200 string protocol = "http://";
196 201
@@ -199,10 +204,9 @@ namespace OpenSim.Region.ClientStack.Linden
199 204
200 string uploaderURL = protocol + m_scene.RegionInfo.ExternalHostName + ":" + MainServer.Instance.Port.ToString() + capsBase + 205 string uploaderURL = protocol + m_scene.RegionInfo.ExternalHostName + ":" + MainServer.Instance.Port.ToString() + capsBase +
201 uploaderPath; 206 uploaderPath;
202 207
203 208
204 LLSDNewFileAngentInventoryVariablePriceReplyResponse uploadResponse = new LLSDNewFileAngentInventoryVariablePriceReplyResponse(); 209 LLSDNewFileAngentInventoryVariablePriceReplyResponse uploadResponse = new LLSDNewFileAngentInventoryVariablePriceReplyResponse();
205
206 210
207 uploadResponse.rsvp = uploaderURL; 211 uploadResponse.rsvp = uploaderURL;
208 uploadResponse.state = "upload"; 212 uploadResponse.state = "upload";
@@ -220,6 +224,7 @@ namespace OpenSim.Region.ClientStack.Linden
220 pinventoryItem, pparentFolder, pdata, pinventoryType, 224 pinventoryItem, pparentFolder, pdata, pinventoryType,
221 passetType,agentID); 225 passetType,agentID);
222 }; 226 };
227
223 return uploadResponse; 228 return uploadResponse;
224 } 229 }
225 230
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs
index 1c47f0e..4ccfc43 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs
@@ -66,12 +66,14 @@ namespace OpenSim.Region.ClientStack.Linden
66 66
67// m_log.InfoFormat("[OBJECTADD]: {0}", "/CAPS/OA/" + capuuid + "/"); 67// m_log.InfoFormat("[OBJECTADD]: {0}", "/CAPS/OA/" + capuuid + "/");
68 68
69 caps.RegisterHandler("ObjectAdd", 69 caps.RegisterHandler(
70 new RestHTTPHandler("POST", "/CAPS/OA/" + capuuid + "/", 70 "ObjectAdd",
71 delegate(Hashtable m_dhttpMethod) 71 new RestHTTPHandler(
72 { 72 "POST",
73 return ProcessAdd(m_dhttpMethod, agentID, caps); 73 "/CAPS/OA/" + capuuid + "/",
74 })); 74 httpMethod => ProcessAdd(httpMethod, agentID, caps),
75 "ObjectAdd",
76 agentID.ToString()));;
75 } 77 }
76 78
77 public Hashtable ProcessAdd(Hashtable request, UUID AgentId, Caps cap) 79 public Hashtable ProcessAdd(Hashtable request, UUID AgentId, Caps cap)
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs
index 7a3d97e..ba902b2 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs
@@ -106,12 +106,15 @@ namespace OpenSim.Region.ClientStack.Linden
106 UUID capID = UUID.Random(); 106 UUID capID = UUID.Random();
107 107
108// m_log.Debug("[UPLOAD OBJECT ASSET MODULE]: /CAPS/" + capID); 108// m_log.Debug("[UPLOAD OBJECT ASSET MODULE]: /CAPS/" + capID);
109 caps.RegisterHandler("UploadObjectAsset", 109 caps.RegisterHandler(
110 new RestHTTPHandler("POST", "/CAPS/OA/" + capID + "/", 110 "UploadObjectAsset",
111 delegate(Hashtable m_dhttpMethod) 111 new RestHTTPHandler(
112 { 112 "POST",
113 return ProcessAdd(m_dhttpMethod, agentID, caps); 113 "/CAPS/OA/" + capID + "/",
114 })); 114 httpMethod => ProcessAdd(httpMethod, agentID, caps),
115 "UploadObjectAsset",
116 agentID.ToString()));
117
115 /* 118 /*
116 caps.RegisterHandler("NewFileAgentInventoryVariablePrice", 119 caps.RegisterHandler("NewFileAgentInventoryVariablePrice",
117 120
@@ -330,7 +333,6 @@ namespace OpenSim.Region.ClientStack.Linden
330 grp.AbsolutePosition = obj.Position; 333 grp.AbsolutePosition = obj.Position;
331 prim.RotationOffset = obj.Rotation; 334 prim.RotationOffset = obj.Rotation;
332 335
333 grp.IsAttachment = false;
334 // Required for linking 336 // Required for linking
335 grp.RootPart.ClearUpdateSchedule(); 337 grp.RootPart.ClearUpdateSchedule();
336 338
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
index 1dd8938..8ed0fb3 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
@@ -154,7 +154,9 @@ namespace OpenSim.Region.ClientStack.Linden
154 public void RegisterCaps(UUID agentID, Caps caps) 154 public void RegisterCaps(UUID agentID, Caps caps)
155 { 155 {
156 IRequestHandler reqHandler 156 IRequestHandler reqHandler
157 = new RestHTTPHandler("GET", "/CAPS/" + UUID.Random(), HandleSimulatorFeaturesRequest); 157 = new RestHTTPHandler(
158 "GET", "/CAPS/" + UUID.Random(),
159 HandleSimulatorFeaturesRequest, "SimulatorFeatures", agentID.ToString());
158 160
159 caps.RegisterHandler("SimulatorFeatures", reqHandler); 161 caps.RegisterHandler("SimulatorFeatures", reqHandler);
160 } 162 }
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
index 45d6071..b3d61a8 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
@@ -106,7 +106,9 @@ namespace OpenSim.Region.ClientStack.Linden
106 "POST", 106 "POST",
107 "/CAPS/" + caps.CapsObjectPath + m_uploadBakedTexturePath, 107 "/CAPS/" + caps.CapsObjectPath + m_uploadBakedTexturePath,
108 new UploadBakedTextureHandler( 108 new UploadBakedTextureHandler(
109 caps, m_scene.AssetService, m_persistBakedTextures).UploadBakedTexture)); 109 caps, m_scene.AssetService, m_persistBakedTextures).UploadBakedTexture,
110 "UploadBakedTexture",
111 agentID.ToString()));
110 } 112 }
111 } 113 }
112} \ No newline at end of file 114} \ No newline at end of file
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
index 10f43d1..2359bd6 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
@@ -144,7 +144,12 @@ namespace OpenSim.Region.ClientStack.Linden
144 capUrl = "/CAPS/" + UUID.Random(); 144 capUrl = "/CAPS/" + UUID.Random();
145 145
146 IRequestHandler reqHandler 146 IRequestHandler reqHandler
147 = new RestStreamHandler("POST", capUrl, m_webFetchHandler.FetchInventoryDescendentsRequest); 147 = new RestStreamHandler(
148 "POST",
149 capUrl,
150 m_webFetchHandler.FetchInventoryDescendentsRequest,
151 "FetchInventoryDescendents2",
152 agentID.ToString());
148 153
149 caps.RegisterHandler(capName, reqHandler); 154 caps.RegisterHandler(capName, reqHandler);
150 } 155 }
@@ -160,4 +165,4 @@ namespace OpenSim.Region.ClientStack.Linden
160// capName, capUrl, m_scene.RegionInfo.RegionName, agentID); 165// capName, capUrl, m_scene.RegionInfo.RegionName, agentID);
161 } 166 }
162 } 167 }
163} 168} \ No newline at end of file
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs
index 90b3ede..1b8535c 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs
@@ -39,7 +39,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
39 public sealed class IncomingPacket 39 public sealed class IncomingPacket
40 { 40 {
41 /// <summary>Client this packet came from</summary> 41 /// <summary>Client this packet came from</summary>
42 public LLUDPClient Client; 42 public LLClientView Client;
43
43 /// <summary>Packet data that has been received</summary> 44 /// <summary>Packet data that has been received</summary>
44 public Packet Packet; 45 public Packet Packet;
45 46
@@ -48,7 +49,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
48 /// </summary> 49 /// </summary>
49 /// <param name="client">Reference to the client this packet came from</param> 50 /// <param name="client">Reference to the client this packet came from</param>
50 /// <param name="packet">Packet data</param> 51 /// <param name="packet">Packet data</param>
51 public IncomingPacket(LLUDPClient client, Packet packet) 52 public IncomingPacket(LLClientView client, Packet packet)
52 { 53 {
53 Client = client; 54 Client = client;
54 Packet = packet; 55 Packet = packet;
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 9c96b52..e6289bd 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -59,7 +59,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
59 /// Handles new client connections 59 /// Handles new client connections
60 /// Constructor takes a single Packet and authenticates everything 60 /// Constructor takes a single Packet and authenticates everything
61 /// </summary> 61 /// </summary>
62 public class LLClientView : IClientAPI, IClientCore, IClientIM, IClientChat, IClientInventory, IClientIPEndpoint, IStatsCollector 62 public class LLClientView : IClientAPI, IClientCore, IClientIM, IClientChat, IClientInventory, IStatsCollector
63 { 63 {
64 /// <value> 64 /// <value>
65 /// Debug packet level. See OpenSim.RegisterConsoleCommands() for more details. 65 /// Debug packet level. See OpenSim.RegisterConsoleCommands() for more details.
@@ -365,7 +365,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
365 protected string m_lastName; 365 protected string m_lastName;
366 protected Thread m_clientThread; 366 protected Thread m_clientThread;
367 protected Vector3 m_startpos; 367 protected Vector3 m_startpos;
368 protected EndPoint m_userEndPoint;
369 protected UUID m_activeGroupID; 368 protected UUID m_activeGroupID;
370 protected string m_activeGroupName = String.Empty; 369 protected string m_activeGroupName = String.Empty;
371 protected ulong m_activeGroupPowers; 370 protected ulong m_activeGroupPowers;
@@ -458,7 +457,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
458 /// <summary> 457 /// <summary>
459 /// Constructor 458 /// Constructor
460 /// </summary> 459 /// </summary>
461 public LLClientView(EndPoint remoteEP, Scene scene, LLUDPServer udpServer, LLUDPClient udpClient, AuthenticateResponse sessionInfo, 460 public LLClientView(Scene scene, LLUDPServer udpServer, LLUDPClient udpClient, AuthenticateResponse sessionInfo,
462 UUID agentId, UUID sessionId, uint circuitCode) 461 UUID agentId, UUID sessionId, uint circuitCode)
463 { 462 {
464// DebugPacketLevel = 1; 463// DebugPacketLevel = 1;
@@ -466,7 +465,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
466 RegisterInterface<IClientIM>(this); 465 RegisterInterface<IClientIM>(this);
467 RegisterInterface<IClientInventory>(this); 466 RegisterInterface<IClientInventory>(this);
468 RegisterInterface<IClientChat>(this); 467 RegisterInterface<IClientChat>(this);
469 RegisterInterface<IClientIPEndpoint>(this);
470 468
471 m_scene = scene; 469 m_scene = scene;
472 m_entityUpdates = new PriorityQueue(m_scene.Entities.Count); 470 m_entityUpdates = new PriorityQueue(m_scene.Entities.Count);
@@ -483,7 +481,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
483 m_sessionId = sessionId; 481 m_sessionId = sessionId;
484 m_secureSessionId = sessionInfo.LoginInfo.SecureSession; 482 m_secureSessionId = sessionInfo.LoginInfo.SecureSession;
485 m_circuitCode = circuitCode; 483 m_circuitCode = circuitCode;
486 m_userEndPoint = remoteEP;
487 m_firstName = sessionInfo.LoginInfo.First; 484 m_firstName = sessionInfo.LoginInfo.First;
488 m_lastName = sessionInfo.LoginInfo.Last; 485 m_lastName = sessionInfo.LoginInfo.Last;
489 m_startpos = sessionInfo.LoginInfo.StartPos; 486 m_startpos = sessionInfo.LoginInfo.StartPos;
@@ -515,6 +512,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
515 /// </summary> 512 /// </summary>
516 public void Close(bool sendStop) 513 public void Close(bool sendStop)
517 { 514 {
515 IsActive = false;
516
518 m_log.DebugFormat( 517 m_log.DebugFormat(
519 "[CLIENT]: Close has been called for {0} attached to scene {1}", 518 "[CLIENT]: Close has been called for {0} attached to scene {1}",
520 Name, m_scene.RegionInfo.RegionName); 519 Name, m_scene.RegionInfo.RegionName);
@@ -3902,7 +3901,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3902 canUseImproved = false; 3901 canUseImproved = false;
3903 } 3902 }
3904 } 3903 }
3905 3904
3906 #endregion UpdateFlags to packet type conversion 3905 #endregion UpdateFlags to packet type conversion
3907 3906
3908 #region Block Construction 3907 #region Block Construction
@@ -11866,7 +11865,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11866 if (DebugPacketLevel <= 100 && (packet.Type == PacketType.AvatarAnimation || packet.Type == PacketType.ViewerEffect)) 11865 if (DebugPacketLevel <= 100 && (packet.Type == PacketType.AvatarAnimation || packet.Type == PacketType.ViewerEffect))
11867 logPacket = false; 11866 logPacket = false;
11868 11867
11869 if (DebugPacketLevel <= 50 && packet.Type == PacketType.ImprovedTerseObjectUpdate) 11868 if (DebugPacketLevel <= 50
11869 & (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate))
11870 logPacket = false; 11870 logPacket = false;
11871 11871
11872 if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily) 11872 if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily)
@@ -11979,7 +11979,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11979 { 11979 {
11980 ClientInfo info = m_udpClient.GetClientInfo(); 11980 ClientInfo info = m_udpClient.GetClientInfo();
11981 11981
11982 info.userEP = m_userEndPoint;
11983 info.proxyEP = null; 11982 info.proxyEP = null;
11984 info.agentcircuit = RequestClientInfo(); 11983 info.agentcircuit = RequestClientInfo();
11985 11984
@@ -11991,11 +11990,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11991 m_udpClient.SetClientInfo(info); 11990 m_udpClient.SetClientInfo(info);
11992 } 11991 }
11993 11992
11994 public EndPoint GetClientEP()
11995 {
11996 return m_userEndPoint;
11997 }
11998
11999 #region Media Parcel Members 11993 #region Media Parcel Members
12000 11994
12001 public void SendParcelMediaCommand(uint flags, ParcelMediaCommandEnum command, float time) 11995 public void SendParcelMediaCommand(uint flags, ParcelMediaCommandEnum command, float time)
@@ -12076,10 +12070,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12076 return string.Empty; 12070 return string.Empty;
12077 } 12071 }
12078 12072
12079 public void KillEndDone()
12080 {
12081 }
12082
12083 #region IClientCore 12073 #region IClientCore
12084 12074
12085 private readonly Dictionary<Type, object> m_clientInterfaces = new Dictionary<Type, object>(); 12075 private readonly Dictionary<Type, object> m_clientInterfaces = new Dictionary<Type, object>();
@@ -12167,21 +12157,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12167 protected void MakeAssetRequest(TransferRequestPacket transferRequest, UUID taskID) 12157 protected void MakeAssetRequest(TransferRequestPacket transferRequest, UUID taskID)
12168 { 12158 {
12169 UUID requestID = UUID.Zero; 12159 UUID requestID = UUID.Zero;
12170 if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset) 12160 int sourceType = transferRequest.TransferInfo.SourceType;
12161
12162 if (sourceType == (int)SourceType.Asset)
12171 { 12163 {
12172 requestID = new UUID(transferRequest.TransferInfo.Params, 0); 12164 requestID = new UUID(transferRequest.TransferInfo.Params, 0);
12173 } 12165 }
12174 else if (transferRequest.TransferInfo.SourceType == (int)SourceType.SimInventoryItem) 12166 else if (sourceType == (int)SourceType.SimInventoryItem)
12175 { 12167 {
12176 requestID = new UUID(transferRequest.TransferInfo.Params, 80); 12168 requestID = new UUID(transferRequest.TransferInfo.Params, 80);
12177 } 12169 }
12178 else if (transferRequest.TransferInfo.SourceType == (int)SourceType.SimEstate) 12170 else if (sourceType == (int)SourceType.SimEstate)
12179 { 12171 {
12180 requestID = taskID; 12172 requestID = taskID;
12181 } 12173 }
12182 12174
12183 12175// m_log.DebugFormat(
12184// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID); 12176// "[LLCLIENTVIEW]: Received transfer request for {0} in {1} type {2} by {3}",
12177// requestID, taskID, (SourceType)sourceType, Name);
12185 12178
12186 12179
12187 //Note, the bool returned from the below function is useless since it is always false. 12180 //Note, the bool returned from the below function is useless since it is always false.
@@ -12270,24 +12263,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12270 return numPackets; 12263 return numPackets;
12271 } 12264 }
12272 12265
12273 #region IClientIPEndpoint Members
12274
12275 public IPAddress EndPoint
12276 {
12277 get
12278 {
12279 if (m_userEndPoint is IPEndPoint)
12280 {
12281 IPEndPoint ep = (IPEndPoint)m_userEndPoint;
12282
12283 return ep.Address;
12284 }
12285 return null;
12286 }
12287 }
12288
12289 #endregion
12290
12291 public void SendRebakeAvatarTextures(UUID textureID) 12266 public void SendRebakeAvatarTextures(UUID textureID)
12292 { 12267 {
12293 RebakeAvatarTexturesPacket pack = 12268 RebakeAvatarTexturesPacket pack =
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index 46337b3..79e35f4 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -147,23 +147,36 @@ namespace OpenSim.Region.ClientStack.LindenUDP
147 private int m_elapsed500MSOutgoingPacketHandler; 147 private int m_elapsed500MSOutgoingPacketHandler;
148 148
149 /// <summary>Flag to signal when clients should check for resends</summary> 149 /// <summary>Flag to signal when clients should check for resends</summary>
150 private bool m_resendUnacked; 150 protected bool m_resendUnacked;
151
151 /// <summary>Flag to signal when clients should send ACKs</summary> 152 /// <summary>Flag to signal when clients should send ACKs</summary>
152 private bool m_sendAcks; 153 protected bool m_sendAcks;
154
153 /// <summary>Flag to signal when clients should send pings</summary> 155 /// <summary>Flag to signal when clients should send pings</summary>
154 private bool m_sendPing; 156 protected bool m_sendPing;
155 157
156 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>(); 158 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>();
157 159
158 private int m_defaultRTO = 0; 160 private int m_defaultRTO = 0;
159 private int m_maxRTO = 0; 161 private int m_maxRTO = 0;
160 162 private int m_ackTimeout = 0;
163 private int m_pausedAckTimeout = 0;
161 private bool m_disableFacelights = false; 164 private bool m_disableFacelights = false;
162 165
163 public Socket Server { get { return null; } } 166 public Socket Server { get { return null; } }
164 167
165 private int m_malformedCount = 0; // Guard against a spamming attack 168 private int m_malformedCount = 0; // Guard against a spamming attack
166 169
170 /// <summary>
171 /// Record current outgoing client for monitoring purposes.
172 /// </summary>
173 private IClientAPI m_currentOutgoingClient;
174
175 /// <summary>
176 /// Recording current incoming client for monitoring purposes.
177 /// </summary>
178 private IClientAPI m_currentIncomingClient;
179
167 public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) 180 public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager)
168 : base(listenIP, (int)port) 181 : base(listenIP, (int)port)
169 { 182 {
@@ -200,11 +213,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
200 m_defaultRTO = config.GetInt("DefaultRTO", 0); 213 m_defaultRTO = config.GetInt("DefaultRTO", 0);
201 m_maxRTO = config.GetInt("MaxRTO", 0); 214 m_maxRTO = config.GetInt("MaxRTO", 0);
202 m_disableFacelights = config.GetBoolean("DisableFacelights", false); 215 m_disableFacelights = config.GetBoolean("DisableFacelights", false);
216 m_ackTimeout = 1000 * config.GetInt("AckTimeout", 60);
217 m_pausedAckTimeout = 1000 * config.GetInt("PausedAckTimeout", 300);
203 } 218 }
204 else 219 else
205 { 220 {
206 PrimUpdatesPerCallback = 100; 221 PrimUpdatesPerCallback = 100;
207 TextureSendLimit = 20; 222 TextureSendLimit = 20;
223 m_ackTimeout = 1000 * 60; // 1 minute
224 m_pausedAckTimeout = 1000 * 300; // 5 minutes
208 } 225 }
209 226
210 #region BinaryStats 227 #region BinaryStats
@@ -241,19 +258,56 @@ namespace OpenSim.Region.ClientStack.LindenUDP
241 if (m_scene == null) 258 if (m_scene == null)
242 throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference"); 259 throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference");
243 260
244 m_log.Info("[LLUDPSERVER]: Starting the LLUDP server in " + (m_asyncPacketHandling ? "asynchronous" : "synchronous") + " mode"); 261 m_log.InfoFormat(
262 "[LLUDPSERVER]: Starting the LLUDP server in {0} mode",
263 m_asyncPacketHandling ? "asynchronous" : "synchronous");
245 264
246 base.Start(m_recvBufferSize, m_asyncPacketHandling); 265 base.Start(m_recvBufferSize, m_asyncPacketHandling);
247 266
248 // Start the packet processing threads 267 // Start the packet processing threads
249 Watchdog.StartThread( 268 Watchdog.StartThread(
250 IncomingPacketHandler, "Incoming Packets (" + m_scene.RegionInfo.RegionName + ")", ThreadPriority.Normal, false, true); 269 IncomingPacketHandler,
270 string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName),
271 ThreadPriority.Normal,
272 false,
273 true,
274 GetWatchdogIncomingAlarmData,
275 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS);
276
251 Watchdog.StartThread( 277 Watchdog.StartThread(
252 OutgoingPacketHandler, "Outgoing Packets (" + m_scene.RegionInfo.RegionName + ")", ThreadPriority.Normal, false, true); 278 OutgoingPacketHandler,
279 string.Format("Outgoing Packets ({0})", m_scene.RegionInfo.RegionName),
280 ThreadPriority.Normal,
281 false,
282 true,
283 GetWatchdogOutgoingAlarmData,
284 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS);
253 285
254 m_elapsedMSSinceLastStatReport = Environment.TickCount; 286 m_elapsedMSSinceLastStatReport = Environment.TickCount;
255 } 287 }
256 288
289 /// <summary>
290 /// If the outgoing UDP thread times out, then return client that was being processed to help with debugging.
291 /// </summary>
292 /// <returns></returns>
293 private string GetWatchdogIncomingAlarmData()
294 {
295 return string.Format(
296 "Client is {0}",
297 m_currentIncomingClient != null ? m_currentIncomingClient.Name : "none");
298 }
299
300 /// <summary>
301 /// If the outgoing UDP thread times out, then return client that was being processed to help with debugging.
302 /// </summary>
303 /// <returns></returns>
304 private string GetWatchdogOutgoingAlarmData()
305 {
306 return string.Format(
307 "Client is {0}",
308 m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none");
309 }
310
257 public new void Stop() 311 public new void Stop()
258 { 312 {
259 m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName); 313 m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName);
@@ -487,19 +541,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP
487 SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false, null); 541 SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false, null);
488 } 542 }
489 543
490 public void HandleUnacked(LLUDPClient udpClient) 544 public void HandleUnacked(LLClientView client)
491 { 545 {
546 LLUDPClient udpClient = client.UDPClient;
547
492 if (!udpClient.IsConnected) 548 if (!udpClient.IsConnected)
493 return; 549 return;
494 550
495 // Disconnect an agent if no packets are received for some time 551 // Disconnect an agent if no packets are received for some time
496 //FIXME: Make 60 an .ini setting 552 int timeoutTicks = m_ackTimeout;
497 if ((Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > 1000 * 60) 553
554 // Allow more slack if the client is "paused" eg file upload dialogue is open
555 // Some sort of limit is needed in case the client crashes, loses its network connection
556 // or some other disaster prevents it from sendung the AgentResume
557 if (udpClient.IsPaused)
558 timeoutTicks = m_pausedAckTimeout;
559
560 if (client.IsActive &&
561 (Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > timeoutTicks)
498 { 562 {
499 m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + udpClient.AgentID); 563 // We must set IsActive synchronously so that we can stop the packet loop reinvoking this method, even
500 StatsManager.SimExtraStats.AddAbnormalClientThreadTermination(); 564 // though it's set later on by LLClientView.Close()
565 client.IsActive = false;
566
567 // Fire this out on a different thread so that we don't hold up outgoing packet processing for
568 // everybody else if this is being called due to an ack timeout.
569 // This is the same as processing as the async process of a logout request.
570 Util.FireAndForget(o => DeactivateClientDueToTimeout(client));
501 571
502 RemoveClient(udpClient);
503 return; 572 return;
504 } 573 }
505 574
@@ -850,7 +919,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
850 #endregion Ping Check Handling 919 #endregion Ping Check Handling
851 920
852 // Inbox insertion 921 // Inbox insertion
853 packetInbox.Enqueue(new IncomingPacket(udpClient, packet)); 922 packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet));
854 } 923 }
855 924
856 #region BinaryStats 925 #region BinaryStats
@@ -946,7 +1015,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
946 UDPPacketBuffer buffer = (UDPPacketBuffer)array[0]; 1015 UDPPacketBuffer buffer = (UDPPacketBuffer)array[0];
947 UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1]; 1016 UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1];
948 1017
949 m_log.DebugFormat("[LLUDPSERVER]: Handling UseCircuitCode request from {0}", buffer.RemoteEndPoint); 1018 m_log.DebugFormat(
1019 "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}",
1020 uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, buffer.RemoteEndPoint);
950 1021
951 remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint; 1022 remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint;
952 1023
@@ -1001,8 +1072,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1001 { 1072 {
1002 // Don't create clients for unauthorized requesters. 1073 // Don't create clients for unauthorized requesters.
1003 m_log.WarnFormat( 1074 m_log.WarnFormat(
1004 "[LLUDPSERVER]: Connection request for client {0} connecting with unnotified circuit code {1} from {2}", 1075 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
1005 uccp.CircuitCode.ID, uccp.CircuitCode.Code, remoteEndPoint); 1076 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint);
1006 lock (m_pendingCache) 1077 lock (m_pendingCache)
1007 m_pendingCache.Remove(remoteEndPoint); 1078 m_pendingCache.Remove(remoteEndPoint);
1008 } 1079 }
@@ -1090,7 +1161,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1090 { 1161 {
1091 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); 1162 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO);
1092 1163
1093 client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); 1164 client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
1094 client.OnLogout += LogoutHandler; 1165 client.OnLogout += LogoutHandler;
1095 1166
1096 ((LLClientView)client).DisableFacelights = m_disableFacelights; 1167 ((LLClientView)client).DisableFacelights = m_disableFacelights;
@@ -1102,15 +1173,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1102 return client; 1173 return client;
1103 } 1174 }
1104 1175
1105 private void RemoveClient(LLUDPClient udpClient) 1176 /// <summary>
1177 /// Deactivates the client if we don't receive any packets within a certain amount of time (default 60 seconds).
1178 /// </summary>
1179 /// <remarks>
1180 /// If a connection is active then we will always receive packets even if nothing else is happening, due to
1181 /// regular client pings.
1182 /// </remarks>
1183 /// <param name='client'></param>
1184 private void DeactivateClientDueToTimeout(IClientAPI client)
1106 { 1185 {
1107 // Remove this client from the scene 1186 // We must set IsActive synchronously so that we can stop the packet loop reinvoking this method, even
1108 IClientAPI client; 1187 // though it's set later on by LLClientView.Close()
1109 if (m_scene.TryGetClient(udpClient.AgentID, out client)) 1188 client.IsActive = false;
1110 { 1189
1111 client.IsLoggingOut = true; 1190 m_log.WarnFormat(
1112 client.Close(false); 1191 "[LLUDPSERVER]: Ack timeout, disconnecting {0} agent for {1} in {2}",
1113 } 1192 client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, m_scene.RegionInfo.RegionName);
1193
1194 StatsManager.SimExtraStats.AddAbnormalClientThreadTermination();
1195
1196 if (!client.SceneAgent.IsChildAgent)
1197 client.Kick("Simulator logged you out due to connection timeout");
1198
1199 Util.FireAndForget(o => client.Close());
1114 } 1200 }
1115 1201
1116 private void IncomingPacketHandler() 1202 private void IncomingPacketHandler()
@@ -1219,6 +1305,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1219 // client. m_packetSent will be set to true if a packet is sent 1305 // client. m_packetSent will be set to true if a packet is sent
1220 m_scene.ForEachClient(clientPacketHandler); 1306 m_scene.ForEachClient(clientPacketHandler);
1221 1307
1308 m_currentOutgoingClient = null;
1309
1222 // If nothing was sent, sleep for the minimum amount of time before a 1310 // If nothing was sent, sleep for the minimum amount of time before a
1223 // token bucket could get more tokens 1311 // token bucket could get more tokens
1224 if (!m_packetSent) 1312 if (!m_packetSent)
@@ -1235,18 +1323,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1235 Watchdog.RemoveThread(); 1323 Watchdog.RemoveThread();
1236 } 1324 }
1237 1325
1238 private void ClientOutgoingPacketHandler(IClientAPI client) 1326 protected void ClientOutgoingPacketHandler(IClientAPI client)
1239 { 1327 {
1328 m_currentOutgoingClient = client;
1329
1240 try 1330 try
1241 { 1331 {
1242 if (client is LLClientView) 1332 if (client is LLClientView)
1243 { 1333 {
1244 LLUDPClient udpClient = ((LLClientView)client).UDPClient; 1334 LLClientView llClient = (LLClientView)client;
1335 LLUDPClient udpClient = llClient.UDPClient;
1245 1336
1246 if (udpClient.IsConnected) 1337 if (udpClient.IsConnected)
1247 { 1338 {
1248 if (m_resendUnacked) 1339 if (m_resendUnacked)
1249 HandleUnacked(udpClient); 1340 HandleUnacked(llClient);
1250 1341
1251 if (m_sendAcks) 1342 if (m_sendAcks)
1252 SendAcks(udpClient); 1343 SendAcks(udpClient);
@@ -1262,8 +1353,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1262 } 1353 }
1263 catch (Exception ex) 1354 catch (Exception ex)
1264 { 1355 {
1265 m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler iteration for " + client.Name + 1356 m_log.Error(
1266 " threw an exception: " + ex.Message, ex); 1357 string.Format("[LLUDPSERVER]: OutgoingPacketHandler iteration for {0} threw ", client.Name), ex);
1267 } 1358 }
1268 } 1359 }
1269 1360
@@ -1289,11 +1380,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1289 { 1380 {
1290 nticks++; 1381 nticks++;
1291 watch1.Start(); 1382 watch1.Start();
1383 m_currentOutgoingClient = client;
1384
1292 try 1385 try
1293 { 1386 {
1294 if (client is LLClientView) 1387 if (client is LLClientView)
1295 { 1388 {
1296 LLUDPClient udpClient = ((LLClientView)client).UDPClient; 1389 LLClientView llClient = (LLClientView)client;
1390 LLUDPClient udpClient = llClient.UDPClient;
1297 1391
1298 if (udpClient.IsConnected) 1392 if (udpClient.IsConnected)
1299 { 1393 {
@@ -1302,7 +1396,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1302 nticksUnack++; 1396 nticksUnack++;
1303 watch2.Start(); 1397 watch2.Start();
1304 1398
1305 HandleUnacked(udpClient); 1399 HandleUnacked(llClient);
1306 1400
1307 watch2.Stop(); 1401 watch2.Stop();
1308 avgResendUnackedTicks = (nticksUnack - 1)/(float)nticksUnack * avgResendUnackedTicks + (watch2.ElapsedTicks / (float)nticksUnack); 1402 avgResendUnackedTicks = (nticksUnack - 1)/(float)nticksUnack * avgResendUnackedTicks + (watch2.ElapsedTicks / (float)nticksUnack);
@@ -1373,23 +1467,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1373 1467
1374 #endregion 1468 #endregion
1375 1469
1376 private void ProcessInPacket(object state) 1470 private void ProcessInPacket(IncomingPacket incomingPacket)
1377 { 1471 {
1378 IncomingPacket incomingPacket = (IncomingPacket)state;
1379 Packet packet = incomingPacket.Packet; 1472 Packet packet = incomingPacket.Packet;
1380 LLUDPClient udpClient = incomingPacket.Client; 1473 LLClientView client = incomingPacket.Client;
1381 IClientAPI client;
1382 1474
1383 // Sanity check 1475 if (client.IsActive)
1384 if (packet == null || udpClient == null)
1385 { 1476 {
1386 m_log.WarnFormat("[LLUDPSERVER]: Processing a packet with incomplete state. Packet=\"{0}\", UDPClient=\"{1}\"", 1477 m_currentIncomingClient = client;
1387 packet, udpClient);
1388 }
1389 1478
1390 // Make sure this client is still alive
1391 if (m_scene.TryGetClient(udpClient.AgentID, out client))
1392 {
1393 try 1479 try
1394 { 1480 {
1395 // Process this packet 1481 // Process this packet
@@ -1404,21 +1490,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1404 catch (Exception e) 1490 catch (Exception e)
1405 { 1491 {
1406 // Don't let a failure in an individual client thread crash the whole sim. 1492 // Don't let a failure in an individual client thread crash the whole sim.
1407 m_log.ErrorFormat("[LLUDPSERVER]: Client packet handler for {0} for packet {1} threw an exception", udpClient.AgentID, packet.Type); 1493 m_log.Error(
1408 m_log.Error(e.Message, e); 1494 string.Format(
1495 "[LLUDPSERVER]: Client packet handler for {0} for packet {1} threw ",
1496 client.Name, packet.Type),
1497 e);
1498 }
1499 finally
1500 {
1501 m_currentIncomingClient = null;
1409 } 1502 }
1410 } 1503 }
1411 else 1504 else
1412 { 1505 {
1413 m_log.DebugFormat("[LLUDPSERVER]: Dropping incoming {0} packet for dead client {1}", packet.Type, udpClient.AgentID); 1506 m_log.DebugFormat(
1507 "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
1508 packet.Type, client.Name, m_scene.RegionInfo.RegionName);
1414 } 1509 }
1415 } 1510 }
1416 1511
1417 protected void LogoutHandler(IClientAPI client) 1512 protected void LogoutHandler(IClientAPI client)
1418 { 1513 {
1419 client.SendLogoutPacket(); 1514 client.SendLogoutPacket();
1420 if (client.IsActive) 1515
1421 RemoveClient(((LLClientView)client).UDPClient); 1516 if (!client.IsLoggingOut)
1517 {
1518 client.IsLoggingOut = true;
1519 client.Close();
1520 }
1422 } 1521 }
1423 } 1522 }
1424} 1523}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
index a575e36..109a8e1 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
@@ -45,6 +45,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
45 [TestFixture] 45 [TestFixture]
46 public class BasicCircuitTests 46 public class BasicCircuitTests
47 { 47 {
48 private Scene m_scene;
49 private TestLLUDPServer m_udpServer;
50
48 [TestFixtureSetUp] 51 [TestFixtureSetUp]
49 public void FixtureInit() 52 public void FixtureInit()
50 { 53 {
@@ -61,83 +64,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
61 Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; 64 Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
62 } 65 }
63 66
64// /// <summary> 67 [SetUp]
65// /// Add a client for testing 68 public void SetUp()
66// /// </summary> 69 {
67// /// <param name="scene"></param> 70 m_scene = new SceneHelpers().SetupScene();
68// /// <param name="testLLUDPServer"></param> 71 }
69// /// <param name="testPacketServer"></param>
70// /// <param name="acm">Agent circuit manager used in setting up the stack</param>
71// protected void SetupStack(
72// IScene scene, out TestLLUDPServer testLLUDPServer, out TestLLPacketServer testPacketServer,
73// out AgentCircuitManager acm)
74// {
75// IConfigSource configSource = new IniConfigSource();
76// ClientStackUserSettings userSettings = new ClientStackUserSettings();
77// testLLUDPServer = new TestLLUDPServer();
78// acm = new AgentCircuitManager();
79//
80// uint port = 666;
81// testLLUDPServer.Initialise(null, ref port, 0, false, configSource, acm);
82// testPacketServer = new TestLLPacketServer(testLLUDPServer, userSettings);
83// testLLUDPServer.LocalScene = scene;
84// }
85
86// /// <summary>
87// /// Set up a client for tests which aren't concerned with this process itself and where only one client is being
88// /// tested
89// /// </summary>
90// /// <param name="circuitCode"></param>
91// /// <param name="epSender"></param>
92// /// <param name="testLLUDPServer"></param>
93// /// <param name="acm"></param>
94// protected void AddClient(
95// uint circuitCode, EndPoint epSender, TestLLUDPServer testLLUDPServer, AgentCircuitManager acm)
96// {
97// UUID myAgentUuid = UUID.Parse("00000000-0000-0000-0000-000000000001");
98// UUID mySessionUuid = UUID.Parse("00000000-0000-0000-0000-000000000002");
99//
100// AddClient(circuitCode, epSender, myAgentUuid, mySessionUuid, testLLUDPServer, acm);
101// }
102
103// /// <summary>
104// /// Set up a client for tests which aren't concerned with this process itself
105// /// </summary>
106// /// <param name="circuitCode"></param>
107// /// <param name="epSender"></param>
108// /// <param name="agentId"></param>
109// /// <param name="sessionId"></param>
110// /// <param name="testLLUDPServer"></param>
111// /// <param name="acm"></param>
112// protected void AddClient(
113// uint circuitCode, EndPoint epSender, UUID agentId, UUID sessionId,
114// TestLLUDPServer testLLUDPServer, AgentCircuitManager acm)
115// {
116// AgentCircuitData acd = new AgentCircuitData();
117// acd.AgentID = agentId;
118// acd.SessionID = sessionId;
119//
120// UseCircuitCodePacket uccp = new UseCircuitCodePacket();
121//
122// UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock
123// = new UseCircuitCodePacket.CircuitCodeBlock();
124// uccpCcBlock.Code = circuitCode;
125// uccpCcBlock.ID = agentId;
126// uccpCcBlock.SessionID = sessionId;
127// uccp.CircuitCode = uccpCcBlock;
128//
129// acm.AddNewCircuit(circuitCode, acd);
130//
131// testLLUDPServer.LoadReceive(uccp, epSender);
132// testLLUDPServer.ReceiveData(null);
133// }
134 72
135 /// <summary> 73 /// <summary>
136 /// Build an object name packet for test purposes 74 /// Build an object name packet for test purposes
137 /// </summary> 75 /// </summary>
138 /// <param name="objectLocalId"></param> 76 /// <param name="objectLocalId"></param>
139 /// <param name="objectName"></param> 77 /// <param name="objectName"></param>
140 protected ObjectNamePacket BuildTestObjectNamePacket(uint objectLocalId, string objectName) 78 private ObjectNamePacket BuildTestObjectNamePacket(uint objectLocalId, string objectName)
141 { 79 {
142 ObjectNamePacket onp = new ObjectNamePacket(); 80 ObjectNamePacket onp = new ObjectNamePacket();
143 ObjectNamePacket.ObjectDataBlock odb = new ObjectNamePacket.ObjectDataBlock(); 81 ObjectNamePacket.ObjectDataBlock odb = new ObjectNamePacket.ObjectDataBlock();
@@ -148,6 +86,55 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
148 86
149 return onp; 87 return onp;
150 } 88 }
89
90 private void AddUdpServer()
91 {
92 AddUdpServer(new IniConfigSource());
93 }
94
95 private void AddUdpServer(IniConfigSource configSource)
96 {
97 uint port = 0;
98 AgentCircuitManager acm = m_scene.AuthenticateHandler;
99
100 m_udpServer = new TestLLUDPServer(IPAddress.Any, ref port, 0, false, configSource, acm);
101 m_udpServer.AddScene(m_scene);
102 }
103
104 /// <summary>
105 /// Used by tests that aren't testing this stage.
106 /// </summary>
107 private ScenePresence AddClient()
108 {
109 UUID myAgentUuid = TestHelpers.ParseTail(0x1);
110 UUID mySessionUuid = TestHelpers.ParseTail(0x2);
111 uint myCircuitCode = 123456;
112 IPEndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999);
113
114 UseCircuitCodePacket uccp = new UseCircuitCodePacket();
115
116 UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock
117 = new UseCircuitCodePacket.CircuitCodeBlock();
118 uccpCcBlock.Code = myCircuitCode;
119 uccpCcBlock.ID = myAgentUuid;
120 uccpCcBlock.SessionID = mySessionUuid;
121 uccp.CircuitCode = uccpCcBlock;
122
123 byte[] uccpBytes = uccp.ToBytes();
124 UDPPacketBuffer upb = new UDPPacketBuffer(testEp, uccpBytes.Length);
125 upb.DataLength = uccpBytes.Length; // God knows why this isn't set by the constructor.
126 Buffer.BlockCopy(uccpBytes, 0, upb.Data, 0, uccpBytes.Length);
127
128 AgentCircuitData acd = new AgentCircuitData();
129 acd.AgentID = myAgentUuid;
130 acd.SessionID = mySessionUuid;
131
132 m_scene.AuthenticateHandler.AddNewCircuit(myCircuitCode, acd);
133
134 m_udpServer.PacketReceived(upb);
135
136 return m_scene.GetScenePresence(myAgentUuid);
137 }
151 138
152 /// <summary> 139 /// <summary>
153 /// Test adding a client to the stack 140 /// Test adding a client to the stack
@@ -158,19 +145,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
158 TestHelpers.InMethod(); 145 TestHelpers.InMethod();
159// XmlConfigurator.Configure(); 146// XmlConfigurator.Configure();
160 147
161 TestScene scene = SceneHelpers.SetupScene(); 148 AddUdpServer();
162 uint myCircuitCode = 123456; 149
163 UUID myAgentUuid = TestHelpers.ParseTail(0x1); 150 UUID myAgentUuid = TestHelpers.ParseTail(0x1);
164 UUID mySessionUuid = TestHelpers.ParseTail(0x2); 151 UUID mySessionUuid = TestHelpers.ParseTail(0x2);
152 uint myCircuitCode = 123456;
165 IPEndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999); 153 IPEndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999);
166 154
167 uint port = 0;
168 AgentCircuitManager acm = scene.AuthenticateHandler;
169
170 TestLLUDPServer llUdpServer
171 = new TestLLUDPServer(IPAddress.Any, ref port, 0, false, new IniConfigSource(), acm);
172 llUdpServer.AddScene(scene);
173
174 UseCircuitCodePacket uccp = new UseCircuitCodePacket(); 155 UseCircuitCodePacket uccp = new UseCircuitCodePacket();
175 156
176 UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock 157 UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock
@@ -185,26 +166,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
185 upb.DataLength = uccpBytes.Length; // God knows why this isn't set by the constructor. 166 upb.DataLength = uccpBytes.Length; // God knows why this isn't set by the constructor.
186 Buffer.BlockCopy(uccpBytes, 0, upb.Data, 0, uccpBytes.Length); 167 Buffer.BlockCopy(uccpBytes, 0, upb.Data, 0, uccpBytes.Length);
187 168
188 llUdpServer.PacketReceived(upb); 169 m_udpServer.PacketReceived(upb);
189 170
190 // Presence shouldn't exist since the circuit manager doesn't know about this circuit for authentication yet 171 // Presence shouldn't exist since the circuit manager doesn't know about this circuit for authentication yet
191 Assert.That(scene.GetScenePresence(myAgentUuid), Is.Null); 172 Assert.That(m_scene.GetScenePresence(myAgentUuid), Is.Null);
192 173
193 AgentCircuitData acd = new AgentCircuitData(); 174 AgentCircuitData acd = new AgentCircuitData();
194 acd.AgentID = myAgentUuid; 175 acd.AgentID = myAgentUuid;
195 acd.SessionID = mySessionUuid; 176 acd.SessionID = mySessionUuid;
196 177
197 acm.AddNewCircuit(myCircuitCode, acd); 178 m_scene.AuthenticateHandler.AddNewCircuit(myCircuitCode, acd);
198 179
199 llUdpServer.PacketReceived(upb); 180 m_udpServer.PacketReceived(upb);
200 181
201 // Should succeed now 182 // Should succeed now
202 ScenePresence sp = scene.GetScenePresence(myAgentUuid); 183 ScenePresence sp = m_scene.GetScenePresence(myAgentUuid);
203 Assert.That(sp.UUID, Is.EqualTo(myAgentUuid)); 184 Assert.That(sp.UUID, Is.EqualTo(myAgentUuid));
204 185
205 Assert.That(llUdpServer.PacketsSent.Count, Is.EqualTo(1)); 186 Assert.That(m_udpServer.PacketsSent.Count, Is.EqualTo(1));
206 187
207 Packet packet = llUdpServer.PacketsSent[0]; 188 Packet packet = m_udpServer.PacketsSent[0];
208 Assert.That(packet, Is.InstanceOf(typeof(PacketAckPacket))); 189 Assert.That(packet, Is.InstanceOf(typeof(PacketAckPacket)));
209 190
210 PacketAckPacket ackPacket = packet as PacketAckPacket; 191 PacketAckPacket ackPacket = packet as PacketAckPacket;
@@ -212,6 +193,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
212 Assert.That(ackPacket.Packets[0].ID, Is.EqualTo(0)); 193 Assert.That(ackPacket.Packets[0].ID, Is.EqualTo(0));
213 } 194 }
214 195
196 [Test]
197 public void TestLogoutClientDueToAck()
198 {
199 TestHelpers.InMethod();
200// TestHelpers.EnableLogging();
201
202 IniConfigSource ics = new IniConfigSource();
203 IConfig config = ics.AddConfig("ClientStack.LindenUDP");
204 config.Set("AckTimeout", -1);
205 AddUdpServer(ics);
206
207 ScenePresence sp = AddClient();
208 m_udpServer.ClientOutgoingPacketHandler(sp.ControllingClient, true, false, false);
209
210 ScenePresence spAfterAckTimeout = m_scene.GetScenePresence(sp.UUID);
211 Assert.That(spAfterAckTimeout, Is.Null);
212
213// TestHelpers.DisableLogging();
214 }
215
215// /// <summary> 216// /// <summary>
216// /// Test removing a client from the stack 217// /// Test removing a client from the stack
217// /// </summary> 218// /// </summary>
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs
index 1b68d68..5fcf376 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs
@@ -79,7 +79,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
79 79
80 J2KDecoderModule j2kdm = new J2KDecoderModule(); 80 J2KDecoderModule j2kdm = new J2KDecoderModule();
81 81
82 scene = SceneHelpers.SetupScene(); 82 SceneHelpers sceneHelpers = new SceneHelpers();
83 scene = sceneHelpers.SetupScene();
83 SceneHelpers.SetupSceneModules(scene, j2kdm); 84 SceneHelpers.SetupSceneModules(scene, j2kdm);
84 85
85 tc = new TestClient(SceneHelpers.GenerateAgentData(userId), scene); 86 tc = new TestClient(SceneHelpers.GenerateAgentData(userId), scene);
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs
index d76927b..119a677 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs
@@ -44,9 +44,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
44 } 44 }
45 protected int m_objectNameCallsReceived; 45 protected int m_objectNameCallsReceived;
46 46
47 public MockScene() 47 public MockScene() : base(new RegionInfo(1000, 1000, null, null))
48 { 48 {
49 m_regInfo = new RegionInfo(1000, 1000, null, null);
50 m_regStatus = RegionStatus.Up; 49 m_regStatus = RegionStatus.Up;
51 } 50 }
52 51
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/TestLLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/TestLLUDPServer.cs
index 0302385..27b9e5b 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/TestLLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/TestLLUDPServer.cs
@@ -59,6 +59,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
59 PacketsSent.Add(packet); 59 PacketsSent.Add(packet);
60 } 60 }
61 61
62 public void ClientOutgoingPacketHandler(IClientAPI client, bool resendUnacked, bool sendAcks, bool sendPing)
63 {
64 m_resendUnacked = resendUnacked;
65 m_sendAcks = sendAcks;
66 m_sendPing = sendPing;
67
68 ClientOutgoingPacketHandler(client);
69 }
70
62//// /// <summary> 71//// /// <summary>
63//// /// The chunks of data to pass to the LLUDPServer when it calls EndReceive 72//// /// The chunks of data to pass to the LLUDPServer when it calls EndReceive
64//// /// </summary> 73//// /// </summary>
diff --git a/OpenSim/Region/ClientStack/RegionApplicationBase.cs b/OpenSim/Region/ClientStack/RegionApplicationBase.cs
index 6e3a58e..c4324e8 100644
--- a/OpenSim/Region/ClientStack/RegionApplicationBase.cs
+++ b/OpenSim/Region/ClientStack/RegionApplicationBase.cs
@@ -94,24 +94,21 @@ namespace OpenSim.Region.ClientStack
94 m_log.InfoFormat("[REGION SERVER]: Starting HTTP server on port {0}", m_httpServerPort); 94 m_log.InfoFormat("[REGION SERVER]: Starting HTTP server on port {0}", m_httpServerPort);
95 m_httpServer.Start(); 95 m_httpServer.Start();
96 96
97 MainServer.AddHttpServer(m_httpServer);
97 MainServer.Instance = m_httpServer; 98 MainServer.Instance = m_httpServer;
98 99
99 // "OOB" Server 100 // "OOB" Server
100 if (m_networkServersInfo.ssl_listener) 101 if (m_networkServersInfo.ssl_listener)
101 { 102 {
102 BaseHttpServer server = null; 103 BaseHttpServer server = new BaseHttpServer(
103 server = new BaseHttpServer(
104 m_networkServersInfo.https_port, m_networkServersInfo.ssl_listener, m_networkServersInfo.cert_path, 104 m_networkServersInfo.https_port, m_networkServersInfo.ssl_listener, m_networkServersInfo.cert_path,
105 m_networkServersInfo.cert_pass); 105 m_networkServersInfo.cert_pass);
106 // Add the server to m_Servers
107 if(server != null)
108 {
109 m_log.InfoFormat("[REGION SERVER]: Starting HTTPS server on port {0}", server.Port);
110 MainServer.AddHttpServer(server);
111 server.Start();
112 }
113 }
114 106
107 m_log.InfoFormat("[REGION SERVER]: Starting HTTPS server on port {0}", server.Port);
108 MainServer.AddHttpServer(server);
109 server.Start();
110 }
111
115 base.StartupSpecific(); 112 base.StartupSpecific();
116 } 113 }
117 114
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
index 874693e..7081989 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
@@ -42,8 +42,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
42 public class AssetTransactionModule : INonSharedRegionModule, 42 public class AssetTransactionModule : INonSharedRegionModule,
43 IAgentAssetTransactions 43 IAgentAssetTransactions
44 { 44 {
45// private static readonly ILog m_log = LogManager.GetLogger( 45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46// MethodBase.GetCurrentMethod().DeclaringType);
47 46
48 protected Scene m_Scene; 47 protected Scene m_Scene;
49 private bool m_dumpAssetsToFile = false; 48 private bool m_dumpAssetsToFile = false;
@@ -209,15 +208,15 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
209 /// and comes through this method. 208 /// and comes through this method.
210 /// </summary> 209 /// </summary>
211 /// <param name="remoteClient"></param> 210 /// <param name="remoteClient"></param>
211 /// <param name="part"></param>
212 /// <param name="transactionID"></param> 212 /// <param name="transactionID"></param>
213 /// <param name="item"></param> 213 /// <param name="item"></param>
214 public void HandleTaskItemUpdateFromTransaction(IClientAPI remoteClient, 214 public void HandleTaskItemUpdateFromTransaction(
215 SceneObjectPart part, UUID transactionID, 215 IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item)
216 TaskInventoryItem item)
217 { 216 {
218// m_log.DebugFormat( 217 m_log.DebugFormat(
219// "[TRANSACTIONS MANAGER] Called HandleTaskItemUpdateFromTransaction with item {0}", 218 "[TRANSACTIONS MANAGER] Called HandleTaskItemUpdateFromTransaction with item {0} in {1} for {2} in {3}",
220// item.Name); 219 item.Name, part.Name, remoteClient.Name, m_Scene.RegionInfo.RegionName);
221 220
222 AgentAssetTransactions transactions = 221 AgentAssetTransactions transactions =
223 GetUserTransactions(remoteClient.AgentId); 222 GetUserTransactions(remoteClient.AgentId);
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index 127ca1d..7d7176f 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -83,7 +83,7 @@ namespace Flotsam.RegionModules.AssetCache
83 private Dictionary<string, ManualResetEvent> m_CurrentlyWriting = new Dictionary<string, ManualResetEvent>(); 83 private Dictionary<string, ManualResetEvent> m_CurrentlyWriting = new Dictionary<string, ManualResetEvent>();
84 private int m_WaitOnInprogressTimeout = 3000; 84 private int m_WaitOnInprogressTimeout = 3000;
85#else 85#else
86 private List<string> m_CurrentlyWriting = new List<string>(); 86 private HashSet<string> m_CurrentlyWriting = new HashSet<string>();
87#endif 87#endif
88 88
89 private bool m_FileCacheEnabled = true; 89 private bool m_FileCacheEnabled = true;
@@ -143,7 +143,7 @@ namespace Flotsam.RegionModules.AssetCache
143 IConfig assetConfig = source.Configs["AssetCache"]; 143 IConfig assetConfig = source.Configs["AssetCache"];
144 if (assetConfig == null) 144 if (assetConfig == null)
145 { 145 {
146 m_log.Warn( 146 m_log.Debug(
147 "[FLOTSAM ASSET CACHE]: AssetCache section missing from config (not copied config-include/FlotsamCache.ini.example? Using defaults."); 147 "[FLOTSAM ASSET CACHE]: AssetCache section missing from config (not copied config-include/FlotsamCache.ini.example? Using defaults.");
148 } 148 }
149 else 149 else
@@ -272,7 +272,11 @@ namespace Flotsam.RegionModules.AssetCache
272 // the other thread has updated the time for us. 272 // the other thread has updated the time for us.
273 try 273 try
274 { 274 {
275 File.SetLastAccessTime(filename, DateTime.Now); 275 lock (m_CurrentlyWriting)
276 {
277 if (!m_CurrentlyWriting.Contains(filename))
278 File.SetLastAccessTime(filename, DateTime.Now);
279 }
276 } 280 }
277 catch 281 catch
278 { 282 {
diff --git a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
index 5adb845..c91b25f 100644
--- a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
+++ b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
@@ -65,7 +65,7 @@ namespace OpenSim.Region.CoreModules.Asset.Tests
65 config.Configs["AssetCache"].Set("MemoryCacheEnabled", "true"); 65 config.Configs["AssetCache"].Set("MemoryCacheEnabled", "true");
66 66
67 m_cache = new FlotsamAssetCache(); 67 m_cache = new FlotsamAssetCache();
68 m_scene = SceneHelpers.SetupScene(); 68 m_scene = new SceneHelpers().SetupScene();
69 SceneHelpers.SetupSceneModules(m_scene, config, m_cache); 69 SceneHelpers.SetupSceneModules(m_scene, config, m_cache);
70 } 70 }
71 71
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index fd7cad2..394b90a 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -50,7 +50,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51 51
52 private Scene m_scene; 52 private Scene m_scene;
53 private IDialogModule m_dialogModule; 53 private IInventoryAccessModule m_invAccessModule;
54 54
55 /// <summary> 55 /// <summary>
56 /// Are attachments enabled? 56 /// Are attachments enabled?
@@ -72,7 +72,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
72 public void AddRegion(Scene scene) 72 public void AddRegion(Scene scene)
73 { 73 {
74 m_scene = scene; 74 m_scene = scene;
75 m_dialogModule = m_scene.RequestModuleInterface<IDialogModule>();
76 m_scene.RegisterModuleInterface<IAttachmentsModule>(this); 75 m_scene.RegisterModuleInterface<IAttachmentsModule>(this);
77 76
78 if (Enabled) 77 if (Enabled)
@@ -89,7 +88,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
89 m_scene.EventManager.OnNewClient -= SubscribeToClientEvents; 88 m_scene.EventManager.OnNewClient -= SubscribeToClientEvents;
90 } 89 }
91 90
92 public void RegionLoaded(Scene scene) {} 91 public void RegionLoaded(Scene scene)
92 {
93 m_invAccessModule = m_scene.RequestModuleInterface<IInventoryAccessModule>();
94 }
93 95
94 public void Close() 96 public void Close()
95 { 97 {
@@ -100,6 +102,56 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
100 102
101 #region IAttachmentsModule 103 #region IAttachmentsModule
102 104
105 public void CopyAttachments(IScenePresence sp, AgentData ad)
106 {
107 lock (sp.AttachmentsSyncLock)
108 {
109 // Attachment objects
110 List<SceneObjectGroup> attachments = sp.GetAttachments();
111 if (attachments.Count > 0)
112 {
113 ad.AttachmentObjects = new List<ISceneObject>();
114 ad.AttachmentObjectStates = new List<string>();
115 // IScriptModule se = m_scene.RequestModuleInterface<IScriptModule>();
116 sp.InTransitScriptStates.Clear();
117
118 foreach (SceneObjectGroup sog in attachments)
119 {
120 // We need to make a copy and pass that copy
121 // because of transfers withn the same sim
122 ISceneObject clone = sog.CloneForNewScene();
123 // Attachment module assumes that GroupPosition holds the offsets...!
124 ((SceneObjectGroup)clone).RootPart.GroupPosition = sog.RootPart.AttachedPos;
125 ((SceneObjectGroup)clone).IsAttachment = false;
126 ad.AttachmentObjects.Add(clone);
127 string state = sog.GetStateSnapshot();
128 ad.AttachmentObjectStates.Add(state);
129 sp.InTransitScriptStates.Add(state);
130 // Let's remove the scripts of the original object here
131 sog.RemoveScriptInstances(true);
132 }
133 }
134 }
135 }
136
137 public void CopyAttachments(AgentData ad, IScenePresence sp)
138 {
139 if (ad.AttachmentObjects != null && ad.AttachmentObjects.Count > 0)
140 {
141 lock (sp.AttachmentsSyncLock)
142 sp.ClearAttachments();
143
144 int i = 0;
145 foreach (ISceneObject so in ad.AttachmentObjects)
146 {
147 ((SceneObjectGroup)so).LocalId = 0;
148 ((SceneObjectGroup)so).RootPart.ClearUpdateSchedule();
149 so.SetState(ad.AttachmentObjectStates[i++], m_scene);
150 m_scene.IncomingCreateObject(Vector3.Zero, so);
151 }
152 }
153 }
154
103 /// <summary> 155 /// <summary>
104 /// RezAttachments. This should only be called upon login on the first region. 156 /// RezAttachments. This should only be called upon login on the first region.
105 /// Attachment rezzings on crossings and TPs are done in a different way. 157 /// Attachment rezzings on crossings and TPs are done in a different way.
@@ -185,40 +237,55 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
185 if (sp.PresenceType == PresenceType.Npc) 237 if (sp.PresenceType == PresenceType.Npc)
186 RezSingleAttachmentFromInventoryInternal(sp, UUID.Zero, attach.AssetID, p, null); 238 RezSingleAttachmentFromInventoryInternal(sp, UUID.Zero, attach.AssetID, p, null);
187 else 239 else
188 RezSingleAttachmentFromInventory(sp, attach.ItemID, p, true, d); 240 RezSingleAttachmentFromInventory(sp, attach.ItemID, p, d);
189 } 241 }
190 catch (Exception e) 242 catch (Exception e)
191 { 243 {
192 m_log.ErrorFormat("[ATTACHMENTS MODULE]: Unable to rez attachment: {0}{1}", e.Message, e.StackTrace); 244 UUID agentId = (sp.ControllingClient == null) ? (UUID)null : sp.ControllingClient.AgentId;
245 m_log.ErrorFormat("[ATTACHMENTS MODULE]: Unable to rez attachment with itemID {0}, assetID {1}, point {2} for {3}: {4}\n{5}",
246 attach.ItemID, attach.AssetID, p, agentId, e.Message, e.StackTrace);
193 } 247 }
194 } 248 }
195 } 249 }
196 250
197 public void SaveChangedAttachments(IScenePresence sp, bool saveAllScripted) 251 public void DeRezAttachments(IScenePresence sp, bool saveChanged, bool saveAllScripted)
198 { 252 {
199// m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name);
200
201 if (!Enabled) 253 if (!Enabled)
202 return; 254 return;
203 255
204 foreach (SceneObjectGroup grp in sp.GetAttachments()) 256// m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name);
257
258 lock (sp.AttachmentsSyncLock)
205 { 259 {
206 grp.IsAttachment = false; 260 foreach (SceneObjectGroup so in sp.GetAttachments())
207 grp.AbsolutePosition = grp.RootPart.AttachedPos; 261 {
208 UpdateKnownItem(sp, grp, saveAllScripted); 262 // We can only remove the script instances from the script engine after we've retrieved their xml state
209 grp.IsAttachment = true; 263 // when we update the attachment item.
264 m_scene.DeleteSceneObject(so, false, false);
265
266 if (saveChanged || saveAllScripted)
267 {
268 so.IsAttachment = false;
269 so.AbsolutePosition = so.RootPart.AttachedPos;
270 UpdateKnownItem(sp, so, saveAllScripted);
271 }
272
273 so.RemoveScriptInstances(true);
274 }
275
276 sp.ClearAttachments();
210 } 277 }
211 } 278 }
212 279
213 public void DeleteAttachmentsFromScene(IScenePresence sp, bool silent) 280 public void DeleteAttachmentsFromScene(IScenePresence sp, bool silent)
214 { 281 {
215// m_log.DebugFormat(
216// "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}",
217// m_scene.RegionInfo.RegionName, sp.Name, silent);
218
219 if (!Enabled) 282 if (!Enabled)
220 return; 283 return;
221 284
285// m_log.DebugFormat(
286// "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}",
287// m_scene.RegionInfo.RegionName, sp.Name, silent);
288
222 foreach (SceneObjectGroup sop in sp.GetAttachments()) 289 foreach (SceneObjectGroup sop in sp.GetAttachments())
223 { 290 {
224 sop.Scene.DeleteSceneObject(sop, silent); 291 sop.Scene.DeleteSceneObject(sop, silent);
@@ -234,6 +301,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
234// m_log.DebugFormat( 301// m_log.DebugFormat(
235// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})", 302// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
236// group.Name, group.LocalId, sp.Name, attachmentPt, silent); 303// group.Name, group.LocalId, sp.Name, attachmentPt, silent);
304
305 if (group.GetSittingAvatarsCount() != 0)
306 {
307// m_log.WarnFormat(
308// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since {4} avatars are still sitting on it",
309// group.Name, group.LocalId, sp.Name, attachmentPt, group.GetSittingAvatarsCount());
310
311 return false;
312 }
237 313
238 if (sp.GetAttachments(attachmentPt).Contains(group)) 314 if (sp.GetAttachments(attachmentPt).Contains(group))
239 { 315 {
@@ -294,32 +370,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
294 group.AttachmentPoint = attachmentPt; 370 group.AttachmentPoint = attachmentPt;
295 group.AbsolutePosition = attachPos; 371 group.AbsolutePosition = attachPos;
296 372
297 // We also don't want to do any of the inventory operations for an NPC.
298 if (sp.PresenceType != PresenceType.Npc) 373 if (sp.PresenceType != PresenceType.Npc)
299 { 374 UpdateUserInventoryWithAttachment(sp, group, attachmentPt);
300 // Remove any previous attachments
301 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
302
303 // At the moment we can only deal with a single attachment
304 if (attachments.Count != 0)
305 {
306 UUID oldAttachmentItemID = attachments[0].FromItemID;
307
308 if (oldAttachmentItemID != UUID.Zero)
309 DetachSingleAttachmentToInvInternal(sp, oldAttachmentItemID);
310 else
311 m_log.WarnFormat(
312 "[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!",
313 attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name);
314 }
315
316 // Add the new attachment to inventory if we don't already have it.
317 UUID newAttachmentItemID = group.FromItemID;
318 if (newAttachmentItemID == UUID.Zero)
319 newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID;
320
321 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group);
322 }
323 375
324 AttachToAgent(sp, group, attachmentPt, attachPos, silent); 376 AttachToAgent(sp, group, attachmentPt, attachPos, silent);
325 } 377 }
@@ -327,12 +379,36 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
327 return true; 379 return true;
328 } 380 }
329 381
382 private void UpdateUserInventoryWithAttachment(IScenePresence sp, SceneObjectGroup group, uint attachmentPt)
383 {
384 // Remove any previous attachments
385 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
386
387 // At the moment we can only deal with a single attachment
388 if (attachments.Count != 0)
389 {
390 if (attachments[0].FromItemID != UUID.Zero)
391 DetachSingleAttachmentToInvInternal(sp, attachments[0]);
392 else
393 m_log.WarnFormat(
394 "[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!",
395 attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name);
396 }
397
398 // Add the new attachment to inventory if we don't already have it.
399 UUID newAttachmentItemID = group.FromItemID;
400 if (newAttachmentItemID == UUID.Zero)
401 newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID;
402
403 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group);
404 }
405
330 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt) 406 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt)
331 { 407 {
332 return RezSingleAttachmentFromInventory(sp, itemID, AttachmentPt, true, null); 408 return RezSingleAttachmentFromInventory(sp, itemID, AttachmentPt, null);
333 } 409 }
334 410
335 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt, bool updateInventoryStatus, XmlDocument doc) 411 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt, XmlDocument doc)
336 { 412 {
337 if (!Enabled) 413 if (!Enabled)
338 return null; 414 return null;
@@ -371,12 +447,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
371 return null; 447 return null;
372 } 448 }
373 449
374 SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, doc); 450 return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, doc);
375
376 if (att == null)
377 DetachSingleAttachmentToInv(sp, itemID);
378
379 return att;
380 } 451 }
381 452
382 public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist) 453 public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist)
@@ -453,18 +524,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
453 m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero); 524 m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero);
454 } 525 }
455 526
456 public void DetachSingleAttachmentToInv(IScenePresence sp, UUID itemID) 527 public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so)
457 { 528 {
458 lock (sp.AttachmentsSyncLock) 529 lock (sp.AttachmentsSyncLock)
459 { 530 {
460 // Save avatar attachment information 531 // Save avatar attachment information
461 m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + sp.UUID + ", ItemID: " + itemID); 532// m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + sp.UUID + ", ItemID: " + itemID);
533
534 if (so.AttachedAvatar != sp.UUID)
535 {
536 m_log.WarnFormat(
537 "[ATTACHMENTS MODULE]: Tried to detach object {0} from {1} {2} but attached avatar id was {3} in {4}",
538 so.Name, sp.Name, sp.UUID, so.AttachedAvatar, m_scene.RegionInfo.RegionName);
462 539
463 bool changed = sp.Appearance.DetachAttachment(itemID); 540 return;
541 }
542
543 bool changed = sp.Appearance.DetachAttachment(so.FromItemID);
464 if (changed && m_scene.AvatarFactory != null) 544 if (changed && m_scene.AvatarFactory != null)
465 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); 545 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
466 546
467 DetachSingleAttachmentToInvInternal(sp, itemID); 547 DetachSingleAttachmentToInvInternal(sp, so);
468 } 548 }
469 } 549 }
470 550
@@ -473,17 +553,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
473 if (!Enabled) 553 if (!Enabled)
474 return; 554 return;
475 555
476 // First we save the
477 // attachment point information, then we update the relative
478 // positioning. Then we have to mark the object as NOT an
479 // attachment. This is necessary in order to correctly save
480 // and retrieve GroupPosition information for the attachment.
481 // Finally, we restore the object's attachment status.
482 uint attachmentPoint = sog.AttachmentPoint;
483 sog.UpdateGroupPosition(pos); 556 sog.UpdateGroupPosition(pos);
484 sog.IsAttachment = false;
485 sog.AbsolutePosition = sog.RootPart.AttachedPos;
486 sog.AttachmentPoint = attachmentPoint;
487 sog.HasGroupChanged = true; 557 sog.HasGroupChanged = true;
488 } 558 }
489 559
@@ -526,6 +596,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
526 /// </remarks> 596 /// </remarks>
527 /// <param name="sp"></param> 597 /// <param name="sp"></param>
528 /// <param name="grp"></param> 598 /// <param name="grp"></param>
599 /// <param name="saveAllScripted"></param>
529 private void UpdateKnownItem(IScenePresence sp, SceneObjectGroup grp, bool saveAllScripted) 600 private void UpdateKnownItem(IScenePresence sp, SceneObjectGroup grp, bool saveAllScripted)
530 { 601 {
531 // Saving attachments for NPCs messes them up for the real owner! 602 // Saving attachments for NPCs messes them up for the real owner!
@@ -538,9 +609,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
538 609
539 if (grp.HasGroupChanged || (saveAllScripted && grp.ContainsScripts())) 610 if (grp.HasGroupChanged || (saveAllScripted && grp.ContainsScripts()))
540 { 611 {
541 m_log.DebugFormat( 612// m_log.DebugFormat(
542 "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", 613// "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}",
543 grp.UUID, grp.AttachmentPoint); 614// grp.UUID, grp.AttachmentPoint);
544 615
545 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp); 616 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
546 617
@@ -571,12 +642,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
571 } 642 }
572 grp.HasGroupChanged = false; // Prevent it being saved over and over 643 grp.HasGroupChanged = false; // Prevent it being saved over and over
573 } 644 }
574 else 645// else
575 { 646// {
576 m_log.DebugFormat( 647// m_log.DebugFormat(
577 "[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}", 648// "[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}",
578 grp.UUID, grp.AttachmentPoint); 649// grp.UUID, grp.AttachmentPoint);
579 } 650// }
580 } 651 }
581 652
582 /// <summary> 653 /// <summary>
@@ -594,9 +665,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
594 private void AttachToAgent( 665 private void AttachToAgent(
595 IScenePresence sp, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent) 666 IScenePresence sp, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
596 { 667 {
597 // m_log.DebugFormat( 668// m_log.DebugFormat(
598 // "[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}", 669// "[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}",
599 // so.Name, avatar.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos); 670// so.Name, sp.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos);
600 671
601 so.DetachFromBackup(); 672 so.DetachFromBackup();
602 673
@@ -627,6 +698,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
627 { 698 {
628 m_scene.SendKillObject(new List<uint> { so.RootPart.LocalId }); 699 m_scene.SendKillObject(new List<uint> { so.RootPart.LocalId });
629 } 700 }
701 else if (so.HasPrivateAttachmentPoint)
702 {
703// m_log.DebugFormat(
704// "[ATTACHMENTS MODULE]: Killing private HUD {0} for avatars other than {1} at attachment point {2}",
705// so.Name, sp.Name, so.AttachmentPoint);
706
707 // As this scene object can now only be seen by the attaching avatar, tell everybody else in the
708 // scene that it's no longer in their awareness.
709 m_scene.ForEachClient(
710 client =>
711 { if (client.AgentId != so.AttachedAvatar)
712 client.SendKillObject(m_scene.RegionInfo.RegionHandle, new List<uint>() { so.LocalId });
713 });
714 }
630 715
631 so.IsSelected = false; // fudge.... 716 so.IsSelected = false; // fudge....
632 so.ScheduleGroupForFullUpdate(); 717 so.ScheduleGroupForFullUpdate();
@@ -645,210 +730,124 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
645 /// <returns>The user inventory item created that holds the attachment.</returns> 730 /// <returns>The user inventory item created that holds the attachment.</returns>
646 private InventoryItemBase AddSceneObjectAsNewAttachmentInInv(IScenePresence sp, SceneObjectGroup grp) 731 private InventoryItemBase AddSceneObjectAsNewAttachmentInInv(IScenePresence sp, SceneObjectGroup grp)
647 { 732 {
733 if (m_invAccessModule == null)
734 return null;
735
648 // m_log.DebugFormat( 736 // m_log.DebugFormat(
649 // "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}", 737 // "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}",
650 // grp.Name, grp.LocalId, remoteClient.Name); 738 // grp.Name, grp.LocalId, remoteClient.Name);
651 739
652// Vector3 inventoryStoredPosition = new Vector3 740 InventoryItemBase newItem
653// (((grp.AbsolutePosition.X > (int)Constants.RegionSize) 741 = m_invAccessModule.CopyToInventory(
654// ? (float)Constants.RegionSize - 6 742 DeRezAction.TakeCopy,
655// : grp.AbsolutePosition.X) 743 m_scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object).ID,
656// , 744 new List<SceneObjectGroup> { grp },
657// (grp.AbsolutePosition.Y > (int)Constants.RegionSize) 745 sp.ControllingClient, true)[0];
658// ? (float)Constants.RegionSize - 6
659// : grp.AbsolutePosition.Y,
660// grp.AbsolutePosition.Z);
661//
662// Vector3 originalPosition = grp.AbsolutePosition;
663//
664// grp.AbsolutePosition = inventoryStoredPosition;
665
666 // If we're being called from a script, then trying to serialize that same script's state will not complete
667 // in any reasonable time period. Therefore, we'll avoid it. The worst that can happen is that if
668 // the client/server crashes rather than logging out normally, the attachment's scripts will resume
669 // without state on relog. Arguably, this is what we want anyway.
670 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, false);
671
672// grp.AbsolutePosition = originalPosition;
673
674 AssetBase asset = m_scene.CreateAsset(
675 grp.GetPartName(grp.LocalId),
676 grp.GetPartDescription(grp.LocalId),
677 (sbyte)AssetType.Object,
678 Utils.StringToBytes(sceneObjectXml),
679 sp.UUID);
680
681 m_scene.AssetService.Store(asset);
682
683 InventoryItemBase item = new InventoryItemBase();
684 item.CreatorId = grp.RootPart.CreatorID.ToString();
685 item.CreatorData = grp.RootPart.CreatorData;
686 item.Owner = sp.UUID;
687 item.ID = UUID.Random();
688 item.AssetID = asset.FullID;
689 item.Description = asset.Description;
690 item.Name = asset.Name;
691 item.AssetType = asset.Type;
692 item.InvType = (int)InventoryType.Object;
693
694 InventoryFolderBase folder = m_scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object);
695 if (folder != null)
696 item.Folder = folder.ID;
697 else // oopsies
698 item.Folder = UUID.Zero;
699
700 // Nix the special bits we used to use for slam and the folded perms
701 uint allowablePermissionsMask = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move);
702
703 if ((sp.UUID != grp.RootPart.OwnerID) && m_scene.Permissions.PropagatePermissions())
704 {
705 item.BasePermissions = grp.RootPart.BaseMask & grp.RootPart.NextOwnerMask & allowablePermissionsMask;
706 item.CurrentPermissions = grp.RootPart.BaseMask & grp.RootPart.NextOwnerMask & allowablePermissionsMask;
707 item.NextPermissions = grp.RootPart.NextOwnerMask & allowablePermissionsMask;
708 item.EveryOnePermissions = grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask & allowablePermissionsMask;
709 item.GroupPermissions = grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask & allowablePermissionsMask;
710 }
711 else
712 {
713 item.BasePermissions = grp.RootPart.BaseMask & allowablePermissionsMask;
714 item.CurrentPermissions = grp.RootPart.OwnerMask & allowablePermissionsMask;
715 item.NextPermissions = grp.RootPart.NextOwnerMask & allowablePermissionsMask;
716 item.EveryOnePermissions = grp.RootPart.EveryoneMask & allowablePermissionsMask;
717 item.GroupPermissions = grp.RootPart.GroupMask & allowablePermissionsMask;
718 }
719 item.CreationDate = Util.UnixTimeSinceEpoch();
720 746
721 // sets itemID so client can show item as 'attached' in inventory 747 // sets itemID so client can show item as 'attached' in inventory
722 grp.FromItemID = item.ID; 748 grp.FromItemID = newItem.ID;
723
724 if (m_scene.AddInventoryItem(item))
725 {
726 sp.ControllingClient.SendInventoryItemCreateUpdate(item, 0);
727 }
728 else
729 {
730 if (m_dialogModule != null)
731 m_dialogModule.SendAlertToUser(sp.ControllingClient, "Operation failed");
732 }
733 749
734 return item; 750 return newItem;
735 } 751 }
736 752
737 // What makes this method odd and unique is it tries to detach using an UUID.... Yay for standards. 753 private void DetachSingleAttachmentToInvInternal(IScenePresence sp, SceneObjectGroup so)
738 // To LocalId or UUID, *THAT* is the question. How now Brown UUID??
739 private void DetachSingleAttachmentToInvInternal(IScenePresence sp, UUID itemID)
740 { 754 {
741 // m_log.DebugFormat("[ATTACHMENTS MODULE]: Detaching item {0} to inventory for {1}", itemID, sp.Name); 755 // m_log.DebugFormat("[ATTACHMENTS MODULE]: Detaching item {0} to inventory for {1}", itemID, sp.Name);
742 756
743 if (itemID == UUID.Zero) // If this happened, someone made a mistake.... 757 m_scene.EventManager.TriggerOnAttach(so.LocalId, so.FromItemID, UUID.Zero);
744 return; 758 sp.RemoveAttachment(so);
745
746 // We can NOT use the dictionries here, as we are looking
747 // for an entity by the fromAssetID, which is NOT the prim UUID
748 EntityBase[] detachEntities = m_scene.GetEntities();
749 SceneObjectGroup group;
750
751 lock (sp.AttachmentsSyncLock)
752 {
753 foreach (EntityBase entity in detachEntities)
754 {
755 if (entity is SceneObjectGroup)
756 {
757 group = (SceneObjectGroup)entity;
758 if (group.FromItemID == itemID)
759 {
760 m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero);
761 sp.RemoveAttachment(group);
762 759
763 // Prepare sog for storage 760 // We can only remove the script instances from the script engine after we've retrieved their xml state
764 group.AttachedAvatar = UUID.Zero; 761 // when we update the attachment item.
765 group.RootPart.SetParentLocalId(0); 762 m_scene.DeleteSceneObject(so, false, false);
766 group.IsAttachment = false;
767 group.AbsolutePosition = group.RootPart.AttachedPos;
768 763
769 UpdateKnownItem(sp, group, true); 764 // Prepare sog for storage
770 m_scene.DeleteSceneObject(group, false); 765 so.AttachedAvatar = UUID.Zero;
766 so.RootPart.SetParentLocalId(0);
767 so.IsAttachment = false;
768 so.AbsolutePosition = so.RootPart.AttachedPos;
771 769
772 return; 770 UpdateKnownItem(sp, so, true);
773 } 771 so.RemoveScriptInstances(true);
774 }
775 }
776 }
777 } 772 }
778 773
779 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal( 774 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal(
780 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, XmlDocument doc) 775 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, XmlDocument doc)
781 { 776 {
782 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>(); 777 if (m_invAccessModule == null)
783 if (invAccess != null) 778 return null;
779
780 lock (sp.AttachmentsSyncLock)
784 { 781 {
785 lock (sp.AttachmentsSyncLock) 782 SceneObjectGroup objatt;
783
784 if (itemID != UUID.Zero)
785 objatt = m_invAccessModule.RezObject(sp.ControllingClient,
786 itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
787 false, false, sp.UUID, true);
788 else
789 objatt = m_invAccessModule.RezObject(sp.ControllingClient,
790 null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
791 false, false, sp.UUID, true);
792
793 if (objatt != null)
786 { 794 {
787 SceneObjectGroup objatt; 795// m_log.DebugFormat(
788 796// "[ATTACHMENTS MODULE]: Rezzed single object {0} for attachment to {1} on point {2} in {3}",
789 if (itemID != UUID.Zero) 797// objatt.Name, sp.Name, attachmentPt, m_scene.Name);
790 objatt = invAccess.RezObject(sp.ControllingClient, 798
791 itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, 799 // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller.
792 false, false, sp.UUID, true); 800 objatt.HasGroupChanged = false;
793 else 801 bool tainted = false;
794 objatt = invAccess.RezObject(sp.ControllingClient, 802 if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint)
795 null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, 803 tainted = true;
796 false, false, sp.UUID, true); 804
797 805 // FIXME: Detect whether it's really likely for AttachObject to throw an exception in the normal
798 // m_log.DebugFormat( 806 // course of events. If not, then it's probably not worth trying to recover the situation
799 // "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}", 807 // since this is more likely to trigger further exceptions and confuse later debugging. If
800 // objatt.Name, remoteClient.Name, AttachmentPt); 808 // exceptions can be thrown in expected error conditions (not NREs) then make this consistent
801 809 // since other normal error conditions will simply return false instead.
802 if (objatt != null) 810 // This will throw if the attachment fails
811 try
803 { 812 {
804 // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. 813 AttachObject(sp, objatt, attachmentPt, false, false);
805 objatt.HasGroupChanged = false;
806 bool tainted = false;
807 if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint)
808 tainted = true;
809
810 // This will throw if the attachment fails
811 try
812 {
813 AttachObject(sp, objatt, attachmentPt, false, false);
814 }
815 catch (Exception e)
816 {
817 m_log.ErrorFormat(
818 "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}",
819 objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace);
820
821 // Make sure the object doesn't stick around and bail
822 sp.RemoveAttachment(objatt);
823 m_scene.DeleteSceneObject(objatt, false);
824 return null;
825 }
826
827 if (tainted)
828 objatt.HasGroupChanged = true;
829
830 if (doc != null)
831 {
832 objatt.LoadScriptState(doc);
833 objatt.ResetOwnerChangeFlag();
834 }
835
836 // Fire after attach, so we don't get messy perms dialogs
837 // 4 == AttachedRez
838 objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4);
839 objatt.ResumeScripts();
840
841 // Do this last so that event listeners have access to all the effects of the attachment
842 m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID);
843
844 return objatt;
845 } 814 }
846 else 815 catch (Exception e)
816 {
817 m_log.ErrorFormat(
818 "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}",
819 objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace);
820
821 // Make sure the object doesn't stick around and bail
822 sp.RemoveAttachment(objatt);
823 m_scene.DeleteSceneObject(objatt, false);
824 return null;
825 }
826
827 if (tainted)
828 objatt.HasGroupChanged = true;
829
830 if (doc != null)
847 { 831 {
848 m_log.WarnFormat( 832 objatt.LoadScriptState(doc);
849 "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}", 833 objatt.ResetOwnerChangeFlag();
850 itemID, sp.Name, attachmentPt);
851 } 834 }
835
836 // Fire after attach, so we don't get messy perms dialogs
837 // 4 == AttachedRez
838 objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4);
839 objatt.ResumeScripts();
840
841 // Do this last so that event listeners have access to all the effects of the attachment
842 m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID);
843
844 return objatt;
845 }
846 else
847 {
848 m_log.WarnFormat(
849 "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}",
850 itemID, sp.Name, attachmentPt);
852 } 851 }
853 } 852 }
854 853
@@ -864,9 +863,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
864 /// <param name="att"></param> 863 /// <param name="att"></param>
865 private void ShowAttachInUserInventory(IScenePresence sp, uint AttachmentPt, UUID itemID, SceneObjectGroup att) 864 private void ShowAttachInUserInventory(IScenePresence sp, uint AttachmentPt, UUID itemID, SceneObjectGroup att)
866 { 865 {
867 // m_log.DebugFormat( 866// m_log.DebugFormat(
868 // "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}", 867// "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}",
869 // att.Name, sp.Name, AttachmentPt, itemID); 868// att.Name, sp.Name, AttachmentPt, itemID);
870 869
871 if (UUID.Zero == itemID) 870 if (UUID.Zero == itemID)
872 { 871 {
@@ -884,7 +883,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
884 item = m_scene.InventoryService.GetItem(item); 883 item = m_scene.InventoryService.GetItem(item);
885 bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID); 884 bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID);
886 if (changed && m_scene.AvatarFactory != null) 885 if (changed && m_scene.AvatarFactory != null)
886 {
887// m_log.DebugFormat(
888// "[ATTACHMENTS MODULE]: Queueing appearance save for {0}, attachment {1} point {2} in ShowAttachInUserInventory()",
889// sp.Name, att.Name, AttachmentPt);
890
887 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); 891 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
892 }
888 } 893 }
889 894
890 #endregion 895 #endregion
@@ -929,9 +934,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
929 934
930 private void Client_OnObjectAttach(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, bool silent) 935 private void Client_OnObjectAttach(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, bool silent)
931 { 936 {
932 // m_log.DebugFormat( 937// m_log.DebugFormat(
933 // "[ATTACHMENTS MODULE]: Attaching object local id {0} to {1} point {2} from ground (silent = {3})", 938// "[ATTACHMENTS MODULE]: Attaching object local id {0} to {1} point {2} from ground (silent = {3})",
934 // objectLocalID, remoteClient.Name, AttachmentPt, silent); 939// objectLocalID, remoteClient.Name, AttachmentPt, silent);
935 940
936 if (!Enabled) 941 if (!Enabled)
937 return; 942 return;
@@ -967,13 +972,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
967 // Calls attach with a Zero position 972 // Calls attach with a Zero position
968 if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, true)) 973 if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, true))
969 { 974 {
970 m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.FromItemID, remoteClient.AgentId); 975// m_log.Debug(
976// "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId
977// + ", AttachmentPoint: " + AttachmentPt);
971 978
972 // Save avatar attachment information 979 // Save avatar attachment information
973 m_log.Debug( 980 m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.FromItemID, remoteClient.AgentId);
974 "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId
975 + ", AttachmentPoint: " + AttachmentPt);
976
977 } 981 }
978 } 982 }
979 catch (Exception e) 983 catch (Exception e)
@@ -989,8 +993,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
989 993
990 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); 994 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
991 SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID); 995 SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID);
996
992 if (sp != null && group != null) 997 if (sp != null && group != null)
993 DetachSingleAttachmentToInv(sp, group.FromItemID); 998 DetachSingleAttachmentToInv(sp, group);
994 } 999 }
995 1000
996 private void Client_OnDetachAttachmentIntoInv(UUID itemID, IClientAPI remoteClient) 1001 private void Client_OnDetachAttachmentIntoInv(UUID itemID, IClientAPI remoteClient)
@@ -1000,7 +1005,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1000 1005
1001 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); 1006 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
1002 if (sp != null) 1007 if (sp != null)
1003 DetachSingleAttachmentToInv(sp, itemID); 1008 {
1009 lock (sp.AttachmentsSyncLock)
1010 {
1011 List<SceneObjectGroup> attachments = sp.GetAttachments();
1012
1013 foreach (SceneObjectGroup group in attachments)
1014 {
1015 if (group.FromItemID == itemID)
1016 {
1017 DetachSingleAttachmentToInv(sp, group);
1018 return;
1019 }
1020 }
1021 }
1022 }
1004 } 1023 }
1005 1024
1006 private void Client_OnObjectDrop(uint soLocalId, IClientAPI remoteClient) 1025 private void Client_OnObjectDrop(uint soLocalId, IClientAPI remoteClient)
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index 7119ad2..cd1e1c1 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -31,6 +31,7 @@ using System.Reflection;
31using System.Text; 31using System.Text;
32using System.Threading; 32using System.Threading;
33using System.Timers; 33using System.Timers;
34using System.Xml;
34using Timer=System.Timers.Timer; 35using Timer=System.Timers.Timer;
35using Nini.Config; 36using Nini.Config;
36using NUnit.Framework; 37using NUnit.Framework;
@@ -38,11 +39,16 @@ using OpenMetaverse;
38using OpenSim.Framework; 39using OpenSim.Framework;
39using OpenSim.Framework.Communications; 40using OpenSim.Framework.Communications;
40using OpenSim.Region.CoreModules.Avatar.Attachments; 41using OpenSim.Region.CoreModules.Avatar.Attachments;
42using OpenSim.Region.CoreModules.Framework;
43using OpenSim.Region.CoreModules.Framework.EntityTransfer;
41using OpenSim.Region.CoreModules.Framework.InventoryAccess; 44using OpenSim.Region.CoreModules.Framework.InventoryAccess;
42using OpenSim.Region.CoreModules.World.Serialiser; 45using OpenSim.Region.CoreModules.Scripting.WorldComm;
43using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; 46using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
47using OpenSim.Region.CoreModules.World.Serialiser;
44using OpenSim.Region.Framework.Scenes; 48using OpenSim.Region.Framework.Scenes;
45using OpenSim.Region.Framework.Interfaces; 49using OpenSim.Region.Framework.Interfaces;
50using OpenSim.Region.ScriptEngine.XEngine;
51using OpenSim.Services.Interfaces;
46using OpenSim.Tests.Common; 52using OpenSim.Tests.Common;
47using OpenSim.Tests.Common.Mock; 53using OpenSim.Tests.Common.Mock;
48 54
@@ -52,11 +58,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
52 /// Attachment tests 58 /// Attachment tests
53 /// </summary> 59 /// </summary>
54 [TestFixture] 60 [TestFixture]
55 public class AttachmentsModuleTests 61 public class AttachmentsModuleTests : OpenSimTestCase
56 { 62 {
57 private Scene scene; 63 private AutoResetEvent m_chatEvent = new AutoResetEvent(false);
58 private AttachmentsModule m_attMod; 64 private OSChatMessage m_osChatMessageReceived;
59 private ScenePresence m_presence;
60 65
61 [TestFixtureSetUp] 66 [TestFixtureSetUp]
62 public void FixtureInit() 67 public void FixtureInit()
@@ -65,52 +70,129 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
65 Util.FireAndForgetMethod = FireAndForgetMethod.None; 70 Util.FireAndForgetMethod = FireAndForgetMethod.None;
66 } 71 }
67 72
68 [SetUp] 73 [TestFixtureTearDown]
69 public void Init() 74 public void TearDown()
75 {
76 // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple
77 // threads. Possibly, later tests should be rewritten not to worry about such things.
78 Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
79 }
80
81 private void OnChatFromWorld(object sender, OSChatMessage oscm)
82 {
83// Console.WriteLine("Got chat [{0}]", oscm.Message);
84
85 m_osChatMessageReceived = oscm;
86 m_chatEvent.Set();
87 }
88
89 private Scene CreateTestScene()
70 { 90 {
71 IConfigSource config = new IniConfigSource(); 91 IConfigSource config = new IniConfigSource();
92 List<object> modules = new List<object>();
93
94 AddCommonConfig(config, modules);
95
96 Scene scene
97 = new SceneHelpers().SetupScene(
98 "attachments-test-scene", TestHelpers.ParseTail(999), 1000, 1000, config);
99 SceneHelpers.SetupSceneModules(scene, config, modules.ToArray());
100
101 return scene;
102 }
103
104 private Scene CreateScriptingEnabledTestScene()
105 {
106 IConfigSource config = new IniConfigSource();
107 List<object> modules = new List<object>();
108
109 AddCommonConfig(config, modules);
110 AddScriptingConfig(config, modules);
111
112 Scene scene
113 = new SceneHelpers().SetupScene(
114 "attachments-test-scene", TestHelpers.ParseTail(999), 1000, 1000, config);
115 SceneHelpers.SetupSceneModules(scene, config, modules.ToArray());
116
117 scene.StartScripts();
118
119 return scene;
120 }
121
122 private void AddCommonConfig(IConfigSource config, List<object> modules)
123 {
72 config.AddConfig("Modules"); 124 config.AddConfig("Modules");
73 config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule"); 125 config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule");
74 126
75 scene = SceneHelpers.SetupScene(); 127 modules.Add(new AttachmentsModule());
76 m_attMod = new AttachmentsModule(); 128 modules.Add(new BasicInventoryAccessModule());
77 SceneHelpers.SetupSceneModules(scene, config, m_attMod, new BasicInventoryAccessModule());
78 } 129 }
79 130
80 [TestFixtureTearDown] 131 private void AddScriptingConfig(IConfigSource config, List<object> modules)
81 public void TearDown()
82 { 132 {
83 // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple 133 IConfig startupConfig = config.AddConfig("Startup");
84 // threads. Possibly, later tests should be rewritten not to worry about such things. 134 startupConfig.Set("DefaultScriptEngine", "XEngine");
85 Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; 135
136 IConfig xEngineConfig = config.AddConfig("XEngine");
137 xEngineConfig.Set("Enabled", "true");
138 xEngineConfig.Set("StartDelay", "0");
139
140 // These tests will not run with AppDomainLoading = true, at least on mono. For unknown reasons, the call
141 // to AssemblyResolver.OnAssemblyResolve fails.
142 xEngineConfig.Set("AppDomainLoading", "false");
143
144 modules.Add(new XEngine());
145
146 // Necessary to stop serialization complaining
147 // FIXME: Stop this being necessary if at all possible
148// modules.Add(new WorldCommModule());
86 } 149 }
87 150
88 /// <summary> 151 /// <summary>
89 /// Add the standard presence for a test. 152 /// Creates an attachment item in the given user's inventory. Does not attach.
90 /// </summary> 153 /// </summary>
91 private void AddPresence() 154 /// <remarks>
155 /// A user with the given ID and an inventory must already exist.
156 /// </remarks>
157 /// <returns>
158 /// The attachment item.
159 /// </returns>
160 /// <param name='scene'></param>
161 /// <param name='userId'></param>
162 /// <param name='attName'></param>
163 /// <param name='rawItemId'></param>
164 /// <param name='rawAssetId'></param>
165 private InventoryItemBase CreateAttachmentItem(
166 Scene scene, UUID userId, string attName, int rawItemId, int rawAssetId)
92 { 167 {
93 UUID userId = TestHelpers.ParseTail(0x1); 168 return UserInventoryHelpers.CreateInventoryItem(
94 UserAccountHelpers.CreateUserWithInventory(scene, userId); 169 scene,
95 m_presence = SceneHelpers.AddScenePresence(scene, userId); 170 attName,
171 TestHelpers.ParseTail(rawItemId),
172 TestHelpers.ParseTail(rawAssetId),
173 userId,
174 InventoryType.Object);
96 } 175 }
97 176
98 [Test] 177 [Test]
99 public void TestAddAttachmentFromGround() 178 public void TestAddAttachmentFromGround()
100 { 179 {
101 TestHelpers.InMethod(); 180 TestHelpers.InMethod();
102// log4net.Config.XmlConfigurator.Configure(); 181// TestHelpers.EnableLogging();
182
183 Scene scene = CreateTestScene();
184 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
185 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
103 186
104 AddPresence();
105 string attName = "att"; 187 string attName = "att";
106 188
107 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName).ParentGroup; 189 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID);
108 190
109 m_attMod.AttachObject(m_presence, so, (uint)AttachmentPoint.Chest, false, false); 191 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false);
110 192
111 // Check status on scene presence 193 // Check status on scene presence
112 Assert.That(m_presence.HasAttachments(), Is.True); 194 Assert.That(sp.HasAttachments(), Is.True);
113 List<SceneObjectGroup> attachments = m_presence.GetAttachments(); 195 List<SceneObjectGroup> attachments = sp.GetAttachments();
114 Assert.That(attachments.Count, Is.EqualTo(1)); 196 Assert.That(attachments.Count, Is.EqualTo(1));
115 SceneObjectGroup attSo = attachments[0]; 197 SceneObjectGroup attSo = attachments[0];
116 Assert.That(attSo.Name, Is.EqualTo(attName)); 198 Assert.That(attSo.Name, Is.EqualTo(attName));
@@ -121,42 +203,107 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
121 203
122 // Check item status 204 // Check item status
123 Assert.That( 205 Assert.That(
124 m_presence.Appearance.GetAttachpoint(attSo.FromItemID), 206 sp.Appearance.GetAttachpoint(attSo.FromItemID),
125 Is.EqualTo((int)AttachmentPoint.Chest)); 207 Is.EqualTo((int)AttachmentPoint.Chest));
208
209 InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID));
210 Assert.That(attachmentItem, Is.Not.Null);
211 Assert.That(attachmentItem.Name, Is.EqualTo(attName));
212
213 InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object);
214 Assert.That(attachmentItem.Folder, Is.EqualTo(targetFolder.ID));
215
216 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
217
218// TestHelpers.DisableLogging();
126 } 219 }
127 220
221 /// <summary>
222 /// Test that we do not attempt to attach an in-world object that someone else is sitting on.
223 /// </summary>
128 [Test] 224 [Test]
129 public void TestAddAttachmentFromInventory() 225 public void TestAddSatOnAttachmentFromGround()
130 { 226 {
131 TestHelpers.InMethod(); 227 TestHelpers.InMethod();
132// log4net.Config.XmlConfigurator.Configure(); 228// TestHelpers.EnableLogging();
133 229
134 AddPresence(); 230 Scene scene = CreateTestScene();
231 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
232 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
135 233
136 UUID attItemId = TestHelpers.ParseTail(0x2);
137 UUID attAssetId = TestHelpers.ParseTail(0x3);
138 string attName = "att"; 234 string attName = "att";
139 235
140 UserInventoryHelpers.CreateInventoryItem( 236 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID);
141 scene, attName, attItemId, attAssetId, m_presence.UUID, InventoryType.Object); 237
238 UserAccount ua2 = UserAccountHelpers.CreateUserWithInventory(scene, 0x2);
239 ScenePresence sp2 = SceneHelpers.AddScenePresence(scene, ua2);
240
241 // Put avatar within 10m of the prim so that sit doesn't fail.
242 sp2.AbsolutePosition = new Vector3(0, 0, 0);
243 sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero);
244
245 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false);
246
247 Assert.That(sp.HasAttachments(), Is.False);
248 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
249 }
250
251 [Test]
252 public void TestRezAttachmentFromInventory()
253 {
254 TestHelpers.InMethod();
255// log4net.Config.XmlConfigurator.Configure();
256
257 Scene scene = CreateTestScene();
258 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
259 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID);
142 260
143 m_attMod.RezSingleAttachmentFromInventory( 261 InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
144 m_presence, attItemId, (uint)AttachmentPoint.Chest); 262
263 scene.AttachmentsModule.RezSingleAttachmentFromInventory(
264 sp, attItem.ID, (uint)AttachmentPoint.Chest);
145 265
146 // Check scene presence status 266 // Check scene presence status
147 Assert.That(m_presence.HasAttachments(), Is.True); 267 Assert.That(sp.HasAttachments(), Is.True);
148 List<SceneObjectGroup> attachments = m_presence.GetAttachments(); 268 List<SceneObjectGroup> attachments = sp.GetAttachments();
149 Assert.That(attachments.Count, Is.EqualTo(1)); 269 Assert.That(attachments.Count, Is.EqualTo(1));
150 SceneObjectGroup attSo = attachments[0]; 270 SceneObjectGroup attSo = attachments[0];
151 Assert.That(attSo.Name, Is.EqualTo(attName)); 271 Assert.That(attSo.Name, Is.EqualTo(attItem.Name));
152 Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest)); 272 Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest));
153 Assert.That(attSo.IsAttachment); 273 Assert.That(attSo.IsAttachment);
154 Assert.That(attSo.UsesPhysics, Is.False); 274 Assert.That(attSo.UsesPhysics, Is.False);
155 Assert.That(attSo.IsTemporary, Is.False); 275 Assert.That(attSo.IsTemporary, Is.False);
156 276
157 // Check appearance status 277 // Check appearance status
158 Assert.That(m_presence.Appearance.GetAttachments().Count, Is.EqualTo(1)); 278 Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
159 Assert.That(m_presence.Appearance.GetAttachpoint(attItemId), Is.EqualTo((int)AttachmentPoint.Chest)); 279 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
280
281 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
282 }
283
284 /// <summary>
285 /// Test specific conditions associated with rezzing a scripted attachment from inventory.
286 /// </summary>
287 [Test]
288 public void TestRezScriptedAttachmentFromInventory()
289 {
290 TestHelpers.InMethod();
291
292 Scene scene = CreateTestScene();
293 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
294 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID);
295
296 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, sp.UUID, "att-name", 0x10);
297 TaskInventoryHelpers.AddScript(scene, so.RootPart);
298 InventoryItemBase userItem = UserInventoryHelpers.AddInventoryItem(scene, so, 0x100, 0x1000);
299
300 scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest);
301
302 // TODO: Need to have a test that checks the script is actually started but this involves a lot more
303 // plumbing of the script engine and either pausing for events or more infrastructure to turn off various
304 // script engine delays/asychronicity that isn't helpful in an automated regression testing context.
305 SceneObjectGroup attSo = scene.GetSceneObjectGroup(so.Name);
306 Assert.That(attSo.ContainsScripts(), Is.True);
160 } 307 }
161 308
162 [Test] 309 [Test]
@@ -165,29 +312,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
165 TestHelpers.InMethod(); 312 TestHelpers.InMethod();
166// log4net.Config.XmlConfigurator.Configure(); 313// log4net.Config.XmlConfigurator.Configure();
167 314
168 AddPresence(); 315 Scene scene = CreateTestScene();
316 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
317 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID);
169 318
170 UUID attItemId = TestHelpers.ParseTail(0x2); 319 InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
171 UUID attAssetId = TestHelpers.ParseTail(0x3);
172 string attName = "att";
173 320
174 UserInventoryHelpers.CreateInventoryItem( 321 ISceneEntity so
175 scene, attName, attItemId, attAssetId, m_presence.UUID, InventoryType.Object); 322 = scene.AttachmentsModule.RezSingleAttachmentFromInventory(
176 323 sp, attItem.ID, (uint)AttachmentPoint.Chest);
177 ISceneEntity so = m_attMod.RezSingleAttachmentFromInventory( 324 scene.AttachmentsModule.DetachSingleAttachmentToGround(sp, so.LocalId);
178 m_presence, attItemId, (uint)AttachmentPoint.Chest);
179 m_attMod.DetachSingleAttachmentToGround(m_presence, so.LocalId);
180 325
181 // Check scene presence status 326 // Check scene presence status
182 Assert.That(m_presence.HasAttachments(), Is.False); 327 Assert.That(sp.HasAttachments(), Is.False);
183 List<SceneObjectGroup> attachments = m_presence.GetAttachments(); 328 List<SceneObjectGroup> attachments = sp.GetAttachments();
184 Assert.That(attachments.Count, Is.EqualTo(0)); 329 Assert.That(attachments.Count, Is.EqualTo(0));
185 330
186 // Check appearance status 331 // Check appearance status
187 Assert.That(m_presence.Appearance.GetAttachments().Count, Is.EqualTo(0)); 332 Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(0));
188 333
189 // Check item status 334 // Check item status
190 Assert.That(scene.InventoryService.GetItem(new InventoryItemBase(attItemId)), Is.Null); 335 Assert.That(scene.InventoryService.GetItem(new InventoryItemBase(attItem.ID)), Is.Null);
191 336
192 // Check object in scene 337 // Check object in scene
193 Assert.That(scene.GetSceneObjectGroup("att"), Is.Not.Null); 338 Assert.That(scene.GetSceneObjectGroup("att"), Is.Not.Null);
@@ -197,28 +342,66 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
197 public void TestDetachAttachmentToInventory() 342 public void TestDetachAttachmentToInventory()
198 { 343 {
199 TestHelpers.InMethod(); 344 TestHelpers.InMethod();
200// log4net.Config.XmlConfigurator.Configure();
201 345
202 AddPresence(); 346 Scene scene = CreateTestScene();
347 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
348 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID);
203 349
204 UUID attItemId = TestHelpers.ParseTail(0x2); 350 InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
205 UUID attAssetId = TestHelpers.ParseTail(0x3);
206 string attName = "att";
207
208 UserInventoryHelpers.CreateInventoryItem(
209 scene, attName, attItemId, attAssetId, m_presence.UUID, InventoryType.Object);
210 351
211 m_attMod.RezSingleAttachmentFromInventory( 352 SceneObjectGroup so
212 m_presence, attItemId, (uint)AttachmentPoint.Chest); 353 = (SceneObjectGroup)scene.AttachmentsModule.RezSingleAttachmentFromInventory(
213 m_attMod.DetachSingleAttachmentToInv(m_presence, attItemId); 354 sp, attItem.ID, (uint)AttachmentPoint.Chest);
355 scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, so);
214 356
215 // Check status on scene presence 357 // Check status on scene presence
216 Assert.That(m_presence.HasAttachments(), Is.False); 358 Assert.That(sp.HasAttachments(), Is.False);
217 List<SceneObjectGroup> attachments = m_presence.GetAttachments(); 359 List<SceneObjectGroup> attachments = sp.GetAttachments();
218 Assert.That(attachments.Count, Is.EqualTo(0)); 360 Assert.That(attachments.Count, Is.EqualTo(0));
219 361
220 // Check item status 362 // Check item status
221 Assert.That(m_presence.Appearance.GetAttachpoint(attItemId), Is.EqualTo(0)); 363 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo(0));
364
365 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(0));
366 }
367
368 /// <summary>
369 /// Test specific conditions associated with detaching a scripted attachment from inventory.
370 /// </summary>
371 [Test]
372 public void TestDetachScriptedAttachmentToInventory()
373 {
374 TestHelpers.InMethod();
375// TestHelpers.EnableLogging();
376
377 Scene scene = CreateScriptingEnabledTestScene();
378 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
379 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
380
381 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, sp.UUID, "att-name", 0x10);
382 TaskInventoryHelpers.AddScript(scene, so.RootPart);
383 InventoryItemBase userItem = UserInventoryHelpers.AddInventoryItem(scene, so, 0x100, 0x1000);
384
385 // FIXME: Right now, we have to do a tricksy chat listen to make sure we know when the script is running.
386 // In the future, we need to be able to do this programatically more predicably.
387 scene.EventManager.OnChatFromWorld += OnChatFromWorld;
388
389 SceneObjectGroup soRezzed
390 = (SceneObjectGroup)scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest);
391
392 // Wait for chat to signal rezzed script has been started.
393 m_chatEvent.WaitOne(60000);
394
395 scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, soRezzed);
396
397 InventoryItemBase userItemUpdated = scene.InventoryService.GetItem(userItem);
398 AssetBase asset = scene.AssetService.Get(userItemUpdated.AssetID.ToString());
399
400 XmlDocument soXml = new XmlDocument();
401 soXml.LoadXml(Encoding.UTF8.GetString(asset.Data));
402
403 XmlNodeList scriptStateNodes = soXml.GetElementsByTagName("ScriptState");
404 Assert.That(scriptStateNodes.Count, Is.EqualTo(1));
222 } 405 }
223 406
224 /// <summary> 407 /// <summary>
@@ -230,17 +413,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
230 TestHelpers.InMethod(); 413 TestHelpers.InMethod();
231// log4net.Config.XmlConfigurator.Configure(); 414// log4net.Config.XmlConfigurator.Configure();
232 415
233 UUID userId = TestHelpers.ParseTail(0x1); 416 Scene scene = CreateTestScene();
234 UUID attItemId = TestHelpers.ParseTail(0x2); 417 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
235 UUID attAssetId = TestHelpers.ParseTail(0x3); 418 InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
236 string attName = "att";
237
238 UserAccountHelpers.CreateUserWithInventory(scene, userId);
239 InventoryItemBase attItem
240 = UserInventoryHelpers.CreateInventoryItem(
241 scene, attName, attItemId, attAssetId, userId, InventoryType.Object);
242 419
243 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId); 420 AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID);
244 acd.Appearance = new AvatarAppearance(); 421 acd.Appearance = new AvatarAppearance();
245 acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID); 422 acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID);
246 ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd); 423 ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd);
@@ -259,17 +436,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
259 TestHelpers.InMethod(); 436 TestHelpers.InMethod();
260// log4net.Config.XmlConfigurator.Configure(); 437// log4net.Config.XmlConfigurator.Configure();
261 438
262 UUID userId = TestHelpers.ParseTail(0x1); 439 Scene scene = CreateTestScene();
263 UUID attItemId = TestHelpers.ParseTail(0x2); 440 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
264 UUID attAssetId = TestHelpers.ParseTail(0x3); 441 InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
265 string attName = "att";
266 442
267 UserAccountHelpers.CreateUserWithInventory(scene, userId); 443 AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID);
268 InventoryItemBase attItem
269 = UserInventoryHelpers.CreateInventoryItem(
270 scene, attName, attItemId, attAssetId, userId, InventoryType.Object);
271
272 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
273 acd.Appearance = new AvatarAppearance(); 444 acd.Appearance = new AvatarAppearance();
274 acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID); 445 acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID);
275 ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd); 446 ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd);
@@ -279,7 +450,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
279 450
280 Assert.That(attachments.Count, Is.EqualTo(1)); 451 Assert.That(attachments.Count, Is.EqualTo(1));
281 SceneObjectGroup attSo = attachments[0]; 452 SceneObjectGroup attSo = attachments[0];
282 Assert.That(attSo.Name, Is.EqualTo(attName)); 453 Assert.That(attSo.Name, Is.EqualTo(attItem.Name));
283 Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest)); 454 Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest));
284 Assert.That(attSo.IsAttachment); 455 Assert.That(attSo.IsAttachment);
285 Assert.That(attSo.UsesPhysics, Is.False); 456 Assert.That(attSo.UsesPhysics, Is.False);
@@ -289,9 +460,125 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
289 List<AvatarAttachment> retreivedAttachments = presence.Appearance.GetAttachments(); 460 List<AvatarAttachment> retreivedAttachments = presence.Appearance.GetAttachments();
290 Assert.That(retreivedAttachments.Count, Is.EqualTo(1)); 461 Assert.That(retreivedAttachments.Count, Is.EqualTo(1));
291 Assert.That(retreivedAttachments[0].AttachPoint, Is.EqualTo((int)AttachmentPoint.Chest)); 462 Assert.That(retreivedAttachments[0].AttachPoint, Is.EqualTo((int)AttachmentPoint.Chest));
292 Assert.That(retreivedAttachments[0].ItemID, Is.EqualTo(attItemId)); 463 Assert.That(retreivedAttachments[0].ItemID, Is.EqualTo(attItem.ID));
293 Assert.That(retreivedAttachments[0].AssetID, Is.EqualTo(attAssetId)); 464 Assert.That(retreivedAttachments[0].AssetID, Is.EqualTo(attItem.AssetID));
294 Assert.That(presence.Appearance.GetAttachpoint(attItemId), Is.EqualTo((int)AttachmentPoint.Chest)); 465 Assert.That(presence.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
466
467 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
468 }
469
470 [Test]
471 public void TestUpdateAttachmentPosition()
472 {
473 TestHelpers.InMethod();
474
475 Scene scene = CreateTestScene();
476 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
477 InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
478
479 AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID);
480 acd.Appearance = new AvatarAppearance();
481 acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID);
482 ScenePresence sp = SceneHelpers.AddScenePresence(scene, acd);
483
484 SceneObjectGroup attSo = sp.GetAttachments()[0];
485
486 Vector3 newPosition = new Vector3(1, 2, 4);
487
488 scene.SceneGraph.UpdatePrimGroupPosition(attSo.LocalId, newPosition, sp.ControllingClient);
489
490 Assert.That(attSo.AbsolutePosition, Is.EqualTo(sp.AbsolutePosition));
491 Assert.That(attSo.RootPart.AttachedPos, Is.EqualTo(newPosition));
492 }
493
494 [Test]
495 public void TestSameSimulatorNeighbouringRegionsTeleport()
496 {
497 TestHelpers.InMethod();
498// TestHelpers.EnableLogging();
499
500 AttachmentsModule attModA = new AttachmentsModule();
501 AttachmentsModule attModB = new AttachmentsModule();
502 EntityTransferModule etmA = new EntityTransferModule();
503 EntityTransferModule etmB = new EntityTransferModule();
504 LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
505
506 IConfigSource config = new IniConfigSource();
507 IConfig modulesConfig = config.AddConfig("Modules");
508 modulesConfig.Set("EntityTransferModule", etmA.Name);
509 modulesConfig.Set("SimulationServices", lscm.Name);
510 IConfig entityTransferConfig = config.AddConfig("EntityTransfer");
511
512 // In order to run a single threaded regression test we do not want the entity transfer module waiting
513 // for a callback from the destination scene before removing its avatar data.
514 entityTransferConfig.Set("wait_for_callback", false);
515
516 modulesConfig.Set("InventoryAccessModule", "BasicInventoryAccessModule");
517
518 SceneHelpers sh = new SceneHelpers();
519 TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
520 TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1001, 1000);
521
522 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
523 SceneHelpers.SetupSceneModules(
524 sceneA, config, new CapabilitiesModule(), etmA, attModA, new BasicInventoryAccessModule());
525 SceneHelpers.SetupSceneModules(
526 sceneB, config, new CapabilitiesModule(), etmB, attModB, new BasicInventoryAccessModule());
527
528 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(sceneA, 0x1);
529 ScenePresence beforeTeleportSp = SceneHelpers.AddScenePresence(sceneA, ua1.PrincipalID, sh.SceneManager);
530 beforeTeleportSp.AbsolutePosition = new Vector3(30, 31, 32);
531
532 InventoryItemBase attItem = CreateAttachmentItem(sceneA, ua1.PrincipalID, "att", 0x10, 0x20);
533
534 sceneA.AttachmentsModule.RezSingleAttachmentFromInventory(
535 beforeTeleportSp, attItem.ID, (uint)AttachmentPoint.Chest);
536
537 Vector3 teleportPosition = new Vector3(10, 11, 12);
538 Vector3 teleportLookAt = new Vector3(20, 21, 22);
539
540 sceneA.RequestTeleportLocation(
541 beforeTeleportSp.ControllingClient,
542 sceneB.RegionInfo.RegionHandle,
543 teleportPosition,
544 teleportLookAt,
545 (uint)TeleportFlags.ViaLocation);
546
547 ((TestClient)beforeTeleportSp.ControllingClient).CompleteTeleportClientSide();
548
549 // Check attachments have made it into sceneB
550 ScenePresence afterTeleportSceneBSp = sceneB.GetScenePresence(ua1.PrincipalID);
551
552 // This is appearance data, as opposed to actually rezzed attachments
553 List<AvatarAttachment> sceneBAttachments = afterTeleportSceneBSp.Appearance.GetAttachments();
554 Assert.That(sceneBAttachments.Count, Is.EqualTo(1));
555 Assert.That(sceneBAttachments[0].AttachPoint, Is.EqualTo((int)AttachmentPoint.Chest));
556 Assert.That(sceneBAttachments[0].ItemID, Is.EqualTo(attItem.ID));
557 Assert.That(sceneBAttachments[0].AssetID, Is.EqualTo(attItem.AssetID));
558 Assert.That(afterTeleportSceneBSp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
559
560 // This is the actual attachment
561 List<SceneObjectGroup> actualSceneBAttachments = afterTeleportSceneBSp.GetAttachments();
562 Assert.That(actualSceneBAttachments.Count, Is.EqualTo(1));
563 SceneObjectGroup actualSceneBAtt = actualSceneBAttachments[0];
564 Assert.That(actualSceneBAtt.Name, Is.EqualTo(attItem.Name));
565 Assert.That(actualSceneBAtt.AttachmentPoint, Is.EqualTo((uint)AttachmentPoint.Chest));
566
567 Assert.That(sceneB.GetSceneObjectGroups().Count, Is.EqualTo(1));
568
569 // Check attachments have been removed from sceneA
570 ScenePresence afterTeleportSceneASp = sceneA.GetScenePresence(ua1.PrincipalID);
571
572 // Since this is appearance data, it is still present on the child avatar!
573 List<AvatarAttachment> sceneAAttachments = afterTeleportSceneASp.Appearance.GetAttachments();
574 Assert.That(sceneAAttachments.Count, Is.EqualTo(1));
575 Assert.That(afterTeleportSceneASp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
576
577 // This is the actual attachment, which should no longer exist
578 List<SceneObjectGroup> actualSceneAAttachments = afterTeleportSceneASp.GetAttachments();
579 Assert.That(actualSceneAAttachments.Count, Is.EqualTo(0));
580
581 Assert.That(sceneA.GetSceneObjectGroups().Count, Is.EqualTo(0));
295 } 582 }
296 583
297 // I'm commenting this test because scene setup NEEDS InventoryService to 584 // I'm commenting this test because scene setup NEEDS InventoryService to
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index 2bebd30..89cc4f6 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -128,7 +128,9 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
128 /// <param name="visualParam"></param> 128 /// <param name="visualParam"></param>
129 public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams) 129 public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams)
130 { 130 {
131 // m_log.InfoFormat("[AVFACTORY]: start SetAppearance for {0}", client.AgentId); 131// m_log.DebugFormat(
132// "[AVFACTORY]: start SetAppearance for {0}, te {1}, visualParams {2}",
133// sp.Name, textureEntry, visualParams);
132 134
133 // TODO: This is probably not necessary any longer, just assume the 135 // TODO: This is probably not necessary any longer, just assume the
134 // textureEntry set implies that the appearance transaction is complete 136 // textureEntry set implies that the appearance transaction is complete
@@ -158,7 +160,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
158 // Process the baked texture array 160 // Process the baked texture array
159 if (textureEntry != null) 161 if (textureEntry != null)
160 { 162 {
161 m_log.InfoFormat("[AVFACTORY]: Received texture update for {0} {1}", sp.Name, sp.UUID); 163// m_log.DebugFormat("[AVFACTORY]: Received texture update for {0} {1}", sp.Name, sp.UUID);
162 164
163// WriteBakedTexturesReport(sp, m_log.DebugFormat); 165// WriteBakedTexturesReport(sp, m_log.DebugFormat);
164 166
@@ -208,7 +210,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
208 ScenePresence sp = m_scene.GetScenePresence(agentId); 210 ScenePresence sp = m_scene.GetScenePresence(agentId);
209 if (sp == null) 211 if (sp == null)
210 { 212 {
211 m_log.WarnFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentId); 213 // This is expected if the user has gone away.
214// m_log.DebugFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentId);
212 return false; 215 return false;
213 } 216 }
214 217
@@ -248,10 +251,10 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
248 251
249 if (bakedTextureFace == null) 252 if (bakedTextureFace == null)
250 { 253 {
251 m_log.WarnFormat( 254 // This can happen legitimately, since some baked textures might not exist
252 "[AV FACTORY]: No texture ID set for {0} for {1} in {2} not found when trying to save permanently", 255 //m_log.WarnFormat(
253 bakeType, sp.Name, m_scene.RegionInfo.RegionName); 256 // "[AV FACTORY]: No texture ID set for {0} for {1} in {2} not found when trying to save permanently",
254 257 // bakeType, sp.Name, m_scene.RegionInfo.RegionName);
255 continue; 258 continue;
256 } 259 }
257 260
@@ -337,7 +340,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
337 return false; 340 return false;
338 } 341 }
339 342
340 m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0} {1}", sp.Name, sp.UUID); 343// m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0} {1}", sp.Name, sp.UUID);
341 344
342 // If we only found default textures, then the appearance is not cached 345 // If we only found default textures, then the appearance is not cached
343 return (defonly ? false : true); 346 return (defonly ? false : true);
@@ -370,11 +373,21 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
370 if (missingTexturesOnly) 373 if (missingTexturesOnly)
371 { 374 {
372 if (m_scene.AssetService.Get(face.TextureID.ToString()) != null) 375 if (m_scene.AssetService.Get(face.TextureID.ToString()) != null)
376 {
373 continue; 377 continue;
378 }
374 else 379 else
380 {
381 // On inter-simulator teleports, this occurs if baked textures are not being stored by the
382 // grid asset service (which means that they are not available to the new region and so have
383 // to be re-requested from the client).
384 //
385 // The only available core OpenSimulator behaviour right now
386 // is not to store these textures, temporarily or otherwise.
375 m_log.DebugFormat( 387 m_log.DebugFormat(
376 "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.", 388 "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.",
377 face.TextureID, idx, sp.Name); 389 face.TextureID, idx, sp.Name);
390 }
378 } 391 }
379 else 392 else
380 { 393 {
@@ -417,7 +430,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
417// acd.AgentID, i, acd.Appearance.Texture.FaceTextures[i]); 430// acd.AgentID, i, acd.Appearance.Texture.FaceTextures[i]);
418 431
419 int ftIndex = (int)AppearanceManager.BakeTypeToAgentTextureIndex(bakeType); 432 int ftIndex = (int)AppearanceManager.BakeTypeToAgentTextureIndex(bakeType);
420 bakedTextures[bakeType] = faceTextures[ftIndex]; 433 Primitive.TextureEntryFace texture = faceTextures[ftIndex]; // this will be null if there's no such baked texture
434 bakedTextures[bakeType] = texture;
421 } 435 }
422 436
423 return bakedTextures; 437 return bakedTextures;
@@ -482,7 +496,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
482 ScenePresence sp = m_scene.GetScenePresence(agentid); 496 ScenePresence sp = m_scene.GetScenePresence(agentid);
483 if (sp == null) 497 if (sp == null)
484 { 498 {
485 m_log.WarnFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentid); 499 // This is expected if the user has gone away.
500// m_log.DebugFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentid);
486 return; 501 return;
487 } 502 }
488 503
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
index 11a0a86..848b3bf 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
@@ -53,7 +53,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
53 UUID userId = TestHelpers.ParseTail(0x1); 53 UUID userId = TestHelpers.ParseTail(0x1);
54 54
55 AvatarFactoryModule afm = new AvatarFactoryModule(); 55 AvatarFactoryModule afm = new AvatarFactoryModule();
56 TestScene scene = SceneHelpers.SetupScene(); 56 TestScene scene = new SceneHelpers().SetupScene();
57 SceneHelpers.SetupSceneModules(scene, afm); 57 SceneHelpers.SetupSceneModules(scene, afm);
58 ScenePresence sp = SceneHelpers.AddScenePresence(scene, userId); 58 ScenePresence sp = SceneHelpers.AddScenePresence(scene, userId);
59 59
@@ -81,7 +81,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
81 CoreAssetCache assetCache = new CoreAssetCache(); 81 CoreAssetCache assetCache = new CoreAssetCache();
82 82
83 AvatarFactoryModule afm = new AvatarFactoryModule(); 83 AvatarFactoryModule afm = new AvatarFactoryModule();
84 TestScene scene = SceneHelpers.SetupScene(assetCache); 84 TestScene scene = new SceneHelpers(assetCache).SetupScene();
85 SceneHelpers.SetupSceneModules(scene, afm); 85 SceneHelpers.SetupSceneModules(scene, afm);
86 ScenePresence sp = SceneHelpers.AddScenePresence(scene, userId); 86 ScenePresence sp = SceneHelpers.AddScenePresence(scene, userId);
87 87
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
index 6215526..dbbb0ae 100644
--- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
@@ -266,7 +266,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
266 receiverIDs.Add(presence.UUID); 266 receiverIDs.Add(presence.UUID);
267 } 267 }
268 } 268 }
269
270 } 269 }
271 ); 270 );
272 } 271 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs b/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs
index 0babeb5..3a91465 100644
--- a/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs
@@ -96,6 +96,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule
96 ScenePresence killingAvatar = null; 96 ScenePresence killingAvatar = null;
97// string killingAvatarMessage; 97// string killingAvatarMessage;
98 98
99 // check to see if it is an NPC and just remove it
100 INPCModule NPCmodule = deadAvatar.Scene.RequestModuleInterface<INPCModule>();
101 if (NPCmodule != null && NPCmodule.DeleteNPC(deadAvatar.UUID, deadAvatar.Scene))
102 {
103 return;
104 }
105
99 if (killerObjectLocalID == 0) 106 if (killerObjectLocalID == 0)
100 deadAvatarMessage = "You committed suicide!"; 107 deadAvatarMessage = "You committed suicide!";
101 else 108 else
@@ -145,7 +152,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule
145 catch (InvalidOperationException) 152 catch (InvalidOperationException)
146 { } 153 { }
147 154
148 deadAvatar.Health = 100; 155 deadAvatar.setHealthWithUpdate(100.0f);
149 deadAvatar.Scene.TeleportClientHome(deadAvatar.UUID, deadAvatar.ControllingClient); 156 deadAvatar.Scene.TeleportClientHome(deadAvatar.UUID, deadAvatar.ControllingClient);
150 } 157 }
151 158
@@ -154,14 +161,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule
154 try 161 try
155 { 162 {
156 ILandObject obj = avatar.Scene.LandChannel.GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); 163 ILandObject obj = avatar.Scene.LandChannel.GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
157 164 if ((obj.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0
158 if ((obj.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0) 165 || avatar.Scene.RegionInfo.RegionSettings.AllowDamage)
159 { 166 {
160 avatar.Invulnerable = false; 167 avatar.Invulnerable = false;
161 } 168 }
162 else 169 else
163 { 170 {
164 avatar.Invulnerable = true; 171 avatar.Invulnerable = true;
172 if (avatar.Health < 100.0f)
173 {
174 avatar.setHealthWithUpdate(100.0f);
175 }
165 } 176 }
166 } 177 }
167 catch (Exception) 178 catch (Exception)
diff --git a/OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs b/OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs
new file mode 100644
index 0000000..4bcd2ac
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs
@@ -0,0 +1,189 @@
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.Text;
32using System.Text.RegularExpressions;
33using log4net;
34using Mono.Addins;
35using NDesk.Options;
36using Nini.Config;
37using OpenMetaverse;
38using OpenSim.Framework;
39using OpenSim.Framework.Console;
40using OpenSim.Framework.Statistics;
41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes;
43
44namespace OpenSim.Region.CoreModules.Avatars.Commands
45{
46 /// <summary>
47 /// A module that holds commands for manipulating objects in the scene.
48 /// </summary>
49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserCommandsModule")]
50 public class UserCommandsModule : ISharedRegionModule
51 {
52// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
54 public const string TeleportUserCommandSyntax = "teleport user <first-name> <last-name> <destination>";
55
56 public static Regex InterRegionDestinationRegex
57 = new Regex(@"^(?<regionName>.+)/(?<x>\d+)/(?<y>\d+)/(?<z>\d+)$", RegexOptions.Compiled);
58
59 public static Regex WithinRegionDestinationRegex
60 = new Regex(@"^(?<x>\d+)/(?<y>\d+)/(?<z>\d+)$", RegexOptions.Compiled);
61
62 private Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>();
63
64 public string Name { get { return "User Commands Module"; } }
65
66 public Type ReplaceableInterface { get { return null; } }
67
68 public void Initialise(IConfigSource source)
69 {
70// m_log.DebugFormat("[USER COMMANDS MODULE]: INITIALIZED MODULE");
71 }
72
73 public void PostInitialise()
74 {
75// m_log.DebugFormat("[USER COMMANDS MODULE]: POST INITIALIZED MODULE");
76 }
77
78 public void Close()
79 {
80// m_log.DebugFormat("[USER COMMANDS MODULE]: CLOSED MODULE");
81 }
82
83 public void AddRegion(Scene scene)
84 {
85// m_log.DebugFormat("[USER COMMANDS MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName);
86
87 lock (m_scenes)
88 m_scenes[scene.RegionInfo.RegionID] = scene;
89
90 scene.AddCommand(
91 "Users",
92 this,
93 "teleport user",
94 TeleportUserCommandSyntax,
95 "Teleport a user in this simulator to the given destination",
96 "<destination> is in format [<region-name>]/<x>/<y>/<z>, e.g. regionone/20/30/40 or just 20/30/40 to teleport within same region."
97 + "\nIf the region contains a space then the whole destination must be in quotes, e.g. \"region one/20/30/40\"",
98 HandleTeleportUser);
99 }
100
101 public void RemoveRegion(Scene scene)
102 {
103// m_log.DebugFormat("[USER COMMANDS MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName);
104
105 lock (m_scenes)
106 m_scenes.Remove(scene.RegionInfo.RegionID);
107 }
108
109 public void RegionLoaded(Scene scene)
110 {
111// m_log.DebugFormat("[USER COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName);
112 }
113
114 private ScenePresence GetUser(string firstName, string lastName)
115 {
116 ScenePresence userFound = null;
117
118 lock (m_scenes)
119 {
120 foreach (Scene scene in m_scenes.Values)
121 {
122 ScenePresence user = scene.GetScenePresence(firstName, lastName);
123 if (user != null && !user.IsChildAgent)
124 {
125 userFound = user;
126 break;
127 }
128 }
129 }
130
131 return userFound;
132 }
133
134 private void HandleTeleportUser(string module, string[] cmd)
135 {
136 if (cmd.Length < 5)
137 {
138 MainConsole.Instance.OutputFormat("Usage: " + TeleportUserCommandSyntax);
139 return;
140 }
141
142 string firstName = cmd[2];
143 string lastName = cmd[3];
144 string rawDestination = cmd[4];
145
146 ScenePresence user = GetUser(firstName, lastName);
147
148 if (user == null)
149 {
150 MainConsole.Instance.OutputFormat("No user found with name {0} {1}", firstName, lastName);
151 return;
152 }
153
154// MainConsole.Instance.OutputFormat("rawDestination [{0}]", rawDestination);
155
156 Match m = WithinRegionDestinationRegex.Match(rawDestination);
157
158 if (!m.Success)
159 {
160 m = InterRegionDestinationRegex.Match(rawDestination);
161
162 if (!m.Success)
163 {
164 MainConsole.Instance.OutputFormat("Invalid destination {0}", rawDestination);
165 return;
166 }
167 }
168
169 string regionName
170 = m.Groups["regionName"].Success ? m.Groups["regionName"].Value : user.Scene.RegionInfo.RegionName;
171
172 MainConsole.Instance.OutputFormat(
173 "Teleporting {0} to {1},{2},{3} in {4}",
174 user.Name,
175 m.Groups["x"], m.Groups["y"], m.Groups["z"],
176 regionName);
177
178 user.Scene.RequestTeleportLocation(
179 user.ControllingClient,
180 regionName,
181 new Vector3(
182 float.Parse(m.Groups["x"].Value),
183 float.Parse(m.Groups["y"].Value),
184 float.Parse(m.Groups["z"].Value)),
185 user.Lookat,
186 (uint)TeleportFlags.ViaLocation);
187 }
188 }
189} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index f64c161..24ec435 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -162,7 +162,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
162 } 162 }
163 } 163 }
164 164
165 protected void InitModule(IConfigSource config) 165 protected virtual void InitModule(IConfigSource config)
166 { 166 {
167 IConfig friendsConfig = config.Configs["Friends"]; 167 IConfig friendsConfig = config.Configs["Friends"];
168 if (friendsConfig != null) 168 if (friendsConfig != null)
@@ -449,29 +449,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
449 /// </summary> 449 /// </summary>
450 public IClientAPI LocateClientObject(UUID agentID) 450 public IClientAPI LocateClientObject(UUID agentID)
451 { 451 {
452 Scene scene = GetClientScene(agentID);
453 if (scene != null)
454 {
455 ScenePresence presence = scene.GetScenePresence(agentID);
456 if (presence != null)
457 return presence.ControllingClient;
458 }
459
460 return null;
461 }
462
463 /// <summary>
464 /// Find the scene for an agent
465 /// </summary>
466 private Scene GetClientScene(UUID agentId)
467 {
468 lock (m_Scenes) 452 lock (m_Scenes)
469 { 453 {
470 foreach (Scene scene in m_Scenes) 454 foreach (Scene scene in m_Scenes)
471 { 455 {
472 ScenePresence presence = scene.GetScenePresence(agentId); 456 ScenePresence presence = scene.GetScenePresence(agentID);
473 if (presence != null && !presence.IsChildAgent) 457 if (presence != null && !presence.IsChildAgent)
474 return scene; 458 return presence.ControllingClient;
475 } 459 }
476 } 460 }
477 461
@@ -498,7 +482,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
498 Util.FireAndForget( 482 Util.FireAndForget(
499 delegate 483 delegate
500 { 484 {
501 m_log.DebugFormat("[FRIENDS MODULE]: Notifying {0} friends", friendList.Count); 485 m_log.DebugFormat(
486 "[FRIENDS MODULE]: Notifying {0} friends of {1} of online status {2}",
487 friendList.Count, agentID, online);
488
502 // Notify about this user status 489 // Notify about this user status
503 StatusNotify(friendList, agentID, online); 490 StatusNotify(friendList, agentID, online);
504 } 491 }
@@ -515,7 +502,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
515 { 502 {
516 // Try local 503 // Try local
517 if (LocalStatusNotification(userID, friendID, online)) 504 if (LocalStatusNotification(userID, friendID, online))
518 return; 505 continue;
519 506
520 // The friend is not here [as root]. Let's forward. 507 // The friend is not here [as root]. Let's forward.
521 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); 508 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() });
@@ -523,11 +510,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
523 { 510 {
524 PresenceInfo friendSession = null; 511 PresenceInfo friendSession = null;
525 foreach (PresenceInfo pinfo in friendSessions) 512 foreach (PresenceInfo pinfo in friendSessions)
513 {
526 if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad 514 if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad
527 { 515 {
528 friendSession = pinfo; 516 friendSession = pinfo;
529 break; 517 break;
530 } 518 }
519 }
531 520
532 if (friendSession != null) 521 if (friendSession != null)
533 { 522 {
@@ -546,7 +535,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
546 } 535 }
547 } 536 }
548 537
549 private void OnInstantMessage(IClientAPI client, GridInstantMessage im) 538 protected virtual void OnInstantMessage(IClientAPI client, GridInstantMessage im)
550 { 539 {
551 if ((InstantMessageDialog)im.dialog == InstantMessageDialog.FriendshipOffered) 540 if ((InstantMessageDialog)im.dialog == InstantMessageDialog.FriendshipOffered)
552 { 541 {
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
index 9a6d277..06f27e2 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
@@ -50,6 +50,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
50 { 50 {
51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52 52
53 private int m_levelHGFriends = 0;
54
53 IUserManagement m_uMan; 55 IUserManagement m_uMan;
54 public IUserManagement UserManagementModule 56 public IUserManagement UserManagementModule
55 { 57 {
@@ -87,6 +89,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
87 m_StatusNotifier = new HGStatusNotifier(this); 89 m_StatusNotifier = new HGStatusNotifier(this);
88 } 90 }
89 91
92 protected override void InitModule(IConfigSource config)
93 {
94 base.InitModule(config);
95
96 // Additionally to the base method
97 IConfig friendsConfig = config.Configs["HGFriendsModule"];
98 if (friendsConfig != null)
99 {
100 m_levelHGFriends = friendsConfig.GetInt("LevelHGFriends", 0);
101
102 // TODO: read in all config variables pertaining to
103 // HG friendship permissions
104 }
105 }
106
90 #endregion 107 #endregion
91 108
92 #region IFriendsSimConnector 109 #region IFriendsSimConnector
@@ -105,6 +122,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
105 122
106 #endregion 123 #endregion
107 124
125 protected override void OnInstantMessage(IClientAPI client, GridInstantMessage im)
126 {
127 if ((InstantMessageDialog)im.dialog == InstantMessageDialog.FriendshipOffered)
128 {
129 // we got a friendship offer
130 UUID principalID = new UUID(im.fromAgentID);
131 UUID friendID = new UUID(im.toAgentID);
132
133 // Check if friendID is foreigner and if principalID has the permission
134 // to request friendships with foreigners. If not, return immediately.
135 if (!UserManagementModule.IsLocalGridUser(friendID))
136 {
137 ScenePresence avatar = null;
138 ((Scene)client.Scene).TryGetScenePresence(principalID, out avatar);
139
140 if (avatar == null)
141 return;
142
143 if (avatar.UserLevel < m_levelHGFriends)
144 {
145 client.SendAgentAlertMessage("Unable to send friendship invitation to foreigner. Insufficient permissions.", false);
146 return;
147 }
148 }
149 }
150
151 base.OnInstantMessage(client, im);
152 }
153
108 protected override void OnApproveFriendRequest(IClientAPI client, UUID friendID, List<UUID> callingCardFolders) 154 protected override void OnApproveFriendRequest(IClientAPI client, UUID friendID, List<UUID> callingCardFolders)
109 { 155 {
110 // Update the local cache. Yes, we need to do it right here 156 // Update the local cache. Yes, we need to do it right here
@@ -369,12 +415,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
369 415
370 protected override void StoreBackwards(UUID friendID, UUID agentID) 416 protected override void StoreBackwards(UUID friendID, UUID agentID)
371 { 417 {
372 Boolean agentIsLocal = true; 418 bool agentIsLocal = true;
373 Boolean friendIsLocal = true; 419// bool friendIsLocal = true;
420
374 if (UserManagementModule != null) 421 if (UserManagementModule != null)
375 { 422 {
376 agentIsLocal = UserManagementModule.IsLocalGridUser(agentID); 423 agentIsLocal = UserManagementModule.IsLocalGridUser(agentID);
377 friendIsLocal = UserManagementModule.IsLocalGridUser(friendID); 424// friendIsLocal = UserManagementModule.IsLocalGridUser(friendID);
378 } 425 }
379 426
380 // Is the requester a local user? 427 // Is the requester a local user?
@@ -461,7 +508,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
461 { 508 {
462 friendUUI = finfo.Friend; 509 friendUUI = finfo.Friend;
463 theFriendUUID = friendUUI; 510 theFriendUUID = friendUUI;
464 UUID utmp = UUID.Zero; String url = String.Empty; String first = String.Empty, last = String.Empty, tmp = String.Empty; 511 UUID utmp = UUID.Zero;
512 string url = String.Empty;
513 string first = String.Empty;
514 string last = String.Empty;
515
465 // If it's confirming the friendship, we already have the full UUI with the secret 516 // If it's confirming the friendship, we already have the full UUI with the secret
466 if (Util.ParseUniversalUserIdentifier(theFriendUUID, out utmp, out url, out first, out last, out secret)) 517 if (Util.ParseUniversalUserIdentifier(theFriendUUID, out utmp, out url, out first, out last, out secret))
467 { 518 {
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs
index 45b4264..7a197f7 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs
@@ -78,7 +78,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends.Tests
78 config.AddConfig("FriendsService"); 78 config.AddConfig("FriendsService");
79 config.Configs["FriendsService"].Set("StorageProvider", "OpenSim.Data.Null.dll"); 79 config.Configs["FriendsService"].Set("StorageProvider", "OpenSim.Data.Null.dll");
80 80
81 m_scene = SceneHelpers.SetupScene(); 81 m_scene = new SceneHelpers().SetupScene();
82 m_fm = new FriendsModule(); 82 m_fm = new FriendsModule();
83 SceneHelpers.SetupSceneModules(m_scene, config, m_fm); 83 SceneHelpers.SetupSceneModules(m_scene, config, m_fm);
84 } 84 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
index 8560c73..6587ead 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
@@ -39,6 +39,9 @@ using OpenSim.Framework.Serialization.External;
39using OpenSim.Region.CoreModules.World.Archiver; 39using OpenSim.Region.CoreModules.World.Archiver;
40using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
41using OpenSim.Services.Interfaces; 41using OpenSim.Services.Interfaces;
42using Ionic.Zlib;
43using GZipStream = Ionic.Zlib.GZipStream;
44using CompressionMode = Ionic.Zlib.CompressionMode;
42 45
43namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver 46namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
44{ 47{
@@ -91,7 +94,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
91 /// Constructor 94 /// Constructor
92 /// </summary> 95 /// </summary>
93 public InventoryArchiveWriteRequest( 96 public InventoryArchiveWriteRequest(
94 Guid id, InventoryArchiverModule module, Scene scene, 97 Guid id, InventoryArchiverModule module, Scene scene,
95 UserAccount userInfo, string invPath, string savePath) 98 UserAccount userInfo, string invPath, string savePath)
96 : this( 99 : this(
97 id, 100 id,
@@ -99,7 +102,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
99 scene, 102 scene,
100 userInfo, 103 userInfo,
101 invPath, 104 invPath,
102 new GZipStream(new FileStream(savePath, FileMode.Create), CompressionMode.Compress)) 105 new GZipStream(new FileStream(savePath, FileMode.Create), CompressionMode.Compress, CompressionLevel.BestCompression))
103 { 106 {
104 } 107 }
105 108
@@ -107,7 +110,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
107 /// Constructor 110 /// Constructor
108 /// </summary> 111 /// </summary>
109 public InventoryArchiveWriteRequest( 112 public InventoryArchiveWriteRequest(
110 Guid id, InventoryArchiverModule module, Scene scene, 113 Guid id, InventoryArchiverModule module, Scene scene,
111 UserAccount userInfo, string invPath, Stream saveStream) 114 UserAccount userInfo, string invPath, Stream saveStream)
112 { 115 {
113 m_id = id; 116 m_id = id;
@@ -125,7 +128,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
125 { 128 {
126 Exception reportedException = null; 129 Exception reportedException = null;
127 bool succeeded = true; 130 bool succeeded = true;
128 131
129 try 132 try
130 { 133 {
131 m_archiveWriter.Close(); 134 m_archiveWriter.Close();
@@ -146,6 +149,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
146 149
147 protected void SaveInvItem(InventoryItemBase inventoryItem, string path, Dictionary<string, object> options, IUserAccountService userAccountService) 150 protected void SaveInvItem(InventoryItemBase inventoryItem, string path, Dictionary<string, object> options, IUserAccountService userAccountService)
148 { 151 {
152 if (options.ContainsKey("exclude"))
153 {
154 if (((List<String>)options["exclude"]).Contains(inventoryItem.Name) ||
155 ((List<String>)options["exclude"]).Contains(inventoryItem.ID.ToString()))
156 {
157 if (options.ContainsKey("verbose"))
158 {
159 m_log.InfoFormat(
160 "[INVENTORY ARCHIVER]: Skipping inventory item {0} {1} at {2}",
161 inventoryItem.Name, inventoryItem.ID, path);
162 }
163 return;
164 }
165 }
166
149 if (options.ContainsKey("verbose")) 167 if (options.ContainsKey("verbose"))
150 m_log.InfoFormat( 168 m_log.InfoFormat(
151 "[INVENTORY ARCHIVER]: Saving item {0} {1} with asset {2}", 169 "[INVENTORY ARCHIVER]: Saving item {0} {1} with asset {2}",
@@ -175,9 +193,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
175 /// <param name="options"></param> 193 /// <param name="options"></param>
176 /// <param name="userAccountService"></param> 194 /// <param name="userAccountService"></param>
177 protected void SaveInvFolder( 195 protected void SaveInvFolder(
178 InventoryFolderBase inventoryFolder, string path, bool saveThisFolderItself, 196 InventoryFolderBase inventoryFolder, string path, bool saveThisFolderItself,
179 Dictionary<string, object> options, IUserAccountService userAccountService) 197 Dictionary<string, object> options, IUserAccountService userAccountService)
180 { 198 {
199 if (options.ContainsKey("excludefolders"))
200 {
201 if (((List<String>)options["excludefolders"]).Contains(inventoryFolder.Name) ||
202 ((List<String>)options["excludefolders"]).Contains(inventoryFolder.ID.ToString()))
203 {
204 if (options.ContainsKey("verbose"))
205 {
206 m_log.InfoFormat(
207 "[INVENTORY ARCHIVER]: Skipping folder {0} at {1}",
208 inventoryFolder.Name, path);
209 }
210 return;
211 }
212 }
213
214 if (options.ContainsKey("verbose"))
215 m_log.InfoFormat("[INVENTORY ARCHIVER]: Saving folder {0}", inventoryFolder.Name);
216
181 if (saveThisFolderItself) 217 if (saveThisFolderItself)
182 { 218 {
183 path += CreateArchiveFolderName(inventoryFolder); 219 path += CreateArchiveFolderName(inventoryFolder);
@@ -186,7 +222,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
186 m_archiveWriter.WriteDir(path); 222 m_archiveWriter.WriteDir(path);
187 } 223 }
188 224
189 InventoryCollection contents 225 InventoryCollection contents
190 = m_scene.InventoryService.GetFolderContent(inventoryFolder.Owner, inventoryFolder.ID); 226 = m_scene.InventoryService.GetFolderContent(inventoryFolder.Owner, inventoryFolder.ID);
191 227
192 foreach (InventoryFolderBase childFolder in contents.Folders) 228 foreach (InventoryFolderBase childFolder in contents.Folders)
@@ -213,16 +249,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
213 InventoryFolderBase inventoryFolder = null; 249 InventoryFolderBase inventoryFolder = null;
214 InventoryItemBase inventoryItem = null; 250 InventoryItemBase inventoryItem = null;
215 InventoryFolderBase rootFolder = m_scene.InventoryService.GetRootFolder(m_userInfo.PrincipalID); 251 InventoryFolderBase rootFolder = m_scene.InventoryService.GetRootFolder(m_userInfo.PrincipalID);
216 252
217 bool saveFolderContentsOnly = false; 253 bool saveFolderContentsOnly = false;
218 254
219 // Eliminate double slashes and any leading / on the path. 255 // Eliminate double slashes and any leading / on the path.
220 string[] components 256 string[] components
221 = m_invPath.Split( 257 = m_invPath.Split(
222 new string[] { InventoryFolderImpl.PATH_DELIMITER }, StringSplitOptions.RemoveEmptyEntries); 258 new string[] { InventoryFolderImpl.PATH_DELIMITER }, StringSplitOptions.RemoveEmptyEntries);
223 259
224 int maxComponentIndex = components.Length - 1; 260 int maxComponentIndex = components.Length - 1;
225 261
226 // If the path terminates with a STAR then later on we want to archive all nodes in the folder but not the 262 // If the path terminates with a STAR then later on we want to archive all nodes in the folder but not the
227 // folder itself. This may get more sophisicated later on 263 // folder itself. This may get more sophisicated later on
228 if (maxComponentIndex >= 0 && components[maxComponentIndex] == STAR_WILDCARD) 264 if (maxComponentIndex >= 0 && components[maxComponentIndex] == STAR_WILDCARD)
@@ -230,13 +266,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
230 saveFolderContentsOnly = true; 266 saveFolderContentsOnly = true;
231 maxComponentIndex--; 267 maxComponentIndex--;
232 } 268 }
233 269
234 m_invPath = String.Empty; 270 m_invPath = String.Empty;
235 for (int i = 0; i <= maxComponentIndex; i++) 271 for (int i = 0; i <= maxComponentIndex; i++)
236 { 272 {
237 m_invPath += components[i] + InventoryFolderImpl.PATH_DELIMITER; 273 m_invPath += components[i] + InventoryFolderImpl.PATH_DELIMITER;
238 } 274 }
239 275
240 // Annoyingly Split actually returns the original string if the input string consists only of delimiters 276 // Annoyingly Split actually returns the original string if the input string consists only of delimiters
241 // Therefore if we still start with a / after the split, then we need the root folder 277 // Therefore if we still start with a / after the split, then we need the root folder
242 if (m_invPath.Length == 0) 278 if (m_invPath.Length == 0)
@@ -246,25 +282,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
246 else 282 else
247 { 283 {
248 m_invPath = m_invPath.Remove(m_invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER)); 284 m_invPath = m_invPath.Remove(m_invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER));
249 List<InventoryFolderBase> candidateFolders 285 List<InventoryFolderBase> candidateFolders
250 = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, rootFolder, m_invPath); 286 = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, rootFolder, m_invPath);
251 if (candidateFolders.Count > 0) 287 if (candidateFolders.Count > 0)
252 inventoryFolder = candidateFolders[0]; 288 inventoryFolder = candidateFolders[0];
253 } 289 }
254 290
255 // The path may point to an item instead 291 // The path may point to an item instead
256 if (inventoryFolder == null) 292 if (inventoryFolder == null)
257 inventoryItem = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, rootFolder, m_invPath); 293 inventoryItem = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, rootFolder, m_invPath);
258 294
259 if (null == inventoryFolder && null == inventoryItem) 295 if (null == inventoryFolder && null == inventoryItem)
260 { 296 {
261 // We couldn't find the path indicated 297 // We couldn't find the path indicated
262 string errorMessage = string.Format("Aborted save. Could not find inventory path {0}", m_invPath); 298 string errorMessage = string.Format("Aborted save. Could not find inventory path {0}", m_invPath);
263 Exception e = new InventoryArchiverException(errorMessage); 299 Exception e = new InventoryArchiverException(errorMessage);
264 m_module.TriggerInventoryArchiveSaved(m_id, false, m_userInfo, m_invPath, m_saveStream, e); 300 m_module.TriggerInventoryArchiveSaved(m_id, false, m_userInfo, m_invPath, m_saveStream, e);
265 throw e; 301 throw e;
266 } 302 }
267 303
268 m_archiveWriter = new TarArchiveWriter(m_saveStream); 304 m_archiveWriter = new TarArchiveWriter(m_saveStream);
269 305
270 m_log.InfoFormat("[INVENTORY ARCHIVER]: Adding control file to archive."); 306 m_log.InfoFormat("[INVENTORY ARCHIVER]: Adding control file to archive.");
@@ -278,10 +314,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
278 { 314 {
279 m_log.DebugFormat( 315 m_log.DebugFormat(
280 "[INVENTORY ARCHIVER]: Found folder {0} {1} at {2}", 316 "[INVENTORY ARCHIVER]: Found folder {0} {1} at {2}",
281 inventoryFolder.Name, 317 inventoryFolder.Name,
282 inventoryFolder.ID, 318 inventoryFolder.ID,
283 m_invPath == String.Empty ? InventoryFolderImpl.PATH_DELIMITER : m_invPath); 319 m_invPath == String.Empty ? InventoryFolderImpl.PATH_DELIMITER : m_invPath);
284 320
285 //recurse through all dirs getting dirs and files 321 //recurse through all dirs getting dirs and files
286 SaveInvFolder(inventoryFolder, ArchiveConstants.INVENTORY_PATH, !saveFolderContentsOnly, options, userAccountService); 322 SaveInvFolder(inventoryFolder, ArchiveConstants.INVENTORY_PATH, !saveFolderContentsOnly, options, userAccountService);
287 } 323 }
@@ -290,10 +326,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
290 m_log.DebugFormat( 326 m_log.DebugFormat(
291 "[INVENTORY ARCHIVER]: Found item {0} {1} at {2}", 327 "[INVENTORY ARCHIVER]: Found item {0} {1} at {2}",
292 inventoryItem.Name, inventoryItem.ID, m_invPath); 328 inventoryItem.Name, inventoryItem.ID, m_invPath);
293 329
294 SaveInvItem(inventoryItem, ArchiveConstants.INVENTORY_PATH, options, userAccountService); 330 SaveInvItem(inventoryItem, ArchiveConstants.INVENTORY_PATH, options, userAccountService);
295 } 331 }
296 332
297 // Don't put all this profile information into the archive right now. 333 // Don't put all this profile information into the archive right now.
298 //SaveUsers(); 334 //SaveUsers();
299 335
@@ -352,7 +388,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
352 /// 388 ///
353 /// These names are prepended with an inventory folder's UUID so that more than one folder can have the 389 /// These names are prepended with an inventory folder's UUID so that more than one folder can have the
354 /// same name 390 /// same name
355 /// 391 ///
356 /// <param name="folder"></param> 392 /// <param name="folder"></param>
357 /// <returns></returns> 393 /// <returns></returns>
358 public static string CreateArchiveFolderName(InventoryFolderBase folder) 394 public static string CreateArchiveFolderName(InventoryFolderBase folder)
@@ -366,7 +402,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
366 /// 402 ///
367 /// These names are prepended with an inventory item's UUID so that more than one item can have the 403 /// These names are prepended with an inventory item's UUID so that more than one item can have the
368 /// same name 404 /// same name
369 /// 405 ///
370 /// <param name="item"></param> 406 /// <param name="item"></param>
371 /// <returns></returns> 407 /// <returns></returns>
372 public static string CreateArchiveItemName(InventoryItemBase item) 408 public static string CreateArchiveItemName(InventoryItemBase item)
@@ -412,7 +448,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
412 public string CreateControlFile(Dictionary<string, object> options) 448 public string CreateControlFile(Dictionary<string, object> options)
413 { 449 {
414 int majorVersion, minorVersion; 450 int majorVersion, minorVersion;
415 451
416 if (options.ContainsKey("home")) 452 if (options.ContainsKey("home"))
417 { 453 {
418 majorVersion = 1; 454 majorVersion = 1;
@@ -422,10 +458,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
422 { 458 {
423 majorVersion = 0; 459 majorVersion = 0;
424 minorVersion = 3; 460 minorVersion = 3;
425 } 461 }
426 462
427 m_log.InfoFormat("[INVENTORY ARCHIVER]: Creating version {0}.{1} IAR", majorVersion, minorVersion); 463 m_log.InfoFormat("[INVENTORY ARCHIVER]: Creating version {0}.{1} IAR", majorVersion, minorVersion);
428 464
429 StringWriter sw = new StringWriter(); 465 StringWriter sw = new StringWriter();
430 XmlTextWriter xtw = new XmlTextWriter(sw); 466 XmlTextWriter xtw = new XmlTextWriter(sw);
431 xtw.Formatting = Formatting.Indented; 467 xtw.Formatting = Formatting.Indented;
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
index ac22c3f..cf87010 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
@@ -47,18 +47,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
47 public class InventoryArchiverModule : IRegionModule, IInventoryArchiverModule 47 public class InventoryArchiverModule : IRegionModule, IInventoryArchiverModule
48 { 48 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 50
51 public string Name { get { return "Inventory Archiver Module"; } } 51 public string Name { get { return "Inventory Archiver Module"; } }
52 52
53 public bool IsSharedModule { get { return true; } } 53 public bool IsSharedModule { get { return true; } }
54 54
55 /// <value> 55 /// <value>
56 /// Enable or disable checking whether the iar user is actually logged in 56 /// Enable or disable checking whether the iar user is actually logged in
57 /// </value> 57 /// </value>
58// public bool DisablePresenceChecks { get; set; } 58// public bool DisablePresenceChecks { get; set; }
59 59
60 public event InventoryArchiveSaved OnInventoryArchiveSaved; 60 public event InventoryArchiveSaved OnInventoryArchiveSaved;
61 61
62 /// <summary> 62 /// <summary>
63 /// The file to load and save inventory if no filename has been specified 63 /// The file to load and save inventory if no filename has been specified
64 /// </summary> 64 /// </summary>
@@ -68,7 +68,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
68 /// Pending save completions initiated from the console 68 /// Pending save completions initiated from the console
69 /// </value> 69 /// </value>
70 protected List<Guid> m_pendingConsoleSaves = new List<Guid>(); 70 protected List<Guid> m_pendingConsoleSaves = new List<Guid>();
71 71
72 /// <value> 72 /// <value>
73 /// All scenes that this module knows about 73 /// All scenes that this module knows about
74 /// </value> 74 /// </value>
@@ -106,7 +106,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
106 { 106 {
107 scene.RegisterModuleInterface<IInventoryArchiverModule>(this); 107 scene.RegisterModuleInterface<IInventoryArchiverModule>(this);
108 OnInventoryArchiveSaved += SaveInvConsoleCommandCompleted; 108 OnInventoryArchiveSaved += SaveInvConsoleCommandCompleted;
109 109
110 scene.AddCommand( 110 scene.AddCommand(
111 "Archiving", this, "load iar", 111 "Archiving", this, "load iar",
112 "load iar [-m|--merge] <first> <last> <inventory path> <password> [<IAR path>]", 112 "load iar [-m|--merge] <first> <last> <inventory path> <password> [<IAR path>]",
@@ -119,11 +119,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
119 + "<IAR path> is the filesystem path or URI from which to load the IAR." 119 + "<IAR path> is the filesystem path or URI from which to load the IAR."
120 + string.Format(" If this is not given then the filename {0} in the current directory is used", DEFAULT_INV_BACKUP_FILENAME), 120 + string.Format(" If this is not given then the filename {0} in the current directory is used", DEFAULT_INV_BACKUP_FILENAME),
121 HandleLoadInvConsoleCommand); 121 HandleLoadInvConsoleCommand);
122 122
123 scene.AddCommand( 123 scene.AddCommand(
124 "Archiving", this, "save iar", 124 "Archiving", this, "save iar",
125 "save iar [-h|--home=<url>] [--noassets] <first> <last> <inventory path> <password> [<IAR path>] [-c|--creators] [-v|--verbose]", 125 "save iar [-h|--home=<url>] [--noassets] <first> <last> <inventory path> <password> [<IAR path>] [-c|--creators] [-e|--exclude=<name/uuid>] [-f|--excludefolder=<foldername/uuid>] [-v|--verbose]",
126 "Save user inventory archive (IAR).", 126 "Save user inventory archive (IAR).",
127 "<first> is the user's first name.\n" 127 "<first> is the user's first name.\n"
128 + "<last> is the user's last name.\n" 128 + "<last> is the user's last name.\n"
129 + "<inventory path> is the path inside the user's inventory for the folder/item to be saved.\n" 129 + "<inventory path> is the path inside the user's inventory for the folder/item to be saved.\n"
@@ -131,32 +131,34 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
131 + string.Format(" If this is not given then the filename {0} in the current directory is used.\n", DEFAULT_INV_BACKUP_FILENAME) 131 + string.Format(" If this is not given then the filename {0} in the current directory is used.\n", DEFAULT_INV_BACKUP_FILENAME)
132 + "-h|--home=<url> adds the url of the profile service to the saved user information.\n" 132 + "-h|--home=<url> adds the url of the profile service to the saved user information.\n"
133 + "-c|--creators preserves information about foreign creators.\n" 133 + "-c|--creators preserves information about foreign creators.\n"
134 + "-e|--exclude=<name/uuid> don't save the inventory item in archive" + Environment.NewLine
135 + "-f|--excludefolder=<folder/uuid> don't save contents of the folder in archive" + Environment.NewLine
134 + "-v|--verbose extra debug messages.\n" 136 + "-v|--verbose extra debug messages.\n"
135 + "--noassets stops assets being saved to the IAR.", 137 + "--noassets stops assets being saved to the IAR.",
136 HandleSaveInvConsoleCommand); 138 HandleSaveInvConsoleCommand);
137 139
138 m_aScene = scene; 140 m_aScene = scene;
139 } 141 }
140 142
141 m_scenes[scene.RegionInfo.RegionID] = scene; 143 m_scenes[scene.RegionInfo.RegionID] = scene;
142 } 144 }
143 145
144 public void PostInitialise() {} 146 public void PostInitialise() {}
145 147
146 public void Close() {} 148 public void Close() {}
147 149
148 /// <summary> 150 /// <summary>
149 /// Trigger the inventory archive saved event. 151 /// Trigger the inventory archive saved event.
150 /// </summary> 152 /// </summary>
151 protected internal void TriggerInventoryArchiveSaved( 153 protected internal void TriggerInventoryArchiveSaved(
152 Guid id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream, 154 Guid id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream,
153 Exception reportedException) 155 Exception reportedException)
154 { 156 {
155 InventoryArchiveSaved handlerInventoryArchiveSaved = OnInventoryArchiveSaved; 157 InventoryArchiveSaved handlerInventoryArchiveSaved = OnInventoryArchiveSaved;
156 if (handlerInventoryArchiveSaved != null) 158 if (handlerInventoryArchiveSaved != null)
157 handlerInventoryArchiveSaved(id, succeeded, userInfo, invPath, saveStream, reportedException); 159 handlerInventoryArchiveSaved(id, succeeded, userInfo, invPath, saveStream, reportedException);
158 } 160 }
159 161
160 public bool ArchiveInventory( 162 public bool ArchiveInventory(
161 Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream) 163 Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream)
162 { 164 {
@@ -164,7 +166,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
164 } 166 }
165 167
166 public bool ArchiveInventory( 168 public bool ArchiveInventory(
167 Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream, 169 Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream,
168 Dictionary<string, object> options) 170 Dictionary<string, object> options)
169 { 171 {
170 if (m_scenes.Count > 0) 172 if (m_scenes.Count > 0)
@@ -188,7 +190,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
188 190
189 return false; 191 return false;
190 } 192 }
191 193
192 return true; 194 return true;
193// } 195// }
194// else 196// else
@@ -202,15 +204,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
202 204
203 return false; 205 return false;
204 } 206 }
205 207
206 public bool ArchiveInventory( 208 public bool ArchiveInventory(
207 Guid id, string firstName, string lastName, string invPath, string pass, string savePath, 209 Guid id, string firstName, string lastName, string invPath, string pass, string savePath,
208 Dictionary<string, object> options) 210 Dictionary<string, object> options)
209 { 211 {
210 if (m_scenes.Count > 0) 212 if (m_scenes.Count > 0)
211 { 213 {
212 UserAccount userInfo = GetUserInfo(firstName, lastName, pass); 214 UserAccount userInfo = GetUserInfo(firstName, lastName, pass);
213 215
214 if (userInfo != null) 216 if (userInfo != null)
215 { 217 {
216// if (CheckPresence(userInfo.PrincipalID)) 218// if (CheckPresence(userInfo.PrincipalID))
@@ -228,7 +230,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
228 230
229 return false; 231 return false;
230 } 232 }
231 233
232 return true; 234 return true;
233// } 235// }
234// else 236// else
@@ -239,7 +241,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
239// } 241// }
240 } 242 }
241 } 243 }
242 244
243 return false; 245 return false;
244 } 246 }
245 247
@@ -247,9 +249,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
247 { 249 {
248 return DearchiveInventory(firstName, lastName, invPath, pass, loadStream, new Dictionary<string, object>()); 250 return DearchiveInventory(firstName, lastName, invPath, pass, loadStream, new Dictionary<string, object>());
249 } 251 }
250 252
251 public bool DearchiveInventory( 253 public bool DearchiveInventory(
252 string firstName, string lastName, string invPath, string pass, Stream loadStream, 254 string firstName, string lastName, string invPath, string pass, Stream loadStream,
253 Dictionary<string, object> options) 255 Dictionary<string, object> options)
254 { 256 {
255 if (m_scenes.Count > 0) 257 if (m_scenes.Count > 0)
@@ -295,22 +297,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
295 297
296 return false; 298 return false;
297 } 299 }
298 300
299 public bool DearchiveInventory( 301 public bool DearchiveInventory(
300 string firstName, string lastName, string invPath, string pass, string loadPath, 302 string firstName, string lastName, string invPath, string pass, string loadPath,
301 Dictionary<string, object> options) 303 Dictionary<string, object> options)
302 { 304 {
303 if (m_scenes.Count > 0) 305 if (m_scenes.Count > 0)
304 { 306 {
305 UserAccount userInfo = GetUserInfo(firstName, lastName, pass); 307 UserAccount userInfo = GetUserInfo(firstName, lastName, pass);
306 308
307 if (userInfo != null) 309 if (userInfo != null)
308 { 310 {
309// if (CheckPresence(userInfo.PrincipalID)) 311// if (CheckPresence(userInfo.PrincipalID))
310// { 312// {
311 InventoryArchiveReadRequest request; 313 InventoryArchiveReadRequest request;
312 bool merge = (options.ContainsKey("merge") ? (bool)options["merge"] : false); 314 bool merge = (options.ContainsKey("merge") ? (bool)options["merge"] : false);
313 315
314 try 316 try
315 { 317 {
316 request = new InventoryArchiveReadRequest(m_aScene, userInfo, invPath, loadPath, merge); 318 request = new InventoryArchiveReadRequest(m_aScene, userInfo, invPath, loadPath, merge);
@@ -324,7 +326,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
324 326
325 return false; 327 return false;
326 } 328 }
327 329
328 UpdateClientWithLoadedNodes(userInfo, request.Execute()); 330 UpdateClientWithLoadedNodes(userInfo, request.Execute());
329 331
330 return true; 332 return true;
@@ -340,7 +342,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
340 342
341 return false; 343 return false;
342 } 344 }
343 345
344 /// <summary> 346 /// <summary>
345 /// Load inventory from an inventory file archive 347 /// Load inventory from an inventory file archive
346 /// </summary> 348 /// </summary>
@@ -351,26 +353,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
351 { 353 {
352 Dictionary<string, object> options = new Dictionary<string, object>(); 354 Dictionary<string, object> options = new Dictionary<string, object>();
353 OptionSet optionSet = new OptionSet().Add("m|merge", delegate (string v) { options["merge"] = v != null; }); 355 OptionSet optionSet = new OptionSet().Add("m|merge", delegate (string v) { options["merge"] = v != null; });
354 356
355 List<string> mainParams = optionSet.Parse(cmdparams); 357 List<string> mainParams = optionSet.Parse(cmdparams);
356 358
357 if (mainParams.Count < 6) 359 if (mainParams.Count < 6)
358 { 360 {
359 m_log.Error( 361 m_log.Error(
360 "[INVENTORY ARCHIVER]: usage is load iar [-m|--merge] <first name> <last name> <inventory path> <user password> [<load file path>]"); 362 "[INVENTORY ARCHIVER]: usage is load iar [-m|--merge] <first name> <last name> <inventory path> <user password> [<load file path>]");
361 return; 363 return;
362 } 364 }
363 365
364 string firstName = mainParams[2]; 366 string firstName = mainParams[2];
365 string lastName = mainParams[3]; 367 string lastName = mainParams[3];
366 string invPath = mainParams[4]; 368 string invPath = mainParams[4];
367 string pass = mainParams[5]; 369 string pass = mainParams[5];
368 string loadPath = (mainParams.Count > 6 ? mainParams[6] : DEFAULT_INV_BACKUP_FILENAME); 370 string loadPath = (mainParams.Count > 6 ? mainParams[6] : DEFAULT_INV_BACKUP_FILENAME);
369 371
370 m_log.InfoFormat( 372 m_log.InfoFormat(
371 "[INVENTORY ARCHIVER]: Loading archive {0} to inventory path {1} for {2} {3}", 373 "[INVENTORY ARCHIVER]: Loading archive {0} to inventory path {1} for {2} {3}",
372 loadPath, invPath, firstName, lastName); 374 loadPath, invPath, firstName, lastName);
373 375
374 if (DearchiveInventory(firstName, lastName, invPath, pass, loadPath, options)) 376 if (DearchiveInventory(firstName, lastName, invPath, pass, loadPath, options))
375 m_log.InfoFormat( 377 m_log.InfoFormat(
376 "[INVENTORY ARCHIVER]: Loaded archive {0} for {1} {2}", 378 "[INVENTORY ARCHIVER]: Loaded archive {0} for {1} {2}",
@@ -381,7 +383,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
381 m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", e.Message); 383 m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", e.Message);
382 } 384 }
383 } 385 }
384 386
385 /// <summary> 387 /// <summary>
386 /// Save inventory to a file archive 388 /// Save inventory to a file archive
387 /// </summary> 389 /// </summary>
@@ -398,6 +400,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
398 ops.Add("v|verbose", delegate(string v) { options["verbose"] = v; }); 400 ops.Add("v|verbose", delegate(string v) { options["verbose"] = v; });
399 ops.Add("c|creators", delegate(string v) { options["creators"] = v; }); 401 ops.Add("c|creators", delegate(string v) { options["creators"] = v; });
400 ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; }); 402 ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; });
403 ops.Add("e|exclude=", delegate(string v)
404 {
405 if (!options.ContainsKey("exclude"))
406 options["exclude"] = new List<String>();
407 ((List<String>)options["exclude"]).Add(v);
408 });
409 ops.Add("f|excludefolder=", delegate(string v)
410 {
411 if (!options.ContainsKey("excludefolders"))
412 options["excludefolders"] = new List<String>();
413 ((List<String>)options["excludefolders"]).Add(v);
414 });
401 415
402 List<string> mainParams = ops.Parse(cmdparams); 416 List<string> mainParams = ops.Parse(cmdparams);
403 417
@@ -406,10 +420,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
406 if (mainParams.Count < 6) 420 if (mainParams.Count < 6)
407 { 421 {
408 m_log.Error( 422 m_log.Error(
409 "[INVENTORY ARCHIVER]: usage is save iar [-h|--home=<url>] [--noassets] <first name> <last name> <inventory path> <user password> [<save file path>] [-c|--creators] [-v|--verbose]"); 423 "[INVENTORY ARCHIVER]: save iar [-h|--home=<url>] [--noassets] <first> <last> <inventory path> <password> [<IAR path>] [-c|--creators] [-e|--exclude=<name/uuid>] [-f|--excludefolder=<foldername/uuid>] [-v|--verbose]");
410 return; 424 return;
411 } 425 }
412 426
413 if (options.ContainsKey("home")) 427 if (options.ContainsKey("home"))
414 m_log.WarnFormat("[INVENTORY ARCHIVER]: Please be aware that inventory archives with creator information are not compatible with OpenSim 0.7.0.2 and earlier. Do not use the -home option if you want to produce a compatible IAR"); 428 m_log.WarnFormat("[INVENTORY ARCHIVER]: Please be aware that inventory archives with creator information are not compatible with OpenSim 0.7.0.2 and earlier. Do not use the -home option if you want to produce a compatible IAR");
415 429
@@ -418,7 +432,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
418 string invPath = mainParams[4]; 432 string invPath = mainParams[4];
419 string pass = mainParams[5]; 433 string pass = mainParams[5];
420 string savePath = (mainParams.Count > 6 ? mainParams[6] : DEFAULT_INV_BACKUP_FILENAME); 434 string savePath = (mainParams.Count > 6 ? mainParams[6] : DEFAULT_INV_BACKUP_FILENAME);
421 435
422 m_log.InfoFormat( 436 m_log.InfoFormat(
423 "[INVENTORY ARCHIVER]: Saving archive {0} using inventory path {1} for {2} {3}", 437 "[INVENTORY ARCHIVER]: Saving archive {0} using inventory path {1} for {2} {3}",
424 savePath, invPath, firstName, lastName); 438 savePath, invPath, firstName, lastName);
@@ -433,9 +447,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
433 m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", e.Message); 447 m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", e.Message);
434 } 448 }
435 } 449 }
436 450
437 private void SaveInvConsoleCommandCompleted( 451 private void SaveInvConsoleCommandCompleted(
438 Guid id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream, 452 Guid id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream,
439 Exception reportedException) 453 Exception reportedException)
440 { 454 {
441 lock (m_pendingConsoleSaves) 455 lock (m_pendingConsoleSaves)
@@ -445,7 +459,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
445 else 459 else
446 return; 460 return;
447 } 461 }
448 462
449 if (succeeded) 463 if (succeeded)
450 { 464 {
451 m_log.InfoFormat("[INVENTORY ARCHIVER]: Saved archive for {0} {1}", userInfo.FirstName, userInfo.LastName); 465 m_log.InfoFormat("[INVENTORY ARCHIVER]: Saved archive for {0} {1}", userInfo.FirstName, userInfo.LastName);
@@ -453,11 +467,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
453 else 467 else
454 { 468 {
455 m_log.ErrorFormat( 469 m_log.ErrorFormat(
456 "[INVENTORY ARCHIVER]: Archive save for {0} {1} failed - {2}", 470 "[INVENTORY ARCHIVER]: Archive save for {0} {1} failed - {2}",
457 userInfo.FirstName, userInfo.LastName, reportedException.Message); 471 userInfo.FirstName, userInfo.LastName, reportedException.Message);
458 } 472 }
459 } 473 }
460 474
461 /// <summary> 475 /// <summary>
462 /// Get user information for the given name. 476 /// Get user information for the given name.
463 /// </summary> 477 /// </summary>
@@ -467,13 +481,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
467 /// <returns></returns> 481 /// <returns></returns>
468 protected UserAccount GetUserInfo(string firstName, string lastName, string pass) 482 protected UserAccount GetUserInfo(string firstName, string lastName, string pass)
469 { 483 {
470 UserAccount account 484 UserAccount account
471 = m_aScene.UserAccountService.GetUserAccount(m_aScene.RegionInfo.ScopeID, firstName, lastName); 485 = m_aScene.UserAccountService.GetUserAccount(m_aScene.RegionInfo.ScopeID, firstName, lastName);
472 486
473 if (null == account) 487 if (null == account)
474 { 488 {
475 m_log.ErrorFormat( 489 m_log.ErrorFormat(
476 "[INVENTORY ARCHIVER]: Failed to find user info for {0} {1}", 490 "[INVENTORY ARCHIVER]: Failed to find user info for {0} {1}",
477 firstName, lastName); 491 firstName, lastName);
478 return null; 492 return null;
479 } 493 }
@@ -488,7 +502,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
488 else 502 else
489 { 503 {
490 m_log.ErrorFormat( 504 m_log.ErrorFormat(
491 "[INVENTORY ARCHIVER]: Password for user {0} {1} incorrect. Please try again.", 505 "[INVENTORY ARCHIVER]: Password for user {0} {1} incorrect. Please try again.",
492 firstName, lastName); 506 firstName, lastName);
493 return null; 507 return null;
494 } 508 }
@@ -499,7 +513,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
499 return null; 513 return null;
500 } 514 }
501 } 515 }
502 516
503 /// <summary> 517 /// <summary>
504 /// Notify the client of loaded nodes if they are logged in 518 /// Notify the client of loaded nodes if they are logged in
505 /// </summary> 519 /// </summary>
@@ -508,22 +522,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
508 { 522 {
509 if (loadedNodes.Count == 0) 523 if (loadedNodes.Count == 0)
510 return; 524 return;
511 525
512 foreach (Scene scene in m_scenes.Values) 526 foreach (Scene scene in m_scenes.Values)
513 { 527 {
514 ScenePresence user = scene.GetScenePresence(userInfo.PrincipalID); 528 ScenePresence user = scene.GetScenePresence(userInfo.PrincipalID);
515 529
516 if (user != null && !user.IsChildAgent) 530 if (user != null && !user.IsChildAgent)
517 { 531 {
518 foreach (InventoryNodeBase node in loadedNodes) 532 foreach (InventoryNodeBase node in loadedNodes)
519 { 533 {
520// m_log.DebugFormat( 534// m_log.DebugFormat(
521// "[INVENTORY ARCHIVER]: Notifying {0} of loaded inventory node {1}", 535// "[INVENTORY ARCHIVER]: Notifying {0} of loaded inventory node {1}",
522// user.Name, node.Name); 536// user.Name, node.Name);
523 537
524 user.ControllingClient.SendBulkUpdateInventory(node); 538 user.ControllingClient.SendBulkUpdateInventory(node);
525 } 539 }
526 540
527 break; 541 break;
528 } 542 }
529 } 543 }
@@ -538,7 +552,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
538// { 552// {
539// if (DisablePresenceChecks) 553// if (DisablePresenceChecks)
540// return true; 554// return true;
541// 555//
542// foreach (Scene scene in m_scenes.Values) 556// foreach (Scene scene in m_scenes.Values)
543// { 557// {
544// ScenePresence p; 558// ScenePresence p;
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs
index 19ef571..1056865 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs
@@ -48,7 +48,7 @@ using OpenSim.Tests.Common.Mock;
48namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests 48namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
49{ 49{
50 [TestFixture] 50 [TestFixture]
51 public class InventoryArchiveTestCase 51 public class InventoryArchiveTestCase : OpenSimTestCase
52 { 52 {
53 protected ManualResetEvent mre = new ManualResetEvent(false); 53 protected ManualResetEvent mre = new ManualResetEvent(false);
54 54
@@ -84,8 +84,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
84 protected string m_coaItemName = "Coalesced Item"; 84 protected string m_coaItemName = "Coalesced Item";
85 85
86 [SetUp] 86 [SetUp]
87 public virtual void SetUp() 87 public override void SetUp()
88 { 88 {
89 base.SetUp();
89 m_iarStream = new MemoryStream(m_iarStreamBytes); 90 m_iarStream = new MemoryStream(m_iarStreamBytes);
90 } 91 }
91 92
@@ -100,7 +101,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
100// log4net.Config.XmlConfigurator.Configure(); 101// log4net.Config.XmlConfigurator.Configure();
101 102
102 InventoryArchiverModule archiverModule = new InventoryArchiverModule(); 103 InventoryArchiverModule archiverModule = new InventoryArchiverModule();
103 Scene scene = SceneHelpers.SetupScene(); 104 Scene scene = new SceneHelpers().SetupScene();
104 SceneHelpers.SetupSceneModules(scene, archiverModule); 105 SceneHelpers.SetupSceneModules(scene, archiverModule);
105 106
106 UserAccountHelpers.CreateUserWithInventory(scene, m_uaLL1, "hampshire"); 107 UserAccountHelpers.CreateUserWithInventory(scene, m_uaLL1, "hampshire");
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
index e409c8e..b112b6d 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
@@ -61,7 +61,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
61 SerialiserModule serialiserModule = new SerialiserModule(); 61 SerialiserModule serialiserModule = new SerialiserModule();
62 m_archiverModule = new InventoryArchiverModule(); 62 m_archiverModule = new InventoryArchiverModule();
63 63
64 m_scene = SceneHelpers.SetupScene(); 64 m_scene = new SceneHelpers().SetupScene();
65 SceneHelpers.SetupSceneModules(m_scene, serialiserModule, m_archiverModule); 65 SceneHelpers.SetupSceneModules(m_scene, serialiserModule, m_archiverModule);
66 } 66 }
67 67
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs
index 417c20c..6eb3605 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs
@@ -62,7 +62,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
62 62
63 InventoryArchiverModule archiverModule = new InventoryArchiverModule(); 63 InventoryArchiverModule archiverModule = new InventoryArchiverModule();
64 64
65 Scene scene = SceneHelpers.SetupScene(); 65 Scene scene = new SceneHelpers().SetupScene();
66 SceneHelpers.SetupSceneModules(scene, archiverModule); 66 SceneHelpers.SetupSceneModules(scene, archiverModule);
67 67
68 // Create user 68 // Create user
@@ -179,7 +179,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
179 InventoryArchiverModule archiverModule = new InventoryArchiverModule(); 179 InventoryArchiverModule archiverModule = new InventoryArchiverModule();
180 180
181 // Annoyingly, we have to set up a scene even though inventory loading has nothing to do with a scene 181 // Annoyingly, we have to set up a scene even though inventory loading has nothing to do with a scene
182 Scene scene = SceneHelpers.SetupScene(); 182 Scene scene = new SceneHelpers().SetupScene();
183 183
184 SceneHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); 184 SceneHelpers.SetupSceneModules(scene, serialiserModule, archiverModule);
185 185
@@ -222,7 +222,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
222 222
223 SerialiserModule serialiserModule = new SerialiserModule(); 223 SerialiserModule serialiserModule = new SerialiserModule();
224 InventoryArchiverModule archiverModule = new InventoryArchiverModule(); 224 InventoryArchiverModule archiverModule = new InventoryArchiverModule();
225 Scene scene = SceneHelpers.SetupScene(); 225 Scene scene = new SceneHelpers().SetupScene();
226 SceneHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); 226 SceneHelpers.SetupSceneModules(scene, serialiserModule, archiverModule);
227 227
228 UserAccountHelpers.CreateUserWithInventory(scene, m_uaMT, "password"); 228 UserAccountHelpers.CreateUserWithInventory(scene, m_uaMT, "password");
@@ -247,7 +247,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
247 247
248 InventoryArchiverModule archiverModule = new InventoryArchiverModule(); 248 InventoryArchiverModule archiverModule = new InventoryArchiverModule();
249 249
250 Scene scene = SceneHelpers.SetupScene(); 250 Scene scene = new SceneHelpers().SetupScene();
251 SceneHelpers.SetupSceneModules(scene, archiverModule); 251 SceneHelpers.SetupSceneModules(scene, archiverModule);
252 252
253 // Create user 253 // Create user
@@ -326,7 +326,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
326 TestHelpers.InMethod(); 326 TestHelpers.InMethod();
327// log4net.Config.XmlConfigurator.Configure(); 327// log4net.Config.XmlConfigurator.Configure();
328 328
329 Scene scene = SceneHelpers.SetupScene(); 329 Scene scene = new SceneHelpers().SetupScene();
330 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene); 330 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene);
331 331
332 Dictionary <string, InventoryFolderBase> foldersCreated = new Dictionary<string, InventoryFolderBase>(); 332 Dictionary <string, InventoryFolderBase> foldersCreated = new Dictionary<string, InventoryFolderBase>();
@@ -393,7 +393,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
393 TestHelpers.InMethod(); 393 TestHelpers.InMethod();
394 //log4net.Config.XmlConfigurator.Configure(); 394 //log4net.Config.XmlConfigurator.Configure();
395 395
396 Scene scene = SceneHelpers.SetupScene(); 396 Scene scene = new SceneHelpers().SetupScene();
397 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene); 397 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene);
398 398
399 string folder1ExistingName = "a"; 399 string folder1ExistingName = "a";
@@ -444,7 +444,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
444 TestHelpers.InMethod(); 444 TestHelpers.InMethod();
445// log4net.Config.XmlConfigurator.Configure(); 445// log4net.Config.XmlConfigurator.Configure();
446 446
447 Scene scene = SceneHelpers.SetupScene(); 447 Scene scene = new SceneHelpers().SetupScene();
448 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene); 448 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene);
449 449
450 string folder1ExistingName = "a"; 450 string folder1ExistingName = "a";
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
index bc5c1ff..92cf9d1 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
@@ -240,13 +240,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
240 { 240 {
241 ScenePresence sp = scene.GetScenePresence(client.AgentId); 241 ScenePresence sp = scene.GetScenePresence(client.AgentId);
242 IEntityTransferModule transferMod = scene.RequestModuleInterface<IEntityTransferModule>(); 242 IEntityTransferModule transferMod = scene.RequestModuleInterface<IEntityTransferModule>();
243 IEventQueue eq = sp.Scene.RequestModuleInterface<IEventQueue>(); 243
244 if (transferMod != null && sp != null && eq != null) 244 if (transferMod != null && sp != null)
245 transferMod.DoTeleport(sp, gatekeeper, finalDestination, im.Position + new Vector3(0.5f, 0.5f, 0f), Vector3.UnitX, teleportflags, eq); 245 transferMod.DoTeleport(
246 sp, gatekeeper, finalDestination, im.Position + new Vector3(0.5f, 0.5f, 0f),
247 Vector3.UnitX, teleportflags);
246 } 248 }
247 } 249 }
248 } 250 }
249 } 251 }
250 } 252 }
251 } 253 }
252} 254} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
index dcfdf8f..a889984 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
@@ -151,6 +151,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
151 Scene scene = (Scene)(client.Scene); 151 Scene scene = (Scene)(client.Scene);
152 ScenePresence presence = scene.GetScenePresence(client.AgentId); 152 ScenePresence presence = scene.GetScenePresence(client.AgentId);
153 153
154 // Round up Z co-ordinate rather than round-down by casting. This stops tall avatars from being given
155 // a teleport Z co-ordinate by short avatars that drops them through or embeds them in thin floors on
156 // arrival.
157 //
158 // Ideally we would give the exact float position adjusting for the relative height of the two avatars
159 // but it looks like a float component isn't possible with a parcel ID.
154 UUID dest = Util.BuildFakeParcelID( 160 UUID dest = Util.BuildFakeParcelID(
155 scene.RegionInfo.RegionHandle, 161 scene.RegionInfo.RegionHandle,
156 (uint)presence.AbsolutePosition.X, 162 (uint)presence.AbsolutePosition.X,
diff --git a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
index 8101ca2..87ca327 100644
--- a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
@@ -57,14 +57,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Profile
57 57
58 public void Initialise(IConfigSource config) 58 public void Initialise(IConfigSource config)
59 { 59 {
60 // This can be reduced later as the loader will determine
61 // whether we are needed
62 if (config.Configs["Profile"] != null)
63 {
64 if (config.Configs["Profile"].GetString("Module", string.Empty) != "BasicProfileModule")
65 return;
66 }
67
68 m_log.DebugFormat("[PROFILE MODULE]: Basic Profile Module enabled"); 60 m_log.DebugFormat("[PROFILE MODULE]: Basic Profile Module enabled");
69 m_Enabled = true; 61 m_Enabled = true;
70 } 62 }
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index 2b790f4..560f807 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -30,7 +30,6 @@ using System.Collections.Generic;
30using System.Net; 30using System.Net;
31using System.Reflection; 31using System.Reflection;
32using System.Threading; 32using System.Threading;
33
34using OpenSim.Framework; 33using OpenSim.Framework;
35using OpenSim.Framework.Capabilities; 34using OpenSim.Framework.Capabilities;
36using OpenSim.Framework.Client; 35using OpenSim.Framework.Client;
@@ -47,29 +46,39 @@ using Nini.Config;
47 46
48namespace OpenSim.Region.CoreModules.Framework.EntityTransfer 47namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
49{ 48{
50 public class EntityTransferModule : ISharedRegionModule, IEntityTransferModule 49 public class EntityTransferModule : INonSharedRegionModule, IEntityTransferModule
51 { 50 {
52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53 52
53 public const int DefaultMaxTransferDistance = 4095;
54 public const bool WaitForAgentArrivedAtDestinationDefault = true;
55
54 /// <summary> 56 /// <summary>
55 /// The maximum distance, in standard region units (256m) that an agent is allowed to transfer. 57 /// The maximum distance, in standard region units (256m) that an agent is allowed to transfer.
56 /// </summary> 58 /// </summary>
57 private int m_MaxTransferDistance = 4095; 59 public int MaxTransferDistance { get; set; }
58 public int MaxTransferDistance
59 {
60 get { return m_MaxTransferDistance; }
61 set { m_MaxTransferDistance = value; }
62 }
63 60
64 private int m_levelHGTeleport = 0; 61 /// <summary>
62 /// If true then on a teleport, the source region waits for a callback from the destination region. If
63 /// a callback fails to arrive within a set time then the user is pulled back into the source region.
64 /// </summary>
65 public bool WaitForAgentArrivedAtDestination { get; set; }
65 66
66 protected bool m_Enabled = false; 67 protected bool m_Enabled = false;
67 protected Scene m_aScene; 68
68 protected List<Scene> m_Scenes = new List<Scene>(); 69 public Scene Scene { get; private set; }
69 protected List<UUID> m_agentsInTransit; 70
71 /// <summary>
72 /// Handles recording and manipulation of state for entities that are in transfer within or between regions
73 /// (cross or teleport).
74 /// </summary>
75 private EntityTransferStateMachine m_entityTransferStateMachine;
76
70 private ExpiringCache<UUID, ExpiringCache<ulong, DateTime>> m_bannedRegions = 77 private ExpiringCache<UUID, ExpiringCache<ulong, DateTime>> m_bannedRegions =
71 new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>(); 78 new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>();
72 79
80 private IEventQueue m_eqModule;
81
73 #region ISharedRegionModule 82 #region ISharedRegionModule
74 83
75 public Type ReplaceableInterface 84 public Type ReplaceableInterface
@@ -105,11 +114,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
105 IConfig transferConfig = source.Configs["EntityTransfer"]; 114 IConfig transferConfig = source.Configs["EntityTransfer"];
106 if (transferConfig != null) 115 if (transferConfig != null)
107 { 116 {
108 MaxTransferDistance = transferConfig.GetInt("max_distance", 4095); 117 WaitForAgentArrivedAtDestination
109 m_levelHGTeleport = transferConfig.GetInt("LevelHGTeleport", 0); 118 = transferConfig.GetBoolean("wait_for_callback", WaitForAgentArrivedAtDestinationDefault);
119
120 MaxTransferDistance = transferConfig.GetInt("max_distance", DefaultMaxTransferDistance);
121 }
122 else
123 {
124 MaxTransferDistance = DefaultMaxTransferDistance;
110 } 125 }
111 126
112 m_agentsInTransit = new List<UUID>(); 127 m_entityTransferStateMachine = new EntityTransferStateMachine(this);
128
113 m_Enabled = true; 129 m_Enabled = true;
114 } 130 }
115 131
@@ -122,10 +138,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
122 if (!m_Enabled) 138 if (!m_Enabled)
123 return; 139 return;
124 140
125 if (m_aScene == null) 141 Scene = scene;
126 m_aScene = scene;
127 142
128 m_Scenes.Add(scene);
129 scene.RegisterModuleInterface<IEntityTransferModule>(this); 143 scene.RegisterModuleInterface<IEntityTransferModule>(this);
130 scene.EventManager.OnNewClient += OnNewClient; 144 scene.EventManager.OnNewClient += OnNewClient;
131 } 145 }
@@ -136,26 +150,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
136 client.OnTeleportLandmarkRequest += RequestTeleportLandmark; 150 client.OnTeleportLandmarkRequest += RequestTeleportLandmark;
137 } 151 }
138 152
139 public virtual void Close() 153 public virtual void Close() {}
140 {
141 if (!m_Enabled)
142 return;
143 }
144 154
145 public virtual void RemoveRegion(Scene scene) 155 public virtual void RemoveRegion(Scene scene) {}
146 {
147 if (!m_Enabled)
148 return;
149 if (scene == m_aScene)
150 m_aScene = null;
151
152 m_Scenes.Remove(scene);
153 }
154 156
155 public virtual void RegionLoaded(Scene scene) 157 public virtual void RegionLoaded(Scene scene)
156 { 158 {
157 if (!m_Enabled) 159 if (!m_Enabled)
158 return; 160 return;
161
162 m_eqModule = Scene.RequestModuleInterface<IEventQueue>();
159 } 163 }
160 164
161 #endregion 165 #endregion
@@ -164,170 +168,257 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
164 168
165 public void Teleport(ScenePresence sp, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags) 169 public void Teleport(ScenePresence sp, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags)
166 { 170 {
171 if (sp.Scene.Permissions.IsGridGod(sp.UUID))
172 {
173 // This user will be a God in the destination scene, too
174 teleportFlags |= (uint)TeleportFlags.Godlike;
175 }
176
167 if (!sp.Scene.Permissions.CanTeleport(sp.UUID)) 177 if (!sp.Scene.Permissions.CanTeleport(sp.UUID))
168 return; 178 return;
169 179
170 IEventQueue eq = sp.Scene.RequestModuleInterface<IEventQueue>();
171
172 // Reset animations; the viewer does that in teleports. 180 // Reset animations; the viewer does that in teleports.
173 sp.Animator.ResetAnimations(); 181 sp.Animator.ResetAnimations();
174 182
183 string destinationRegionName = "(not found)";
184
175 try 185 try
176 { 186 {
177 if (regionHandle == sp.Scene.RegionInfo.RegionHandle) 187 if (regionHandle == sp.Scene.RegionInfo.RegionHandle)
178 { 188 {
179 m_log.DebugFormat( 189 destinationRegionName = sp.Scene.RegionInfo.RegionName;
180 "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation {0} within {1}",
181 position, sp.Scene.RegionInfo.RegionName);
182 190
183 // Teleport within the same region 191 TeleportAgentWithinRegion(sp, position, lookAt, teleportFlags);
184 if (IsOutsideRegion(sp.Scene, position) || position.Z < 0) 192 }
185 { 193 else // Another region possibly in another simulator
186 Vector3 emergencyPos = new Vector3(128, 128, 128); 194 {
195 GridRegion finalDestination;
196 TeleportAgentToDifferentRegion(
197 sp, regionHandle, position, lookAt, teleportFlags, out finalDestination);
187 198
188 m_log.WarnFormat( 199 if (finalDestination != null)
189 "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}. Substituting {3}", 200 destinationRegionName = finalDestination.RegionName;
190 position, sp.Name, sp.UUID, emergencyPos); 201 }
191 position = emergencyPos; 202 }
192 } 203 catch (Exception e)
204 {
205 m_log.ErrorFormat(
206 "[ENTITY TRANSFER MODULE]: Exception on teleport of {0} from {1}@{2} to {3}@{4}: {5}{6}",
207 sp.Name, sp.AbsolutePosition, sp.Scene.RegionInfo.RegionName, position, destinationRegionName,
208 e.Message, e.StackTrace);
193 209
194 // TODO: Get proper AVG Height 210 // Make sure that we clear the in-transit flag so that future teleport attempts don't always fail.
195 float localAVHeight = 1.56f; 211 m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
196 float posZLimit = 22;
197 212
198 // TODO: Check other Scene HeightField 213 sp.ControllingClient.SendTeleportFailed("Internal error");
199 if (position.X > 0 && position.X <= (int)Constants.RegionSize && position.Y > 0 && position.Y <= (int)Constants.RegionSize) 214 }
200 { 215 }
201 posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y];
202 }
203 216
204 float newPosZ = posZLimit + localAVHeight; 217 /// <summary>
205 if (posZLimit >= (position.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) 218 /// Teleports the agent within its current region.
206 { 219 /// </summary>
207 position.Z = newPosZ; 220 /// <param name="sp"></param>
208 } 221 /// <param name="position"></param>
222 /// <param name="lookAt"></param>
223 /// <param name="teleportFlags"></param
224 private void TeleportAgentWithinRegion(ScenePresence sp, Vector3 position, Vector3 lookAt, uint teleportFlags)
225 {
226 m_log.DebugFormat(
227 "[ENTITY TRANSFER MODULE]: Teleport for {0} to {1} within {2}",
228 sp.Name, position, sp.Scene.RegionInfo.RegionName);
209 229
210 sp.ControllingClient.SendTeleportStart(teleportFlags); 230 if (!m_entityTransferStateMachine.SetInTransit(sp.UUID))
231 {
232 m_log.DebugFormat(
233 "[ENTITY TRANSFER MODULE]: Ignoring within region teleport request of {0} {1} to {2} - agent is already in transit.",
234 sp.Name, sp.UUID, position);
211 235
212 sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags); 236 return;
213 sp.TeleportFlags = (Constants.TeleportFlags)teleportFlags; 237 }
214 sp.Teleport(position);
215 238
216 foreach (SceneObjectGroup grp in sp.GetAttachments()) 239 // Teleport within the same region
217 { 240 if (IsOutsideRegion(sp.Scene, position) || position.Z < 0)
218 sp.Scene.EventManager.TriggerOnScriptChangedEvent(grp.LocalId, (uint)Changed.TELEPORT); 241 {
219 } 242 Vector3 emergencyPos = new Vector3(128, 128, 128);
243
244 m_log.WarnFormat(
245 "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}. Substituting {3}",
246 position, sp.Name, sp.UUID, emergencyPos);
247
248 position = emergencyPos;
249 }
250
251 // TODO: Get proper AVG Height
252 float localAVHeight = 1.56f;
253 float posZLimit = 22;
254
255 // TODO: Check other Scene HeightField
256 if (position.X > 0 && position.X <= (int)Constants.RegionSize && position.Y > 0 && position.Y <= (int)Constants.RegionSize)
257 {
258 posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y];
259 }
260
261 float newPosZ = posZLimit + localAVHeight;
262 if (posZLimit >= (position.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
263 {
264 position.Z = newPosZ;
265 }
266
267 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
268
269 sp.ControllingClient.SendTeleportStart(teleportFlags);
270
271 sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags);
272 sp.TeleportFlags = (Constants.TeleportFlags)teleportFlags;
273 sp.Velocity = Vector3.Zero;
274 sp.Teleport(position);
275
276 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.ReceivedAtDestination);
277
278 foreach (SceneObjectGroup grp in sp.GetAttachments())
279 {
280 sp.Scene.EventManager.TriggerOnScriptChangedEvent(grp.LocalId, (uint)Changed.TELEPORT);
281 }
282
283 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
284 m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
285 }
286
287 /// <summary>
288 /// Teleports the agent to a different region.
289 /// </summary>
290 /// <param name='sp'></param>
291 /// <param name='regionHandle'>/param>
292 /// <param name='position'></param>
293 /// <param name='lookAt'></param>
294 /// <param name='teleportFlags'></param>
295 /// <param name='finalDestination'></param>
296 private void TeleportAgentToDifferentRegion(
297 ScenePresence sp, ulong regionHandle, Vector3 position,
298 Vector3 lookAt, uint teleportFlags, out GridRegion finalDestination)
299 {
300 uint x = 0, y = 0;
301 Utils.LongToUInts(regionHandle, out x, out y);
302 GridRegion reg = Scene.GridService.GetRegionByPosition(sp.Scene.RegionInfo.ScopeID, (int)x, (int)y);
303
304 if (reg != null)
305 {
306 finalDestination = GetFinalDestination(reg);
307
308 if (finalDestination == null)
309 {
310 m_log.WarnFormat(
311 "[ENTITY TRANSFER MODULE]: Final destination is having problems. Unable to teleport {0} {1}",
312 sp.Name, sp.UUID);
313
314 sp.ControllingClient.SendTeleportFailed("Problem at destination");
315 return;
220 } 316 }
221 else // Another region possibly in another simulator 317
318 // Check that these are not the same coordinates
319 if (finalDestination.RegionLocX == sp.Scene.RegionInfo.RegionLocX &&
320 finalDestination.RegionLocY == sp.Scene.RegionInfo.RegionLocY)
222 { 321 {
223 uint x = 0, y = 0; 322 // Can't do. Viewer crashes
224 Utils.LongToUInts(regionHandle, out x, out y); 323 sp.ControllingClient.SendTeleportFailed("Space warp! You would crash. Move to a different region and try again.");
225 GridRegion reg = m_aScene.GridService.GetRegionByPosition(sp.Scene.RegionInfo.ScopeID, (int)x, (int)y); 324 return;
325 }
226 326
227 if (reg != null) 327 //
228 { 328 // This is it
229 GridRegion finalDestination = GetFinalDestination(reg); 329 //
230 if (finalDestination == null) 330 DoTeleport(sp, reg, finalDestination, position, lookAt, teleportFlags);
231 { 331 //
232 m_log.WarnFormat("[ENTITY TRANSFER MODULE]: Final destination is having problems. Unable to teleport agent."); 332 //
233 sp.ControllingClient.SendTeleportFailed("Problem at destination"); 333 //
234 return; 334 }
235 } 335 else
336 {
337 finalDestination = null;
236 338
237 // check if HyperGrid teleport is allowed, based on user level 339 // TP to a place that doesn't exist (anymore)
238 int flags = m_aScene.GridService.GetRegionFlags(sp.Scene.RegionInfo.ScopeID, reg.RegionID); 340 // Inform the viewer about that
341 sp.ControllingClient.SendTeleportFailed("The region you tried to teleport to doesn't exist anymore");
239 342
240 if (((flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) && (sp.UserLevel < m_levelHGTeleport)) 343 // and set the map-tile to '(Offline)'
241 { 344 uint regX, regY;
242 m_log.WarnFormat("[ENTITY TRANSFER MODULE]: Final destination link is non permitted hypergrid region. Unable to teleport agent."); 345 Utils.LongToUInts(regionHandle, out regX, out regY);
243 sp.ControllingClient.SendTeleportFailed("HyperGrid teleport not permitted");
244 return;
245 }
246 346
247 uint curX = 0, curY = 0; 347 MapBlockData block = new MapBlockData();
248 Utils.LongToUInts(sp.Scene.RegionInfo.RegionHandle, out curX, out curY); 348 block.X = (ushort)(regX / Constants.RegionSize);
249 int curCellX = (int)(curX / Constants.RegionSize); 349 block.Y = (ushort)(regY / Constants.RegionSize);
250 int curCellY = (int)(curY / Constants.RegionSize); 350 block.Access = 254; // == not there
251 int destCellX = (int)(finalDestination.RegionLocX / Constants.RegionSize);
252 int destCellY = (int)(finalDestination.RegionLocY / Constants.RegionSize);
253 351
352 List<MapBlockData> blocks = new List<MapBlockData>();
353 blocks.Add(block);
354 sp.ControllingClient.SendMapBlock(blocks, 0);
355 }
356 }
357
358 /// <summary>
359 /// Determines whether this instance is within the max transfer distance.
360 /// </summary>
361 /// <param name="sourceRegion"></param>
362 /// <param name="destRegion"></param>
363 /// <returns>
364 /// <c>true</c> if this instance is within max transfer distance; otherwise, <c>false</c>.
365 /// </returns>
366 private bool IsWithinMaxTeleportDistance(RegionInfo sourceRegion, GridRegion destRegion)
367 {
254// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Source co-ords are x={0} y={1}", curRegionX, curRegionY); 368// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Source co-ords are x={0} y={1}", curRegionX, curRegionY);
255// 369//
256// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final dest is x={0} y={1} {2}@{3}", 370// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final dest is x={0} y={1} {2}@{3}",
257// destRegionX, destRegionY, finalDestination.RegionID, finalDestination.ServerURI); 371// destRegionX, destRegionY, finalDestination.RegionID, finalDestination.ServerURI);
258 372
259 // Check that these are not the same coordinates 373 // Insanely, RegionLoc on RegionInfo is the 256m map co-ord whilst GridRegion.RegionLoc is the raw meters position.
260 if (finalDestination.RegionLocX == sp.Scene.RegionInfo.RegionLocX && 374 return Math.Abs(sourceRegion.RegionLocX - destRegion.RegionCoordX) <= MaxTransferDistance
261 finalDestination.RegionLocY == sp.Scene.RegionInfo.RegionLocY) 375 && Math.Abs(sourceRegion.RegionLocY - destRegion.RegionCoordY) <= MaxTransferDistance;
262 { 376 }
263 // Can't do. Viewer crashes
264 sp.ControllingClient.SendTeleportFailed("Space warp! You would crash. Move to a different region and try again.");
265 return;
266 }
267
268 if (Math.Abs(curCellX - destCellX) > MaxTransferDistance || Math.Abs(curCellY - destCellY) > MaxTransferDistance)
269 {
270 sp.ControllingClient.SendTeleportFailed(
271 string.Format(
272 "Can't teleport to {0} ({1},{2}) from {3} ({4},{5}), destination is more than {6} regions way",
273 finalDestination.RegionName, destCellX, destCellY,
274 sp.Scene.RegionInfo.RegionName, curCellX, curCellY,
275 MaxTransferDistance));
276
277 return;
278 }
279 377
280 // 378 public void DoTeleport(
281 // This is it 379 ScenePresence sp, GridRegion reg, GridRegion finalDestination,
282 // 380 Vector3 position, Vector3 lookAt, uint teleportFlags)
283 DoTeleport(sp, reg, finalDestination, position, lookAt, teleportFlags, eq); 381 {
284 // 382 // Record that this agent is in transit so that we can prevent simultaneous requests and do later detection
285 // 383 // of whether the destination region completes the teleport.
286 // 384 if (!m_entityTransferStateMachine.SetInTransit(sp.UUID))
287 }
288 else
289 {
290 // TP to a place that doesn't exist (anymore)
291 // Inform the viewer about that
292 sp.ControllingClient.SendTeleportFailed("The region you tried to teleport to doesn't exist anymore");
293
294 // and set the map-tile to '(Offline)'
295 uint regX, regY;
296 Utils.LongToUInts(regionHandle, out regX, out regY);
297
298 MapBlockData block = new MapBlockData();
299 block.X = (ushort)(regX / Constants.RegionSize);
300 block.Y = (ushort)(regY / Constants.RegionSize);
301 block.Access = 254; // == not there
302
303 List<MapBlockData> blocks = new List<MapBlockData>();
304 blocks.Add(block);
305 sp.ControllingClient.SendMapBlock(blocks, 0);
306 }
307 }
308 }
309 catch (Exception e)
310 { 385 {
311 m_log.WarnFormat("[ENTITY TRANSFER MODULE]: Exception on teleport: {0} {1}", e.Message, e.StackTrace); 386 m_log.DebugFormat(
312 sp.ControllingClient.SendTeleportFailed("Internal error"); 387 "[ENTITY TRANSFER MODULE]: Ignoring teleport request of {0} {1} to {2} ({3}) {4}/{5} - agent is already in transit.",
388 sp.Name, sp.UUID, reg.ServerURI, finalDestination.ServerURI, finalDestination.RegionName, position);
389
390 return;
313 } 391 }
314 }
315 392
316 public void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq)
317 {
318 if (reg == null || finalDestination == null) 393 if (reg == null || finalDestination == null)
319 { 394 {
320 sp.ControllingClient.SendTeleportFailed("Unable to locate destination"); 395 sp.ControllingClient.SendTeleportFailed("Unable to locate destination");
321 return; 396 m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
322 }
323 397
324 if (IsInTransit(sp.UUID)) // Avie is already on the way. Caller shouldn't do this.
325 return; 398 return;
399 }
326 400
327 m_log.DebugFormat( 401 m_log.DebugFormat(
328 "[ENTITY TRANSFER MODULE]: Request Teleport to {0} ({1}) {2}/{3}", 402 "[ENTITY TRANSFER MODULE]: Teleporting {0} {1} from {2} to {3} ({4}) {5}/{6}",
403 sp.Name, sp.UUID, sp.Scene.RegionInfo.RegionName,
329 reg.ServerURI, finalDestination.ServerURI, finalDestination.RegionName, position); 404 reg.ServerURI, finalDestination.ServerURI, finalDestination.RegionName, position);
330 405
406 RegionInfo sourceRegion = sp.Scene.RegionInfo;
407
408 if (!IsWithinMaxTeleportDistance(sourceRegion, finalDestination))
409 {
410 sp.ControllingClient.SendTeleportFailed(
411 string.Format(
412 "Can't teleport to {0} ({1},{2}) from {3} ({4},{5}), destination is more than {6} regions way",
413 finalDestination.RegionName, finalDestination.RegionCoordX, finalDestination.RegionCoordY,
414 sourceRegion.RegionName, sourceRegion.RegionLocX, sourceRegion.RegionLocY,
415 MaxTransferDistance));
416
417 m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
418
419 return;
420 }
421
331 uint newRegionX = (uint)(reg.RegionHandle >> 40); 422 uint newRegionX = (uint)(reg.RegionHandle >> 40);
332 uint newRegionY = (((uint)(reg.RegionHandle)) >> 8); 423 uint newRegionY = (((uint)(reg.RegionHandle)) >> 8);
333 uint oldRegionX = (uint)(sp.Scene.RegionInfo.RegionHandle >> 40); 424 uint oldRegionX = (uint)(sp.Scene.RegionInfo.RegionHandle >> 40);
@@ -339,17 +430,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
339 // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field, 430 // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field,
340 // it's actually doing a lot of work. 431 // it's actually doing a lot of work.
341 IPEndPoint endPoint = finalDestination.ExternalEndPoint; 432 IPEndPoint endPoint = finalDestination.ExternalEndPoint;
342 if (endPoint != null && endPoint.Address != null) 433 if (endPoint == null || endPoint.Address == null)
343 { 434 {
344 // Fixing a bug where teleporting while sitting results in the avatar ending up removed from 435 sp.ControllingClient.SendTeleportFailed("Remote Region appears to be down");
345 // both regions 436 m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
346 if (sp.ParentID != (uint)0)
347 sp.StandUp();
348 437
349 if (!sp.ValidateAttachments()) 438 return;
350 m_log.DebugFormat( 439 }
351 "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}. Continuing.", 440
352 sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName); 441 if (!sp.ValidateAttachments())
442 m_log.DebugFormat(
443 "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}. Continuing.",
444 sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName);
353 445
354// if (!sp.ValidateAttachments()) 446// if (!sp.ValidateAttachments())
355// { 447// {
@@ -357,218 +449,245 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
357// return; 449// return;
358// } 450// }
359 451
360 string reason; 452 string reason;
361 string version; 453 string version;
362 if (!m_aScene.SimulationService.QueryAccess(finalDestination, sp.ControllingClient.AgentId, Vector3.Zero, out version, out reason)) 454 if (!Scene.SimulationService.QueryAccess(
363 { 455 finalDestination, sp.ControllingClient.AgentId, Vector3.Zero, out version, out reason))
364 sp.ControllingClient.SendTeleportFailed("Teleport failed: " + reason); 456 {
365 return; 457 sp.ControllingClient.SendTeleportFailed(reason);
366 } 458 m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
367 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Destination is running version {0}", version);
368
369 sp.ControllingClient.SendTeleportStart(teleportFlags);
370
371 // the avatar.Close below will clear the child region list. We need this below for (possibly)
372 // closing the child agents, so save it here (we need a copy as it is Clear()-ed).
373 //List<ulong> childRegions = avatar.KnownRegionHandles;
374 // Compared to ScenePresence.CrossToNewRegion(), there's no obvious code to handle a teleport
375 // failure at this point (unlike a border crossing failure). So perhaps this can never fail
376 // once we reach here...
377 //avatar.Scene.RemoveCapsHandler(avatar.UUID);
378
379 string capsPath = String.Empty;
380
381 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
382 AgentCircuitData agentCircuit = sp.ControllingClient.RequestClientInfo();
383 agentCircuit.startpos = position;
384 agentCircuit.child = true;
385 agentCircuit.Appearance = sp.Appearance;
386 if (currentAgentCircuit != null)
387 {
388 agentCircuit.ServiceURLs = currentAgentCircuit.ServiceURLs;
389 agentCircuit.IPAddress = currentAgentCircuit.IPAddress;
390 agentCircuit.Viewer = currentAgentCircuit.Viewer;
391 agentCircuit.Channel = currentAgentCircuit.Channel;
392 agentCircuit.Mac = currentAgentCircuit.Mac;
393 agentCircuit.Id0 = currentAgentCircuit.Id0;
394 }
395 459
396 if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) 460 m_log.DebugFormat(
397 { 461 "[ENTITY TRANSFER MODULE]: {0} was stopped from teleporting from {1} to {2} because {3}",
398 // brand new agent, let's create a new caps seed 462 sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName, reason);
399 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
400 }
401 463
402 // Let's create an agent there if one doesn't exist yet. 464 return;
403 bool logout = false; 465 }
404 if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout))
405 {
406 sp.ControllingClient.SendTeleportFailed(String.Format("Destination refused: {0}",
407 reason));
408 return;
409 }
410 466
411 // OK, it got this agent. Let's close some child agents 467 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Destination is running version {0}", version);
412 sp.CloseChildAgents(newRegionX, newRegionY);
413 IClientIPEndpoint ipepClient;
414 if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
415 {
416 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");
417 #region IP Translation for NAT
418 // Uses ipepClient above
419 if (sp.ClientView.TryGet(out ipepClient))
420 {
421 endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
422 }
423 #endregion
424 capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
425 468
426 if (eq != null) 469 // Fixing a bug where teleporting while sitting results in the avatar ending up removed from
427 { 470 // both regions
428 eq.EnableSimulator(destinationHandle, endPoint, sp.UUID); 471 if (sp.ParentID != (uint)0)
472 sp.StandUp();
429 473
430 // ES makes the client send a UseCircuitCode message to the destination, 474 sp.ControllingClient.SendTeleportStart(teleportFlags);
431 // which triggers a bunch of things there.
432 // So let's wait
433 Thread.Sleep(200);
434 475
435 eq.EstablishAgentCommunication(sp.UUID, endPoint, capsPath); 476 // the avatar.Close below will clear the child region list. We need this below for (possibly)
477 // closing the child agents, so save it here (we need a copy as it is Clear()-ed).
478 //List<ulong> childRegions = avatar.KnownRegionHandles;
479 // Compared to ScenePresence.CrossToNewRegion(), there's no obvious code to handle a teleport
480 // failure at this point (unlike a border crossing failure). So perhaps this can never fail
481 // once we reach here...
482 //avatar.Scene.RemoveCapsHandler(avatar.UUID);
436 483
437 } 484 string capsPath = String.Empty;
438 else
439 {
440 sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint);
441 }
442 }
443 else
444 {
445 agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle);
446 capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
447 }
448 485
486 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
487 AgentCircuitData agentCircuit = sp.ControllingClient.RequestClientInfo();
488 agentCircuit.startpos = position;
489 agentCircuit.child = true;
490 agentCircuit.Appearance = sp.Appearance;
491 if (currentAgentCircuit != null)
492 {
493 agentCircuit.ServiceURLs = currentAgentCircuit.ServiceURLs;
494 agentCircuit.IPAddress = currentAgentCircuit.IPAddress;
495 agentCircuit.Viewer = currentAgentCircuit.Viewer;
496 agentCircuit.Channel = currentAgentCircuit.Channel;
497 agentCircuit.Mac = currentAgentCircuit.Mac;
498 agentCircuit.Id0 = currentAgentCircuit.Id0;
499 }
449 500
450 SetInTransit(sp.UUID); 501 if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
502 {
503 // brand new agent, let's create a new caps seed
504 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
505 }
451 506
452 // Let's send a full update of the agent. This is a synchronous call. 507 // Let's create an agent there if one doesn't exist yet.
453 AgentData agent = new AgentData(); 508 bool logout = false;
454 sp.CopyTo(agent); 509 if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout))
455 agent.Position = position; 510 {
456 SetCallbackURL(agent, sp.Scene.RegionInfo); 511 sp.ControllingClient.SendTeleportFailed(String.Format("Teleport refused: {0}", reason));
512 m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
457 513
458 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent..."); 514 m_log.DebugFormat(
515 "[ENTITY TRANSFER MODULE]: Teleport of {0} from {1} to {2} was refused because {3}",
516 sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName, reason);
459 517
460 if (!UpdateAgent(reg, finalDestination, agent)) 518 return;
519 }
520
521 // Past this point we have to attempt clean up if the teleport fails, so update transfer state.
522 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
523
524 // OK, it got this agent. Let's close some child agents
525 sp.CloseChildAgents(newRegionX, newRegionY);
526
527 IClientIPEndpoint ipepClient;
528 if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
529 {
530 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");
531 #region IP Translation for NAT
532 // Uses ipepClient above
533 if (sp.ClientView.TryGet(out ipepClient))
461 { 534 {
462 // Region doesn't take it 535 endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
463 m_log.WarnFormat(
464 "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1}. Returning avatar to source region.",
465 sp.Name, finalDestination.RegionName);
466
467 Fail(sp, finalDestination, logout);
468 return;
469 } 536 }
537 #endregion
538 capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
470 539
471 sp.ControllingClient.SendTeleportProgress(teleportFlags | (uint)TeleportFlags.DisableCancel, "sending_dest"); 540 if (m_eqModule != null)
541 {
542 m_eqModule.EnableSimulator(destinationHandle, endPoint, sp.UUID);
472 543
473 m_log.DebugFormat( 544 // ES makes the client send a UseCircuitCode message to the destination,
474 "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, sp.UUID); 545 // which triggers a bunch of things there.
546 // So let's wait
547 Thread.Sleep(200);
548
549 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath);
475 550
476 if (eq != null)
477 {
478 eq.TeleportFinishEvent(destinationHandle, 13, endPoint,
479 0, teleportFlags, capsPath, sp.UUID);
480 } 551 }
481 else 552 else
482 { 553 {
483 sp.ControllingClient.SendRegionTeleport(destinationHandle, 13, endPoint, 4, 554 sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint);
484 teleportFlags, capsPath);
485 } 555 }
556 }
557 else
558 {
559 agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle);
560 capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
561 }
486 562
487 // Let's set this to true tentatively. This does not trigger OnChildAgent 563 // Let's send a full update of the agent. This is a synchronous call.
488 sp.IsChildAgent = true; 564 AgentData agent = new AgentData();
565 sp.CopyTo(agent);
566 agent.Position = position;
567 SetCallbackURL(agent, sp.Scene.RegionInfo);
489 568
490 // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which 569 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent...");
491 // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation
492 // that the client contacted the destination before we close things here.
493 if (!WaitForCallback(sp.UUID))
494 {
495 m_log.WarnFormat(
496 "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} failed due to no callback from destination region. Returning avatar to source region.",
497 sp.Name, finalDestination.RegionName);
498
499 Fail(sp, finalDestination, logout);
500 return;
501 }
502 570
503 // For backwards compatibility 571 if (!UpdateAgent(reg, finalDestination, agent))
504 if (version == "Unknown" || version == string.Empty) 572 {
505 { 573 // Region doesn't take it
506 // CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it 574 m_log.WarnFormat(
507 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Old simulator, sending attachments one by one..."); 575 "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Returning avatar to source region.",
508 CrossAttachmentsIntoNewRegion(finalDestination, sp, true); 576 sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
509 } 577
578 Fail(sp, finalDestination, logout);
579 return;
580 }
510 581
511 // May need to logout or other cleanup 582 sp.ControllingClient.SendTeleportProgress(teleportFlags | (uint)TeleportFlags.DisableCancel, "sending_dest");
512 AgentHasMovedAway(sp, logout);
513 583
514 // Well, this is it. The agent is over there. 584 m_log.DebugFormat(
515 KillEntity(sp.Scene, sp.LocalId); 585 "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}",
586 capsPath, sp.Scene.RegionInfo.RegionName, sp.Name);
516 587
517 // Now let's make it officially a child agent 588 if (m_eqModule != null)
518 sp.MakeChildAgent(); 589 {
590 m_eqModule.TeleportFinishEvent(destinationHandle, 13, endPoint, 0, teleportFlags, capsPath, sp.UUID);
591 }
592 else
593 {
594 sp.ControllingClient.SendRegionTeleport(destinationHandle, 13, endPoint, 4,
595 teleportFlags, capsPath);
596 }
519 597
520// sp.Scene.CleanDroppedAttachments(); 598 // Let's set this to true tentatively. This does not trigger OnChildAgent
599 sp.IsChildAgent = true;
600
601 // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which
602 // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation
603 // that the client contacted the destination before we close things here.
604 if (!m_entityTransferStateMachine.WaitForAgentArrivedAtDestination(sp.UUID))
605 {
606 m_log.WarnFormat(
607 "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.",
608 sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
609
610 Fail(sp, finalDestination, logout);
611 return;
612 }
521 613
522 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone 614 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
523 615
524 if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) 616 // For backwards compatibility
525 { 617 if (version == "Unknown" || version == string.Empty)
526 Thread.Sleep(5000); 618 {
527 sp.Close(); 619 // CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it
528 sp.Scene.IncomingCloseAgent(sp.UUID); 620 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Old simulator, sending attachments one by one...");
529 } 621 CrossAttachmentsIntoNewRegion(finalDestination, sp, true);
530 else 622 }
531 {
532 // now we have a child agent in this region.
533 sp.Reset();
534 }
535 623
536 // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! 624 // May need to logout or other cleanup
537 if (sp.Scene.NeedSceneCacheClear(sp.UUID)) 625 AgentHasMovedAway(sp, logout);
538 { 626
539 m_log.DebugFormat( 627 // Well, this is it. The agent is over there.
540 "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed", 628 KillEntity(sp.Scene, sp.LocalId);
541 sp.UUID); 629
542 } 630 // Now let's make it officially a child agent
631 sp.MakeChildAgent();
632
633// sp.Scene.CleanDroppedAttachments();
634
635 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
636
637 if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
638 {
639 // We need to delay here because Imprudence viewers, unlike v1 or v3, have a short (<200ms, <500ms) delay before
640 // they regard the new region as the current region after receiving the AgentMovementComplete
641 // response. If close is sent before then, it will cause the viewer to quit instead.
642 //
643 // This sleep can be increased if necessary. However, whilst it's active,
644 // an agent cannot teleport back to this region if it has teleported away.
645 Thread.Sleep(2000);
646
647 sp.Scene.IncomingCloseAgent(sp.UUID);
543 } 648 }
544 else 649 else
545 { 650 {
546 sp.ControllingClient.SendTeleportFailed("Remote Region appears to be down"); 651 // now we have a child agent in this region.
652 sp.Reset();
547 } 653 }
654
655 // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE!
656 if (sp.Scene.NeedSceneCacheClear(sp.UUID))
657 {
658 m_log.DebugFormat(
659 "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed",
660 sp.UUID);
661 }
662
663 m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
548 } 664 }
549 665
550 protected virtual void Fail(ScenePresence sp, GridRegion finalDestination, bool logout) 666 protected virtual void Fail(ScenePresence sp, GridRegion finalDestination, bool logout)
551 { 667 {
668 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
669
552 // Client never contacted destination. Let's restore everything back 670 // Client never contacted destination. Let's restore everything back
553 sp.ControllingClient.SendTeleportFailed("Problems connecting to destination."); 671 sp.ControllingClient.SendTeleportFailed("Problems connecting to destination.");
554 672
555 // Fail. Reset it back 673 // Fail. Reset it back
556 sp.IsChildAgent = false; 674 sp.IsChildAgent = false;
557 ReInstantiateScripts(sp); 675 ReInstantiateScripts(sp);
558 ResetFromTransit(sp.UUID);
559 676
560 EnableChildAgents(sp); 677 EnableChildAgents(sp);
561 678
562 // Finally, kill the agent we just created at the destination. 679 // Finally, kill the agent we just created at the destination.
563 m_aScene.SimulationService.CloseAgent(finalDestination, sp.UUID); 680 Scene.SimulationService.CloseAgent(finalDestination, sp.UUID);
564 681
565 sp.Scene.EventManager.TriggerTeleportFail(sp.ControllingClient, logout); 682 sp.Scene.EventManager.TriggerTeleportFail(sp.ControllingClient, logout);
683
684 m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
566 } 685 }
567 686
568 protected virtual bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout) 687 protected virtual bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout)
569 { 688 {
570 logout = false; 689 logout = false;
571 bool success = m_aScene.SimulationService.CreateAgent(finalDestination, agentCircuit, teleportFlags, out reason); 690 bool success = Scene.SimulationService.CreateAgent(finalDestination, agentCircuit, teleportFlags, out reason);
572 691
573 if (success) 692 if (success)
574 sp.Scene.EventManager.TriggerTeleportStart(sp.ControllingClient, reg, finalDestination, teleportFlags, logout); 693 sp.Scene.EventManager.TriggerTeleportStart(sp.ControllingClient, reg, finalDestination, teleportFlags, logout);
@@ -578,19 +697,27 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
578 697
579 protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent) 698 protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent)
580 { 699 {
581 return m_aScene.SimulationService.UpdateAgent(finalDestination, agent); 700 return Scene.SimulationService.UpdateAgent(finalDestination, agent);
582 } 701 }
583 702
584 protected virtual void SetCallbackURL(AgentData agent, RegionInfo region) 703 protected virtual void SetCallbackURL(AgentData agent, RegionInfo region)
585 { 704 {
586 agent.CallbackURI = region.ServerURI + "agent/" + agent.AgentID.ToString() + "/" + region.RegionID.ToString() + "/release/"; 705 agent.CallbackURI = region.ServerURI + "agent/" + agent.AgentID.ToString() + "/" + region.RegionID.ToString() + "/release/";
587 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Set callback URL to {0}", agent.CallbackURI);
588 706
707 m_log.DebugFormat(
708 "[ENTITY TRANSFER MODULE]: Set release callback URL to {0} in {1}",
709 agent.CallbackURI, region.RegionName);
589 } 710 }
590 711
712 /// <summary>
713 /// Clean up operations once an agent has moved away through cross or teleport.
714 /// </summary>
715 /// <param name='sp'></param>
716 /// <param name='logout'></param>
591 protected virtual void AgentHasMovedAway(ScenePresence sp, bool logout) 717 protected virtual void AgentHasMovedAway(ScenePresence sp, bool logout)
592 { 718 {
593 sp.Scene.AttachmentsModule.DeleteAttachmentsFromScene(sp, true); 719 if (sp.Scene.AttachmentsModule != null)
720 sp.Scene.AttachmentsModule.DeleteAttachmentsFromScene(sp, true);
594 } 721 }
595 722
596 protected void KillEntity(Scene scene, uint localID) 723 protected void KillEntity(Scene scene, uint localID)
@@ -615,7 +742,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
615 742
616 protected virtual bool IsOutsideRegion(Scene s, Vector3 pos) 743 protected virtual bool IsOutsideRegion(Scene s, Vector3 pos)
617 { 744 {
618
619 if (s.TestBorderCross(pos, Cardinals.N)) 745 if (s.TestBorderCross(pos, Cardinals.N))
620 return true; 746 return true;
621 if (s.TestBorderCross(pos, Cardinals.S)) 747 if (s.TestBorderCross(pos, Cardinals.S))
@@ -628,7 +754,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
628 return false; 754 return false;
629 } 755 }
630 756
631
632 #endregion 757 #endregion
633 758
634 #region Landmark Teleport 759 #region Landmark Teleport
@@ -640,7 +765,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
640 /// <param name="position"></param> 765 /// <param name="position"></param>
641 public virtual void RequestTeleportLandmark(IClientAPI remoteClient, AssetLandmark lm) 766 public virtual void RequestTeleportLandmark(IClientAPI remoteClient, AssetLandmark lm)
642 { 767 {
643 GridRegion info = m_aScene.GridService.GetRegionByUUID(UUID.Zero, lm.RegionID); 768 GridRegion info = Scene.GridService.GetRegionByUUID(UUID.Zero, lm.RegionID);
644 769
645 if (info == null) 770 if (info == null)
646 { 771 {
@@ -663,10 +788,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
663 788
664 public virtual bool TeleportHome(UUID id, IClientAPI client) 789 public virtual bool TeleportHome(UUID id, IClientAPI client)
665 { 790 {
666 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Request to teleport {0} {1} home", client.FirstName, client.LastName); 791 m_log.DebugFormat(
792 "[ENTITY TRANSFER MODULE]: Request to teleport {0} {1} home", client.Name, client.AgentId);
667 793
668 //OpenSim.Services.Interfaces.PresenceInfo pinfo = m_aScene.PresenceService.GetAgent(client.SessionId); 794 //OpenSim.Services.Interfaces.PresenceInfo pinfo = Scene.PresenceService.GetAgent(client.SessionId);
669 GridUserInfo uinfo = m_aScene.GridUserService.GetGridUserInfo(client.AgentId.ToString()); 795 GridUserInfo uinfo = Scene.GridUserService.GetGridUserInfo(client.AgentId.ToString());
670 796
671 if (uinfo != null) 797 if (uinfo != null)
672 { 798 {
@@ -676,7 +802,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
676 client.SendTeleportFailed("You don't have a home position set."); 802 client.SendTeleportFailed("You don't have a home position set.");
677 return false; 803 return false;
678 } 804 }
679 GridRegion regionInfo = m_aScene.GridService.GetRegionByUUID(UUID.Zero, uinfo.HomeRegionID); 805 GridRegion regionInfo = Scene.GridService.GetRegionByUUID(UUID.Zero, uinfo.HomeRegionID);
680 if (regionInfo == null) 806 if (regionInfo == null)
681 { 807 {
682 // can't find the Home region: Tell viewer and abort 808 // can't find the Home region: Tell viewer and abort
@@ -684,8 +810,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
684 return false; 810 return false;
685 } 811 }
686 812
687 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: User's home region is {0} {1} ({2}-{3})", 813 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Home region of {0} is {1} ({2}-{3})",
688 regionInfo.RegionName, regionInfo.RegionID, regionInfo.RegionLocX / Constants.RegionSize, regionInfo.RegionLocY / Constants.RegionSize); 814 client.Name, regionInfo.RegionName, regionInfo.RegionCoordX, regionInfo.RegionCoordY);
689 815
690 // a little eekie that this goes back to Scene and with a forced cast, will fix that at some point... 816 // a little eekie that this goes back to Scene and with a forced cast, will fix that at some point...
691 ((Scene)(client.Scene)).RequestTeleportLocation( 817 ((Scene)(client.Scene)).RequestTeleportLocation(
@@ -736,7 +862,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
736 862
737 neighbourx--; 863 neighbourx--;
738 newpos.X = Constants.RegionSize - enterDistance; 864 newpos.X = Constants.RegionSize - enterDistance;
739
740 } 865 }
741 else if (scene.TestBorderCross(pos + eastCross, Cardinals.E)) 866 else if (scene.TestBorderCross(pos + eastCross, Cardinals.E))
742 { 867 {
@@ -922,107 +1047,123 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
922 ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, 1047 ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion,
923 bool isFlying, string version) 1048 bool isFlying, string version)
924 { 1049 {
1050 if (neighbourRegion == null)
1051 return agent;
1052
925 try 1053 try
926 { 1054 {
1055 m_entityTransferStateMachine.SetInTransit(agent.UUID);
1056
927 ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize)); 1057 ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize));
928 1058
929 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} to {2}-{3} running version {4}", agent.Firstname, agent.Lastname, neighbourx, neighboury, version); 1059 m_log.DebugFormat(
1060 "[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} to {2}-{3} running version {4}",
1061 agent.Firstname, agent.Lastname, neighbourx, neighboury, version);
930 1062
931 Scene m_scene = agent.Scene; 1063 Scene m_scene = agent.Scene;
932 1064
933 if (neighbourRegion != null) 1065 if (!agent.ValidateAttachments())
1066 m_log.DebugFormat(
1067 "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for region crossing of {0} from {1} to {2}. Continuing.",
1068 agent.Name, agent.Scene.RegionInfo.RegionName, neighbourRegion.RegionName);
1069
1070 pos = pos + agent.Velocity;
1071 Vector3 vel2 = new Vector3(agent.Velocity.X, agent.Velocity.Y, 0);
1072
1073 agent.RemoveFromPhysicalScene();
1074
1075 AgentData cAgent = new AgentData();
1076 agent.CopyTo(cAgent);
1077 cAgent.Position = pos;
1078 if (isFlying)
1079 cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
1080
1081 // We don't need the callback anymnore
1082 cAgent.CallbackURI = String.Empty;
1083
1084 // Beyond this point, extra cleanup is needed beyond removing transit state
1085 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.Transferring);
1086
1087 if (!m_scene.SimulationService.UpdateAgent(neighbourRegion, cAgent))
934 { 1088 {
935 if (!agent.ValidateAttachments()) 1089 // region doesn't take it
936 m_log.DebugFormat( 1090 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp);
937 "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for region crossing of {0} from {1} to {2}. Continuing.",
938 agent.Name, agent.Scene.RegionInfo.RegionName, neighbourRegion.RegionName);
939 1091
940 pos = pos + agent.Velocity; 1092 ReInstantiateScripts(agent);
941 Vector3 vel2 = new Vector3(agent.Velocity.X, agent.Velocity.Y, 0); 1093 agent.AddToPhysicalScene(isFlying);
1094 m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
942 1095
943 agent.RemoveFromPhysicalScene(); 1096 return agent;
944 SetInTransit(agent.UUID); 1097 }
945 1098
946 AgentData cAgent = new AgentData(); 1099 //AgentCircuitData circuitdata = m_controllingClient.RequestClientInfo();
947 agent.CopyTo(cAgent); 1100 agent.ControllingClient.RequestClientInfo();
948 cAgent.Position = pos;
949 if (isFlying)
950 cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
951 1101
952 // We don't need the callback anymnore 1102 //m_log.Debug("BEFORE CROSS");
953 cAgent.CallbackURI = String.Empty; 1103 //Scene.DumpChildrenSeeds(UUID);
1104 //DumpKnownRegions();
1105 string agentcaps;
1106 if (!agent.KnownRegions.TryGetValue(neighbourRegion.RegionHandle, out agentcaps))
1107 {
1108 m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: No ENTITY TRANSFER MODULE information for region handle {0}, exiting CrossToNewRegion.",
1109 neighbourRegion.RegionHandle);
1110 return agent;
1111 }
1112 // No turning back
1113 agent.IsChildAgent = true;
954 1114
955 if (!m_scene.SimulationService.UpdateAgent(neighbourRegion, cAgent)) 1115 string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentcaps);
956 {
957 // region doesn't take it
958 ReInstantiateScripts(agent);
959 agent.AddToPhysicalScene(isFlying);
960 ResetFromTransit(agent.UUID);
961 return agent;
962 }
963
964 //AgentCircuitData circuitdata = m_controllingClient.RequestClientInfo();
965 agent.ControllingClient.RequestClientInfo();
966
967 //m_log.Debug("BEFORE CROSS");
968 //Scene.DumpChildrenSeeds(UUID);
969 //DumpKnownRegions();
970 string agentcaps;
971 if (!agent.KnownRegions.TryGetValue(neighbourRegion.RegionHandle, out agentcaps))
972 {
973 m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: No ENTITY TRANSFER MODULE information for region handle {0}, exiting CrossToNewRegion.",
974 neighbourRegion.RegionHandle);
975 return agent;
976 }
977 // No turning back
978 agent.IsChildAgent = true;
979 1116
980 string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentcaps); 1117 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID);
981
982 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID);
983 1118
984 IEventQueue eq = agent.Scene.RequestModuleInterface<IEventQueue>(); 1119 if (m_eqModule != null)
985 if (eq != null) 1120 {
986 { 1121 m_eqModule.CrossRegion(
987 eq.CrossRegion(neighbourHandle, pos, vel2 /* agent.Velocity */, neighbourRegion.ExternalEndPoint, 1122 neighbourHandle, pos, vel2 /* agent.Velocity */, neighbourRegion.ExternalEndPoint,
988 capsPath, agent.UUID, agent.ControllingClient.SessionId); 1123 capsPath, agent.UUID, agent.ControllingClient.SessionId);
989 } 1124 }
990 else 1125 else
991 { 1126 {
992 agent.ControllingClient.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint, 1127 agent.ControllingClient.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint,
993 capsPath); 1128 capsPath);
994 } 1129 }
995 1130
996 // SUCCESS! 1131 // SUCCESS!
997 agent.MakeChildAgent(); 1132 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.ReceivedAtDestination);
998 ResetFromTransit(agent.UUID);
999 1133
1000 // now we have a child agent in this region. Request all interesting data about other (root) agents 1134 // Unlike a teleport, here we do not wait for the destination region to confirm the receipt.
1001 agent.SendOtherAgentsAvatarDataToMe(); 1135 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp);
1002 agent.SendOtherAgentsAppearanceToMe();
1003 1136
1004 // Backwards compatibility. Best effort 1137 agent.MakeChildAgent();
1005 if (version == "Unknown" || version == string.Empty)
1006 {
1007 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: neighbor with old version, passing attachments one by one...");
1008 Thread.Sleep(3000); // wait a little now that we're not waiting for the callback
1009 CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true);
1010 }
1011 1138
1139 // FIXME: Possibly this should occur lower down after other commands to close other agents,
1140 // but not sure yet what the side effects would be.
1141 m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
1012 1142
1013 // Next, let's close the child agent connections that are too far away. 1143 // now we have a child agent in this region. Request all interesting data about other (root) agents
1014 agent.CloseChildAgents(neighbourx, neighboury); 1144 agent.SendOtherAgentsAvatarDataToMe();
1015 1145 agent.SendOtherAgentsAppearanceToMe();
1016 AgentHasMovedAway(agent, false); 1146
1017 1147 // Backwards compatibility. Best effort
1018 // the user may change their profile information in other region, 1148 if (version == "Unknown" || version == string.Empty)
1019 // so the userinfo in UserProfileCache is not reliable any more, delete it 1149 {
1020 // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! 1150 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: neighbor with old version, passing attachments one by one...");
1021 if (agent.Scene.NeedSceneCacheClear(agent.UUID)) 1151 Thread.Sleep(3000); // wait a little now that we're not waiting for the callback
1022 { 1152 CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true);
1023 m_log.DebugFormat( 1153 }
1024 "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID); 1154
1025 } 1155 // Next, let's close the child agent connections that are too far away.
1156 agent.CloseChildAgents(neighbourx, neighboury);
1157
1158 AgentHasMovedAway(agent, false);
1159
1160 // the user may change their profile information in other region,
1161 // so the userinfo in UserProfileCache is not reliable any more, delete it
1162 // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE!
1163 if (agent.Scene.NeedSceneCacheClear(agent.UUID))
1164 {
1165 m_log.DebugFormat(
1166 "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID);
1026 } 1167 }
1027 1168
1028 //m_log.Debug("AFTER CROSS"); 1169 //m_log.Debug("AFTER CROSS");
@@ -1034,11 +1175,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1034 m_log.ErrorFormat( 1175 m_log.ErrorFormat(
1035 "[ENTITY TRANSFER MODULE]: Problem crossing user {0} to new region {1} from {2}. Exception {3}{4}", 1176 "[ENTITY TRANSFER MODULE]: Problem crossing user {0} to new region {1} from {2}. Exception {3}{4}",
1036 agent.Name, neighbourRegion.RegionName, agent.Scene.RegionInfo.RegionName, e.Message, e.StackTrace); 1177 agent.Name, neighbourRegion.RegionName, agent.Scene.RegionInfo.RegionName, e.Message, e.StackTrace);
1178
1179 // TODO: Might be worth attempting other restoration here such as reinstantiation of scripts, etc.
1037 } 1180 }
1038 1181
1039 return agent; 1182 return agent;
1040 } 1183 }
1041 1184
1042 private void CrossAgentToNewRegionCompleted(IAsyncResult iar) 1185 private void CrossAgentToNewRegionCompleted(IAsyncResult iar)
1043 { 1186 {
1044 CrossAgentToNewRegionDelegate icon = (CrossAgentToNewRegionDelegate)iar.AsyncState; 1187 CrossAgentToNewRegionDelegate icon = (CrossAgentToNewRegionDelegate)iar.AsyncState;
@@ -1186,7 +1329,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1186 { 1329 {
1187 if (neighbour.RegionHandle != sp.Scene.RegionInfo.RegionHandle) 1330 if (neighbour.RegionHandle != sp.Scene.RegionInfo.RegionHandle)
1188 { 1331 {
1189
1190 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); 1332 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
1191 AgentCircuitData agent = sp.ControllingClient.RequestClientInfo(); 1333 AgentCircuitData agent = sp.ControllingClient.RequestClientInfo();
1192 agent.BaseFolder = UUID.Zero; 1334 agent.BaseFolder = UUID.Zero;
@@ -1211,7 +1353,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1211 seeds.Add(neighbour.RegionHandle, agent.CapsPath); 1353 seeds.Add(neighbour.RegionHandle, agent.CapsPath);
1212 } 1354 }
1213 else 1355 else
1356 {
1214 agent.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, neighbour.RegionHandle); 1357 agent.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, neighbour.RegionHandle);
1358 }
1215 1359
1216 cagents.Add(agent); 1360 cagents.Add(agent);
1217 } 1361 }
@@ -1322,24 +1466,21 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1322 // after a cross here 1466 // after a cross here
1323 Thread.Sleep(500); 1467 Thread.Sleep(500);
1324 1468
1325 Scene m_scene = sp.Scene; 1469 Scene scene = sp.Scene;
1326 1470
1327 uint x, y; 1471 m_log.DebugFormat(
1328 Utils.LongToUInts(reg.RegionHandle, out x, out y); 1472 "[ENTITY TRANSFER MODULE]: Informing {0} {1} about neighbour {2} {3} at ({4},{5})",
1329 x = x / Constants.RegionSize; 1473 sp.Name, sp.UUID, reg.RegionName, endPoint, reg.RegionCoordX, reg.RegionCoordY);
1330 y = y / Constants.RegionSize;
1331 m_log.Debug("[ENTITY TRANSFER MODULE]: Starting to inform client about neighbour " + x + ", " + y + "(" + endPoint + ")");
1332 1474
1333 string capsPath = reg.ServerURI + CapsUtil.GetCapsSeedPath(a.CapsPath); 1475 string capsPath = reg.ServerURI + CapsUtil.GetCapsSeedPath(a.CapsPath);
1334 1476
1335 string reason = String.Empty; 1477 string reason = String.Empty;
1336 1478
1337 bool regionAccepted = m_scene.SimulationService.CreateAgent(reg, a, (uint)TeleportFlags.Default, out reason); 1479 bool regionAccepted = scene.SimulationService.CreateAgent(reg, a, (uint)TeleportFlags.Default, out reason);
1338 1480
1339 if (regionAccepted && newAgent) 1481 if (regionAccepted && newAgent)
1340 { 1482 {
1341 IEventQueue eq = sp.Scene.RequestModuleInterface<IEventQueue>(); 1483 if (m_eqModule != null)
1342 if (eq != null)
1343 { 1484 {
1344 #region IP Translation for NAT 1485 #region IP Translation for NAT
1345 IClientIPEndpoint ipepClient; 1486 IClientIPEndpoint ipepClient;
@@ -1351,10 +1492,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1351 1492
1352 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: {0} is sending {1} EnableSimulator for neighbour region {2} @ {3} " + 1493 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: {0} is sending {1} EnableSimulator for neighbour region {2} @ {3} " +
1353 "and EstablishAgentCommunication with seed cap {4}", 1494 "and EstablishAgentCommunication with seed cap {4}",
1354 m_scene.RegionInfo.RegionName, sp.Name, reg.RegionName, reg.RegionHandle, capsPath); 1495 scene.RegionInfo.RegionName, sp.Name, reg.RegionName, reg.RegionHandle, capsPath);
1355 1496
1356 eq.EnableSimulator(reg.RegionHandle, endPoint, sp.UUID); 1497 m_eqModule.EnableSimulator(reg.RegionHandle, endPoint, sp.UUID);
1357 eq.EstablishAgentCommunication(sp.UUID, endPoint, capsPath); 1498 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath);
1358 } 1499 }
1359 else 1500 else
1360 { 1501 {
@@ -1362,8 +1503,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1362 // TODO: make Event Queue disablable! 1503 // TODO: make Event Queue disablable!
1363 } 1504 }
1364 1505
1365 m_log.Debug("[ENTITY TRANSFER MODULE]: Completed inform client about neighbour " + endPoint.ToString()); 1506 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Completed inform {0} {1} about neighbour {2}", sp.Name, sp.UUID, endPoint);
1366 } 1507 }
1508
1509 if (!regionAccepted)
1510 m_log.WarnFormat(
1511 "[ENTITY TRANSFER MODULE]: Region {0} did not accept {1} {2}: {3}",
1512 reg.RegionName, sp.Name, sp.UUID, reason);
1367 } 1513 }
1368 1514
1369 /// <summary> 1515 /// <summary>
@@ -1471,17 +1617,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1471 1617
1472 #endregion 1618 #endregion
1473 1619
1474
1475 #region Agent Arrived 1620 #region Agent Arrived
1621
1476 public void AgentArrivedAtDestination(UUID id) 1622 public void AgentArrivedAtDestination(UUID id)
1477 { 1623 {
1478 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Agent {0} released", id); 1624 m_entityTransferStateMachine.SetAgentArrivedAtDestination(id);
1479 ResetFromTransit(id);
1480 } 1625 }
1481 1626
1482 #endregion 1627 #endregion
1483 1628
1484 #region Object Transfers 1629 #region Object Transfers
1630
1485 /// <summary> 1631 /// <summary>
1486 /// Move the given scene object into a new region depending on which region its absolute position has moved 1632 /// Move the given scene object into a new region depending on which region its absolute position has moved
1487 /// into. 1633 /// into.
@@ -1747,8 +1893,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1747 //// And the new channel... 1893 //// And the new channel...
1748 //if (m_interregionCommsOut != null) 1894 //if (m_interregionCommsOut != null)
1749 // successYN = m_interregionCommsOut.SendCreateObject(newRegionHandle, grp, true); 1895 // successYN = m_interregionCommsOut.SendCreateObject(newRegionHandle, grp, true);
1750 if (m_aScene.SimulationService != null) 1896 if (Scene.SimulationService != null)
1751 successYN = m_aScene.SimulationService.CreateObject(destination, newPosition, grp, true); 1897 successYN = Scene.SimulationService.CreateObject(destination, newPosition, grp, true);
1752 1898
1753 if (successYN) 1899 if (successYN)
1754 { 1900 {
@@ -1792,86 +1938,52 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1792 return successYN; 1938 return successYN;
1793 } 1939 }
1794 1940
1795 protected bool CrossAttachmentsIntoNewRegion(GridRegion destination, ScenePresence sp, bool silent) 1941 /// <summary>
1942 /// Cross the attachments for an avatar into the destination region.
1943 /// </summary>
1944 /// <remarks>
1945 /// This is only invoked for simulators released prior to April 2011. Versions of OpenSimulator since then
1946 /// transfer attachments in one go as part of the ChildAgentDataUpdate data passed in the update agent call.
1947 /// </remarks>
1948 /// <param name='destination'></param>
1949 /// <param name='sp'></param>
1950 /// <param name='silent'></param>
1951 protected void CrossAttachmentsIntoNewRegion(GridRegion destination, ScenePresence sp, bool silent)
1796 { 1952 {
1797 List<SceneObjectGroup> m_attachments = sp.GetAttachments(); 1953 List<SceneObjectGroup> attachments = sp.GetAttachments();
1798 1954
1799 // Validate 1955// m_log.DebugFormat(
1800// foreach (SceneObjectGroup gobj in m_attachments) 1956// "[ENTITY TRANSFER MODULE]: Crossing {0} attachments into {1} for {2}",
1801// { 1957// m_attachments.Count, destination.RegionName, sp.Name);
1802// if (gobj == null || gobj.IsDeleted)
1803// return false;
1804// }
1805 1958
1806 foreach (SceneObjectGroup gobj in m_attachments) 1959 foreach (SceneObjectGroup gobj in attachments)
1807 { 1960 {
1808 // If the prim group is null then something must have happened to it! 1961 // If the prim group is null then something must have happened to it!
1809 if (gobj != null && !gobj.IsDeleted) 1962 if (gobj != null && !gobj.IsDeleted)
1810 { 1963 {
1811 // Set the parent localID to 0 so it transfers over properly. 1964 SceneObjectGroup clone = (SceneObjectGroup)gobj.CloneForNewScene();
1812 gobj.RootPart.SetParentLocalId(0); 1965 clone.RootPart.GroupPosition = gobj.RootPart.AttachedPos;
1813 gobj.AbsolutePosition = gobj.RootPart.AttachedPos; 1966 clone.IsAttachment = false;
1814 gobj.IsAttachment = false; 1967
1815 //gobj.RootPart.LastOwnerID = gobj.GetFromAssetID(); 1968 //gobj.RootPart.LastOwnerID = gobj.GetFromAssetID();
1816 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending attachment {0} to region {1}", gobj.UUID, destination.RegionName); 1969 m_log.DebugFormat(
1817 CrossPrimGroupIntoNewRegion(destination, Vector3.Zero, gobj, silent); 1970 "[ENTITY TRANSFER MODULE]: Sending attachment {0} to region {1}",
1971 clone.UUID, destination.RegionName);
1972
1973 CrossPrimGroupIntoNewRegion(destination, Vector3.Zero, clone, silent);
1818 } 1974 }
1819 } 1975 }
1820 1976
1821 sp.ClearAttachments(); 1977 sp.ClearAttachments();
1822
1823 return true;
1824 } 1978 }
1825 1979
1826 #endregion 1980 #endregion
1827 1981
1828 #region Misc 1982 #region Misc
1829 1983
1830 protected bool WaitForCallback(UUID id) 1984 public bool IsInTransit(UUID id)
1831 {
1832 int count = 200;
1833 while (m_agentsInTransit.Contains(id) && count-- > 0)
1834 {
1835 //m_log.Debug(" >>> Waiting... " + count);
1836 Thread.Sleep(100);
1837 }
1838
1839 if (count > 0)
1840 return true;
1841 else
1842 return false;
1843 }
1844
1845 protected void SetInTransit(UUID id)
1846 {
1847 lock (m_agentsInTransit)
1848 {
1849 if (!m_agentsInTransit.Contains(id))
1850 m_agentsInTransit.Add(id);
1851 }
1852 }
1853
1854 protected bool IsInTransit(UUID id)
1855 { 1985 {
1856 lock (m_agentsInTransit) 1986 return m_entityTransferStateMachine.IsInTransit(id);
1857 {
1858 if (m_agentsInTransit.Contains(id))
1859 return true;
1860 }
1861 return false;
1862 }
1863
1864 protected bool ResetFromTransit(UUID id)
1865 {
1866 lock (m_agentsInTransit)
1867 {
1868 if (m_agentsInTransit.Contains(id))
1869 {
1870 m_agentsInTransit.Remove(id);
1871 return true;
1872 }
1873 }
1874 return false;
1875 } 1987 }
1876 1988
1877 protected void ReInstantiateScripts(ScenePresence sp) 1989 protected void ReInstantiateScripts(ScenePresence sp)
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs
new file mode 100644
index 0000000..d0cab49
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs
@@ -0,0 +1,269 @@
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.Net;
31using System.Reflection;
32using System.Threading;
33using OpenMetaverse;
34using log4net;
35using Nini.Config;
36using OpenSim.Framework;
37using OpenSim.Framework.Capabilities;
38using OpenSim.Framework.Client;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes;
41using OpenSim.Region.Physics.Manager;
42using OpenSim.Services.Interfaces;
43using GridRegion = OpenSim.Services.Interfaces.GridRegion;
44
45namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
46{
47 /// <summary>
48 /// The possible states that an agent can be in when its being transferred between regions.
49 /// </summary>
50 /// <remarks>
51 /// This is a state machine.
52 ///
53 /// [Entry] => Preparing
54 /// Preparing => { Transferring || CleaningUp || [Exit] }
55 /// Transferring => { ReceivedAtDestination || CleaningUp }
56 /// ReceivedAtDestination => CleaningUp
57 /// CleaningUp => [Exit]
58 ///
59 /// In other words, agents normally travel throwing Preparing => Transferring => ReceivedAtDestination => CleaningUp
60 /// However, any state can transition to CleaningUp if the teleport has failed.
61 /// </remarks>
62 enum AgentTransferState
63 {
64 Preparing, // The agent is being prepared for transfer
65 Transferring, // The agent is in the process of being transferred to a destination
66 ReceivedAtDestination, // The destination has notified us that the agent has been successfully received
67 CleaningUp // The agent is being changed to child/removed after a transfer
68 }
69
70 /// <summary>
71 /// Records the state of entities when they are in transfer within or between regions (cross or teleport).
72 /// </summary>
73 public class EntityTransferStateMachine
74 {
75 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
76
77 /// <summary>
78 /// If true then on a teleport, the source region waits for a callback from the destination region. If
79 /// a callback fails to arrive within a set time then the user is pulled back into the source region.
80 /// </summary>
81 public bool EnableWaitForAgentArrivedAtDestination { get; set; }
82
83 private EntityTransferModule m_mod;
84
85 private Dictionary<UUID, AgentTransferState> m_agentsInTransit = new Dictionary<UUID, AgentTransferState>();
86
87 public EntityTransferStateMachine(EntityTransferModule module)
88 {
89 m_mod = module;
90 }
91
92 /// <summary>
93 /// Set that an agent is in transit.
94 /// </summary>
95 /// <param name='id'>The ID of the agent being teleported</param>
96 /// <returns>true if the agent was not already in transit, false if it was</returns>
97 internal bool SetInTransit(UUID id)
98 {
99 lock (m_agentsInTransit)
100 {
101 if (!m_agentsInTransit.ContainsKey(id))
102 {
103 m_agentsInTransit[id] = AgentTransferState.Preparing;
104 return true;
105 }
106 }
107
108 return false;
109 }
110
111 /// <summary>
112 /// Updates the state of an agent that is already in transit.
113 /// </summary>
114 /// <param name='id'></param>
115 /// <param name='newState'></param>
116 /// <returns></returns>
117 /// <exception cref='Exception'>Illegal transitions will throw an Exception</exception>
118 internal void UpdateInTransit(UUID id, AgentTransferState newState)
119 {
120 lock (m_agentsInTransit)
121 {
122 // Illegal to try and update an agent that's not actually in transit.
123 if (!m_agentsInTransit.ContainsKey(id))
124 throw new Exception(
125 string.Format(
126 "Agent with ID {0} is not registered as in transit in {1}",
127 id, m_mod.Scene.RegionInfo.RegionName));
128
129 AgentTransferState oldState = m_agentsInTransit[id];
130
131 bool transitionOkay = false;
132
133 if (newState == AgentTransferState.CleaningUp && oldState != AgentTransferState.CleaningUp)
134 transitionOkay = true;
135 else if (newState == AgentTransferState.Transferring && oldState == AgentTransferState.Preparing)
136 transitionOkay = true;
137 else if (newState == AgentTransferState.ReceivedAtDestination && oldState == AgentTransferState.Transferring)
138 transitionOkay = true;
139
140 if (transitionOkay)
141 m_agentsInTransit[id] = newState;
142 else
143 throw new Exception(
144 string.Format(
145 "Agent with ID {0} is not allowed to move from old transit state {1} to new state {2} in {3}",
146 id, oldState, newState, m_mod.Scene.RegionInfo.RegionName));
147 }
148 }
149
150 internal bool IsInTransit(UUID id)
151 {
152 lock (m_agentsInTransit)
153 return m_agentsInTransit.ContainsKey(id);
154 }
155
156 /// <summary>
157 /// Removes an agent from the transit state machine.
158 /// </summary>
159 /// <param name='id'></param>
160 /// <returns>true if the agent was flagged as being teleported when this method was called, false otherwise</returns>
161 internal bool ResetFromTransit(UUID id)
162 {
163 lock (m_agentsInTransit)
164 {
165 if (m_agentsInTransit.ContainsKey(id))
166 {
167 AgentTransferState state = m_agentsInTransit[id];
168
169 if (state == AgentTransferState.Transferring || state == AgentTransferState.ReceivedAtDestination)
170 {
171 // FIXME: For now, we allow exit from any state since a thrown exception in teleport is now guranteed
172 // to be handled properly - ResetFromTransit() could be invoked at any step along the process
173 m_log.WarnFormat(
174 "[ENTITY TRANSFER STATE MACHINE]: Agent with ID {0} should not exit directly from state {1}, should go to {2} state first in {3}",
175 id, state, AgentTransferState.CleaningUp, m_mod.Scene.RegionInfo.RegionName);
176
177// throw new Exception(
178// "Agent with ID {0} cannot exit directly from state {1}, it must go to {2} state first",
179// state, AgentTransferState.CleaningUp);
180 }
181
182 m_agentsInTransit.Remove(id);
183
184 m_log.DebugFormat(
185 "[ENTITY TRANSFER STATE MACHINE]: Agent {0} cleared from transit in {1}",
186 id, m_mod.Scene.RegionInfo.RegionName);
187
188 return true;
189 }
190 }
191
192 m_log.WarnFormat(
193 "[ENTITY TRANSFER STATE MACHINE]: Agent {0} requested to clear from transit in {1} but was already cleared",
194 id, m_mod.Scene.RegionInfo.RegionName);
195
196 return false;
197 }
198
199 internal bool WaitForAgentArrivedAtDestination(UUID id)
200 {
201 if (!m_mod.WaitForAgentArrivedAtDestination)
202 return true;
203
204 lock (m_agentsInTransit)
205 {
206 if (!IsInTransit(id))
207 throw new Exception(
208 string.Format(
209 "Asked to wait for destination callback for agent with ID {0} in {1} but agent is not in transit",
210 id, m_mod.Scene.RegionInfo.RegionName));
211
212 AgentTransferState currentState = m_agentsInTransit[id];
213
214 if (currentState != AgentTransferState.Transferring && currentState != AgentTransferState.ReceivedAtDestination)
215 throw new Exception(
216 string.Format(
217 "Asked to wait for destination callback for agent with ID {0} in {1} but agent is in state {2}",
218 id, m_mod.Scene.RegionInfo.RegionName, currentState));
219 }
220
221 int count = 200;
222
223 // There should be no race condition here since no other code should be removing the agent transfer or
224 // changing the state to another other than Transferring => ReceivedAtDestination.
225 while (m_agentsInTransit[id] != AgentTransferState.ReceivedAtDestination && count-- > 0)
226 {
227// m_log.Debug(" >>> Waiting... " + count);
228 Thread.Sleep(100);
229 }
230
231 return count > 0;
232 }
233
234 internal void SetAgentArrivedAtDestination(UUID id)
235 {
236 lock (m_agentsInTransit)
237 {
238 if (!m_agentsInTransit.ContainsKey(id))
239 {
240 m_log.WarnFormat(
241 "[ENTITY TRANSFER STATE MACHINE]: Region {0} received notification of arrival in destination of agent {1} but no teleport request is active",
242 m_mod.Scene.RegionInfo.RegionName, id);
243
244 return;
245 }
246
247 AgentTransferState currentState = m_agentsInTransit[id];
248
249 if (currentState == AgentTransferState.ReceivedAtDestination)
250 {
251 // An anomoly but don't make this an outright failure - destination region could be overzealous in sending notification.
252 m_log.WarnFormat(
253 "[ENTITY TRANSFER STATE MACHINE]: Region {0} received notification of arrival in destination of agent {1} but notification has already previously been received",
254 m_mod.Scene.RegionInfo.RegionName, id);
255 }
256 else if (currentState != AgentTransferState.Transferring)
257 {
258 m_log.ErrorFormat(
259 "[ENTITY TRANSFER STATE MACHINE]: Region {0} received notification of arrival in destination of agent {1} but agent is in state {2}",
260 m_mod.Scene.RegionInfo.RegionName, id, currentState);
261
262 return;
263 }
264
265 m_agentsInTransit[id] = AgentTransferState.ReceivedAtDestination;
266 }
267 }
268 }
269} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
index 8b5ad23..3010b59 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
@@ -45,11 +45,12 @@ using Nini.Config;
45 45
46namespace OpenSim.Region.CoreModules.Framework.EntityTransfer 46namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
47{ 47{
48 public class HGEntityTransferModule : EntityTransferModule, ISharedRegionModule, IEntityTransferModule, IUserAgentVerificationModule 48 public class HGEntityTransferModule
49 : EntityTransferModule, INonSharedRegionModule, IEntityTransferModule, IUserAgentVerificationModule
49 { 50 {
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51 52
52 private bool m_Initialized = false; 53 private int m_levelHGTeleport = 0;
53 54
54 private GatekeeperServiceConnector m_GatekeeperConnector; 55 private GatekeeperServiceConnector m_GatekeeperConnector;
55 56
@@ -63,11 +64,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
63 public override void Initialise(IConfigSource source) 64 public override void Initialise(IConfigSource source)
64 { 65 {
65 IConfig moduleConfig = source.Configs["Modules"]; 66 IConfig moduleConfig = source.Configs["Modules"];
67
66 if (moduleConfig != null) 68 if (moduleConfig != null)
67 { 69 {
68 string name = moduleConfig.GetString("EntityTransferModule", ""); 70 string name = moduleConfig.GetString("EntityTransferModule", "");
69 if (name == Name) 71 if (name == Name)
70 { 72 {
73 IConfig transferConfig = source.Configs["EntityTransfer"];
74 if (transferConfig != null)
75 m_levelHGTeleport = transferConfig.GetInt("LevelHGTeleport", 0);
76
71 InitialiseCommon(source); 77 InitialiseCommon(source);
72 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name); 78 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name);
73 } 79 }
@@ -77,10 +83,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
77 public override void AddRegion(Scene scene) 83 public override void AddRegion(Scene scene)
78 { 84 {
79 base.AddRegion(scene); 85 base.AddRegion(scene);
86
80 if (m_Enabled) 87 if (m_Enabled)
81 {
82 scene.RegisterModuleInterface<IUserAgentVerificationModule>(this); 88 scene.RegisterModuleInterface<IUserAgentVerificationModule>(this);
83 }
84 } 89 }
85 90
86 protected override void OnNewClient(IClientAPI client) 91 protected override void OnNewClient(IClientAPI client)
@@ -93,33 +98,28 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
93 public override void RegionLoaded(Scene scene) 98 public override void RegionLoaded(Scene scene)
94 { 99 {
95 base.RegionLoaded(scene); 100 base.RegionLoaded(scene);
96 if (m_Enabled)
97 if (!m_Initialized)
98 {
99 m_GatekeeperConnector = new GatekeeperServiceConnector(scene.AssetService);
100 m_Initialized = true;
101
102 }
103 101
102 if (m_Enabled)
103 m_GatekeeperConnector = new GatekeeperServiceConnector(scene.AssetService);
104 } 104 }
105
105 public override void RemoveRegion(Scene scene) 106 public override void RemoveRegion(Scene scene)
106 { 107 {
107 base.AddRegion(scene); 108 base.AddRegion(scene);
109
108 if (m_Enabled) 110 if (m_Enabled)
109 {
110 scene.UnregisterModuleInterface<IUserAgentVerificationModule>(this); 111 scene.UnregisterModuleInterface<IUserAgentVerificationModule>(this);
111 }
112 } 112 }
113 113
114
115 #endregion 114 #endregion
116 115
117 #region HG overrides of IEntiryTransferModule 116 #region HG overrides of IEntiryTransferModule
118 117
119 protected override GridRegion GetFinalDestination(GridRegion region) 118 protected override GridRegion GetFinalDestination(GridRegion region)
120 { 119 {
121 int flags = m_aScene.GridService.GetRegionFlags(m_aScene.RegionInfo.ScopeID, region.RegionID); 120 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, region.RegionID);
122 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: region {0} flags: {1}", region.RegionID, flags); 121 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: region {0} flags: {1}", region.RegionID, flags);
122
123 if ((flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) 123 if ((flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0)
124 { 124 {
125 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region {0} is hyperlink", region.RegionID); 125 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region {0} is hyperlink", region.RegionID);
@@ -130,6 +130,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
130 m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: GetHyperlinkRegion to Gatekeeper {0} failed", region.ServerURI); 130 m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: GetHyperlinkRegion to Gatekeeper {0} failed", region.ServerURI);
131 return real_destination; 131 return real_destination;
132 } 132 }
133
133 return region; 134 return region;
134 } 135 }
135 136
@@ -138,7 +139,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
138 if (base.NeedsClosing(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) 139 if (base.NeedsClosing(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
139 return true; 140 return true;
140 141
141 int flags = m_aScene.GridService.GetRegionFlags(m_aScene.RegionInfo.ScopeID, reg.RegionID); 142 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID);
142 if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) 143 if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0)
143 return true; 144 return true;
144 145
@@ -151,7 +152,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
151 if (logout) 152 if (logout)
152 { 153 {
153 // Log them out of this grid 154 // Log them out of this grid
154 m_aScene.PresenceService.LogoutAgent(sp.ControllingClient.SessionId); 155 Scene.PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
155 } 156 }
156 } 157 }
157 158
@@ -160,10 +161,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
160 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: CreateAgent {0} {1}", reg.ServerURI, finalDestination.ServerURI); 161 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: CreateAgent {0} {1}", reg.ServerURI, finalDestination.ServerURI);
161 reason = string.Empty; 162 reason = string.Empty;
162 logout = false; 163 logout = false;
163 int flags = m_aScene.GridService.GetRegionFlags(m_aScene.RegionInfo.ScopeID, reg.RegionID); 164 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID);
164 if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) 165 if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0)
165 { 166 {
166 // this user is going to another grid 167 // this user is going to another grid
168 // check if HyperGrid teleport is allowed, based on user level
169 if (sp.UserLevel < m_levelHGTeleport)
170 {
171 m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to HG teleport agent due to insufficient UserLevel.");
172 reason = "Hypergrid teleport not allowed";
173 return false;
174 }
175
167 if (agentCircuit.ServiceURLs.ContainsKey("HomeURI")) 176 if (agentCircuit.ServiceURLs.ContainsKey("HomeURI"))
168 { 177 {
169 string userAgentDriver = agentCircuit.ServiceURLs["HomeURI"].ToString(); 178 string userAgentDriver = agentCircuit.ServiceURLs["HomeURI"].ToString();
@@ -193,10 +202,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
193 202
194 public override bool TeleportHome(UUID id, IClientAPI client) 203 public override bool TeleportHome(UUID id, IClientAPI client)
195 { 204 {
196 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Request to teleport {0} {1} home", client.FirstName, client.LastName); 205 m_log.DebugFormat(
206 "[ENTITY TRANSFER MODULE]: Request to teleport {0} {1} home", client.Name, client.AgentId);
197 207
198 // Let's find out if this is a foreign user or a local user 208 // Let's find out if this is a foreign user or a local user
199 IUserManagement uMan = m_aScene.RequestModuleInterface<IUserManagement>(); 209 IUserManagement uMan = Scene.RequestModuleInterface<IUserManagement>();
200 if (uMan != null && uMan.IsLocalGridUser(id)) 210 if (uMan != null && uMan.IsLocalGridUser(id))
201 { 211 {
202 // local grid user 212 // local grid user
@@ -232,13 +242,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
232 return false; 242 return false;
233 } 243 }
234 244
235 IEventQueue eq = sp.Scene.RequestModuleInterface<IEventQueue>();
236 GridRegion homeGatekeeper = MakeRegion(aCircuit); 245 GridRegion homeGatekeeper = MakeRegion(aCircuit);
237 246
238 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: teleporting user {0} {1} home to {2} via {3}:{4}", 247 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: teleporting user {0} {1} home to {2} via {3}:{4}",
239 aCircuit.firstname, aCircuit.lastname, finalDestination.RegionName, homeGatekeeper.ServerURI, homeGatekeeper.RegionName); 248 aCircuit.firstname, aCircuit.lastname, finalDestination.RegionName, homeGatekeeper.ServerURI, homeGatekeeper.RegionName);
240 249
241 DoTeleport(sp, homeGatekeeper, finalDestination, position, lookAt, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome), eq); 250 DoTeleport(sp, homeGatekeeper, finalDestination, position, lookAt, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome));
242 return true; 251 return true;
243 } 252 }
244 253
@@ -252,19 +261,21 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
252 { 261 {
253 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Teleporting agent via landmark to {0} region {1} position {2}", 262 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Teleporting agent via landmark to {0} region {1} position {2}",
254 (lm.Gatekeeper == string.Empty) ? "local" : lm.Gatekeeper, lm.RegionID, lm.Position); 263 (lm.Gatekeeper == string.Empty) ? "local" : lm.Gatekeeper, lm.RegionID, lm.Position);
264
255 if (lm.Gatekeeper == string.Empty) 265 if (lm.Gatekeeper == string.Empty)
256 { 266 {
257 base.RequestTeleportLandmark(remoteClient, lm); 267 base.RequestTeleportLandmark(remoteClient, lm);
258 return; 268 return;
259 } 269 }
260 270
261 GridRegion info = m_aScene.GridService.GetRegionByUUID(UUID.Zero, lm.RegionID); 271 GridRegion info = Scene.GridService.GetRegionByUUID(UUID.Zero, lm.RegionID);
262 272
263 // Local region? 273 // Local region?
264 if (info != null) 274 if (info != null)
265 { 275 {
266 ((Scene)(remoteClient.Scene)).RequestTeleportLocation(remoteClient, info.RegionHandle, lm.Position, 276 ((Scene)(remoteClient.Scene)).RequestTeleportLocation(remoteClient, info.RegionHandle, lm.Position,
267 Vector3.Zero, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaLandmark)); 277 Vector3.Zero, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaLandmark));
278
268 return; 279 return;
269 } 280 }
270 else 281 else
@@ -275,21 +286,22 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
275 GridRegion gatekeeper = new GridRegion(); 286 GridRegion gatekeeper = new GridRegion();
276 gatekeeper.ServerURI = lm.Gatekeeper; 287 gatekeeper.ServerURI = lm.Gatekeeper;
277 GridRegion finalDestination = gConn.GetHyperlinkRegion(gatekeeper, new UUID(lm.RegionID)); 288 GridRegion finalDestination = gConn.GetHyperlinkRegion(gatekeeper, new UUID(lm.RegionID));
289
278 if (finalDestination != null) 290 if (finalDestination != null)
279 { 291 {
280 ScenePresence sp = scene.GetScenePresence(remoteClient.AgentId); 292 ScenePresence sp = scene.GetScenePresence(remoteClient.AgentId);
281 IEntityTransferModule transferMod = scene.RequestModuleInterface<IEntityTransferModule>(); 293 IEntityTransferModule transferMod = scene.RequestModuleInterface<IEntityTransferModule>();
282 IEventQueue eq = sp.Scene.RequestModuleInterface<IEventQueue>(); 294
283 if (transferMod != null && sp != null && eq != null) 295 if (transferMod != null && sp != null)
284 transferMod.DoTeleport(sp, gatekeeper, finalDestination, lm.Position, 296 transferMod.DoTeleport(
285 Vector3.UnitX, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaLandmark), eq); 297 sp, gatekeeper, finalDestination, lm.Position, Vector3.UnitX,
298 (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaLandmark));
286 } 299 }
287 300
288 } 301 }
289 302
290 // can't find the region: Tell viewer and abort 303 // can't find the region: Tell viewer and abort
291 remoteClient.SendTeleportFailed("The teleport destination could not be found."); 304 remoteClient.SendTeleportFailed("The teleport destination could not be found.");
292
293 } 305 }
294 306
295 #endregion 307 #endregion
@@ -304,49 +316,48 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
304 IUserAgentService security = new UserAgentServiceConnector(url); 316 IUserAgentService security = new UserAgentServiceConnector(url);
305 return security.VerifyClient(aCircuit.SessionID, token); 317 return security.VerifyClient(aCircuit.SessionID, token);
306 } 318 }
307 else 319 else
308 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Agent {0} {1} does not have a HomeURI OH NO!", aCircuit.firstname, aCircuit.lastname); 320 {
321 m_log.DebugFormat(
322 "[HG ENTITY TRANSFER MODULE]: Agent {0} {1} does not have a HomeURI OH NO!",
323 aCircuit.firstname, aCircuit.lastname);
324 }
309 325
310 return false; 326 return false;
311 } 327 }
312 328
313 void OnConnectionClosed(IClientAPI obj) 329 void OnConnectionClosed(IClientAPI obj)
314 { 330 {
315 if (obj.IsLoggingOut) 331 if (obj.SceneAgent.IsChildAgent)
316 { 332 return;
317 object sp = null;
318 if (obj.Scene.TryGetScenePresence(obj.AgentId, out sp))
319 {
320 if (((ScenePresence)sp).IsChildAgent)
321 return;
322 }
323 333
324 // Let's find out if this is a foreign user or a local user 334 // Let's find out if this is a foreign user or a local user
325 IUserManagement uMan = m_aScene.RequestModuleInterface<IUserManagement>(); 335 IUserManagement uMan = Scene.RequestModuleInterface<IUserManagement>();
326 UserAccount account = m_aScene.UserAccountService.GetUserAccount(m_aScene.RegionInfo.ScopeID, obj.AgentId); 336// UserAccount account = Scene.UserAccountService.GetUserAccount(Scene.RegionInfo.ScopeID, obj.AgentId);
327 if (uMan != null && uMan.IsLocalGridUser(obj.AgentId)) 337
328 { 338 if (uMan != null && uMan.IsLocalGridUser(obj.AgentId))
329 // local grid user 339 {
330 return; 340 // local grid user
331 } 341 return;
342 }
332 343
333 AgentCircuitData aCircuit = ((Scene)(obj.Scene)).AuthenticateHandler.GetAgentCircuitData(obj.CircuitCode); 344 AgentCircuitData aCircuit = ((Scene)(obj.Scene)).AuthenticateHandler.GetAgentCircuitData(obj.CircuitCode);
334 345
335 if (aCircuit.ServiceURLs.ContainsKey("HomeURI")) 346 if (aCircuit.ServiceURLs.ContainsKey("HomeURI"))
336 { 347 {
337 string url = aCircuit.ServiceURLs["HomeURI"].ToString(); 348 string url = aCircuit.ServiceURLs["HomeURI"].ToString();
338 IUserAgentService security = new UserAgentServiceConnector(url); 349 IUserAgentService security = new UserAgentServiceConnector(url);
339 security.LogoutAgent(obj.AgentId, obj.SessionId); 350 security.LogoutAgent(obj.AgentId, obj.SessionId);
340 //m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Sent logout call to UserAgentService @ {0}", url); 351 //m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Sent logout call to UserAgentService @ {0}", url);
341 } 352 }
342 else 353 else
354 {
343 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: HomeURI not found for agent {0} logout", obj.AgentId); 355 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: HomeURI not found for agent {0} logout", obj.AgentId);
344 } 356 }
345 } 357 }
346 358
347 #endregion 359 #endregion
348 360
349
350 private GridRegion MakeRegion(AgentCircuitData aCircuit) 361 private GridRegion MakeRegion(AgentCircuitData aCircuit)
351 { 362 {
352 GridRegion region = new GridRegion(); 363 GridRegion region = new GridRegion();
@@ -363,6 +374,5 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
363 region.InternalEndPoint = new System.Net.IPEndPoint(System.Net.IPAddress.Parse("0.0.0.0"), (int)0); 374 region.InternalEndPoint = new System.Net.IPEndPoint(System.Net.IPAddress.Parse("0.0.0.0"), (int)0);
364 return region; 375 return region;
365 } 376 }
366
367 } 377 }
368} 378} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
index a71584a..cf72b58 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
@@ -364,8 +364,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
364 { 364 {
365 m_log.DebugFormat("[HG INVENTORY ACCESS MODULE]: Changing root inventory for user {0}", client.Name); 365 m_log.DebugFormat("[HG INVENTORY ACCESS MODULE]: Changing root inventory for user {0}", client.Name);
366 InventoryCollection content = m_Scene.InventoryService.GetFolderContent(client.AgentId, root.ID); 366 InventoryCollection content = m_Scene.InventoryService.GetFolderContent(client.AgentId, root.ID);
367 List<UUID> fids = new List<UUID>(); 367
368 List<UUID> iids = new List<UUID>();
369 List<InventoryFolderBase> keep = new List<InventoryFolderBase>(); 368 List<InventoryFolderBase> keep = new List<InventoryFolderBase>();
370 369
371 foreach (InventoryFolderBase f in content.Folders) 370 foreach (InventoryFolderBase f in content.Folders)
@@ -395,4 +394,4 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
395 394
396 #endregion 395 #endregion
397 } 396 }
398} 397} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index ee9961f..d30c2e2 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -175,7 +175,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
175 sbyte assetType, 175 sbyte assetType,
176 byte wearableType, uint nextOwnerMask, int creationDate) 176 byte wearableType, uint nextOwnerMask, int creationDate)
177 { 177 {
178 m_log.DebugFormat("[AGENT INVENTORY]: Received request to create inventory item {0} in folder {1}", name, folderID); 178 m_log.DebugFormat("[INVENTORY ACCESS MODULE]: Received request to create inventory item {0} in folder {1}", name, folderID);
179 179
180 if (!m_Scene.Permissions.CanCreateUserInventory(invType, remoteClient.AgentId)) 180 if (!m_Scene.Permissions.CanCreateUserInventory(invType, remoteClient.AgentId))
181 return; 181 return;
@@ -210,13 +210,13 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
210 else 210 else
211 { 211 {
212 m_log.ErrorFormat( 212 m_log.ErrorFormat(
213 "ScenePresence for agent uuid {0} unexpectedly not found in CreateNewInventoryItem", 213 "[INVENTORY ACCESS MODULE]: ScenePresence for agent uuid {0} unexpectedly not found in CreateNewInventoryItem",
214 remoteClient.AgentId); 214 remoteClient.AgentId);
215 } 215 }
216 } 216 }
217 else 217 else
218 { 218 {
219 IAgentAssetTransactions agentTransactions = m_Scene.RequestModuleInterface<IAgentAssetTransactions>(); 219 IAgentAssetTransactions agentTransactions = m_Scene.AgentTransactionsModule;
220 if (agentTransactions != null) 220 if (agentTransactions != null)
221 { 221 {
222 agentTransactions.HandleItemCreationFromTransaction( 222 agentTransactions.HandleItemCreationFromTransaction(
@@ -288,16 +288,19 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
288 else 288 else
289 { 289 {
290 m_log.ErrorFormat( 290 m_log.ErrorFormat(
291 "[AGENT INVENTORY]: Could not find item {0} for caps inventory update", 291 "[INVENTORY ACCESS MODULE]: Could not find item {0} for caps inventory update",
292 itemID); 292 itemID);
293 } 293 }
294 294
295 return UUID.Zero; 295 return UUID.Zero;
296 } 296 }
297 297
298 public virtual UUID CopyToInventory(DeRezAction action, UUID folderID, 298 public virtual List<InventoryItemBase> CopyToInventory(
299 List<SceneObjectGroup> objectGroups, IClientAPI remoteClient) 299 DeRezAction action, UUID folderID,
300 List<SceneObjectGroup> objectGroups, IClientAPI remoteClient, bool asAttachment)
300 { 301 {
302 List<InventoryItemBase> copiedItems = new List<InventoryItemBase>();
303
301 Dictionary<UUID, List<SceneObjectGroup>> bundlesToCopy = new Dictionary<UUID, List<SceneObjectGroup>>(); 304 Dictionary<UUID, List<SceneObjectGroup>> bundlesToCopy = new Dictionary<UUID, List<SceneObjectGroup>>();
302 305
303 if (CoalesceMultipleObjectsToInventory) 306 if (CoalesceMultipleObjectsToInventory)
@@ -324,16 +327,16 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
324 } 327 }
325 } 328 }
326 329
327 // This is method scoped and will be returned. It will be the 330// m_log.DebugFormat(
328 // last created asset id 331// "[INVENTORY ACCESS MODULE]: Copying {0} object bundles to folder {1} action {2} for {3}",
329 UUID assetID = UUID.Zero; 332// bundlesToCopy.Count, folderID, action, remoteClient.Name);
330 333
331 // Each iteration is really a separate asset being created, 334 // Each iteration is really a separate asset being created,
332 // with distinct destinations as well. 335 // with distinct destinations as well.
333 foreach (List<SceneObjectGroup> bundle in bundlesToCopy.Values) 336 foreach (List<SceneObjectGroup> bundle in bundlesToCopy.Values)
334 assetID = CopyBundleToInventory(action, folderID, bundle, remoteClient); 337 copiedItems.Add(CopyBundleToInventory(action, folderID, bundle, remoteClient, asAttachment));
335 338
336 return assetID; 339 return copiedItems;
337 } 340 }
338 341
339 /// <summary> 342 /// <summary>
@@ -344,12 +347,13 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
344 /// <param name="folderID"></param> 347 /// <param name="folderID"></param>
345 /// <param name="objlist"></param> 348 /// <param name="objlist"></param>
346 /// <param name="remoteClient"></param> 349 /// <param name="remoteClient"></param>
347 /// <returns></returns> 350 /// <param name="asAttachment">Should be true if the bundle is being copied as an attachment. This prevents
348 protected UUID CopyBundleToInventory( 351 /// attempted serialization of any script state which would abort any operating scripts.</param>
349 DeRezAction action, UUID folderID, List<SceneObjectGroup> objlist, IClientAPI remoteClient) 352 /// <returns>The inventory item created by the copy</returns>
353 protected InventoryItemBase CopyBundleToInventory(
354 DeRezAction action, UUID folderID, List<SceneObjectGroup> objlist, IClientAPI remoteClient,
355 bool asAttachment)
350 { 356 {
351 UUID assetID = UUID.Zero;
352
353 CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero); 357 CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero);
354 Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>(); 358 Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>();
355 359
@@ -401,18 +405,27 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
401 405
402 string itemXml; 406 string itemXml;
403 407
408 // If we're being called from a script, then trying to serialize that same script's state will not complete
409 // in any reasonable time period. Therefore, we'll avoid it. The worst that can happen is that if
410 // the client/server crashes rather than logging out normally, the attachment's scripts will resume
411 // without state on relog. Arguably, this is what we want anyway.
404 if (objlist.Count > 1) 412 if (objlist.Count > 1)
405 itemXml = CoalescedSceneObjectsSerializer.ToXml(coa); 413 itemXml = CoalescedSceneObjectsSerializer.ToXml(coa, !asAttachment);
406 else 414 else
407 itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0]); 415 itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0], !asAttachment);
408 416
409 // Restore the position of each group now that it has been stored to inventory. 417 // Restore the position of each group now that it has been stored to inventory.
410 foreach (SceneObjectGroup objectGroup in objlist) 418 foreach (SceneObjectGroup objectGroup in objlist)
411 objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID]; 419 objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID];
412 420
413 InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID); 421 InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID);
422
423// m_log.DebugFormat(
424// "[INVENTORY ACCESS MODULE]: Created item is {0}",
425// item != null ? item.ID.ToString() : "NULL");
426
414 if (item == null) 427 if (item == null)
415 return UUID.Zero; 428 return null;
416 429
417 // Can't know creator is the same, so null it in inventory 430 // Can't know creator is the same, so null it in inventory
418 if (objlist.Count > 1) 431 if (objlist.Count > 1)
@@ -422,7 +435,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
422 } 435 }
423 else 436 else
424 { 437 {
425 item.CreatorId = objlist[0].RootPart.CreatorID.ToString(); 438 item.CreatorId = objlist[0].RootPart.CreatorID.ToString();
439 item.CreatorData = objlist[0].RootPart.CreatorData;
426 item.SaleType = objlist[0].RootPart.ObjectSaleType; 440 item.SaleType = objlist[0].RootPart.ObjectSaleType;
427 item.SalePrice = objlist[0].RootPart.SalePrice; 441 item.SalePrice = objlist[0].RootPart.SalePrice;
428 } 442 }
@@ -435,8 +449,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
435 objlist[0].OwnerID.ToString()); 449 objlist[0].OwnerID.ToString());
436 m_Scene.AssetService.Store(asset); 450 m_Scene.AssetService.Store(asset);
437 451
438 item.AssetID = asset.FullID; 452 item.AssetID = asset.FullID;
439 assetID = asset.FullID;
440 453
441 if (DeRezAction.SaveToExistingUserInventoryItem == action) 454 if (DeRezAction.SaveToExistingUserInventoryItem == action)
442 { 455 {
@@ -469,9 +482,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
469 482
470 // This is a hook to do some per-asset post-processing for subclasses that need that 483 // This is a hook to do some per-asset post-processing for subclasses that need that
471 if (remoteClient != null) 484 if (remoteClient != null)
472 ExportAsset(remoteClient.AgentId, assetID); 485 ExportAsset(remoteClient.AgentId, asset.FullID);
473 486
474 return assetID; 487 return item;
475 } 488 }
476 489
477 protected virtual void ExportAsset(UUID agentID, UUID assetID) 490 protected virtual void ExportAsset(UUID agentID, UUID assetID)
@@ -617,7 +630,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
617 if (null == item) 630 if (null == item)
618 { 631 {
619 m_log.DebugFormat( 632 m_log.DebugFormat(
620 "[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.", 633 "[INVENTORY ACCESS MODULE]: Object {0} {1} scheduled for save to inventory has already been deleted.",
621 so.Name, so.UUID); 634 so.Name, so.UUID);
622 635
623 return null; 636 return null;
@@ -668,7 +681,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
668 { 681 {
669 // Catch all. Use lost & found 682 // Catch all. Use lost & found
670 // 683 //
671
672 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); 684 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
673 } 685 }
674 } 686 }
@@ -718,7 +730,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
718 730
719 if (item == null) 731 if (item == null)
720 { 732 {
721
722 return null; 733 return null;
723 } 734 }
724 735
@@ -748,7 +759,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
748 else 759 else
749 { 760 {
750 m_log.WarnFormat( 761 m_log.WarnFormat(
751 "[InventoryAccessModule]: Could not find asset {0} for {1} in RezObject()", 762 "[INVENTORY ACCESS MODULE]: Could not find asset {0} for {1} in RezObject()",
752 assetID, remoteClient.Name); 763 assetID, remoteClient.Name);
753 } 764 }
754 765
@@ -859,7 +870,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
859 SceneObjectPart rootPart = group.RootPart; 870 SceneObjectPart rootPart = group.RootPart;
860 871
861// m_log.DebugFormat( 872// m_log.DebugFormat(
862// "[InventoryAccessModule]: Preparing to rez {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}", 873// "[INVENTORY ACCESS MODULE]: Preparing to rez {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}",
863// group.Name, group.LocalId, group.UUID, 874// group.Name, group.LocalId, group.UUID,
864// group.RootPart.OwnerMask, group.RootPart.NextOwnerMask, group.RootPart.GroupMask, group.RootPart.EveryoneMask, 875// group.RootPart.OwnerMask, group.RootPart.NextOwnerMask, group.RootPart.GroupMask, group.RootPart.EveryoneMask,
865// remoteClient.Name); 876// remoteClient.Name);
@@ -867,7 +878,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
867// Vector3 storedPosition = group.AbsolutePosition; 878// Vector3 storedPosition = group.AbsolutePosition;
868 if (group.UUID == UUID.Zero) 879 if (group.UUID == UUID.Zero)
869 { 880 {
870 m_log.Debug("[InventoryAccessModule]: Object has UUID.Zero! Position 3"); 881 m_log.Debug("[INVENTORY ACCESS MODULE]: Object has UUID.Zero! Position 3");
871 } 882 }
872 883
873 foreach (SceneObjectPart part in group.Parts) 884 foreach (SceneObjectPart part in group.Parts)
@@ -928,7 +939,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
928 } 939 }
929 940
930// m_log.DebugFormat( 941// m_log.DebugFormat(
931// "[InventoryAccessModule]: Rezzed {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}", 942// "[INVENTORY ACCESS MODULE]: Rezzed {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}",
932// group.Name, group.LocalId, group.UUID, 943// group.Name, group.LocalId, group.UUID,
933// group.RootPart.OwnerMask, group.RootPart.NextOwnerMask, group.RootPart.GroupMask, group.RootPart.EveryoneMask, 944// group.RootPart.OwnerMask, group.RootPart.NextOwnerMask, group.RootPart.GroupMask, group.RootPart.EveryoneMask,
934// remoteClient.Name); 945// remoteClient.Name);
@@ -1023,8 +1034,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
1023 1034
1024 so.FromFolderID = item.Folder; 1035 so.FromFolderID = item.Folder;
1025 1036
1026// Console.WriteLine("rootPart.OwnedID {0}, item.Owner {1}, item.CurrentPermissions {2:X}", 1037// m_log.DebugFormat(
1027// rootPart.OwnerID, item.Owner, item.CurrentPermissions); 1038// "[INVENTORY ACCESS MODULE]: rootPart.OwnedID {0}, item.Owner {1}, item.CurrentPermissions {2:X}",
1039// rootPart.OwnerID, item.Owner, item.CurrentPermissions);
1028 1040
1029 if ((rootPart.OwnerID != item.Owner) || 1041 if ((rootPart.OwnerID != item.Owner) ||
1030 (item.CurrentPermissions & 16) != 0 || 1042 (item.CurrentPermissions & 16) != 0 ||
@@ -1160,7 +1172,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
1160 if (assetRequestItem.AssetID != requestID) 1172 if (assetRequestItem.AssetID != requestID)
1161 { 1173 {
1162 m_log.WarnFormat( 1174 m_log.WarnFormat(
1163 "[CLIENT]: {0} requested asset {1} from item {2} but this does not match item's asset {3}", 1175 "[INVENTORY ACCESS MODULE]: {0} requested asset {1} from item {2} but this does not match item's asset {3}",
1164 Name, requestID, itemID, assetRequestItem.AssetID); 1176 Name, requestID, itemID, assetRequestItem.AssetID);
1165 1177
1166 return false; 1178 return false;
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs
index e74310c..21d8bd7 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs
@@ -64,8 +64,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests
64 IConfigSource config = new IniConfigSource(); 64 IConfigSource config = new IniConfigSource();
65 config.AddConfig("Modules"); 65 config.AddConfig("Modules");
66 config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule"); 66 config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule");
67 67
68 m_scene = SceneHelpers.SetupScene(); 68 SceneHelpers sceneHelpers = new SceneHelpers();
69 m_scene = sceneHelpers.SetupScene();
69 SceneHelpers.SetupSceneModules(m_scene, config, m_iam); 70 SceneHelpers.SetupSceneModules(m_scene, config, m_iam);
70 71
71 // Create user 72 // Create user
@@ -76,7 +77,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests
76 77
77 AgentCircuitData acd = new AgentCircuitData(); 78 AgentCircuitData acd = new AgentCircuitData();
78 acd.AgentID = m_userId; 79 acd.AgentID = m_userId;
79 m_tc = new TestClient(acd, m_scene); 80 m_tc = new TestClient(acd, m_scene);
80 } 81 }
81 82
82 [Test] 83 [Test]
diff --git a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs
index 7f8271d..e135c21 100644
--- a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs
@@ -49,7 +49,16 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
49 public bool Enabled { get; private set; } 49 public bool Enabled { get; private set; }
50 50
51 private Scene m_scene; 51 private Scene m_scene;
52 private readonly List<IMonitor> m_monitors = new List<IMonitor>(); 52
53 /// <summary>
54 /// These are monitors where we know the static details in advance.
55 /// </summary>
56 /// <remarks>
57 /// Dynamic monitors also exist (we don't know any of the details of what stats we get back here)
58 /// but these are currently hardcoded.
59 /// </remarks>
60 private readonly List<IMonitor> m_staticMonitors = new List<IMonitor>();
61
53 private readonly List<IAlert> m_alerts = new List<IAlert>(); 62 private readonly List<IAlert> m_alerts = new List<IAlert>();
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 63 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 64
@@ -84,9 +93,18 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
84 93
85 public void DebugMonitors(string module, string[] args) 94 public void DebugMonitors(string module, string[] args)
86 { 95 {
87 foreach (IMonitor monitor in m_monitors) 96 foreach (IMonitor monitor in m_staticMonitors)
88 { 97 {
89 m_log.Info("[MonitorModule]: " + m_scene.RegionInfo.RegionName + " reports " + monitor.GetFriendlyName() + " = " + monitor.GetFriendlyValue()); 98 m_log.InfoFormat(
99 "[MONITOR MODULE]: {0} reports {1} = {2}",
100 m_scene.RegionInfo.RegionName, monitor.GetFriendlyName(), monitor.GetFriendlyValue());
101 }
102
103 foreach (KeyValuePair<string, float> tuple in m_scene.StatsReporter.GetExtraSimStats())
104 {
105 m_log.InfoFormat(
106 "[MONITOR MODULE]: {0} reports {1} = {2}",
107 m_scene.RegionInfo.RegionName, tuple.Key, tuple.Value);
90 } 108 }
91 } 109 }
92 110
@@ -106,11 +124,12 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
106 { 124 {
107 string monID = (string) request["monitor"]; 125 string monID = (string) request["monitor"];
108 126
109 foreach (IMonitor monitor in m_monitors) 127 foreach (IMonitor monitor in m_staticMonitors)
110 { 128 {
111 string elemName = monitor.ToString(); 129 string elemName = monitor.ToString();
112 if (elemName.StartsWith(monitor.GetType().Namespace)) 130 if (elemName.StartsWith(monitor.GetType().Namespace))
113 elemName = elemName.Substring(monitor.GetType().Namespace.Length + 1); 131 elemName = elemName.Substring(monitor.GetType().Namespace.Length + 1);
132
114 if (elemName == monID || monitor.ToString() == monID) 133 if (elemName == monID || monitor.ToString() == monID)
115 { 134 {
116 Hashtable ereply3 = new Hashtable(); 135 Hashtable ereply3 = new Hashtable();
@@ -123,6 +142,9 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
123 } 142 }
124 } 143 }
125 144
145 // FIXME: Arguably this should also be done with dynamic monitors but I'm not sure what the above code
146 // is even doing. Why are we inspecting the type of the monitor???
147
126 // No monitor with that name 148 // No monitor with that name
127 Hashtable ereply2 = new Hashtable(); 149 Hashtable ereply2 = new Hashtable();
128 150
@@ -134,12 +156,18 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
134 } 156 }
135 157
136 string xml = "<data>"; 158 string xml = "<data>";
137 foreach (IMonitor monitor in m_monitors) 159 foreach (IMonitor monitor in m_staticMonitors)
138 { 160 {
139 string elemName = monitor.GetName(); 161 string elemName = monitor.GetName();
140 xml += "<" + elemName + ">" + monitor.GetValue().ToString() + "</" + elemName + ">"; 162 xml += "<" + elemName + ">" + monitor.GetValue().ToString() + "</" + elemName + ">";
141// m_log.DebugFormat("[MONITOR MODULE]: {0} = {1}", elemName, monitor.GetValue()); 163// m_log.DebugFormat("[MONITOR MODULE]: {0} = {1}", elemName, monitor.GetValue());
142 } 164 }
165
166 foreach (KeyValuePair<string, float> tuple in m_scene.StatsReporter.GetExtraSimStats())
167 {
168 xml += "<" + tuple.Key + ">" + tuple.Value + "</" + tuple.Key + ">";
169 }
170
143 xml += "</data>"; 171 xml += "</data>";
144 172
145 Hashtable ereply = new Hashtable(); 173 Hashtable ereply = new Hashtable();
@@ -156,20 +184,20 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
156 if (!Enabled) 184 if (!Enabled)
157 return; 185 return;
158 186
159 m_monitors.Add(new AgentCountMonitor(m_scene)); 187 m_staticMonitors.Add(new AgentCountMonitor(m_scene));
160 m_monitors.Add(new ChildAgentCountMonitor(m_scene)); 188 m_staticMonitors.Add(new ChildAgentCountMonitor(m_scene));
161 m_monitors.Add(new GCMemoryMonitor()); 189 m_staticMonitors.Add(new GCMemoryMonitor());
162 m_monitors.Add(new ObjectCountMonitor(m_scene)); 190 m_staticMonitors.Add(new ObjectCountMonitor(m_scene));
163 m_monitors.Add(new PhysicsFrameMonitor(m_scene)); 191 m_staticMonitors.Add(new PhysicsFrameMonitor(m_scene));
164 m_monitors.Add(new PhysicsUpdateFrameMonitor(m_scene)); 192 m_staticMonitors.Add(new PhysicsUpdateFrameMonitor(m_scene));
165 m_monitors.Add(new PWSMemoryMonitor()); 193 m_staticMonitors.Add(new PWSMemoryMonitor());
166 m_monitors.Add(new ThreadCountMonitor()); 194 m_staticMonitors.Add(new ThreadCountMonitor());
167 m_monitors.Add(new TotalFrameMonitor(m_scene)); 195 m_staticMonitors.Add(new TotalFrameMonitor(m_scene));
168 m_monitors.Add(new EventFrameMonitor(m_scene)); 196 m_staticMonitors.Add(new EventFrameMonitor(m_scene));
169 m_monitors.Add(new LandFrameMonitor(m_scene)); 197 m_staticMonitors.Add(new LandFrameMonitor(m_scene));
170 m_monitors.Add(new LastFrameTimeMonitor(m_scene)); 198 m_staticMonitors.Add(new LastFrameTimeMonitor(m_scene));
171 199
172 m_monitors.Add( 200 m_staticMonitors.Add(
173 new GenericMonitor( 201 new GenericMonitor(
174 m_scene, 202 m_scene,
175 "TimeDilationMonitor", 203 "TimeDilationMonitor",
@@ -177,7 +205,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
177 m => m.Scene.StatsReporter.LastReportedSimStats[0], 205 m => m.Scene.StatsReporter.LastReportedSimStats[0],
178 m => m.GetValue().ToString())); 206 m => m.GetValue().ToString()));
179 207
180 m_monitors.Add( 208 m_staticMonitors.Add(
181 new GenericMonitor( 209 new GenericMonitor(
182 m_scene, 210 m_scene,
183 "SimFPSMonitor", 211 "SimFPSMonitor",
@@ -185,7 +213,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
185 m => m.Scene.StatsReporter.LastReportedSimStats[1], 213 m => m.Scene.StatsReporter.LastReportedSimStats[1],
186 m => string.Format("{0}", m.GetValue()))); 214 m => string.Format("{0}", m.GetValue())));
187 215
188 m_monitors.Add( 216 m_staticMonitors.Add(
189 new GenericMonitor( 217 new GenericMonitor(
190 m_scene, 218 m_scene,
191 "PhysicsFPSMonitor", 219 "PhysicsFPSMonitor",
@@ -193,7 +221,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
193 m => m.Scene.StatsReporter.LastReportedSimStats[2], 221 m => m.Scene.StatsReporter.LastReportedSimStats[2],
194 m => string.Format("{0}", m.GetValue()))); 222 m => string.Format("{0}", m.GetValue())));
195 223
196 m_monitors.Add( 224 m_staticMonitors.Add(
197 new GenericMonitor( 225 new GenericMonitor(
198 m_scene, 226 m_scene,
199 "AgentUpdatesPerSecondMonitor", 227 "AgentUpdatesPerSecondMonitor",
@@ -201,15 +229,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
201 m => m.Scene.StatsReporter.LastReportedSimStats[3], 229 m => m.Scene.StatsReporter.LastReportedSimStats[3],
202 m => string.Format("{0} per second", m.GetValue()))); 230 m => string.Format("{0} per second", m.GetValue())));
203 231
204 m_monitors.Add( 232 m_staticMonitors.Add(
205 new GenericMonitor(
206 m_scene,
207 "ObjectUpdatesPerSecondMonitor",
208 "Object Updates",
209 m => m.Scene.StatsReporter.LastReportedObjectUpdates,
210 m => string.Format("{0} per second", m.GetValue())));
211
212 m_monitors.Add(
213 new GenericMonitor( 233 new GenericMonitor(
214 m_scene, 234 m_scene,
215 "ActiveObjectCountMonitor", 235 "ActiveObjectCountMonitor",
@@ -217,7 +237,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
217 m => m.Scene.StatsReporter.LastReportedSimStats[7], 237 m => m.Scene.StatsReporter.LastReportedSimStats[7],
218 m => string.Format("{0}", m.GetValue()))); 238 m => string.Format("{0}", m.GetValue())));
219 239
220 m_monitors.Add( 240 m_staticMonitors.Add(
221 new GenericMonitor( 241 new GenericMonitor(
222 m_scene, 242 m_scene,
223 "ActiveScriptsMonitor", 243 "ActiveScriptsMonitor",
@@ -225,7 +245,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
225 m => m.Scene.StatsReporter.LastReportedSimStats[19], 245 m => m.Scene.StatsReporter.LastReportedSimStats[19],
226 m => string.Format("{0}", m.GetValue()))); 246 m => string.Format("{0}", m.GetValue())));
227 247
228 m_monitors.Add( 248 m_staticMonitors.Add(
229 new GenericMonitor( 249 new GenericMonitor(
230 m_scene, 250 m_scene,
231 "ScriptEventsPerSecondMonitor", 251 "ScriptEventsPerSecondMonitor",
@@ -233,7 +253,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
233 m => m.Scene.StatsReporter.LastReportedSimStats[20], 253 m => m.Scene.StatsReporter.LastReportedSimStats[20],
234 m => string.Format("{0} per second", m.GetValue()))); 254 m => string.Format("{0} per second", m.GetValue())));
235 255
236 m_monitors.Add( 256 m_staticMonitors.Add(
237 new GenericMonitor( 257 new GenericMonitor(
238 m_scene, 258 m_scene,
239 "InPacketsPerSecondMonitor", 259 "InPacketsPerSecondMonitor",
@@ -241,7 +261,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
241 m => m.Scene.StatsReporter.LastReportedSimStats[13], 261 m => m.Scene.StatsReporter.LastReportedSimStats[13],
242 m => string.Format("{0} per second", m.GetValue()))); 262 m => string.Format("{0} per second", m.GetValue())));
243 263
244 m_monitors.Add( 264 m_staticMonitors.Add(
245 new GenericMonitor( 265 new GenericMonitor(
246 m_scene, 266 m_scene,
247 "OutPacketsPerSecondMonitor", 267 "OutPacketsPerSecondMonitor",
@@ -249,7 +269,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
249 m => m.Scene.StatsReporter.LastReportedSimStats[14], 269 m => m.Scene.StatsReporter.LastReportedSimStats[14],
250 m => string.Format("{0} per second", m.GetValue()))); 270 m => string.Format("{0} per second", m.GetValue())));
251 271
252 m_monitors.Add( 272 m_staticMonitors.Add(
253 new GenericMonitor( 273 new GenericMonitor(
254 m_scene, 274 m_scene,
255 "UnackedBytesMonitor", 275 "UnackedBytesMonitor",
@@ -257,7 +277,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
257 m => m.Scene.StatsReporter.LastReportedSimStats[15], 277 m => m.Scene.StatsReporter.LastReportedSimStats[15],
258 m => string.Format("{0}", m.GetValue()))); 278 m => string.Format("{0}", m.GetValue())));
259 279
260 m_monitors.Add( 280 m_staticMonitors.Add(
261 new GenericMonitor( 281 new GenericMonitor(
262 m_scene, 282 m_scene,
263 "PendingDownloadsMonitor", 283 "PendingDownloadsMonitor",
@@ -265,7 +285,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
265 m => m.Scene.StatsReporter.LastReportedSimStats[17], 285 m => m.Scene.StatsReporter.LastReportedSimStats[17],
266 m => string.Format("{0}", m.GetValue()))); 286 m => string.Format("{0}", m.GetValue())));
267 287
268 m_monitors.Add( 288 m_staticMonitors.Add(
269 new GenericMonitor( 289 new GenericMonitor(
270 m_scene, 290 m_scene,
271 "PendingUploadsMonitor", 291 "PendingUploadsMonitor",
@@ -273,7 +293,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
273 m => m.Scene.StatsReporter.LastReportedSimStats[18], 293 m => m.Scene.StatsReporter.LastReportedSimStats[18],
274 m => string.Format("{0}", m.GetValue()))); 294 m => string.Format("{0}", m.GetValue())));
275 295
276 m_monitors.Add( 296 m_staticMonitors.Add(
277 new GenericMonitor( 297 new GenericMonitor(
278 m_scene, 298 m_scene,
279 "TotalFrameTimeMonitor", 299 "TotalFrameTimeMonitor",
@@ -281,7 +301,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
281 m => m.Scene.StatsReporter.LastReportedSimStats[8], 301 m => m.Scene.StatsReporter.LastReportedSimStats[8],
282 m => string.Format("{0} ms", m.GetValue()))); 302 m => string.Format("{0} ms", m.GetValue())));
283 303
284 m_monitors.Add( 304 m_staticMonitors.Add(
285 new GenericMonitor( 305 new GenericMonitor(
286 m_scene, 306 m_scene,
287 "NetFrameTimeMonitor", 307 "NetFrameTimeMonitor",
@@ -289,7 +309,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
289 m => m.Scene.StatsReporter.LastReportedSimStats[9], 309 m => m.Scene.StatsReporter.LastReportedSimStats[9],
290 m => string.Format("{0} ms", m.GetValue()))); 310 m => string.Format("{0} ms", m.GetValue())));
291 311
292 m_monitors.Add( 312 m_staticMonitors.Add(
293 new GenericMonitor( 313 new GenericMonitor(
294 m_scene, 314 m_scene,
295 "PhysicsFrameTimeMonitor", 315 "PhysicsFrameTimeMonitor",
@@ -297,7 +317,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
297 m => m.Scene.StatsReporter.LastReportedSimStats[10], 317 m => m.Scene.StatsReporter.LastReportedSimStats[10],
298 m => string.Format("{0} ms", m.GetValue()))); 318 m => string.Format("{0} ms", m.GetValue())));
299 319
300 m_monitors.Add( 320 m_staticMonitors.Add(
301 new GenericMonitor( 321 new GenericMonitor(
302 m_scene, 322 m_scene,
303 "SimulationFrameTimeMonitor", 323 "SimulationFrameTimeMonitor",
@@ -305,7 +325,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
305 m => m.Scene.StatsReporter.LastReportedSimStats[12], 325 m => m.Scene.StatsReporter.LastReportedSimStats[12],
306 m => string.Format("{0} ms", m.GetValue()))); 326 m => string.Format("{0} ms", m.GetValue())));
307 327
308 m_monitors.Add( 328 m_staticMonitors.Add(
309 new GenericMonitor( 329 new GenericMonitor(
310 m_scene, 330 m_scene,
311 "AgentFrameTimeMonitor", 331 "AgentFrameTimeMonitor",
@@ -313,7 +333,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
313 m => m.Scene.StatsReporter.LastReportedSimStats[16], 333 m => m.Scene.StatsReporter.LastReportedSimStats[16],
314 m => string.Format("{0} ms", m.GetValue()))); 334 m => string.Format("{0} ms", m.GetValue())));
315 335
316 m_monitors.Add( 336 m_staticMonitors.Add(
317 new GenericMonitor( 337 new GenericMonitor(
318 m_scene, 338 m_scene,
319 "ImagesFrameTimeMonitor", 339 "ImagesFrameTimeMonitor",
@@ -321,7 +341,15 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
321 m => m.Scene.StatsReporter.LastReportedSimStats[11], 341 m => m.Scene.StatsReporter.LastReportedSimStats[11],
322 m => string.Format("{0} ms", m.GetValue()))); 342 m => string.Format("{0} ms", m.GetValue())));
323 343
324 m_alerts.Add(new DeadlockAlert(m_monitors.Find(x => x is LastFrameTimeMonitor) as LastFrameTimeMonitor)); 344 m_staticMonitors.Add(
345 new GenericMonitor(
346 m_scene,
347 "SpareFrameTimeMonitor",
348 "Spare Frame Time",
349 m => m.Scene.StatsReporter.LastReportedSimStats[21],
350 m => string.Format("{0} ms", m.GetValue())));
351
352 m_alerts.Add(new DeadlockAlert(m_staticMonitors.Find(x => x is LastFrameTimeMonitor) as LastFrameTimeMonitor));
325 353
326 foreach (IAlert alert in m_alerts) 354 foreach (IAlert alert in m_alerts)
327 { 355 {
diff --git a/OpenSim/Region/CoreModules/LightShare/EnvironmentModule.cs b/OpenSim/Region/CoreModules/LightShare/EnvironmentModule.cs
new file mode 100644
index 0000000..1526886
--- /dev/null
+++ b/OpenSim/Region/CoreModules/LightShare/EnvironmentModule.cs
@@ -0,0 +1,224 @@
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 OpenMetaverse;
31using OpenSim.Framework;
32using OpenSim.Framework.Capabilities;
33using OpenSim.Framework.Servers.HttpServer;
34using OpenSim.Region.Framework.Interfaces;
35using OpenSim.Region.Framework.Scenes;
36using log4net;
37using Nini.Config;
38using Mono.Addins;
39
40using Caps = OpenSim.Framework.Capabilities.Caps;
41
42
43namespace OpenSim.Region.CoreModules.World.LightShare
44{
45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "EnvironmentModule")]
46
47 public class EnvironmentModule : INonSharedRegionModule, IEnvironmentModule
48 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50
51 private Scene m_scene = null;
52 private UUID regionID = UUID.Zero;
53 private static bool Enabled = false;
54
55 private static readonly string capsName = "EnvironmentSettings";
56 private static readonly string capsBase = "/CAPS/0020/";
57
58 private LLSDEnvironmentSetResponse setResponse = null;
59
60 #region INonSharedRegionModule
61 public void Initialise(IConfigSource source)
62 {
63 IConfig config = source.Configs["ClientStack.LindenCaps"];
64
65 if (null == config)
66 return;
67
68 if (config.GetString("Cap_EnvironmentSettings", String.Empty) != "localhost")
69 {
70 m_log.InfoFormat("[{0}]: Module is disabled.", Name);
71 return;
72 }
73
74 Enabled = true;
75
76 m_log.InfoFormat("[{0}]: Module is enabled.", Name);
77 }
78
79 public void Close()
80 {
81 }
82
83 public string Name
84 {
85 get { return "EnvironmentModule"; }
86 }
87
88 public Type ReplaceableInterface
89 {
90 get { return null; }
91 }
92
93 public void AddRegion(Scene scene)
94 {
95 if (!Enabled)
96 return;
97
98 scene.RegisterModuleInterface<IEnvironmentModule>(this);
99 m_scene = scene;
100 regionID = scene.RegionInfo.RegionID;
101 }
102
103 public void RegionLoaded(Scene scene)
104 {
105 if (!Enabled)
106 return;
107
108 setResponse = new LLSDEnvironmentSetResponse();
109 scene.EventManager.OnRegisterCaps += OnRegisterCaps;
110 }
111
112 public void RemoveRegion(Scene scene)
113 {
114 if (Enabled)
115 return;
116
117 scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
118 m_scene = null;
119 }
120 #endregion
121
122 #region IEnvironmentModule
123 public void ResetEnvironmentSettings(UUID regionUUID)
124 {
125 if (!Enabled)
126 return;
127
128 m_scene.SimulationDataService.RemoveRegionEnvironmentSettings(regionUUID);
129 }
130 #endregion
131
132 #region Events
133 private void OnRegisterCaps(UUID agentID, Caps caps)
134 {
135// m_log.DebugFormat("[{0}]: Register capability for agentID {1} in region {2}",
136// Name, agentID, caps.RegionName);
137
138 string capsPath = capsBase + UUID.Random();
139
140 // Get handler
141 caps.RegisterHandler(
142 capsName,
143 new RestStreamHandler(
144 "GET",
145 capsPath,
146 (request, path, param, httpRequest, httpResponse)
147 => GetEnvironmentSettings(request, path, param, agentID, caps),
148 capsName,
149 agentID.ToString()));
150
151 // Set handler
152 caps.HttpListener.AddStreamHandler(
153 new RestStreamHandler(
154 "POST",
155 capsPath,
156 (request, path, param, httpRequest, httpResponse)
157 => SetEnvironmentSettings(request, path, param, agentID, caps),
158 capsName,
159 agentID.ToString()));
160 }
161 #endregion
162
163 private string GetEnvironmentSettings(string request, string path, string param,
164 UUID agentID, Caps caps)
165 {
166// m_log.DebugFormat("[{0}]: Environment GET handle for agentID {1} in region {2}",
167// Name, agentID, caps.RegionName);
168
169 string env = String.Empty;
170
171 try
172 {
173 env = m_scene.SimulationDataService.LoadRegionEnvironmentSettings(regionID);
174 }
175 catch (Exception e)
176 {
177 m_log.ErrorFormat("[{0}]: Unable to load environment settings for region {1}, Exception: {2} - {3}",
178 Name, caps.RegionName, e.Message, e.StackTrace);
179 }
180
181 if (String.IsNullOrEmpty(env))
182 env = EnvironmentSettings.EmptySettings(UUID.Zero, regionID);
183
184 return env;
185 }
186
187 private string SetEnvironmentSettings(string request, string path, string param,
188 UUID agentID, Caps caps)
189 {
190
191// m_log.DebugFormat("[{0}]: Environment SET handle from agentID {1} in region {2}",
192// Name, agentID, caps.RegionName);
193
194 setResponse.regionID = regionID;
195 setResponse.success = false;
196
197 if (!m_scene.Permissions.CanIssueEstateCommand(agentID, false))
198 {
199 setResponse.fail_reason = "Insufficient estate permissions, settings has not been saved.";
200 return LLSDHelpers.SerialiseLLSDReply(setResponse);
201 }
202
203 try
204 {
205 m_scene.SimulationDataService.StoreRegionEnvironmentSettings(regionID, request);
206 setResponse.success = true;
207
208 m_log.InfoFormat("[{0}]: New Environment settings has been saved from agentID {1} in region {2}",
209 Name, agentID, caps.RegionName);
210 }
211 catch (Exception e)
212 {
213 m_log.ErrorFormat("[{0}]: Environment settings has not been saved for region {1}, Exception: {2} - {3}",
214 Name, caps.RegionName, e.Message, e.StackTrace);
215
216 setResponse.success = false;
217 setResponse.fail_reason = String.Format("Environment Set for region {0} has failed, settings has not been saved.", caps.RegionName);
218 }
219
220 return LLSDHelpers.SerialiseLLSDReply(setResponse);
221 }
222 }
223}
224
diff --git a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml
index dc6efed..424e0ab 100644
--- a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml
+++ b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml
@@ -79,7 +79,6 @@
79 <RegionModule id="AuthenticationServiceInConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsIn.Authentication.AuthenticationServiceInConnectorModule" /> 79 <RegionModule id="AuthenticationServiceInConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsIn.Authentication.AuthenticationServiceInConnectorModule" />
80 <RegionModule id="AccessModule" type="OpenSim.Region.CoreModules.World.AccessModule" /> \ 80 <RegionModule id="AccessModule" type="OpenSim.Region.CoreModules.World.AccessModule" /> \
81 <RegionModule id="MapImageModule" type="OpenSim.Region.CoreModules.World.LegacyMap.MapImageModule" /> \ 81 <RegionModule id="MapImageModule" type="OpenSim.Region.CoreModules.World.LegacyMap.MapImageModule" /> \
82 <RegionModule id="Warp3DImageModule" type="OpenSim.Region.CoreModules.World.Warp3DMap.Warp3DImageModule" /> \
83 82
84 </Extension> 83 </Extension>
85 84
diff --git a/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs
index 9255791..e91e8b9 100644
--- a/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs
@@ -64,6 +64,8 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
64 private TimeSpan m_QueueTimeout = new TimeSpan(2, 0, 0); // 2 hours without llGetNextEmail drops the queue 64 private TimeSpan m_QueueTimeout = new TimeSpan(2, 0, 0); // 2 hours without llGetNextEmail drops the queue
65 private string m_InterObjectHostname = "lsl.opensim.local"; 65 private string m_InterObjectHostname = "lsl.opensim.local";
66 66
67 private int m_MaxEmailSize = 4096; // largest email allowed by default, as per lsl docs.
68
67 // Scenes by Region Handle 69 // Scenes by Region Handle
68 private Dictionary<ulong, Scene> m_Scenes = 70 private Dictionary<ulong, Scene> m_Scenes =
69 new Dictionary<ulong, Scene>(); 71 new Dictionary<ulong, Scene>();
@@ -127,6 +129,7 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
127 SMTP_SERVER_PORT = SMTPConfig.GetInt("SMTP_SERVER_PORT", SMTP_SERVER_PORT); 129 SMTP_SERVER_PORT = SMTPConfig.GetInt("SMTP_SERVER_PORT", SMTP_SERVER_PORT);
128 SMTP_SERVER_LOGIN = SMTPConfig.GetString("SMTP_SERVER_LOGIN", SMTP_SERVER_LOGIN); 130 SMTP_SERVER_LOGIN = SMTPConfig.GetString("SMTP_SERVER_LOGIN", SMTP_SERVER_LOGIN);
129 SMTP_SERVER_PASSWORD = SMTPConfig.GetString("SMTP_SERVER_PASSWORD", SMTP_SERVER_PASSWORD); 131 SMTP_SERVER_PASSWORD = SMTPConfig.GetString("SMTP_SERVER_PASSWORD", SMTP_SERVER_PASSWORD);
132 m_MaxEmailSize = SMTPConfig.GetInt("email_max_size", m_MaxEmailSize);
130 } 133 }
131 catch (Exception e) 134 catch (Exception e)
132 { 135 {
@@ -176,18 +179,6 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
176 get { return true; } 179 get { return true; }
177 } 180 }
178 181
179 /// <summary>
180 /// Delay function using thread in seconds
181 /// </summary>
182 /// <param name="seconds"></param>
183 private void DelayInSeconds(int delay)
184 {
185 delay = (int)((float)delay * 1000);
186 if (delay == 0)
187 return;
188 System.Threading.Thread.Sleep(delay);
189 }
190
191 private bool IsLocal(UUID objectID) 182 private bool IsLocal(UUID objectID)
192 { 183 {
193 string unused; 184 string unused;
@@ -267,10 +258,9 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
267 m_log.Error("[EMAIL] REGEX Problem in EMail Address: "+address); 258 m_log.Error("[EMAIL] REGEX Problem in EMail Address: "+address);
268 return; 259 return;
269 } 260 }
270 //FIXME:Check if subject + body = 4096 Byte 261 if ((subject.Length + body.Length) > m_MaxEmailSize)
271 if ((subject.Length + body.Length) > 1024)
272 { 262 {
273 m_log.Error("[EMAIL] subject + body > 1024 Byte"); 263 m_log.Error("[EMAIL] subject + body larger than limit of " + m_MaxEmailSize + " bytes");
274 return; 264 return;
275 } 265 }
276 266
@@ -345,10 +335,6 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
345 // TODO FIX 335 // TODO FIX
346 } 336 }
347 } 337 }
348
349 //DONE: Message as Second Life style
350 //20 second delay - AntiSpam System - for now only 10 seconds
351 DelayInSeconds(10);
352 } 338 }
353 339
354 /// <summary> 340 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
index dcf49a7..f4a89bd 100644
--- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
@@ -77,7 +77,9 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
77 private Dictionary<string, UrlData> m_UrlMap = 77 private Dictionary<string, UrlData> m_UrlMap =
78 new Dictionary<string, UrlData>(); 78 new Dictionary<string, UrlData>();
79 79
80 80 /// <summary>
81 /// Maximum number of external urls that can be set up by this module.
82 /// </summary>
81 private int m_TotalUrls = 5000; 83 private int m_TotalUrls = 5000;
82 84
83 private uint https_port = 0; 85 private uint https_port = 0;
@@ -85,6 +87,10 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
85 private IHttpServer m_HttpsServer = null; 87 private IHttpServer m_HttpsServer = null;
86 88
87 private string m_ExternalHostNameForLSL = ""; 89 private string m_ExternalHostNameForLSL = "";
90 public string ExternalHostNameForLSL
91 {
92 get { return m_ExternalHostNameForLSL; }
93 }
88 94
89 public Type ReplaceableInterface 95 public Type ReplaceableInterface
90 { 96 {
@@ -104,6 +110,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
104 { 110 {
105 https_port = (uint) config.Configs["Network"].GetInt("https_port",0); 111 https_port = (uint) config.Configs["Network"].GetInt("https_port",0);
106 } 112 }
113
114 IConfig llFunctionsConfig = config.Configs["LL-Functions"];
115
116 if (llFunctionsConfig != null)
117 m_TotalUrls = llFunctionsConfig.GetInt("max_external_urls_per_simulator", m_TotalUrls);
107 } 118 }
108 119
109 public void PostInitialise() 120 public void PostInitialise()
@@ -147,6 +158,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
147 public void Close() 158 public void Close()
148 { 159 {
149 } 160 }
161
150 public UUID RequestURL(IScriptModule engine, SceneObjectPart host, UUID itemID) 162 public UUID RequestURL(IScriptModule engine, SceneObjectPart host, UUID itemID)
151 { 163 {
152 UUID urlcode = UUID.Random(); 164 UUID urlcode = UUID.Random();
@@ -176,6 +188,10 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
176 args.Type = PollServiceEventArgs.EventType.LslHttp; 188 args.Type = PollServiceEventArgs.EventType.LslHttp;
177 m_HttpServer.AddPollServiceHTTPHandler(uri, args); 189 m_HttpServer.AddPollServiceHTTPHandler(uri, args);
178 190
191 m_log.DebugFormat(
192 "[URL MODULE]: Set up incoming request url {0} for {1} in {2} {3}",
193 uri, itemID, host.Name, host.LocalId);
194
179 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url }); 195 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url });
180 } 196 }
181 197
@@ -218,6 +234,10 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
218 args.Type = PollServiceEventArgs.EventType.LslHttp; 234 args.Type = PollServiceEventArgs.EventType.LslHttp;
219 m_HttpsServer.AddPollServiceHTTPHandler(uri, args); 235 m_HttpsServer.AddPollServiceHTTPHandler(uri, args);
220 236
237 m_log.DebugFormat(
238 "[URL MODULE]: Set up incoming secure request url {0} for {1} in {2} {3}",
239 uri, itemID, host.Name, host.LocalId);
240
221 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url }); 241 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url });
222 } 242 }
223 243
@@ -241,6 +261,10 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
241 m_RequestMap.Remove(req); 261 m_RequestMap.Remove(req);
242 } 262 }
243 263
264// m_log.DebugFormat(
265// "[URL MODULE]: Releasing url {0} for {1} in {2}",
266// url, data.itemID, data.hostID);
267
244 RemoveUrl(data); 268 RemoveUrl(data);
245 m_UrlMap.Remove(url); 269 m_UrlMap.Remove(url);
246 } 270 }
diff --git a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs
index 40ffcb4..0003af2 100644
--- a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs
@@ -131,11 +131,12 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC
131 { 131 {
132 // Start http server 132 // Start http server
133 // Attach xmlrpc handlers 133 // Attach xmlrpc handlers
134 m_log.Info("[XML RPC MODULE]: " + 134// m_log.InfoFormat(
135 "Starting up XMLRPC Server on port " + m_remoteDataPort + " for llRemoteData commands."); 135// "[XML RPC MODULE]: Starting up XMLRPC Server on port {0} for llRemoteData commands.",
136 BaseHttpServer httpServer = new BaseHttpServer((uint) m_remoteDataPort); 136// m_remoteDataPort);
137
138 IHttpServer httpServer = MainServer.GetHttpServer((uint)m_remoteDataPort);
137 httpServer.AddXmlRPCHandler("llRemoteData", XmlRpcRemoteData); 139 httpServer.AddXmlRPCHandler("llRemoteData", XmlRpcRemoteData);
138 httpServer.Start();
139 } 140 }
140 } 141 }
141 142
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs
index 8df1c7b..a7dd0dd 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs
@@ -122,7 +122,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Hypergrid
122 ISimulationService simService = scene.RequestModuleInterface<ISimulationService>(); 122 ISimulationService simService = scene.RequestModuleInterface<ISimulationService>();
123 IFriendsSimConnector friendsConn = scene.RequestModuleInterface<IFriendsSimConnector>(); 123 IFriendsSimConnector friendsConn = scene.RequestModuleInterface<IFriendsSimConnector>();
124 Object[] args = new Object[] { m_Config }; 124 Object[] args = new Object[] { m_Config };
125 IFriendsService friendsService = ServerUtils.LoadPlugin<IFriendsService>(m_LocalServiceDll, args); 125// IFriendsService friendsService = ServerUtils.LoadPlugin<IFriendsService>(m_LocalServiceDll, args)
126 ServerUtils.LoadPlugin<IFriendsService>(m_LocalServiceDll, args);
126 127
127 m_HypergridHandler = new GatekeeperServiceInConnector(m_Config, MainServer.Instance, simService); 128 m_HypergridHandler = new GatekeeperServiceInConnector(m_Config, MainServer.Instance, simService);
128 129
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs
index c8f45f6..2f3c350 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs
@@ -75,7 +75,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Land
75 if (!m_Enabled) 75 if (!m_Enabled)
76 return; 76 return;
77 77
78 m_log.Info("[LAND IN CONNECTOR]: Starting..."); 78// m_log.Info("[LAND IN CONNECTOR]: Starting...");
79 } 79 }
80 80
81 public void Close() 81 public void Close()
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs
index 3fd89b9..b544ab3 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs
@@ -74,7 +74,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Neighbour
74 if (!m_Enabled) 74 if (!m_Enabled)
75 return; 75 return;
76 76
77 m_log.Info("[NEIGHBOUR IN CONNECTOR]: Starting..."); 77// m_log.Info("[NEIGHBOUR IN CONNECTOR]: Starting...");
78 } 78 }
79 79
80 public void Close() 80 public void Close()
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
index 8395f83..008465f 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
@@ -149,7 +149,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
149 149
150 m_aScene = scene; 150 m_aScene = scene;
151 151
152 scene.RegisterModuleInterface<IAssetService>(this); 152 m_aScene.RegisterModuleInterface<IAssetService>(this);
153 } 153 }
154 154
155 public void RemoveRegion(Scene scene) 155 public void RemoveRegion(Scene scene)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/AuthorizationService.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/AuthorizationService.cs
index f0d21e6..4470799 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/AuthorizationService.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/AuthorizationService.cs
@@ -55,7 +55,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authorization
55 MethodBase.GetCurrentMethod().DeclaringType); 55 MethodBase.GetCurrentMethod().DeclaringType);
56 56
57 private IUserManagement m_UserManagement; 57 private IUserManagement m_UserManagement;
58 private IGridService m_GridService; 58// private IGridService m_GridService;
59 59
60 private Scene m_Scene; 60 private Scene m_Scene;
61 AccessFlags m_accessValue = AccessFlags.None; 61 AccessFlags m_accessValue = AccessFlags.None;
@@ -65,7 +65,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authorization
65 { 65 {
66 m_Scene = scene; 66 m_Scene = scene;
67 m_UserManagement = scene.RequestModuleInterface<IUserManagement>(); 67 m_UserManagement = scene.RequestModuleInterface<IUserManagement>();
68 m_GridService = scene.GridService; 68// m_GridService = scene.GridService;
69 69
70 if (config != null) 70 if (config != null)
71 { 71 {
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
index 540f33a..3c6e381 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
@@ -41,8 +41,7 @@ using OpenMetaverse;
41 41
42namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid 42namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
43{ 43{
44 public class LocalGridServicesConnector : 44 public class LocalGridServicesConnector : ISharedRegionModule, IGridService
45 ISharedRegionModule, IGridService
46 { 45 {
47 private static readonly ILog m_log = 46 private static readonly ILog m_log =
48 LogManager.GetLogger( 47 LogManager.GetLogger(
@@ -51,7 +50,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
51 private IGridService m_GridService; 50 private IGridService m_GridService;
52 private Dictionary<UUID, RegionCache> m_LocalCache = new Dictionary<UUID, RegionCache>(); 51 private Dictionary<UUID, RegionCache> m_LocalCache = new Dictionary<UUID, RegionCache>();
53 52
54 private bool m_Enabled = false; 53 private bool m_Enabled;
55 54
56 public LocalGridServicesConnector() 55 public LocalGridServicesConnector()
57 { 56 {
@@ -59,7 +58,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
59 58
60 public LocalGridServicesConnector(IConfigSource source) 59 public LocalGridServicesConnector(IConfigSource source)
61 { 60 {
62 m_log.Debug("[LOCAL GRID CONNECTOR]: LocalGridServicesConnector instantiated"); 61 m_log.Debug("[LOCAL GRID SERVICE CONNECTOR]: LocalGridServicesConnector instantiated directly.");
63 InitialiseService(source); 62 InitialiseService(source);
64 } 63 }
65 64
@@ -84,8 +83,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
84 if (name == Name) 83 if (name == Name)
85 { 84 {
86 InitialiseService(source); 85 InitialiseService(source);
87 m_Enabled = true; 86 m_log.Info("[LOCAL GRID SERVICE CONNECTOR]: Local grid connector enabled");
88 m_log.Info("[LOCAL GRID CONNECTOR]: Local grid connector enabled");
89 } 87 }
90 } 88 }
91 } 89 }
@@ -95,7 +93,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
95 IConfig assetConfig = source.Configs["GridService"]; 93 IConfig assetConfig = source.Configs["GridService"];
96 if (assetConfig == null) 94 if (assetConfig == null)
97 { 95 {
98 m_log.Error("[LOCAL GRID CONNECTOR]: GridService missing from OpenSim.ini"); 96 m_log.Error("[LOCAL GRID SERVICE CONNECTOR]: GridService missing from OpenSim.ini");
99 return; 97 return;
100 } 98 }
101 99
@@ -104,7 +102,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
104 102
105 if (serviceDll == String.Empty) 103 if (serviceDll == String.Empty)
106 { 104 {
107 m_log.Error("[LOCAL GRID CONNECTOR]: No LocalServiceModule named in section GridService"); 105 m_log.Error("[LOCAL GRID SERVICE CONNECTOR]: No LocalServiceModule named in section GridService");
108 return; 106 return;
109 } 107 }
110 108
@@ -115,16 +113,20 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
115 113
116 if (m_GridService == null) 114 if (m_GridService == null)
117 { 115 {
118 m_log.Error("[LOCAL GRID CONNECTOR]: Can't load grid service"); 116 m_log.Error("[LOCAL GRID SERVICE CONNECTOR]: Can't load grid service");
119 return; 117 return;
120 } 118 }
119
120 m_Enabled = true;
121 } 121 }
122 122
123 public void PostInitialise() 123 public void PostInitialise()
124 { 124 {
125 // FIXME: We will still add this command even if we aren't enabled since RemoteGridServiceConnector
126 // will have instantiated us directly.
125 MainConsole.Instance.Commands.AddCommand("Regions", false, "show neighbours", 127 MainConsole.Instance.Commands.AddCommand("Regions", false, "show neighbours",
126 "show neighbours", 128 "show neighbours",
127 "Shows the local regions' neighbours", NeighboursCommand); 129 "Shows the local regions' neighbours", HandleShowNeighboursCommand);
128 } 130 }
129 131
130 public void Close() 132 public void Close()
@@ -133,17 +135,22 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
133 135
134 public void AddRegion(Scene scene) 136 public void AddRegion(Scene scene)
135 { 137 {
136 if (m_Enabled) 138 if (!m_Enabled)
137 scene.RegisterModuleInterface<IGridService>(this); 139 return;
140
141 scene.RegisterModuleInterface<IGridService>(this);
138 142
139 if (m_LocalCache.ContainsKey(scene.RegionInfo.RegionID)) 143 if (m_LocalCache.ContainsKey(scene.RegionInfo.RegionID))
140 m_log.ErrorFormat("[LOCAL GRID CONNECTOR]: simulator seems to have more than one region with the same UUID. Please correct this!"); 144 m_log.ErrorFormat("[LOCAL GRID SERVICE CONNECTOR]: simulator seems to have more than one region with the same UUID. Please correct this!");
141 else 145 else
142 m_LocalCache.Add(scene.RegionInfo.RegionID, new RegionCache(scene)); 146 m_LocalCache.Add(scene.RegionInfo.RegionID, new RegionCache(scene));
143 } 147 }
144 148
145 public void RemoveRegion(Scene scene) 149 public void RemoveRegion(Scene scene)
146 { 150 {
151 if (!m_Enabled)
152 return;
153
147 m_LocalCache[scene.RegionInfo.RegionID].Clear(); 154 m_LocalCache[scene.RegionInfo.RegionID].Clear();
148 m_LocalCache.Remove(scene.RegionInfo.RegionID); 155 m_LocalCache.Remove(scene.RegionInfo.RegionID);
149 } 156 }
@@ -232,7 +239,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
232 239
233 #endregion 240 #endregion
234 241
235 public void NeighboursCommand(string module, string[] cmdparams) 242 public void HandleShowNeighboursCommand(string module, string[] cmdparams)
236 { 243 {
237 System.Text.StringBuilder caps = new System.Text.StringBuilder(); 244 System.Text.StringBuilder caps = new System.Text.StringBuilder();
238 245
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
index 4cf62ec..b0edce7 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
@@ -79,29 +79,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
79 79
80 public void OnConnectionClose(IClientAPI client) 80 public void OnConnectionClose(IClientAPI client)
81 { 81 {
82 if (client.IsLoggingOut) 82 if (client.SceneAgent.IsChildAgent)
83 { 83 return;
84 object sp = null;
85 Vector3 position = new Vector3(128, 128, 0);
86 Vector3 lookat = new Vector3(0, 1, 0);
87
88 if (client.Scene.TryGetScenePresence(client.AgentId, out sp))
89 {
90 if (sp is ScenePresence)
91 {
92 if (((ScenePresence)sp).IsChildAgent)
93 return;
94
95 position = ((ScenePresence)sp).AbsolutePosition;
96 lookat = ((ScenePresence)sp).Lookat;
97 }
98 }
99
100// m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName);
101 m_GridUserService.LoggedOut(client.AgentId.ToString(), client.SessionId, client.Scene.RegionInfo.RegionID, position, lookat);
102 }
103 84
85// m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName);
86 m_GridUserService.LoggedOut(
87 client.AgentId.ToString(), client.SessionId, client.Scene.RegionInfo.RegionID,
88 client.SceneAgent.AbsolutePosition, client.SceneAgent.Lookat);
104 } 89 }
105
106 } 90 }
107} 91}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
index 3b862da..6cd077a 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
@@ -149,9 +149,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
149 lock (m_scenes) 149 lock (m_scenes)
150 m_scenes[scene.RegionInfo.RegionID] = scene; 150 m_scenes[scene.RegionInfo.RegionID] = scene;
151 151
152 scene.EventManager.OnPrimsLoaded += new EventManager.PrimsLoaded(EventManager_OnPrimsLoaded); 152 scene.EventManager.OnLoginsEnabled += OnLoginsEnabled;
153 } 153 }
154 154
155
155 ///<summary> 156 ///<summary>
156 /// 157 ///
157 ///</summary> 158 ///</summary>
@@ -166,9 +167,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
166 167
167 #endregion ISharedRegionModule 168 #endregion ISharedRegionModule
168 169
169 void EventManager_OnPrimsLoaded(Scene s) 170 void OnLoginsEnabled(string regionName)
170 { 171 {
171 UploadMapTile(s); 172 Scene scene = null;
173 foreach (Scene s in m_scenes.Values)
174 if (s.RegionInfo.RegionName == regionName)
175 {
176 scene = s;
177 break;
178 }
179 if (scene != null)
180 UploadMapTile(scene);
172 } 181 }
173 182
174 183
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/LocalNeighbourServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/LocalNeighbourServiceConnector.cs
index 40cc536..7a90686 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/LocalNeighbourServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/LocalNeighbourServiceConnector.cs
@@ -125,13 +125,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Neighbour
125 uint x, y; 125 uint x, y;
126 Utils.LongToUInts(regionHandle, out x, out y); 126 Utils.LongToUInts(regionHandle, out x, out y);
127 127
128 m_log.DebugFormat("[NEIGHBOUR CONNECTOR]: HelloNeighbour from region {0} to region at {1}-{2}",
129 thisRegion.RegionName, x / Constants.RegionSize, y / Constants.RegionSize);
130
131 foreach (Scene s in m_Scenes) 128 foreach (Scene s in m_Scenes)
132 { 129 {
133 if (s.RegionInfo.RegionHandle == regionHandle) 130 if (s.RegionInfo.RegionHandle == regionHandle)
134 { 131 {
132 m_log.DebugFormat("[LOCAL NEIGHBOUR SERVICE CONNECTOR]: HelloNeighbour from region {0} to neighbour {1} at {2}-{3}",
133 thisRegion.RegionName, s.Name, x / Constants.RegionSize, y / Constants.RegionSize);
134
135 //m_log.Debug("[NEIGHBOUR CONNECTOR]: Found region to SendHelloNeighbour"); 135 //m_log.Debug("[NEIGHBOUR CONNECTOR]: Found region to SendHelloNeighbour");
136 return s.IncomingHelloNeighbour(thisRegion); 136 return s.IncomingHelloNeighbour(thisRegion);
137 } 137 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs
index ccfbf78..172bea1 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs
@@ -64,7 +64,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
64 scene.EventManager.OnNewClient -= OnNewClient; 64 scene.EventManager.OnNewClient -= OnNewClient;
65 65
66 m_PresenceService.LogoutRegionAgents(scene.RegionInfo.RegionID); 66 m_PresenceService.LogoutRegionAgents(scene.RegionInfo.RegionID);
67
68 } 67 }
69 68
70 public void OnMakeRootAgent(ScenePresence sp) 69 public void OnMakeRootAgent(ScenePresence sp)
@@ -80,18 +79,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
80 79
81 public void OnConnectionClose(IClientAPI client) 80 public void OnConnectionClose(IClientAPI client)
82 { 81 {
83 if (client.IsLoggingOut) 82 if (!client.SceneAgent.IsChildAgent)
84 { 83 {
85 object sp = null;
86 if (client.Scene.TryGetScenePresence(client.AgentId, out sp))
87 {
88 if (sp is ScenePresence)
89 {
90 if (((ScenePresence)sp).IsChildAgent)
91 return;
92 }
93 }
94
95// m_log.DebugFormat("[PRESENCE DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName); 84// m_log.DebugFormat("[PRESENCE DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName);
96 m_PresenceService.LogoutAgent(client.SessionId); 85 m_PresenceService.LogoutAgent(client.SessionId);
97 } 86 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
index 6e75692..6eb99ea 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27using System; 27using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.Linq;
29using System.Reflection; 30using System.Reflection;
30using log4net; 31using log4net;
31using Nini.Config; 32using Nini.Config;
@@ -41,22 +42,20 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
41 public class LocalSimulationConnectorModule : ISharedRegionModule, ISimulationService 42 public class LocalSimulationConnectorModule : ISharedRegionModule, ISimulationService
42 { 43 {
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44 // Version of this service
45 private const string m_Version = "SIMULATION/0.1";
46 45
47 private List<Scene> m_sceneList = new List<Scene>(); 46 /// <summary>
47 /// Version of this service
48 /// </summary>
49 private const string m_Version = "SIMULATION/0.1";
48 50
49 private IEntityTransferModule m_AgentTransferModule; 51 /// <summary>
50 protected IEntityTransferModule AgentTransferModule 52 /// Map region ID to scene.
51 { 53 /// </summary>
52 get 54 private Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>();
53 {
54 if (m_AgentTransferModule == null)
55 m_AgentTransferModule = m_sceneList[0].RequestModuleInterface<IEntityTransferModule>();
56 return m_AgentTransferModule;
57 }
58 }
59 55
56 /// <summary>
57 /// Is this module enabled?
58 /// </summary>
60 private bool m_ModuleEnabled = false; 59 private bool m_ModuleEnabled = false;
61 60
62 #region IRegionModule 61 #region IRegionModule
@@ -129,12 +128,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
129 /// <param name="scene"></param> 128 /// <param name="scene"></param>
130 public void RemoveScene(Scene scene) 129 public void RemoveScene(Scene scene)
131 { 130 {
132 lock (m_sceneList) 131 lock (m_scenes)
133 { 132 {
134 if (m_sceneList.Contains(scene)) 133 if (m_scenes.ContainsKey(scene.RegionInfo.RegionID))
135 { 134 m_scenes.Remove(scene.RegionInfo.RegionID);
136 m_sceneList.Remove(scene); 135 else
137 } 136 m_log.WarnFormat(
137 "[LOCAL SIMULATION CONNECTOR]: Tried to remove region {0} but it was not present",
138 scene.RegionInfo.RegionName);
138 } 139 }
139 } 140 }
140 141
@@ -144,13 +145,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
144 /// <param name="scene"></param> 145 /// <param name="scene"></param>
145 public void Init(Scene scene) 146 public void Init(Scene scene)
146 { 147 {
147 if (!m_sceneList.Contains(scene)) 148 lock (m_scenes)
148 { 149 {
149 lock (m_sceneList) 150 if (!m_scenes.ContainsKey(scene.RegionInfo.RegionID))
150 { 151 m_scenes[scene.RegionInfo.RegionID] = scene;
151 m_sceneList.Add(scene); 152 else
152 } 153 m_log.WarnFormat(
153 154 "[LOCAL SIMULATION CONNECTOR]: Tried to add region {0} but it is already present",
155 scene.RegionInfo.RegionName);
154 } 156 }
155 } 157 }
156 158
@@ -158,15 +160,24 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
158 160
159 #region ISimulation 161 #region ISimulation
160 162
161 public IScene GetScene(ulong regionhandle) 163 public IScene GetScene(UUID regionId)
162 { 164 {
163 foreach (Scene s in m_sceneList) 165 if (m_scenes.ContainsKey(regionId))
164 { 166 {
165 if (s.RegionInfo.RegionHandle == regionhandle) 167 return m_scenes[regionId];
166 return s; 168 }
169 else
170 {
171 // FIXME: This was pre-existing behaviour but possibly not a good idea, since it hides an error rather
172 // than making it obvious and fixable. Need to see if the error message comes up in practice.
173 Scene s = m_scenes.Values.ToArray()[0];
174
175 m_log.ErrorFormat(
176 "[LOCAL SIMULATION CONNECTOR]: Region with id {0} not found. Returning {1} {2} instead",
177 regionId, s.RegionInfo.RegionName, s.RegionInfo.RegionID);
178
179 return s;
167 } 180 }
168 // ? weird. should not happen
169 return m_sceneList[0];
170 } 181 }
171 182
172 public ISimulationService GetInnerService() 183 public ISimulationService GetInnerService()
@@ -187,13 +198,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
187 return false; 198 return false;
188 } 199 }
189 200
190 foreach (Scene s in m_sceneList) 201 if (m_scenes.ContainsKey(destination.RegionID))
191 { 202 {
192 if (s.RegionInfo.RegionHandle == destination.RegionHandle) 203// m_log.DebugFormat("[LOCAL SIMULATION CONNECTOR]: Found region {0} to send SendCreateChildAgent", destination.RegionName);
193 { 204 return m_scenes[destination.RegionID].NewUserConnection(aCircuit, teleportFlags, out reason);
194 m_log.DebugFormat("[LOCAL SIMULATION CONNECTOR]: Found region {0} to send SendCreateChildAgent", destination.RegionName);
195 return s.NewUserConnection(aCircuit, teleportFlags, out reason);
196 }
197 } 205 }
198 206
199 reason = "Did not find region " + destination.RegionName; 207 reason = "Did not find region " + destination.RegionName;
@@ -205,17 +213,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
205 if (destination == null) 213 if (destination == null)
206 return false; 214 return false;
207 215
208 foreach (Scene s in m_sceneList) 216 if (m_scenes.ContainsKey(destination.RegionID))
209 { 217 {
210 if (s.RegionInfo.RegionHandle == destination.RegionHandle) 218// m_log.DebugFormat(
211 { 219// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
212 m_log.DebugFormat( 220// s.RegionInfo.RegionName, destination.RegionHandle);
213 "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
214 s.RegionInfo.RegionName, destination.RegionHandle);
215 221
216 s.IncomingChildAgentDataUpdate(cAgentData); 222 return m_scenes[destination.RegionID].IncomingChildAgentDataUpdate(cAgentData);
217 return true;
218 }
219 } 223 }
220 224
221// m_log.DebugFormat("[LOCAL COMMS]: Did not find region {0} for ChildAgentUpdate", regionHandle); 225// m_log.DebugFormat("[LOCAL COMMS]: Did not find region {0} for ChildAgentUpdate", regionHandle);
@@ -231,11 +235,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
231 // simulator so when we receive the update we need to hand it to each of the 235 // simulator so when we receive the update we need to hand it to each of the
232 // scenes; scenes each check to see if the is a scene presence for the avatar 236 // scenes; scenes each check to see if the is a scene presence for the avatar
233 // note that we really don't need the GridRegion for this call 237 // note that we really don't need the GridRegion for this call
234 foreach (Scene s in m_sceneList) 238 foreach (Scene s in m_scenes.Values)
235 { 239 {
236 //m_log.Debug("[LOCAL COMMS]: Found region to send ChildAgentUpdate"); 240 //m_log.Debug("[LOCAL COMMS]: Found region to send ChildAgentUpdate");
237 s.IncomingChildAgentDataUpdate(cAgentData); 241 s.IncomingChildAgentDataUpdate(cAgentData);
238 } 242 }
243
239 //m_log.Debug("[LOCAL COMMS]: region not found for ChildAgentUpdate"); 244 //m_log.Debug("[LOCAL COMMS]: region not found for ChildAgentUpdate");
240 return true; 245 return true;
241 } 246 }
@@ -247,14 +252,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
247 if (destination == null) 252 if (destination == null)
248 return false; 253 return false;
249 254
250 foreach (Scene s in m_sceneList) 255 if (m_scenes.ContainsKey(destination.RegionID))
251 { 256 {
252 if (s.RegionInfo.RegionHandle == destination.RegionHandle) 257// m_log.DebugFormat(
253 { 258// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
254 //m_log.Debug("[LOCAL COMMS]: Found region to send ChildAgentUpdate"); 259// s.RegionInfo.RegionName, destination.RegionHandle);
255 return s.IncomingRetrieveRootAgent(id, out agent); 260
256 } 261 return m_scenes[destination.RegionID].IncomingRetrieveRootAgent(id, out agent);
257 } 262 }
263
258 //m_log.Debug("[LOCAL COMMS]: region not found for ChildAgentUpdate"); 264 //m_log.Debug("[LOCAL COMMS]: region not found for ChildAgentUpdate");
259 return false; 265 return false;
260 } 266 }
@@ -266,59 +272,49 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
266 if (destination == null) 272 if (destination == null)
267 return false; 273 return false;
268 274
269 foreach (Scene s in m_sceneList) 275 if (m_scenes.ContainsKey(destination.RegionID))
270 { 276 {
271 if (s.RegionInfo.RegionID == destination.RegionID) 277// m_log.DebugFormat(
272 return s.QueryAccess(id, position, out reason); 278// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
279// s.RegionInfo.RegionName, destination.RegionHandle);
280
281 return m_scenes[destination.RegionID].QueryAccess(id, position, out reason);
273 } 282 }
283
284 //m_log.Debug("[LOCAL COMMS]: region not found for QueryAccess");
274 return false; 285 return false;
275 } 286 }
276 287
277 public bool ReleaseAgent(UUID origin, UUID id, string uri) 288 public bool ReleaseAgent(UUID originId, UUID agentId, string uri)
278 { 289 {
279 foreach (Scene s in m_sceneList) 290 if (m_scenes.ContainsKey(originId))
280 { 291 {
281 if (s.RegionInfo.RegionID == origin) 292// m_log.DebugFormat(
282 { 293// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
283 m_log.Debug("[LOCAL COMMS]: Found region to SendReleaseAgent"); 294// s.RegionInfo.RegionName, destination.RegionHandle);
284 AgentTransferModule.AgentArrivedAtDestination(id); 295
285 return true; 296 m_scenes[originId].EntityTransferModule.AgentArrivedAtDestination(agentId);
286// return s.IncomingReleaseAgent(id); 297 return true;
287 }
288 } 298 }
299
289 //m_log.Debug("[LOCAL COMMS]: region not found in SendReleaseAgent " + origin); 300 //m_log.Debug("[LOCAL COMMS]: region not found in SendReleaseAgent " + origin);
290 return false; 301 return false;
291 } 302 }
292 303
293 public bool CloseAgent(GridRegion destination, UUID id) 304 public bool CloseChildAgent(GridRegion destination, UUID id)
294 { 305 {
295 if (destination == null) 306 return CloseAgent(destination, id);
296 return false;
297
298 foreach (Scene s in m_sceneList)
299 {
300 if (s.RegionInfo.RegionID == destination.RegionID)
301 {
302 //m_log.Debug("[LOCAL COMMS]: Found region to SendCloseAgent");
303 return s.IncomingCloseAgent(id);
304 }
305 }
306 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent");
307 return false;
308 } 307 }
309 308
310 public bool CloseChildAgent(GridRegion destination, UUID id) 309 public bool CloseAgent(GridRegion destination, UUID id)
311 { 310 {
312 if (destination == null) 311 if (destination == null)
313 return false; 312 return false;
314 313
315 foreach (Scene s in m_sceneList) 314 if (m_scenes.ContainsKey(destination.RegionID))
316 { 315 {
317 if (s.RegionInfo.RegionID == destination.RegionID) 316 Util.FireAndForget(delegate { m_scenes[destination.RegionID].IncomingCloseAgent(id); });
318 { 317 return true;
319 //m_log.Debug("[LOCAL COMMS]: Found region to SendCloseAgent");
320 return s.IncomingCloseChildAgent(id);
321 }
322 } 318 }
323 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent"); 319 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent");
324 return false; 320 return false;
@@ -333,62 +329,47 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
333 if (destination == null) 329 if (destination == null)
334 return false; 330 return false;
335 331
336 foreach (Scene s in m_sceneList) 332 if (m_scenes.ContainsKey(destination.RegionID))
337 { 333 {
338 if (s.RegionInfo.RegionHandle == destination.RegionHandle) 334// m_log.DebugFormat(
339 { 335// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
340 //m_log.Debug("[LOCAL COMMS]: Found region to SendCreateObject"); 336// s.RegionInfo.RegionName, destination.RegionHandle);
341 if (isLocalCall)
342 {
343 // We need to make a local copy of the object
344 ISceneObject sogClone = sog.CloneForNewScene();
345 sogClone.SetState(sog.GetStateSnapshot(), s);
346 return s.IncomingCreateObject(newPosition, sogClone);
347 }
348 else
349 {
350 // Use the object as it came through the wire
351 return s.IncomingCreateObject(newPosition, sog);
352 }
353 }
354 }
355 return false;
356 }
357 337
358 public bool CreateObject(GridRegion destination, UUID userID, UUID itemID) 338 Scene s = m_scenes[destination.RegionID];
359 {
360 if (destination == null)
361 return false;
362 339
363 foreach (Scene s in m_sceneList) 340 if (isLocalCall)
364 { 341 {
365 if (s.RegionInfo.RegionHandle == destination.RegionHandle) 342 // We need to make a local copy of the object
343 ISceneObject sogClone = sog.CloneForNewScene();
344 sogClone.SetState(sog.GetStateSnapshot(), s);
345 return s.IncomingCreateObject(newPosition, sogClone);
346 }
347 else
366 { 348 {
367 return s.IncomingCreateObject(userID, itemID); 349 // Use the object as it came through the wire
350 return s.IncomingCreateObject(newPosition, sog);
368 } 351 }
369 } 352 }
353
370 return false; 354 return false;
371 } 355 }
372 356
373
374 #endregion /* IInterregionComms */ 357 #endregion /* IInterregionComms */
375 358
376 #region Misc 359 #region Misc
377 360
378 public bool IsLocalRegion(ulong regionhandle) 361 public bool IsLocalRegion(ulong regionhandle)
379 { 362 {
380 foreach (Scene s in m_sceneList) 363 foreach (Scene s in m_scenes.Values)
381 if (s.RegionInfo.RegionHandle == regionhandle) 364 if (s.RegionInfo.RegionHandle == regionhandle)
382 return true; 365 return true;
366
383 return false; 367 return false;
384 } 368 }
385 369
386 public bool IsLocalRegion(UUID id) 370 public bool IsLocalRegion(UUID id)
387 { 371 {
388 foreach (Scene s in m_sceneList) 372 return m_scenes.ContainsKey(id);
389 if (s.RegionInfo.RegionID == id)
390 return true;
391 return false;
392 } 373 }
393 374
394 #endregion 375 #endregion
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
index 4b70692..68be552 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
@@ -151,9 +151,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
151 151
152 #region IInterregionComms 152 #region IInterregionComms
153 153
154 public IScene GetScene(ulong handle) 154 public IScene GetScene(UUID regionId)
155 { 155 {
156 return m_localBackend.GetScene(handle); 156 return m_localBackend.GetScene(regionId);
157 } 157 }
158 158
159 public ISimulationService GetInnerService() 159 public ISimulationService GetInnerService()
@@ -226,13 +226,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
226 return m_remoteConnector.RetrieveAgent(destination, id, out agent); 226 return m_remoteConnector.RetrieveAgent(destination, id, out agent);
227 227
228 return false; 228 return false;
229
230 } 229 }
231 230
232 public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason) 231 public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason)
233 { 232 {
234 reason = "Communications failure"; 233 reason = "Communications failure";
235 version = "Unknown"; 234 version = "Unknown";
235
236 if (destination == null) 236 if (destination == null)
237 return false; 237 return false;
238 238
@@ -245,7 +245,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
245 return m_remoteConnector.QueryAccess(destination, id, position, out version, out reason); 245 return m_remoteConnector.QueryAccess(destination, id, position, out version, out reason);
246 246
247 return false; 247 return false;
248
249 } 248 }
250 249
251 public bool ReleaseAgent(UUID origin, UUID id, string uri) 250 public bool ReleaseAgent(UUID origin, UUID id, string uri)
@@ -316,13 +315,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
316 return false; 315 return false;
317 } 316 }
318 317
319 public bool CreateObject(GridRegion destination, UUID userID, UUID itemID)
320 {
321 // Not Implemented
322 return false;
323 }
324
325 #endregion /* IInterregionComms */ 318 #endregion /* IInterregionComms */
326
327 } 319 }
328} 320} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index 38db239..619550c 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -41,6 +41,7 @@ using OpenSim.Framework.Serialization.External;
41using OpenSim.Region.CoreModules.World.Terrain; 41using OpenSim.Region.CoreModules.World.Terrain;
42using OpenSim.Region.Framework.Interfaces; 42using OpenSim.Region.Framework.Interfaces;
43using OpenSim.Region.Framework.Scenes; 43using OpenSim.Region.Framework.Scenes;
44using OpenSim.Region.Framework.Scenes.Serialization;
44using OpenSim.Services.Interfaces; 45using OpenSim.Services.Interfaces;
45 46
46namespace OpenSim.Region.CoreModules.World.Archiver 47namespace OpenSim.Region.CoreModules.World.Archiver
@@ -245,6 +246,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
245 // Reload serialized prims 246 // Reload serialized prims
246 m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count); 247 m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count);
247 248
249 UUID oldTelehubUUID = m_scene.RegionInfo.RegionSettings.TelehubObject;
250
248 IRegionSerialiserModule serialiser = m_scene.RequestModuleInterface<IRegionSerialiserModule>(); 251 IRegionSerialiserModule serialiser = m_scene.RequestModuleInterface<IRegionSerialiserModule>();
249 int sceneObjectsLoadedCount = 0; 252 int sceneObjectsLoadedCount = 0;
250 253
@@ -266,11 +269,21 @@ namespace OpenSim.Region.CoreModules.World.Archiver
266 269
267 SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject); 270 SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject);
268 271
272 bool isTelehub = (sceneObject.UUID == oldTelehubUUID);
273
269 // For now, give all incoming scene objects new uuids. This will allow scenes to be cloned 274 // For now, give all incoming scene objects new uuids. This will allow scenes to be cloned
270 // on the same region server and multiple examples a single object archive to be imported 275 // on the same region server and multiple examples a single object archive to be imported
271 // to the same scene (when this is possible). 276 // to the same scene (when this is possible).
272 sceneObject.ResetIDs(); 277 sceneObject.ResetIDs();
273 278
279 if (isTelehub)
280 {
281 // Change the Telehub Object to the new UUID
282 m_scene.RegionInfo.RegionSettings.TelehubObject = sceneObject.UUID;
283 m_scene.RegionInfo.RegionSettings.Save();
284 oldTelehubUUID = UUID.Zero;
285 }
286
274 // Try to retain the original creator/owner/lastowner if their uuid is present on this grid 287 // Try to retain the original creator/owner/lastowner if their uuid is present on this grid
275 // or creator data is present. Otherwise, use the estate owner instead. 288 // or creator data is present. Otherwise, use the estate owner instead.
276 foreach (SceneObjectPart part in sceneObject.Parts) 289 foreach (SceneObjectPart part in sceneObject.Parts)
@@ -347,7 +360,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver
347 int ignoredObjects = serialisedSceneObjects.Count - sceneObjectsLoadedCount; 360 int ignoredObjects = serialisedSceneObjects.Count - sceneObjectsLoadedCount;
348 361
349 if (ignoredObjects > 0) 362 if (ignoredObjects > 0)
350 m_log.WarnFormat("[ARCHIVER]: Ignored {0} scene objects that already existed in the scene", ignoredObjects); 363 m_log.WarnFormat("[ARCHIVER]: Ignored {0} scene objects that already existed in the scene", ignoredObjects);
364
365 if (oldTelehubUUID != UUID.Zero)
366 {
367 m_log.WarnFormat("Telehub object not found: {0}", oldTelehubUUID);
368 m_scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero;
369 m_scene.RegionInfo.RegionSettings.ClearSpawnPoints();
370 }
351 } 371 }
352 372
353 /// <summary> 373 /// <summary>
@@ -523,6 +543,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver
523 currentRegionSettings.TerrainTexture4 = loadedRegionSettings.TerrainTexture4; 543 currentRegionSettings.TerrainTexture4 = loadedRegionSettings.TerrainTexture4;
524 currentRegionSettings.UseEstateSun = loadedRegionSettings.UseEstateSun; 544 currentRegionSettings.UseEstateSun = loadedRegionSettings.UseEstateSun;
525 currentRegionSettings.WaterHeight = loadedRegionSettings.WaterHeight; 545 currentRegionSettings.WaterHeight = loadedRegionSettings.WaterHeight;
546 currentRegionSettings.TelehubObject = loadedRegionSettings.TelehubObject;
547 currentRegionSettings.ClearSpawnPoints();
548 foreach (SpawnPoint sp in loadedRegionSettings.SpawnPoints())
549 currentRegionSettings.AddSpawnPoint(sp);
526 550
527 currentRegionSettings.Save(); 551 currentRegionSettings.Save();
528 552
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs
index 4d459bf..4edaaca 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs
@@ -40,6 +40,9 @@ using OpenSim.Framework.Serialization;
40using OpenSim.Region.CoreModules.World.Terrain; 40using OpenSim.Region.CoreModules.World.Terrain;
41using OpenSim.Region.Framework.Interfaces; 41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
43using Ionic.Zlib;
44using GZipStream = Ionic.Zlib.GZipStream;
45using CompressionMode = Ionic.Zlib.CompressionMode;
43 46
44namespace OpenSim.Region.CoreModules.World.Archiver 47namespace OpenSim.Region.CoreModules.World.Archiver
45{ 48{
@@ -64,7 +67,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
64 /// Determine whether this archive will save assets. Default is true. 67 /// Determine whether this archive will save assets. Default is true.
65 /// </summary> 68 /// </summary>
66 public bool SaveAssets { get; set; } 69 public bool SaveAssets { get; set; }
67 70
71 protected ArchiverModule m_module;
68 protected Scene m_scene; 72 protected Scene m_scene;
69 protected Stream m_saveStream; 73 protected Stream m_saveStream;
70 protected Guid m_requestId; 74 protected Guid m_requestId;
@@ -72,17 +76,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver
72 /// <summary> 76 /// <summary>
73 /// Constructor 77 /// Constructor
74 /// </summary> 78 /// </summary>
75 /// <param name="scene"></param> 79 /// <param name="module">Calling module</param>
76 /// <param name="savePath">The path to which to save data.</param> 80 /// <param name="savePath">The path to which to save data.</param>
77 /// <param name="requestId">The id associated with this request</param> 81 /// <param name="requestId">The id associated with this request</param>
78 /// <exception cref="System.IO.IOException"> 82 /// <exception cref="System.IO.IOException">
79 /// If there was a problem opening a stream for the file specified by the savePath 83 /// If there was a problem opening a stream for the file specified by the savePath
80 /// </exception> 84 /// </exception>
81 public ArchiveWriteRequestPreparation(Scene scene, string savePath, Guid requestId) : this(scene, requestId) 85 public ArchiveWriteRequestPreparation(ArchiverModule module, string savePath, Guid requestId) : this(module, requestId)
82 { 86 {
83 try 87 try
84 { 88 {
85 m_saveStream = new GZipStream(new FileStream(savePath, FileMode.Create), CompressionMode.Compress); 89 m_saveStream = new GZipStream(new FileStream(savePath, FileMode.Create), CompressionMode.Compress, CompressionLevel.BestCompression);
86 } 90 }
87 catch (EntryPointNotFoundException e) 91 catch (EntryPointNotFoundException e)
88 { 92 {
@@ -96,17 +100,23 @@ namespace OpenSim.Region.CoreModules.World.Archiver
96 /// <summary> 100 /// <summary>
97 /// Constructor. 101 /// Constructor.
98 /// </summary> 102 /// </summary>
99 /// <param name="scene"></param> 103 /// <param name="module">Calling module</param>
100 /// <param name="saveStream">The stream to which to save data.</param> 104 /// <param name="saveStream">The stream to which to save data.</param>
101 /// <param name="requestId">The id associated with this request</param> 105 /// <param name="requestId">The id associated with this request</param>
102 public ArchiveWriteRequestPreparation(Scene scene, Stream saveStream, Guid requestId) : this(scene, requestId) 106 public ArchiveWriteRequestPreparation(ArchiverModule module, Stream saveStream, Guid requestId) : this(module, requestId)
103 { 107 {
104 m_saveStream = saveStream; 108 m_saveStream = saveStream;
105 } 109 }
106 110
107 protected ArchiveWriteRequestPreparation(Scene scene, Guid requestId) 111 protected ArchiveWriteRequestPreparation(ArchiverModule module, Guid requestId)
108 { 112 {
109 m_scene = scene; 113 m_module = module;
114
115 // FIXME: This is only here for regression test purposes since they do not supply a module. Need to fix
116 // this.
117 if (m_module != null)
118 m_scene = m_module.Scene;
119
110 m_requestId = requestId; 120 m_requestId = requestId;
111 121
112 SaveAssets = true; 122 SaveAssets = true;
@@ -297,10 +307,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver
297 if (checkPermissions.Contains("T") && !canTransfer) 307 if (checkPermissions.Contains("T") && !canTransfer)
298 partPermitted = false; 308 partPermitted = false;
299 309
310 // If the user is the Creator of the object then it can always be included in the OAR
311 bool creator = (obj.CreatorID.Guid == user.Guid);
312 if (creator)
313 partPermitted = true;
314
300 //string name = (objGroup.PrimCount == 1) ? objGroup.Name : string.Format("{0} ({1}/{2})", obj.Name, primNumber, objGroup.PrimCount); 315 //string name = (objGroup.PrimCount == 1) ? objGroup.Name : string.Format("{0} ({1}/{2})", obj.Name, primNumber, objGroup.PrimCount);
301 //m_log.DebugFormat("[ARCHIVER]: Object permissions: {0}: Base={1:X4}, Owner={2:X4}, Everyone={3:X4}, permissionClass={4}, checkPermissions={5}, canCopy={6}, canTransfer={7}, permitted={8}", 316 //m_log.DebugFormat("[ARCHIVER]: Object permissions: {0}: Base={1:X4}, Owner={2:X4}, Everyone={3:X4}, permissionClass={4}, checkPermissions={5}, canCopy={6}, canTransfer={7}, creator={8}, permitted={9}",
302 // name, obj.BaseMask, obj.OwnerMask, obj.EveryoneMask, 317 // name, obj.BaseMask, obj.OwnerMask, obj.EveryoneMask,
303 // permissionClass, checkPermissions, canCopy, canTransfer, permitted); 318 // permissionClass, checkPermissions, canCopy, canTransfer, creator, partPermitted);
304 319
305 if (!partPermitted) 320 if (!partPermitted)
306 { 321 {
@@ -320,7 +335,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
320 /// <returns></returns> 335 /// <returns></returns>
321 public string CreateControlFile(Dictionary<string, object> options) 336 public string CreateControlFile(Dictionary<string, object> options)
322 { 337 {
323 int majorVersion = MAX_MAJOR_VERSION, minorVersion = 7; 338 int majorVersion = MAX_MAJOR_VERSION, minorVersion = 8;
324// 339//
325// if (options.ContainsKey("version")) 340// if (options.ContainsKey("version"))
326// { 341// {
@@ -356,32 +371,66 @@ namespace OpenSim.Region.CoreModules.World.Archiver
356 //if (majorVersion == 1) 371 //if (majorVersion == 1)
357 //{ 372 //{
358 // m_log.WarnFormat("[ARCHIVER]: Please be aware that version 1.0 OARs are not compatible with OpenSim 0.7.0.2 and earlier. Please use the --version=0 option if you want to produce a compatible OAR"); 373 // m_log.WarnFormat("[ARCHIVER]: Please be aware that version 1.0 OARs are not compatible with OpenSim 0.7.0.2 and earlier. Please use the --version=0 option if you want to produce a compatible OAR");
359 //} 374 //}
375
376 String s;
360 377
361 StringWriter sw = new StringWriter(); 378 using (StringWriter sw = new StringWriter())
362 XmlTextWriter xtw = new XmlTextWriter(sw); 379 {
363 xtw.Formatting = Formatting.Indented; 380 using (XmlTextWriter xtw = new XmlTextWriter(sw))
364 xtw.WriteStartDocument(); 381 {
365 xtw.WriteStartElement("archive"); 382 xtw.Formatting = Formatting.Indented;
366 xtw.WriteAttributeString("major_version", majorVersion.ToString()); 383 xtw.WriteStartDocument();
367 xtw.WriteAttributeString("minor_version", minorVersion.ToString()); 384 xtw.WriteStartElement("archive");
368 385 xtw.WriteAttributeString("major_version", majorVersion.ToString());
369 xtw.WriteStartElement("creation_info"); 386 xtw.WriteAttributeString("minor_version", minorVersion.ToString());
370 DateTime now = DateTime.UtcNow; 387
371 TimeSpan t = now - new DateTime(1970, 1, 1); 388 xtw.WriteStartElement("creation_info");
372 xtw.WriteElementString("datetime", ((int)t.TotalSeconds).ToString()); 389 DateTime now = DateTime.UtcNow;
373 xtw.WriteElementString("id", UUID.Random().ToString()); 390 TimeSpan t = now - new DateTime(1970, 1, 1);
374 xtw.WriteEndElement(); 391 xtw.WriteElementString("datetime", ((int)t.TotalSeconds).ToString());
375 392 xtw.WriteElementString("id", UUID.Random().ToString());
376 xtw.WriteElementString("assets_included", SaveAssets.ToString()); 393 xtw.WriteEndElement();
377 394
378 xtw.WriteEndElement(); 395 xtw.WriteStartElement("region_info");
379 396
380 xtw.Flush(); 397 bool isMegaregion;
381 xtw.Close(); 398 Vector2 size;
382 399 IRegionCombinerModule rcMod = null;
383 String s = sw.ToString(); 400
384 sw.Close(); 401 // FIXME: This is only here for regression test purposes since they do not supply a module. Need to fix
402 // this, possibly by doing control file creation somewhere else.
403 if (m_module != null)
404 rcMod = m_module.RegionCombinerModule;
405
406 if (rcMod != null)
407 isMegaregion = rcMod.IsRootForMegaregion(m_scene.RegionInfo.RegionID);
408 else
409 isMegaregion = false;
410
411 if (isMegaregion)
412 size = rcMod.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID);
413 else
414 size = new Vector2((float)Constants.RegionSize, (float)Constants.RegionSize);
415
416 xtw.WriteElementString("is_megaregion", isMegaregion.ToString());
417 xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y));
418
419 xtw.WriteEndElement();
420
421 xtw.WriteElementString("assets_included", SaveAssets.ToString());
422
423 xtw.WriteEndElement();
424
425 xtw.Flush();
426 }
427
428 s = sw.ToString();
429 }
430
431// if (m_scene != null)
432// Console.WriteLine(
433// "[ARCHIVE WRITE REQUEST PREPARATION]: Control file for {0} is: {1}", m_scene.RegionInfo.RegionName, s);
385 434
386 return s; 435 return s;
387 } 436 }
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
index f5a5a8d..bf3b124 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
@@ -45,7 +45,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
45 private static readonly ILog m_log = 45 private static readonly ILog m_log =
46 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 47
48 private Scene m_scene; 48 public Scene Scene { get; private set; }
49 public IRegionCombinerModule RegionCombinerModule { get; private set; }
49 50
50 /// <value> 51 /// <value>
51 /// The file used to load and save an opensimulator archive if no filename has been specified 52 /// The file used to load and save an opensimulator archive if no filename has been specified
@@ -70,13 +71,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver
70 71
71 public void AddRegion(Scene scene) 72 public void AddRegion(Scene scene)
72 { 73 {
73 m_scene = scene; 74 Scene = scene;
74 m_scene.RegisterModuleInterface<IRegionArchiverModule>(this); 75 Scene.RegisterModuleInterface<IRegionArchiverModule>(this);
75 //m_log.DebugFormat("[ARCHIVER]: Enabled for region {0}", scene.RegionInfo.RegionName); 76 //m_log.DebugFormat("[ARCHIVER]: Enabled for region {0}", scene.RegionInfo.RegionName);
76 } 77 }
77 78
78 public void RegionLoaded(Scene scene) 79 public void RegionLoaded(Scene scene)
79 { 80 {
81 RegionCombinerModule = scene.RequestModuleInterface<IRegionCombinerModule>();
80 } 82 }
81 83
82 public void RemoveRegion(Scene scene) 84 public void RemoveRegion(Scene scene)
@@ -165,9 +167,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
165 public void ArchiveRegion(string savePath, Guid requestId, Dictionary<string, object> options) 167 public void ArchiveRegion(string savePath, Guid requestId, Dictionary<string, object> options)
166 { 168 {
167 m_log.InfoFormat( 169 m_log.InfoFormat(
168 "[ARCHIVER]: Writing archive for region {0} to {1}", m_scene.RegionInfo.RegionName, savePath); 170 "[ARCHIVER]: Writing archive for region {0} to {1}", Scene.RegionInfo.RegionName, savePath);
169 171
170 new ArchiveWriteRequestPreparation(m_scene, savePath, requestId).ArchiveRegion(options); 172 new ArchiveWriteRequestPreparation(this, savePath, requestId).ArchiveRegion(options);
171 } 173 }
172 174
173 public void ArchiveRegion(Stream saveStream) 175 public void ArchiveRegion(Stream saveStream)
@@ -182,7 +184,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
182 184
183 public void ArchiveRegion(Stream saveStream, Guid requestId, Dictionary<string, object> options) 185 public void ArchiveRegion(Stream saveStream, Guid requestId, Dictionary<string, object> options)
184 { 186 {
185 new ArchiveWriteRequestPreparation(m_scene, saveStream, requestId).ArchiveRegion(options); 187 new ArchiveWriteRequestPreparation(this, saveStream, requestId).ArchiveRegion(options);
186 } 188 }
187 189
188 public void DearchiveRegion(string loadPath) 190 public void DearchiveRegion(string loadPath)
@@ -193,9 +195,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
193 public void DearchiveRegion(string loadPath, bool merge, bool skipAssets, Guid requestId) 195 public void DearchiveRegion(string loadPath, bool merge, bool skipAssets, Guid requestId)
194 { 196 {
195 m_log.InfoFormat( 197 m_log.InfoFormat(
196 "[ARCHIVER]: Loading archive to region {0} from {1}", m_scene.RegionInfo.RegionName, loadPath); 198 "[ARCHIVER]: Loading archive to region {0} from {1}", Scene.RegionInfo.RegionName, loadPath);
197 199
198 new ArchiveReadRequest(m_scene, loadPath, merge, skipAssets, requestId).DearchiveRegion(); 200 new ArchiveReadRequest(Scene, loadPath, merge, skipAssets, requestId).DearchiveRegion();
199 } 201 }
200 202
201 public void DearchiveRegion(Stream loadStream) 203 public void DearchiveRegion(Stream loadStream)
@@ -205,7 +207,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
205 207
206 public void DearchiveRegion(Stream loadStream, bool merge, bool skipAssets, Guid requestId) 208 public void DearchiveRegion(Stream loadStream, bool merge, bool skipAssets, Guid requestId)
207 { 209 {
208 new ArchiveReadRequest(m_scene, loadStream, merge, skipAssets, requestId).DearchiveRegion(); 210 new ArchiveReadRequest(Scene, loadStream, merge, skipAssets, requestId).DearchiveRegion();
209 } 211 }
210 } 212 }
211} 213}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsDearchiver.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsDearchiver.cs
index 2c04008..8c0ef88 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/AssetsDearchiver.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsDearchiver.cs
@@ -46,8 +46,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
46 { 46 {
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 protected static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding();
50
51 /// <summary> 49 /// <summary>
52 /// Store for asset data we received before we get the metadata 50 /// Store for asset data we received before we get the metadata
53 /// </summary> 51 /// </summary>
diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
index 63f1363..5deaf52 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
@@ -68,7 +68,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
68 SerialiserModule serialiserModule = new SerialiserModule(); 68 SerialiserModule serialiserModule = new SerialiserModule();
69 TerrainModule terrainModule = new TerrainModule(); 69 TerrainModule terrainModule = new TerrainModule();
70 70
71 m_scene = SceneHelpers.SetupScene(); 71 m_scene = new SceneHelpers().SetupScene();
72 SceneHelpers.SetupSceneModules(m_scene, m_archiverModule, serialiserModule, terrainModule); 72 SceneHelpers.SetupSceneModules(m_scene, m_archiverModule, serialiserModule, terrainModule);
73 } 73 }
74 74
@@ -102,9 +102,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
102 PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); 102 PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere();
103 Vector3 groupPosition = new Vector3(10, 20, 30); 103 Vector3 groupPosition = new Vector3(10, 20, 30);
104 Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); 104 Quaternion rotationOffset = new Quaternion(20, 30, 40, 50);
105 Vector3 offsetPosition = new Vector3(5, 10, 15); 105// Vector3 offsetPosition = new Vector3(5, 10, 15);
106 106
107 return new SceneObjectPart(ownerId, shape, groupPosition, rotationOffset, offsetPosition) { Name = partName }; 107 return new SceneObjectPart(ownerId, shape, groupPosition, rotationOffset, Vector3.Zero) { Name = partName };
108 } 108 }
109 109
110 protected SceneObjectPart CreateSceneObjectPart2() 110 protected SceneObjectPart CreateSceneObjectPart2()
@@ -292,6 +292,59 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
292 } 292 }
293 293
294 /// <summary> 294 /// <summary>
295 /// Test loading an OpenSim Region Archive where the scene object parts are not ordered by link number (e.g.
296 /// 2 can come after 3).
297 /// </summary>
298 [Test]
299 public void TestLoadOarUnorderedParts()
300 {
301 TestHelpers.InMethod();
302
303 UUID ownerId = TestHelpers.ParseTail(0xaaaa);
304
305 MemoryStream archiveWriteStream = new MemoryStream();
306 TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream);
307
308 tar.WriteFile(
309 ArchiveConstants.CONTROL_FILE_PATH,
310 new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary<string, Object>()));
311
312 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11);
313 SceneObjectPart sop2
314 = SceneHelpers.CreateSceneObjectPart("obj1-Part2", TestHelpers.ParseTail(0x12), ownerId);
315 SceneObjectPart sop3
316 = SceneHelpers.CreateSceneObjectPart("obj1-Part3", TestHelpers.ParseTail(0x13), ownerId);
317
318 // Add the parts so they will be written out in reverse order to the oar
319 sog1.AddPart(sop3);
320 sop3.LinkNum = 3;
321 sog1.AddPart(sop2);
322 sop2.LinkNum = 2;
323
324 tar.WriteFile(
325 ArchiveConstants.CreateOarObjectPath(sog1.Name, sog1.UUID, sog1.AbsolutePosition),
326 SceneObjectSerializer.ToXml2Format(sog1));
327
328 tar.Close();
329
330 MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray());
331
332 lock (this)
333 {
334 m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
335 m_archiverModule.DearchiveRegion(archiveReadStream);
336 }
337
338 Assert.That(m_lastErrorMessage, Is.Null);
339
340 SceneObjectPart part2 = m_scene.GetSceneObjectPart("obj1-Part2");
341 Assert.That(part2.LinkNum, Is.EqualTo(2));
342
343 SceneObjectPart part3 = m_scene.GetSceneObjectPart("obj1-Part3");
344 Assert.That(part3.LinkNum, Is.EqualTo(3));
345 }
346
347 /// <summary>
295 /// Test loading an OpenSim Region Archive. 348 /// Test loading an OpenSim Region Archive.
296 /// </summary> 349 /// </summary>
297 [Test] 350 [Test]
@@ -463,7 +516,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
463 SerialiserModule serialiserModule = new SerialiserModule(); 516 SerialiserModule serialiserModule = new SerialiserModule();
464 TerrainModule terrainModule = new TerrainModule(); 517 TerrainModule terrainModule = new TerrainModule();
465 518
466 TestScene scene2 = SceneHelpers.SetupScene(); 519 TestScene scene2 = new SceneHelpers().SetupScene();
467 SceneHelpers.SetupSceneModules(scene2, archiverModule, serialiserModule, terrainModule); 520 SceneHelpers.SetupSceneModules(scene2, archiverModule, serialiserModule, terrainModule);
468 521
469 // Make sure there's a valid owner for the owner we saved (this should have been wiped if the code is 522 // Make sure there's a valid owner for the owner we saved (this should have been wiped if the code is
@@ -534,6 +587,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
534 rs.TerrainTexture4 = UUID.Parse("00000000-0000-0000-0000-000000000080"); 587 rs.TerrainTexture4 = UUID.Parse("00000000-0000-0000-0000-000000000080");
535 rs.UseEstateSun = true; 588 rs.UseEstateSun = true;
536 rs.WaterHeight = 23; 589 rs.WaterHeight = 23;
590 rs.TelehubObject = UUID.Parse("00000000-0000-0000-0000-111111111111");
591 rs.AddSpawnPoint(SpawnPoint.Parse("1,-2,0.33"));
537 592
538 tar.WriteFile(ArchiveConstants.SETTINGS_PATH + "region1.xml", RegionSettingsSerializer.Serialize(rs)); 593 tar.WriteFile(ArchiveConstants.SETTINGS_PATH + "region1.xml", RegionSettingsSerializer.Serialize(rs));
539 594
@@ -580,6 +635,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
580 Assert.That(loadedRs.TerrainTexture4, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000080"))); 635 Assert.That(loadedRs.TerrainTexture4, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000080")));
581 Assert.That(loadedRs.UseEstateSun, Is.True); 636 Assert.That(loadedRs.UseEstateSun, Is.True);
582 Assert.That(loadedRs.WaterHeight, Is.EqualTo(23)); 637 Assert.That(loadedRs.WaterHeight, Is.EqualTo(23));
638 Assert.AreEqual(UUID.Zero, loadedRs.TelehubObject); // because no object was found with the original UUID
639 Assert.AreEqual(0, loadedRs.SpawnPoints().Count);
583 } 640 }
584 641
585 /// <summary> 642 /// <summary>
@@ -607,7 +664,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
607 SerialiserModule serialiserModule = new SerialiserModule(); 664 SerialiserModule serialiserModule = new SerialiserModule();
608 TerrainModule terrainModule = new TerrainModule(); 665 TerrainModule terrainModule = new TerrainModule();
609 666
610 Scene scene = SceneHelpers.SetupScene(); 667 Scene scene = new SceneHelpers().SetupScene();
611 SceneHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule); 668 SceneHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule);
612 669
613 m_scene.AddNewSceneObject(new SceneObjectGroup(part2), false); 670 m_scene.AddNewSceneObject(new SceneObjectGroup(part2), false);
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs
index d2bbea3..3b84d57 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs
@@ -73,7 +73,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
73 "set terrain heights <corner> <min> <max> [<x>] [<y>]", 73 "set terrain heights <corner> <min> <max> [<x>] [<y>]",
74 "Sets the terrain texture heights on corner #<corner> to <min>/<max>, if <x> or <y> are specified, it will only " + 74 "Sets the terrain texture heights on corner #<corner> to <min>/<max>, if <x> or <y> are specified, it will only " +
75 "set it on regions with a matching coordinate. Specify -1 in <x> or <y> to wildcard" + 75 "set it on regions with a matching coordinate. Specify -1 in <x> or <y> to wildcard" +
76 " that coordinate. Corner # SW = 0, NW = 1, SE = 2, NE = 3.", 76 " that coordinate. Corner # SW = 0, NW = 1, SE = 2, NE = 3, all corners = -1.",
77 consoleSetTerrainHeights); 77 consoleSetTerrainHeights);
78 78
79 m_module.Scene.AddCommand( 79 m_module.Scene.AddCommand(
@@ -143,6 +143,16 @@ namespace OpenSim.Region.CoreModules.World.Estate
143 143
144 switch (corner) 144 switch (corner)
145 { 145 {
146 case -1:
147 m_module.Scene.RegionInfo.RegionSettings.Elevation1SW = lowValue;
148 m_module.Scene.RegionInfo.RegionSettings.Elevation2SW = highValue;
149 m_module.Scene.RegionInfo.RegionSettings.Elevation1NW = lowValue;
150 m_module.Scene.RegionInfo.RegionSettings.Elevation2NW = highValue;
151 m_module.Scene.RegionInfo.RegionSettings.Elevation1SE = lowValue;
152 m_module.Scene.RegionInfo.RegionSettings.Elevation2SE = highValue;
153 m_module.Scene.RegionInfo.RegionSettings.Elevation1NE = lowValue;
154 m_module.Scene.RegionInfo.RegionSettings.Elevation2NE = highValue;
155 break;
146 case 0: 156 case 0:
147 m_module.Scene.RegionInfo.RegionSettings.Elevation1SW = lowValue; 157 m_module.Scene.RegionInfo.RegionSettings.Elevation1SW = lowValue;
148 m_module.Scene.RegionInfo.RegionSettings.Elevation2SW = highValue; 158 m_module.Scene.RegionInfo.RegionSettings.Elevation2SW = highValue;
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index 97a2f4a..fdef9d8 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -170,12 +170,18 @@ namespace OpenSim.Region.CoreModules.World.Estate
170 sendRegionInfoPacketToAll(); 170 sendRegionInfoPacketToAll();
171 } 171 }
172 172
173 public void setEstateTerrainBaseTexture(IClientAPI remoteClient, int corner, UUID texture) 173 public void setEstateTerrainBaseTexture(int level, UUID texture)
174 {
175 setEstateTerrainBaseTexture(null, level, texture);
176 sendRegionHandshakeToAll();
177 }
178
179 public void setEstateTerrainBaseTexture(IClientAPI remoteClient, int level, UUID texture)
174 { 180 {
175 if (texture == UUID.Zero) 181 if (texture == UUID.Zero)
176 return; 182 return;
177 183
178 switch (corner) 184 switch (level)
179 { 185 {
180 case 0: 186 case 0:
181 Scene.RegionInfo.RegionSettings.TerrainTexture1 = texture; 187 Scene.RegionInfo.RegionSettings.TerrainTexture1 = texture;
@@ -195,6 +201,11 @@ namespace OpenSim.Region.CoreModules.World.Estate
195 sendRegionInfoPacketToAll(); 201 sendRegionInfoPacketToAll();
196 } 202 }
197 203
204 public void setEstateTerrainTextureHeights(int corner, float lowValue, float highValue)
205 {
206 setEstateTerrainTextureHeights(null, corner, lowValue, highValue);
207 }
208
198 public void setEstateTerrainTextureHeights(IClientAPI client, int corner, float lowValue, float highValue) 209 public void setEstateTerrainTextureHeights(IClientAPI client, int corner, float lowValue, float highValue)
199 { 210 {
200 switch (corner) 211 switch (corner)
@@ -993,7 +1004,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
993 { 1004 {
994 RegionHandshakeArgs args = new RegionHandshakeArgs(); 1005 RegionHandshakeArgs args = new RegionHandshakeArgs();
995 1006
996 args.isEstateManager = Scene.RegionInfo.EstateSettings.IsEstateManager(remoteClient.AgentId); 1007 args.isEstateManager = Scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(remoteClient.AgentId);
997 if (Scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero && Scene.RegionInfo.EstateSettings.EstateOwner == remoteClient.AgentId) 1008 if (Scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero && Scene.RegionInfo.EstateSettings.EstateOwner == remoteClient.AgentId)
998 args.isEstateManager = true; 1009 args.isEstateManager = true;
999 1010
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index add1551..51dcb67 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
@@ -1395,21 +1395,26 @@ namespace OpenSim.Region.CoreModules.World.Land
1395 private void EventManagerOnRegisterCaps(UUID agentID, Caps caps) 1395 private void EventManagerOnRegisterCaps(UUID agentID, Caps caps)
1396 { 1396 {
1397 string capsBase = "/CAPS/" + caps.CapsObjectPath; 1397 string capsBase = "/CAPS/" + caps.CapsObjectPath;
1398 caps.RegisterHandler("RemoteParcelRequest", 1398 caps.RegisterHandler(
1399 new RestStreamHandler("POST", capsBase + remoteParcelRequestPath, 1399 "RemoteParcelRequest",
1400 delegate(string request, string path, string param, 1400 new RestStreamHandler(
1401 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 1401 "POST",
1402 { 1402 capsBase + remoteParcelRequestPath,
1403 return RemoteParcelRequest(request, path, param, agentID, caps); 1403 (request, path, param, httpRequest, httpResponse)
1404 })); 1404 => RemoteParcelRequest(request, path, param, agentID, caps),
1405 "RemoteParcelRequest",
1406 agentID.ToString()));
1407
1405 UUID parcelCapID = UUID.Random(); 1408 UUID parcelCapID = UUID.Random();
1406 caps.RegisterHandler("ParcelPropertiesUpdate", 1409 caps.RegisterHandler(
1407 new RestStreamHandler("POST", "/CAPS/" + parcelCapID, 1410 "ParcelPropertiesUpdate",
1408 delegate(string request, string path, string param, 1411 new RestStreamHandler(
1409 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 1412 "POST",
1410 { 1413 "/CAPS/" + parcelCapID,
1411 return ProcessPropertiesUpdate(request, path, param, agentID, caps); 1414 (request, path, param, httpRequest, httpResponse)
1412 })); 1415 => ProcessPropertiesUpdate(request, path, param, agentID, caps),
1416 "ParcelPropertiesUpdate",
1417 agentID.ToString()));
1413 } 1418 }
1414 private string ProcessPropertiesUpdate(string request, string path, string param, UUID agentID, Caps caps) 1419 private string ProcessPropertiesUpdate(string request, string path, string param, UUID agentID, Caps caps)
1415 { 1420 {
@@ -1774,7 +1779,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1774 1779
1775 Vector3 pos = m_scene.GetNearestAllowedPosition(targetAvatar, land); 1780 Vector3 pos = m_scene.GetNearestAllowedPosition(targetAvatar, land);
1776 1781
1777 targetAvatar.TeleportWithMomentum(pos); 1782 targetAvatar.TeleportWithMomentum(pos, null);
1778 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname); 1783 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1779 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected."); 1784 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected.");
1780 1785
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index 5974112..4f06737 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -450,7 +450,10 @@ namespace OpenSim.Region.CoreModules.World.Land
450 { 450 {
451 bool isMember; 451 bool isMember;
452 if (m_groupMemberCache.TryGetValue(avatar, out isMember)) 452 if (m_groupMemberCache.TryGetValue(avatar, out isMember))
453 {
454 m_groupMemberCache.Update(avatar, isMember, m_groupMemberCacheTimeout);
453 return isMember; 455 return isMember;
456 }
454 457
455 IGroupsModule groupsModule = m_scene.RequestModuleInterface<IGroupsModule>(); 458 IGroupsModule groupsModule = m_scene.RequestModuleInterface<IGroupsModule>();
456 if (groupsModule == null) 459 if (groupsModule == null)
@@ -487,7 +490,7 @@ namespace OpenSim.Region.CoreModules.World.Land
487 if (m_scene.Permissions.IsAdministrator(avatar)) 490 if (m_scene.Permissions.IsAdministrator(avatar))
488 return false; 491 return false;
489 492
490 if (m_scene.RegionInfo.EstateSettings.IsEstateManager(avatar)) 493 if (m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(avatar))
491 return false; 494 return false;
492 495
493 if (avatar == LandData.OwnerID) 496 if (avatar == LandData.OwnerID)
@@ -517,7 +520,7 @@ namespace OpenSim.Region.CoreModules.World.Land
517 if (m_scene.Permissions.IsAdministrator(avatar)) 520 if (m_scene.Permissions.IsAdministrator(avatar))
518 return false; 521 return false;
519 522
520 if (m_scene.RegionInfo.EstateSettings.IsEstateManager(avatar)) 523 if (m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(avatar))
521 return false; 524 return false;
522 525
523 if (avatar == LandData.OwnerID) 526 if (avatar == LandData.OwnerID)
@@ -1230,7 +1233,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1230 if (land.LandData.LocalID == LandData.LocalID) 1233 if (land.LandData.LocalID == LandData.LocalID)
1231 { 1234 {
1232 Vector3 pos = m_scene.GetNearestAllowedPosition(presence, land); 1235 Vector3 pos = m_scene.GetNearestAllowedPosition(presence, land);
1233 presence.TeleportWithMomentum(pos); 1236 presence.TeleportWithMomentum(pos, null);
1234 presence.ControllingClient.SendAlertMessage("You have been ejected from this land"); 1237 presence.ControllingClient.SendAlertMessage("You have been ejected from this land");
1235 } 1238 }
1236 } 1239 }
diff --git a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
index 5122734..102b4d7 100644
--- a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
@@ -126,7 +126,6 @@ namespace OpenSim.Region.CoreModules.World.Land
126// m_log.DebugFormat( 126// m_log.DebugFormat(
127// "[PRIM COUNT MODULE]: Ignoring OnParcelPrimCountAdd() for {0} on {1} since count is tainted", 127// "[PRIM COUNT MODULE]: Ignoring OnParcelPrimCountAdd() for {0} on {1} since count is tainted",
128// obj.Name, m_Scene.RegionInfo.RegionName); 128// obj.Name, m_Scene.RegionInfo.RegionName);
129
130 } 129 }
131 } 130 }
132 131
diff --git a/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs b/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs
index e553ffa..b5ee4d2 100644
--- a/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs
+++ b/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs
@@ -64,7 +64,7 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
64 { 64 {
65 m_pcm = new PrimCountModule(); 65 m_pcm = new PrimCountModule();
66 LandManagementModule lmm = new LandManagementModule(); 66 LandManagementModule lmm = new LandManagementModule();
67 m_scene = SceneHelpers.SetupScene(); 67 m_scene = new SceneHelpers().SetupScene();
68 SceneHelpers.SetupSceneModules(m_scene, lmm, m_pcm); 68 SceneHelpers.SetupSceneModules(m_scene, lmm, m_pcm);
69 69
70 int xParcelDivider = (int)Constants.RegionSize - 1; 70 int xParcelDivider = (int)Constants.RegionSize - 1;
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
index f86c790..aa306c7 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
@@ -225,7 +225,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
225 int tc = 0; 225 int tc = 0;
226 double[,] hm = whichScene.Heightmap.GetDoubles(); 226 double[,] hm = whichScene.Heightmap.GetDoubles();
227 tc = Environment.TickCount; 227 tc = Environment.TickCount;
228 m_log.Info("[MAPTILE]: Generating Maptile Step 2: Object Volume Profile"); 228 m_log.Debug("[MAPTILE]: Generating Maptile Step 2: Object Volume Profile");
229 EntityBase[] objs = whichScene.GetEntities(); 229 EntityBase[] objs = whichScene.GetEntities();
230 Dictionary<uint, DrawStruct> z_sort = new Dictionary<uint, DrawStruct>(); 230 Dictionary<uint, DrawStruct> z_sort = new Dictionary<uint, DrawStruct>();
231 //SortedList<float, RectangleDrawStruct> z_sort = new SortedList<float, RectangleDrawStruct>(); 231 //SortedList<float, RectangleDrawStruct> z_sort = new SortedList<float, RectangleDrawStruct>();
@@ -541,7 +541,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
541 g.Dispose(); 541 g.Dispose();
542 } // lock entities objs 542 } // lock entities objs
543 543
544 m_log.Info("[MAPTILE]: Generating Maptile Step 2: Done in " + (Environment.TickCount - tc) + " ms"); 544 m_log.Debug("[MAPTILE]: Generating Maptile Step 2: Done in " + (Environment.TickCount - tc) + " ms");
545 return mapbmp; 545 return mapbmp;
546 } 546 }
547 547
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs b/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs
index eb1a27f..992bff3 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs
@@ -54,7 +54,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
54 public void TerrainToBitmap(Bitmap mapbmp) 54 public void TerrainToBitmap(Bitmap mapbmp)
55 { 55 {
56 int tc = Environment.TickCount; 56 int tc = Environment.TickCount;
57 m_log.Info("[MAPTILE]: Generating Maptile Step 1: Terrain"); 57 m_log.Debug("[MAPTILE]: Generating Maptile Step 1: Terrain");
58 58
59 double[,] hm = m_scene.Heightmap.GetDoubles(); 59 double[,] hm = m_scene.Heightmap.GetDoubles();
60 bool ShadowDebugContinue = true; 60 bool ShadowDebugContinue = true;
@@ -238,7 +238,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
238 } 238 }
239 } 239 }
240 } 240 }
241 m_log.Info("[MAPTILE]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms"); 241 m_log.Debug("[MAPTILE]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms");
242 } 242 }
243 } 243 }
244} 244}
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs b/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs
index 1d2141e..d13c2ef 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs
@@ -278,7 +278,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
278 public void TerrainToBitmap(Bitmap mapbmp) 278 public void TerrainToBitmap(Bitmap mapbmp)
279 { 279 {
280 int tc = Environment.TickCount; 280 int tc = Environment.TickCount;
281 m_log.Info("[MAPTILE]: Generating Maptile Step 1: Terrain"); 281 m_log.Debug("[MAPTILE]: Generating Maptile Step 1: Terrain");
282 282
283 // These textures should be in the AssetCache anyway, as every client conneting to this 283 // These textures should be in the AssetCache anyway, as every client conneting to this
284 // region needs them. Except on start, when the map is recreated (before anyone connected), 284 // region needs them. Except on start, when the map is recreated (before anyone connected),
@@ -412,7 +412,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
412 } 412 }
413 } 413 }
414 } 414 }
415 m_log.Info("[MAPTILE]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms"); 415 m_log.Debug("[MAPTILE]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms");
416 } 416 }
417 } 417 }
418} 418}
diff --git a/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs b/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs
index 5239f50..601e81e 100644
--- a/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs
+++ b/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs
@@ -145,7 +145,9 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
145 145
146 // Even though we're registering for POST we're going to get GETS and UPDATES too 146 // Even though we're registering for POST we're going to get GETS and UPDATES too
147 caps.RegisterHandler( 147 caps.RegisterHandler(
148 "ObjectMedia", new RestStreamHandler("POST", omCapUrl, HandleObjectMediaMessage)); 148 "ObjectMedia",
149 new RestStreamHandler(
150 "POST", omCapUrl, HandleObjectMediaMessage, "ObjectMedia", agentID.ToString()));
149 } 151 }
150 152
151 string omuCapUrl = "/CAPS/" + UUID.Random(); 153 string omuCapUrl = "/CAPS/" + UUID.Random();
@@ -157,7 +159,9 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
157 159
158 // Even though we're registering for POST we're going to get GETS and UPDATES too 160 // Even though we're registering for POST we're going to get GETS and UPDATES too
159 caps.RegisterHandler( 161 caps.RegisterHandler(
160 "ObjectMediaNavigate", new RestStreamHandler("POST", omuCapUrl, HandleObjectMediaNavigateMessage)); 162 "ObjectMediaNavigate",
163 new RestStreamHandler(
164 "POST", omuCapUrl, HandleObjectMediaNavigateMessage, "ObjectMediaNavigate", agentID.ToString()));
161 } 165 }
162 } 166 }
163 167
diff --git a/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs b/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs
index 4326606..396095a 100644
--- a/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs
+++ b/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs
@@ -53,7 +53,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap.Tests
53 public void SetUp() 53 public void SetUp()
54 { 54 {
55 m_module = new MoapModule(); 55 m_module = new MoapModule();
56 m_scene = SceneHelpers.SetupScene(); 56 m_scene = new SceneHelpers().SetupScene();
57 SceneHelpers.SetupSceneModules(m_scene, m_module); 57 SceneHelpers.SetupSceneModules(m_scene, m_module);
58 } 58 }
59 59
@@ -63,7 +63,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap.Tests
63 TestHelpers.InMethod(); 63 TestHelpers.InMethod();
64// log4net.Config.XmlConfigurator.Configure(); 64// log4net.Config.XmlConfigurator.Configure();
65 65
66 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene); 66 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart;
67 MediaEntry me = new MediaEntry(); 67 MediaEntry me = new MediaEntry();
68 68
69 m_module.SetMediaEntry(part, 1, me); 69 m_module.SetMediaEntry(part, 1, me);
@@ -88,7 +88,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap.Tests
88 88
89 string homeUrl = "opensimulator.org"; 89 string homeUrl = "opensimulator.org";
90 90
91 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene); 91 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart;
92 MediaEntry me = new MediaEntry() { HomeURL = homeUrl }; 92 MediaEntry me = new MediaEntry() { HomeURL = homeUrl };
93 93
94 m_module.SetMediaEntry(part, 1, me); 94 m_module.SetMediaEntry(part, 1, me);
diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
index f5a5c92..e5cd3e2 100644
--- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
@@ -29,8 +29,10 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using System.Text; 31using System.Text;
32using System.Text.RegularExpressions;
32using log4net; 33using log4net;
33using Mono.Addins; 34using Mono.Addins;
35using NDesk.Options;
34using Nini.Config; 36using Nini.Config;
35using OpenMetaverse; 37using OpenMetaverse;
36using OpenSim.Framework; 38using OpenSim.Framework;
@@ -78,49 +80,64 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
78 m_scene = scene; 80 m_scene = scene;
79 m_console = MainConsole.Instance; 81 m_console = MainConsole.Instance;
80 82
81 m_console.Commands.AddCommand("Regions", false, "delete object owner", 83 m_console.Commands.AddCommand(
82 "delete object owner <UUID>", 84 "Objects", false, "delete object owner",
83 "Delete a scene object by owner", HandleDeleteObject); 85 "delete object owner <UUID>",
84 m_console.Commands.AddCommand("Regions", false, "delete object creator", 86 "Delete a scene object by owner", HandleDeleteObject);
85 "delete object creator <UUID>", 87
86 "Delete a scene object by creator", HandleDeleteObject); 88 m_console.Commands.AddCommand(
87 m_console.Commands.AddCommand("Regions", false, "delete object uuid", 89 "Objects", false, "delete object creator",
88 "delete object uuid <UUID>", 90 "delete object creator <UUID>",
89 "Delete a scene object by uuid", HandleDeleteObject); 91 "Delete a scene object by creator", HandleDeleteObject);
90 m_console.Commands.AddCommand("Regions", false, "delete object name", 92
91 "delete object name <name>", 93 m_console.Commands.AddCommand(
92 "Delete a scene object by name", HandleDeleteObject); 94 "Objects", false, "delete object uuid",
93 m_console.Commands.AddCommand("Regions", false, "delete object outside", 95 "delete object uuid <UUID>",
94 "delete object outside", 96 "Delete a scene object by uuid", HandleDeleteObject);
95 "Delete all scene objects outside region boundaries", HandleDeleteObject); 97
98 m_console.Commands.AddCommand(
99 "Objects", false, "delete object name",
100 "delete object name [--regex] <name>",
101 "Delete a scene object by name.",
102 "If --regex is specified then the name is treatead as a regular expression",
103 HandleDeleteObject);
104
105 m_console.Commands.AddCommand(
106 "Objects", false, "delete object outside",
107 "delete object outside",
108 "Delete all scene objects outside region boundaries", HandleDeleteObject);
96 109
97 m_console.Commands.AddCommand( 110 m_console.Commands.AddCommand(
98 "Regions", 111 "Objects",
99 false, 112 false,
100 "show object uuid", 113 "show object uuid",
101 "show object uuid <UUID>", 114 "show object uuid <UUID>",
102 "Show details of a scene object with the given UUID", HandleShowObjectByUuid); 115 "Show details of a scene object with the given UUID", HandleShowObjectByUuid);
103 116
104 m_console.Commands.AddCommand( 117 m_console.Commands.AddCommand(
105 "Regions", 118 "Objects",
106 false, 119 false,
107 "show object name", 120 "show object name",
108 "show object name <name>", 121 "show object name [--regex] <name>",
109 "Show details of scene objects with the given name", HandleShowObjectByName); 122 "Show details of scene objects with the given name.",
123 "If --regex is specified then the name is treatead as a regular expression",
124 HandleShowObjectByName);
110 125
111 m_console.Commands.AddCommand( 126 m_console.Commands.AddCommand(
112 "Regions", 127 "Objects",
113 false, 128 false,
114 "show part uuid", 129 "show part uuid",
115 "show part uuid <UUID>", 130 "show part uuid <UUID>",
116 "Show details of a scene object parts with the given UUID", HandleShowPartByUuid); 131 "Show details of a scene object parts with the given UUID", HandleShowPartByUuid);
117 132
118 m_console.Commands.AddCommand( 133 m_console.Commands.AddCommand(
119 "Regions", 134 "Objects",
120 false, 135 false,
121 "show part name", 136 "show part name",
122 "show part name <name>", 137 "show part name [--regex] <name>",
123 "Show details of scene object parts with the given name", HandleShowPartByName); 138 "Show details of scene object parts with the given name.",
139 "If --regex is specified then the name is treatead as a regular expression",
140 HandleShowPartByName);
124 } 141 }
125 142
126 public void RemoveRegion(Scene scene) 143 public void RemoveRegion(Scene scene)
@@ -165,22 +182,38 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
165 m_console.OutputFormat(sb.ToString()); 182 m_console.OutputFormat(sb.ToString());
166 } 183 }
167 184
168 private void HandleShowObjectByName(string module, string[] cmd) 185 private void HandleShowObjectByName(string module, string[] cmdparams)
169 { 186 {
170 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) 187 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
171 return; 188 return;
172 189
173 if (cmd.Length < 4) 190 bool useRegex = false;
191 OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null );
192
193 List<string> mainParams = options.Parse(cmdparams);
194
195 if (mainParams.Count < 4)
174 { 196 {
175 m_console.OutputFormat("Usage: show object name <name>"); 197 m_console.OutputFormat("Usage: show object name [--regex] <name>");
176 return; 198 return;
177 } 199 }
178 200
179 string name = cmd[3]; 201 string name = mainParams[3];
180 202
181 List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>(); 203 List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>();
204 Action<SceneObjectGroup> searchAction;
182 205
183 m_scene.ForEachSOG(so => { if (so.Name == name) { sceneObjects.Add(so); }}); 206 if (useRegex)
207 {
208 Regex nameRegex = new Regex(name);
209 searchAction = so => { if (nameRegex.IsMatch(so.Name)) { sceneObjects.Add(so); }};
210 }
211 else
212 {
213 searchAction = so => { if (so.Name == name) { sceneObjects.Add(so); }};
214 }
215
216 m_scene.ForEachSOG(searchAction);
184 217
185 if (sceneObjects.Count == 0) 218 if (sceneObjects.Count == 0)
186 { 219 {
@@ -231,22 +264,39 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
231 m_console.OutputFormat(sb.ToString()); 264 m_console.OutputFormat(sb.ToString());
232 } 265 }
233 266
234 private void HandleShowPartByName(string module, string[] cmd) 267 private void HandleShowPartByName(string module, string[] cmdparams)
235 { 268 {
236 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) 269 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
237 return; 270 return;
238 271
239 if (cmd.Length < 4) 272 bool useRegex = false;
273 OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null );
274
275 List<string> mainParams = options.Parse(cmdparams);
276
277 if (mainParams.Count < 4)
240 { 278 {
241 m_console.OutputFormat("Usage: show part name <name>"); 279 m_console.OutputFormat("Usage: show part name [--regex] <name>");
242 return; 280 return;
243 } 281 }
244 282
245 string name = cmd[3]; 283 string name = mainParams[3];
246 284
247 List<SceneObjectPart> parts = new List<SceneObjectPart>(); 285 List<SceneObjectPart> parts = new List<SceneObjectPart>();
248 286
249 m_scene.ForEachSOG(so => so.ForEachPart(sop => { if (sop.Name == name) { parts.Add(sop); } })); 287 Action<SceneObjectGroup> searchAction;
288
289 if (useRegex)
290 {
291 Regex nameRegex = new Regex(name);
292 searchAction = so => so.ForEachPart(sop => { if (nameRegex.IsMatch(sop.Name)) { parts.Add(sop); } });
293 }
294 else
295 {
296 searchAction = so => so.ForEachPart(sop => { if (sop.Name == name) { parts.Add(sop); } });
297 }
298
299 m_scene.ForEachSOG(searchAction);
250 300
251 if (parts.Count == 0) 301 if (parts.Count == 0)
252 { 302 {
@@ -271,6 +321,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
271 sb.AppendFormat("Description: {0}\n", so.Description); 321 sb.AppendFormat("Description: {0}\n", so.Description);
272 sb.AppendFormat("Location: {0} @ {1}\n", so.AbsolutePosition, so.Scene.RegionInfo.RegionName); 322 sb.AppendFormat("Location: {0} @ {1}\n", so.AbsolutePosition, so.Scene.RegionInfo.RegionName);
273 sb.AppendFormat("Parts: {0}\n", so.PrimCount); 323 sb.AppendFormat("Parts: {0}\n", so.PrimCount);
324 sb.AppendFormat("Flags: {0}\n", so.RootPart.Flags);
274 325
275 return sb; 326 return sb;
276 } 327 }
@@ -282,7 +333,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
282 sb.AppendFormat("Location: {0} @ {1}\n", sop.AbsolutePosition, sop.ParentGroup.Scene.RegionInfo.RegionName); 333 sb.AppendFormat("Location: {0} @ {1}\n", sop.AbsolutePosition, sop.ParentGroup.Scene.RegionInfo.RegionName);
283 sb.AppendFormat("Parent: {0}", 334 sb.AppendFormat("Parent: {0}",
284 sop.IsRoot ? "Is Root\n" : string.Format("{0} {1}\n", sop.ParentGroup.Name, sop.ParentGroup.UUID)); 335 sop.IsRoot ? "Is Root\n" : string.Format("{0} {1}\n", sop.ParentGroup.Name, sop.ParentGroup.UUID));
285 sb.AppendFormat("Parts: {0}\n", !sop.IsRoot ? "1" : sop.ParentGroup.PrimCount.ToString());; 336 sb.AppendFormat("Link number: {0}\n", sop.LinkNum);
337 sb.AppendFormat("Flags: {0}\n", sop.Flags);
286 338
287 return sb; 339 return sb;
288 } 340 }
@@ -306,105 +358,169 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
306 o = cmd[3]; 358 o = cmd[3];
307 } 359 }
308 360
309 List<SceneObjectGroup> deletes = new List<SceneObjectGroup>(); 361 List<SceneObjectGroup> deletes = null;
310
311 UUID match; 362 UUID match;
363 bool requireConfirmation = true;
312 364
313 switch (mode) 365 switch (mode)
314 { 366 {
315 case "owner": 367 case "owner":
316 if (!UUID.TryParse(o, out match)) 368 if (!UUID.TryParse(o, out match))
317 return; 369 return;
318 370
319 m_scene.ForEachSOG(delegate (SceneObjectGroup g) 371 deletes = new List<SceneObjectGroup>();
320 {
321 if (g.OwnerID == match && !g.IsAttachment)
322 deletes.Add(g);
323 });
324 372
325// if (deletes.Count == 0) 373 m_scene.ForEachSOG(delegate (SceneObjectGroup g)
326// m_console.OutputFormat("No objects were found with owner {0}", match); 374 {
327 375 if (g.OwnerID == match && !g.IsAttachment)
328 break; 376 deletes.Add(g);
377 });
378
379 // if (deletes.Count == 0)
380 // m_console.OutputFormat("No objects were found with owner {0}", match);
381
382 break;
383
384 case "creator":
385 if (!UUID.TryParse(o, out match))
386 return;
329 387
330 case "creator": 388 deletes = new List<SceneObjectGroup>();
331 if (!UUID.TryParse(o, out match))
332 return;
333 389
334 m_scene.ForEachSOG(delegate (SceneObjectGroup g) 390 m_scene.ForEachSOG(delegate (SceneObjectGroup g)
335 { 391 {
336 if (g.RootPart.CreatorID == match && !g.IsAttachment) 392 if (g.RootPart.CreatorID == match && !g.IsAttachment)
337 deletes.Add(g); 393 deletes.Add(g);
338 }); 394 });
395
396 // if (deletes.Count == 0)
397 // m_console.OutputFormat("No objects were found with creator {0}", match);
398
399 break;
400
401 case "uuid":
402 if (!UUID.TryParse(o, out match))
403 return;
339 404
340// if (deletes.Count == 0) 405 requireConfirmation = false;
341// m_console.OutputFormat("No objects were found with creator {0}", match); 406 deletes = new List<SceneObjectGroup>();
407
408 m_scene.ForEachSOG(delegate (SceneObjectGroup g)
409 {
410 if (g.UUID == match && !g.IsAttachment)
411 deletes.Add(g);
412 });
413
414 // if (deletes.Count == 0)
415 // m_console.OutputFormat("No objects were found with uuid {0}", match);
416
417 break;
418
419 case "name":
420 deletes = GetDeleteCandidatesByName(module, cmd);
421 break;
422
423 case "outside":
424 deletes = new List<SceneObjectGroup>();
342 425
343 break; 426 m_scene.ForEachSOG(delegate (SceneObjectGroup g)
427 {
428 SceneObjectPart rootPart = g.RootPart;
429 bool delete = false;
430
431 if (rootPart.GroupPosition.Z < 0.0 || rootPart.GroupPosition.Z > 10000.0)
432 {
433 delete = true;
434 }
435 else
436 {
437 ILandObject parcel
438 = m_scene.LandChannel.GetLandObject(rootPart.GroupPosition.X, rootPart.GroupPosition.Y);
439
440 if (parcel == null || parcel.LandData.Name == "NO LAND")
441 delete = true;
442 }
443
444 if (delete && !g.IsAttachment && !deletes.Contains(g))
445 deletes.Add(g);
446 });
447
448 if (deletes.Count == 0)
449 m_console.OutputFormat("No objects were found outside region bounds");
450
451 break;
344 452
345 case "uuid": 453 default:
346 if (!UUID.TryParse(o, out match)) 454 m_console.OutputFormat("Unrecognized mode {0}", mode);
347 return; 455 return;
456 }
348 457
349 m_scene.ForEachSOG(delegate (SceneObjectGroup g) 458 if (deletes == null || deletes.Count <= 0)
350 { 459 return;
351 if (g.UUID == match && !g.IsAttachment)
352 deletes.Add(g);
353 });
354
355// if (deletes.Count == 0)
356// m_console.OutputFormat("No objects were found with uuid {0}", match);
357
358 break;
359 460
360 case "name": 461 if (requireConfirmation)
361 m_scene.ForEachSOG(delegate (SceneObjectGroup g) 462 {
463 string response = MainConsole.Instance.CmdPrompt(
464 string.Format(
465 "Are you sure that you want to delete {0} objects from {1}",
466 deletes.Count, m_scene.RegionInfo.RegionName),
467 "n");
468
469 if (response.ToLower() != "y")
362 { 470 {
363 if (g.RootPart.Name == o && !g.IsAttachment) 471 MainConsole.Instance.OutputFormat(
364 deletes.Add(g); 472 "Aborting delete of {0} objects from {1}", deletes.Count, m_scene.RegionInfo.RegionName);
365 });
366 473
367// if (deletes.Count == 0) 474 return;
368// m_console.OutputFormat("No objects were found with name {0}", o); 475 }
369 476 }
370 break;
371 477
372 case "outside": 478 m_console.OutputFormat("Deleting {0} objects in {1}", deletes.Count, m_scene.RegionInfo.RegionName);
373 m_scene.ForEachSOG(delegate (SceneObjectGroup g)
374 {
375 SceneObjectPart rootPart = g.RootPart;
376 bool delete = false;
377 479
378 if (rootPart.GroupPosition.Z < 0.0 || rootPart.GroupPosition.Z > 10000.0) 480 foreach (SceneObjectGroup g in deletes)
379 { 481 {
380 delete = true; 482 m_console.OutputFormat("Deleting object {0} {1}", g.UUID, g.Name);
381 } 483 m_scene.DeleteSceneObject(g, false);
382 else 484 }
383 { 485 }
384 ILandObject parcel
385 = m_scene.LandChannel.GetLandObject(rootPart.GroupPosition.X, rootPart.GroupPosition.Y);
386 486
387 if (parcel == null || parcel.LandData.Name == "NO LAND") 487 private List<SceneObjectGroup> GetDeleteCandidatesByName(string module, string[] cmdparams)
388 delete = true; 488 {
389 } 489 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
490 return null;
390 491
391 if (delete && !g.IsAttachment && !deletes.Contains(g)) 492 bool useRegex = false;
392 deletes.Add(g); 493 OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null );
393 });
394 494
395// if (deletes.Count == 0) 495 List<string> mainParams = options.Parse(cmdparams);
396// m_console.OutputFormat("No objects were found outside region bounds");
397 496
398 break; 497 if (mainParams.Count < 4)
498 {
499 m_console.OutputFormat("Usage: delete object name [--regex] <name>");
500 return null;
399 } 501 }
400 502
401 m_console.OutputFormat("Deleting {0} objects in {1}", deletes.Count, m_scene.RegionInfo.RegionName); 503 string name = mainParams[3];
402 504
403 foreach (SceneObjectGroup g in deletes) 505 List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>();
506 Action<SceneObjectGroup> searchAction;
507
508 if (useRegex)
404 { 509 {
405 m_console.OutputFormat("Deleting object {0} {1}", g.UUID, g.Name); 510 Regex nameRegex = new Regex(name);
406 m_scene.DeleteSceneObject(g, false); 511 searchAction = so => { if (nameRegex.IsMatch(so.Name)) { sceneObjects.Add(so); }};
512 }
513 else
514 {
515 searchAction = so => { if (so.Name == name) { sceneObjects.Add(so); }};
407 } 516 }
517
518 m_scene.ForEachSOG(searchAction);
519
520 if (sceneObjects.Count == 0)
521 m_console.OutputFormat("No objects with name {0} found in {1}", name, m_scene.RegionInfo.RegionName);
522
523 return sceneObjects;
408 } 524 }
409 } 525 }
410} \ No newline at end of file 526} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
index 82ccaf8..f3d38bc 100644
--- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
@@ -166,6 +166,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
166 m_scene.Permissions.OnDeedParcel += CanDeedParcel; 166 m_scene.Permissions.OnDeedParcel += CanDeedParcel;
167 m_scene.Permissions.OnDeedObject += CanDeedObject; 167 m_scene.Permissions.OnDeedObject += CanDeedObject;
168 m_scene.Permissions.OnIsGod += IsGod; 168 m_scene.Permissions.OnIsGod += IsGod;
169 m_scene.Permissions.OnIsGridGod += IsGridGod;
169 m_scene.Permissions.OnIsAdministrator += IsAdministrator; 170 m_scene.Permissions.OnIsAdministrator += IsAdministrator;
170 m_scene.Permissions.OnDuplicateObject += CanDuplicateObject; 171 m_scene.Permissions.OnDuplicateObject += CanDuplicateObject;
171 m_scene.Permissions.OnDeleteObject += CanDeleteObject; //MAYBE FULLY IMPLEMENTED 172 m_scene.Permissions.OnDeleteObject += CanDeleteObject; //MAYBE FULLY IMPLEMENTED
@@ -220,7 +221,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
220 "Force permissions on or off", 221 "Force permissions on or off",
221 HandleForcePermissions); 222 HandleForcePermissions);
222 223
223 m_scene.AddCommand("Users", this, "debug permissions", 224 m_scene.AddCommand("Debug", this, "debug permissions",
224 "debug permissions <true / false>", 225 "debug permissions <true / false>",
225 "Turn on permissions debugging", 226 "Turn on permissions debugging",
226 HandleDebugPermissions); 227 HandleDebugPermissions);
@@ -347,12 +348,12 @@ namespace OpenSim.Region.CoreModules.World.Permissions
347 m_friendsModule = m_scene.RequestModuleInterface<IFriendsModule>(); 348 m_friendsModule = m_scene.RequestModuleInterface<IFriendsModule>();
348 349
349 if (m_friendsModule == null) 350 if (m_friendsModule == null)
350 m_log.Warn("[PERMISSIONS]: Friends module not found, friend permissions will not work"); 351 m_log.Debug("[PERMISSIONS]: Friends module not found, friend permissions will not work");
351 352
352 m_groupsModule = m_scene.RequestModuleInterface<IGroupsModule>(); 353 m_groupsModule = m_scene.RequestModuleInterface<IGroupsModule>();
353 354
354 if (m_groupsModule == null) 355 if (m_groupsModule == null)
355 m_log.Warn("[PERMISSIONS]: Groups module not found, group permissions will not work"); 356 m_log.Debug("[PERMISSIONS]: Groups module not found, group permissions will not work");
356 357
357 m_moapModule = m_scene.RequestModuleInterface<IMoapModule>(); 358 m_moapModule = m_scene.RequestModuleInterface<IMoapModule>();
358 359
@@ -449,39 +450,49 @@ namespace OpenSim.Region.CoreModules.World.Permissions
449 } 450 }
450 451
451 /// <summary> 452 /// <summary>
452 /// Is the given user an administrator (in other words, a god)? 453 /// Is the user regarded as an administrator?
453 /// </summary> 454 /// </summary>
454 /// <param name="user"></param> 455 /// <param name="user"></param>
455 /// <returns></returns> 456 /// <returns></returns>
456 protected bool IsAdministrator(UUID user) 457 protected bool IsAdministrator(UUID user)
457 { 458 {
458 if (user == UUID.Zero) return false; 459 if (user == UUID.Zero)
459 460 return false;
460 if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero) 461
461 { 462 if (m_scene.RegionInfo.EstateSettings.EstateOwner == user && m_RegionOwnerIsGod)
462 if (m_scene.RegionInfo.EstateSettings.EstateOwner == user && m_RegionOwnerIsGod) 463 return true;
463 return true;
464 }
465 464
466 if (IsEstateManager(user) && m_RegionManagerIsGod) 465 if (IsEstateManager(user) && m_RegionManagerIsGod)
467 return true; 466 return true;
468 467
468 if (IsGridGod(user, null))
469 return true;
470
471 return false;
472 }
473
474 /// <summary>
475 /// Is the given user a God throughout the grid (not just in the current scene)?
476 /// </summary>
477 /// <param name="user">The user</param>
478 /// <param name="scene">Unused, can be null</param>
479 /// <returns></returns>
480 protected bool IsGridGod(UUID user, Scene scene)
481 {
482 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
483 if (m_bypassPermissions) return m_bypassPermissionsValue;
484
485 if (user == UUID.Zero) return false;
486
469 if (m_allowGridGods) 487 if (m_allowGridGods)
470 { 488 {
471 ScenePresence sp = m_scene.GetScenePresence(user); 489 ScenePresence sp = m_scene.GetScenePresence(user);
472 if (sp != null) 490 if (sp != null)
473 { 491 return (sp.UserLevel >= 200);
474 if (sp.UserLevel >= 200)
475 return true;
476 return false;
477 }
478 492
479 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, user); 493 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, user);
480 if (account != null) 494 if (account != null)
481 { 495 return (account.UserLevel >= 200);
482 if (account.UserLevel >= 200)
483 return true;
484 }
485 } 496 }
486 497
487 return false; 498 return false;
@@ -503,7 +514,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
503 { 514 {
504 if (user == UUID.Zero) return false; 515 if (user == UUID.Zero) return false;
505 516
506 return m_scene.RegionInfo.EstateSettings.IsEstateManager(user); 517 return m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(user);
507 } 518 }
508 519
509#endregion 520#endregion
diff --git a/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs b/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs
new file mode 100644
index 0000000..2838e0c
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs
@@ -0,0 +1,155 @@
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.Text;
32using System.Text.RegularExpressions;
33using log4net;
34using Mono.Addins;
35using NDesk.Options;
36using Nini.Config;
37using OpenMetaverse;
38using OpenSim.Framework;
39using OpenSim.Framework.Console;
40using OpenSim.Framework.Statistics;
41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes;
43
44namespace OpenSim.Region.CoreModules.World.Objects.Commands
45{
46 /// <summary>
47 /// A module that holds commands for manipulating objects in the scene.
48 /// </summary>
49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RegionCommandsModule")]
50 public class RegionCommandsModule : INonSharedRegionModule
51 {
52 private Scene m_scene;
53 private ICommandConsole m_console;
54
55 public string Name { get { return "Region Commands Module"; } }
56
57 public Type ReplaceableInterface { get { return null; } }
58
59 public void Initialise(IConfigSource source)
60 {
61// m_log.DebugFormat("[REGION COMMANDS MODULE]: INITIALIZED MODULE");
62 }
63
64 public void PostInitialise()
65 {
66// m_log.DebugFormat("[REGION COMMANDS MODULE]: POST INITIALIZED MODULE");
67 }
68
69 public void Close()
70 {
71// m_log.DebugFormat("[REGION COMMANDS MODULE]: CLOSED MODULE");
72 }
73
74 public void AddRegion(Scene scene)
75 {
76// m_log.DebugFormat("[REGION COMMANDS MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName);
77
78 m_scene = scene;
79 m_console = MainConsole.Instance;
80
81 m_console.Commands.AddCommand(
82 "Regions", false, "show scene",
83 "show scene",
84 "Show live scene information for the currently selected region.", HandleShowScene);
85 }
86
87 public void RemoveRegion(Scene scene)
88 {
89// m_log.DebugFormat("[REGION COMMANDS MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName);
90 }
91
92 public void RegionLoaded(Scene scene)
93 {
94// m_log.DebugFormat("[REGION COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName);
95 }
96
97 private void HandleShowScene(string module, string[] cmd)
98 {
99 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_scene))
100 return;
101
102 SimStatsReporter r = m_scene.StatsReporter;
103 float[] stats = r.LastReportedSimStats;
104
105 float timeDilation = stats[0];
106 float simFps = stats[1];
107 float physicsFps = stats[2];
108 float agentUpdates = stats[3];
109 float rootAgents = stats[4];
110 float childAgents = stats[5];
111 float totalPrims = stats[6];
112 float activePrims = stats[7];
113 float totalFrameTime = stats[8];
114// float netFrameTime = stats.StatsBlock[9].StatValue; // Ignored - not used by OpenSimulator
115 float physicsFrameTime = stats[10];
116 float otherFrameTime = stats[11];
117// float imageFrameTime = stats.StatsBlock[12].StatValue; // Ignored
118 float inPacketsPerSecond = stats[13];
119 float outPacketsPerSecond = stats[14];
120 float unackedBytes = stats[15];
121// float agentFrameTime = stats.StatsBlock[16].StatValue; // Not really used
122 float pendingDownloads = stats[17];
123 float pendingUploads = stats[18];
124 float activeScripts = stats[19];
125 float scriptLinesPerSecond = stats[20];
126
127 StringBuilder sb = new StringBuilder();
128 sb.AppendFormat("Scene statistics for {0}\n", m_scene.RegionInfo.RegionName);
129
130 ConsoleDisplayList dispList = new ConsoleDisplayList();
131 dispList.AddRow("Time Dilation", timeDilation);
132 dispList.AddRow("Sim FPS", simFps);
133 dispList.AddRow("Physics FPS", physicsFps);
134 dispList.AddRow("Avatars", rootAgents);
135 dispList.AddRow("Child agents", childAgents);
136 dispList.AddRow("Total prims", totalPrims);
137 dispList.AddRow("Scripts", activeScripts);
138 dispList.AddRow("Script lines processed per second", scriptLinesPerSecond);
139 dispList.AddRow("Physics enabled prims", activePrims);
140 dispList.AddRow("Total frame time", totalFrameTime);
141 dispList.AddRow("Physics frame time", physicsFrameTime);
142 dispList.AddRow("Other frame time", otherFrameTime);
143 dispList.AddRow("Agent Updates per second", agentUpdates);
144 dispList.AddRow("Packets processed from clients per second", inPacketsPerSecond);
145 dispList.AddRow("Packets sent to clients per second", outPacketsPerSecond);
146 dispList.AddRow("Bytes unacknowledged by clients", unackedBytes);
147 dispList.AddRow("Pending asset downloads to clients", pendingDownloads);
148 dispList.AddRow("Pending asset uploads from clients", pendingUploads);
149
150 dispList.AddToStringBuilder(sb);
151
152 MainConsole.Instance.Output(sb.ToString());
153 }
154 }
155} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs
index d1d2020..7825e3e 100644
--- a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs
+++ b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs
@@ -343,7 +343,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
343 public void Init() 343 public void Init()
344 { 344 {
345 m_serialiserModule = new SerialiserModule(); 345 m_serialiserModule = new SerialiserModule();
346 m_scene = SceneHelpers.SetupScene(); 346 m_scene = new SceneHelpers().SetupScene();
347 SceneHelpers.SetupSceneModules(m_scene, m_serialiserModule); 347 SceneHelpers.SetupSceneModules(m_scene, m_serialiserModule);
348 } 348 }
349 349
diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
index 93b1005..d768a1a 100644
--- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
+++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
@@ -78,11 +78,8 @@ namespace OpenSim.Region.CoreModules.World.Sound
78 78
79 if (grp.IsAttachment) 79 if (grp.IsAttachment)
80 { 80 {
81 if (grp.AttachmentPoint > 30) // HUD 81 if (grp.HasPrivateAttachmentPoint && sp.ControllingClient.AgentId != grp.OwnerID)
82 { 82 return;
83 if (sp.ControllingClient.AgentId != grp.OwnerID)
84 return;
85 }
86 83
87 if (sp.ControllingClient.AgentId == grp.OwnerID) 84 if (sp.ControllingClient.AgentId == grp.OwnerID)
88 dis = 0; 85 dis = 0;
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
index da81dc1..d78ade5 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
@@ -59,28 +59,32 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
59 /// <returns>A terrain channel generated from the image.</returns> 59 /// <returns>A terrain channel generated from the image.</returns>
60 public virtual ITerrainChannel LoadFile(string filename) 60 public virtual ITerrainChannel LoadFile(string filename)
61 { 61 {
62 return LoadBitmap(new Bitmap(filename)); 62 using (Bitmap b = new Bitmap(filename))
63 return LoadBitmap(b);
63 } 64 }
64 65
65 public virtual ITerrainChannel LoadFile(string filename, int offsetX, int offsetY, int fileWidth, int fileHeight, int w, int h) 66 public virtual ITerrainChannel LoadFile(string filename, int offsetX, int offsetY, int fileWidth, int fileHeight, int w, int h)
66 { 67 {
67 Bitmap bitmap = new Bitmap(filename); 68 using (Bitmap bitmap = new Bitmap(filename))
68 ITerrainChannel retval = new TerrainChannel(true);
69
70 for (int x = 0; x < retval.Width; x++)
71 { 69 {
72 for (int y = 0; y < retval.Height; y++) 70 ITerrainChannel retval = new TerrainChannel(true);
71
72 for (int x = 0; x < retval.Width; x++)
73 { 73 {
74 retval[x, y] = bitmap.GetPixel(offsetX * retval.Width + x, (bitmap.Height - (retval.Height * (offsetY + 1))) + retval.Height - y - 1).GetBrightness() * 128; 74 for (int y = 0; y < retval.Height; y++)
75 {
76 retval[x, y] = bitmap.GetPixel(offsetX * retval.Width + x, (bitmap.Height - (retval.Height * (offsetY + 1))) + retval.Height - y - 1).GetBrightness() * 128;
77 }
75 } 78 }
76 }
77 79
78 return retval; 80 return retval;
81 }
79 } 82 }
80 83
81 public virtual ITerrainChannel LoadStream(Stream stream) 84 public virtual ITerrainChannel LoadStream(Stream stream)
82 { 85 {
83 return LoadBitmap(new Bitmap(stream)); 86 using (Bitmap b = new Bitmap(stream))
87 return LoadBitmap(b);
84 } 88 }
85 89
86 protected virtual ITerrainChannel LoadBitmap(Bitmap bitmap) 90 protected virtual ITerrainChannel LoadBitmap(Bitmap bitmap)
@@ -134,35 +138,53 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
134 // "Saving the image to the same file it was constructed from is not allowed and throws an exception." 138 // "Saving the image to the same file it was constructed from is not allowed and throws an exception."
135 string tempName = Path.GetTempFileName(); 139 string tempName = Path.GetTempFileName();
136 140
137 Bitmap entireBitmap = null; 141 Bitmap existingBitmap = null;
138 Bitmap thisBitmap = null; 142 Bitmap thisBitmap = null;
139 if (File.Exists(filename)) 143 Bitmap newBitmap = null;
144
145 try
140 { 146 {
141 File.Copy(filename, tempName, true); 147 if (File.Exists(filename))
142 entireBitmap = new Bitmap(tempName); 148 {
143 if (entireBitmap.Width != fileWidth * regionSizeX || entireBitmap.Height != fileHeight * regionSizeY) 149 File.Copy(filename, tempName, true);
150 existingBitmap = new Bitmap(tempName);
151 if (existingBitmap.Width != fileWidth * regionSizeX || existingBitmap.Height != fileHeight * regionSizeY)
152 {
153 // old file, let's overwrite it
154 newBitmap = new Bitmap(fileWidth * regionSizeX, fileHeight * regionSizeY);
155 }
156 else
157 {
158 newBitmap = existingBitmap;
159 }
160 }
161 else
144 { 162 {
145 // old file, let's overwrite it 163 newBitmap = new Bitmap(fileWidth * regionSizeX, fileHeight * regionSizeY);
146 entireBitmap = new Bitmap(fileWidth * regionSizeX, fileHeight * regionSizeY);
147 } 164 }
165
166 thisBitmap = CreateGrayscaleBitmapFromMap(m_channel);
167 // Console.WriteLine("offsetX=" + offsetX + " offsetY=" + offsetY);
168 for (int x = 0; x < regionSizeX; x++)
169 for (int y = 0; y < regionSizeY; y++)
170 newBitmap.SetPixel(x + offsetX * regionSizeX, y + (fileHeight - 1 - offsetY) * regionSizeY, thisBitmap.GetPixel(x, y));
171
172 Save(newBitmap, filename);
148 } 173 }
149 else 174 finally
150 { 175 {
151 entireBitmap = new Bitmap(fileWidth * regionSizeX, fileHeight * regionSizeY); 176 if (existingBitmap != null)
152 } 177 existingBitmap.Dispose();
153 178
154 thisBitmap = CreateGrayscaleBitmapFromMap(m_channel); 179 if (thisBitmap != null)
155// Console.WriteLine("offsetX=" + offsetX + " offsetY=" + offsetY); 180 thisBitmap.Dispose();
156 for (int x = 0; x < regionSizeX; x++)
157 for (int y = 0; y < regionSizeY; y++)
158 entireBitmap.SetPixel(x + offsetX * regionSizeX, y + (fileHeight - 1 - offsetY) * regionSizeY, thisBitmap.GetPixel(x, y));
159 181
160 Save(entireBitmap, filename); 182 if (newBitmap != null)
161 thisBitmap.Dispose(); 183 newBitmap.Dispose();
162 entireBitmap.Dispose();
163 184
164 if (File.Exists(tempName)) 185 if (File.Exists(tempName))
165 File.Delete(tempName); 186 File.Delete(tempName);
187 }
166 } 188 }
167 189
168 protected virtual void Save(Bitmap bmp, string filename) 190 protected virtual void Save(Bitmap bmp, string filename)
@@ -226,16 +248,21 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
226 /// <returns>A System.Drawing.Bitmap containing a coloured image</returns> 248 /// <returns>A System.Drawing.Bitmap containing a coloured image</returns>
227 protected static Bitmap CreateBitmapFromMap(ITerrainChannel map) 249 protected static Bitmap CreateBitmapFromMap(ITerrainChannel map)
228 { 250 {
229 Bitmap gradientmapLd = new Bitmap("defaultstripe.png"); 251 int pallete;
230 252 Bitmap bmp;
231 int pallete = gradientmapLd.Height; 253 Color[] colours;
232 254
233 Bitmap bmp = new Bitmap(map.Width, map.Height); 255 using (Bitmap gradientmapLd = new Bitmap("defaultstripe.png"))
234 Color[] colours = new Color[pallete];
235
236 for (int i = 0; i < pallete; i++)
237 { 256 {
238 colours[i] = gradientmapLd.GetPixel(0, i); 257 pallete = gradientmapLd.Height;
258
259 bmp = new Bitmap(map.Width, map.Height);
260 colours = new Color[pallete];
261
262 for (int i = 0; i < pallete; i++)
263 {
264 colours[i] = gradientmapLd.GetPixel(0, i);
265 }
239 } 266 }
240 267
241 for (int y = 0; y < map.Height; y++) 268 for (int y = 0; y < map.Height; y++)
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs
index 699d67a..9cc767a 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs
@@ -99,16 +99,21 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
99 99
100 private static Bitmap CreateBitmapFromMap(ITerrainChannel map) 100 private static Bitmap CreateBitmapFromMap(ITerrainChannel map)
101 { 101 {
102 Bitmap gradientmapLd = new Bitmap("defaultstripe.png"); 102 int pallete;
103 Bitmap bmp;
104 Color[] colours;
103 105
104 int pallete = gradientmapLd.Height; 106 using (Bitmap gradientmapLd = new Bitmap("defaultstripe.png"))
105
106 Bitmap bmp = new Bitmap(map.Width, map.Height);
107 Color[] colours = new Color[pallete];
108
109 for (int i = 0; i < pallete; i++)
110 { 107 {
111 colours[i] = gradientmapLd.GetPixel(0, i); 108 pallete = gradientmapLd.Height;
109
110 bmp = new Bitmap(map.Width, map.Height);
111 colours = new Color[pallete];
112
113 for (int i = 0; i < pallete; i++)
114 {
115 colours[i] = gradientmapLd.GetPixel(0, i);
116 }
112 } 117 }
113 118
114 for (int y = 0; y < map.Height; y++) 119 for (int y = 0; y < map.Height; y++)
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/TIFF.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/TIFF.cs
index 5d2f893..b416b82 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/TIFF.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/TIFF.cs
@@ -59,7 +59,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
59 } 59 }
60 60
61 //Returns true if this extension is supported for terrain save-tile 61 //Returns true if this extension is supported for terrain save-tile
62 public bool SupportsTileSave() 62 public override bool SupportsTileSave()
63 { 63 {
64 return false; 64 return false;
65 } 65 }
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs
index 1ebf916..b5c7d33 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs
@@ -65,7 +65,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
65 bool eof = false; 65 bool eof = false;
66 66
67 int fileXPoints = 0; 67 int fileXPoints = 0;
68 int fileYPoints = 0; 68// int fileYPoints = 0;
69 69
70 // Terragen file 70 // Terragen file
71 while (eof == false) 71 while (eof == false)
@@ -75,7 +75,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
75 { 75 {
76 case "SIZE": 76 case "SIZE":
77 fileXPoints = bs.ReadInt16() + 1; 77 fileXPoints = bs.ReadInt16() + 1;
78 fileYPoints = fileXPoints; 78// fileYPoints = fileXPoints;
79 bs.ReadInt16(); 79 bs.ReadInt16();
80 break; 80 break;
81 case "XPTS": 81 case "XPTS":
@@ -83,7 +83,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
83 bs.ReadInt16(); 83 bs.ReadInt16();
84 break; 84 break;
85 case "YPTS": 85 case "YPTS":
86 fileYPoints = bs.ReadInt16(); 86// fileYPoints = bs.ReadInt16();
87 bs.ReadInt16();
87 bs.ReadInt16(); 88 bs.ReadInt16();
88 break; 89 break;
89 case "ALTW": 90 case "ALTW":
@@ -164,10 +165,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
164 bool eof = false; 165 bool eof = false;
165 if (Encoding.ASCII.GetString(bs.ReadBytes(16)) == "TERRAGENTERRAIN ") 166 if (Encoding.ASCII.GetString(bs.ReadBytes(16)) == "TERRAGENTERRAIN ")
166 { 167 {
167 168// int fileWidth = w;
168 int fileWidth = w; 169// int fileHeight = h;
169 int fileHeight = h;
170
171 170
172 // Terragen file 171 // Terragen file
173 while (eof == false) 172 while (eof == false)
@@ -176,17 +175,20 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
176 switch (tmp) 175 switch (tmp)
177 { 176 {
178 case "SIZE": 177 case "SIZE":
179 int sztmp = bs.ReadInt16() + 1; 178// int sztmp = bs.ReadInt16() + 1;
180 fileWidth = sztmp; 179// fileWidth = sztmp;
181 fileHeight = sztmp; 180// fileHeight = sztmp;
181 bs.ReadInt16();
182 bs.ReadInt16(); 182 bs.ReadInt16();
183 break; 183 break;
184 case "XPTS": 184 case "XPTS":
185 fileWidth = bs.ReadInt16(); 185// fileWidth = bs.ReadInt16();
186 bs.ReadInt16();
186 bs.ReadInt16(); 187 bs.ReadInt16();
187 break; 188 break;
188 case "YPTS": 189 case "YPTS":
189 fileHeight = bs.ReadInt16(); 190// fileHeight = bs.ReadInt16();
191 bs.ReadInt16();
190 bs.ReadInt16(); 192 bs.ReadInt16();
191 break; 193 break;
192 case "ALTW": 194 case "ALTW":
@@ -250,7 +252,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
250 if (horizontalScale < 0.01d) 252 if (horizontalScale < 0.01d)
251 horizontalScale = 0.01d; 253 horizontalScale = 0.01d;
252 254
253 System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); 255 Encoding enc = Encoding.ASCII;
254 256
255 bs.Write(enc.GetBytes("TERRAGENTERRAIN ")); 257 bs.Write(enc.GetBytes("TERRAGENTERRAIN "));
256 258
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
index e2bd769..402b9fb 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
@@ -724,6 +724,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
724 } 724 }
725 if (shouldTaint) 725 if (shouldTaint)
726 { 726 {
727 m_scene.EventManager.TriggerTerrainTainted();
727 m_tainted = true; 728 m_tainted = true;
728 } 729 }
729 } 730 }
@@ -1109,6 +1110,32 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1109 CheckForTerrainUpdates(); 1110 CheckForTerrainUpdates();
1110 } 1111 }
1111 1112
1113 private void InterfaceMinTerrain(Object[] args)
1114 {
1115 int x, y;
1116 for (x = 0; x < m_channel.Width; x++)
1117 {
1118 for (y = 0; y < m_channel.Height; y++)
1119 {
1120 m_channel[x, y] = Math.Max((double)args[0], m_channel[x, y]);
1121 }
1122 }
1123 CheckForTerrainUpdates();
1124 }
1125
1126 private void InterfaceMaxTerrain(Object[] args)
1127 {
1128 int x, y;
1129 for (x = 0; x < m_channel.Width; x++)
1130 {
1131 for (y = 0; y < m_channel.Height; y++)
1132 {
1133 m_channel[x, y] = Math.Min((double)args[0], m_channel[x, y]);
1134 }
1135 }
1136 CheckForTerrainUpdates();
1137 }
1138
1112 private void InterfaceShowDebugStats(Object[] args) 1139 private void InterfaceShowDebugStats(Object[] args)
1113 { 1140 {
1114 double max = Double.MinValue; 1141 double max = Double.MinValue;
@@ -1249,6 +1276,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1249 rescaleCommand.AddArgument("min", "min terrain height after rescaling", "Double"); 1276 rescaleCommand.AddArgument("min", "min terrain height after rescaling", "Double");
1250 rescaleCommand.AddArgument("max", "max terrain height after rescaling", "Double"); 1277 rescaleCommand.AddArgument("max", "max terrain height after rescaling", "Double");
1251 1278
1279 Command minCommand = new Command("min", CommandIntentions.COMMAND_HAZARDOUS, InterfaceMinTerrain, "Sets the minimum terrain height to the specified value.");
1280 minCommand.AddArgument("min", "terrain height to use as minimum", "Double");
1281
1282 Command maxCommand = new Command("max", CommandIntentions.COMMAND_HAZARDOUS, InterfaceMaxTerrain, "Sets the maximum terrain height to the specified value.");
1283 maxCommand.AddArgument("min", "terrain height to use as maximum", "Double");
1284
1252 1285
1253 // Debug 1286 // Debug
1254 Command showDebugStatsCommand = 1287 Command showDebugStatsCommand =
@@ -1280,6 +1313,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1280 m_commander.RegisterCommand("effect", pluginRunCommand); 1313 m_commander.RegisterCommand("effect", pluginRunCommand);
1281 m_commander.RegisterCommand("flip", flipCommand); 1314 m_commander.RegisterCommand("flip", flipCommand);
1282 m_commander.RegisterCommand("rescale", rescaleCommand); 1315 m_commander.RegisterCommand("rescale", rescaleCommand);
1316 m_commander.RegisterCommand("min", minCommand);
1317 m_commander.RegisterCommand("max", maxCommand);
1283 1318
1284 // Add this to our scene so scripts can call these functions 1319 // Add this to our scene so scripts can call these functions
1285 m_scene.RegisterModuleCommander(m_commander); 1320 m_scene.RegisterModuleCommander(m_commander);
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs
index 7bf675d..df5ac92 100644
--- a/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs
+++ b/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs
@@ -84,218 +84,241 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
84 Debug.Assert(heightRanges.Length == 4); 84 Debug.Assert(heightRanges.Length == 4);
85 85
86 Bitmap[] detailTexture = new Bitmap[4]; 86 Bitmap[] detailTexture = new Bitmap[4];
87 Bitmap output = null;
88 BitmapData outputData = null;
87 89
88 if (textureTerrain) 90 try
89 { 91 {
90 // Swap empty terrain textureIDs with default IDs 92 if (textureTerrain)
91 for (int i = 0; i < textureIDs.Length; i++)
92 { 93 {
93 if (textureIDs[i] == UUID.Zero) 94 // Swap empty terrain textureIDs with default IDs
94 textureIDs[i] = DEFAULT_TERRAIN_DETAIL[i]; 95 for (int i = 0; i < textureIDs.Length; i++)
95 }
96
97 #region Texture Fetching
98
99 if (assetService != null)
100 {
101 for (int i = 0; i < 4; i++)
102 { 96 {
103 AssetBase asset; 97 if (textureIDs[i] == UUID.Zero)
104 UUID cacheID = UUID.Combine(TERRAIN_CACHE_MAGIC, textureIDs[i]); 98 textureIDs[i] = DEFAULT_TERRAIN_DETAIL[i];
105 99 }
106 // Try to fetch a cached copy of the decoded/resized version of this texture 100
107 asset = assetService.GetCached(cacheID.ToString()); 101 #region Texture Fetching
108 if (asset != null) 102
109 { 103 if (assetService != null)
110 try 104 {
111 { 105 for (int i = 0; i < 4; i++)
112 using (System.IO.MemoryStream stream = new System.IO.MemoryStream(asset.Data))
113 detailTexture[i] = (Bitmap)Image.FromStream(stream);
114 }
115 catch (Exception ex)
116 {
117 m_log.Warn("Failed to decode cached terrain texture " + cacheID +
118 " (textureID: " + textureIDs[i] + "): " + ex.Message);
119 }
120 }
121
122 if (detailTexture[i] == null)
123 { 106 {
124 // Try to fetch the original JPEG2000 texture, resize if needed, and cache as PNG 107 AssetBase asset;
125 asset = assetService.Get(textureIDs[i].ToString()); 108 UUID cacheID = UUID.Combine(TERRAIN_CACHE_MAGIC, textureIDs[i]);
109
110 // Try to fetch a cached copy of the decoded/resized version of this texture
111 asset = assetService.GetCached(cacheID.ToString());
126 if (asset != null) 112 if (asset != null)
127 { 113 {
128 try { detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); } 114// m_log.DebugFormat(
115// "[TERRAIN SPLAT]: Got asset service cached terrain texture {0} {1}", i, asset.ID);
116
117 try
118 {
119 using (System.IO.MemoryStream stream = new System.IO.MemoryStream(asset.Data))
120 detailTexture[i] = (Bitmap)Image.FromStream(stream);
121 }
129 catch (Exception ex) 122 catch (Exception ex)
130 { 123 {
131 m_log.Warn("Failed to decode terrain texture " + asset.ID + ": " + ex.Message); 124 m_log.Warn("Failed to decode cached terrain texture " + cacheID +
125 " (textureID: " + textureIDs[i] + "): " + ex.Message);
132 } 126 }
133 } 127 }
134 128
135 if (detailTexture[i] != null) 129 if (detailTexture[i] == null)
136 { 130 {
137 Bitmap bitmap = detailTexture[i]; 131 // Try to fetch the original JPEG2000 texture, resize if needed, and cache as PNG
138 132 asset = assetService.Get(textureIDs[i].ToString());
139 // Make sure this texture is the correct size, otherwise resize 133 if (asset != null)
140 if (bitmap.Width != 256 || bitmap.Height != 256)
141 bitmap = ImageUtils.ResizeImage(bitmap, 256, 256);
142
143 // Save the decoded and resized texture to the cache
144 byte[] data;
145 using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
146 { 134 {
147 bitmap.Save(stream, ImageFormat.Png); 135// m_log.DebugFormat(
148 data = stream.ToArray(); 136// "[TERRAIN SPLAT]: Got cached original JPEG2000 terrain texture {0} {1}", i, asset.ID);
137
138 try { detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); }
139 catch (Exception ex)
140 {
141 m_log.Warn("Failed to decode terrain texture " + asset.ID + ": " + ex.Message);
142 }
143 }
144
145 if (detailTexture[i] != null)
146 {
147 // Make sure this texture is the correct size, otherwise resize
148 if (detailTexture[i].Width != 256 || detailTexture[i].Height != 256)
149 {
150 using (Bitmap origBitmap = detailTexture[i])
151 {
152 detailTexture[i] = ImageUtils.ResizeImage(origBitmap, 256, 256);
153 }
154 }
155
156 // Save the decoded and resized texture to the cache
157 byte[] data;
158 using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
159 {
160 detailTexture[i].Save(stream, ImageFormat.Png);
161 data = stream.ToArray();
162 }
163
164 // Cache a PNG copy of this terrain texture
165 AssetBase newAsset = new AssetBase
166 {
167 Data = data,
168 Description = "PNG",
169 Flags = AssetFlags.Collectable,
170 FullID = cacheID,
171 ID = cacheID.ToString(),
172 Local = true,
173 Name = String.Empty,
174 Temporary = true,
175 Type = (sbyte)AssetType.Unknown
176 };
177 newAsset.Metadata.ContentType = "image/png";
178 assetService.Store(newAsset);
149 } 179 }
150
151 // Cache a PNG copy of this terrain texture
152 AssetBase newAsset = new AssetBase
153 {
154 Data = data,
155 Description = "PNG",
156 Flags = AssetFlags.Collectable,
157 FullID = cacheID,
158 ID = cacheID.ToString(),
159 Local = true,
160 Name = String.Empty,
161 Temporary = true,
162 Type = (sbyte)AssetType.Unknown
163 };
164 newAsset.Metadata.ContentType = "image/png";
165 assetService.Store(newAsset);
166 } 180 }
167 } 181 }
168 } 182 }
183
184 #endregion Texture Fetching
169 } 185 }
170 186
171 #endregion Texture Fetching 187 // Fill in any missing textures with a solid color
172 } 188 for (int i = 0; i < 4; i++)
173
174 // Fill in any missing textures with a solid color
175 for (int i = 0; i < 4; i++)
176 {
177 if (detailTexture[i] == null)
178 { 189 {
179 // Create a solid color texture for this layer 190 if (detailTexture[i] == null)
180 detailTexture[i] = new Bitmap(256, 256, PixelFormat.Format24bppRgb);
181 using (Graphics gfx = Graphics.FromImage(detailTexture[i]))
182 { 191 {
183 using (SolidBrush brush = new SolidBrush(DEFAULT_TERRAIN_COLOR[i])) 192// m_log.DebugFormat(
184 gfx.FillRectangle(brush, 0, 0, 256, 256); 193// "[TERRAIN SPLAT]: Generating solid colour for missing texture {0}", i);
185 }
186 }
187 }
188
189 #region Layer Map
190
191 float[] layermap = new float[256 * 256];
192
193 for (int y = 0; y < 256; y++)
194 {
195 for (int x = 0; x < 256; x++)
196 {
197 float height = heightmap[y * 256 + x];
198 194
199 float pctX = (float)x / 255f; 195 // Create a solid color texture for this layer
200 float pctY = (float)y / 255f; 196 detailTexture[i] = new Bitmap(256, 256, PixelFormat.Format24bppRgb);
201 197 using (Graphics gfx = Graphics.FromImage(detailTexture[i]))
202 // Use bilinear interpolation between the four corners of start height and 198 {
203 // height range to select the current values at this position 199 using (SolidBrush brush = new SolidBrush(DEFAULT_TERRAIN_COLOR[i]))
204 float startHeight = ImageUtils.Bilinear( 200 gfx.FillRectangle(brush, 0, 0, 256, 256);
205 startHeights[0], 201 }
206 startHeights[2], 202 }
207 startHeights[1],
208 startHeights[3],
209 pctX, pctY);
210 startHeight = Utils.Clamp(startHeight, 0f, 255f);
211
212 float heightRange = ImageUtils.Bilinear(
213 heightRanges[0],
214 heightRanges[2],
215 heightRanges[1],
216 heightRanges[3],
217 pctX, pctY);
218 heightRange = Utils.Clamp(heightRange, 0f, 255f);
219
220 // Generate two frequencies of perlin noise based on our global position
221 // The magic values were taken from http://opensimulator.org/wiki/Terrain_Splatting
222 Vector3 vec = new Vector3
223 (
224 ((float)regionPosition.X + x) * 0.20319f,
225 ((float)regionPosition.Y + y) * 0.20319f,
226 height * 0.25f
227 );
228
229 float lowFreq = Perlin.noise2(vec.X * 0.222222f, vec.Y * 0.222222f) * 6.5f;
230 float highFreq = Perlin.turbulence2(vec.X, vec.Y, 2f) * 2.25f;
231 float noise = (lowFreq + highFreq) * 2f;
232
233 // Combine the current height, generated noise, start height, and height range parameters, then scale all of it
234 float layer = ((height + noise - startHeight) / heightRange) * 4f;
235 if (Single.IsNaN(layer)) layer = 0f;
236 layermap[y * 256 + x] = Utils.Clamp(layer, 0f, 3f);
237 } 203 }
238 } 204
239 205 #region Layer Map
240 #endregion Layer Map 206
241 207 float[] layermap = new float[256 * 256];
242 #region Texture Compositing 208
243
244 Bitmap output = new Bitmap(256, 256, PixelFormat.Format24bppRgb);
245 BitmapData outputData = output.LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
246
247 unsafe
248 {
249 // Get handles to all of the texture data arrays
250 BitmapData[] datas = new BitmapData[]
251 {
252 detailTexture[0].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[0].PixelFormat),
253 detailTexture[1].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[1].PixelFormat),
254 detailTexture[2].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[2].PixelFormat),
255 detailTexture[3].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[3].PixelFormat)
256 };
257
258 int[] comps = new int[]
259 {
260 (datas[0].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
261 (datas[1].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
262 (datas[2].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
263 (datas[3].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3
264 };
265
266 for (int y = 0; y < 256; y++) 209 for (int y = 0; y < 256; y++)
267 { 210 {
268 for (int x = 0; x < 256; x++) 211 for (int x = 0; x < 256; x++)
269 { 212 {
270 float layer = layermap[y * 256 + x]; 213 float height = heightmap[y * 256 + x];
271 214
272 // Select two textures 215 float pctX = (float)x / 255f;
273 int l0 = (int)Math.Floor(layer); 216 float pctY = (float)y / 255f;
274 int l1 = Math.Min(l0 + 1, 3); 217
275 218 // Use bilinear interpolation between the four corners of start height and
276 byte* ptrA = (byte*)datas[l0].Scan0 + y * datas[l0].Stride + x * comps[l0]; 219 // height range to select the current values at this position
277 byte* ptrB = (byte*)datas[l1].Scan0 + y * datas[l1].Stride + x * comps[l1]; 220 float startHeight = ImageUtils.Bilinear(
278 byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride + x * 3; 221 startHeights[0],
279 222 startHeights[2],
280 float aB = *(ptrA + 0); 223 startHeights[1],
281 float aG = *(ptrA + 1); 224 startHeights[3],
282 float aR = *(ptrA + 2); 225 pctX, pctY);
283 226 startHeight = Utils.Clamp(startHeight, 0f, 255f);
284 float bB = *(ptrB + 0); 227
285 float bG = *(ptrB + 1); 228 float heightRange = ImageUtils.Bilinear(
286 float bR = *(ptrB + 2); 229 heightRanges[0],
287 230 heightRanges[2],
288 float layerDiff = layer - l0; 231 heightRanges[1],
289 232 heightRanges[3],
290 // Interpolate between the two selected textures 233 pctX, pctY);
291 *(ptrO + 0) = (byte)Math.Floor(aB + layerDiff * (bB - aB)); 234 heightRange = Utils.Clamp(heightRange, 0f, 255f);
292 *(ptrO + 1) = (byte)Math.Floor(aG + layerDiff * (bG - aG)); 235
293 *(ptrO + 2) = (byte)Math.Floor(aR + layerDiff * (bR - aR)); 236 // Generate two frequencies of perlin noise based on our global position
237 // The magic values were taken from http://opensimulator.org/wiki/Terrain_Splatting
238 Vector3 vec = new Vector3
239 (
240 ((float)regionPosition.X + x) * 0.20319f,
241 ((float)regionPosition.Y + y) * 0.20319f,
242 height * 0.25f
243 );
244
245 float lowFreq = Perlin.noise2(vec.X * 0.222222f, vec.Y * 0.222222f) * 6.5f;
246 float highFreq = Perlin.turbulence2(vec.X, vec.Y, 2f) * 2.25f;
247 float noise = (lowFreq + highFreq) * 2f;
248
249 // Combine the current height, generated noise, start height, and height range parameters, then scale all of it
250 float layer = ((height + noise - startHeight) / heightRange) * 4f;
251 if (Single.IsNaN(layer)) layer = 0f;
252 layermap[y * 256 + x] = Utils.Clamp(layer, 0f, 3f);
294 } 253 }
295 } 254 }
296 255
256 #endregion Layer Map
257
258 #region Texture Compositing
259
260 output = new Bitmap(256, 256, PixelFormat.Format24bppRgb);
261 outputData = output.LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
262
263 unsafe
264 {
265 // Get handles to all of the texture data arrays
266 BitmapData[] datas = new BitmapData[]
267 {
268 detailTexture[0].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[0].PixelFormat),
269 detailTexture[1].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[1].PixelFormat),
270 detailTexture[2].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[2].PixelFormat),
271 detailTexture[3].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[3].PixelFormat)
272 };
273
274 int[] comps = new int[]
275 {
276 (datas[0].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
277 (datas[1].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
278 (datas[2].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
279 (datas[3].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3
280 };
281
282 for (int y = 0; y < 256; y++)
283 {
284 for (int x = 0; x < 256; x++)
285 {
286 float layer = layermap[y * 256 + x];
287
288 // Select two textures
289 int l0 = (int)Math.Floor(layer);
290 int l1 = Math.Min(l0 + 1, 3);
291
292 byte* ptrA = (byte*)datas[l0].Scan0 + y * datas[l0].Stride + x * comps[l0];
293 byte* ptrB = (byte*)datas[l1].Scan0 + y * datas[l1].Stride + x * comps[l1];
294 byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride + x * 3;
295
296 float aB = *(ptrA + 0);
297 float aG = *(ptrA + 1);
298 float aR = *(ptrA + 2);
299
300 float bB = *(ptrB + 0);
301 float bG = *(ptrB + 1);
302 float bR = *(ptrB + 2);
303
304 float layerDiff = layer - l0;
305
306 // Interpolate between the two selected textures
307 *(ptrO + 0) = (byte)Math.Floor(aB + layerDiff * (bB - aB));
308 *(ptrO + 1) = (byte)Math.Floor(aG + layerDiff * (bG - aG));
309 *(ptrO + 2) = (byte)Math.Floor(aR + layerDiff * (bR - aR));
310 }
311 }
312
313 for (int i = 0; i < 4; i++)
314 detailTexture[i].UnlockBits(datas[i]);
315 }
316 }
317 finally
318 {
297 for (int i = 0; i < 4; i++) 319 for (int i = 0; i < 4; i++)
298 detailTexture[i].UnlockBits(datas[i]); 320 if (detailTexture[i] != null)
321 detailTexture[i].Dispose();
299 } 322 }
300 323
301 output.UnlockBits(outputData); 324 output.UnlockBits(outputData);
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
index e6f2855..3c48d07 100644
--- a/OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
@@ -54,8 +54,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
54 private static readonly UUID TEXTURE_METADATA_MAGIC = new UUID("802dc0e0-f080-4931-8b57-d1be8611c4f3"); 54 private static readonly UUID TEXTURE_METADATA_MAGIC = new UUID("802dc0e0-f080-4931-8b57-d1be8611c4f3");
55 private static readonly Color4 WATER_COLOR = new Color4(29, 72, 96, 216); 55 private static readonly Color4 WATER_COLOR = new Color4(29, 72, 96, 216);
56 56
57 private static readonly ILog m_log = 57 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
58 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
59 58
60 private Scene m_scene; 59 private Scene m_scene;
61 private IRendering m_primMesher; 60 private IRendering m_primMesher;
@@ -164,7 +163,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
164 } 163 }
165 catch 164 catch
166 { 165 {
167 m_log.Warn("[MAPTILE]: Failed to load StartupConfig"); 166 m_log.Warn("[WARP 3D IMAGE MODULE]: Failed to load StartupConfig");
168 } 167 }
169 168
170 m_colors.Clear(); 169 m_colors.Clear();
@@ -218,7 +217,10 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
218 Bitmap bitmap = renderer.Scene.getImage(); 217 Bitmap bitmap = renderer.Scene.getImage();
219 218
220 if (m_useAntiAliasing) 219 if (m_useAntiAliasing)
221 bitmap = ImageUtils.ResizeImage(bitmap, viewport.Width, viewport.Height); 220 {
221 using (Bitmap origBitmap = bitmap)
222 bitmap = ImageUtils.ResizeImage(origBitmap, viewport.Width, viewport.Height);
223 }
222 224
223 return bitmap; 225 return bitmap;
224 } 226 }
@@ -233,7 +235,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
233 catch (Exception e) 235 catch (Exception e)
234 { 236 {
235 // JPEG2000 encoder failed 237 // JPEG2000 encoder failed
236 m_log.Error("[MAPTILE]: Failed generating terrain map: " + e); 238 m_log.Error("[WARP 3D IMAGE MODULE]: Failed generating terrain map: ", e);
237 } 239 }
238 240
239 return null; 241 return null;
@@ -332,8 +334,17 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
332 uint globalX, globalY; 334 uint globalX, globalY;
333 Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out globalX, out globalY); 335 Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out globalX, out globalY);
334 336
335 Bitmap image = TerrainSplat.Splat(heightmap, textureIDs, startHeights, heightRanges, new Vector3d(globalX, globalY, 0.0), m_scene.AssetService, textureTerrain); 337 warp_Texture texture;
336 warp_Texture texture = new warp_Texture(image); 338
339 using (
340 Bitmap image
341 = TerrainSplat.Splat(
342 heightmap, textureIDs, startHeights, heightRanges,
343 new Vector3d(globalX, globalY, 0.0), m_scene.AssetService, textureTerrain))
344 {
345 texture = new warp_Texture(image);
346 }
347
337 warp_Material material = new warp_Material(texture); 348 warp_Material material = new warp_Material(texture);
338 material.setReflectivity(50); 349 material.setReflectivity(50);
339 renderer.Scene.addMaterial("TerrainColor", material); 350 renderer.Scene.addMaterial("TerrainColor", material);
@@ -560,42 +571,46 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
560 { 571 {
561 try 572 try
562 { 573 {
563 Bitmap bitmap = (Bitmap)J2kImage.FromStream(stream); 574 int pixelBytes;
564 width = bitmap.Width;
565 height = bitmap.Height;
566 575
567 BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, bitmap.PixelFormat); 576 using (Bitmap bitmap = (Bitmap)J2kImage.FromStream(stream))
568 int pixelBytes = (bitmap.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4;
569
570 // Sum up the individual channels
571 unsafe
572 { 577 {
573 if (pixelBytes == 4) 578 width = bitmap.Width;
579 height = bitmap.Height;
580
581 BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
582 pixelBytes = (bitmap.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4;
583
584 // Sum up the individual channels
585 unsafe
574 { 586 {
575 for (int y = 0; y < height; y++) 587 if (pixelBytes == 4)
576 { 588 {
577 byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride); 589 for (int y = 0; y < height; y++)
578
579 for (int x = 0; x < width; x++)
580 { 590 {
581 b += row[x * pixelBytes + 0]; 591 byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride);
582 g += row[x * pixelBytes + 1]; 592
583 r += row[x * pixelBytes + 2]; 593 for (int x = 0; x < width; x++)
584 a += row[x * pixelBytes + 3]; 594 {
595 b += row[x * pixelBytes + 0];
596 g += row[x * pixelBytes + 1];
597 r += row[x * pixelBytes + 2];
598 a += row[x * pixelBytes + 3];
599 }
585 } 600 }
586 } 601 }
587 } 602 else
588 else
589 {
590 for (int y = 0; y < height; y++)
591 { 603 {
592 byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride); 604 for (int y = 0; y < height; y++)
593
594 for (int x = 0; x < width; x++)
595 { 605 {
596 b += row[x * pixelBytes + 0]; 606 byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride);
597 g += row[x * pixelBytes + 1]; 607
598 r += row[x * pixelBytes + 2]; 608 for (int x = 0; x < width; x++)
609 {
610 b += row[x * pixelBytes + 0];
611 g += row[x * pixelBytes + 1];
612 r += row[x * pixelBytes + 2];
613 }
599 } 614 }
600 } 615 }
601 } 616 }
@@ -617,7 +632,10 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
617 } 632 }
618 catch (Exception ex) 633 catch (Exception ex)
619 { 634 {
620 m_log.WarnFormat("[MAPTILE]: Error decoding JPEG2000 texture {0} ({1} bytes): {2}", textureID, j2kData.Length, ex.Message); 635 m_log.WarnFormat(
636 "[WARP 3D IMAGE MODULE]: Error decoding JPEG2000 texture {0} ({1} bytes): {2}",
637 textureID, j2kData.Length, ex.Message);
638
621 width = 0; 639 width = 0;
622 height = 0; 640 height = 0;
623 return new Color4(0.5f, 0.5f, 0.5f, 1.0f); 641 return new Color4(0.5f, 0.5f, 0.5f, 1.0f);
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
index 1dedcce..309856f 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
@@ -193,14 +193,15 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
193 { 193 {
194 //m_log.DebugFormat("[WORLD MAP]: OnRegisterCaps: agentID {0} caps {1}", agentID, caps); 194 //m_log.DebugFormat("[WORLD MAP]: OnRegisterCaps: agentID {0} caps {1}", agentID, caps);
195 string capsBase = "/CAPS/" + caps.CapsObjectPath; 195 string capsBase = "/CAPS/" + caps.CapsObjectPath;
196 caps.RegisterHandler("MapLayer", 196 caps.RegisterHandler(
197 new RestStreamHandler("POST", capsBase + m_mapLayerPath, 197 "MapLayer",
198 delegate(string request, string path, string param, 198 new RestStreamHandler(
199 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 199 "POST",
200 { 200 capsBase + m_mapLayerPath,
201 return MapLayerRequest(request, path, param, 201 (request, path, param, httpRequest, httpResponse)
202 agentID, caps); 202 => MapLayerRequest(request, path, param, agentID, caps),
203 })); 203 "MapLayer",
204 agentID.ToString()));
204 } 205 }
205 206
206 /// <summary> 207 /// <summary>
@@ -675,7 +676,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
675 { 676 {
676 if (Environment.TickCount > (m_blacklistedregions[regionhandle] + blacklistTimeout)) 677 if (Environment.TickCount > (m_blacklistedregions[regionhandle] + blacklistTimeout))
677 { 678 {
678 m_log.DebugFormat("[WORLDMAP]: Unblock blacklisted region {0}", regionhandle); 679 m_log.DebugFormat("[WORLD MAP]: Unblock blacklisted region {0}", regionhandle);
679 680
680 m_blacklistedregions.Remove(regionhandle); 681 m_blacklistedregions.Remove(regionhandle);
681 } 682 }
@@ -730,7 +731,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
730 { 731 {
731 if (Environment.TickCount > (m_blacklistedurls[httpserver] + blacklistTimeout)) 732 if (Environment.TickCount > (m_blacklistedurls[httpserver] + blacklistTimeout))
732 { 733 {
733 m_log.DebugFormat("[WORLDMAP]: Unblock blacklisted URL {0}", httpserver); 734 m_log.DebugFormat("[WORLD MAP]: Unblock blacklisted URL {0}", httpserver);
734 735
735 m_blacklistedurls.Remove(httpserver); 736 m_blacklistedurls.Remove(httpserver);
736 } 737 }
@@ -1427,14 +1428,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1427 if (terrain == null) 1428 if (terrain == null)
1428 return; 1429 return;
1429 1430
1431 m_log.DebugFormat("[WORLD MAP]: Generating map image for {0}", m_scene.RegionInfo.RegionName);
1432
1430 byte[] data = terrain.WriteJpeg2000Image(); 1433 byte[] data = terrain.WriteJpeg2000Image();
1431 if (data == null) 1434 if (data == null)
1432 return; 1435 return;
1433 1436
1434 byte[] overlay = GenerateOverlay(); 1437 byte[] overlay = GenerateOverlay();
1435 1438
1436 m_log.Debug("[WORLDMAP]: STORING MAPTILE IMAGE");
1437
1438 UUID terrainImageID = UUID.Random(); 1439 UUID terrainImageID = UUID.Random();
1439 UUID parcelImageID = UUID.Zero; 1440 UUID parcelImageID = UUID.Zero;
1440 1441
@@ -1449,7 +1450,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1449 asset.Flags = AssetFlags.Maptile; 1450 asset.Flags = AssetFlags.Maptile;
1450 1451
1451 // Store the new one 1452 // Store the new one
1452 m_log.DebugFormat("[WORLDMAP]: Storing map tile {0}", asset.ID); 1453 m_log.DebugFormat("[WORLD MAP]: Storing map tile {0} for {1}", asset.ID, m_scene.RegionInfo.RegionName);
1454
1453 m_scene.AssetService.Store(asset); 1455 m_scene.AssetService.Store(asset);
1454 1456
1455 if (overlay != null) 1457 if (overlay != null)
diff --git a/OpenSim/Region/DataSnapshot/DataRequestHandler.cs b/OpenSim/Region/DataSnapshot/DataRequestHandler.cs
index 2f2b3e6..32e93b4 100644
--- a/OpenSim/Region/DataSnapshot/DataRequestHandler.cs
+++ b/OpenSim/Region/DataSnapshot/DataRequestHandler.cs
@@ -42,13 +42,13 @@ namespace OpenSim.Region.DataSnapshot
42{ 42{
43 public class DataRequestHandler 43 public class DataRequestHandler
44 { 44 {
45 private Scene m_scene = null; 45// private Scene m_scene = null;
46 private DataSnapshotManager m_externalData = null; 46 private DataSnapshotManager m_externalData = null;
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 public DataRequestHandler(Scene scene, DataSnapshotManager externalData) 49 public DataRequestHandler(Scene scene, DataSnapshotManager externalData)
50 { 50 {
51 m_scene = scene; 51// m_scene = scene;
52 m_externalData = externalData; 52 m_externalData = externalData;
53 53
54 //Register HTTP handler 54 //Register HTTP handler
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index 0516cb1..410eda0 100644
--- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
@@ -37,6 +37,20 @@ namespace OpenSim.Region.Framework.Interfaces
37 public interface IAttachmentsModule 37 public interface IAttachmentsModule
38 { 38 {
39 /// <summary> 39 /// <summary>
40 /// Copy attachment data from a ScenePresence into the AgentData structure for transmission to another simulator
41 /// </summary>
42 /// <param name='sp'></param>
43 /// <param name='ad'></param>
44 void CopyAttachments(IScenePresence sp, AgentData ad);
45
46 /// <summary>
47 /// Copy attachment data from an AgentData structure into a ScenePresence.
48 /// </summary>
49 /// <param name='ad'></param>
50 /// <param name='sp'></param>
51 void CopyAttachments(AgentData ad, IScenePresence sp);
52
53 /// <summary>
40 /// RezAttachments. This should only be called upon login on the first region. 54 /// RezAttachments. This should only be called upon login on the first region.
41 /// Attachment rezzings on crossings and TPs are done in a different way. 55 /// Attachment rezzings on crossings and TPs are done in a different way.
42 /// </summary> 56 /// </summary>
@@ -44,10 +58,15 @@ namespace OpenSim.Region.Framework.Interfaces
44 void RezAttachments(IScenePresence sp); 58 void RezAttachments(IScenePresence sp);
45 59
46 /// <summary> 60 /// <summary>
47 /// Save the attachments that have change on this presence. 61 /// Derez the attachements for a scene presence that is closing.
48 /// </summary> 62 /// </summary>
49 /// <param name="sp"></param> 63 /// <remarks>
50 void SaveChangedAttachments(IScenePresence sp, bool saveAllScripted); 64 /// Attachment changes are saved.
65 /// </remarks>
66 /// <param name="sp">The presence closing</param>
67 /// <param name="saveChanged">Save changed attachments.</param>
68 /// <param name="saveAllScripted">Save attachments with scripts even if they haven't changed.</para>
69 void DeRezAttachments(IScenePresence sp, bool saveChanged, bool saveAllScripted);
51 70
52 /// <summary> 71 /// <summary>
53 /// Delete all the presence's attachments from the scene 72 /// Delete all the presence's attachments from the scene
@@ -78,7 +97,7 @@ namespace OpenSim.Region.Framework.Interfaces
78 97
79 // Same as above, but also load script states from a separate doc 98 // Same as above, but also load script states from a separate doc
80 ISceneEntity RezSingleAttachmentFromInventory( 99 ISceneEntity RezSingleAttachmentFromInventory(
81 IScenePresence presence, UUID itemID, uint AttachmentPt, bool updateInventoryStatus, XmlDocument doc); 100 IScenePresence presence, UUID itemID, uint AttachmentPt, XmlDocument doc);
82 101
83 /// <summary> 102 /// <summary>
84 /// Rez multiple attachments from a user's inventory 103 /// Rez multiple attachments from a user's inventory
@@ -95,11 +114,11 @@ namespace OpenSim.Region.Framework.Interfaces
95 void DetachSingleAttachmentToGround(IScenePresence sp, uint objectLocalID); 114 void DetachSingleAttachmentToGround(IScenePresence sp, uint objectLocalID);
96 115
97 /// <summary> 116 /// <summary>
98 /// Detach the given item so that it remains in the user's inventory. 117 /// Detach the given attachment so that it remains in the user's inventory.
99 /// </summary> 118 /// </summary>
100 /// <param name="sp">/param> 119 /// <param name="sp">/param>
101 /// <param name="itemID"></param> 120 /// <param name="grp">The attachment to detach.</param>
102 void DetachSingleAttachmentToInv(IScenePresence sp, UUID itemID); 121 void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup grp);
103 122
104 /// Update the position of an attachment. 123 /// Update the position of an attachment.
105 /// </summary> 124 /// </summary>
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
index 32f4eea..4274cbe 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
@@ -81,13 +81,18 @@ namespace OpenSim.Region.Framework.Interfaces
81 /// <summary> 81 /// <summary>
82 /// Start all the scripts contained in this entity's inventory 82 /// Start all the scripts contained in this entity's inventory
83 /// </summary> 83 /// </summary>
84 void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource); 84 /// <param name="startParam"></param>
85 /// <param name="postOnRez"></param>
86 /// <param name="engine"></param>
87 /// <param name="stateSource"></param>
88 /// <returns>Number of scripts started.</returns>
89 int CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource);
85 90
86 ArrayList GetScriptErrors(UUID itemID); 91 ArrayList GetScriptErrors(UUID itemID);
87 void ResumeScripts(); 92 void ResumeScripts();
88 93
89 /// <summary> 94 /// <summary>
90 /// Stop all the scripts in this entity. 95 /// Stop and remove all the scripts in this entity from the scene.
91 /// </summary> 96 /// </summary>
92 /// <param name="sceneObjectBeingDeleted"> 97 /// <param name="sceneObjectBeingDeleted">
93 /// Should be true if these scripts are being removed because the scene 98 /// Should be true if these scripts are being removed because the scene
@@ -96,13 +101,22 @@ namespace OpenSim.Region.Framework.Interfaces
96 void RemoveScriptInstances(bool sceneObjectBeingDeleted); 101 void RemoveScriptInstances(bool sceneObjectBeingDeleted);
97 102
98 /// <summary> 103 /// <summary>
104 /// Stop all the scripts in this entity.
105 /// </summary>
106 void StopScriptInstances();
107
108 /// <summary>
99 /// Start a script which is in this entity's inventory. 109 /// Start a script which is in this entity's inventory.
100 /// </summary> 110 /// </summary>
101 /// <param name="item"></param> 111 /// <param name="item"></param>
102 /// <param name="postOnRez"></param> 112 /// <param name="postOnRez"></param>
103 /// <param name="engine"></param> 113 /// <param name="engine"></param>
104 /// <param name="stateSource"></param> 114 /// <param name="stateSource"></param>
105 void CreateScriptInstance( 115 /// <returns>
116 /// true if the script instance was valid for starting, false otherwise. This does not guarantee
117 /// that the script was actually started, just that the script was valid (i.e. its asset data could be found, etc.)
118 /// </returns>
119 bool CreateScriptInstance(
106 TaskInventoryItem item, int startParam, bool postOnRez, string engine, int stateSource); 120 TaskInventoryItem item, int startParam, bool postOnRez, string engine, int stateSource);
107 121
108 /// <summary> 122 /// <summary>
@@ -113,12 +127,16 @@ namespace OpenSim.Region.Framework.Interfaces
113 /// <param name="postOnRez"></param> 127 /// <param name="postOnRez"></param>
114 /// <param name="engine"></param> 128 /// <param name="engine"></param>
115 /// <param name="stateSource"></param> 129 /// <param name="stateSource"></param>
116 void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource); 130 /// <returns>
131 /// true if the script instance was valid for starting, false otherwise. This does not guarantee
132 /// that the script was actually started, just that the script was valid (i.e. its asset data could be found, etc.)
133 /// </returns>
134 bool CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
117 135
118 ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource); 136 ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
119 137
120 /// <summary> 138 /// <summary>
121 /// Stop a script which is in this prim's inventory. 139 /// Stop and remove a script which is in this prim's inventory from the scene.
122 /// </summary> 140 /// </summary>
123 /// <param name="itemId"></param> 141 /// <param name="itemId"></param>
124 /// <param name="sceneObjectBeingDeleted"> 142 /// <param name="sceneObjectBeingDeleted">
@@ -128,6 +146,12 @@ namespace OpenSim.Region.Framework.Interfaces
128 void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted); 146 void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted);
129 147
130 /// <summary> 148 /// <summary>
149 /// Stop a script which is in this prim's inventory.
150 /// </summary>
151 /// <param name="itemId"></param>
152 void StopScriptInstance(UUID itemId);
153
154 /// <summary>
131 /// Add an item to this entity's inventory. If an item with the same name already exists, then an alternative 155 /// Add an item to this entity's inventory. If an item with the same name already exists, then an alternative
132 /// name is chosen. 156 /// name is chosen.
133 /// </summary> 157 /// </summary>
@@ -166,6 +190,19 @@ namespace OpenSim.Region.Framework.Interfaces
166 List<TaskInventoryItem> GetInventoryItems(); 190 List<TaskInventoryItem> GetInventoryItems();
167 191
168 /// <summary> 192 /// <summary>
193 /// Gets an inventory item by name
194 /// </summary>
195 /// <remarks>
196 /// This method returns the first inventory item that matches the given name. In SL this is all you need
197 /// since each item in a prim inventory must have a unique name.
198 /// </remarks>
199 /// <param name='name'></param>
200 /// <returns>
201 /// The inventory item. Null if no such item was found.
202 /// </returns>
203 TaskInventoryItem GetInventoryItem(string name);
204
205 /// <summary>
169 /// Get inventory items by name. 206 /// Get inventory items by name.
170 /// </summary> 207 /// </summary>
171 /// <param name="name"></param> 208 /// <param name="name"></param>
@@ -174,7 +211,17 @@ namespace OpenSim.Region.Framework.Interfaces
174 /// If no inventory item has that name then an empty list is returned. 211 /// If no inventory item has that name then an empty list is returned.
175 /// </returns> 212 /// </returns>
176 List<TaskInventoryItem> GetInventoryItems(string name); 213 List<TaskInventoryItem> GetInventoryItems(string name);
177 214
215 /// <summary>
216 /// Get inventory items by type.
217 /// </summary>
218 /// <param type="name"></param>
219 /// <returns>
220 /// A list of inventory items of that type.
221 /// If no inventory items of that type then an empty list is returned.
222 /// </returns>
223 List<TaskInventoryItem> GetInventoryItems(InventoryType type);
224
178 /// <summary> 225 /// <summary>
179 /// Get the scene object referenced by an inventory item. 226 /// Get the scene object referenced by an inventory item.
180 /// </summary> 227 /// </summary>
@@ -228,6 +275,16 @@ namespace OpenSim.Region.Framework.Interfaces
228 bool ContainsScripts(); 275 bool ContainsScripts();
229 276
230 /// <summary> 277 /// <summary>
278 /// Returns the count of scripts contained
279 /// </summary></returns>
280 int ScriptCount();
281
282 /// <summary>
283 /// Returns the count of running scripts contained
284 /// </summary></returns>
285 int RunningScriptCount();
286
287 /// <summary>
231 /// Get the uuids of all items in this inventory 288 /// Get the uuids of all items in this inventory
232 /// </summary> 289 /// </summary>
233 /// <returns></returns> 290 /// <returns></returns>
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
index 76f1641..5bc8e51 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
@@ -39,13 +39,30 @@ namespace OpenSim.Region.Framework.Interfaces
39 39
40 public interface IEntityTransferModule 40 public interface IEntityTransferModule
41 { 41 {
42 void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, 42 /// <summary>
43 Vector3 lookAt, uint teleportFlags); 43 /// Teleport an agent within the same or to a different region.
44 /// </summary>
45 /// <param name='agent'></param>
46 /// <param name='regionHandle'>
47 /// The handle of the destination region. If it's the same as the region currently
48 /// occupied by the agent then the teleport will be within that region.
49 /// </param>
50 /// <param name='position'></param>
51 /// <param name='lookAt'></param>
52 /// <param name='teleportFlags'></param>
53 void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags);
44 54
45 bool TeleportHome(UUID id, IClientAPI client); 55 bool TeleportHome(UUID id, IClientAPI client);
46 56
47 void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, 57 void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination,
48 Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq); 58 Vector3 position, Vector3 lookAt, uint teleportFlags);
59
60 /// <summary>
61 /// Show whether the given agent is being teleported.
62 /// </summary>
63 /// <param name='id'>The agent ID</para></param>
64 /// <returns>true if the agent is in the process of being teleported, false otherwise.</returns>
65 bool IsInTransit(UUID id);
49 66
50 bool Cross(ScenePresence agent, bool isFlying); 67 bool Cross(ScenePresence agent, bool isFlying);
51 68
diff --git a/OpenSim/Region/Framework/Interfaces/IEnvironmentModule.cs b/OpenSim/Region/Framework/Interfaces/IEnvironmentModule.cs
new file mode 100644
index 0000000..7a7b782
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IEnvironmentModule.cs
@@ -0,0 +1,36 @@
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 OpenMetaverse;
29
30namespace OpenSim.Region.Framework.Interfaces
31{
32 public interface IEnvironmentModule
33 {
34 void ResetEnvironmentSettings(UUID regionUUID);
35 }
36}
diff --git a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
index 72e79ed..ca2ad94 100644
--- a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
@@ -47,5 +47,8 @@ namespace OpenSim.Region.Framework.Interfaces
47 void sendRegionHandshakeToAll(); 47 void sendRegionHandshakeToAll();
48 void TriggerEstateInfoChange(); 48 void TriggerEstateInfoChange();
49 void TriggerRegionInfoChange(); 49 void TriggerRegionInfoChange();
50
51 void setEstateTerrainBaseTexture(int level, UUID texture);
52 void setEstateTerrainTextureHeights(int corner, float lowValue, float highValue);
50 } 53 }
51} 54}
diff --git a/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs b/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs
index 1904011..3576e35 100644
--- a/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs
@@ -49,11 +49,15 @@ namespace OpenSim.Region.Framework.Interfaces
49 /// <param name="folderID"></param> 49 /// <param name="folderID"></param>
50 /// <param name="objectGroups"></param> 50 /// <param name="objectGroups"></param>
51 /// <param name="remoteClient"></param> 51 /// <param name="remoteClient"></param>
52 /// <param name="asAttachment">
53 /// Should be true if the object(s) are begin taken as attachments. False otherwise.
54 /// </param>
52 /// <returns> 55 /// <returns>
53 /// Returns the UUID of the newly created item asset (not the item itself). 56 /// A list of the items created. If there was more than one object and objects are not being coaleseced in
54 /// FIXME: This is not very useful. It would be far more useful to return a list of items instead. 57 /// inventory, then the order of items is in the same order as the input objects.
55 /// </returns> 58 /// </returns>
56 UUID CopyToInventory(DeRezAction action, UUID folderID, List<SceneObjectGroup> objectGroups, IClientAPI remoteClient); 59 List<InventoryItemBase> CopyToInventory(
60 DeRezAction action, UUID folderID, List<SceneObjectGroup> objectGroups, IClientAPI remoteClient, bool asAttachment);
57 61
58 /// <summary> 62 /// <summary>
59 /// Rez an object into the scene from the user's inventory 63 /// Rez an object into the scene from the user's inventory
diff --git a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
new file mode 100644
index 0000000..baac6e8
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
@@ -0,0 +1,48 @@
1/*
2 * Copyright (c) Contributors
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 OpenSim 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 OpenMetaverse;
31
32namespace OpenSim.Region.Framework.Interfaces
33{
34 public delegate void TakeValueCallback(string s);
35
36 public interface IJsonStoreModule
37 {
38 bool CreateStore(string value, out UUID result);
39 bool DestroyStore(UUID storeID);
40 bool TestPath(UUID storeID, string path, bool useJson);
41 bool SetValue(UUID storeID, string path, string value, bool useJson);
42 bool RemoveValue(UUID storeID, string path);
43 bool GetValue(UUID storeID, string path, bool useJson, out string value);
44
45 void TakeValue(UUID storeID, string path, bool useJson, TakeValueCallback cback);
46 void ReadValue(UUID storeID, string path, bool useJson, TakeValueCallback cback);
47 }
48}
diff --git a/OpenSim/Region/Framework/Interfaces/INPCModule.cs b/OpenSim/Region/Framework/Interfaces/INPCModule.cs
index dc3ff89..d582149 100644
--- a/OpenSim/Region/Framework/Interfaces/INPCModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/INPCModule.cs
@@ -113,9 +113,11 @@ namespace OpenSim.Region.Framework.Interfaces
113 /// </param> 113 /// </param>
114 /// <param name="landAtTarget"> 114 /// <param name="landAtTarget">
115 /// If true and the avatar is flying when it reaches the target, land. 115 /// If true and the avatar is flying when it reaches the target, land.
116 /// </param> 116 /// </param> name="running">
117 /// If true, NPC moves with running speed.
117 /// <returns>True if the operation succeeded, false if there was no such agent or the agent was not an NPC</returns> 118 /// <returns>True if the operation succeeded, false if there was no such agent or the agent was not an NPC</returns>
118 bool MoveToTarget(UUID agentID, Scene scene, Vector3 pos, bool noFly, bool landAtTarget); 119 ///
120 bool MoveToTarget(UUID agentID, Scene scene, Vector3 pos, bool noFly, bool landAtTarget, bool running);
119 121
120 /// <summary> 122 /// <summary>
121 /// Stop the NPC's current movement. 123 /// Stop the NPC's current movement.
@@ -135,6 +137,36 @@ namespace OpenSim.Region.Framework.Interfaces
135 bool Say(UUID agentID, Scene scene, string text); 137 bool Say(UUID agentID, Scene scene, string text);
136 138
137 /// <summary> 139 /// <summary>
140 /// Get the NPC to say something.
141 /// </summary>
142 /// <param name="agentID">The UUID of the NPC</param>
143 /// <param name="scene"></param>
144 /// <param name="text"></param>
145 /// <param name="channel"></param>
146 /// <returns>True if the operation succeeded, false if there was no such agent or the agent was not an NPC</returns>
147 bool Say(UUID agentID, Scene scene, string text, int channel);
148
149 /// <summary>
150 /// Get the NPC to shout something.
151 /// </summary>
152 /// <param name="agentID">The UUID of the NPC</param>
153 /// <param name="scene"></param>
154 /// <param name="text"></param>
155 /// <param name="channel"></param>
156 /// <returns>True if the operation succeeded, false if there was no such agent or the agent was not an NPC</returns>
157 bool Shout(UUID agentID, Scene scene, string text, int channel);
158
159 /// <summary>
160 /// Get the NPC to whisper something.
161 /// </summary>
162 /// <param name="agentID">The UUID of the NPC</param>
163 /// <param name="scene"></param>
164 /// <param name="text"></param>
165 /// <param name="channel"></param>
166 /// <returns>True if the operation succeeded, false if there was no such agent or the agent was not an NPC</returns>
167 bool Whisper(UUID agentID, Scene scene, string text, int channel);
168
169 /// <summary>
138 /// Sit the NPC. 170 /// Sit the NPC.
139 /// </summary> 171 /// </summary>
140 /// <param name="agentID"></param> 172 /// <param name="agentID"></param>
@@ -152,6 +184,14 @@ namespace OpenSim.Region.Framework.Interfaces
152 bool Stand(UUID agentID, Scene scene); 184 bool Stand(UUID agentID, Scene scene);
153 185
154 /// <summary> 186 /// <summary>
187 /// Get the NPC to touch an object.
188 /// </summary>
189 /// <param name="agentID"></param>
190 /// <param name="partID"></param>
191 /// <returns>true if the touch is actually attempted, false if not</returns>
192 bool Touch(UUID agentID, UUID partID);
193
194 /// <summary>
155 /// Delete an NPC. 195 /// Delete an NPC.
156 /// </summary> 196 /// </summary>
157 /// <param name="agentID">The UUID of the NPC</param> 197 /// <param name="agentID">The UUID of the NPC</param>
diff --git a/OpenSim/Region/Framework/Interfaces/IRegionCombinerModule.cs b/OpenSim/Region/Framework/Interfaces/IRegionCombinerModule.cs
new file mode 100644
index 0000000..e03ac5a
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IRegionCombinerModule.cs
@@ -0,0 +1,59 @@
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.Linq;
31using System.Text;
32using OpenSim.Region.Framework.Scenes;
33using System.IO;
34using OpenMetaverse;
35
36namespace OpenSim.Region.Framework.Interfaces
37{
38 public interface IRegionCombinerModule
39 {
40 /// <summary>
41 /// Does the given id belong to the root region of a megaregion?
42 /// </summary>
43 bool IsRootForMegaregion(UUID regionId);
44
45 /// <summary>
46 /// Gets the size of megaregion.
47 /// </summary>
48 /// <remarks>
49 /// Returns size in meters.
50 /// Do not rely on this method remaining the same - this area is actively under development.
51 /// </remarks>
52 /// <param name="sceneId">
53 /// The id of the root region for a megaregion.
54 /// This may change in the future to allow any region id that makes up a megaregion.
55 /// Currently, will throw an exception if this does not match a root region.
56 /// </param>
57 Vector2 GetSizeOfMegaregion(UUID regionId);
58 }
59} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Interfaces/IScenePresence.cs b/OpenSim/Region/Framework/Interfaces/IScenePresence.cs
index 5e43843..e6b926c 100644
--- a/OpenSim/Region/Framework/Interfaces/IScenePresence.cs
+++ b/OpenSim/Region/Framework/Interfaces/IScenePresence.cs
@@ -41,6 +41,12 @@ namespace OpenSim.Region.Framework.Interfaces
41 public interface IScenePresence : ISceneAgent 41 public interface IScenePresence : ISceneAgent
42 { 42 {
43 /// <summary> 43 /// <summary>
44 /// Copy of the script states while the agent is in transit. This state may
45 /// need to be placed back in case of transfer fail.
46 /// </summary>
47 List<string> InTransitScriptStates { get; }
48
49 /// <summary>
44 /// The AttachmentsModule synchronizes on this to avoid race conditions between commands to add and remove attachments. 50 /// The AttachmentsModule synchronizes on this to avoid race conditions between commands to add and remove attachments.
45 /// </summary> 51 /// </summary>
46 /// <remarks> 52 /// <remarks>
@@ -66,6 +72,10 @@ namespace OpenSim.Region.Framework.Interfaces
66 /// <returns></returns> 72 /// <returns></returns>
67 List<SceneObjectGroup> GetAttachments(uint attachmentPoint); 73 List<SceneObjectGroup> GetAttachments(uint attachmentPoint);
68 74
75 /// <summary>
76 /// Does this avatar have any attachments?
77 /// </summary>
78 /// <returns></returns>
69 bool HasAttachments(); 79 bool HasAttachments();
70 80
71 // Don't use these methods directly. Instead, use the AttachmentsModule 81 // Don't use these methods directly. Instead, use the AttachmentsModule
diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
index ce66100..42dbedc 100644
--- a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
@@ -71,6 +71,14 @@ namespace OpenSim.Region.Framework.Interfaces
71 71
72 bool HasScript(UUID itemID, out bool running); 72 bool HasScript(UUID itemID, out bool running);
73 73
74 /// <summary>
75 /// Returns true if a script is running.
76 /// </summary>
77 /// <param name="itemID">The item ID of the script.</param>
78 bool GetScriptState(UUID itemID);
79
80 void SetRunEnable(UUID instanceID, bool enable);
81
74 void SaveAllState(); 82 void SaveAllState();
75 83
76 /// <summary> 84 /// <summary>
@@ -79,6 +87,14 @@ namespace OpenSim.Region.Framework.Interfaces
79 void StartProcessing(); 87 void StartProcessing();
80 88
81 /// <summary> 89 /// <summary>
90 /// Get the execution times of all scripts in the given array if they are currently running.
91 /// </summary>
92 /// <returns>
93 /// A float the value is a representative execution time in milliseconds of all scripts in that Array.
94 /// </returns>
95 float GetScriptExecutionTime(List<UUID> itemIDs);
96
97 /// <summary>
82 /// Get the execution times of all scripts in each object. 98 /// Get the execution times of all scripts in each object.
83 /// </summary> 99 /// </summary>
84 /// <returns> 100 /// <returns>
@@ -87,4 +103,4 @@ namespace OpenSim.Region.Framework.Interfaces
87 /// </returns> 103 /// </returns>
88 Dictionary<uint, float> GetObjectScriptsExecutionTimes(); 104 Dictionary<uint, float> GetObjectScriptsExecutionTimes();
89 } 105 }
90} \ No newline at end of file 106}
diff --git a/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs b/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
index 5b69616..ccb583d 100644
--- a/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
@@ -96,6 +96,26 @@ namespace OpenSim.Region.Framework.Interfaces
96 void StoreRegionWindlightSettings(RegionLightShareData wl); 96 void StoreRegionWindlightSettings(RegionLightShareData wl);
97 void RemoveRegionWindlightSettings(UUID regionID); 97 void RemoveRegionWindlightSettings(UUID regionID);
98 98
99 /// <summary>
100 /// Load Environment settings from region storage
101 /// </summary>
102 /// <param name="regionUUID">the region UUID</param>
103 /// <returns>LLSD string for viewer</returns>
104 string LoadRegionEnvironmentSettings(UUID regionUUID);
105
106 /// <summary>
107 /// Store Environment settings into region storage
108 /// </summary>
109 /// <param name="regionUUID">the region UUID</param>
110 /// <param name="settings">LLSD string from viewer</param>
111 void StoreRegionEnvironmentSettings(UUID regionUUID, string settings);
112
113 /// <summary>
114 /// Delete Environment settings from region storage
115 /// </summary>
116 /// <param name="regionUUID">the region UUID</param>
117 void RemoveRegionEnvironmentSettings(UUID regionUUID);
118
99 UUID[] GetObjectIDs(UUID regionID); 119 UUID[] GetObjectIDs(UUID regionID);
100 } 120 }
101} 121}
diff --git a/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs b/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
index b7d9cfa..d7c80f7 100644
--- a/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
@@ -108,6 +108,26 @@ namespace OpenSim.Region.Framework.Interfaces
108 void RemoveRegionWindlightSettings(UUID regionID); 108 void RemoveRegionWindlightSettings(UUID regionID);
109 UUID[] GetObjectIDs(UUID regionID); 109 UUID[] GetObjectIDs(UUID regionID);
110 110
111 /// <summary>
112 /// Load Environment settings from region storage
113 /// </summary>
114 /// <param name="regionUUID">the region UUID</param>
115 /// <returns>LLSD string for viewer</returns>
116 string LoadRegionEnvironmentSettings(UUID regionUUID);
117
118 /// <summary>
119 /// Store Environment settings into region storage
120 /// </summary>
121 /// <param name="regionUUID">the region UUID</param>
122 /// <param name="settings">LLSD string from viewer</param>
123 void StoreRegionEnvironmentSettings(UUID regionUUID, string settings);
124
125 /// <summary>
126 /// Delete Environment settings from region storage
127 /// </summary>
128 /// <param name="regionUUID">the region UUID</param>
129 void RemoveRegionEnvironmentSettings(UUID regionUUID);
130
111 void Shutdown(); 131 void Shutdown();
112 } 132 }
113} 133}
diff --git a/OpenSim/Region/Framework/Interfaces/IUrlModule.cs b/OpenSim/Region/Framework/Interfaces/IUrlModule.cs
index 1b91166..457444c 100644
--- a/OpenSim/Region/Framework/Interfaces/IUrlModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IUrlModule.cs
@@ -34,6 +34,7 @@ namespace OpenSim.Region.Framework.Interfaces
34{ 34{
35 public interface IUrlModule 35 public interface IUrlModule
36 { 36 {
37 string ExternalHostNameForLSL { get; }
37 UUID RequestURL(IScriptModule engine, SceneObjectPart host, UUID itemID); 38 UUID RequestURL(IScriptModule engine, SceneObjectPart host, UUID itemID);
38 UUID RequestSecureURL(IScriptModule engine, SceneObjectPart host, UUID itemID); 39 UUID RequestSecureURL(IScriptModule engine, SceneObjectPart host, UUID itemID);
39 void ReleaseURL(string url); 40 void ReleaseURL(string url);
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
index e577958..9ddac19 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -294,6 +294,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
294 return "FALLDOWN"; 294 return "FALLDOWN";
295 } 295 }
296 296
297 // Check if the user has stopped walking just now
298 if (CurrentMovementAnimation == "WALK" && (move == Vector3.Zero))
299 return "STAND";
300
297 return CurrentMovementAnimation; 301 return CurrentMovementAnimation;
298 } 302 }
299 303
@@ -418,13 +422,16 @@ namespace OpenSim.Region.Framework.Scenes.Animation
418 /// </summary> 422 /// </summary>
419 public void UpdateMovementAnimations() 423 public void UpdateMovementAnimations()
420 { 424 {
421 CurrentMovementAnimation = DetermineMovementAnimation(); 425 lock (m_animations)
426 {
427 CurrentMovementAnimation = DetermineMovementAnimation();
422 428
423// m_log.DebugFormat( 429// m_log.DebugFormat(
424// "[SCENE PRESENCE ANIMATOR]: Determined animation {0} for {1} in UpdateMovementAnimations()", 430// "[SCENE PRESENCE ANIMATOR]: Determined animation {0} for {1} in UpdateMovementAnimations()",
425// CurrentMovementAnimation, m_scenePresence.Name); 431// CurrentMovementAnimation, m_scenePresence.Name);
426 432
427 TrySetMovementAnimation(CurrentMovementAnimation); 433 TrySetMovementAnimation(CurrentMovementAnimation);
434 }
428 } 435 }
429 436
430 public UUID[] GetAnimationArray() 437 public UUID[] GetAnimationArray()
diff --git a/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs b/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs
index 9cb5674..d9d2e64 100644
--- a/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs
+++ b/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs
@@ -137,7 +137,7 @@ namespace OpenSim.Region.Framework.Scenes
137 } 137 }
138 } 138 }
139 139
140 if (fh.Client.IsLoggingOut) 140 if (!fh.Client.IsActive)
141 continue; 141 continue;
142 142
143// m_log.DebugFormat( 143// m_log.DebugFormat(
diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
index f678d07..f555b49 100644
--- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
+++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
@@ -117,7 +117,7 @@ namespace OpenSim.Region.Framework.Scenes
117 117
118 private void InventoryRunDeleteTimer(object sender, ElapsedEventArgs e) 118 private void InventoryRunDeleteTimer(object sender, ElapsedEventArgs e)
119 { 119 {
120 m_log.Debug("[ASYNC DELETER]: Starting send to inventory loop"); 120// m_log.Debug("[ASYNC DELETER]: Starting send to inventory loop");
121 121
122 // We must set appearance parameters in the en_US culture in order to avoid issues where values are saved 122 // We must set appearance parameters in the en_US culture in order to avoid issues where values are saved
123 // in a culture where decimal points are commas and then reloaded in a culture which just treats them as 123 // in a culture where decimal points are commas and then reloaded in a culture which just treats them as
@@ -147,15 +147,15 @@ namespace OpenSim.Region.Framework.Scenes
147 { 147 {
148 x = m_inventoryDeletes.Dequeue(); 148 x = m_inventoryDeletes.Dequeue();
149 149
150 m_log.DebugFormat( 150// m_log.DebugFormat(
151 "[ASYNC DELETER]: Sending object to user's inventory, action {1}, count {2}, {0} item(s) remaining.", 151// "[ASYNC DELETER]: Sending object to user's inventory, action {1}, count {2}, {0} item(s) remaining.",
152 left, x.action, x.objectGroups.Count); 152// left, x.action, x.objectGroups.Count);
153 153
154 try 154 try
155 { 155 {
156 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>(); 156 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>();
157 if (invAccess != null) 157 if (invAccess != null)
158 invAccess.CopyToInventory(x.action, x.folderID, x.objectGroups, x.remoteClient); 158 invAccess.CopyToInventory(x.action, x.folderID, x.objectGroups, x.remoteClient, false);
159 159
160 if (x.permissionToDelete) 160 if (x.permissionToDelete)
161 { 161 {
@@ -185,7 +185,7 @@ namespace OpenSim.Region.Framework.Scenes
185 e.StackTrace); 185 e.StackTrace);
186 } 186 }
187 187
188 m_log.Debug("[ASYNC DELETER]: No objects left in inventory send queue."); 188// m_log.Debug("[ASYNC DELETER]: No objects left in inventory send queue.");
189 189
190 return false; 190 return false;
191 } 191 }
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index 2365cfe..76a952b 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -53,6 +53,10 @@ namespace OpenSim.Region.Framework.Scenes
53 53
54 public event ClientMovement OnClientMovement; 54 public event ClientMovement OnClientMovement;
55 55
56 public delegate void OnTerrainTaintedDelegate();
57
58 public event OnTerrainTaintedDelegate OnTerrainTainted;
59
56 public delegate void OnTerrainTickDelegate(); 60 public delegate void OnTerrainTickDelegate();
57 61
58 public delegate void OnTerrainUpdateDelegate(); 62 public delegate void OnTerrainUpdateDelegate();
@@ -484,6 +488,9 @@ namespace OpenSim.Region.Framework.Scenes
484 public delegate void SceneObjectPartUpdated(SceneObjectPart sop); 488 public delegate void SceneObjectPartUpdated(SceneObjectPart sop);
485 public event SceneObjectPartUpdated OnSceneObjectPartUpdated; 489 public event SceneObjectPartUpdated OnSceneObjectPartUpdated;
486 490
491 public delegate void ScenePresenceUpdated(ScenePresence sp);
492 public event ScenePresenceUpdated OnScenePresenceUpdated;
493
487 public delegate void RegionUp(GridRegion region); 494 public delegate void RegionUp(GridRegion region);
488 public event RegionUp OnRegionUp; 495 public event RegionUp OnRegionUp;
489 496
@@ -935,6 +942,27 @@ namespace OpenSim.Region.Framework.Scenes
935 } 942 }
936 } 943 }
937 944
945 public void TriggerTerrainTainted()
946 {
947 OnTerrainTaintedDelegate handlerTerrainTainted = OnTerrainTainted;
948 if (handlerTerrainTainted != null)
949 {
950 foreach (OnTerrainTaintedDelegate d in handlerTerrainTainted.GetInvocationList())
951 {
952 try
953 {
954 d();
955 }
956 catch (Exception e)
957 {
958 m_log.ErrorFormat(
959 "[EVENT MANAGER]: Delegate for TriggerTerrainTainted failed - continuing. {0} {1}",
960 e.Message, e.StackTrace);
961 }
962 }
963 }
964 }
965
938 public void TriggerParcelPrimCountAdd(SceneObjectGroup obj) 966 public void TriggerParcelPrimCountAdd(SceneObjectGroup obj)
939 { 967 {
940 OnParcelPrimCountAddDelegate handlerParcelPrimCountAdd = OnParcelPrimCountAdd; 968 OnParcelPrimCountAddDelegate handlerParcelPrimCountAdd = OnParcelPrimCountAdd;
@@ -2367,6 +2395,27 @@ namespace OpenSim.Region.Framework.Scenes
2367 } 2395 }
2368 } 2396 }
2369 2397
2398 public void TriggerScenePresenceUpdated(ScenePresence sp)
2399 {
2400 ScenePresenceUpdated handler = OnScenePresenceUpdated;
2401 if (handler != null)
2402 {
2403 foreach (ScenePresenceUpdated d in handler.GetInvocationList())
2404 {
2405 try
2406 {
2407 d(sp);
2408 }
2409 catch (Exception e)
2410 {
2411 m_log.ErrorFormat(
2412 "[EVENT MANAGER]: Delegate for TriggerScenePresenceUpdated failed - continuing. {0} {1}",
2413 e.Message, e.StackTrace);
2414 }
2415 }
2416 }
2417 }
2418
2370 public void TriggerOnParcelPropertiesUpdateRequest(LandUpdateArgs args, 2419 public void TriggerOnParcelPropertiesUpdateRequest(LandUpdateArgs args,
2371 int local_id, IClientAPI remote_client) 2420 int local_id, IClientAPI remote_client)
2372 { 2421 {
diff --git a/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs b/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs
index 6c5685c..1365831 100644
--- a/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs
+++ b/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs
@@ -48,16 +48,19 @@ namespace OpenSim.Region.Framework.Scenes
48{ 48{
49 public class RegionStatsHandler : IStreamedRequestHandler 49 public class RegionStatsHandler : IStreamedRequestHandler
50 { 50 {
51 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52
51 private string osRXStatsURI = String.Empty; 53 private string osRXStatsURI = String.Empty;
52 private string osXStatsURI = String.Empty; 54 private string osXStatsURI = String.Empty;
53 //private string osSecret = String.Empty; 55 //private string osSecret = String.Empty;
54 private OpenSim.Framework.RegionInfo regionInfo; 56 private OpenSim.Framework.RegionInfo regionInfo;
55 public string localZone = TimeZone.CurrentTimeZone.StandardName; 57 public string localZone = TimeZone.CurrentTimeZone.StandardName;
56 public TimeSpan utcOffset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now); 58 public TimeSpan utcOffset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now);
57
58 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
59 59
60 public RegionStatsHandler(OpenSim.Framework.RegionInfo region_info) 60 public string Name { get { return "RegionStats"; } }
61 public string Description { get { return "Region Statistics"; } }
62
63 public RegionStatsHandler(RegionInfo region_info)
61 { 64 {
62 regionInfo = region_info; 65 regionInfo = region_info;
63 osRXStatsURI = Util.SHA1Hash(regionInfo.regionSecret); 66 osRXStatsURI = Util.SHA1Hash(regionInfo.regionSecret);
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 29465c0..9776a82 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -60,19 +60,32 @@ namespace OpenSim.Region.Framework.Scenes
60 /// <summary> 60 /// <summary>
61 /// Creates all the scripts in the scene which should be started. 61 /// Creates all the scripts in the scene which should be started.
62 /// </summary> 62 /// </summary>
63 public void CreateScriptInstances() 63 /// <returns>
64 /// Number of scripts that were valid for starting. This does not guarantee that all these scripts
65 /// were actually started, but just that the start could be attempt (e.g. the asset data for the script could be found)
66 /// </returns>
67 public int CreateScriptInstances()
64 { 68 {
65 m_log.Info("[PRIM INVENTORY]: Creating scripts in scene"); 69 m_log.InfoFormat("[SCENE]: Initializing script instances in {0}", RegionInfo.RegionName);
70
71 int scriptsValidForStarting = 0;
66 72
67 EntityBase[] entities = Entities.GetEntities(); 73 EntityBase[] entities = Entities.GetEntities();
68 foreach (EntityBase group in entities) 74 foreach (EntityBase group in entities)
69 { 75 {
70 if (group is SceneObjectGroup) 76 if (group is SceneObjectGroup)
71 { 77 {
72 ((SceneObjectGroup) group).CreateScriptInstances(0, false, DefaultScriptEngine, 0); 78 scriptsValidForStarting
79 += ((SceneObjectGroup) group).CreateScriptInstances(0, false, DefaultScriptEngine, 0);
73 ((SceneObjectGroup) group).ResumeScripts(); 80 ((SceneObjectGroup) group).ResumeScripts();
74 } 81 }
75 } 82 }
83
84 m_log.InfoFormat(
85 "[SCENE]: Initialized {0} script instances in {1}",
86 scriptsValidForStarting, RegionInfo.RegionName);
87
88 return scriptsValidForStarting;
76 } 89 }
77 90
78 /// <summary> 91 /// <summary>
@@ -80,7 +93,7 @@ namespace OpenSim.Region.Framework.Scenes
80 /// </summary> 93 /// </summary>
81 public void StartScripts() 94 public void StartScripts()
82 { 95 {
83 m_log.Info("[PRIM INVENTORY]: Starting scripts in scene"); 96 m_log.InfoFormat("[SCENE]: Starting scripts in {0}, please wait.", RegionInfo.RegionName);
84 97
85 IScriptModule[] engines = RequestModuleInterfaces<IScriptModule>(); 98 IScriptModule[] engines = RequestModuleInterfaces<IScriptModule>();
86 99
@@ -300,6 +313,10 @@ namespace OpenSim.Region.Framework.Scenes
300 AssetBase asset = CreateAsset(item.Name, item.Description, (sbyte)AssetType.LSLText, data, remoteClient.AgentId); 313 AssetBase asset = CreateAsset(item.Name, item.Description, (sbyte)AssetType.LSLText, data, remoteClient.AgentId);
301 AssetService.Store(asset); 314 AssetService.Store(asset);
302 315
316// m_log.DebugFormat(
317// "[PRIM INVENTORY]: Stored asset {0} when updating item {1} in prim {2} for {3}",
318// asset.ID, item.Name, part.Name, remoteClient.Name);
319
303 if (isScriptRunning) 320 if (isScriptRunning)
304 { 321 {
305 part.Inventory.RemoveScriptInstance(item.ItemID, false); 322 part.Inventory.RemoveScriptInstance(item.ItemID, false);
@@ -431,10 +448,9 @@ namespace OpenSim.Region.Framework.Scenes
431 } 448 }
432 else 449 else
433 { 450 {
434 IAgentAssetTransactions agentTransactions = this.RequestModuleInterface<IAgentAssetTransactions>(); 451 if (AgentTransactionsModule != null)
435 if (agentTransactions != null)
436 { 452 {
437 agentTransactions.HandleItemUpdateFromTransaction(remoteClient, transactionID, item); 453 AgentTransactionsModule.HandleItemUpdateFromTransaction(remoteClient, transactionID, item);
438 } 454 }
439 } 455 }
440 } 456 }
@@ -950,8 +966,8 @@ namespace OpenSim.Region.Framework.Scenes
950 sbyte invType, sbyte type, UUID olditemID) 966 sbyte invType, sbyte type, UUID olditemID)
951 { 967 {
952// m_log.DebugFormat( 968// m_log.DebugFormat(
953// "[AGENT INVENTORY]: Received request from {0} to create inventory item link {1} in folder {2} pointing to {3}", 969// "[AGENT INVENTORY]: Received request from {0} to create inventory item link {1} in folder {2} pointing to {3}, assetType {4}, inventoryType {5}",
954// remoteClient.Name, name, folderID, olditemID); 970// remoteClient.Name, name, folderID, olditemID, (AssetType)type, (InventoryType)invType);
955 971
956 if (!Permissions.CanCreateUserInventory(invType, remoteClient.AgentId)) 972 if (!Permissions.CanCreateUserInventory(invType, remoteClient.AgentId))
957 return; 973 return;
@@ -984,10 +1000,10 @@ namespace OpenSim.Region.Framework.Scenes
984 asset.Type = type; 1000 asset.Type = type;
985 asset.Name = name; 1001 asset.Name = name;
986 asset.Description = description; 1002 asset.Description = description;
987 1003
988 CreateNewInventoryItem( 1004 CreateNewInventoryItem(
989 remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID, name, 0, callbackID, asset, invType, 1005 remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID, name, 0, callbackID, asset, invType,
990 (uint)PermissionMask.All, (uint)PermissionMask.All, (uint)PermissionMask.All, 1006 (uint)PermissionMask.All, (uint)PermissionMask.All, (uint)PermissionMask.All,
991 (uint)PermissionMask.All, (uint)PermissionMask.All, Util.UnixTimeSinceEpoch()); 1007 (uint)PermissionMask.All, (uint)PermissionMask.All, Util.UnixTimeSinceEpoch());
992 } 1008 }
993 else 1009 else
@@ -1562,21 +1578,17 @@ namespace OpenSim.Region.Framework.Scenes
1562 // Only look for an uploaded updated asset if we are passed a transaction ID. This is only the 1578 // Only look for an uploaded updated asset if we are passed a transaction ID. This is only the
1563 // case for updates uploded through UDP. Updates uploaded via a capability (e.g. a script update) 1579 // case for updates uploded through UDP. Updates uploaded via a capability (e.g. a script update)
1564 // will not pass in a transaction ID in the update message. 1580 // will not pass in a transaction ID in the update message.
1565 if (transactionID != UUID.Zero) 1581 if (transactionID != UUID.Zero && AgentTransactionsModule != null)
1566 { 1582 {
1567 IAgentAssetTransactions agentTransactions = this.RequestModuleInterface<IAgentAssetTransactions>(); 1583 AgentTransactionsModule.HandleTaskItemUpdateFromTransaction(
1568 if (agentTransactions != null) 1584 remoteClient, part, transactionID, currentItem);
1569 { 1585
1570 agentTransactions.HandleTaskItemUpdateFromTransaction( 1586// if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1571 remoteClient, part, transactionID, currentItem); 1587// remoteClient.SendAgentAlertMessage("Notecard saved", false);
1572 1588// else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1573// if ((InventoryType)itemInfo.InvType == InventoryType.Notecard) 1589// remoteClient.SendAgentAlertMessage("Script saved", false);
1574// remoteClient.SendAgentAlertMessage("Notecard saved", false); 1590// else
1575// else if ((InventoryType)itemInfo.InvType == InventoryType.LSL) 1591// remoteClient.SendAgentAlertMessage("Item saved", false);
1576// remoteClient.SendAgentAlertMessage("Script saved", false);
1577// else
1578// remoteClient.SendAgentAlertMessage("Item saved", false);
1579 }
1580 } 1592 }
1581 1593
1582 // Base ALWAYS has move 1594 // Base ALWAYS has move
@@ -2286,10 +2298,24 @@ namespace OpenSim.Region.Framework.Scenes
2286 if (part == null) 2298 if (part == null)
2287 return; 2299 return;
2288 2300
2301 IScriptModule[] engines = RequestModuleInterfaces<IScriptModule>();
2302
2289 if (running) 2303 if (running)
2304 {
2305 foreach (IScriptModule engine in engines)
2306 {
2307 engine.SetRunEnable(itemID, true);
2308 }
2290 EventManager.TriggerStartScript(part.LocalId, itemID); 2309 EventManager.TriggerStartScript(part.LocalId, itemID);
2310 }
2291 else 2311 else
2312 {
2313 foreach (IScriptModule engine in engines)
2314 {
2315 engine.SetRunEnable(itemID, false);
2316 }
2292 EventManager.TriggerStopScript(part.LocalId, itemID); 2317 EventManager.TriggerStopScript(part.LocalId, itemID);
2318 }
2293 } 2319 }
2294 2320
2295 public void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID) 2321 public void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID)
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
index e1fedf4..535d87a 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
@@ -67,6 +67,7 @@ namespace OpenSim.Region.Framework.Scenes
67 public delegate bool RunConsoleCommandHandler(UUID user, Scene requestFromScene); 67 public delegate bool RunConsoleCommandHandler(UUID user, Scene requestFromScene);
68 public delegate bool IssueEstateCommandHandler(UUID user, Scene requestFromScene, bool ownerCommand); 68 public delegate bool IssueEstateCommandHandler(UUID user, Scene requestFromScene, bool ownerCommand);
69 public delegate bool IsGodHandler(UUID user, Scene requestFromScene); 69 public delegate bool IsGodHandler(UUID user, Scene requestFromScene);
70 public delegate bool IsGridGodHandler(UUID user, Scene requestFromScene);
70 public delegate bool IsAdministratorHandler(UUID user); 71 public delegate bool IsAdministratorHandler(UUID user);
71 public delegate bool EditParcelHandler(UUID user, ILandObject parcel, Scene scene); 72 public delegate bool EditParcelHandler(UUID user, ILandObject parcel, Scene scene);
72 public delegate bool EditParcelPropertiesHandler(UUID user, ILandObject parcel, GroupPowers p, Scene scene); 73 public delegate bool EditParcelPropertiesHandler(UUID user, ILandObject parcel, GroupPowers p, Scene scene);
@@ -134,6 +135,7 @@ namespace OpenSim.Region.Framework.Scenes
134 public event RunConsoleCommandHandler OnRunConsoleCommand; 135 public event RunConsoleCommandHandler OnRunConsoleCommand;
135 public event IssueEstateCommandHandler OnIssueEstateCommand; 136 public event IssueEstateCommandHandler OnIssueEstateCommand;
136 public event IsGodHandler OnIsGod; 137 public event IsGodHandler OnIsGod;
138 public event IsGridGodHandler OnIsGridGod;
137 public event IsAdministratorHandler OnIsAdministrator; 139 public event IsAdministratorHandler OnIsAdministrator;
138// public event EditParcelHandler OnEditParcel; 140// public event EditParcelHandler OnEditParcel;
139 public event EditParcelPropertiesHandler OnEditParcelProperties; 141 public event EditParcelPropertiesHandler OnEditParcelProperties;
@@ -728,6 +730,21 @@ namespace OpenSim.Region.Framework.Scenes
728 return true; 730 return true;
729 } 731 }
730 732
733 public bool IsGridGod(UUID user)
734 {
735 IsGridGodHandler handler = OnIsGridGod;
736 if (handler != null)
737 {
738 Delegate[] list = handler.GetInvocationList();
739 foreach (IsGridGodHandler h in list)
740 {
741 if (h(user, m_scene) == false)
742 return false;
743 }
744 }
745 return true;
746 }
747
731 public bool IsAdministrator(UUID user) 748 public bool IsAdministrator(UUID user)
732 { 749 {
733 IsAdministratorHandler handler = OnIsAdministrator; 750 IsAdministratorHandler handler = OnIsAdministrator;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 48aca98..f437bc8 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -77,7 +77,12 @@ namespace OpenSim.Region.Framework.Scenes
77 public bool DebugUpdates { get; private set; } 77 public bool DebugUpdates { get; private set; }
78 78
79 public SynchronizeSceneHandler SynchronizeScene; 79 public SynchronizeSceneHandler SynchronizeScene;
80 public SimStatsReporter StatsReporter; 80
81 /// <summary>
82 /// Statistical information for this scene.
83 /// </summary>
84 public SimStatsReporter StatsReporter { get; private set; }
85
81 public List<Border> NorthBorders = new List<Border>(); 86 public List<Border> NorthBorders = new List<Border>();
82 public List<Border> EastBorders = new List<Border>(); 87 public List<Border> EastBorders = new List<Border>();
83 public List<Border> SouthBorders = new List<Border>(); 88 public List<Border> SouthBorders = new List<Border>();
@@ -103,6 +108,7 @@ namespace OpenSim.Region.Framework.Scenes
103 public bool m_trustBinaries; 108 public bool m_trustBinaries;
104 public bool m_allowScriptCrossings; 109 public bool m_allowScriptCrossings;
105 public bool m_useFlySlow; 110 public bool m_useFlySlow;
111 public bool m_useTrashOnDelete = true;
106 112
107 /// <summary> 113 /// <summary>
108 /// Temporarily setting to trigger appearance resends at 60 second intervals. 114 /// Temporarily setting to trigger appearance resends at 60 second intervals.
@@ -114,6 +120,9 @@ namespace OpenSim.Region.Framework.Scenes
114 { 120 {
115 get { return m_defaultDrawDistance; } 121 get { return m_defaultDrawDistance; }
116 } 122 }
123
124 private List<string> m_AllowedViewers = new List<string>();
125 private List<string> m_BannedViewers = new List<string>();
117 126
118 // TODO: need to figure out how allow client agents but deny 127 // TODO: need to figure out how allow client agents but deny
119 // root agents when ACL denies access to root agent 128 // root agents when ACL denies access to root agent
@@ -163,7 +172,6 @@ namespace OpenSim.Region.Framework.Scenes
163 protected IConfigSource m_config; 172 protected IConfigSource m_config;
164 protected IRegionSerialiserModule m_serialiser; 173 protected IRegionSerialiserModule m_serialiser;
165 protected IDialogModule m_dialogModule; 174 protected IDialogModule m_dialogModule;
166 protected IEntityTransferModule m_teleportModule;
167 protected ICapabilitiesModule m_capsModule; 175 protected ICapabilitiesModule m_capsModule;
168 protected IGroupsModule m_groupsModule; 176 protected IGroupsModule m_groupsModule;
169 177
@@ -217,6 +225,7 @@ namespace OpenSim.Region.Framework.Scenes
217 private int backupMS; 225 private int backupMS;
218 private int terrainMS; 226 private int terrainMS;
219 private int landMS; 227 private int landMS;
228 private int spareMS;
220 229
221 /// <summary> 230 /// <summary>
222 /// Tick at which the last frame was processed. 231 /// Tick at which the last frame was processed.
@@ -458,6 +467,7 @@ namespace OpenSim.Region.Framework.Scenes
458 { 467 {
459 if (m_simulationService == null) 468 if (m_simulationService == null)
460 m_simulationService = RequestModuleInterface<ISimulationService>(); 469 m_simulationService = RequestModuleInterface<ISimulationService>();
470
461 return m_simulationService; 471 return m_simulationService;
462 } 472 }
463 } 473 }
@@ -513,6 +523,9 @@ namespace OpenSim.Region.Framework.Scenes
513 } 523 }
514 524
515 public IAttachmentsModule AttachmentsModule { get; set; } 525 public IAttachmentsModule AttachmentsModule { get; set; }
526 public IEntityTransferModule EntityTransferModule { get; private set; }
527 public IAgentAssetTransactions AgentTransactionsModule { get; private set; }
528 public IUserManagement UserManagementModule { get; private set; }
516 529
517 public IAvatarFactoryModule AvatarFactory 530 public IAvatarFactoryModule AvatarFactory
518 { 531 {
@@ -589,6 +602,20 @@ namespace OpenSim.Region.Framework.Scenes
589 get { return m_sceneGraph.Entities; } 602 get { return m_sceneGraph.Entities; }
590 } 603 }
591 604
605
606 // used in sequence see: SpawnPoint()
607 private int m_SpawnPoint;
608 // can be closest/random/sequence
609 public string SpawnPointRouting
610 {
611 get; private set;
612 }
613 // allow landmarks to pass
614 public bool TelehubAllowLandmarks
615 {
616 get; private set;
617 }
618
592 #endregion Properties 619 #endregion Properties
593 620
594 #region Constructors 621 #region Constructors
@@ -606,14 +633,13 @@ namespace OpenSim.Region.Framework.Scenes
606 633
607 Random random = new Random(); 634 Random random = new Random();
608 635
609 m_lastAllocatedLocalId = (uint)(random.NextDouble() * (double)(uint.MaxValue/2))+(uint)(uint.MaxValue/4); 636 m_lastAllocatedLocalId = (uint)(random.NextDouble() * (double)(uint.MaxValue / 2)) + (uint)(uint.MaxValue / 4);
610 m_moduleLoader = moduleLoader; 637 m_moduleLoader = moduleLoader;
611 m_authenticateHandler = authen; 638 m_authenticateHandler = authen;
612 m_sceneGridService = sceneGridService; 639 m_sceneGridService = sceneGridService;
613 m_SimulationDataService = simDataService; 640 m_SimulationDataService = simDataService;
614 m_EstateDataService = estateDataService; 641 m_EstateDataService = estateDataService;
615 m_regionHandle = m_regInfo.RegionHandle; 642 m_regionHandle = m_regInfo.RegionHandle;
616 m_regionName = m_regInfo.RegionName;
617 m_lastIncoming = 0; 643 m_lastIncoming = 0;
618 m_lastOutgoing = 0; 644 m_lastOutgoing = 0;
619 645
@@ -630,7 +656,7 @@ namespace OpenSim.Region.Framework.Scenes
630 // resave. 656 // resave.
631 // FIXME: It shouldn't be up to the database plugins to create this data - we should do it when a new 657 // FIXME: It shouldn't be up to the database plugins to create this data - we should do it when a new
632 // region is set up and avoid these gyrations. 658 // region is set up and avoid these gyrations.
633 RegionSettings rs = simDataService.LoadRegionSettings(m_regInfo.RegionID); 659 RegionSettings rs = simDataService.LoadRegionSettings(RegionInfo.RegionID);
634 bool updatedTerrainTextures = false; 660 bool updatedTerrainTextures = false;
635 if (rs.TerrainTexture1 == UUID.Zero) 661 if (rs.TerrainTexture1 == UUID.Zero)
636 { 662 {
@@ -659,10 +685,10 @@ namespace OpenSim.Region.Framework.Scenes
659 if (updatedTerrainTextures) 685 if (updatedTerrainTextures)
660 rs.Save(); 686 rs.Save();
661 687
662 m_regInfo.RegionSettings = rs; 688 RegionInfo.RegionSettings = rs;
663 689
664 if (estateDataService != null) 690 if (estateDataService != null)
665 m_regInfo.EstateSettings = estateDataService.LoadEstateSettings(m_regInfo.RegionID, false); 691 RegionInfo.EstateSettings = estateDataService.LoadEstateSettings(RegionInfo.RegionID, false);
666 692
667 #endregion Region Settings 693 #endregion Region Settings
668 694
@@ -726,6 +752,9 @@ namespace OpenSim.Region.Framework.Scenes
726 m_maxPhys = RegionInfo.PhysPrimMax; 752 m_maxPhys = RegionInfo.PhysPrimMax;
727 } 753 }
728 754
755 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest");
756 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false);
757
729 // Here, if clamping is requested in either global or 758 // Here, if clamping is requested in either global or
730 // local config, it will be used 759 // local config, it will be used
731 // 760 //
@@ -735,6 +764,7 @@ namespace OpenSim.Region.Framework.Scenes
735 m_clampPrimSize = true; 764 m_clampPrimSize = true;
736 } 765 }
737 766
767 m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete",m_useTrashOnDelete);
738 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries); 768 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries);
739 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings); 769 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings);
740 m_dontPersistBefore = 770 m_dontPersistBefore =
@@ -781,6 +811,24 @@ namespace OpenSim.Region.Framework.Scenes
781 } 811 }
782 } 812 }
783 813
814 string grant = startupConfig.GetString("AllowedClients", String.Empty);
815 if (grant.Length > 0)
816 {
817 foreach (string viewer in grant.Split(','))
818 {
819 m_AllowedViewers.Add(viewer.Trim().ToLower());
820 }
821 }
822
823 grant = startupConfig.GetString("BannedClients", String.Empty);
824 if (grant.Length > 0)
825 {
826 foreach (string viewer in grant.Split(','))
827 {
828 m_BannedViewers.Add(viewer.Trim().ToLower());
829 }
830 }
831
784 MinFrameTime = startupConfig.GetFloat( "MinFrameTime", MinFrameTime); 832 MinFrameTime = startupConfig.GetFloat( "MinFrameTime", MinFrameTime);
785 m_update_backup = startupConfig.GetInt( "UpdateStorageEveryNFrames", m_update_backup); 833 m_update_backup = startupConfig.GetInt( "UpdateStorageEveryNFrames", m_update_backup);
786 m_update_coarse_locations = startupConfig.GetInt( "UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations); 834 m_update_coarse_locations = startupConfig.GetInt( "UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations);
@@ -835,13 +883,11 @@ namespace OpenSim.Region.Framework.Scenes
835 MainConsole.Instance.Commands.AddCommand("scene", false, "gc collect", "gc collect", "gc collect", "Cause the garbage collector to make a single pass", HandleGcCollect); 883 MainConsole.Instance.Commands.AddCommand("scene", false, "gc collect", "gc collect", "gc collect", "Cause the garbage collector to make a single pass", HandleGcCollect);
836 } 884 }
837 885
838 /// <summary> 886 public Scene(RegionInfo regInfo) : base(regInfo)
839 /// Mock constructor for scene group persistency unit tests.
840 /// SceneObjectGroup RegionId property is delegated to Scene.
841 /// </summary>
842 /// <param name="regInfo"></param>
843 public Scene(RegionInfo regInfo)
844 { 887 {
888 PhysicalPrims = true;
889 CollidablePrims = true;
890
845 BordersLocked = true; 891 BordersLocked = true;
846 Border northBorder = new Border(); 892 Border northBorder = new Border();
847 northBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, (int)Constants.RegionSize); //<--- 893 northBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, (int)Constants.RegionSize); //<---
@@ -864,12 +910,9 @@ namespace OpenSim.Region.Framework.Scenes
864 WestBorders.Add(westBorder); 910 WestBorders.Add(westBorder);
865 BordersLocked = false; 911 BordersLocked = false;
866 912
867 m_regInfo = regInfo;
868 m_eventManager = new EventManager(); 913 m_eventManager = new EventManager();
869 914
870 m_permissions = new ScenePermissions(this); 915 m_permissions = new ScenePermissions(this);
871
872// m_lastUpdate = Util.EnvironmentTickCount();
873 } 916 }
874 917
875 #endregion 918 #endregion
@@ -938,8 +981,8 @@ namespace OpenSim.Region.Framework.Scenes
938 List<ulong> old = new List<ulong>(); 981 List<ulong> old = new List<ulong>();
939 old.Add(otherRegion.RegionHandle); 982 old.Add(otherRegion.RegionHandle);
940 agent.DropOldNeighbours(old); 983 agent.DropOldNeighbours(old);
941 if (m_teleportModule != null && agent.PresenceType != PresenceType.Npc) 984 if (EntityTransferModule != null && agent.PresenceType != PresenceType.Npc)
942 m_teleportModule.EnableChildAgent(agent, otherRegion); 985 EntityTransferModule.EnableChildAgent(agent, otherRegion);
943 }); 986 });
944 } 987 }
945 catch (NullReferenceException) 988 catch (NullReferenceException)
@@ -952,7 +995,7 @@ namespace OpenSim.Region.Framework.Scenes
952 else 995 else
953 { 996 {
954 m_log.InfoFormat( 997 m_log.InfoFormat(
955 "[INTERGRID]: Got notice about far away Region: {0} at ({1}, {2})", 998 "[SCENE]: Got notice about far away Region: {0} at ({1}, {2})",
956 otherRegion.RegionName, otherRegion.RegionLocX, otherRegion.RegionLocY); 999 otherRegion.RegionName, otherRegion.RegionLocX, otherRegion.RegionLocY);
957 } 1000 }
958 } 1001 }
@@ -1046,13 +1089,13 @@ namespace OpenSim.Region.Framework.Scenes
1046 } 1089 }
1047 } 1090 }
1048 1091
1092 m_log.Error("[REGION]: Closing");
1093 Close();
1094
1049 if (PhysicsScene != null) 1095 if (PhysicsScene != null)
1050 { 1096 {
1051 PhysicsScene.Dispose(); 1097 PhysicsScene.Dispose();
1052 } 1098 }
1053
1054 m_log.Error("[REGION]: Closing");
1055 Close();
1056 1099
1057 m_log.Error("[REGION]: Firing Region Restart Message"); 1100 m_log.Error("[REGION]: Firing Region Restart Message");
1058 1101
@@ -1076,8 +1119,8 @@ namespace OpenSim.Region.Framework.Scenes
1076 { 1119 {
1077 ForEachRootScenePresence(delegate(ScenePresence agent) 1120 ForEachRootScenePresence(delegate(ScenePresence agent)
1078 { 1121 {
1079 if (m_teleportModule != null && agent.PresenceType != PresenceType.Npc) 1122 if (EntityTransferModule != null && agent.PresenceType != PresenceType.Npc)
1080 m_teleportModule.EnableChildAgent(agent, r); 1123 EntityTransferModule.EnableChildAgent(agent, r);
1081 }); 1124 });
1082 } 1125 }
1083 catch (NullReferenceException) 1126 catch (NullReferenceException)
@@ -1210,8 +1253,8 @@ namespace OpenSim.Region.Framework.Scenes
1210 1253
1211 m_sceneGraph.Close(); 1254 m_sceneGraph.Close();
1212 1255
1213 if (!GridService.DeregisterRegion(m_regInfo.RegionID)) 1256 if (!GridService.DeregisterRegion(RegionInfo.RegionID))
1214 m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", m_regInfo.RegionName); 1257 m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name);
1215 1258
1216 // call the base class Close method. 1259 // call the base class Close method.
1217 base.Close(); 1260 base.Close();
@@ -1267,8 +1310,10 @@ namespace OpenSim.Region.Framework.Scenes
1267 m_serialiser = RequestModuleInterface<IRegionSerialiserModule>(); 1310 m_serialiser = RequestModuleInterface<IRegionSerialiserModule>();
1268 m_dialogModule = RequestModuleInterface<IDialogModule>(); 1311 m_dialogModule = RequestModuleInterface<IDialogModule>();
1269 m_capsModule = RequestModuleInterface<ICapabilitiesModule>(); 1312 m_capsModule = RequestModuleInterface<ICapabilitiesModule>();
1270 m_teleportModule = RequestModuleInterface<IEntityTransferModule>(); 1313 EntityTransferModule = RequestModuleInterface<IEntityTransferModule>();
1271 m_groupsModule = RequestModuleInterface<IGroupsModule>(); 1314 m_groupsModule = RequestModuleInterface<IGroupsModule>();
1315 AgentTransactionsModule = RequestModuleInterface<IAgentAssetTransactions>();
1316 UserManagementModule = RequestModuleInterface<IUserManagement>();
1272 } 1317 }
1273 1318
1274 #endregion 1319 #endregion
@@ -1389,37 +1434,41 @@ namespace OpenSim.Region.Framework.Scenes
1389 endFrame = Frame + frames; 1434 endFrame = Frame + frames;
1390 1435
1391 float physicsFPS = 0f; 1436 float physicsFPS = 0f;
1392 int tmpPhysicsMS, tmpPhysicsMS2, tmpAgentMS, tmpTempOnRezMS, evMS, backMS, terMS; 1437 int previousFrameTick, tmpMS;
1393 int previousFrameTick; 1438 int maintc = Util.EnvironmentTickCount();
1394 int maintc;
1395 int sleepMS;
1396 int framestart;
1397 1439
1398 while (!m_shuttingDown && (endFrame == null || Frame < endFrame)) 1440 while (!m_shuttingDown && (endFrame == null || Frame < endFrame))
1399 { 1441 {
1400 framestart = Util.EnvironmentTickCount();
1401 ++Frame; 1442 ++Frame;
1402 1443
1403// m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName); 1444// m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName);
1404 1445
1405 agentMS = tempOnRezMS = eventMS = backupMS = terrainMS = landMS = 0; 1446 agentMS = tempOnRezMS = eventMS = backupMS = terrainMS = landMS = spareMS = 0;
1406 1447
1407 try 1448 try
1408 { 1449 {
1409 tmpPhysicsMS2 = Util.EnvironmentTickCount(); 1450 // Apply taints in terrain module to terrain in physics scene
1451 if (Frame % m_update_terrain == 0)
1452 {
1453 tmpMS = Util.EnvironmentTickCount();
1454 UpdateTerrain();
1455 terrainMS = Util.EnvironmentTickCountSubtract(tmpMS);
1456 }
1457
1458 tmpMS = Util.EnvironmentTickCount();
1410 if ((Frame % m_update_physics == 0) && m_physics_enabled) 1459 if ((Frame % m_update_physics == 0) && m_physics_enabled)
1411 m_sceneGraph.UpdatePreparePhysics(); 1460 m_sceneGraph.UpdatePreparePhysics();
1412 physicsMS2 = Util.EnvironmentTickCountSubtract(tmpPhysicsMS2); 1461 physicsMS2 = Util.EnvironmentTickCountSubtract(tmpMS);
1413 1462
1414 // Apply any pending avatar force input to the avatar's velocity 1463 // Apply any pending avatar force input to the avatar's velocity
1415 tmpAgentMS = Util.EnvironmentTickCount(); 1464 tmpMS = Util.EnvironmentTickCount();
1416 if (Frame % m_update_entitymovement == 0) 1465 if (Frame % m_update_entitymovement == 0)
1417 m_sceneGraph.UpdateScenePresenceMovement(); 1466 m_sceneGraph.UpdateScenePresenceMovement();
1418 agentMS = Util.EnvironmentTickCountSubtract(tmpAgentMS); 1467 agentMS = Util.EnvironmentTickCountSubtract(tmpMS);
1419 1468
1420 // Perform the main physics update. This will do the actual work of moving objects and avatars according to their 1469 // Perform the main physics update. This will do the actual work of moving objects and avatars according to their
1421 // velocity 1470 // velocity
1422 tmpPhysicsMS = Util.EnvironmentTickCount(); 1471 tmpMS = Util.EnvironmentTickCount();
1423 if (Frame % m_update_physics == 0) 1472 if (Frame % m_update_physics == 0)
1424 { 1473 {
1425 if (m_physics_enabled) 1474 if (m_physics_enabled)
@@ -1428,9 +1477,9 @@ namespace OpenSim.Region.Framework.Scenes
1428 if (SynchronizeScene != null) 1477 if (SynchronizeScene != null)
1429 SynchronizeScene(this); 1478 SynchronizeScene(this);
1430 } 1479 }
1431 physicsMS = Util.EnvironmentTickCountSubtract(tmpPhysicsMS); 1480 physicsMS = Util.EnvironmentTickCountSubtract(tmpMS);
1432 1481
1433 tmpAgentMS = Util.EnvironmentTickCount(); 1482 tmpMS = Util.EnvironmentTickCount();
1434 1483
1435 // Check if any objects have reached their targets 1484 // Check if any objects have reached their targets
1436 CheckAtTargets(); 1485 CheckAtTargets();
@@ -1445,36 +1494,29 @@ namespace OpenSim.Region.Framework.Scenes
1445 if (Frame % m_update_presences == 0) 1494 if (Frame % m_update_presences == 0)
1446 m_sceneGraph.UpdatePresences(); 1495 m_sceneGraph.UpdatePresences();
1447 1496
1448 agentMS += Util.EnvironmentTickCountSubtract(tmpAgentMS); 1497 agentMS += Util.EnvironmentTickCountSubtract(tmpMS);
1449 1498
1450 // Delete temp-on-rez stuff 1499 // Delete temp-on-rez stuff
1451 if (Frame % m_update_temp_cleaning == 0 && !m_cleaningTemps) 1500 if (Frame % m_update_temp_cleaning == 0 && !m_cleaningTemps)
1452 { 1501 {
1453 tmpTempOnRezMS = Util.EnvironmentTickCount(); 1502 tmpMS = Util.EnvironmentTickCount();
1454 m_cleaningTemps = true; 1503 m_cleaningTemps = true;
1455 Util.FireAndForget(delegate { CleanTempObjects(); m_cleaningTemps = false; }); 1504 Util.FireAndForget(delegate { CleanTempObjects(); m_cleaningTemps = false; });
1456 tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpTempOnRezMS); 1505 tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpMS);
1457 } 1506 }
1458 1507
1459 if (Frame % m_update_events == 0) 1508 if (Frame % m_update_events == 0)
1460 { 1509 {
1461 evMS = Util.EnvironmentTickCount(); 1510 tmpMS = Util.EnvironmentTickCount();
1462 UpdateEvents(); 1511 UpdateEvents();
1463 eventMS = Util.EnvironmentTickCountSubtract(evMS); 1512 eventMS = Util.EnvironmentTickCountSubtract(tmpMS);
1464 } 1513 }
1465 1514
1466 if (Frame % m_update_backup == 0) 1515 if (Frame % m_update_backup == 0)
1467 { 1516 {
1468 backMS = Util.EnvironmentTickCount(); 1517 tmpMS = Util.EnvironmentTickCount();
1469 UpdateStorageBackup(); 1518 UpdateStorageBackup();
1470 backupMS = Util.EnvironmentTickCountSubtract(backMS); 1519 backupMS = Util.EnvironmentTickCountSubtract(tmpMS);
1471 }
1472
1473 if (Frame % m_update_terrain == 0)
1474 {
1475 terMS = Util.EnvironmentTickCount();
1476 UpdateTerrain();
1477 terrainMS = Util.EnvironmentTickCountSubtract(terMS);
1478 } 1520 }
1479 1521
1480 //if (Frame % m_update_land == 0) 1522 //if (Frame % m_update_land == 0)
@@ -1483,29 +1525,6 @@ namespace OpenSim.Region.Framework.Scenes
1483 // UpdateLand(); 1525 // UpdateLand();
1484 // landMS = Util.EnvironmentTickCountSubtract(ldMS); 1526 // landMS = Util.EnvironmentTickCountSubtract(ldMS);
1485 //} 1527 //}
1486
1487 // frameMS = Util.EnvironmentTickCountSubtract(maintc);
1488 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS;
1489
1490 // if (Frame%m_update_avatars == 0)
1491 // UpdateInWorldTime();
1492 StatsReporter.AddPhysicsFPS(physicsFPS);
1493 StatsReporter.AddTimeDilation(TimeDilation);
1494 StatsReporter.AddFPS(1);
1495 StatsReporter.SetRootAgents(m_sceneGraph.GetRootAgentCount());
1496 StatsReporter.SetChildAgents(m_sceneGraph.GetChildAgentCount());
1497 StatsReporter.SetObjects(m_sceneGraph.GetTotalObjectsCount());
1498 StatsReporter.SetActiveObjects(m_sceneGraph.GetActiveObjectsCount());
1499
1500 // frameMS currently records work frame times, not total frame times (work + any required sleep to
1501 // reach min frame time.
1502 // StatsReporter.addFrameMS(frameMS);
1503
1504 StatsReporter.addAgentMS(agentMS);
1505 StatsReporter.addPhysicsMS(physicsMS + physicsMS2);
1506 StatsReporter.addOtherMS(otherMS);
1507 StatsReporter.SetActiveScripts(m_sceneGraph.GetActiveScriptsCount());
1508 StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS());
1509 1528
1510 if (LoginsDisabled && Frame == 20) 1529 if (LoginsDisabled && Frame == 20)
1511 { 1530 {
@@ -1526,11 +1545,11 @@ namespace OpenSim.Region.Framework.Scenes
1526 LoginLock = false; 1545 LoginLock = false;
1527 EventManager.TriggerLoginsEnabled(RegionInfo.RegionName); 1546 EventManager.TriggerLoginsEnabled(RegionInfo.RegionName);
1528 } 1547 }
1529 m_log.DebugFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName);
1530 1548
1531 // For RegionReady lockouts 1549 // For RegionReady lockouts
1532 if(LoginLock == false) 1550 if (!LoginLock)
1533 { 1551 {
1552 m_log.InfoFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName);
1534 LoginsDisabled = false; 1553 LoginsDisabled = false;
1535 } 1554 }
1536 1555
@@ -1556,23 +1575,36 @@ namespace OpenSim.Region.Framework.Scenes
1556 1575
1557 previousFrameTick = m_lastFrameTick; 1576 previousFrameTick = m_lastFrameTick;
1558 m_lastFrameTick = Util.EnvironmentTickCount(); 1577 m_lastFrameTick = Util.EnvironmentTickCount();
1559 maintc = Util.EnvironmentTickCountSubtract(m_lastFrameTick, framestart); 1578 tmpMS = Util.EnvironmentTickCountSubtract(m_lastFrameTick, maintc);
1560 maintc = (int)(MinFrameTime * 1000) - maintc; 1579 tmpMS = (int)(MinFrameTime * 1000) - tmpMS;
1561 1580
1562 m_firstHeartbeat = false; 1581 m_firstHeartbeat = false;
1563 1582
1583 if (tmpMS > 0)
1584 {
1585 Thread.Sleep(tmpMS);
1586 spareMS += tmpMS;
1587 }
1588
1589 frameMS = Util.EnvironmentTickCountSubtract(maintc);
1590 maintc = Util.EnvironmentTickCount();
1564 1591
1565 sleepMS = Util.EnvironmentTickCount(); 1592 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS;
1566 1593
1567 if (maintc > 0) 1594 // if (Frame%m_update_avatars == 0)
1568 Thread.Sleep(maintc); 1595 // UpdateInWorldTime();
1596 StatsReporter.AddPhysicsFPS(physicsFPS);
1597 StatsReporter.AddTimeDilation(TimeDilation);
1598 StatsReporter.AddFPS(1);
1569 1599
1570 sleepMS = Util.EnvironmentTickCountSubtract(sleepMS);
1571 frameMS = Util.EnvironmentTickCountSubtract(framestart);
1572 StatsReporter.addSleepMS(sleepMS);
1573 StatsReporter.addFrameMS(frameMS); 1600 StatsReporter.addFrameMS(frameMS);
1574 1601 StatsReporter.addAgentMS(agentMS);
1575 // Optionally warn if a frame takes double the amount of time that it should. 1602 StatsReporter.addPhysicsMS(physicsMS + physicsMS2);
1603 StatsReporter.addOtherMS(otherMS);
1604 StatsReporter.AddSpareMS(spareMS);
1605 StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS());
1606
1607 // Optionally warn if a frame takes double the amount of time that it should.
1576 if (DebugUpdates 1608 if (DebugUpdates
1577 && Util.EnvironmentTickCountSubtract( 1609 && Util.EnvironmentTickCountSubtract(
1578 m_lastFrameTick, previousFrameTick) > (int)(MinFrameTime * 1000 * 2)) 1610 m_lastFrameTick, previousFrameTick) > (int)(MinFrameTime * 1000 * 2))
@@ -1759,14 +1791,14 @@ namespace OpenSim.Region.Framework.Scenes
1759 1791
1760 public void StoreWindlightProfile(RegionLightShareData wl) 1792 public void StoreWindlightProfile(RegionLightShareData wl)
1761 { 1793 {
1762 m_regInfo.WindlightSettings = wl; 1794 RegionInfo.WindlightSettings = wl;
1763 SimulationDataService.StoreRegionWindlightSettings(wl); 1795 SimulationDataService.StoreRegionWindlightSettings(wl);
1764 m_eventManager.TriggerOnSaveNewWindlightProfile(); 1796 m_eventManager.TriggerOnSaveNewWindlightProfile();
1765 } 1797 }
1766 1798
1767 public void LoadWindlightProfile() 1799 public void LoadWindlightProfile()
1768 { 1800 {
1769 m_regInfo.WindlightSettings = SimulationDataService.LoadRegionWindlightSettings(RegionInfo.RegionID); 1801 RegionInfo.WindlightSettings = SimulationDataService.LoadRegionWindlightSettings(RegionInfo.RegionID);
1770 m_eventManager.TriggerOnSaveNewWindlightProfile(); 1802 m_eventManager.TriggerOnSaveNewWindlightProfile();
1771 } 1803 }
1772 1804
@@ -2085,9 +2117,8 @@ namespace OpenSim.Region.Framework.Scenes
2085 sceneObject.SetGroup(groupID, null); 2117 sceneObject.SetGroup(groupID, null);
2086 } 2118 }
2087 2119
2088 IUserManagement uman = RequestModuleInterface<IUserManagement>(); 2120 if (UserManagementModule != null)
2089 if (uman != null) 2121 sceneObject.RootPart.CreatorIdentification = UserManagementModule.GetUserUUI(ownerID);
2090 sceneObject.RootPart.CreatorIdentification = uman.GetUserUUI(ownerID);
2091 2122
2092 sceneObject.ScheduleGroupForFullUpdate(); 2123 sceneObject.ScheduleGroupForFullUpdate();
2093 2124
@@ -2252,13 +2283,30 @@ namespace OpenSim.Region.Framework.Scenes
2252 /// <summary> 2283 /// <summary>
2253 /// Synchronously delete the given object from the scene. 2284 /// Synchronously delete the given object from the scene.
2254 /// </summary> 2285 /// </summary>
2286 /// <remarks>
2287 /// Scripts are also removed.
2288 /// </remarks>
2255 /// <param name="group">Object Id</param> 2289 /// <param name="group">Object Id</param>
2256 /// <param name="silent">Suppress broadcasting changes to other clients.</param> 2290 /// <param name="silent">Suppress broadcasting changes to other clients.</param>
2257 public void DeleteSceneObject(SceneObjectGroup group, bool silent) 2291 public void DeleteSceneObject(SceneObjectGroup group, bool silent)
2292 {
2293 DeleteSceneObject(group, silent, true);
2294 }
2295
2296 /// <summary>
2297 /// Synchronously delete the given object from the scene.
2298 /// </summary>
2299 /// <param name="group">Object Id</param>
2300 /// <param name="silent">Suppress broadcasting changes to other clients.</param>
2301 /// <param name="removeScripts">If true, then scripts are removed. If false, then they are only stopped.</para>
2302 public void DeleteSceneObject(SceneObjectGroup group, bool silent, bool removeScripts)
2258 { 2303 {
2259// m_log.DebugFormat("[SCENE]: Deleting scene object {0} {1}", group.Name, group.UUID); 2304// m_log.DebugFormat("[SCENE]: Deleting scene object {0} {1}", group.Name, group.UUID);
2260 2305
2261 group.RemoveScriptInstances(true); 2306 if (removeScripts)
2307 group.RemoveScriptInstances(true);
2308 else
2309 group.StopScriptInstances();
2262 2310
2263 SceneObjectPart[] partList = group.Parts; 2311 SceneObjectPart[] partList = group.Parts;
2264 2312
@@ -2308,7 +2356,7 @@ namespace OpenSim.Region.Framework.Scenes
2308 ForceSceneObjectBackup(so); 2356 ForceSceneObjectBackup(so);
2309 2357
2310 so.DetachFromBackup(); 2358 so.DetachFromBackup();
2311 SimulationDataService.RemoveObject(so.UUID, m_regInfo.RegionID); 2359 SimulationDataService.RemoveObject(so.UUID, RegionInfo.RegionID);
2312 } 2360 }
2313 2361
2314 // We need to keep track of this state in case this group is still queued for further backup. 2362 // We need to keep track of this state in case this group is still queued for further backup.
@@ -2365,8 +2413,8 @@ namespace OpenSim.Region.Framework.Scenes
2365 return; 2413 return;
2366 } 2414 }
2367 2415
2368 if (m_teleportModule != null) 2416 if (EntityTransferModule != null)
2369 m_teleportModule.Cross(grp, attemptedPosition, silent); 2417 EntityTransferModule.Cross(grp, attemptedPosition, silent);
2370 } 2418 }
2371 2419
2372 public Border GetCrossedBorder(Vector3 position, Cardinals gridline) 2420 public Border GetCrossedBorder(Vector3 position, Cardinals gridline)
@@ -2566,7 +2614,16 @@ namespace OpenSim.Region.Framework.Scenes
2566 } 2614 }
2567 catch (Exception e) 2615 catch (Exception e)
2568 { 2616 {
2569 m_log.WarnFormat("[SCENE]: Problem casting object, exception {0}{1}", e.Message, e.StackTrace); 2617 m_log.WarnFormat("[INTERREGION]: Problem casting object, exception {0}{1}", e.Message, e.StackTrace);
2618 return false;
2619 }
2620
2621 // If the user is banned, we won't let any of their objects
2622 // enter. Period.
2623 //
2624 if (RegionInfo.EstateSettings.IsBanned(newObject.OwnerID, 36))
2625 {
2626 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", newObject.OwnerID);
2570 return false; 2627 return false;
2571 } 2628 }
2572 2629
@@ -2577,32 +2634,30 @@ namespace OpenSim.Region.Framework.Scenes
2577 2634
2578 if (!AddSceneObject(newObject)) 2635 if (!AddSceneObject(newObject))
2579 { 2636 {
2580 m_log.DebugFormat("[SCENE]: Problem adding scene object {0} in {1} ", sog.UUID, RegionInfo.RegionName); 2637 m_log.DebugFormat(
2638 "[INTERREGION]: Problem adding scene object {0} in {1} ", newObject.UUID, RegionInfo.RegionName);
2581 return false; 2639 return false;
2582 } 2640 }
2583 2641
2584 // For attachments, we need to wait until the agent is root
2585 // before we restart the scripts, or else some functions won't work.
2586 if (!newObject.IsAttachment) 2642 if (!newObject.IsAttachment)
2587 { 2643 {
2588 newObject.RootPart.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, GetStateSource(newObject)); 2644 // FIXME: It would be better to never add the scene object at all rather than add it and then delete
2589 newObject.ResumeScripts(); 2645 // it
2590 } 2646 if (!Permissions.CanObjectEntry(newObject.UUID, true, newObject.AbsolutePosition))
2591 else
2592 {
2593 ScenePresence sp;
2594 if (TryGetScenePresence(newObject.OwnerID, out sp))
2595 { 2647 {
2596 // If the scene presence is here and already a root 2648 // Deny non attachments based on parcel settings
2597 // agent, we came from a ;egacy region. Start the scripts 2649 //
2598 // here as they used to start. 2650 m_log.Info("[INTERREGION]: Denied prim crossing because of parcel settings");
2599 // TODO: Remove in 0.7.3 2651
2600 if (!sp.IsChildAgent) 2652 DeleteSceneObject(newObject, false);
2601 { 2653
2602 newObject.RootPart.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, GetStateSource(newObject)); 2654 return false;
2603 newObject.ResumeScripts();
2604 }
2605 } 2655 }
2656
2657 // For attachments, we need to wait until the agent is root
2658 // before we restart the scripts, or else some functions won't work.
2659 newObject.RootPart.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, GetStateSource(newObject));
2660 newObject.ResumeScripts();
2606 } 2661 }
2607 2662
2608 // Do this as late as possible so that listeners have full access to the incoming object 2663 // Do this as late as possible so that listeners have full access to the incoming object
@@ -2612,28 +2667,6 @@ namespace OpenSim.Region.Framework.Scenes
2612 } 2667 }
2613 2668
2614 /// <summary> 2669 /// <summary>
2615 /// Attachment rezzing
2616 /// </summary>
2617 /// <param name="userID">Agent Unique ID</param>
2618 /// <param name="itemID">Object ID</param>
2619 /// <returns>False</returns>
2620 public virtual bool IncomingCreateObject(UUID userID, UUID itemID)
2621 {
2622 m_log.DebugFormat(" >>> IncomingCreateObject(userID, itemID) <<< {0} {1}", userID, itemID);
2623
2624 // Commented out since this is as yet unused and is arguably not the appropriate place to do this, as
2625 // attachments are being rezzed elsewhere in AddNewClient()
2626// ScenePresence sp = GetScenePresence(userID);
2627// if (sp != null && AttachmentsModule != null)
2628// {
2629// uint attPt = (uint)sp.Appearance.GetAttachpoint(itemID);
2630// AttachmentsModule.RezSingleAttachmentFromInventory(sp.ControllingClient, itemID, attPt);
2631// }
2632
2633 return false;
2634 }
2635
2636 /// <summary>
2637 /// Adds a Scene Object group to the Scene. 2670 /// Adds a Scene Object group to the Scene.
2638 /// Verifies that the creator of the object is not banned from the simulator. 2671 /// Verifies that the creator of the object is not banned from the simulator.
2639 /// Checks if the item is an Attachment 2672 /// Checks if the item is an Attachment
@@ -2652,15 +2685,13 @@ namespace OpenSim.Region.Framework.Scenes
2652 // enter. Period. 2685 // enter. Period.
2653 // 2686 //
2654 int flags = GetUserFlags(sceneObject.OwnerID); 2687 int flags = GetUserFlags(sceneObject.OwnerID);
2655 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags)) 2688 if (RegionInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2656 { 2689 {
2657 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID); 2690 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID);
2658 2691
2659 return false; 2692 return false;
2660 } 2693 }
2661 2694
2662 sceneObject.SetScene(this);
2663
2664 // Force allocation of new LocalId 2695 // Force allocation of new LocalId
2665 // 2696 //
2666 SceneObjectPart[] parts = sceneObject.Parts; 2697 SceneObjectPart[] parts = sceneObject.Parts;
@@ -2686,10 +2717,10 @@ namespace OpenSim.Region.Framework.Scenes
2686 { 2717 {
2687 SceneObjectGroup grp = sceneObject; 2718 SceneObjectGroup grp = sceneObject;
2688 2719
2689 m_log.DebugFormat( 2720// m_log.DebugFormat(
2690 "[ATTACHMENT]: Received attachment {0}, inworld asset id {1}", grp.FromItemID, grp.UUID); 2721// "[ATTACHMENT]: Received attachment {0}, inworld asset id {1}", grp.FromItemID, grp.UUID);
2691 m_log.DebugFormat( 2722// m_log.DebugFormat(
2692 "[ATTACHMENT]: Attach to avatar {0} at position {1}", sp.UUID, grp.AbsolutePosition); 2723// "[ATTACHMENT]: Attach to avatar {0} at position {1}", sp.UUID, grp.AbsolutePosition);
2693 2724
2694 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2725 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2695 2726
@@ -2716,18 +2747,6 @@ namespace OpenSim.Region.Framework.Scenes
2716 return false; 2747 return false;
2717 } 2748 }
2718 AddRestoredSceneObject(sceneObject, true, false); 2749 AddRestoredSceneObject(sceneObject, true, false);
2719
2720 if (!Permissions.CanObjectEntry(sceneObject.UUID,
2721 true, sceneObject.AbsolutePosition))
2722 {
2723 // Deny non attachments based on parcel settings
2724 //
2725 m_log.Info("[INTERREGION]: Denied prim crossing because of parcel settings");
2726
2727 DeleteSceneObject(sceneObject, false);
2728
2729 return false;
2730 }
2731 } 2750 }
2732 2751
2733 return true; 2752 return true;
@@ -2785,7 +2804,8 @@ namespace OpenSim.Region.Framework.Scenes
2785 if (sp == null) 2804 if (sp == null)
2786 { 2805 {
2787 m_log.DebugFormat( 2806 m_log.DebugFormat(
2788 "[SCENE]: Adding new child scene presence {0} to scene {1} at pos {2}", client.Name, RegionInfo.RegionName, client.StartPos); 2807 "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}",
2808 client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos);
2789 2809
2790 m_clientManager.Add(client); 2810 m_clientManager.Add(client);
2791 SubscribeToClientEvents(client); 2811 SubscribeToClientEvents(client);
@@ -2845,14 +2865,13 @@ namespace OpenSim.Region.Framework.Scenes
2845 /// <param name="aCircuit"></param> 2865 /// <param name="aCircuit"></param>
2846 private void CacheUserName(ScenePresence sp, AgentCircuitData aCircuit) 2866 private void CacheUserName(ScenePresence sp, AgentCircuitData aCircuit)
2847 { 2867 {
2848 IUserManagement uMan = RequestModuleInterface<IUserManagement>(); 2868 if (UserManagementModule != null)
2849 if (uMan != null)
2850 { 2869 {
2851 string first = aCircuit.firstname, last = aCircuit.lastname; 2870 string first = aCircuit.firstname, last = aCircuit.lastname;
2852 2871
2853 if (sp.PresenceType == PresenceType.Npc) 2872 if (sp.PresenceType == PresenceType.Npc)
2854 { 2873 {
2855 uMan.AddUser(aCircuit.AgentID, first, last); 2874 UserManagementModule.AddUser(aCircuit.AgentID, first, last);
2856 } 2875 }
2857 else 2876 else
2858 { 2877 {
@@ -2871,7 +2890,7 @@ namespace OpenSim.Region.Framework.Scenes
2871 } 2890 }
2872 } 2891 }
2873 2892
2874 uMan.AddUser(aCircuit.AgentID, first, last, homeURL); 2893 UserManagementModule.AddUser(aCircuit.AgentID, first, last, homeURL);
2875 } 2894 }
2876 } 2895 }
2877 } 2896 }
@@ -3209,8 +3228,10 @@ namespace OpenSim.Region.Framework.Scenes
3209 /// <param name="client">The IClientAPI for the client</param> 3228 /// <param name="client">The IClientAPI for the client</param>
3210 public virtual bool TeleportClientHome(UUID agentId, IClientAPI client) 3229 public virtual bool TeleportClientHome(UUID agentId, IClientAPI client)
3211 { 3230 {
3212 if (m_teleportModule != null) 3231 if (EntityTransferModule != null)
3213 return m_teleportModule.TeleportHome(agentId, client); 3232 {
3233 EntityTransferModule.TeleportHome(agentId, client);
3234 }
3214 else 3235 else
3215 { 3236 {
3216 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); 3237 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active");
@@ -3372,65 +3393,82 @@ namespace OpenSim.Region.Framework.Scenes
3372// CheckHeartbeat(); 3393// CheckHeartbeat();
3373 bool isChildAgent = false; 3394 bool isChildAgent = false;
3374 ScenePresence avatar = GetScenePresence(agentID); 3395 ScenePresence avatar = GetScenePresence(agentID);
3375 if (avatar != null) 3396
3397 if (avatar == null)
3398 {
3399 m_log.WarnFormat(
3400 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID);
3401
3402 return;
3403 }
3404
3405 try
3376 { 3406 {
3377 isChildAgent = avatar.IsChildAgent; 3407 isChildAgent = avatar.IsChildAgent;
3378 3408
3379 if (avatar.ParentID != 0) 3409 m_log.DebugFormat(
3410 "[SCENE]: Removing {0} agent {1} {2} from {3}",
3411 (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName);
3412
3413 // Don't do this to root agents, it's not nice for the viewer
3414 if (closeChildAgents && isChildAgent)
3380 { 3415 {
3381 avatar.StandUp(); 3416 // Tell a single agent to disconnect from the region.
3417 IEventQueue eq = RequestModuleInterface<IEventQueue>();
3418 if (eq != null)
3419 {
3420 eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID);
3421 }
3422 else
3423 {
3424 avatar.ControllingClient.SendShutdownConnectionNotice();
3425 }
3382 } 3426 }
3383 3427
3384 try 3428 // Only applies to root agents.
3429 if (avatar.ParentID != 0)
3385 { 3430 {
3386 m_log.DebugFormat( 3431 avatar.StandUp();
3387 "[SCENE]: Removing {0} agent {1} from region {2}", 3432 }
3388 (isChildAgent ? "child" : "root"), agentID, RegionInfo.RegionName);
3389 3433
3390 m_sceneGraph.removeUserCount(!isChildAgent); 3434 m_sceneGraph.removeUserCount(!isChildAgent);
3391 3435
3392 // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop 3436 // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop
3393 // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI 3437 // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI
3394 if (closeChildAgents && CapsModule != null) 3438 if (closeChildAgents && CapsModule != null)
3395 CapsModule.RemoveCaps(agentID); 3439 CapsModule.RemoveCaps(agentID);
3396 3440
3397 // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever 3441 // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever
3398 // this method is doing is HORRIBLE!!! 3442 // this method is doing is HORRIBLE!!!
3399 avatar.Scene.NeedSceneCacheClear(avatar.UUID); 3443 avatar.Scene.NeedSceneCacheClear(avatar.UUID);
3400 3444
3401 if (closeChildAgents && !avatar.IsChildAgent) 3445 if (closeChildAgents && !isChildAgent)
3402 {
3403 List<ulong> regions = avatar.KnownRegionHandles;
3404 regions.Remove(RegionInfo.RegionHandle);
3405 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3406 }
3407 m_log.Debug("[Scene] Beginning ClientClosed");
3408 m_eventManager.TriggerClientClosed(agentID, this);
3409 m_log.Debug("[Scene] Finished ClientClosed");
3410 }
3411 catch (NullReferenceException)
3412 { 3446 {
3413 // We don't know which count to remove it from 3447 List<ulong> regions = avatar.KnownRegionHandles;
3414 // Avatar is already disposed :/ 3448 regions.Remove(RegionInfo.RegionHandle);
3449 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3415 } 3450 }
3416 3451
3417 try 3452 m_eventManager.TriggerClientClosed(agentID, this);
3453 m_eventManager.TriggerOnRemovePresence(agentID);
3454
3455 if (!isChildAgent)
3418 { 3456 {
3419 m_eventManager.TriggerOnRemovePresence(agentID); 3457 if (AttachmentsModule != null)
3420
3421 if (AttachmentsModule != null && !isChildAgent && avatar.PresenceType != PresenceType.Npc)
3422 { 3458 {
3423 IUserManagement uMan = RequestModuleInterface<IUserManagement>();
3424 // Don't save attachments for HG visitors, it 3459 // Don't save attachments for HG visitors, it
3425 // messes up their inventory. When a HG visitor logs 3460 // messes up their inventory. When a HG visitor logs
3426 // out on a foreign grid, their attachments will be 3461 // out on a foreign grid, their attachments will be
3427 // reloaded in the state they were in when they left 3462 // reloaded in the state they were in when they left
3428 // the home grid. This is best anyway as the visited 3463 // the home grid. This is best anyway as the visited
3429 // grid may use an incompatible script engine. 3464 // grid may use an incompatible script engine.
3430 if (uMan == null || uMan.IsLocalGridUser(avatar.UUID)) 3465 bool saveChanged
3431 AttachmentsModule.SaveChangedAttachments(avatar, false); 3466 = avatar.PresenceType != PresenceType.Npc
3467 && (UserManagementModule == null || UserManagementModule.IsLocalGridUser(avatar.UUID));
3468
3469 AttachmentsModule.DeRezAttachments(avatar, saveChanged, false);
3432 } 3470 }
3433 3471
3434 ForEachClient( 3472 ForEachClient(
3435 delegate(IClientAPI client) 3473 delegate(IClientAPI client)
3436 { 3474 {
@@ -3438,43 +3476,35 @@ namespace OpenSim.Region.Framework.Scenes
3438 try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); } 3476 try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); }
3439 catch (NullReferenceException) { } 3477 catch (NullReferenceException) { }
3440 }); 3478 });
3441
3442 IAgentAssetTransactions agentTransactions = this.RequestModuleInterface<IAgentAssetTransactions>();
3443 if (agentTransactions != null)
3444 {
3445 agentTransactions.RemoveAgentAssetTransactions(agentID);
3446 }
3447 }
3448 finally
3449 {
3450 // Always clean these structures up so that any failure above doesn't cause them to remain in the
3451 // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering
3452 // the same cleanup exception continually.
3453 // TODO: This should probably extend to the whole method, but we don't want to also catch the NRE
3454 // since this would hide the underlying failure and other associated problems.
3455 m_sceneGraph.RemoveScenePresence(agentID);
3456 m_clientManager.Remove(agentID);
3457 } 3479 }
3458 3480
3459 try 3481 // It's possible for child agents to have transactions if changes are being made cross-border.
3460 { 3482 if (AgentTransactionsModule != null)
3461 avatar.Close(); 3483 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID);
3462 } 3484
3463 catch (NullReferenceException) 3485 avatar.Close();
3464 { 3486
3465 //We can safely ignore null reference exceptions. It means the avatar are dead and cleaned up anyway.
3466 }
3467 catch (Exception e)
3468 {
3469 m_log.ErrorFormat("[SCENE] Scene.cs:RemoveClient exception {0}{1}", e.Message, e.StackTrace);
3470 }
3471 m_log.Debug("[Scene] Done. Firing RemoveCircuit");
3472 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3487 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3473// CleanDroppedAttachments();
3474 m_log.Debug("[Scene] The avatar has left the building"); 3488 m_log.Debug("[Scene] The avatar has left the building");
3475 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
3476 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
3477 } 3489 }
3490 catch (Exception e)
3491 {
3492 m_log.Error(
3493 string.Format("[SCENE]: Exception removing {0} from {1}, ", avatar.Name, RegionInfo.RegionName), e);
3494 }
3495 finally
3496 {
3497 // Always clean these structures up so that any failure above doesn't cause them to remain in the
3498 // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering
3499 // the same cleanup exception continually.
3500 // TODO: This should probably extend to the whole method, but we don't want to also catch the NRE
3501 // since this would hide the underlying failure and other associated problems.
3502 m_sceneGraph.RemoveScenePresence(agentID);
3503 m_clientManager.Remove(agentID);
3504 }
3505
3506 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
3507 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
3478 } 3508 }
3479 3509
3480 /// <summary> 3510 /// <summary>
@@ -3556,7 +3586,7 @@ namespace OpenSim.Region.Framework.Scenes
3556 public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, out string reason, bool requirePresenceLookup) 3586 public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, out string reason, bool requirePresenceLookup)
3557 { 3587 {
3558 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 || 3588 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 ||
3559 (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0); 3589 (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0);
3560 bool viahome = ((teleportFlags & (uint)TPFlags.ViaHome) != 0); 3590 bool viahome = ((teleportFlags & (uint)TPFlags.ViaHome) != 0);
3561 bool godlike = ((teleportFlags & (uint)TPFlags.Godlike) != 0); 3591 bool godlike = ((teleportFlags & (uint)TPFlags.Godlike) != 0);
3562 3592
@@ -3572,8 +3602,17 @@ namespace OpenSim.Region.Framework.Scenes
3572 // Don't disable this log message - it's too helpful 3602 // Don't disable this log message - it's too helpful
3573 m_log.DebugFormat( 3603 m_log.DebugFormat(
3574 "[SCENE]: Region {0} told of incoming {1} agent {2} {3} {4} (circuit code {5}, IP {6}, viewer {7}, teleportflags ({8}), position {9})", 3604 "[SCENE]: Region {0} told of incoming {1} agent {2} {3} {4} (circuit code {5}, IP {6}, viewer {7}, teleportflags ({8}), position {9})",
3575 RegionInfo.RegionName, (agent.child ? "child" : "root"),agent.firstname, agent.lastname, 3605 RegionInfo.RegionName,
3576 agent.AgentID, agent.circuitcode, agent.IPAddress, agent.Viewer, ((TPFlags)teleportFlags).ToString(), agent.startpos); 3606 (agent.child ? "child" : "root"),
3607 agent.firstname,
3608 agent.lastname,
3609 agent.AgentID,
3610 agent.circuitcode,
3611 agent.IPAddress,
3612 agent.Viewer,
3613 ((TPFlags)teleportFlags).ToString(),
3614 agent.startpos
3615 );
3577 3616
3578 if (LoginsDisabled) 3617 if (LoginsDisabled)
3579 { 3618 {
@@ -3581,6 +3620,50 @@ namespace OpenSim.Region.Framework.Scenes
3581 return false; 3620 return false;
3582 } 3621 }
3583 3622
3623 //Check if the viewer is banned or in the viewer access list
3624 //We check if the substring is listed for higher flexebility
3625 bool ViewerDenied = true;
3626
3627 //Check if the specific viewer is listed in the allowed viewer list
3628 if (m_AllowedViewers.Count > 0)
3629 {
3630 foreach (string viewer in m_AllowedViewers)
3631 {
3632 if (viewer == agent.Viewer.Substring(0, viewer.Length).Trim().ToLower())
3633 {
3634 ViewerDenied = false;
3635 break;
3636 }
3637 }
3638 }
3639 else
3640 {
3641 ViewerDenied = false;
3642 }
3643
3644 //Check if the viewer is in the banned list
3645 if (m_BannedViewers.Count > 0)
3646 {
3647 foreach (string viewer in m_BannedViewers)
3648 {
3649 if (viewer == agent.Viewer.Substring(0, viewer.Length).Trim().ToLower())
3650 {
3651 ViewerDenied = true;
3652 break;
3653 }
3654 }
3655 }
3656
3657 if (ViewerDenied)
3658 {
3659 m_log.DebugFormat(
3660 "[SCENE]: Access denied for {0} {1} using {2}",
3661 agent.firstname, agent.lastname, agent.Viewer);
3662 reason = "Access denied, your viewer is banned by the region owner";
3663 return false;
3664 }
3665
3666
3584 ScenePresence sp = GetScenePresence(agent.AgentID); 3667 ScenePresence sp = GetScenePresence(agent.AgentID);
3585 3668
3586 if (sp != null && !sp.IsChildAgent) 3669 if (sp != null && !sp.IsChildAgent)
@@ -3588,7 +3671,10 @@ namespace OpenSim.Region.Framework.Scenes
3588 // We have a zombie from a crashed session. 3671 // We have a zombie from a crashed session.
3589 // Or the same user is trying to be root twice here, won't work. 3672 // Or the same user is trying to be root twice here, won't work.
3590 // Kill it. 3673 // Kill it.
3591 m_log.DebugFormat("[SCENE]: Zombie scene presence detected for {0} in {1}", agent.AgentID, RegionInfo.RegionName); 3674 m_log.DebugFormat(
3675 "[SCENE]: Zombie scene presence detected for {0} {1} in {2}",
3676 sp.Name, sp.UUID, RegionInfo.RegionName);
3677
3592 sp.ControllingClient.Close(); 3678 sp.ControllingClient.Close();
3593 sp = null; 3679 sp = null;
3594 } 3680 }
@@ -3615,8 +3701,7 @@ namespace OpenSim.Region.Framework.Scenes
3615 { 3701 {
3616 if (!VerifyUserPresence(agent, out reason)) 3702 if (!VerifyUserPresence(agent, out reason))
3617 return false; 3703 return false;
3618 } 3704 } catch (Exception e)
3619 catch (Exception e)
3620 { 3705 {
3621 m_log.ErrorFormat( 3706 m_log.ErrorFormat(
3622 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); 3707 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace);
@@ -3651,8 +3736,7 @@ namespace OpenSim.Region.Framework.Scenes
3651 CapsModule.SetAgentCapsSeeds(agent); 3736 CapsModule.SetAgentCapsSeeds(agent);
3652 CapsModule.CreateCaps(agent.AgentID); 3737 CapsModule.CreateCaps(agent.AgentID);
3653 } 3738 }
3654 } 3739 } else
3655 else
3656 { 3740 {
3657 // Let the SP know how we got here. This has a lot of interesting 3741 // Let the SP know how we got here. This has a lot of interesting
3658 // uses down the line. 3742 // uses down the line.
@@ -3675,7 +3759,7 @@ namespace OpenSim.Region.Framework.Scenes
3675 agent.teleportFlags = teleportFlags; 3759 agent.teleportFlags = teleportFlags;
3676 m_authenticateHandler.AddNewCircuit(agent.circuitcode, agent); 3760 m_authenticateHandler.AddNewCircuit(agent.circuitcode, agent);
3677 3761
3678 if (vialogin) 3762 if (vialogin)
3679 { 3763 {
3680// CleanDroppedAttachments(); 3764// CleanDroppedAttachments();
3681 3765
@@ -3716,8 +3800,7 @@ namespace OpenSim.Region.Framework.Scenes
3716 agent.startpos.Z = 720; 3800 agent.startpos.Z = 720;
3717 } 3801 }
3718 } 3802 }
3719 } 3803 } else
3720 else
3721 { 3804 {
3722 if (agent.startpos.X > EastBorders[0].BorderLine.Z) 3805 if (agent.startpos.X > EastBorders[0].BorderLine.Z)
3723 { 3806 {
@@ -3743,10 +3826,19 @@ namespace OpenSim.Region.Framework.Scenes
3743 SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject); 3826 SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject);
3744 // Can have multiple SpawnPoints 3827 // Can have multiple SpawnPoints
3745 List<SpawnPoint> spawnpoints = RegionInfo.RegionSettings.SpawnPoints(); 3828 List<SpawnPoint> spawnpoints = RegionInfo.RegionSettings.SpawnPoints();
3746 if ( spawnpoints.Count > 1) 3829 if (spawnpoints.Count > 1)
3747 { 3830 {
3748 // We have multiple SpawnPoints, Route the agent to a random one 3831 // We have multiple SpawnPoints, Route the agent to a random or sequential one
3749 agent.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count)].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); 3832 if (SpawnPointRouting == "random")
3833 agent.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation(
3834 telehub.AbsolutePosition,
3835 telehub.GroupRotation
3836 );
3837 else
3838 agent.startpos = spawnpoints[SpawnPoint()].GetLocation(
3839 telehub.AbsolutePosition,
3840 telehub.GroupRotation
3841 );
3750 } 3842 }
3751 else 3843 else
3752 { 3844 {
@@ -3869,9 +3961,9 @@ namespace OpenSim.Region.Framework.Scenes
3869 } 3961 }
3870 } 3962 }
3871 3963
3872 if (m_regInfo.EstateSettings != null) 3964 if (RegionInfo.EstateSettings != null)
3873 { 3965 {
3874 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID,0)) 3966 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, 0))
3875 { 3967 {
3876 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 3968 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
3877 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3969 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
@@ -3903,7 +3995,7 @@ namespace OpenSim.Region.Framework.Scenes
3903 } 3995 }
3904 3996
3905 bool groupAccess = false; 3997 bool groupAccess = false;
3906 UUID[] estateGroups = m_regInfo.EstateSettings.EstateGroups; 3998 UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups;
3907 3999
3908 if (estateGroups != null) 4000 if (estateGroups != null)
3909 { 4001 {
@@ -3921,8 +4013,8 @@ namespace OpenSim.Region.Framework.Scenes
3921 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!"); 4013 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!");
3922 } 4014 }
3923 4015
3924 if (!m_regInfo.EstateSettings.PublicAccess && 4016 if (!RegionInfo.EstateSettings.PublicAccess &&
3925 !m_regInfo.EstateSettings.HasAccess(agent.AgentID) && 4017 !RegionInfo.EstateSettings.HasAccess(agent.AgentID) &&
3926 !groupAccess) 4018 !groupAccess)
3927 { 4019 {
3928 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate", 4020 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate",
@@ -3983,41 +4075,41 @@ namespace OpenSim.Region.Framework.Scenes
3983 return m_authenticateHandler.TryChangeCiruitCode(oldcc, newcc); 4075 return m_authenticateHandler.TryChangeCiruitCode(oldcc, newcc);
3984 } 4076 }
3985 4077
3986 /// <summary> 4078// /// <summary>
3987 /// The Grid has requested that we log-off a user. Log them off. 4079// /// The Grid has requested that we log-off a user. Log them off.
3988 /// </summary> 4080// /// </summary>
3989 /// <param name="AvatarID">Unique ID of the avatar to log-off</param> 4081// /// <param name="AvatarID">Unique ID of the avatar to log-off</param>
3990 /// <param name="RegionSecret">SecureSessionID of the user, or the RegionSecret text when logging on to the grid</param> 4082// /// <param name="RegionSecret">SecureSessionID of the user, or the RegionSecret text when logging on to the grid</param>
3991 /// <param name="message">message to display to the user. Reason for being logged off</param> 4083// /// <param name="message">message to display to the user. Reason for being logged off</param>
3992 public void HandleLogOffUserFromGrid(UUID AvatarID, UUID RegionSecret, string message) 4084// public void HandleLogOffUserFromGrid(UUID AvatarID, UUID RegionSecret, string message)
3993 { 4085// {
3994 ScenePresence loggingOffUser = GetScenePresence(AvatarID); 4086// ScenePresence loggingOffUser = GetScenePresence(AvatarID);
3995 if (loggingOffUser != null) 4087// if (loggingOffUser != null)
3996 { 4088// {
3997 UUID localRegionSecret = UUID.Zero; 4089// UUID localRegionSecret = UUID.Zero;
3998 bool parsedsecret = UUID.TryParse(m_regInfo.regionSecret, out localRegionSecret); 4090// bool parsedsecret = UUID.TryParse(RegionInfo.regionSecret, out localRegionSecret);
3999 4091//
4000 // Region Secret is used here in case a new sessionid overwrites an old one on the user server. 4092// // Region Secret is used here in case a new sessionid overwrites an old one on the user server.
4001 // Will update the user server in a few revisions to use it. 4093// // Will update the user server in a few revisions to use it.
4002 4094//
4003 if (RegionSecret == loggingOffUser.ControllingClient.SecureSessionId || (parsedsecret && RegionSecret == localRegionSecret)) 4095// if (RegionSecret == loggingOffUser.ControllingClient.SecureSessionId || (parsedsecret && RegionSecret == localRegionSecret))
4004 { 4096// {
4005 m_sceneGridService.SendCloseChildAgentConnections(loggingOffUser.UUID, loggingOffUser.KnownRegionHandles); 4097// m_sceneGridService.SendCloseChildAgentConnections(loggingOffUser.UUID, loggingOffUser.KnownRegionHandles);
4006 loggingOffUser.ControllingClient.Kick(message); 4098// loggingOffUser.ControllingClient.Kick(message);
4007 // Give them a second to receive the message! 4099// // Give them a second to receive the message!
4008 Thread.Sleep(1000); 4100// Thread.Sleep(1000);
4009 loggingOffUser.ControllingClient.Close(); 4101// loggingOffUser.ControllingClient.Close();
4010 } 4102// }
4011 else 4103// else
4012 { 4104// {
4013 m_log.Info("[USERLOGOFF]: System sending the LogOff user message failed to sucessfully authenticate"); 4105// m_log.Info("[USERLOGOFF]: System sending the LogOff user message failed to sucessfully authenticate");
4014 } 4106// }
4015 } 4107// }
4016 else 4108// else
4017 { 4109// {
4018 m_log.InfoFormat("[USERLOGOFF]: Got a logoff request for {0} but the user isn't here. The user might already have been logged out", AvatarID.ToString()); 4110// m_log.InfoFormat("[USERLOGOFF]: Got a logoff request for {0} but the user isn't here. The user might already have been logged out", AvatarID.ToString());
4019 } 4111// }
4020 } 4112// }
4021 4113
4022 /// <summary> 4114 /// <summary>
4023 /// Triggered when an agent crosses into this sim. Also happens on initial login. 4115 /// Triggered when an agent crosses into this sim. Also happens on initial login.
@@ -4070,21 +4162,19 @@ namespace OpenSim.Region.Framework.Scenes
4070 return false; 4162 return false;
4071 } 4163 }
4072 4164
4165 // TODO: This check should probably be in QueryAccess().
4073 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 4166 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
4074 if (nearestParcel == null) 4167 if (nearestParcel == null)
4075 { 4168 {
4076 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: no allowed parcel", cAgentData.AgentID); 4169 m_log.DebugFormat(
4077 return false; 4170 "[SCENE]: Denying root agent entry to {0} in {1}: no allowed parcel",
4078 } 4171 cAgentData.AgentID, RegionInfo.RegionName);
4079
4080 int num = m_sceneGraph.GetNumberOfScenePresences();
4081 4172
4082 if (num >= RegionInfo.RegionSettings.AgentLimit) 4173 return false;
4083 {
4084 if (!Permissions.IsAdministrator(cAgentData.AgentID))
4085 return false;
4086 } 4174 }
4087 4175
4176 // We have to wait until the viewer contacts this region after receiving EAC.
4177 // That calls AddNewClient, which finally creates the ScenePresence
4088 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); 4178 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID);
4089 4179
4090 if (childAgentUpdate != null) 4180 if (childAgentUpdate != null)
@@ -4128,14 +4218,28 @@ namespace OpenSim.Region.Framework.Scenes
4128 return false; 4218 return false;
4129 } 4219 }
4130 4220
4221 /// <summary>
4222 /// Poll until the requested ScenePresence appears or we timeout.
4223 /// </summary>
4224 /// <returns>The scene presence is found, else null.</returns>
4225 /// <param name='agentID'></param>
4131 protected virtual ScenePresence WaitGetScenePresence(UUID agentID) 4226 protected virtual ScenePresence WaitGetScenePresence(UUID agentID)
4132 { 4227 {
4133 int ntimes = 10; 4228 int ntimes = 10;
4134 ScenePresence childAgentUpdate = null; 4229 ScenePresence sp = null;
4135 while ((childAgentUpdate = GetScenePresence(agentID)) == null && (ntimes-- > 0)) 4230 while ((sp = GetScenePresence(agentID)) == null && (ntimes-- > 0))
4136 Thread.Sleep(1000); 4231 Thread.Sleep(1000);
4137 return childAgentUpdate;
4138 4232
4233 if (sp == null)
4234 m_log.WarnFormat(
4235 "[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout",
4236 agentID, RegionInfo.RegionName);
4237// else
4238// m_log.DebugFormat(
4239// "[SCENE PRESENCE]: Found presence {0} {1} {2} in {3} after {4} waits",
4240// sp.Name, sp.UUID, sp.IsChildAgent ? "child" : "root", RegionInfo.RegionName, 10 - ntimes);
4241
4242 return sp;
4139 } 4243 }
4140 4244
4141 public virtual bool IncomingRetrieveRootAgent(UUID id, out IAgentData agent) 4245 public virtual bool IncomingRetrieveRootAgent(UUID id, out IAgentData agent)
@@ -4173,33 +4277,7 @@ namespace OpenSim.Region.Framework.Scenes
4173 ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); 4277 ScenePresence presence = m_sceneGraph.GetScenePresence(agentID);
4174 if (presence != null) 4278 if (presence != null)
4175 { 4279 {
4176 // Nothing is removed here, so down count it as such 4280 presence.ControllingClient.Close();
4177 if (presence.IsChildAgent)
4178 {
4179 m_sceneGraph.removeUserCount(false);
4180 }
4181 else if (!childOnly)
4182 {
4183 m_sceneGraph.removeUserCount(true);
4184 }
4185
4186 // Don't do this to root agents on logout, it's not nice for the viewer
4187 if (presence.IsChildAgent)
4188 {
4189 // Tell a single agent to disconnect from the region.
4190 IEventQueue eq = RequestModuleInterface<IEventQueue>();
4191 if (eq != null)
4192 {
4193 eq.DisableSimulator(RegionInfo.RegionHandle, agentID);
4194 }
4195 else
4196 presence.ControllingClient.SendShutdownConnectionNotice();
4197 presence.ControllingClient.Close(false);
4198 }
4199 else if (!childOnly)
4200 {
4201 presence.ControllingClient.Close(true);
4202 }
4203 return true; 4281 return true;
4204 } 4282 }
4205 4283
@@ -4247,13 +4325,13 @@ namespace OpenSim.Region.Framework.Scenes
4247 ScenePresence sp = GetScenePresence(remoteClient.AgentId); 4325 ScenePresence sp = GetScenePresence(remoteClient.AgentId);
4248 if (sp != null) 4326 if (sp != null)
4249 { 4327 {
4250 uint regionX = m_regInfo.RegionLocX; 4328 uint regionX = RegionInfo.RegionLocX;
4251 uint regionY = m_regInfo.RegionLocY; 4329 uint regionY = RegionInfo.RegionLocY;
4252 4330
4253 Utils.LongToUInts(regionHandle, out regionX, out regionY); 4331 Utils.LongToUInts(regionHandle, out regionX, out regionY);
4254 4332
4255 int shiftx = (int) regionX - (int) m_regInfo.RegionLocX * (int)Constants.RegionSize; 4333 int shiftx = (int) regionX - (int) RegionInfo.RegionLocX * (int)Constants.RegionSize;
4256 int shifty = (int) regionY - (int) m_regInfo.RegionLocY * (int)Constants.RegionSize; 4334 int shifty = (int) regionY - (int) RegionInfo.RegionLocY * (int)Constants.RegionSize;
4257 4335
4258 position.X += shiftx; 4336 position.X += shiftx;
4259 position.Y += shifty; 4337 position.Y += shifty;
@@ -4276,7 +4354,7 @@ namespace OpenSim.Region.Framework.Scenes
4276 4354
4277 if (!result) 4355 if (!result)
4278 { 4356 {
4279 regionHandle = m_regInfo.RegionHandle; 4357 regionHandle = RegionInfo.RegionHandle;
4280 } 4358 }
4281 else 4359 else
4282 { 4360 {
@@ -4285,8 +4363,10 @@ namespace OpenSim.Region.Framework.Scenes
4285 position.Y -= shifty; 4363 position.Y -= shifty;
4286 } 4364 }
4287 4365
4288 if (m_teleportModule != null) 4366 if (EntityTransferModule != null)
4289 m_teleportModule.Teleport(sp, regionHandle, position, lookAt, teleportFlags); 4367 {
4368 EntityTransferModule.Teleport(sp, regionHandle, position, lookAt, teleportFlags);
4369 }
4290 else 4370 else
4291 { 4371 {
4292 m_log.DebugFormat("[SCENE]: Unable to perform teleports: no AgentTransferModule is active"); 4372 m_log.DebugFormat("[SCENE]: Unable to perform teleports: no AgentTransferModule is active");
@@ -4297,8 +4377,10 @@ namespace OpenSim.Region.Framework.Scenes
4297 4377
4298 public bool CrossAgentToNewRegion(ScenePresence agent, bool isFlying) 4378 public bool CrossAgentToNewRegion(ScenePresence agent, bool isFlying)
4299 { 4379 {
4300 if (m_teleportModule != null) 4380 if (EntityTransferModule != null)
4301 return m_teleportModule.Cross(agent, isFlying); 4381 {
4382 return EntityTransferModule.Cross(agent, isFlying);
4383 }
4302 else 4384 else
4303 { 4385 {
4304 m_log.DebugFormat("[SCENE]: Unable to cross agent to neighbouring region, because there is no AgentTransferModule"); 4386 m_log.DebugFormat("[SCENE]: Unable to cross agent to neighbouring region, because there is no AgentTransferModule");
@@ -4600,6 +4682,17 @@ namespace OpenSim.Region.Framework.Scenes
4600 } 4682 }
4601 4683
4602 /// <summary> 4684 /// <summary>
4685 /// Get all the scene object groups.
4686 /// </summary>
4687 /// <returns>
4688 /// The scene object groups. If the scene is empty then an empty list is returned.
4689 /// </returns>
4690 public List<SceneObjectGroup> GetSceneObjectGroups()
4691 {
4692 return m_sceneGraph.GetSceneObjectGroups();
4693 }
4694
4695 /// <summary>
4603 /// Get a group via its UUID 4696 /// Get a group via its UUID
4604 /// </summary> 4697 /// </summary>
4605 /// <param name="fullID"></param> 4698 /// <param name="fullID"></param>
@@ -4778,7 +4871,7 @@ namespace OpenSim.Region.Framework.Scenes
4778 4871
4779 public void DeleteFromStorage(UUID uuid) 4872 public void DeleteFromStorage(UUID uuid)
4780 { 4873 {
4781 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID); 4874 SimulationDataService.RemoveObject(uuid, RegionInfo.RegionID);
4782 } 4875 }
4783 4876
4784 public int GetHealth(out int flags, out string message) 4877 public int GetHealth(out int flags, out string message)
@@ -5259,7 +5352,7 @@ Environment.Exit(1);
5259 IEstateDataService estateDataService = EstateDataService; 5352 IEstateDataService estateDataService = EstateDataService;
5260 if (estateDataService != null) 5353 if (estateDataService != null)
5261 { 5354 {
5262 m_regInfo.EstateSettings = estateDataService.LoadEstateSettings(m_regInfo.RegionID, false); 5355 RegionInfo.EstateSettings = estateDataService.LoadEstateSettings(RegionInfo.RegionID, false);
5263 TriggerEstateSunUpdate(); 5356 TriggerEstateSunUpdate();
5264 } 5357 }
5265 } 5358 }
@@ -5446,29 +5539,58 @@ Environment.Exit(1);
5446 throw new Exception(error); 5539 throw new Exception(error);
5447 } 5540 }
5448 5541
5449 // This method is called across the simulation connector to 5542 /// <summary>
5450 // determine if a given agent is allowed in this region 5543 /// This method is called across the simulation connector to
5451 // AS A ROOT AGENT. Returning false here will prevent them 5544 /// determine if a given agent is allowed in this region
5452 // from logging into the region, teleporting into the region 5545 /// AS A ROOT AGENT
5453 // or corssing the broder walking, but will NOT prevent 5546 /// </summary>
5454 // child agent creation, thereby emulating the SL behavior. 5547 /// <remarks>
5548 /// Returning false here will prevent them
5549 /// from logging into the region, teleporting into the region
5550 /// or corssing the broder walking, but will NOT prevent
5551 /// child agent creation, thereby emulating the SL behavior.
5552 /// </remarks>
5553 /// <param name='agentID'></param>
5554 /// <param name='position'></param>
5555 /// <param name='reason'></param>
5556 /// <returns></returns>
5455 public bool QueryAccess(UUID agentID, Vector3 position, out string reason) 5557 public bool QueryAccess(UUID agentID, Vector3 position, out string reason)
5456 { 5558 {
5457 reason = "You are banned from the region"; 5559 reason = "You are banned from the region";
5458 5560
5561 if (EntityTransferModule.IsInTransit(agentID))
5562 {
5563 reason = "Agent is still in transit from this region";
5564
5565 m_log.WarnFormat(
5566 "[SCENE]: Denying agent {0} entry into {1} since region still has them registered as in transit",
5567 agentID, RegionInfo.RegionName);
5568
5569 return false;
5570 }
5571
5459 if (Permissions.IsGod(agentID)) 5572 if (Permissions.IsGod(agentID))
5460 { 5573 {
5461 reason = String.Empty; 5574 reason = String.Empty;
5462 return true; 5575 return true;
5463 } 5576 }
5464 5577
5465 int num = m_sceneGraph.GetNumberOfScenePresences(); 5578 // FIXME: Root agent count is currently known to be inaccurate. This forces a recount before we check.
5579 // However, the long term fix is to make sure root agent count is always accurate.
5580 m_sceneGraph.RecalculateStats();
5581
5582 int num = m_sceneGraph.GetRootAgentCount();
5466 5583
5467 if (num >= RegionInfo.RegionSettings.AgentLimit) 5584 if (num >= RegionInfo.RegionSettings.AgentLimit)
5468 { 5585 {
5469 if (!Permissions.IsAdministrator(agentID)) 5586 if (!Permissions.IsAdministrator(agentID))
5470 { 5587 {
5471 reason = "The region is full"; 5588 reason = "The region is full";
5589
5590 m_log.DebugFormat(
5591 "[SCENE]: Denying presence with id {0} entry into {1} since region is at agent limit of {2}",
5592 agentID, RegionInfo.RegionName, RegionInfo.RegionSettings.AgentLimit);
5593
5472 return false; 5594 return false;
5473 } 5595 }
5474 } 5596 }
@@ -5640,6 +5762,20 @@ Environment.Exit(1);
5640 } 5762 }
5641 } 5763 }
5642 5764
5765 // manage and select spawn points in sequence
5766 public int SpawnPoint()
5767 {
5768 int spawnpoints = RegionInfo.RegionSettings.SpawnPoints().Count;
5769
5770 if (spawnpoints == 0)
5771 return 0;
5772
5773 m_SpawnPoint++;
5774 if (m_SpawnPoint > spawnpoints)
5775 m_SpawnPoint = 1;
5776 return m_SpawnPoint - 1;
5777 }
5778
5643 private void HandleGcCollect(string module, string[] args) 5779 private void HandleGcCollect(string module, string[] args)
5644 { 5780 {
5645 GC.Collect(); 5781 GC.Collect();
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index 9b8a3ae..e8134cd 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -51,6 +51,8 @@ namespace OpenSim.Region.Framework.Scenes
51 #endregion 51 #endregion
52 52
53 #region Fields 53 #region Fields
54
55 public string Name { get { return RegionInfo.RegionName; } }
54 56
55 public IConfigSource Config 57 public IConfigSource Config
56 { 58 {
@@ -148,6 +150,11 @@ namespace OpenSim.Region.Framework.Scenes
148 150
149 #endregion 151 #endregion
150 152
153 public SceneBase(RegionInfo regInfo)
154 {
155 RegionInfo = regInfo;
156 }
157
151 #region Update Methods 158 #region Update Methods
152 159
153 /// <summary> 160 /// <summary>
@@ -211,10 +218,7 @@ namespace OpenSim.Region.Framework.Scenes
211 /// 218 ///
212 /// </summary> 219 /// </summary>
213 /// <returns></returns> 220 /// <returns></returns>
214 public virtual RegionInfo RegionInfo 221 public virtual RegionInfo RegionInfo { get; private set; }
215 {
216 get { return m_regInfo; }
217 }
218 222
219 #region admin stuff 223 #region admin stuff
220 224
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index b806d91..5d8447b 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -84,16 +84,23 @@ namespace OpenSim.Region.Framework.Scenes
84 if (neighbourService != null) 84 if (neighbourService != null)
85 neighbour = neighbourService.HelloNeighbour(regionhandle, region); 85 neighbour = neighbourService.HelloNeighbour(regionhandle, region);
86 else 86 else
87 m_log.DebugFormat("[SCS]: No neighbour service provided for informing neigbhours of this region"); 87 m_log.DebugFormat(
88 "[SCENE COMMUNICATION SERVICE]: No neighbour service provided for region {0} to inform neigbhours of status",
89 m_scene.Name);
88 90
89 if (neighbour != null) 91 if (neighbour != null)
90 { 92 {
91 // m_log.DebugFormat("[INTERGRID]: Successfully informed neighbour {0}-{1} that I'm here", x / Constants.RegionSize, y / Constants.RegionSize); 93 m_log.DebugFormat(
94 "[SCENE COMMUNICATION SERVICE]: Region {0} successfully informed neighbour {1} at {2}-{3} that it is up",
95 m_scene.Name, neighbour.RegionName, x / Constants.RegionSize, y / Constants.RegionSize);
96
92 m_scene.EventManager.TriggerOnRegionUp(neighbour); 97 m_scene.EventManager.TriggerOnRegionUp(neighbour);
93 } 98 }
94 else 99 else
95 { 100 {
96 m_log.InfoFormat("[INTERGRID]: Failed to inform neighbour {0}-{1} that I'm here.", x / Constants.RegionSize, y / Constants.RegionSize); 101 m_log.WarnFormat(
102 "[SCENE COMMUNICATION SERVICE]: Region {0} failed to inform neighbour at {1}-{2} that it is up.",
103 x / Constants.RegionSize, y / Constants.RegionSize);
97 } 104 }
98 } 105 }
99 106
@@ -101,8 +108,13 @@ namespace OpenSim.Region.Framework.Scenes
101 { 108 {
102 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName); 109 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName);
103 110
104 List<GridRegion> neighbours = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID); 111 List<GridRegion> neighbours
105 //m_log.DebugFormat("[INTERGRID]: Informing {0} neighbours that this region is up", neighbours.Count); 112 = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID);
113
114 m_log.DebugFormat(
115 "[SCENE COMMUNICATION SERVICE]: Informing {0} neighbours that region {1} is up",
116 neighbours.Count, m_scene.Name);
117
106 foreach (GridRegion n in neighbours) 118 foreach (GridRegion n in neighbours)
107 { 119 {
108 InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync; 120 InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync;
@@ -156,7 +168,9 @@ namespace OpenSim.Region.Framework.Scenes
156 // that the region position is cached or performance will degrade 168 // that the region position is cached or performance will degrade
157 Utils.LongToUInts(regionHandle, out x, out y); 169 Utils.LongToUInts(regionHandle, out x, out y);
158 GridRegion dest = m_scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y); 170 GridRegion dest = m_scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y);
159// bool v = true; 171 if (dest == null)
172 continue;
173
160 if (!simulatorList.Contains(dest.ServerURI)) 174 if (!simulatorList.Contains(dest.ServerURI))
161 { 175 {
162 // we havent seen this simulator before, add it to the list 176 // we havent seen this simulator before, add it to the list
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 0587846..c3d66eb 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -101,6 +101,13 @@ namespace OpenSim.Region.Framework.Scenes
101 /// </summary> 101 /// </summary>
102 protected internal Dictionary<uint, SceneObjectGroup> SceneObjectGroupsByLocalPartID = new Dictionary<uint, SceneObjectGroup>(); 102 protected internal Dictionary<uint, SceneObjectGroup> SceneObjectGroupsByLocalPartID = new Dictionary<uint, SceneObjectGroup>();
103 103
104 /// <summary>
105 /// Lock to prevent object group update, linking, delinking and duplication operations from running concurrently.
106 /// </summary>
107 /// <remarks>
108 /// These operations rely on the parts composition of the object. If allowed to run concurrently then race
109 /// conditions can occur.
110 /// </remarks>
104 private Object m_updateLock = new Object(); 111 private Object m_updateLock = new Object();
105 112
106 #endregion 113 #endregion
@@ -394,9 +401,9 @@ namespace OpenSim.Region.Framework.Scenes
394 401
395 if (Entities.ContainsKey(sceneObject.UUID)) 402 if (Entities.ContainsKey(sceneObject.UUID))
396 { 403 {
397// m_log.DebugFormat( 404 m_log.DebugFormat(
398// "[SCENEGRAPH]: Scene graph for {0} already contains object {1} in AddSceneObject()", 405 "[SCENEGRAPH]: Scene graph for {0} already contains object {1} in AddSceneObject()",
399// m_parentScene.RegionInfo.RegionName, sceneObject.UUID); 406 m_parentScene.RegionInfo.RegionName, sceneObject.UUID);
400 407
401 return false; 408 return false;
402 } 409 }
@@ -775,12 +782,6 @@ namespace OpenSim.Region.Framework.Scenes
775 782
776 public int GetChildAgentCount() 783 public int GetChildAgentCount()
777 { 784 {
778 // some network situations come in where child agents get closed twice.
779 if (m_numChildAgents < 0)
780 {
781 m_numChildAgents = 0;
782 }
783
784 return m_numChildAgents; 785 return m_numChildAgents;
785 } 786 }
786 787
@@ -852,11 +853,6 @@ namespace OpenSim.Region.Framework.Scenes
852 return m_scenePresenceArray; 853 return m_scenePresenceArray;
853 } 854 }
854 855
855 public int GetNumberOfScenePresences()
856 {
857 return m_scenePresenceArray.Count;
858 }
859
860 /// <summary> 856 /// <summary>
861 /// Request a scene presence by UUID. Fast, indexed lookup. 857 /// Request a scene presence by UUID. Fast, indexed lookup.
862 /// </summary> 858 /// </summary>
@@ -1042,6 +1038,18 @@ namespace OpenSim.Region.Framework.Scenes
1042 } 1038 }
1043 1039
1044 /// <summary> 1040 /// <summary>
1041 /// Get all the scene object groups.
1042 /// </summary>
1043 /// <returns>
1044 /// The scene object groups. If the scene is empty then an empty list is returned.
1045 /// </returns>
1046 protected internal List<SceneObjectGroup> GetSceneObjectGroups()
1047 {
1048 lock (SceneObjectGroupsByFullID)
1049 return new List<SceneObjectGroup>(SceneObjectGroupsByFullID.Values);
1050 }
1051
1052 /// <summary>
1045 /// Get a group in the scene 1053 /// Get a group in the scene
1046 /// </summary> 1054 /// </summary>
1047 /// <param name="fullID">UUID of the group</param> 1055 /// <param name="fullID">UUID of the group</param>
@@ -1184,11 +1192,7 @@ namespace OpenSim.Region.Framework.Scenes
1184 /// <param name="action"></param> 1192 /// <param name="action"></param>
1185 protected internal void ForEachSOG(Action<SceneObjectGroup> action) 1193 protected internal void ForEachSOG(Action<SceneObjectGroup> action)
1186 { 1194 {
1187 List<SceneObjectGroup> objlist; 1195 foreach (SceneObjectGroup obj in GetSceneObjectGroups())
1188 lock (SceneObjectGroupsByFullID)
1189 objlist = new List<SceneObjectGroup>(SceneObjectGroupsByFullID.Values);
1190
1191 foreach (SceneObjectGroup obj in objlist)
1192 { 1196 {
1193 try 1197 try
1194 { 1198 {
@@ -2065,12 +2069,14 @@ namespace OpenSim.Region.Framework.Scenes
2065 /// <param name="AgentID"></param> 2069 /// <param name="AgentID"></param>
2066 /// <param name="GroupID"></param> 2070 /// <param name="GroupID"></param>
2067 /// <param name="rot"></param> 2071 /// <param name="rot"></param>
2072 /// <returns>null if duplication fails, otherwise the duplicated object</returns>
2073 /// <summary>
2068 public SceneObjectGroup DuplicateObject(uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot) 2074 public SceneObjectGroup DuplicateObject(uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot)
2069 { 2075 {
2070// m_log.DebugFormat( 2076// m_log.DebugFormat(
2071// "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}", 2077// "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}",
2072// originalPrimID, offset, AgentID); 2078// originalPrimID, offset, AgentID);
2073 2079
2074 SceneObjectGroup original = GetGroupByPrim(originalPrimID); 2080 SceneObjectGroup original = GetGroupByPrim(originalPrimID);
2075 if (original != null) 2081 if (original != null)
2076 { 2082 {
@@ -2100,25 +2106,25 @@ namespace OpenSim.Region.Framework.Scenes
2100 2106
2101 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2107 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()
2102 Entities.Add(copy); 2108 Entities.Add(copy);
2103 2109
2104 lock (SceneObjectGroupsByFullID) 2110 lock (SceneObjectGroupsByFullID)
2105 SceneObjectGroupsByFullID[copy.UUID] = copy; 2111 SceneObjectGroupsByFullID[copy.UUID] = copy;
2106 2112
2107 SceneObjectPart[] children = copy.Parts; 2113 SceneObjectPart[] children = copy.Parts;
2108 2114
2109 lock (SceneObjectGroupsByFullPartID) 2115 lock (SceneObjectGroupsByFullPartID)
2110 { 2116 {
2111 SceneObjectGroupsByFullPartID[copy.UUID] = copy; 2117 SceneObjectGroupsByFullPartID[copy.UUID] = copy;
2112 foreach (SceneObjectPart part in children) 2118 foreach (SceneObjectPart part in children)
2113 SceneObjectGroupsByFullPartID[part.UUID] = copy; 2119 SceneObjectGroupsByFullPartID[part.UUID] = copy;
2114 } 2120 }
2115 2121
2116 lock (SceneObjectGroupsByLocalPartID) 2122 lock (SceneObjectGroupsByLocalPartID)
2117 { 2123 {
2118 SceneObjectGroupsByLocalPartID[copy.LocalId] = copy; 2124 SceneObjectGroupsByLocalPartID[copy.LocalId] = copy;
2119 foreach (SceneObjectPart part in children) 2125 foreach (SceneObjectPart part in children)
2120 SceneObjectGroupsByLocalPartID[part.LocalId] = copy; 2126 SceneObjectGroupsByLocalPartID[part.LocalId] = copy;
2121 } 2127 }
2122 // PROBABLE END OF FIXME 2128 // PROBABLE END OF FIXME
2123 2129
2124 // Since we copy from a source group that is in selected 2130 // Since we copy from a source group that is in selected
@@ -2150,11 +2156,10 @@ namespace OpenSim.Region.Framework.Scenes
2150 { 2156 {
2151 m_log.WarnFormat("[SCENE]: Attempted to duplicate nonexistant prim id {0}", GroupID); 2157 m_log.WarnFormat("[SCENE]: Attempted to duplicate nonexistant prim id {0}", GroupID);
2152 } 2158 }
2153 2159
2154 return null; 2160 return null;
2155 } 2161 }
2156 2162
2157 /// <summary>
2158 /// Calculates the distance between two Vector3s 2163 /// Calculates the distance between two Vector3s
2159 /// </summary> 2164 /// </summary>
2160 /// <param name="v1"></param> 2165 /// <param name="v1"></param>
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index 2effa25..26524fb 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -54,20 +54,32 @@ namespace OpenSim.Region.Framework.Scenes
54 /// <summary> 54 /// <summary>
55 /// Start the scripts contained in all the prims in this group. 55 /// Start the scripts contained in all the prims in this group.
56 /// </summary> 56 /// </summary>
57 public void CreateScriptInstances(int startParam, bool postOnRez, 57 /// <param name="startParam"></param>
58 string engine, int stateSource) 58 /// <param name="postOnRez"></param>
59 /// <param name="engine"></param>
60 /// <param name="stateSource"></param>
61 /// <returns>
62 /// Number of scripts that were valid for starting. This does not guarantee that all these scripts
63 /// were actually started, but just that the start could be attempt (e.g. the asset data for the script could be found)
64 /// </returns>
65 public int CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
59 { 66 {
67 int scriptsStarted = 0;
68
60 // Don't start scripts if they're turned off in the region! 69 // Don't start scripts if they're turned off in the region!
61 if (!m_scene.RegionInfo.RegionSettings.DisableScripts) 70 if (!m_scene.RegionInfo.RegionSettings.DisableScripts)
62 { 71 {
63 SceneObjectPart[] parts = m_parts.GetArray(); 72 SceneObjectPart[] parts = m_parts.GetArray();
64 for (int i = 0; i < parts.Length; i++) 73 for (int i = 0; i < parts.Length; i++)
65 parts[i].Inventory.CreateScriptInstances(startParam, postOnRez, engine, stateSource); 74 scriptsStarted
75 += parts[i].Inventory.CreateScriptInstances(startParam, postOnRez, engine, stateSource);
66 } 76 }
77
78 return scriptsStarted;
67 } 79 }
68 80
69 /// <summary> 81 /// <summary>
70 /// Stop the scripts contained in all the prims in this group 82 /// Stop and remove the scripts contained in all the prims in this group
71 /// </summary> 83 /// </summary>
72 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 84 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
73 { 85 {
@@ -77,6 +89,14 @@ namespace OpenSim.Region.Framework.Scenes
77 } 89 }
78 90
79 /// <summary> 91 /// <summary>
92 /// Stop the scripts contained in all the prims in this group
93 /// </summary>
94 public void StopScriptInstances()
95 {
96 Array.ForEach<SceneObjectPart>(m_parts.GetArray(), p => p.Inventory.StopScriptInstances());
97 }
98
99 /// <summary>
80 /// Add an inventory item from a user's inventory to a prim in this scene object. 100 /// Add an inventory item from a user's inventory to a prim in this scene object.
81 /// </summary> 101 /// </summary>
82 /// <param name="agentID">The agent adding the item.</param> 102 /// <param name="agentID">The agent adding the item.</param>
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 1734ab7..f1f94a7 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -131,6 +131,15 @@ namespace OpenSim.Region.Framework.Scenes
131 } 131 }
132 } 132 }
133 133
134 /// <summary>
135 /// This indicates whether the object has changed such that it needs to be repersisted to permenant storage
136 /// (the database).
137 /// </summary>
138 /// <remarks>
139 /// Ultimately, this should be managed such that region modules can change it at the end of a set of operations
140 /// so that either all changes are preserved or none at all. However, currently, a large amount of internal
141 /// code will set this anyway when some object properties are changed.
142 /// </remarks>
134 public bool HasGroupChanged 143 public bool HasGroupChanged
135 { 144 {
136 set 145 set
@@ -244,6 +253,22 @@ namespace OpenSim.Region.Framework.Scenes
244 } 253 }
245 } 254 }
246 255
256 /// <summary>
257 /// If this scene object has an attachment point then indicate whether there is a point where
258 /// attachments are perceivable by avatars other than the avatar to which this object is attached.
259 /// </summary>
260 /// <remarks>
261 /// HUDs are not perceivable by other avatars.
262 /// </remarks>
263 public bool HasPrivateAttachmentPoint
264 {
265 get
266 {
267 return AttachmentPoint >= (uint)OpenMetaverse.AttachmentPoint.HUDCenter2
268 && AttachmentPoint <= (uint)OpenMetaverse.AttachmentPoint.HUDBottomRight;
269 }
270 }
271
247 public void ClearPartAttachmentData() 272 public void ClearPartAttachmentData()
248 { 273 {
249 AttachmentPoint = 0; 274 AttachmentPoint = 0;
@@ -621,6 +646,9 @@ namespace OpenSim.Region.Framework.Scenes
621 return; 646 return;
622 } 647 }
623 } 648 }
649
650 // Restuff the new GroupPosition into each SOP of the linkset.
651 // This has the affect of resetting and tainting the physics actors.
624 SceneObjectPart[] parts = m_parts.GetArray(); 652 SceneObjectPart[] parts = m_parts.GetArray();
625 bool triggerScriptEvent = m_rootPart.GroupPosition != val; 653 bool triggerScriptEvent = m_rootPart.GroupPosition != val;
626 if (m_dupeInProgress) 654 if (m_dupeInProgress)
@@ -1649,16 +1677,6 @@ namespace OpenSim.Region.Framework.Scenes
1649 { 1677 {
1650 return Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f); 1678 return Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f);
1651 } 1679 }
1652
1653 /// <summary>
1654 /// Added as a way for the storage provider to reset the scene,
1655 /// most likely a better way to do this sort of thing but for now...
1656 /// </summary>
1657 /// <param name="scene"></param>
1658 public void SetScene(Scene scene)
1659 {
1660 m_scene = scene;
1661 }
1662 1680
1663 /// <summary> 1681 /// <summary>
1664 /// Set a part to act as the root part for this scene object 1682 /// Set a part to act as the root part for this scene object
@@ -1740,6 +1758,9 @@ namespace OpenSim.Region.Framework.Scenes
1740 1758
1741 public void ResetChildPrimPhysicsPositions() 1759 public void ResetChildPrimPhysicsPositions()
1742 { 1760 {
1761 // Setting this SOG's absolute position also loops through and sets the positions
1762 // of the SOP's in this SOG's linkset. This has the side affect of making sure
1763 // the physics world matches the simulated world.
1743 AbsolutePosition = AbsolutePosition; // could someone in the know please explain how this works? 1764 AbsolutePosition = AbsolutePosition; // could someone in the know please explain how this works?
1744 1765
1745 // teravus: AbsolutePosition is NOT a normal property! 1766 // teravus: AbsolutePosition is NOT a normal property!
@@ -1816,8 +1837,9 @@ namespace OpenSim.Region.Framework.Scenes
1816 part.ClearUpdateSchedule(); 1837 part.ClearUpdateSchedule();
1817 if (part == m_rootPart) 1838 if (part == m_rootPart)
1818 { 1839 {
1819 if (!IsAttachment || (AttachedAvatar == avatar.ControllingClient.AgentId) || 1840 if (!IsAttachment
1820 (AttachmentPoint < 31) || (AttachmentPoint > 38)) 1841 || AttachedAvatar == avatar.ControllingClient.AgentId
1842 || !HasPrivateAttachmentPoint)
1821 avatar.ControllingClient.SendKillObject(m_regionHandle, new List<uint> { part.LocalId }); 1843 avatar.ControllingClient.SendKillObject(m_regionHandle, new List<uint> { part.LocalId });
1822 } 1844 }
1823 } 1845 }
@@ -2531,8 +2553,13 @@ namespace OpenSim.Region.Framework.Scenes
2531 } 2553 }
2532 2554
2533 /// <summary> 2555 /// <summary>
2534 /// Schedule a full update for this scene object 2556 /// Schedule a full update for this scene object to all interested viewers.
2535 /// </summary> 2557 /// </summary>
2558 /// <remarks>
2559 /// Ultimately, this should be managed such that region modules can invoke it at the end of a set of operations
2560 /// so that either all changes are sent at once. However, currently, a large amount of internal
2561 /// code will set this anyway when some object properties are changed.
2562 /// </remarks>
2536 public void ScheduleGroupForFullUpdate() 2563 public void ScheduleGroupForFullUpdate()
2537 { 2564 {
2538// if (IsAttachment) 2565// if (IsAttachment)
@@ -2551,8 +2578,13 @@ namespace OpenSim.Region.Framework.Scenes
2551 } 2578 }
2552 2579
2553 /// <summary> 2580 /// <summary>
2554 /// Schedule a terse update for this scene object 2581 /// Schedule a terse update for this scene object to all interested viewers.
2555 /// </summary> 2582 /// </summary>
2583 /// <remarks>
2584 /// Ultimately, this should be managed such that region modules can invoke it at the end of a set of operations
2585 /// so that either all changes are sent at once. However, currently, a large amount of internal
2586 /// code will set this anyway when some object properties are changed.
2587 /// </remarks>
2556 public void ScheduleGroupForTerseUpdate() 2588 public void ScheduleGroupForTerseUpdate()
2557 { 2589 {
2558// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); 2590// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID);
@@ -2682,12 +2714,18 @@ namespace OpenSim.Region.Framework.Scenes
2682 /// <summary> 2714 /// <summary>
2683 /// Link the prims in a given group to this group 2715 /// Link the prims in a given group to this group
2684 /// </summary> 2716 /// </summary>
2717 /// <remarks>
2718 /// Do not call this method directly - use Scene.LinkObjects() instead to avoid races between threads.
2719 /// FIXME: There are places where scripts call these methods directly without locking. This is a potential race condition.
2720 /// </remarks>
2685 /// <param name="objectGroup">The group of prims which should be linked to this group</param> 2721 /// <param name="objectGroup">The group of prims which should be linked to this group</param>
2686 public void LinkToGroup(SceneObjectGroup objectGroup) 2722 public void LinkToGroup(SceneObjectGroup objectGroup)
2687 { 2723 {
2688 LinkToGroup(objectGroup, false); 2724 LinkToGroup(objectGroup, false);
2689 } 2725 }
2690 2726
2727 // Link an existing group to this group.
2728 // The group being linked need not be a linkset -- it can have just one prim.
2691 public void LinkToGroup(SceneObjectGroup objectGroup, bool insert) 2729 public void LinkToGroup(SceneObjectGroup objectGroup, bool insert)
2692 { 2730 {
2693// m_log.DebugFormat( 2731// m_log.DebugFormat(
@@ -2698,6 +2736,7 @@ namespace OpenSim.Region.Framework.Scenes
2698 if (objectGroup == this) 2736 if (objectGroup == this)
2699 return; 2737 return;
2700 2738
2739 // 'linkPart' == the root of the group being linked into this group
2701 SceneObjectPart linkPart = objectGroup.m_rootPart; 2740 SceneObjectPart linkPart = objectGroup.m_rootPart;
2702 2741
2703 if (m_rootPart.PhysActor != null) 2742 if (m_rootPart.PhysActor != null)
@@ -2709,31 +2748,44 @@ namespace OpenSim.Region.Framework.Scenes
2709 bool grpusephys = UsesPhysics; 2748 bool grpusephys = UsesPhysics;
2710 bool grptemporary = IsTemporary; 2749 bool grptemporary = IsTemporary;
2711 2750
2751 // Remember where the group being linked thought it was
2712 Vector3 oldGroupPosition = linkPart.GroupPosition; 2752 Vector3 oldGroupPosition = linkPart.GroupPosition;
2713 Quaternion oldRootRotation = linkPart.RotationOffset; 2753 Quaternion oldRootRotation = linkPart.RotationOffset;
2714 2754
2715 linkPart.OffsetPosition = linkPart.GroupPosition - AbsolutePosition; 2755 // A linked SOP remembers its location and rotation relative to the root of a group.
2756 // Convert the root of the group being linked to be relative to the
2757 // root of the group being linked to.
2758 // Note: Some of the assignments have complex side effects.
2716 2759
2760 // First move the new group's root SOP's position to be relative to ours
2761 // (radams1: Not sure if the multiple setting of OffsetPosition is required. If not,
2762 // this code can be reordered to have a more logical flow.)
2763 linkPart.OffsetPosition = linkPart.GroupPosition - AbsolutePosition;
2764 // Assign the new parent to the root of the old group
2717 linkPart.ParentID = m_rootPart.LocalId; 2765 linkPart.ParentID = m_rootPart.LocalId;
2718 2766 // Now that it's a child, it's group position is our root position
2719 linkPart.GroupPosition = AbsolutePosition; 2767 linkPart.GroupPosition = AbsolutePosition;
2720 2768
2721 Vector3 axPos = linkPart.OffsetPosition; 2769 Vector3 axPos = linkPart.OffsetPosition;
2770 // Rotate the linking root SOP's position to be relative to the new root prim
2722 Quaternion parentRot = m_rootPart.RotationOffset; 2771 Quaternion parentRot = m_rootPart.RotationOffset;
2723 axPos *= Quaternion.Conjugate(parentRot); 2772 axPos *= Quaternion.Conjugate(parentRot);
2724 linkPart.OffsetPosition = axPos; 2773 linkPart.OffsetPosition = axPos;
2725 2774
2775 // Make the linking root SOP's rotation relative to the new root prim
2726 Quaternion oldRot = linkPart.RotationOffset; 2776 Quaternion oldRot = linkPart.RotationOffset;
2727 Quaternion newRot = Quaternion.Conjugate(parentRot) * oldRot; 2777 Quaternion newRot = Quaternion.Conjugate(parentRot) * oldRot;
2728 linkPart.RotationOffset = newRot; 2778 linkPart.RotationOffset = newRot;
2729 2779
2730// linkPart.ParentID = m_rootPart.LocalId; done above 2780 // If there is only one SOP in a SOG, the LinkNum is zero. I.e., not a linkset.
2731 2781 // Now that we know this SOG has at least two SOPs in it, the new root
2782 // SOP becomes the first in the linkset.
2732 if (m_rootPart.LinkNum == 0) 2783 if (m_rootPart.LinkNum == 0)
2733 m_rootPart.LinkNum = 1; 2784 m_rootPart.LinkNum = 1;
2734 2785
2735 lock (m_parts.SyncRoot) 2786 lock (m_parts.SyncRoot)
2736 { 2787 {
2788 // Calculate the new link number for the old root SOP
2737 int linkNum; 2789 int linkNum;
2738 if (insert) 2790 if (insert)
2739 { 2791 {
@@ -2749,6 +2801,7 @@ namespace OpenSim.Region.Framework.Scenes
2749 linkNum = PrimCount + 1; 2801 linkNum = PrimCount + 1;
2750 } 2802 }
2751 2803
2804 // Add the old root SOP as a part in our group's list
2752 m_parts.Add(linkPart.UUID, linkPart); 2805 m_parts.Add(linkPart.UUID, linkPart);
2753 2806
2754 linkPart.SetParent(this); 2807 linkPart.SetParent(this);
@@ -2756,6 +2809,8 @@ namespace OpenSim.Region.Framework.Scenes
2756 2809
2757 // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now 2810 // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now
2758 linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive, true); 2811 linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive, true);
2812
2813 // If the added SOP is physical, also tell the physics engine about the link relationship.
2759 if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical) 2814 if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
2760 { 2815 {
2761 linkPart.PhysActor.link(m_rootPart.PhysActor); 2816 linkPart.PhysActor.link(m_rootPart.PhysActor);
@@ -2763,21 +2818,28 @@ namespace OpenSim.Region.Framework.Scenes
2763 } 2818 }
2764 2819
2765 linkPart.LinkNum = linkNum++; 2820 linkPart.LinkNum = linkNum++;
2821 linkPart.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect, false);
2766 2822
2823 // Get a list of the SOP's in the old group in order of their linknum's.
2767 SceneObjectPart[] ogParts = objectGroup.Parts; 2824 SceneObjectPart[] ogParts = objectGroup.Parts;
2768 Array.Sort(ogParts, delegate(SceneObjectPart a, SceneObjectPart b) 2825 Array.Sort(ogParts, delegate(SceneObjectPart a, SceneObjectPart b)
2769 { 2826 {
2770 return a.LinkNum - b.LinkNum; 2827 return a.LinkNum - b.LinkNum;
2771 }); 2828 });
2772 2829
2830 // Add each of the SOP's from the old linkset to our linkset
2773 for (int i = 0; i < ogParts.Length; i++) 2831 for (int i = 0; i < ogParts.Length; i++)
2774 { 2832 {
2775 SceneObjectPart part = ogParts[i]; 2833 SceneObjectPart part = ogParts[i];
2776 if (part.UUID != objectGroup.m_rootPart.UUID) 2834 if (part.UUID != objectGroup.m_rootPart.UUID)
2777 { 2835 {
2778 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++); 2836 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2779 // let physics know 2837
2838 // Update the physics flags for the newly added SOP
2839 // (Is this necessary? LinkNonRootPart() has already called UpdatePrimFlags but with different flags!??)
2780 part.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (part.Flags & PrimFlags.Phantom) != 0), part.VolumeDetectActive, true); 2840 part.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (part.Flags & PrimFlags.Phantom) != 0), part.VolumeDetectActive, true);
2841
2842 // If the added SOP is physical, also tell the physics engine about the link relationship.
2781 if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical) 2843 if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
2782 { 2844 {
2783 part.PhysActor.link(m_rootPart.PhysActor); 2845 part.PhysActor.link(m_rootPart.PhysActor);
@@ -2788,6 +2850,7 @@ namespace OpenSim.Region.Framework.Scenes
2788 } 2850 }
2789 } 2851 }
2790 2852
2853 // Now that we've aquired all of the old SOG's parts, remove the old SOG from the scene.
2791 m_scene.UnlinkSceneObject(objectGroup, true); 2854 m_scene.UnlinkSceneObject(objectGroup, true);
2792 objectGroup.IsDeleted = true; 2855 objectGroup.IsDeleted = true;
2793 2856
@@ -2814,6 +2877,11 @@ namespace OpenSim.Region.Framework.Scenes
2814 /// Delink the given prim from this group. The delinked prim is established as 2877 /// Delink the given prim from this group. The delinked prim is established as
2815 /// an independent SceneObjectGroup. 2878 /// an independent SceneObjectGroup.
2816 /// </summary> 2879 /// </summary>
2880 /// <remarks>
2881 /// FIXME: This method should not be called directly since it bypasses update locking, allowing a potential race
2882 /// condition. But currently there is no
2883 /// alternative method that does take a lonk to delink a single prim.
2884 /// </remarks>
2817 /// <param name="partID"></param> 2885 /// <param name="partID"></param>
2818 /// <returns>The object group of the newly delinked prim. Null if part could not be found</returns> 2886 /// <returns>The object group of the newly delinked prim. Null if part could not be found</returns>
2819 public SceneObjectGroup DelinkFromGroup(uint partID) 2887 public SceneObjectGroup DelinkFromGroup(uint partID)
@@ -2825,6 +2893,11 @@ namespace OpenSim.Region.Framework.Scenes
2825 /// Delink the given prim from this group. The delinked prim is established as 2893 /// Delink the given prim from this group. The delinked prim is established as
2826 /// an independent SceneObjectGroup. 2894 /// an independent SceneObjectGroup.
2827 /// </summary> 2895 /// </summary>
2896 /// <remarks>
2897 /// FIXME: This method should not be called directly since it bypasses update locking, allowing a potential race
2898 /// condition. But currently there is no
2899 /// alternative method that does take a lonk to delink a single prim.
2900 /// </remarks>
2828 /// <param name="partID"></param> 2901 /// <param name="partID"></param>
2829 /// <param name="sendEvents"></param> 2902 /// <param name="sendEvents"></param>
2830 /// <returns>The object group of the newly delinked prim. Null if part could not be found</returns> 2903 /// <returns>The object group of the newly delinked prim. Null if part could not be found</returns>
@@ -2850,6 +2923,11 @@ namespace OpenSim.Region.Framework.Scenes
2850 /// Delink the given prim from this group. The delinked prim is established as 2923 /// Delink the given prim from this group. The delinked prim is established as
2851 /// an independent SceneObjectGroup. 2924 /// an independent SceneObjectGroup.
2852 /// </summary> 2925 /// </summary>
2926 /// <remarks>
2927 /// FIXME: This method should not be called directly since it bypasses update locking, allowing a potential race
2928 /// condition. But currently there is no
2929 /// alternative method that does take a lock to delink a single prim.
2930 /// </remarks>
2853 /// <param name="partID"></param> 2931 /// <param name="partID"></param>
2854 /// <param name="sendEvents"></param> 2932 /// <param name="sendEvents"></param>
2855 /// <returns>The object group of the newly delinked prim.</returns> 2933 /// <returns>The object group of the newly delinked prim.</returns>
@@ -2864,6 +2942,7 @@ namespace OpenSim.Region.Framework.Scenes
2864 2942
2865 linkPart.ClearUndoState(); 2943 linkPart.ClearUndoState();
2866 2944
2945 Vector3 worldPos = linkPart.GetWorldPosition();
2867 Quaternion worldRot = linkPart.GetWorldRotation(); 2946 Quaternion worldRot = linkPart.GetWorldRotation();
2868 2947
2869 // Remove the part from this object 2948 // Remove the part from this object
@@ -2873,6 +2952,7 @@ namespace OpenSim.Region.Framework.Scenes
2873 2952
2874 SceneObjectPart[] parts = m_parts.GetArray(); 2953 SceneObjectPart[] parts = m_parts.GetArray();
2875 2954
2955 // Rejigger the linknum's of the remaining SOP's to fill any gap
2876 if (parts.Length == 1 && RootPart != null) 2956 if (parts.Length == 1 && RootPart != null)
2877 { 2957 {
2878 // Single prim left 2958 // Single prim left
@@ -2894,22 +2974,31 @@ namespace OpenSim.Region.Framework.Scenes
2894 2974
2895 PhysicsActor linkPartPa = linkPart.PhysActor; 2975 PhysicsActor linkPartPa = linkPart.PhysActor;
2896 2976
2977 // Remove the SOP from the physical scene.
2978 // If the new SOG is physical, it is re-created later.
2979 // (There is a problem here in that we have not yet told the physics
2980 // engine about the delink. Someday, linksets should be made first
2981 // class objects in the physics engine interface).
2897 if (linkPartPa != null) 2982 if (linkPartPa != null)
2898 m_scene.PhysicsScene.RemovePrim(linkPartPa); 2983 m_scene.PhysicsScene.RemovePrim(linkPartPa);
2899 2984
2900 // We need to reset the child part's position 2985 // We need to reset the child part's position
2901 // ready for life as a separate object after being a part of another object 2986 // ready for life as a separate object after being a part of another object
2902 Quaternion parentRot = m_rootPart.RotationOffset;
2903 2987
2988 /* This commented out code seems to recompute what GetWorldPosition already does.
2989 * Replace with a call to GetWorldPosition (before unlinking)
2990 Quaternion parentRot = m_rootPart.RotationOffset;
2904 Vector3 axPos = linkPart.OffsetPosition; 2991 Vector3 axPos = linkPart.OffsetPosition;
2905
2906 axPos *= parentRot; 2992 axPos *= parentRot;
2907 linkPart.OffsetPosition = new Vector3(axPos.X, axPos.Y, axPos.Z); 2993 linkPart.OffsetPosition = new Vector3(axPos.X, axPos.Y, axPos.Z);
2908 linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition; 2994 linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition;
2909 linkPart.OffsetPosition = new Vector3(0, 0, 0); 2995 linkPart.OffsetPosition = new Vector3(0, 0, 0);
2910 2996 */
2997 linkPart.GroupPosition = worldPos;
2998 linkPart.OffsetPosition = Vector3.Zero;
2911 linkPart.RotationOffset = worldRot; 2999 linkPart.RotationOffset = worldRot;
2912 3000
3001 // Create a new SOG to go around this unlinked and unattached SOP
2913 SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart); 3002 SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart);
2914 3003
2915 m_scene.AddNewSceneObject(objectGroup, true); 3004 m_scene.AddNewSceneObject(objectGroup, true);
@@ -2947,42 +3036,58 @@ namespace OpenSim.Region.Framework.Scenes
2947 m_isBackedUp = false; 3036 m_isBackedUp = false;
2948 } 3037 }
2949 3038
3039 // This links an SOP from a previous linkset into my linkset.
3040 // The trick is that the SOP's position and rotation are relative to the old root SOP's
3041 // so we are passed in the position and rotation of the old linkset so this can
3042 // unjigger this SOP's position and rotation from the previous linkset and
3043 // then make them relative to my linkset root.
2950 private void LinkNonRootPart(SceneObjectPart part, Vector3 oldGroupPosition, Quaternion oldGroupRotation, int linkNum) 3044 private void LinkNonRootPart(SceneObjectPart part, Vector3 oldGroupPosition, Quaternion oldGroupRotation, int linkNum)
2951 { 3045 {
2952 Quaternion parentRot = oldGroupRotation; 3046 Quaternion parentRot = oldGroupRotation;
2953 Quaternion oldRot = part.RotationOffset; 3047 Quaternion oldRot = part.RotationOffset;
2954 Quaternion worldRot = parentRot * oldRot;
2955
2956 parentRot = oldGroupRotation;
2957 3048
3049 // Move our position to not be relative to the old parent
2958 Vector3 axPos = part.OffsetPosition; 3050 Vector3 axPos = part.OffsetPosition;
2959
2960 axPos *= parentRot; 3051 axPos *= parentRot;
2961 part.OffsetPosition = axPos; 3052 part.OffsetPosition = axPos;
2962 Vector3 newPos = oldGroupPosition + part.OffsetPosition; 3053 Vector3 newPos = oldGroupPosition + part.OffsetPosition;
2963 part.GroupPosition = newPos; 3054 part.GroupPosition = newPos;
2964 part.OffsetPosition = Vector3.Zero; 3055 part.OffsetPosition = Vector3.Zero;
3056
3057 // Compution our rotation to be not relative to the old parent
3058 Quaternion worldRot = parentRot * oldRot;
2965 part.RotationOffset = worldRot; 3059 part.RotationOffset = worldRot;
2966 3060
3061 // Add this SOP to our linkset
2967 part.SetParent(this); 3062 part.SetParent(this);
2968 part.ParentID = m_rootPart.LocalId; 3063 part.ParentID = m_rootPart.LocalId;
2969
2970 m_parts.Add(part.UUID, part); 3064 m_parts.Add(part.UUID, part);
2971 3065
2972 part.LinkNum = linkNum; 3066 part.LinkNum = linkNum;
2973 3067
2974 part.OffsetPosition = newPos - AbsolutePosition; 3068 // Compute the new position of this SOP relative to the group position
3069 part.OffsetPosition = part.GroupPosition - AbsolutePosition;
2975 3070
2976 Quaternion rootRotation = m_rootPart.RotationOffset; 3071 // (radams1 20120711: I don't know why part.OffsetPosition is set multiple times.
3072 // It would have the affect of setting the physics engine position multiple
3073 // times. In theory, that is not necessary but I don't have a good linkset
3074 // test to know that cleaning up this code wouldn't break things.)
2977 3075
3076 // Rotate the relative position by the rotation of the group
3077 Quaternion rootRotation = m_rootPart.RotationOffset;
2978 Vector3 pos = part.OffsetPosition; 3078 Vector3 pos = part.OffsetPosition;
2979 pos *= Quaternion.Conjugate(rootRotation); 3079 pos *= Quaternion.Conjugate(rootRotation);
2980 part.OffsetPosition = pos; 3080 part.OffsetPosition = pos;
2981 3081
3082 // Compute the SOP's rotation relative to the rotation of the group.
2982 parentRot = m_rootPart.RotationOffset; 3083 parentRot = m_rootPart.RotationOffset;
2983 oldRot = part.RotationOffset; 3084 oldRot = part.RotationOffset;
2984 Quaternion newRot = Quaternion.Conjugate(parentRot) * worldRot; 3085 Quaternion newRot = Quaternion.Conjugate(parentRot) * worldRot;
2985 part.RotationOffset = newRot; 3086 part.RotationOffset = newRot;
3087
3088 // Since this SOP's state has changed, push those changes into the physics engine
3089 // and the simulator.
3090 part.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect, false);
2986 } 3091 }
2987 3092
2988 /// <summary> 3093 /// <summary>
@@ -3498,7 +3603,7 @@ namespace OpenSim.Region.Framework.Scenes
3498 3603
3499 //we need to do a terse update even if the move wasn't allowed 3604 //we need to do a terse update even if the move wasn't allowed
3500 // so that the position is reset in the client (the object snaps back) 3605 // so that the position is reset in the client (the object snaps back)
3501 ScheduleGroupForTerseUpdate(); 3606 RootPart.ScheduleTerseUpdate();
3502 } 3607 }
3503 3608
3504 /// <summary> 3609 /// <summary>
@@ -3613,6 +3718,11 @@ namespace OpenSim.Region.Framework.Scenes
3613 m_scene.PhysicsScene.AddPhysicsActorTaint(actor); 3718 m_scene.PhysicsScene.AddPhysicsActorTaint(actor);
3614 } 3719 }
3615 3720
3721 if (IsAttachment)
3722 {
3723 m_rootPart.AttachedPos = pos;
3724 }
3725
3616 AbsolutePosition = pos; 3726 AbsolutePosition = pos;
3617 3727
3618 HasGroupChanged = true; 3728 HasGroupChanged = true;
@@ -4199,7 +4309,86 @@ namespace OpenSim.Region.Framework.Scenes
4199 for (int i = 0; i < parts.Length; i++) 4309 for (int i = 0; i < parts.Length; i++)
4200 parts[i].TriggerScriptChangedEvent(val); 4310 parts[i].TriggerScriptChangedEvent(val);
4201 } 4311 }
4202 4312
4313 /// <summary>
4314 /// Returns a count of the number of scripts in this groups parts.
4315 /// </summary>
4316 public int ScriptCount()
4317 {
4318 int count = 0;
4319 SceneObjectPart[] parts = m_parts.GetArray();
4320 for (int i = 0; i < parts.Length; i++)
4321 count += parts[i].Inventory.ScriptCount();
4322
4323 return count;
4324 }
4325
4326 /// <summary>
4327 /// A float the value is a representative execution time in milliseconds of all scripts in the link set.
4328 /// </summary>
4329 public float ScriptExecutionTime()
4330 {
4331 IScriptModule[] engines = Scene.RequestModuleInterfaces<IScriptModule>();
4332
4333 if (engines.Length == 0) // No engine at all
4334 return 0.0f;
4335
4336 float time = 0.0f;
4337
4338 // get all the scripts in all parts
4339 SceneObjectPart[] parts = m_parts.GetArray();
4340 List<TaskInventoryItem> scripts = new List<TaskInventoryItem>();
4341 for (int i = 0; i < parts.Length; i++)
4342 {
4343 scripts.AddRange(parts[i].Inventory.GetInventoryItems(InventoryType.LSL));
4344 }
4345 // extract the UUIDs
4346 List<UUID> ids = new List<UUID>(scripts.Count);
4347 foreach (TaskInventoryItem script in scripts)
4348 {
4349 if (!ids.Contains(script.ItemID))
4350 {
4351 ids.Add(script.ItemID);
4352 }
4353 }
4354 // Offer the list of script UUIDs to each engine found and accumulate the time
4355 foreach (IScriptModule e in engines)
4356 {
4357 if (e != null)
4358 {
4359 time += e.GetScriptExecutionTime(ids);
4360 }
4361 }
4362 return time;
4363 }
4364
4365 /// <summary>
4366 /// Returns a count of the number of running scripts in this groups parts.
4367 /// </summary>
4368 public int RunningScriptCount()
4369 {
4370 int count = 0;
4371 SceneObjectPart[] parts = m_parts.GetArray();
4372 for (int i = 0; i < parts.Length; i++)
4373 count += parts[i].Inventory.RunningScriptCount();
4374
4375 return count;
4376 }
4377
4378 /// <summary>
4379 /// Gets the number of sitting avatars.
4380 /// </summary>
4381 /// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks>
4382 /// <returns></returns>
4383 public int GetSittingAvatarsCount()
4384 {
4385 int count = 0;
4386
4387 Array.ForEach<SceneObjectPart>(m_parts.GetArray(), p => count += p.GetSittingAvatarsCount());
4388
4389 return count;
4390 }
4391
4203 public override string ToString() 4392 public override string ToString()
4204 { 4393 {
4205 return String.Format("{0} {1} ({2})", Name, UUID, AbsolutePosition); 4394 return String.Format("{0} {1} ({2})", Name, UUID, AbsolutePosition);
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 16a8588..b038876 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -147,6 +147,21 @@ namespace OpenSim.Region.Framework.Scenes
147 get { return ParentGroup.RootPart == this; } 147 get { return ParentGroup.RootPart == this; }
148 } 148 }
149 149
150 /// <summary>
151 /// Is an explicit sit target set for this part?
152 /// </summary>
153 public bool IsSitTargetSet
154 {
155 get
156 {
157 return
158 !(SitTargetPosition == Vector3.Zero
159 && (SitTargetOrientation == Quaternion.Identity // Valid Zero Rotation quaternion
160 || SitTargetOrientation.X == 0f && SitTargetOrientation.Y == 0f && SitTargetOrientation.Z == 1f && SitTargetOrientation.W == 0f // W-Z Mapping was invalid at one point
161 || SitTargetOrientation.X == 0f && SitTargetOrientation.Y == 0f && SitTargetOrientation.Z == 0f && SitTargetOrientation.W == 0f)); // Invalid Quaternion
162 }
163 }
164
150 #region Fields 165 #region Fields
151 166
152 public bool AllowedDrop; 167 public bool AllowedDrop;
@@ -426,7 +441,6 @@ namespace OpenSim.Region.Framework.Scenes
426 private uint _category; 441 private uint _category;
427 private Int32 _creationDate; 442 private Int32 _creationDate;
428 private uint _parentID = 0; 443 private uint _parentID = 0;
429 private UUID m_sitTargetAvatar = UUID.Zero;
430 private uint _baseMask = (uint)PermissionMask.All; 444 private uint _baseMask = (uint)PermissionMask.All;
431 private uint _ownerMask = (uint)PermissionMask.All; 445 private uint _ownerMask = (uint)PermissionMask.All;
432 private uint _groupMask = (uint)PermissionMask.None; 446 private uint _groupMask = (uint)PermissionMask.None;
@@ -738,6 +752,7 @@ namespace OpenSim.Region.Framework.Scenes
738 return m_groupPosition; 752 return m_groupPosition;
739 } 753 }
740 754
755 // If I'm an attachment, my position is reported as the position of who I'm attached to
741 if (ParentGroup.IsAttachment) 756 if (ParentGroup.IsAttachment)
742 { 757 {
743 ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar); 758 ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
@@ -765,7 +780,7 @@ namespace OpenSim.Region.Framework.Scenes
765 } 780 }
766 else 781 else
767 { 782 {
768 // To move the child prim in respect to the group position and rotation we have to calculate 783 // The physics engine always sees all objects (root or linked) in world coordinates.
769 actor.Position = GetWorldPosition(); 784 actor.Position = GetWorldPosition();
770 actor.Orientation = GetWorldRotation(); 785 actor.Orientation = GetWorldRotation();
771 } 786 }
@@ -844,6 +859,8 @@ namespace OpenSim.Region.Framework.Scenes
844 { 859 {
845 // We don't want the physics engine mucking up the rotations in a linkset 860 // We don't want the physics engine mucking up the rotations in a linkset
846 PhysicsActor actor = PhysActor; 861 PhysicsActor actor = PhysActor;
862 // If this is a root of a linkset, the real rotation is what the physics engine thinks.
863 // If not a root prim, the offset rotation is computed by SOG and is relative to the root.
847 if (ParentID == 0 && (Shape.PCode != 9 || Shape.State == 0) && actor != null) 864 if (ParentID == 0 && (Shape.PCode != 9 || Shape.State == 0) && actor != null)
848 { 865 {
849 if (actor.Orientation.X != 0f || actor.Orientation.Y != 0f 866 if (actor.Orientation.X != 0f || actor.Orientation.Y != 0f
@@ -1024,7 +1041,18 @@ namespace OpenSim.Region.Framework.Scenes
1024 public int LinkNum 1041 public int LinkNum
1025 { 1042 {
1026 get { return m_linkNum; } 1043 get { return m_linkNum; }
1027 set { m_linkNum = value; } 1044 set
1045 {
1046// if (ParentGroup != null)
1047// {
1048// m_log.DebugFormat(
1049// "[SCENE OBJECT PART]: Setting linknum of {0}@{1} to {2} from {3}",
1050// Name, AbsolutePosition, value, m_linkNum);
1051// Util.PrintCallStack();
1052// }
1053
1054 m_linkNum = value;
1055 }
1028 } 1056 }
1029 1057
1030 public byte ClickAction 1058 public byte ClickAction
@@ -1309,13 +1337,20 @@ namespace OpenSim.Region.Framework.Scenes
1309 } 1337 }
1310 1338
1311 /// <summary> 1339 /// <summary>
1312 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero 1340 /// ID of the avatar that is sat on us if we have a sit target. If there is no such avatar then is UUID.Zero
1313 /// </summary> 1341 /// </summary>
1314 public UUID SitTargetAvatar 1342 public UUID SitTargetAvatar { get; set; }
1315 { 1343
1316 get { return m_sitTargetAvatar; } 1344 /// <summary>
1317 set { m_sitTargetAvatar = value; } 1345 /// IDs of all avatars start on this object part.
1318 } 1346 /// </summary>
1347 /// <remarks>
1348 /// We need to track this so that we can stop sat upon prims from being attached.
1349 /// </remarks>
1350 /// <value>
1351 /// null if there are no sitting avatars. This is to save us create a hashset for every prim in a scene.
1352 /// </value>
1353 private HashSet<UUID> m_sittingAvatars;
1319 1354
1320 public virtual UUID RegionID 1355 public virtual UUID RegionID
1321 { 1356 {
@@ -2111,7 +2146,7 @@ namespace OpenSim.Region.Framework.Scenes
2111 else 2146 else
2112 m_log.WarnFormat( 2147 m_log.WarnFormat(
2113 "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data", 2148 "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data",
2114 Name, LocalId, id); 2149 Name, UUID, id);
2115 } 2150 }
2116 2151
2117 /// <summary> 2152 /// <summary>
@@ -2216,6 +2251,9 @@ namespace OpenSim.Region.Framework.Scenes
2216 /// <param name="isNew"></param> 2251 /// <param name="isNew"></param>
2217 public void DoPhysicsPropertyUpdate(bool UsePhysics, bool isNew) 2252 public void DoPhysicsPropertyUpdate(bool UsePhysics, bool isNew)
2218 { 2253 {
2254 if (ParentGroup.Scene == null)
2255 return;
2256
2219 if (!ParentGroup.Scene.PhysicalPrims && UsePhysics) 2257 if (!ParentGroup.Scene.PhysicalPrims && UsePhysics)
2220 return; 2258 return;
2221 2259
@@ -2494,14 +2532,20 @@ namespace OpenSim.Region.Framework.Scenes
2494 /// <returns>A Linked Child Prim objects position in world</returns> 2532 /// <returns>A Linked Child Prim objects position in world</returns>
2495 public Vector3 GetWorldPosition() 2533 public Vector3 GetWorldPosition()
2496 { 2534 {
2497 Quaternion parentRot = ParentGroup.RootPart.RotationOffset; 2535 Vector3 ret;
2498 Vector3 axPos = OffsetPosition; 2536 if (_parentID == 0)
2499 axPos *= parentRot; 2537 // if a root SOP, my position is what it is
2500 Vector3 translationOffsetPosition = axPos; 2538 ret = GroupPosition;
2501 if(_parentID == 0)
2502 return GroupPosition;
2503 else 2539 else
2504 return ParentGroup.AbsolutePosition + translationOffsetPosition; 2540 {
2541 // If a child SOP, my position is relative to the root SOP so take
2542 // my info and add the root's position and rotation to
2543 // get my world position.
2544 Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
2545 Vector3 translationOffsetPosition = OffsetPosition * parentRot;
2546 ret = ParentGroup.AbsolutePosition + translationOffsetPosition;
2547 }
2548 return ret;
2505 } 2549 }
2506 2550
2507 /// <summary> 2551 /// <summary>
@@ -2518,6 +2562,8 @@ namespace OpenSim.Region.Framework.Scenes
2518 } 2562 }
2519 else 2563 else
2520 { 2564 {
2565 // A child SOP's rotation is relative to the root SOP's rotation.
2566 // Combine them to get my absolute rotation.
2521 Quaternion parentRot = ParentGroup.RootPart.RotationOffset; 2567 Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
2522 Quaternion oldRot = RotationOffset; 2568 Quaternion oldRot = RotationOffset;
2523 newRot = parentRot * oldRot; 2569 newRot = parentRot * oldRot;
@@ -3174,8 +3220,9 @@ namespace OpenSim.Region.Framework.Scenes
3174 if (ParentGroup.IsDeleted) 3220 if (ParentGroup.IsDeleted)
3175 return; 3221 return;
3176 3222
3177 if (ParentGroup.IsAttachment && (ParentGroup.AttachedAvatar != remoteClient.AgentId) && 3223 if (ParentGroup.IsAttachment
3178 (ParentGroup.AttachmentPoint >= 31) && (ParentGroup.AttachmentPoint <= 38)) 3224 && ParentGroup.AttachedAvatar != remoteClient.AgentId
3225 && ParentGroup.HasPrivateAttachmentPoint)
3179 return; 3226 return;
3180 3227
3181 if (remoteClient.AgentId == OwnerID) 3228 if (remoteClient.AgentId == OwnerID)
@@ -3694,7 +3741,6 @@ namespace OpenSim.Region.Framework.Scenes
3694 hasProfileCut = hasDimple; // is it the same thing? 3741 hasProfileCut = hasDimple; // is it the same thing?
3695 } 3742 }
3696 3743
3697
3698 public void SetGroup(UUID groupID, IClientAPI client) 3744 public void SetGroup(UUID groupID, IClientAPI client)
3699 { 3745 {
3700 // Scene.AddNewPrims() calls with client == null so can't use this. 3746 // Scene.AddNewPrims() calls with client == null so can't use this.
@@ -3724,10 +3770,12 @@ namespace OpenSim.Region.Framework.Scenes
3724 3770
3725 public void SetPhysicsAxisRotation() 3771 public void SetPhysicsAxisRotation()
3726 { 3772 {
3727 if (PhysActor != null) 3773 PhysicsActor pa = PhysActor;
3774
3775 if (pa != null)
3728 { 3776 {
3729 PhysActor.LockAngularMotion(RotationAxis); 3777 pa.LockAngularMotion(RotationAxis);
3730 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); 3778 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
3731 } 3779 }
3732 } 3780 }
3733 3781
@@ -4444,7 +4492,7 @@ namespace OpenSim.Region.Framework.Scenes
4444 // For now, we use the NINJA naming scheme for identifying joints. 4492 // For now, we use the NINJA naming scheme for identifying joints.
4445 // In the future, we can support other joint specification schemes such as a 4493 // In the future, we can support other joint specification schemes such as a
4446 // custom checkbox in the viewer GUI. 4494 // custom checkbox in the viewer GUI.
4447 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints) 4495 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
4448 { 4496 {
4449 string hingeString = "hingejoint"; 4497 string hingeString = "hingejoint";
4450 return (Name.Length >= hingeString.Length && Name.Substring(0, hingeString.Length) == hingeString); 4498 return (Name.Length >= hingeString.Length && Name.Substring(0, hingeString.Length) == hingeString);
@@ -4460,7 +4508,7 @@ namespace OpenSim.Region.Framework.Scenes
4460 // For now, we use the NINJA naming scheme for identifying joints. 4508 // For now, we use the NINJA naming scheme for identifying joints.
4461 // In the future, we can support other joint specification schemes such as a 4509 // In the future, we can support other joint specification schemes such as a
4462 // custom checkbox in the viewer GUI. 4510 // custom checkbox in the viewer GUI.
4463 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints) 4511 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
4464 { 4512 {
4465 string ballString = "balljoint"; 4513 string ballString = "balljoint";
4466 return (Name.Length >= ballString.Length && Name.Substring(0, ballString.Length) == ballString); 4514 return (Name.Length >= ballString.Length && Name.Substring(0, ballString.Length) == ballString);
@@ -4476,7 +4524,7 @@ namespace OpenSim.Region.Framework.Scenes
4476 // For now, we use the NINJA naming scheme for identifying joints. 4524 // For now, we use the NINJA naming scheme for identifying joints.
4477 // In the future, we can support other joint specification schemes such as a 4525 // In the future, we can support other joint specification schemes such as a
4478 // custom checkbox in the viewer GUI. 4526 // custom checkbox in the viewer GUI.
4479 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints) 4527 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
4480 { 4528 {
4481 return IsHingeJoint() || IsBallJoint(); 4529 return IsHingeJoint() || IsBallJoint();
4482 } 4530 }
@@ -4598,7 +4646,6 @@ namespace OpenSim.Region.Framework.Scenes
4598 } 4646 }
4599*/ 4647*/
4600 } 4648 }
4601
4602 else // it already has a physical representation 4649 else // it already has a physical representation
4603 { 4650 {
4604 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. 4651 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status.
@@ -5074,8 +5121,9 @@ namespace OpenSim.Region.Framework.Scenes
5074 if (ParentGroup.IsDeleted) 5121 if (ParentGroup.IsDeleted)
5075 return; 5122 return;
5076 5123
5077 if (ParentGroup.IsAttachment && ((ParentGroup.RootPart != this) || 5124 if (ParentGroup.IsAttachment
5078 ((ParentGroup.AttachedAvatar != remoteClient.AgentId) && (ParentGroup.AttachmentPoint >= 31) && (ParentGroup.AttachmentPoint <= 38)))) 5125 && (ParentGroup.RootPart != this
5126 || ParentGroup.AttachedAvatar != remoteClient.AgentId && ParentGroup.HasPrivateAttachmentPoint))
5079 return; 5127 return;
5080 5128
5081 // Causes this thread to dig into the Client Thread Data. 5129 // Causes this thread to dig into the Client Thread Data.
@@ -5147,5 +5195,99 @@ namespace OpenSim.Region.Framework.Scenes
5147 Inventory.UpdateInventoryItem(item, false, false); 5195 Inventory.UpdateInventoryItem(item, false, false);
5148 } 5196 }
5149 } 5197 }
5198
5199 /// <summary>
5200 /// Record an avatar sitting on this part.
5201 /// </summary>
5202 /// <remarks>This is called for all the sitting avatars whether there is a sit target set or not.</remarks>
5203 /// <returns>
5204 /// true if the avatar was not already recorded, false otherwise.
5205 /// </returns>
5206 /// <param name='avatarId'></param>
5207 protected internal bool AddSittingAvatar(UUID avatarId)
5208 {
5209 if (IsSitTargetSet && SitTargetAvatar == UUID.Zero)
5210 SitTargetAvatar = avatarId;
5211
5212 HashSet<UUID> sittingAvatars = m_sittingAvatars;
5213
5214 if (sittingAvatars == null)
5215 sittingAvatars = new HashSet<UUID>();
5216
5217 lock (sittingAvatars)
5218 {
5219 m_sittingAvatars = sittingAvatars;
5220 return m_sittingAvatars.Add(avatarId);
5221 }
5222 }
5223
5224 /// <summary>
5225 /// Remove an avatar recorded as sitting on this part.
5226 /// </summary>
5227 /// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks>
5228 /// <returns>
5229 /// true if the avatar was present and removed, false if it was not present.
5230 /// </returns>
5231 /// <param name='avatarId'></param>
5232 protected internal bool RemoveSittingAvatar(UUID avatarId)
5233 {
5234 if (SitTargetAvatar == avatarId)
5235 SitTargetAvatar = UUID.Zero;
5236
5237 HashSet<UUID> sittingAvatars = m_sittingAvatars;
5238
5239 // This can occur under a race condition where another thread
5240 if (sittingAvatars == null)
5241 return false;
5242
5243 lock (sittingAvatars)
5244 {
5245 if (sittingAvatars.Remove(avatarId))
5246 {
5247 if (sittingAvatars.Count == 0)
5248 m_sittingAvatars = null;
5249
5250 return true;
5251 }
5252 }
5253
5254 return false;
5255 }
5256
5257 /// <summary>
5258 /// Get a copy of the list of sitting avatars.
5259 /// </summary>
5260 /// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks>
5261 /// <returns>A hashset of the sitting avatars. Returns null if there are no sitting avatars.</returns>
5262 public HashSet<UUID> GetSittingAvatars()
5263 {
5264 HashSet<UUID> sittingAvatars = m_sittingAvatars;
5265
5266 if (sittingAvatars == null)
5267 {
5268 return null;
5269 }
5270 else
5271 {
5272 lock (sittingAvatars)
5273 return new HashSet<UUID>(sittingAvatars);
5274 }
5275 }
5276
5277 /// <summary>
5278 /// Gets the number of sitting avatars.
5279 /// </summary>
5280 /// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks>
5281 /// <returns></returns>
5282 public int GetSittingAvatarsCount()
5283 {
5284 HashSet<UUID> sittingAvatars = m_sittingAvatars;
5285
5286 if (sittingAvatars == null)
5287 return 0;
5288
5289 lock (sittingAvatars)
5290 return sittingAvatars.Count;
5291 }
5150 } 5292 }
5151} 5293}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 959046a..1c9a17e 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -176,16 +176,14 @@ namespace OpenSim.Region.Framework.Scenes
176 /// <param name="ownerId"></param> 176 /// <param name="ownerId"></param>
177 public void ChangeInventoryOwner(UUID ownerId) 177 public void ChangeInventoryOwner(UUID ownerId)
178 { 178 {
179 m_items.LockItemsForWrite(true); 179 List<TaskInventoryItem> items = GetInventoryItems();
180 if (0 == Items.Count) 180
181 { 181 if (items.Count == 0)
182 m_items.LockItemsForWrite(false);
183 return; 182 return;
184 }
185 183
184 m_items.LockItemsForWrite(true);
186 HasInventoryChanged = true; 185 HasInventoryChanged = true;
187 m_part.ParentGroup.HasGroupChanged = true; 186 m_part.ParentGroup.HasGroupChanged = true;
188 List<TaskInventoryItem> items = GetInventoryItems();
189 foreach (TaskInventoryItem item in items) 187 foreach (TaskInventoryItem item in items)
190 { 188 {
191 if (ownerId != item.OwnerID) 189 if (ownerId != item.OwnerID)
@@ -234,7 +232,7 @@ namespace OpenSim.Region.Framework.Scenes
234 232
235 private void QueryScriptStates() 233 private void QueryScriptStates()
236 { 234 {
237 if (m_part == null || m_part.ParentGroup == null) 235 if (m_part == null || m_part.ParentGroup == null || m_part.ParentGroup.Scene == null)
238 return; 236 return;
239 237
240 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>(); 238 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
@@ -262,19 +260,16 @@ namespace OpenSim.Region.Framework.Scenes
262 Items.LockItemsForRead(false); 260 Items.LockItemsForRead(false);
263 } 261 }
264 262
265 /// <summary> 263 public int CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
266 /// Start all the scripts contained in this prim's inventory
267 /// </summary>
268 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
269 { 264 {
270 Items.LockItemsForRead(true); 265 int scriptsValidForStarting = 0;
271 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 266
272 Items.LockItemsForRead(false); 267 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL);
273 foreach (TaskInventoryItem item in items) 268 foreach (TaskInventoryItem item in scripts)
274 { 269 if (CreateScriptInstance(item, startParam, postOnRez, engine, stateSource))
275 if ((int)InventoryType.LSL == item.InvType) 270 scriptsValidForStarting++;
276 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 271
277 } 272 return scriptsValidForStarting;
278 } 273 }
279 274
280 public ArrayList GetScriptErrors(UUID itemID) 275 public ArrayList GetScriptErrors(UUID itemID)
@@ -297,7 +292,7 @@ namespace OpenSim.Region.Framework.Scenes
297 } 292 }
298 293
299 /// <summary> 294 /// <summary>
300 /// Stop all the scripts in this prim. 295 /// Stop and remove all the scripts in this prim.
301 /// </summary> 296 /// </summary>
302 /// <param name="sceneObjectBeingDeleted"> 297 /// <param name="sceneObjectBeingDeleted">
303 /// Should be true if these scripts are being removed because the scene 298 /// Should be true if these scripts are being removed because the scene
@@ -305,26 +300,28 @@ namespace OpenSim.Region.Framework.Scenes
305 /// </param> 300 /// </param>
306 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 301 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
307 { 302 {
308 Items.LockItemsForRead(true); 303 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL);
309 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 304 foreach (TaskInventoryItem item in scripts)
310 Items.LockItemsForRead(false);
311
312 foreach (TaskInventoryItem item in items)
313 { 305 {
314 if ((int)InventoryType.LSL == item.InvType) 306 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
315 { 307 m_part.RemoveScriptEvents(item.ItemID);
316 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
317 m_part.RemoveScriptEvents(item.ItemID);
318 }
319 } 308 }
320 } 309 }
321 310
322 /// <summary> 311 /// <summary>
312 /// Stop all the scripts in this prim.
313 /// </summary>
314 public void StopScriptInstances()
315 {
316 GetInventoryItems(InventoryType.LSL).ForEach(i => StopScriptInstance(i));
317 }
318
319 /// <summary>
323 /// Start a script which is in this prim's inventory. 320 /// Start a script which is in this prim's inventory.
324 /// </summary> 321 /// </summary>
325 /// <param name="item"></param> 322 /// <param name="item"></param>
326 /// <returns></returns> 323 /// <returns>true if the script instance was created, false otherwise</returns>
327 public void CreateScriptInstance(TaskInventoryItem item, int startParam, bool postOnRez, string engine, int stateSource) 324 public bool CreateScriptInstance(TaskInventoryItem item, int startParam, bool postOnRez, string engine, int stateSource)
328 { 325 {
329// m_log.DebugFormat("[PRIM INVENTORY]: Starting script {0} {1} in prim {2} {3} in {4}", 326// m_log.DebugFormat("[PRIM INVENTORY]: Starting script {0} {1} in prim {2} {3} in {4}",
330// item.Name, item.ItemID, m_part.Name, m_part.UUID, m_part.ParentGroup.Scene.RegionInfo.RegionName); 327// item.Name, item.ItemID, m_part.Name, m_part.UUID, m_part.ParentGroup.Scene.RegionInfo.RegionName);
@@ -332,61 +329,70 @@ namespace OpenSim.Region.Framework.Scenes
332 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) 329 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID))
333 { 330 {
334 StoreScriptError(item.ItemID, "no permission"); 331 StoreScriptError(item.ItemID, "no permission");
335 return; 332 return false;
336 } 333 }
337 334
338 m_part.AddFlag(PrimFlags.Scripted); 335 m_part.AddFlag(PrimFlags.Scripted);
339 336
340 if (!m_part.ParentGroup.Scene.RegionInfo.RegionSettings.DisableScripts) 337 if (m_part.ParentGroup.Scene.RegionInfo.RegionSettings.DisableScripts)
338 return false;
339
340 if (stateSource == 2 && // Prim crossing
341 m_part.ParentGroup.Scene.m_trustBinaries)
341 { 342 {
342 if (stateSource == 2 && // Prim crossing 343 m_items.LockItemsForWrite(true);
343 m_part.ParentGroup.Scene.m_trustBinaries) 344 m_items[item.ItemID].PermsMask = 0;
344 { 345 m_items[item.ItemID].PermsGranter = UUID.Zero;
345 m_items.LockItemsForWrite(true); 346 m_items.LockItemsForWrite(false);
346 m_items[item.ItemID].PermsMask = 0; 347 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
347 m_items[item.ItemID].PermsGranter = UUID.Zero; 348 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
348 m_items.LockItemsForWrite(false); 349 StoreScriptErrors(item.ItemID, null);
349 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 350 m_part.ParentGroup.AddActiveScriptCount(1);
350 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 351 m_part.ScheduleFullUpdate();
351 StoreScriptErrors(item.ItemID, null); 352 return true;
352 m_part.ParentGroup.AddActiveScriptCount(1); 353 }
353 m_part.ScheduleFullUpdate();
354 return;
355 }
356 354
357 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 355 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
358 if (null == asset) 356 if (null == asset)
359 { 357 {
360 string msg = String.Format("asset ID {0} could not be found", item.AssetID); 358 m_log.ErrorFormat(
361 StoreScriptError(item.ItemID, msg); 359 "[PRIM INVENTORY]: Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
362 m_log.ErrorFormat( 360 item.Name, item.ItemID, m_part.AbsolutePosition,
361 m_part.ParentGroup.Scene.RegionInfo.RegionName, item.AssetID);
362
363 return false;
364 }
365 else
366 {
367 if (m_part.ParentGroup.m_savedScriptState != null)
368 item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID);
369
370 string msg = String.Format("asset ID {0} could not be found", item.AssetID);
371 StoreScriptError(item.ItemID, msg);
372 m_log.ErrorFormat(
363 "[PRIM INVENTORY]: Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", 373 "[PRIM INVENTORY]: Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
364 item.Name, item.ItemID, m_part.AbsolutePosition, 374 item.Name, item.ItemID, m_part.AbsolutePosition,
365 m_part.ParentGroup.Scene.RegionInfo.RegionName, item.AssetID); 375 m_part.ParentGroup.Scene.RegionInfo.RegionName, item.AssetID);
366 }
367 else
368 {
369 if (m_part.ParentGroup.m_savedScriptState != null)
370 item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID);
371 376
372 m_items.LockItemsForWrite(true); 377 m_items.LockItemsForWrite(true);
373 378
374 m_items[item.ItemID].OldItemID = item.OldItemID; 379 m_items[item.ItemID].OldItemID = item.OldItemID;
375 m_items[item.ItemID].PermsMask = 0; 380 m_items[item.ItemID].PermsMask = 0;
376 m_items[item.ItemID].PermsGranter = UUID.Zero; 381 m_items[item.ItemID].PermsGranter = UUID.Zero;
377 382
378 m_items.LockItemsForWrite(false); 383 m_items.LockItemsForWrite(false);
379 384
380 string script = Utils.BytesToString(asset.Data); 385 string script = Utils.BytesToString(asset.Data);
381 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 386 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
382 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 387 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
383 StoreScriptErrors(item.ItemID, null); 388 StoreScriptErrors(item.ItemID, null);
384 if (!item.ScriptRunning) 389 if (!item.ScriptRunning)
385 m_part.ParentGroup.Scene.EventManager.TriggerStopScript( 390 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(
386 m_part.LocalId, item.ItemID); 391 m_part.LocalId, item.ItemID);
387 m_part.ParentGroup.AddActiveScriptCount(1); 392 m_part.ParentGroup.AddActiveScriptCount(1);
388 m_part.ScheduleFullUpdate(); 393 m_part.ScheduleFullUpdate();
389 } 394
395 return true;
390 } 396 }
391 } 397 }
392 398
@@ -459,7 +465,7 @@ namespace OpenSim.Region.Framework.Scenes
459 /// <param name="itemId"> 465 /// <param name="itemId">
460 /// A <see cref="UUID"/> 466 /// A <see cref="UUID"/>
461 /// </param> 467 /// </param>
462 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 468 public bool CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
463 { 469 {
464 lock (m_scriptErrors) 470 lock (m_scriptErrors)
465 { 471 {
@@ -467,6 +473,7 @@ namespace OpenSim.Region.Framework.Scenes
467 m_scriptErrors.Remove(itemId); 473 m_scriptErrors.Remove(itemId);
468 } 474 }
469 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource); 475 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
476 return true;
470 } 477 }
471 478
472 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 479 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
@@ -597,7 +604,7 @@ namespace OpenSim.Region.Framework.Scenes
597 } 604 }
598 605
599 /// <summary> 606 /// <summary>
600 /// Stop a script which is in this prim's inventory. 607 /// Stop and remove a script which is in this prim's inventory.
601 /// </summary> 608 /// </summary>
602 /// <param name="itemId"></param> 609 /// <param name="itemId"></param>
603 /// <param name="sceneObjectBeingDeleted"> 610 /// <param name="sceneObjectBeingDeleted">
@@ -616,7 +623,7 @@ namespace OpenSim.Region.Framework.Scenes
616 } 623 }
617 else 624 else
618 { 625 {
619 m_log.ErrorFormat( 626 m_log.WarnFormat(
620 "[PRIM INVENTORY]: " + 627 "[PRIM INVENTORY]: " +
621 "Couldn't stop script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 628 "Couldn't stop script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}",
622 itemId, m_part.Name, m_part.UUID, 629 itemId, m_part.Name, m_part.UUID,
@@ -625,6 +632,51 @@ namespace OpenSim.Region.Framework.Scenes
625 } 632 }
626 633
627 /// <summary> 634 /// <summary>
635 /// Stop a script which is in this prim's inventory.
636 /// </summary>
637 /// <param name="itemId"></param>
638 /// <param name="sceneObjectBeingDeleted">
639 /// Should be true if this script is being removed because the scene
640 /// object is being deleted. This will prevent spurious updates to the client.
641 /// </param>
642 public void StopScriptInstance(UUID itemId)
643 {
644 TaskInventoryItem scriptItem;
645
646 lock (m_items)
647 m_items.TryGetValue(itemId, out scriptItem);
648
649 if (scriptItem != null)
650 {
651 StopScriptInstance(scriptItem);
652 }
653 else
654 {
655 m_log.WarnFormat(
656 "[PRIM INVENTORY]: " +
657 "Couldn't stop script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}",
658 itemId, m_part.Name, m_part.UUID,
659 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
660 }
661 }
662
663 /// <summary>
664 /// Stop a script which is in this prim's inventory.
665 /// </summary>
666 /// <param name="itemId"></param>
667 /// <param name="sceneObjectBeingDeleted">
668 /// Should be true if this script is being removed because the scene
669 /// object is being deleted. This will prevent spurious updates to the client.
670 /// </param>
671 public void StopScriptInstance(TaskInventoryItem item)
672 {
673 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(m_part.LocalId, item.ItemID);
674
675 // At the moment, even stopped scripts are counted as active, which is probably wrong.
676// m_part.ParentGroup.AddActiveScriptCount(-1);
677 }
678
679 /// <summary>
628 /// Check if the inventory holds an item with a given name. 680 /// Check if the inventory holds an item with a given name.
629 /// </summary> 681 /// </summary>
630 /// <param name="name"></param> 682 /// <param name="name"></param>
@@ -770,14 +822,22 @@ namespace OpenSim.Region.Framework.Scenes
770 return item; 822 return item;
771 } 823 }
772 824
773 /// <summary> 825 public TaskInventoryItem GetInventoryItem(string name)
774 /// Get inventory items by name. 826 {
775 /// </summary> 827 m_items.LockItemsForRead(true);
776 /// <param name="name"></param> 828 foreach (TaskInventoryItem item in m_items.Values)
777 /// <returns> 829 {
778 /// A list of inventory items with that name. 830 if (item.Name == name)
779 /// If no inventory item has that name then an empty list is returned. 831 {
780 /// </returns> 832 m_items.LockItemsForRead(false);
833 return item;
834 }
835 }
836 m_items.LockItemsForRead(false);
837
838 return null;
839 }
840
781 public List<TaskInventoryItem> GetInventoryItems(string name) 841 public List<TaskInventoryItem> GetInventoryItems(string name)
782 { 842 {
783 List<TaskInventoryItem> items = new List<TaskInventoryItem>(); 843 List<TaskInventoryItem> items = new List<TaskInventoryItem>();
@@ -1247,10 +1307,10 @@ namespace OpenSim.Region.Framework.Scenes
1247 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0) 1307 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1248 item.CurrentPermissions &= ~(uint)PermissionMask.Modify; 1308 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1249 } 1309 }
1250 item.OwnerChanged = true;
1251 item.CurrentPermissions &= item.NextPermissions; 1310 item.CurrentPermissions &= item.NextPermissions;
1252 item.BasePermissions &= item.NextPermissions; 1311 item.BasePermissions &= item.NextPermissions;
1253 item.EveryonePermissions &= item.NextPermissions; 1312 item.EveryonePermissions &= item.NextPermissions;
1313 item.OwnerChanged = true;
1254 item.PermsMask = 0; 1314 item.PermsMask = 0;
1255 item.PermsGranter = UUID.Zero; 1315 item.PermsGranter = UUID.Zero;
1256 } 1316 }
@@ -1281,9 +1341,57 @@ namespace OpenSim.Region.Framework.Scenes
1281 return true; 1341 return true;
1282 } 1342 }
1283 } 1343 }
1344
1284 return false; 1345 return false;
1285 } 1346 }
1286 1347
1348 /// <summary>
1349 /// Returns the count of scripts in this parts inventory.
1350 /// </summary>
1351 /// <returns></returns>
1352 public int ScriptCount()
1353 {
1354 int count = 0;
1355 Items.LockItemsForRead(true);
1356 foreach (TaskInventoryItem item in m_items.Values)
1357 {
1358 if (item.InvType == (int)InventoryType.LSL)
1359 {
1360 count++;
1361 }
1362 }
1363 Items.LockItemsForRead(false);
1364 return count;
1365 }
1366 /// <summary>
1367 /// Returns the count of running scripts in this parts inventory.
1368 /// </summary>
1369 /// <returns></returns>
1370 public int RunningScriptCount()
1371 {
1372 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
1373 if (engines.Length == 0)
1374 return 0;
1375
1376 int count = 0;
1377 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL);
1378
1379 foreach (TaskInventoryItem item in scripts)
1380 {
1381 foreach (IScriptModule engine in engines)
1382 {
1383 if (engine != null)
1384 {
1385 if (engine.GetScriptState(item.ItemID))
1386 {
1387 count++;
1388 }
1389 }
1390 }
1391 }
1392 return count;
1393 }
1394
1287 public List<UUID> GetInventoryList() 1395 public List<UUID> GetInventoryList()
1288 { 1396 {
1289 List<UUID> ret = new List<UUID>(); 1397 List<UUID> ret = new List<UUID>();
@@ -1298,22 +1406,24 @@ namespace OpenSim.Region.Framework.Scenes
1298 { 1406 {
1299 List<TaskInventoryItem> ret = new List<TaskInventoryItem>(); 1407 List<TaskInventoryItem> ret = new List<TaskInventoryItem>();
1300 1408
1301 lock (m_items) 1409 Items.LockItemsForRead(true);
1302 ret = new List<TaskInventoryItem>(m_items.Values); 1410 ret = new List<TaskInventoryItem>(m_items.Values);
1411 Items.LockItemsForRead(false);
1303 1412
1304 return ret; 1413 return ret;
1305 } 1414 }
1306 1415
1307 public List<TaskInventoryItem> GetInventoryScripts() 1416 public List<TaskInventoryItem> GetInventoryItems(InventoryType type)
1308 { 1417 {
1309 List<TaskInventoryItem> ret = new List<TaskInventoryItem>(); 1418 List<TaskInventoryItem> ret = new List<TaskInventoryItem>();
1310 1419
1311 lock (m_items) 1420 Items.LockItemsForRead(true);
1312 { 1421
1313 foreach (TaskInventoryItem item in m_items.Values) 1422 foreach (TaskInventoryItem item in m_items.Values)
1314 if (item.InvType == (int)InventoryType.LSL) 1423 if (item.InvType == (int)type)
1315 ret.Add(item); 1424 ret.Add(item);
1316 } 1425
1426 Items.LockItemsForRead(false);
1317 1427
1318 return ret; 1428 return ret;
1319 } 1429 }
@@ -1335,35 +1445,36 @@ namespace OpenSim.Region.Framework.Scenes
1335 if (engines.Length == 0) // No engine at all 1445 if (engines.Length == 0) // No engine at all
1336 return ret; 1446 return ret;
1337 1447
1338 Items.LockItemsForRead(true); 1448 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL);
1339 foreach (TaskInventoryItem item in m_items.Values) 1449
1450 foreach (TaskInventoryItem item in scripts)
1340 { 1451 {
1341 if (item.InvType == (int)InventoryType.LSL) 1452 foreach (IScriptModule e in engines)
1342 { 1453 {
1343 foreach (IScriptModule e in engines) 1454 if (e != null)
1344 { 1455 {
1345 if (e != null) 1456// m_log.DebugFormat(
1457// "[PRIM INVENTORY]: Getting script state from engine {0} for {1} in part {2} in group {3} in {4}",
1458// e.Name, item.Name, m_part.Name, m_part.ParentGroup.Name, m_part.ParentGroup.Scene.Name);
1459
1460 string n = e.GetXMLState(item.ItemID);
1461 if (n != String.Empty)
1346 { 1462 {
1347 string n = e.GetXMLState(item.ItemID); 1463 if (oldIDs)
1348 if (n != String.Empty) 1464 {
1465 if (!ret.ContainsKey(item.OldItemID))
1466 ret[item.OldItemID] = n;
1467 }
1468 else
1349 { 1469 {
1350 if (oldIDs) 1470 if (!ret.ContainsKey(item.ItemID))
1351 { 1471 ret[item.ItemID] = n;
1352 if (!ret.ContainsKey(item.OldItemID))
1353 ret[item.OldItemID] = n;
1354 }
1355 else
1356 {
1357 if (!ret.ContainsKey(item.ItemID))
1358 ret[item.ItemID] = n;
1359 }
1360 break;
1361 } 1472 }
1473 break;
1362 } 1474 }
1363 } 1475 }
1364 } 1476 }
1365 } 1477 }
1366 Items.LockItemsForRead(false);
1367 return ret; 1478 return ret;
1368 } 1479 }
1369 1480
@@ -1373,27 +1484,27 @@ namespace OpenSim.Region.Framework.Scenes
1373 if (engines.Length == 0) 1484 if (engines.Length == 0)
1374 return; 1485 return;
1375 1486
1487 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL);
1376 1488
1377 Items.LockItemsForRead(true); 1489 foreach (TaskInventoryItem item in scripts)
1378
1379 foreach (TaskInventoryItem item in m_items.Values)
1380 { 1490 {
1381 if (item.InvType == (int)InventoryType.LSL) 1491 foreach (IScriptModule engine in engines)
1382 { 1492 {
1383 foreach (IScriptModule engine in engines) 1493 if (engine != null)
1384 { 1494 {
1385 if (engine != null) 1495// m_log.DebugFormat(
1386 { 1496// "[PRIM INVENTORY]: Resuming script {0} {1} for {2}, OwnerChanged {3}",
1387 if (item.OwnerChanged) 1497// item.Name, item.ItemID, item.OwnerID, item.OwnerChanged);
1388 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER }); 1498
1389 item.OwnerChanged = false; 1499 engine.ResumeScript(item.ItemID);
1390 engine.ResumeScript(item.ItemID); 1500
1391 } 1501 if (item.OwnerChanged)
1502 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER });
1503
1504 item.OwnerChanged = false;
1392 } 1505 }
1393 } 1506 }
1394 } 1507 }
1395
1396 Items.LockItemsForRead(false);
1397 } 1508 }
1398 } 1509 }
1399} 1510}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 4940063..e27d309 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -45,6 +45,7 @@ using TeleportFlags = OpenSim.Framework.Constants.TeleportFlags;
45 45
46namespace OpenSim.Region.Framework.Scenes 46namespace OpenSim.Region.Framework.Scenes
47{ 47{
48 [Flags]
48 enum ScriptControlled : uint 49 enum ScriptControlled : uint
49 { 50 {
50 CONTROL_ZERO = 0, 51 CONTROL_ZERO = 0,
@@ -76,6 +77,11 @@ namespace OpenSim.Region.Framework.Scenes
76// { 77// {
77// m_log.Debug("[SCENE PRESENCE] Destructor called"); 78// m_log.Debug("[SCENE PRESENCE] Destructor called");
78// } 79// }
80 private void TriggerScenePresenceUpdated()
81 {
82 if (m_scene != null)
83 m_scene.EventManager.TriggerScenePresenceUpdated(this);
84 }
79 85
80 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 86 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
81 87
@@ -497,6 +503,7 @@ namespace OpenSim.Region.Framework.Scenes
497 //m_log.DebugFormat( 503 //m_log.DebugFormat(
498 // "[ENTITY BASE]: In {0} set AbsolutePosition of {1} to {2}", 504 // "[ENTITY BASE]: In {0} set AbsolutePosition of {1} to {2}",
499 // Scene.RegionInfo.RegionName, Name, m_pos); 505 // Scene.RegionInfo.RegionName, Name, m_pos);
506 TriggerScenePresenceUpdated();
500 } 507 }
501 } 508 }
502 509
@@ -516,6 +523,7 @@ namespace OpenSim.Region.Framework.Scenes
516 return; 523 return;
517 524
518 m_pos = value; 525 m_pos = value;
526 TriggerScenePresenceUpdated();
519 } 527 }
520 } 528 }
521 529
@@ -586,6 +594,12 @@ namespace OpenSim.Region.Framework.Scenes
586 private UUID m_parentUUID = UUID.Zero; 594 private UUID m_parentUUID = UUID.Zero;
587 595
588 /// <summary> 596 /// <summary>
597 /// Are we sitting on an object?
598 /// </summary>
599 /// <remarks>A more readable way of testing presence sit status than ParentID == 0</remarks>
600 public bool IsSatOnObject { get { return ParentID != 0; } }
601
602 /// <summary>
589 /// If the avatar is sitting, the prim that it's sitting on. If not sitting then null. 603 /// If the avatar is sitting, the prim that it's sitting on. If not sitting then null.
590 /// </summary> 604 /// </summary>
591 /// <remarks> 605 /// <remarks>
@@ -1087,23 +1101,13 @@ namespace OpenSim.Region.Framework.Scenes
1087 /// <param name="pos"></param> 1101 /// <param name="pos"></param>
1088 public void Teleport(Vector3 pos) 1102 public void Teleport(Vector3 pos)
1089 { 1103 {
1090 bool isFlying = Flying; 1104 TeleportWithMomentum(pos, Vector3.Zero);
1091 RemoveFromPhysicalScene();
1092 Velocity = Vector3.Zero;
1093 CheckLandingPoint(ref pos);
1094 AbsolutePosition = pos;
1095 AddToPhysicalScene(isFlying);
1096
1097 SendTerseUpdateToAllClients();
1098 }
1099
1100 public void TeleportWithMomentum(Vector3 pos)
1101 {
1102 TeleportWithMomentum(pos, null);
1103 } 1105 }
1104 1106
1105 public void TeleportWithMomentum(Vector3 pos, Vector3? v) 1107 public void TeleportWithMomentum(Vector3 pos, Vector3? v)
1106 { 1108 {
1109 if (ParentID != (uint)0)
1110 StandUp();
1107 bool isFlying = Flying; 1111 bool isFlying = Flying;
1108 Vector3 vel = Velocity; 1112 Vector3 vel = Velocity;
1109 RemoveFromPhysicalScene(); 1113 RemoveFromPhysicalScene();
@@ -1283,17 +1287,33 @@ namespace OpenSim.Region.Framework.Scenes
1283 1287
1284 bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); 1288 bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
1285 MakeRootAgent(AbsolutePosition, flying); 1289 MakeRootAgent(AbsolutePosition, flying);
1290 ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look);
1291
1292// m_log.DebugFormat("[SCENE PRESENCE] Completed movement");
1286 1293
1287 if ((m_callbackURI != null) && !m_callbackURI.Equals("")) 1294 if ((m_callbackURI != null) && !m_callbackURI.Equals(""))
1288 { 1295 {
1289 m_log.DebugFormat("[SCENE PRESENCE]: Releasing agent in URI {0}", m_callbackURI); 1296 // We cannot sleep here since this would hold up the inbound packet processing thread, as
1297 // CompleteMovement() is executed synchronously. However, it might be better to delay the release
1298 // here until we know for sure that the agent is active in this region. Sending AgentMovementComplete
1299 // is not enough for Imprudence clients - there appears to be a small delay (<200ms, <500ms) until they regard this
1300 // region as the current region, meaning that a close sent before then will fail the teleport.
1301// System.Threading.Thread.Sleep(2000);
1302
1303 m_log.DebugFormat(
1304 "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}",
1305 client.Name, client.AgentId, m_callbackURI);
1306
1290 Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI); 1307 Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI);
1291 m_callbackURI = null; 1308 m_callbackURI = null;
1292 } 1309 }
1310// else
1311// {
1312// m_log.DebugFormat(
1313// "[SCENE PRESENCE]: No callback provided on CompleteMovement of {0} {1} to {2}",
1314// client.Name, client.AgentId, m_scene.RegionInfo.RegionName);
1315// }
1293 1316
1294// m_log.DebugFormat("[SCENE PRESENCE] Completed movement");
1295
1296 ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look);
1297 ValidateAndSendAppearanceAndAgentData(); 1317 ValidateAndSendAppearanceAndAgentData();
1298 1318
1299 // Create child agents in neighbouring regions 1319 // Create child agents in neighbouring regions
@@ -1308,7 +1328,6 @@ namespace OpenSim.Region.Framework.Scenes
1308 friendsModule.SendFriendsOnlineIfNeeded(ControllingClient); 1328 friendsModule.SendFriendsOnlineIfNeeded(ControllingClient);
1309 } 1329 }
1310 1330
1311
1312// m_log.DebugFormat( 1331// m_log.DebugFormat(
1313// "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms", 1332// "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms",
1314// client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds); 1333// client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds);
@@ -1361,7 +1380,7 @@ namespace OpenSim.Region.Framework.Scenes
1361 { 1380 {
1362// m_log.DebugFormat( 1381// m_log.DebugFormat(
1363// "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}", 1382// "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}",
1364// Scene.RegionInfo.RegionName, remoteClient.Name, agentData.ControlFlags); 1383// Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags);
1365 1384
1366 if (IsChildAgent) 1385 if (IsChildAgent)
1367 { 1386 {
@@ -1471,14 +1490,8 @@ namespace OpenSim.Region.Framework.Scenes
1471 } 1490 }
1472 } 1491 }
1473 1492
1474 lock (scriptedcontrols) 1493 uint flagsForScripts = (uint)flags;
1475 { 1494 flags = RemoveIgnoredControls(flags, IgnoredControls);
1476 if (scriptedcontrols.Count > 0)
1477 {
1478 SendControlToScripts((uint)flags);
1479 flags = RemoveIgnoredControls(flags, IgnoredControls);
1480 }
1481 }
1482 1495
1483 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) 1496 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
1484 HandleAgentSitOnGround(); 1497 HandleAgentSitOnGround();
@@ -1492,6 +1505,7 @@ namespace OpenSim.Region.Framework.Scenes
1492 PhysicsActor actor = PhysicsActor; 1505 PhysicsActor actor = PhysicsActor;
1493 if (actor == null) 1506 if (actor == null)
1494 { 1507 {
1508 SendControlsToScripts(flagsForScripts);
1495 return; 1509 return;
1496 } 1510 }
1497 1511
@@ -1571,7 +1585,7 @@ namespace OpenSim.Region.Framework.Scenes
1571 MovementFlag |= (byte)nudgehack; 1585 MovementFlag |= (byte)nudgehack;
1572 } 1586 }
1573 1587
1574// m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF); 1588 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF);
1575 MovementFlag += (byte)(uint)DCF; 1589 MovementFlag += (byte)(uint)DCF;
1576 update_movementflag = true; 1590 update_movementflag = true;
1577 } 1591 }
@@ -1584,7 +1598,7 @@ namespace OpenSim.Region.Framework.Scenes
1584 && ((MovementFlag & (byte)nudgehack) == nudgehack)) 1598 && ((MovementFlag & (byte)nudgehack) == nudgehack))
1585 ) // This or is for Nudge forward 1599 ) // This or is for Nudge forward
1586 { 1600 {
1587// m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF); 1601 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF);
1588 MovementFlag -= ((byte)(uint)DCF); 1602 MovementFlag -= ((byte)(uint)DCF);
1589 update_movementflag = true; 1603 update_movementflag = true;
1590 1604
@@ -1665,11 +1679,14 @@ namespace OpenSim.Region.Framework.Scenes
1665// } 1679// }
1666// } 1680// }
1667 1681
1668// if (update_movementflag && ParentID == 0) 1682 if (update_movementflag && ParentID == 0)
1669// Animator.UpdateMovementAnimations(); 1683 Animator.UpdateMovementAnimations();
1684
1685 SendControlsToScripts(flagsForScripts);
1670 } 1686 }
1671 1687
1672 m_scene.EventManager.TriggerOnClientMovement(this); 1688 m_scene.EventManager.TriggerOnClientMovement(this);
1689 TriggerScenePresenceUpdated();
1673 } 1690 }
1674 1691
1675 /// <summary> 1692 /// <summary>
@@ -1929,10 +1946,6 @@ namespace OpenSim.Region.Framework.Scenes
1929 } 1946 }
1930 } 1947 }
1931 1948
1932 // Reset sit target.
1933 if (part.SitTargetAvatar == UUID)
1934 part.SitTargetAvatar = UUID.Zero;
1935
1936 part.ParentGroup.DeleteAvatar(UUID); 1949 part.ParentGroup.DeleteAvatar(UUID);
1937// ParentPosition = part.GetWorldPosition(); 1950// ParentPosition = part.GetWorldPosition();
1938 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1951 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
@@ -1950,6 +1963,8 @@ namespace OpenSim.Region.Framework.Scenes
1950 SendAvatarDataToAllAgents(); 1963 SendAvatarDataToAllAgents();
1951 m_requestedSitTargetID = 0; 1964 m_requestedSitTargetID = 0;
1952 1965
1966 part.RemoveSittingAvatar(UUID);
1967
1953 if (part != null) 1968 if (part != null)
1954 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 1969 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
1955 } 1970 }
@@ -1983,15 +1998,7 @@ namespace OpenSim.Region.Framework.Scenes
1983 //look for prims with explicit sit targets that are available 1998 //look for prims with explicit sit targets that are available
1984 foreach (SceneObjectPart part in partArray) 1999 foreach (SceneObjectPart part in partArray)
1985 { 2000 {
1986 // Is a sit target available? 2001 if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero)
1987 Vector3 avSitOffset = part.SitTargetPosition;
1988 Quaternion avSitOrientation = part.SitTargetOrientation;
1989 UUID avOnTargetAlready = part.SitTargetAvatar;
1990
1991 bool SitTargetUnOccupied = avOnTargetAlready == UUID.Zero;
1992 bool SitTargetisSet = avSitOffset != Vector3.Zero || avSitOrientation != Quaternion.Identity;
1993
1994 if (SitTargetisSet && SitTargetUnOccupied)
1995 { 2002 {
1996 //switch the target to this prim 2003 //switch the target to this prim
1997 return part; 2004 return part;
@@ -2002,10 +2009,8 @@ namespace OpenSim.Region.Framework.Scenes
2002 return targetPart; 2009 return targetPart;
2003 } 2010 }
2004 2011
2005 private void SendSitResponse(UUID targetID, Vector3 offset, Quaternion pSitOrientation) 2012 private void SendSitResponse(UUID targetID, Vector3 offset, Quaternion sitOrientation)
2006 { 2013 {
2007 Vector3 pos = new Vector3();
2008 Quaternion sitOrientation = pSitOrientation;
2009 Vector3 cameraEyeOffset = Vector3.Zero; 2014 Vector3 cameraEyeOffset = Vector3.Zero;
2010 Vector3 cameraAtOffset = Vector3.Zero; 2015 Vector3 cameraAtOffset = Vector3.Zero;
2011 bool forceMouselook = false; 2016 bool forceMouselook = false;
@@ -2017,54 +2022,39 @@ namespace OpenSim.Region.Framework.Scenes
2017 // TODO: determine position to sit at based on scene geometry; don't trust offset from client 2022 // TODO: determine position to sit at based on scene geometry; don't trust offset from client
2018 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it 2023 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
2019 2024
2020 // Is a sit target available?
2021 Vector3 avSitOffSet = part.SitTargetPosition;
2022 Quaternion avSitOrientation = part.SitTargetOrientation;
2023 UUID avOnTargetAlready = part.SitTargetAvatar;
2024
2025 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero));
2026 bool SitTargetisSet =
2027 (!(avSitOffSet == Vector3.Zero &&
2028 (
2029 avSitOrientation == Quaternion.Identity // Valid Zero Rotation quaternion
2030 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f && avSitOrientation.W == 0f // W-Z Mapping was invalid at one point
2031 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 0f // Invalid Quaternion
2032 )
2033 ));
2034
2035// m_log.DebugFormat("[SCENE PRESENCE]: {0} {1}", SitTargetisSet, SitTargetUnOccupied);
2036
2037 if (PhysicsActor != null) 2025 if (PhysicsActor != null)
2038 m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f; 2026 m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f;
2039 2027
2040 bool canSit = false; 2028 bool canSit = false;
2041 pos = part.AbsolutePosition + offset; 2029 Vector3 pos = part.AbsolutePosition + offset;
2042 2030
2043 if (SitTargetisSet) 2031 if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero)
2044 { 2032 {
2045 if (SitTargetUnOccupied) 2033// m_log.DebugFormat(
2046 { 2034// "[SCENE PRESENCE]: Sitting {0} on {1} {2} because sit target is set and unoccupied",
2047 m_log.DebugFormat( 2035// Name, part.Name, part.LocalId);
2048 "[SCENE PRESENCE]: Sitting {0} on {1} {2} because sit target is set and unoccupied",
2049 Name, part.Name, part.LocalId);
2050 2036
2051 part.SitTargetAvatar = UUID; 2037 offset = part.SitTargetPosition;
2052 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); 2038 sitOrientation = part.SitTargetOrientation;
2053 sitOrientation = avSitOrientation; 2039 canSit = true;
2054 canSit = true;
2055 }
2056 } 2040 }
2057 else 2041 else
2058 { 2042 {
2059 if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10) 2043 if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10)
2060 { 2044 {
2061 m_log.DebugFormat( 2045// m_log.DebugFormat(
2062 "[SCENE PRESENCE]: Sitting {0} on {1} {2} because sit target is unset and within 10m", 2046// "[SCENE PRESENCE]: Sitting {0} on {1} {2} because sit target is unset and within 10m",
2063 Name, part.Name, part.LocalId); 2047// Name, part.Name, part.LocalId);
2064 2048
2065 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); 2049 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight);
2066 canSit = true; 2050 canSit = true;
2067 } 2051 }
2052// else
2053// {
2054// m_log.DebugFormat(
2055// "[SCENE PRESENCE]: Ignoring sit request of {0} on {1} {2} because sit target is unset and outside 10m",
2056// Name, part.Name, part.LocalId);
2057// }
2068 } 2058 }
2069 2059
2070 if (canSit) 2060 if (canSit)
@@ -2075,6 +2065,8 @@ namespace OpenSim.Region.Framework.Scenes
2075 RemoveFromPhysicalScene(); 2065 RemoveFromPhysicalScene();
2076 } 2066 }
2077 2067
2068 part.AddSittingAvatar(UUID);
2069
2078 cameraAtOffset = part.GetCameraAtOffset(); 2070 cameraAtOffset = part.GetCameraAtOffset();
2079 cameraEyeOffset = part.GetCameraEyeOffset(); 2071 cameraEyeOffset = part.GetCameraEyeOffset();
2080 forceMouselook = part.GetForceMouselook(); 2072 forceMouselook = part.GetForceMouselook();
@@ -2351,6 +2343,15 @@ namespace OpenSim.Region.Framework.Scenes
2351 2343
2352 if (part != null) 2344 if (part != null)
2353 { 2345 {
2346 if (part.ParentGroup.IsAttachment)
2347 {
2348 m_log.WarnFormat(
2349 "[SCENE PRESENCE]: Avatar {0} tried to sit on part {1} from object {2} in {3} but this is an attachment for avatar id {4}",
2350 Name, part.Name, part.ParentGroup.Name, Scene.Name, part.ParentGroup.AttachedAvatar);
2351
2352 return;
2353 }
2354
2354 if (part.SitTargetAvatar == UUID) 2355 if (part.SitTargetAvatar == UUID)
2355 { 2356 {
2356 Vector3 sitTargetPos = part.SitTargetPosition; 2357 Vector3 sitTargetPos = part.SitTargetPosition;
@@ -2616,6 +2617,7 @@ namespace OpenSim.Region.Framework.Scenes
2616 2617
2617 m_scene.ForEachClient(SendTerseUpdateToClient); 2618 m_scene.ForEachClient(SendTerseUpdateToClient);
2618 } 2619 }
2620 TriggerScenePresenceUpdated();
2619 } 2621 }
2620 2622
2621 public void SendCoarseLocations(List<Vector3> coarseLocations, List<UUID> avatarUUIDs) 2623 public void SendCoarseLocations(List<Vector3> coarseLocations, List<UUID> avatarUUIDs)
@@ -2694,7 +2696,7 @@ namespace OpenSim.Region.Framework.Scenes
2694 // If we are using the the cached appearance then send it out to everyone 2696 // If we are using the the cached appearance then send it out to everyone
2695 if (cachedappearance) 2697 if (cachedappearance)
2696 { 2698 {
2697 m_log.DebugFormat("[SCENEPRESENCE]: baked textures are in the cache for {0}", Name); 2699 m_log.DebugFormat("[SCENE PRESENCE]: baked textures are in the cache for {0}", Name);
2698 2700
2699 // If the avatars baked textures are all in the cache, then we have a 2701 // If the avatars baked textures are all in the cache, then we have a
2700 // complete appearance... send it out, if not, then we'll send it when 2702 // complete appearance... send it out, if not, then we'll send it when
@@ -3099,8 +3101,8 @@ namespace OpenSim.Region.Framework.Scenes
3099 x = x / Constants.RegionSize; 3101 x = x / Constants.RegionSize;
3100 y = y / Constants.RegionSize; 3102 y = y / Constants.RegionSize;
3101 3103
3102 //m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX))); 3104// m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX)));
3103 //m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY))); 3105// m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY)));
3104 if (Util.IsOutsideView(DrawDistance, x, newRegionX, y, newRegionY)) 3106 if (Util.IsOutsideView(DrawDistance, x, newRegionX, y, newRegionY))
3105 { 3107 {
3106 byebyeRegions.Add(handle); 3108 byebyeRegions.Add(handle);
@@ -3157,7 +3159,7 @@ namespace OpenSim.Region.Framework.Scenes
3157 3159
3158 public void ChildAgentDataUpdate(AgentData cAgentData) 3160 public void ChildAgentDataUpdate(AgentData cAgentData)
3159 { 3161 {
3160 //m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName); 3162// m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName);
3161 if (!IsChildAgent) 3163 if (!IsChildAgent)
3162 return; 3164 return;
3163 3165
@@ -3269,31 +3271,8 @@ namespace OpenSim.Region.Framework.Scenes
3269 catch { } 3271 catch { }
3270 cAgent.DefaultAnim = Animator.Animations.DefaultAnimation; 3272 cAgent.DefaultAnim = Animator.Animations.DefaultAnimation;
3271 3273
3272 // Attachment objects 3274 if (Scene.AttachmentsModule != null)
3273 List<SceneObjectGroup> attachments = GetAttachments(); 3275 Scene.AttachmentsModule.CopyAttachments(this, cAgent);
3274 if (attachments.Count > 0)
3275 {
3276 cAgent.AttachmentObjects = new List<ISceneObject>();
3277 cAgent.AttachmentObjectStates = new List<string>();
3278// IScriptModule se = m_scene.RequestModuleInterface<IScriptModule>();
3279 InTransitScriptStates.Clear();
3280
3281 foreach (SceneObjectGroup sog in attachments)
3282 {
3283 // We need to make a copy and pass that copy
3284 // because of transfers withn the same sim
3285 ISceneObject clone = sog.CloneForNewScene();
3286 // Attachment module assumes that GroupPosition holds the offsets...!
3287 ((SceneObjectGroup)clone).RootPart.GroupPosition = sog.RootPart.AttachedPos;
3288 ((SceneObjectGroup)clone).IsAttachment = false;
3289 cAgent.AttachmentObjects.Add(clone);
3290 string state = sog.GetStateSnapshot();
3291 cAgent.AttachmentObjectStates.Add(state);
3292 InTransitScriptStates.Add(state);
3293 // Let's remove the scripts of the original object here
3294 sog.RemoveScriptInstances(true);
3295 }
3296 }
3297 } 3276 }
3298 3277
3299 private void CopyFrom(AgentData cAgent) 3278 private void CopyFrom(AgentData cAgent)
@@ -3301,6 +3280,9 @@ namespace OpenSim.Region.Framework.Scenes
3301 m_originRegionID = cAgent.RegionID; 3280 m_originRegionID = cAgent.RegionID;
3302 3281
3303 m_callbackURI = cAgent.CallbackURI; 3282 m_callbackURI = cAgent.CallbackURI;
3283// m_log.DebugFormat(
3284// "[SCENE PRESENCE]: Set callback for {0} in {1} to {2} in CopyFrom()",
3285// Name, m_scene.RegionInfo.RegionName, m_callbackURI);
3304 3286
3305 m_pos = cAgent.Position; 3287 m_pos = cAgent.Position;
3306 m_velocity = cAgent.Velocity; 3288 m_velocity = cAgent.Velocity;
@@ -3365,18 +3347,8 @@ namespace OpenSim.Region.Framework.Scenes
3365 if (cAgent.DefaultAnim != null) 3347 if (cAgent.DefaultAnim != null)
3366 Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero); 3348 Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero);
3367 3349
3368 if (cAgent.AttachmentObjects != null && cAgent.AttachmentObjects.Count > 0) 3350 if (Scene.AttachmentsModule != null)
3369 { 3351 Scene.AttachmentsModule.CopyAttachments(cAgent, this);
3370 m_attachments = new List<SceneObjectGroup>();
3371 int i = 0;
3372 foreach (ISceneObject so in cAgent.AttachmentObjects)
3373 {
3374 ((SceneObjectGroup)so).LocalId = 0;
3375 ((SceneObjectGroup)so).RootPart.ClearUpdateSchedule();
3376 so.SetState(cAgent.AttachmentObjectStates[i++], m_scene);
3377 m_scene.IncomingCreateObject(Vector3.Zero, so);
3378 }
3379 }
3380 } 3352 }
3381 3353
3382 public bool CopyAgent(out IAgentData agent) 3354 public bool CopyAgent(out IAgentData agent)
@@ -3402,6 +3374,7 @@ namespace OpenSim.Region.Framework.Scenes
3402 Velocity = force; 3374 Velocity = force;
3403 3375
3404 m_forceToApply = null; 3376 m_forceToApply = null;
3377 TriggerScenePresenceUpdated();
3405 } 3378 }
3406 } 3379 }
3407 3380
@@ -3509,23 +3482,53 @@ namespace OpenSim.Region.Framework.Scenes
3509 3482
3510 RaiseCollisionScriptEvents(coldata); 3483 RaiseCollisionScriptEvents(coldata);
3511 3484
3512 if (Invulnerable || GodLevel >= 200) 3485 // Gods do not take damage and Invulnerable is set depending on parcel/region flags
3486 if (Invulnerable || GodLevel > 0)
3513 return; 3487 return;
3514 3488
3489 // The following may be better in the ICombatModule
3490 // probably tweaking of the values for ground and normal prim collisions will be needed
3515 float starthealth = Health; 3491 float starthealth = Health;
3516 uint killerObj = 0; 3492 uint killerObj = 0;
3493 SceneObjectPart part = null;
3517 foreach (uint localid in coldata.Keys) 3494 foreach (uint localid in coldata.Keys)
3518 { 3495 {
3519 SceneObjectPart part = Scene.GetSceneObjectPart(localid); 3496 if (localid == 0)
3520 3497 {
3521 if (part != null && part.ParentGroup.Damage != -1.0f) 3498 part = null;
3522 Health -= part.ParentGroup.Damage; 3499 }
3500 else
3501 {
3502 part = Scene.GetSceneObjectPart(localid);
3503 }
3504 if (part != null)
3505 {
3506 // Ignore if it has been deleted or volume detect
3507 if (!part.ParentGroup.IsDeleted && !part.ParentGroup.IsVolumeDetect)
3508 {
3509 if (part.ParentGroup.Damage > 0.0f)
3510 {
3511 // Something with damage...
3512 Health -= part.ParentGroup.Damage;
3513 part.ParentGroup.Scene.DeleteSceneObject(part.ParentGroup, false);
3514 }
3515 else
3516 {
3517 // An ordinary prim
3518 if (coldata[localid].PenetrationDepth >= 0.10f)
3519 Health -= coldata[localid].PenetrationDepth * 5.0f;
3520 }
3521 }
3522 }
3523 else 3523 else
3524 { 3524 {
3525 if (coldata[localid].PenetrationDepth >= 0.10f) 3525 // 0 is the ground
3526 // what about collisions with other avatars?
3527 if (localid == 0 && coldata[localid].PenetrationDepth >= 0.10f)
3526 Health -= coldata[localid].PenetrationDepth * 5.0f; 3528 Health -= coldata[localid].PenetrationDepth * 5.0f;
3527 } 3529 }
3528 3530
3531
3529 if (Health <= 0.0f) 3532 if (Health <= 0.0f)
3530 { 3533 {
3531 if (localid != 0) 3534 if (localid != 0)
@@ -3541,7 +3544,16 @@ namespace OpenSim.Region.Framework.Scenes
3541 ControllingClient.SendHealth(Health); 3544 ControllingClient.SendHealth(Health);
3542 } 3545 }
3543 if (Health <= 0) 3546 if (Health <= 0)
3547 {
3544 m_scene.EventManager.TriggerAvatarKill(killerObj, this); 3548 m_scene.EventManager.TriggerAvatarKill(killerObj, this);
3549 }
3550 if (starthealth == Health && Health < 100.0f)
3551 {
3552 Health += 0.03f;
3553 if (Health > 100.0f)
3554 Health = 100.0f;
3555 ControllingClient.SendHealth(Health);
3556 }
3545 } 3557 }
3546 } 3558 }
3547 3559
@@ -3553,9 +3565,6 @@ namespace OpenSim.Region.Framework.Scenes
3553 3565
3554 public void Close() 3566 public void Close()
3555 { 3567 {
3556 if (!IsChildAgent)
3557 m_scene.AttachmentsModule.DeleteAttachmentsFromScene(this, false);
3558
3559 // Clear known regions 3568 // Clear known regions
3560 KnownRegions = new Dictionary<ulong, string>(); 3569 KnownRegions = new Dictionary<ulong, string>();
3561 3570
@@ -3624,6 +3633,63 @@ namespace OpenSim.Region.Framework.Scenes
3624 return m_attachments.Count > 0; 3633 return m_attachments.Count > 0;
3625 } 3634 }
3626 3635
3636 /// <summary>
3637 /// Returns the total count of scripts in all parts inventories.
3638 /// </summary>
3639 public int ScriptCount()
3640 {
3641 int count = 0;
3642 lock (m_attachments)
3643 {
3644 foreach (SceneObjectGroup gobj in m_attachments)
3645 {
3646 if (gobj != null)
3647 {
3648 count += gobj.ScriptCount();
3649 }
3650 }
3651 }
3652 return count;
3653 }
3654
3655 /// <summary>
3656 /// A float the value is a representative execution time in milliseconds of all scripts in all attachments.
3657 /// </summary>
3658 public float ScriptExecutionTime()
3659 {
3660 float time = 0.0f;
3661 lock (m_attachments)
3662 {
3663 foreach (SceneObjectGroup gobj in m_attachments)
3664 {
3665 if (gobj != null)
3666 {
3667 time += gobj.ScriptExecutionTime();
3668 }
3669 }
3670 }
3671 return time;
3672 }
3673
3674 /// <summary>
3675 /// Returns the total count of running scripts in all parts.
3676 /// </summary>
3677 public int RunningScriptCount()
3678 {
3679 int count = 0;
3680 lock (m_attachments)
3681 {
3682 foreach (SceneObjectGroup gobj in m_attachments)
3683 {
3684 if (gobj != null)
3685 {
3686 count += gobj.RunningScriptCount();
3687 }
3688 }
3689 }
3690 return count;
3691 }
3692
3627 public bool HasScriptedAttachments() 3693 public bool HasScriptedAttachments()
3628 { 3694 {
3629 lock (m_attachments) 3695 lock (m_attachments)
@@ -3841,77 +3907,92 @@ namespace OpenSim.Region.Framework.Scenes
3841 } 3907 }
3842 } 3908 }
3843 3909
3844 internal void SendControlToScripts(uint flags) 3910 private void SendControlsToScripts(uint flags)
3845 { 3911 {
3846 ScriptControlled allflags = ScriptControlled.CONTROL_ZERO; 3912 // Notify the scripts only after calling UpdateMovementAnimations(), so that if a script
3847 3913 // (e.g., a walking script) checks which animation is active it will be the correct animation.
3848 if (MouseDown) 3914 lock (scriptedcontrols)
3849 { 3915 {
3850 allflags = LastCommands & (ScriptControlled.CONTROL_ML_LBUTTON | ScriptControlled.CONTROL_LBUTTON); 3916 if (scriptedcontrols.Count <= 0)
3851 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP) != 0 || (flags & unchecked((uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_UP)) != 0) 3917 return;
3918
3919 ScriptControlled allflags = ScriptControlled.CONTROL_ZERO;
3920
3921 if (MouseDown)
3852 { 3922 {
3853 allflags = ScriptControlled.CONTROL_ZERO; 3923 allflags = LastCommands & (ScriptControlled.CONTROL_ML_LBUTTON | ScriptControlled.CONTROL_LBUTTON);
3924 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP) != 0 || (flags & unchecked((uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_UP)) != 0)
3925 {
3926 allflags = ScriptControlled.CONTROL_ZERO;
3927 MouseDown = true;
3928 }
3929 }
3930
3931 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN) != 0)
3932 {
3933 allflags |= ScriptControlled.CONTROL_ML_LBUTTON;
3854 MouseDown = true; 3934 MouseDown = true;
3855 } 3935 }
3856 } 3936
3937 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0)
3938 {
3939 allflags |= ScriptControlled.CONTROL_LBUTTON;
3940 MouseDown = true;
3941 }
3942
3943 // find all activated controls, whether the scripts are interested in them or not
3944 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) != 0)
3945 {
3946 allflags |= ScriptControlled.CONTROL_FWD;
3947 }
3948
3949 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) != 0)
3950 {
3951 allflags |= ScriptControlled.CONTROL_BACK;
3952 }
3953
3954 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS) != 0)
3955 {
3956 allflags |= ScriptControlled.CONTROL_UP;
3957 }
3958
3959 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)
3960 {
3961 allflags |= ScriptControlled.CONTROL_DOWN;
3962 }
3857 3963
3858 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN) != 0) 3964 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS) != 0)
3859 { 3965 {
3860 allflags |= ScriptControlled.CONTROL_ML_LBUTTON; 3966 allflags |= ScriptControlled.CONTROL_LEFT;
3861 MouseDown = true; 3967 }
3862 } 3968
3863 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0) 3969 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) != 0)
3864 { 3970 {
3865 allflags |= ScriptControlled.CONTROL_LBUTTON; 3971 allflags |= ScriptControlled.CONTROL_RIGHT;
3866 MouseDown = true; 3972 }
3867 } 3973
3974 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
3975 {
3976 allflags |= ScriptControlled.CONTROL_ROT_RIGHT;
3977 }
3978
3979 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
3980 {
3981 allflags |= ScriptControlled.CONTROL_ROT_LEFT;
3982 }
3868 3983
3869 // find all activated controls, whether the scripts are interested in them or not 3984 // optimization; we have to check per script, but if nothing is pressed and nothing changed, we can skip that
3870 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) != 0) 3985 if (allflags != ScriptControlled.CONTROL_ZERO || allflags != LastCommands)
3871 {
3872 allflags |= ScriptControlled.CONTROL_FWD;
3873 }
3874 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) != 0)
3875 {
3876 allflags |= ScriptControlled.CONTROL_BACK;
3877 }
3878 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS) != 0)
3879 {
3880 allflags |= ScriptControlled.CONTROL_UP;
3881 }
3882 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)
3883 {
3884 allflags |= ScriptControlled.CONTROL_DOWN;
3885 }
3886 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS) != 0)
3887 {
3888 allflags |= ScriptControlled.CONTROL_LEFT;
3889 }
3890 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) != 0)
3891 {
3892 allflags |= ScriptControlled.CONTROL_RIGHT;
3893 }
3894 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
3895 {
3896 allflags |= ScriptControlled.CONTROL_ROT_RIGHT;
3897 }
3898 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
3899 {
3900 allflags |= ScriptControlled.CONTROL_ROT_LEFT;
3901 }
3902 // optimization; we have to check per script, but if nothing is pressed and nothing changed, we can skip that
3903 if (allflags != ScriptControlled.CONTROL_ZERO || allflags != LastCommands)
3904 {
3905 lock (scriptedcontrols)
3906 { 3986 {
3907 foreach (KeyValuePair<UUID, ScriptControllers> kvp in scriptedcontrols) 3987 foreach (KeyValuePair<UUID, ScriptControllers> kvp in scriptedcontrols)
3908 { 3988 {
3909 UUID scriptUUID = kvp.Key; 3989 UUID scriptUUID = kvp.Key;
3910 ScriptControllers scriptControlData = kvp.Value; 3990 ScriptControllers scriptControlData = kvp.Value;
3911 3991
3912 ScriptControlled localHeld = allflags & scriptControlData.eventControls; // the flags interesting for us 3992 ScriptControlled localHeld = allflags & scriptControlData.eventControls; // the flags interesting for us
3913 ScriptControlled localLast = LastCommands & scriptControlData.eventControls; // the activated controls in the last cycle 3993 ScriptControlled localLast = LastCommands & scriptControlData.eventControls; // the activated controls in the last cycle
3914 ScriptControlled localChange = localHeld ^ localLast; // the changed bits 3994 ScriptControlled localChange = localHeld ^ localLast; // the changed bits
3995
3915 if (localHeld != ScriptControlled.CONTROL_ZERO || localChange != ScriptControlled.CONTROL_ZERO) 3996 if (localHeld != ScriptControlled.CONTROL_ZERO || localChange != ScriptControlled.CONTROL_ZERO)
3916 { 3997 {
3917 // only send if still pressed or just changed 3998 // only send if still pressed or just changed
@@ -3919,9 +4000,9 @@ namespace OpenSim.Region.Framework.Scenes
3919 } 4000 }
3920 } 4001 }
3921 } 4002 }
4003
4004 LastCommands = allflags;
3922 } 4005 }
3923
3924 LastCommands = allflags;
3925 } 4006 }
3926 4007
3927 internal static AgentManager.ControlFlags RemoveIgnoredControls(AgentManager.ControlFlags flags, ScriptControlled ignored) 4008 internal static AgentManager.ControlFlags RemoveIgnoredControls(AgentManager.ControlFlags flags, ScriptControlled ignored)
@@ -4001,7 +4082,7 @@ namespace OpenSim.Region.Framework.Scenes
4001 land.LandData.UserLocation != Vector3.Zero && 4082 land.LandData.UserLocation != Vector3.Zero &&
4002 land.LandData.OwnerID != m_uuid && 4083 land.LandData.OwnerID != m_uuid &&
4003 (!m_scene.Permissions.IsGod(m_uuid)) && 4084 (!m_scene.Permissions.IsGod(m_uuid)) &&
4004 (!m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid))) 4085 (!m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid)))
4005 { 4086 {
4006 float curr = Vector3.Distance(AbsolutePosition, pos); 4087 float curr = Vector3.Distance(AbsolutePosition, pos);
4007 if (Vector3.Distance(land.LandData.UserLocation, pos) < curr) 4088 if (Vector3.Distance(land.LandData.UserLocation, pos) < curr)
@@ -4015,13 +4096,13 @@ namespace OpenSim.Region.Framework.Scenes
4015 { 4096 {
4016 if ((m_teleportFlags & (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID)) == 4097 if ((m_teleportFlags & (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID)) ==
4017 (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID) || 4098 (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID) ||
4018 (m_teleportFlags & TeleportFlags.ViaLandmark) != 0 || 4099 (m_scene.TelehubAllowLandmarks == true ? false : ((m_teleportFlags & TeleportFlags.ViaLandmark) != 0 )) ||
4019 (m_teleportFlags & TeleportFlags.ViaLocation) != 0 || 4100 (m_teleportFlags & TeleportFlags.ViaLocation) != 0 ||
4020 (m_teleportFlags & Constants.TeleportFlags.ViaHGLogin) != 0) 4101 (m_teleportFlags & Constants.TeleportFlags.ViaHGLogin) != 0)
4021 { 4102 {
4022 if (GodLevel < 200 && 4103 if (GodLevel < 200 &&
4023 ((!m_scene.Permissions.IsGod(m_uuid) && 4104 ((!m_scene.Permissions.IsGod(m_uuid) &&
4024 !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid)) || 4105 !m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid)) ||
4025 (m_teleportFlags & TeleportFlags.ViaLocation) != 0 || 4106 (m_teleportFlags & TeleportFlags.ViaLocation) != 0 ||
4026 (m_teleportFlags & Constants.TeleportFlags.ViaHGLogin) != 0)) 4107 (m_teleportFlags & Constants.TeleportFlags.ViaHGLogin) != 0))
4027 { 4108 {
@@ -4029,28 +4110,92 @@ namespace OpenSim.Region.Framework.Scenes
4029 if (spawnPoints.Length == 0) 4110 if (spawnPoints.Length == 0)
4030 return; 4111 return;
4031 4112
4032 float distance = 9999; 4113 int index;
4033 int closest = -1; 4114 bool selected = false;
4034 4115
4035 for (int i = 0 ; i < spawnPoints.Length ; i++) 4116 switch (m_scene.SpawnPointRouting)
4036 { 4117 {
4037 Vector3 spawnPosition = spawnPoints[i].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); 4118 case "random":
4038 Vector3 offset = spawnPosition - pos;
4039 float d = Vector3.Mag(offset);
4040 if (d >= distance)
4041 continue;
4042 ILandObject land = m_scene.LandChannel.GetLandObject(spawnPosition.X, spawnPosition.Y);
4043 if (land == null)
4044 continue;
4045 if (land.IsEitherBannedOrRestricted(UUID))
4046 continue;
4047 distance = d;
4048 closest = i;
4049 }
4050 if (closest == -1)
4051 return;
4052 4119
4053 pos = spawnPoints[closest].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); 4120 do
4121 {
4122 index = Util.RandomClass.Next(spawnPoints.Length - 1);
4123
4124 Vector3 spawnPosition = spawnPoints[index].GetLocation(
4125 telehub.AbsolutePosition,
4126 telehub.GroupRotation
4127 );
4128 // SpawnPoint sp = spawnPoints[index];
4129
4130 ILandObject land = m_scene.LandChannel.GetLandObject(spawnPosition.X, spawnPosition.Y);
4131 if (land == null || land.IsEitherBannedOrRestricted(UUID))
4132 selected = false;
4133 else
4134 selected = true;
4135
4136 } while ( selected == false);
4137
4138 pos = spawnPoints[index].GetLocation(
4139 telehub.AbsolutePosition,
4140 telehub.GroupRotation
4141 );
4142 return;
4143
4144 case "sequence":
4145
4146 do
4147 {
4148 index = m_scene.SpawnPoint();
4149
4150 Vector3 spawnPosition = spawnPoints[index].GetLocation(
4151 telehub.AbsolutePosition,
4152 telehub.GroupRotation
4153 );
4154 // SpawnPoint sp = spawnPoints[index];
4155
4156 ILandObject land = m_scene.LandChannel.GetLandObject(spawnPosition.X, spawnPosition.Y);
4157 if (land == null || land.IsEitherBannedOrRestricted(UUID))
4158 selected = false;
4159 else
4160 selected = true;
4161
4162 } while (selected == false);
4163
4164 pos = spawnPoints[index].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation);
4165 ;
4166 return;
4167
4168 default:
4169 case "closest":
4170
4171 float distance = 9999;
4172 int closest = -1;
4173
4174 for (int i = 0; i < spawnPoints.Length; i++)
4175 {
4176 Vector3 spawnPosition = spawnPoints[i].GetLocation(
4177 telehub.AbsolutePosition,
4178 telehub.GroupRotation
4179 );
4180 Vector3 offset = spawnPosition - pos;
4181 float d = Vector3.Mag(offset);
4182 if (d >= distance)
4183 continue;
4184 ILandObject land = m_scene.LandChannel.GetLandObject(spawnPosition.X, spawnPosition.Y);
4185 if (land == null)
4186 continue;
4187 if (land.IsEitherBannedOrRestricted(UUID))
4188 continue;
4189 distance = d;
4190 closest = i;
4191 }
4192 if (closest == -1)
4193 return;
4194
4195 pos = spawnPoints[closest].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation);
4196 return;
4197
4198 }
4054 } 4199 }
4055 } 4200 }
4056 } 4201 }
@@ -4095,7 +4240,7 @@ namespace OpenSim.Region.Framework.Scenes
4095 GodLevel < 200 && 4240 GodLevel < 200 &&
4096 ((land.LandData.OwnerID != m_uuid && 4241 ((land.LandData.OwnerID != m_uuid &&
4097 !m_scene.Permissions.IsGod(m_uuid) && 4242 !m_scene.Permissions.IsGod(m_uuid) &&
4098 !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid)) || 4243 !m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid)) ||
4099 (m_teleportFlags & TeleportFlags.ViaLocation) != 0 || 4244 (m_teleportFlags & TeleportFlags.ViaLocation) != 0 ||
4100 (m_teleportFlags & Constants.TeleportFlags.ViaHGLogin) != 0)) 4245 (m_teleportFlags & Constants.TeleportFlags.ViaHGLogin) != 0))
4101 { 4246 {
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs
index 55455cc..a4f730d 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs
@@ -47,14 +47,30 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
47 /// </remarks> 47 /// </remarks>
48 public class CoalescedSceneObjectsSerializer 48 public class CoalescedSceneObjectsSerializer
49 { 49 {
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51 51
52 /// <summary> 52 /// <summary>
53 /// Serialize coalesced objects to Xml 53 /// Serialize coalesced objects to Xml
54 /// </summary> 54 /// </summary>
55 /// <param name="coa"></param> 55 /// <param name="coa"></param>
56 /// <param name="doScriptStates">
57 /// If true then serialize script states. This will halt any running scripts
58 /// </param>
56 /// <returns></returns> 59 /// <returns></returns>
57 public static string ToXml(CoalescedSceneObjects coa) 60 public static string ToXml(CoalescedSceneObjects coa)
61 {
62 return ToXml(coa, true);
63 }
64
65 /// <summary>
66 /// Serialize coalesced objects to Xml
67 /// </summary>
68 /// <param name="coa"></param>
69 /// <param name="doScriptStates">
70 /// If true then serialize script states. This will halt any running scripts
71 /// </param>
72 /// <returns></returns>
73 public static string ToXml(CoalescedSceneObjects coa, bool doScriptStates)
58 { 74 {
59 using (StringWriter sw = new StringWriter()) 75 using (StringWriter sw = new StringWriter())
60 { 76 {
@@ -91,7 +107,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
91 writer.WriteAttributeString("offsety", offsets[i].Y.ToString()); 107 writer.WriteAttributeString("offsety", offsets[i].Y.ToString());
92 writer.WriteAttributeString("offsetz", offsets[i].Z.ToString()); 108 writer.WriteAttributeString("offsetz", offsets[i].Z.ToString());
93 109
94 SceneObjectSerializer.ToOriginalXmlFormat(obj, writer, true); 110 SceneObjectSerializer.ToOriginalXmlFormat(obj, writer, doScriptStates);
95 111
96 writer.WriteEndElement(); // SceneObjectGroup 112 writer.WriteEndElement(); // SceneObjectGroup
97 } 113 }
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index abca14f..2372d6b 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -1537,51 +1537,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1537 } 1537 }
1538 } 1538 }
1539 1539
1540 //////// Read /////////
1541 public static bool Xml2ToSOG(XmlTextReader reader, SceneObjectGroup sog)
1542 {
1543 reader.Read();
1544 reader.ReadStartElement("SceneObjectGroup");
1545 SceneObjectPart root = Xml2ToSOP(reader);
1546 if (root != null)
1547 sog.SetRootPart(root);
1548 else
1549 {
1550 return false;
1551 }
1552
1553 if (sog.UUID == UUID.Zero)
1554 sog.UUID = sog.RootPart.UUID;
1555
1556 reader.Read(); // OtherParts
1557
1558 while (!reader.EOF)
1559 {
1560 switch (reader.NodeType)
1561 {
1562 case XmlNodeType.Element:
1563 if (reader.Name == "SceneObjectPart")
1564 {
1565 SceneObjectPart child = Xml2ToSOP(reader);
1566 if (child != null)
1567 sog.AddPart(child);
1568 }
1569 else
1570 {
1571 //Logger.Log("Found unexpected prim XML element " + reader.Name, Helpers.LogLevel.Debug);
1572 reader.Read();
1573 }
1574 break;
1575 case XmlNodeType.EndElement:
1576 default:
1577 reader.Read();
1578 break;
1579 }
1580
1581 }
1582 return true;
1583 }
1584
1585 public static SceneObjectPart Xml2ToSOP(XmlTextReader reader) 1540 public static SceneObjectPart Xml2ToSOP(XmlTextReader reader)
1586 { 1541 {
1587 SceneObjectPart obj = new SceneObjectPart(); 1542 SceneObjectPart obj = new SceneObjectPart();
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneXmlLoader.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneXmlLoader.cs
index d214eba..a3485d2 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneXmlLoader.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneXmlLoader.cs
@@ -223,50 +223,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
223 223
224 public static SceneObjectGroup DeserializeGroupFromXml2(string xmlString) 224 public static SceneObjectGroup DeserializeGroupFromXml2(string xmlString)
225 { 225 {
226 XmlDocument doc = new XmlDocument(); 226 return SceneObjectSerializer.FromXml2Format(xmlString);
227 XmlNode rootNode;
228
229 XmlTextReader reader = new XmlTextReader(new StringReader(xmlString));
230 reader.WhitespaceHandling = WhitespaceHandling.None;
231 doc.Load(reader);
232 reader.Close();
233 rootNode = doc.FirstChild;
234
235 // This is to deal with neighbouring regions that are still surrounding the group xml with the <scene>
236 // tag. It should be possible to remove the first part of this if statement once we go past 0.5.9 (or
237 // when some other changes forces all regions to upgrade).
238 // This might seem rather pointless since prim crossing from this revision to an earlier revision remains
239 // broken. But it isn't much work to accomodate the old format here.
240 if (rootNode.LocalName.Equals("scene"))
241 {
242 foreach (XmlNode aPrimNode in rootNode.ChildNodes)
243 {
244 // There is only ever one prim. This oddity should be removeable post 0.5.9
245 //return SceneObjectSerializer.FromXml2Format(aPrimNode.OuterXml);
246 using (reader = new XmlTextReader(new StringReader(aPrimNode.OuterXml)))
247 {
248 SceneObjectGroup obj = new SceneObjectGroup();
249 if (SceneObjectSerializer.Xml2ToSOG(reader, obj))
250 return obj;
251
252 return null;
253 }
254 }
255
256 return null;
257 }
258 else
259 {
260 //return SceneObjectSerializer.FromXml2Format(rootNode.OuterXml);
261 using (reader = new XmlTextReader(new StringReader(rootNode.OuterXml)))
262 {
263 SceneObjectGroup obj = new SceneObjectGroup();
264 if (SceneObjectSerializer.Xml2ToSOG(reader, obj))
265 return obj;
266
267 return null;
268 }
269 }
270 } 227 }
271 228
272 /// <summary> 229 /// <summary>
@@ -307,8 +264,8 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
307 ICollection<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>(); 264 ICollection<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>();
308 foreach (XmlNode aPrimNode in rootNode.ChildNodes) 265 foreach (XmlNode aPrimNode in rootNode.ChildNodes)
309 { 266 {
310 SceneObjectGroup obj = CreatePrimFromXml2(scene, aPrimNode.OuterXml); 267 SceneObjectGroup obj = DeserializeGroupFromXml2(aPrimNode.OuterXml);
311 if (obj != null && startScripts) 268 if (startScripts)
312 sceneObjects.Add(obj); 269 sceneObjects.Add(obj);
313 } 270 }
314 271
@@ -319,27 +276,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
319 } 276 }
320 } 277 }
321 278
322 /// <summary>
323 /// Create a prim from the xml2 representation.
324 /// </summary>
325 /// <param name="scene"></param>
326 /// <param name="xmlData"></param>
327 /// <returns>The scene object created. null if the scene object already existed</returns>
328 protected static SceneObjectGroup CreatePrimFromXml2(Scene scene, string xmlData)
329 {
330 //SceneObjectGroup obj = SceneObjectSerializer.FromXml2Format(xmlData);
331 using (XmlTextReader reader = new XmlTextReader(new StringReader(xmlData)))
332 {
333 SceneObjectGroup obj = new SceneObjectGroup();
334 SceneObjectSerializer.Xml2ToSOG(reader, obj);
335
336 if (scene.AddRestoredSceneObject(obj, true, false))
337 return obj;
338 else
339 return null;
340 }
341 }
342
343 #endregion 279 #endregion
344 } 280 }
345} 281} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
index a4afd47..18e6ece 100644
--- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
+++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
@@ -26,7 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29//using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Timers; 30using System.Timers;
31using OpenMetaverse.Packets; 31using OpenMetaverse.Packets;
32using OpenSim.Framework; 32using OpenSim.Framework;
@@ -35,10 +35,18 @@ using OpenSim.Region.Framework.Interfaces;
35 35
36namespace OpenSim.Region.Framework.Scenes 36namespace OpenSim.Region.Framework.Scenes
37{ 37{
38 /// <summary>
39 /// Collect statistics from the scene to send to the client and for access by other monitoring tools.
40 /// </summary>
41 /// <remarks>
42 /// FIXME: This should be a monitoring region module
43 /// </remarks>
38 public class SimStatsReporter 44 public class SimStatsReporter
39 { 45 {
40// private static readonly log4net.ILog m_log 46 private static readonly log4net.ILog m_log
41// = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 47 = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
48
49 public const string LastReportedObjectUpdateStatName = "LastReportedObjectUpdates";
42 50
43 public delegate void SendStatResult(SimStats stats); 51 public delegate void SendStatResult(SimStats stats);
44 52
@@ -48,10 +56,17 @@ namespace OpenSim.Region.Framework.Scenes
48 56
49 public event YourStatsAreWrong OnStatsIncorrect; 57 public event YourStatsAreWrong OnStatsIncorrect;
50 58
51 private SendStatResult handlerSendStatResult = null; 59 private SendStatResult handlerSendStatResult;
52 60
53 private YourStatsAreWrong handlerStatsIncorrect = null; 61 private YourStatsAreWrong handlerStatsIncorrect;
54 62
63 /// <summary>
64 /// These are the IDs of stats sent in the StatsPacket to the viewer.
65 /// </summary>
66 /// <remarks>
67 /// Some of these are not relevant to OpenSimulator since it is architected differently to other simulators
68 /// (e.g. script instructions aren't executed as part of the frame loop so 'script time' is tricky).
69 /// </remarks>
55 public enum Stats : uint 70 public enum Stats : uint
56 { 71 {
57 TimeDilation = 0, 72 TimeDilation = 0,
@@ -75,20 +90,20 @@ namespace OpenSim.Region.Framework.Scenes
75 OutPacketsPerSecond = 18, 90 OutPacketsPerSecond = 18,
76 PendingDownloads = 19, 91 PendingDownloads = 19,
77 PendingUploads = 20, 92 PendingUploads = 20,
78 VirtualSizeKB = 21, 93 VirtualSizeKb = 21,
79 ResidentSizeKB = 22, 94 ResidentSizeKb = 22,
80 PendingLocalUploads = 23, 95 PendingLocalUploads = 23,
81 UnAckedBytes = 24, 96 UnAckedBytes = 24,
82 PhysicsPinnedTasks = 25, 97 PhysicsPinnedTasks = 25,
83 PhysicsLODTasks = 26, 98 PhysicsLodTasks = 26,
84 PhysicsStepMS = 27, 99 SimPhysicsStepMs = 27,
85 PhysicsShapeMS = 28, 100 SimPhysicsShapeMs = 28,
86 PhysicsOtherMS = 29, 101 SimPhysicsOtherMs = 29,
87 PhysicsMemory = 30, 102 SimPhysicsMemory = 30,
88 ScriptEPS = 31, 103 ScriptEps = 31,
89 SimSpareTime = 32, 104 SimSpareMs = 32,
90 SimSleepTime = 33, 105 SimSleepMs = 33,
91 IOPumpTime = 34 106 SimIoPumpTime = 34
92 } 107 }
93 108
94 /// <summary> 109 /// <summary>
@@ -113,11 +128,24 @@ namespace OpenSim.Region.Framework.Scenes
113 get { return lastReportedSimStats; } 128 get { return lastReportedSimStats; }
114 } 129 }
115 130
131 /// <summary>
132 /// Extra sim statistics that are used by monitors but not sent to the client.
133 /// </summary>
134 /// <value>
135 /// The keys are the stat names.
136 /// </value>
137 private Dictionary<string, float> m_lastReportedExtraSimStats = new Dictionary<string, float>();
138
116 // Sending a stats update every 3 seconds- 139 // Sending a stats update every 3 seconds-
117 private int statsUpdatesEveryMS = 3000; 140 private int m_statsUpdatesEveryMS = 3000;
118 private float statsUpdateFactor = 0; 141 private float m_statsUpdateFactor;
119 private float m_timeDilation = 0; 142 private float m_timeDilation;
120 private int m_fps = 0; 143 private int m_fps;
144
145 /// <summary>
146 /// Number of the last frame on which we processed a stats udpate.
147 /// </summary>
148 private uint m_lastUpdateFrame;
121 149
122 /// <summary> 150 /// <summary>
123 /// Our nominal fps target, as expected in fps stats when a sim is running normally. 151 /// Our nominal fps target, as expected in fps stats when a sim is running normally.
@@ -135,43 +163,42 @@ namespace OpenSim.Region.Framework.Scenes
135 private float m_reportedFpsCorrectionFactor = 5; 163 private float m_reportedFpsCorrectionFactor = 5;
136 164
137 // saved last reported value so there is something available for llGetRegionFPS 165 // saved last reported value so there is something available for llGetRegionFPS
138 private float lastReportedSimFPS = 0; 166 private float lastReportedSimFPS;
139 private float[] lastReportedSimStats = new float[23]; 167 private float[] lastReportedSimStats = new float[22];
140 private float m_pfps = 0; 168 private float m_pfps;
141 169
142 /// <summary> 170 /// <summary>
143 /// Number of agent updates requested in this stats cycle 171 /// Number of agent updates requested in this stats cycle
144 /// </summary> 172 /// </summary>
145 private int m_agentUpdates = 0; 173 private int m_agentUpdates;
146 174
147 /// <summary> 175 /// <summary>
148 /// Number of object updates requested in this stats cycle 176 /// Number of object updates requested in this stats cycle
149 /// </summary> 177 /// </summary>
150 private int m_objectUpdates; 178 private int m_objectUpdates;
151 179
152 private int m_frameMS = 0; 180 private int m_frameMS;
153 private int m_netMS = 0; 181 private int m_spareMS;
154 private int m_agentMS = 0; 182 private int m_netMS;
155 private int m_physicsMS = 0; 183 private int m_agentMS;
156 private int m_imageMS = 0; 184 private int m_physicsMS;
157 private int m_otherMS = 0; 185 private int m_imageMS;
158 private int m_sleeptimeMS = 0; 186 private int m_otherMS;
159
160 187
161//Ckrinke: (3-21-08) Comment out to remove a compiler warning. Bring back into play when needed. 188//Ckrinke: (3-21-08) Comment out to remove a compiler warning. Bring back into play when needed.
162//Ckrinke private int m_scriptMS = 0; 189//Ckrinke private int m_scriptMS = 0;
163 190
164 private int m_rootAgents = 0; 191 private int m_rootAgents;
165 private int m_childAgents = 0; 192 private int m_childAgents;
166 private int m_numPrim = 0; 193 private int m_numPrim;
167 private int m_inPacketsPerSecond = 0; 194 private int m_inPacketsPerSecond;
168 private int m_outPacketsPerSecond = 0; 195 private int m_outPacketsPerSecond;
169 private int m_activePrim = 0; 196 private int m_activePrim;
170 private int m_unAckedBytes = 0; 197 private int m_unAckedBytes;
171 private int m_pendingDownloads = 0; 198 private int m_pendingDownloads;
172 private int m_pendingUploads = 0; 199 private int m_pendingUploads = 0; // FIXME: Not currently filled in
173 private int m_activeScripts = 0; 200 private int m_activeScripts;
174 private int m_scriptLinesPerSecond = 0; 201 private int m_scriptLinesPerSecond;
175 202
176 private int m_objectCapacity = 45000; 203 private int m_objectCapacity = 45000;
177 204
@@ -187,13 +214,13 @@ namespace OpenSim.Region.Framework.Scenes
187 { 214 {
188 m_scene = scene; 215 m_scene = scene;
189 m_reportedFpsCorrectionFactor = scene.MinFrameTime * m_nominalReportedFps; 216 m_reportedFpsCorrectionFactor = scene.MinFrameTime * m_nominalReportedFps;
190 statsUpdateFactor = (float)(statsUpdatesEveryMS / 1000); 217 m_statsUpdateFactor = (float)(m_statsUpdatesEveryMS / 1000);
191 ReportingRegion = scene.RegionInfo; 218 ReportingRegion = scene.RegionInfo;
192 219
193 m_objectCapacity = scene.RegionInfo.ObjectCapacity; 220 m_objectCapacity = scene.RegionInfo.ObjectCapacity;
194 m_report.AutoReset = true; 221 m_report.AutoReset = true;
195 m_report.Interval = statsUpdatesEveryMS; 222 m_report.Interval = m_statsUpdatesEveryMS;
196 m_report.Elapsed += statsHeartBeat; 223 m_report.Elapsed += TriggerStatsHeartbeat;
197 m_report.Enabled = true; 224 m_report.Enabled = true;
198 225
199 if (StatsManager.SimExtraStats != null) 226 if (StatsManager.SimExtraStats != null)
@@ -202,20 +229,38 @@ namespace OpenSim.Region.Framework.Scenes
202 229
203 public void Close() 230 public void Close()
204 { 231 {
205 m_report.Elapsed -= statsHeartBeat; 232 m_report.Elapsed -= TriggerStatsHeartbeat;
206 m_report.Close(); 233 m_report.Close();
207 } 234 }
208 235
236 /// <summary>
237 /// Sets the number of milliseconds between stat updates.
238 /// </summary>
239 /// <param name='ms'></param>
209 public void SetUpdateMS(int ms) 240 public void SetUpdateMS(int ms)
210 { 241 {
211 statsUpdatesEveryMS = ms; 242 m_statsUpdatesEveryMS = ms;
212 statsUpdateFactor = (float)(statsUpdatesEveryMS / 1000); 243 m_statsUpdateFactor = (float)(m_statsUpdatesEveryMS / 1000);
213 m_report.Interval = statsUpdatesEveryMS; 244 m_report.Interval = m_statsUpdatesEveryMS;
245 }
246
247 private void TriggerStatsHeartbeat(object sender, EventArgs args)
248 {
249 try
250 {
251 statsHeartBeat(sender, args);
252 }
253 catch (Exception e)
254 {
255 m_log.Warn(string.Format(
256 "[SIM STATS REPORTER] Update for {0} failed with exception ",
257 m_scene.RegionInfo.RegionName), e);
258 }
214 } 259 }
215 260
216 private void statsHeartBeat(object sender, EventArgs e) 261 private void statsHeartBeat(object sender, EventArgs e)
217 { 262 {
218 SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[23]; 263 SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[22];
219 SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock(); 264 SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock();
220 265
221 // Know what's not thread safe in Mono... modifying timers. 266 // Know what's not thread safe in Mono... modifying timers.
@@ -242,7 +287,7 @@ namespace OpenSim.Region.Framework.Scenes
242 int reportedFPS = (int)(m_fps * m_reportedFpsCorrectionFactor); 287 int reportedFPS = (int)(m_fps * m_reportedFpsCorrectionFactor);
243 288
244 // save the reported value so there is something available for llGetRegionFPS 289 // save the reported value so there is something available for llGetRegionFPS
245 lastReportedSimFPS = reportedFPS / statsUpdateFactor; 290 lastReportedSimFPS = reportedFPS / m_statsUpdateFactor;
246 291
247 float physfps = ((m_pfps / 1000)); 292 float physfps = ((m_pfps / 1000));
248 293
@@ -253,7 +298,6 @@ namespace OpenSim.Region.Framework.Scenes
253 physfps = 0; 298 physfps = 0;
254 299
255#endregion 300#endregion
256 float factor = 1 / statsUpdateFactor;
257 if (reportedFPS <= 0) 301 if (reportedFPS <= 0)
258 reportedFPS = 1; 302 reportedFPS = 1;
259 303
@@ -264,32 +308,38 @@ namespace OpenSim.Region.Framework.Scenes
264 float targetframetime = 1100.0f / (float)m_nominalReportedFps; 308 float targetframetime = 1100.0f / (float)m_nominalReportedFps;
265 309
266 float sparetime; 310 float sparetime;
267 float sleeptime;
268 if (TotalFrameTime > targetframetime) 311 if (TotalFrameTime > targetframetime)
269 { 312 {
270 sparetime = 0; 313 sparetime = 0;
271 sleeptime = 0;
272 }
273 else
274 {
275 sparetime = m_frameMS - m_physicsMS - m_agentMS;
276 sparetime *= perframe;
277 if (sparetime < 0)
278 sparetime = 0;
279 else if (sparetime > TotalFrameTime)
280 sparetime = TotalFrameTime;
281 sleeptime = m_sleeptimeMS * perframe;
282 } 314 }
315
316 m_rootAgents = m_scene.SceneGraph.GetRootAgentCount();
317 m_childAgents = m_scene.SceneGraph.GetChildAgentCount();
318 m_numPrim = m_scene.SceneGraph.GetTotalObjectsCount();
319 m_activePrim = m_scene.SceneGraph.GetActiveObjectsCount();
320 m_activeScripts = m_scene.SceneGraph.GetActiveScriptsCount();
321
322 // FIXME: Checking for stat sanity is a complex approach. What we really need to do is fix the code
323 // so that stat numbers are always consistent.
324 CheckStatSanity();
283 325
284 // other MS is actually simulation time 326 // other MS is actually simulation time
285 // m_otherMS = m_frameMS - m_physicsMS - m_imageMS - m_netMS - m_agentMS; 327 // m_otherMS = m_frameMS - m_physicsMS - m_imageMS - m_netMS - m_agentMS;
286 // m_imageMS m_netMS are not included in m_frameMS 328 // m_imageMS m_netMS are not included in m_frameMS
287 329
288 m_otherMS = m_frameMS - m_physicsMS - m_agentMS - m_sleeptimeMS; 330 m_otherMS = m_frameMS - m_physicsMS - m_agentMS;
289 if (m_otherMS < 0) 331 if (m_otherMS < 0)
290 m_otherMS = 0; 332 m_otherMS = 0;
291 333
292 for (int i = 0; i < 23; i++) 334 uint thisFrame = m_scene.Frame;
335 float framesUpdated = (float)(thisFrame - m_lastUpdateFrame) * m_reportedFpsCorrectionFactor;
336 m_lastUpdateFrame = thisFrame;
337
338 // Avoid div-by-zero if somehow we've not updated any frames.
339 if (framesUpdated == 0)
340 framesUpdated = 1;
341
342 for (int i = 0; i < 22; i++)
293 { 343 {
294 sb[i] = new SimStatsPacket.StatBlock(); 344 sb[i] = new SimStatsPacket.StatBlock();
295 } 345 }
@@ -298,13 +348,13 @@ namespace OpenSim.Region.Framework.Scenes
298 sb[0].StatValue = (Single.IsNaN(m_timeDilation)) ? 0.1f : m_timeDilation ; //((((m_timeDilation + (0.10f * statsUpdateFactor)) /10) / statsUpdateFactor)); 348 sb[0].StatValue = (Single.IsNaN(m_timeDilation)) ? 0.1f : m_timeDilation ; //((((m_timeDilation + (0.10f * statsUpdateFactor)) /10) / statsUpdateFactor));
299 349
300 sb[1].StatID = (uint) Stats.SimFPS; 350 sb[1].StatID = (uint) Stats.SimFPS;
301 sb[1].StatValue = reportedFPS / statsUpdateFactor; 351 sb[1].StatValue = reportedFPS / m_statsUpdateFactor;
302 352
303 sb[2].StatID = (uint) Stats.PhysicsFPS; 353 sb[2].StatID = (uint) Stats.PhysicsFPS;
304 sb[2].StatValue = physfps / statsUpdateFactor; 354 sb[2].StatValue = physfps / m_statsUpdateFactor;
305 355
306 sb[3].StatID = (uint) Stats.AgentUpdates; 356 sb[3].StatID = (uint) Stats.AgentUpdates;
307 sb[3].StatValue = (m_agentUpdates / statsUpdateFactor); 357 sb[3].StatValue = (m_agentUpdates / m_statsUpdateFactor);
308 358
309 sb[4].StatID = (uint) Stats.Agents; 359 sb[4].StatID = (uint) Stats.Agents;
310 sb[4].StatValue = m_rootAgents; 360 sb[4].StatValue = m_rootAgents;
@@ -319,38 +369,31 @@ namespace OpenSim.Region.Framework.Scenes
319 sb[7].StatValue = m_activePrim; 369 sb[7].StatValue = m_activePrim;
320 370
321 sb[8].StatID = (uint)Stats.FrameMS; 371 sb[8].StatID = (uint)Stats.FrameMS;
322 // sb[8].StatValue = m_frameMS / statsUpdateFactor; 372 sb[8].StatValue = m_frameMS / framesUpdated;
323 sb[8].StatValue = TotalFrameTime;
324 373
325 sb[9].StatID = (uint)Stats.NetMS; 374 sb[9].StatID = (uint)Stats.NetMS;
326 // sb[9].StatValue = m_netMS / statsUpdateFactor; 375 sb[9].StatValue = m_netMS / framesUpdated;
327 sb[9].StatValue = m_netMS * perframe;
328 376
329 sb[10].StatID = (uint)Stats.PhysicsMS; 377 sb[10].StatID = (uint)Stats.PhysicsMS;
330 // sb[10].StatValue = m_physicsMS / statsUpdateFactor; 378 sb[10].StatValue = m_physicsMS / framesUpdated;
331 sb[10].StatValue = m_physicsMS * perframe;
332 379
333 sb[11].StatID = (uint)Stats.ImageMS ; 380 sb[11].StatID = (uint)Stats.ImageMS ;
334 // sb[11].StatValue = m_imageMS / statsUpdateFactor; 381 sb[11].StatValue = m_imageMS / framesUpdated;
335 sb[11].StatValue = m_imageMS * perframe;
336 382
337 sb[12].StatID = (uint)Stats.OtherMS; 383 sb[12].StatID = (uint)Stats.OtherMS;
338 // sb[12].StatValue = m_otherMS / statsUpdateFactor; 384 sb[12].StatValue = m_otherMS / framesUpdated;
339 sb[12].StatValue = m_otherMS * perframe;
340
341 385
342 sb[13].StatID = (uint)Stats.InPacketsPerSecond; 386 sb[13].StatID = (uint)Stats.InPacketsPerSecond;
343 sb[13].StatValue = (m_inPacketsPerSecond / statsUpdateFactor); 387 sb[13].StatValue = (m_inPacketsPerSecond / m_statsUpdateFactor);
344 388
345 sb[14].StatID = (uint)Stats.OutPacketsPerSecond; 389 sb[14].StatID = (uint)Stats.OutPacketsPerSecond;
346 sb[14].StatValue = (m_outPacketsPerSecond / statsUpdateFactor); 390 sb[14].StatValue = (m_outPacketsPerSecond / m_statsUpdateFactor);
347 391
348 sb[15].StatID = (uint)Stats.UnAckedBytes; 392 sb[15].StatID = (uint)Stats.UnAckedBytes;
349 sb[15].StatValue = m_unAckedBytes; 393 sb[15].StatValue = m_unAckedBytes;
350 394
351 sb[16].StatID = (uint)Stats.AgentMS; 395 sb[16].StatID = (uint)Stats.AgentMS;
352// sb[16].StatValue = m_agentMS / statsUpdateFactor; 396 sb[16].StatValue = m_agentMS / framesUpdated;
353 sb[16].StatValue = m_agentMS * perframe;
354 397
355 sb[17].StatID = (uint)Stats.PendingDownloads; 398 sb[17].StatID = (uint)Stats.PendingDownloads;
356 sb[17].StatValue = m_pendingDownloads; 399 sb[17].StatValue = m_pendingDownloads;
@@ -362,15 +405,12 @@ namespace OpenSim.Region.Framework.Scenes
362 sb[19].StatValue = m_activeScripts; 405 sb[19].StatValue = m_activeScripts;
363 406
364 sb[20].StatID = (uint)Stats.ScriptLinesPerSecond; 407 sb[20].StatID = (uint)Stats.ScriptLinesPerSecond;
365 sb[20].StatValue = m_scriptLinesPerSecond / statsUpdateFactor; 408 sb[20].StatValue = m_scriptLinesPerSecond / m_statsUpdateFactor;
366 409
367 sb[21].StatID = (uint)Stats.SimSpareTime; 410 sb[21].StatID = (uint)Stats.SimSpareMs;
368 sb[21].StatValue = sparetime; 411 sb[21].StatValue = m_spareMS / framesUpdated;
369 412
370 sb[22].StatID = (uint)Stats.SimSleepTime; 413 for (int i = 0; i < 22; i++)
371 sb[22].StatValue = sleeptime;
372
373 for (int i = 0; i < 23; i++)
374 { 414 {
375 lastReportedSimStats[i] = sb[i].StatValue; 415 lastReportedSimStats[i] = sb[i].StatValue;
376 } 416 }
@@ -387,13 +427,32 @@ namespace OpenSim.Region.Framework.Scenes
387 } 427 }
388 428
389 // Extra statistics that aren't currently sent to clients 429 // Extra statistics that aren't currently sent to clients
390 LastReportedObjectUpdates = m_objectUpdates / statsUpdateFactor; 430 lock (m_lastReportedExtraSimStats)
431 {
432 m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / m_statsUpdateFactor;
433
434 Dictionary<string, float> physicsStats = m_scene.PhysicsScene.GetStats();
435
436 if (physicsStats != null)
437 {
438 foreach (KeyValuePair<string, float> tuple in physicsStats)
439 {
440 // FIXME: An extremely dirty hack to divide MS stats per frame rather than per second
441 // Need to change things so that stats source can indicate whether they are per second or
442 // per frame.
443 if (tuple.Key.EndsWith("MS"))
444 m_lastReportedExtraSimStats[tuple.Key] = tuple.Value / framesUpdated;
445 else
446 m_lastReportedExtraSimStats[tuple.Key] = tuple.Value / m_statsUpdateFactor;
447 }
448 }
449 }
391 450
392 resetvalues(); 451 ResetValues();
393 } 452 }
394 } 453 }
395 454
396 private void resetvalues() 455 private void ResetValues()
397 { 456 {
398 m_timeDilation = 0; 457 m_timeDilation = 0;
399 m_fps = 0; 458 m_fps = 0;
@@ -411,7 +470,7 @@ namespace OpenSim.Region.Framework.Scenes
411 m_physicsMS = 0; 470 m_physicsMS = 0;
412 m_imageMS = 0; 471 m_imageMS = 0;
413 m_otherMS = 0; 472 m_otherMS = 0;
414 m_sleeptimeMS = 0; 473 m_spareMS = 0;
415 474
416//Ckrinke This variable is not used, so comment to remove compiler warning until it is used. 475//Ckrinke This variable is not used, so comment to remove compiler warning until it is used.
417//Ckrinke m_scriptMS = 0; 476//Ckrinke m_scriptMS = 0;
@@ -433,13 +492,6 @@ namespace OpenSim.Region.Framework.Scenes
433 m_timeDilation = td; 492 m_timeDilation = td;
434 } 493 }
435 494
436 public void SetRootAgents(int rootAgents)
437 {
438 m_rootAgents = rootAgents;
439 CheckStatSanity();
440
441 }
442
443 internal void CheckStatSanity() 495 internal void CheckStatSanity()
444 { 496 {
445 if (m_rootAgents < 0 || m_childAgents < 0) 497 if (m_rootAgents < 0 || m_childAgents < 0)
@@ -456,22 +508,6 @@ namespace OpenSim.Region.Framework.Scenes
456 } 508 }
457 } 509 }
458 510
459 public void SetChildAgents(int childAgents)
460 {
461 m_childAgents = childAgents;
462 CheckStatSanity();
463 }
464
465 public void SetObjects(int objects)
466 {
467 m_numPrim = objects;
468 }
469
470 public void SetActiveObjects(int objects)
471 {
472 m_activePrim = objects;
473 }
474
475 public void AddFPS(int frames) 511 public void AddFPS(int frames)
476 { 512 {
477 m_fps += frames; 513 m_fps += frames;
@@ -513,6 +549,11 @@ namespace OpenSim.Region.Framework.Scenes
513 m_frameMS += ms; 549 m_frameMS += ms;
514 } 550 }
515 551
552 public void AddSpareMS(int ms)
553 {
554 m_spareMS += ms;
555 }
556
516 public void addNetMS(int ms) 557 public void addNetMS(int ms)
517 { 558 {
518 m_netMS += ms; 559 m_netMS += ms;
@@ -538,15 +579,13 @@ namespace OpenSim.Region.Framework.Scenes
538 m_otherMS += ms; 579 m_otherMS += ms;
539 } 580 }
540 581
541 public void addSleepMS(int ms)
542 {
543 m_sleeptimeMS += ms;
544 }
545
546 public void AddPendingDownloads(int count) 582 public void AddPendingDownloads(int count)
547 { 583 {
548 m_pendingDownloads += count; 584 m_pendingDownloads += count;
549 if (m_pendingDownloads < 0) m_pendingDownloads = 0; 585
586 if (m_pendingDownloads < 0)
587 m_pendingDownloads = 0;
588
550 //m_log.InfoFormat("[stats]: Adding {0} to pending downloads to make {1}", count, m_pendingDownloads); 589 //m_log.InfoFormat("[stats]: Adding {0} to pending downloads to make {1}", count, m_pendingDownloads);
551 } 590 }
552 591
@@ -555,11 +594,6 @@ namespace OpenSim.Region.Framework.Scenes
555 m_scriptLinesPerSecond += count; 594 m_scriptLinesPerSecond += count;
556 } 595 }
557 596
558 public void SetActiveScripts(int count)
559 {
560 m_activeScripts = count;
561 }
562
563 public void AddPacketsStats(int inPackets, int outPackets, int unAckedBytes) 597 public void AddPacketsStats(int inPackets, int outPackets, int unAckedBytes)
564 { 598 {
565 AddInPackets(inPackets); 599 AddInPackets(inPackets);
@@ -568,5 +602,11 @@ namespace OpenSim.Region.Framework.Scenes
568 } 602 }
569 603
570 #endregion 604 #endregion
605
606 public Dictionary<string, float> GetExtraSimStats()
607 {
608 lock (m_lastReportedExtraSimStats)
609 return new Dictionary<string, float>(m_lastReportedExtraSimStats);
610 }
571 } 611 }
572} 612}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/BorderTests.cs b/OpenSim/Region/Framework/Scenes/Tests/BorderTests.cs
index ab6311b..4a21dc9 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/BorderTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/BorderTests.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.IO;
30using System.Text; 31using System.Text;
31using NUnit.Framework; 32using NUnit.Framework;
32using OpenMetaverse; 33using OpenMetaverse;
@@ -68,11 +69,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
68 Vector3 position = new Vector3(200,200,21); 69 Vector3 position = new Vector3(200,200,21);
69 70
70 foreach (Border b in testborders) 71 foreach (Border b in testborders)
71 {
72 Assert.That(!b.TestCross(position)); 72 Assert.That(!b.TestCross(position));
73 73
74 }
75
76 position = new Vector3(200,280,21); 74 position = new Vector3(200,280,21);
77 Assert.That(NorthBorder.TestCross(position)); 75 Assert.That(NorthBorder.TestCross(position));
78 76
diff --git a/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs b/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs
index a5d2b23..ea9fc93 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs
@@ -45,7 +45,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
45 { 45 {
46 static public Random random; 46 static public Random random;
47 SceneObjectGroup found; 47 SceneObjectGroup found;
48 Scene scene = SceneHelpers.SetupScene(); 48 Scene scene = new SceneHelpers().SetupScene();
49 49
50 [Test] 50 [Test]
51 public void T010_AddObjects() 51 public void T010_AddObjects()
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs
index 9a60e50..d23c965 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs
@@ -26,7 +26,9 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.IO;
29using System.Reflection; 30using System.Reflection;
31using System.Text;
30using NUnit.Framework; 32using NUnit.Framework;
31using OpenMetaverse; 33using OpenMetaverse;
32using OpenSim.Framework; 34using OpenSim.Framework;
@@ -44,7 +46,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests
44 public void TestDuplicateObject() 46 public void TestDuplicateObject()
45 { 47 {
46 TestHelpers.InMethod(); 48 TestHelpers.InMethod();
47 Scene scene = SceneHelpers.SetupScene(); 49// TestHelpers.EnableLogging();
50
51 Scene scene = new SceneHelpers().SetupScene();
48 52
49 UUID ownerId = new UUID("00000000-0000-0000-0000-000000000010"); 53 UUID ownerId = new UUID("00000000-0000-0000-0000-000000000010");
50 string part1Name = "part1"; 54 string part1Name = "part1";
@@ -82,6 +86,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
82 Assert.That(dupePart1.PhysActor, Is.Not.Null); 86 Assert.That(dupePart1.PhysActor, Is.Not.Null);
83 Assert.That(dupePart2.PhysActor, Is.Not.Null); 87 Assert.That(dupePart2.PhysActor, Is.Not.Null);
84 */ 88 */
89
90// TestHelpers.DisableLogging();
85 } 91 }
86 } 92 }
87} \ No newline at end of file 93} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs
index 7737d8e..3398a53 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs
@@ -88,7 +88,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
88 { 88 {
89 TestHelpers.InMethod(); 89 TestHelpers.InMethod();
90 90
91 Scene scene = SceneHelpers.SetupScene(); 91 Scene scene = new SceneHelpers().SetupScene();
92 int partsToTestCount = 3; 92 int partsToTestCount = 3;
93 93
94 SceneObjectGroup so 94 SceneObjectGroup so
@@ -118,7 +118,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
118 { 118 {
119 TestHelpers.InMethod(); 119 TestHelpers.InMethod();
120 120
121 Scene scene = SceneHelpers.SetupScene(); 121 Scene scene = new SceneHelpers().SetupScene();
122 122
123 string obj1Name = "Alfred"; 123 string obj1Name = "Alfred";
124 string obj2Name = "Betty"; 124 string obj2Name = "Betty";
@@ -152,7 +152,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
152 { 152 {
153 TestHelpers.InMethod(); 153 TestHelpers.InMethod();
154 154
155 Scene scene = SceneHelpers.SetupScene(); 155 Scene scene = new SceneHelpers().SetupScene();
156 int partsToTestCount = 3; 156 int partsToTestCount = 3;
157 157
158 SceneObjectGroup so 158 SceneObjectGroup so
@@ -185,11 +185,16 @@ namespace OpenSim.Region.Framework.Scenes.Tests
185 { 185 {
186 TestHelpers.InMethod(); 186 TestHelpers.InMethod();
187 187
188 TestScene scene = SceneHelpers.SetupScene(); 188 TestScene scene = new SceneHelpers().SetupScene();
189 SceneObjectPart part = SceneHelpers.AddSceneObject(scene); 189 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene);
190 scene.DeleteSceneObject(part.ParentGroup, false);
191 190
192 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId); 191 Assert.That(so.IsDeleted, Is.False);
192
193 scene.DeleteSceneObject(so, false);
194
195 Assert.That(so.IsDeleted, Is.True);
196
197 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(so.LocalId);
193 Assert.That(retrievedPart, Is.Null); 198 Assert.That(retrievedPart, Is.Null);
194 } 199 }
195 200
@@ -204,24 +209,28 @@ namespace OpenSim.Region.Framework.Scenes.Tests
204 209
205 UUID agentId = UUID.Parse("00000000-0000-0000-0000-000000000001"); 210 UUID agentId = UUID.Parse("00000000-0000-0000-0000-000000000001");
206 211
207 TestScene scene = SceneHelpers.SetupScene(); 212 TestScene scene = new SceneHelpers().SetupScene();
208 213
209 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test. 214 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test.
210 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter; 215 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter;
211 sogd.Enabled = false; 216 sogd.Enabled = false;
212 217
213 SceneObjectPart part = SceneHelpers.AddSceneObject(scene); 218 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene);
214 219
215 IClientAPI client = SceneHelpers.AddScenePresence(scene, agentId).ControllingClient; 220 IClientAPI client = SceneHelpers.AddScenePresence(scene, agentId).ControllingClient;
216 scene.DeRezObjects(client, new System.Collections.Generic.List<uint>() { part.LocalId }, UUID.Zero, DeRezAction.Delete, UUID.Zero); 221 scene.DeRezObjects(client, new System.Collections.Generic.List<uint>() { so.LocalId }, UUID.Zero, DeRezAction.Delete, UUID.Zero);
217 222
218 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId); 223 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(so.LocalId);
219 224
220 Assert.That(retrievedPart, Is.Not.Null); 225 Assert.That(retrievedPart, Is.Not.Null);
221 226
227 Assert.That(so.IsDeleted, Is.False);
228
222 sogd.InventoryDeQueueAndDelete(); 229 sogd.InventoryDeQueueAndDelete();
223 230
224 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(part.LocalId); 231 Assert.That(so.IsDeleted, Is.True);
232
233 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId);
225 Assert.That(retrievedPart2, Is.Null); 234 Assert.That(retrievedPart2, Is.Null);
226 } 235 }
227 236
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
index 654b1a2..0076f41 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
@@ -61,7 +61,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
61 61
62 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001"); 62 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001");
63 63
64 TestScene scene = SceneHelpers.SetupScene(); 64 TestScene scene = new SceneHelpers().SetupScene();
65 IConfigSource configSource = new IniConfigSource(); 65 IConfigSource configSource = new IniConfigSource();
66 IConfig config = configSource.AddConfig("Startup"); 66 IConfig config = configSource.AddConfig("Startup");
67 config.Set("serverside_object_permissions", true); 67 config.Set("serverside_object_permissions", true);
@@ -100,7 +100,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
100 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001"); 100 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001");
101 UUID objectOwnerId = UUID.Parse("20000000-0000-0000-0000-000000000001"); 101 UUID objectOwnerId = UUID.Parse("20000000-0000-0000-0000-000000000001");
102 102
103 TestScene scene = SceneHelpers.SetupScene(); 103 TestScene scene = new SceneHelpers().SetupScene();
104 IConfigSource configSource = new IniConfigSource(); 104 IConfigSource configSource = new IniConfigSource();
105 IConfig config = configSource.AddConfig("Startup"); 105 IConfig config = configSource.AddConfig("Startup");
106 config.Set("serverside_object_permissions", true); 106 config.Set("serverside_object_permissions", true);
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs
index be5b4a8..0e525c9 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs
@@ -55,7 +55,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
55 UUID ownerId = TestHelpers.ParseTail(0x1); 55 UUID ownerId = TestHelpers.ParseTail(0x1);
56 int nParts = 3; 56 int nParts = 3;
57 57
58 TestScene scene = SceneHelpers.SetupScene(); 58 TestScene scene = new SceneHelpers().SetupScene();
59 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(nParts, ownerId, "TestLinkToSelf_", 0x10); 59 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(nParts, ownerId, "TestLinkToSelf_", 0x10);
60 scene.AddSceneObject(sog1); 60 scene.AddSceneObject(sog1);
61 scene.LinkObjects(ownerId, sog1.LocalId, new List<uint>() { sog1.Parts[1].LocalId }); 61 scene.LinkObjects(ownerId, sog1.LocalId, new List<uint>() { sog1.Parts[1].LocalId });
@@ -71,11 +71,11 @@ namespace OpenSim.Region.Framework.Scenes.Tests
71 71
72 bool debugtest = false; 72 bool debugtest = false;
73 73
74 Scene scene = SceneHelpers.SetupScene(); 74 Scene scene = new SceneHelpers().SetupScene();
75 SceneObjectPart part1 = SceneHelpers.AddSceneObject(scene); 75 SceneObjectGroup grp1 = SceneHelpers.AddSceneObject(scene);
76 SceneObjectGroup grp1 = part1.ParentGroup; 76 SceneObjectPart part1 = grp1.RootPart;
77 SceneObjectPart part2 = SceneHelpers.AddSceneObject(scene); 77 SceneObjectGroup grp2 = SceneHelpers.AddSceneObject(scene);
78 SceneObjectGroup grp2 = part2.ParentGroup; 78 SceneObjectPart part2 = grp2.RootPart;
79 79
80 grp1.AbsolutePosition = new Vector3(10, 10, 10); 80 grp1.AbsolutePosition = new Vector3(10, 10, 10);
81 grp2.AbsolutePosition = Vector3.Zero; 81 grp2.AbsolutePosition = Vector3.Zero;
@@ -153,15 +153,15 @@ namespace OpenSim.Region.Framework.Scenes.Tests
153 153
154 bool debugtest = false; 154 bool debugtest = false;
155 155
156 Scene scene = SceneHelpers.SetupScene(); 156 Scene scene = new SceneHelpers().SetupScene();
157 SceneObjectPart part1 = SceneHelpers.AddSceneObject(scene); 157 SceneObjectGroup grp1 = SceneHelpers.AddSceneObject(scene);
158 SceneObjectGroup grp1 = part1.ParentGroup; 158 SceneObjectPart part1 = grp1.RootPart;
159 SceneObjectPart part2 = SceneHelpers.AddSceneObject(scene); 159 SceneObjectGroup grp2 = SceneHelpers.AddSceneObject(scene);
160 SceneObjectGroup grp2 = part2.ParentGroup; 160 SceneObjectPart part2 = grp2.RootPart;
161 SceneObjectPart part3 = SceneHelpers.AddSceneObject(scene); 161 SceneObjectGroup grp3 = SceneHelpers.AddSceneObject(scene);
162 SceneObjectGroup grp3 = part3.ParentGroup; 162 SceneObjectPart part3 = grp3.RootPart;
163 SceneObjectPart part4 = SceneHelpers.AddSceneObject(scene); 163 SceneObjectGroup grp4 = SceneHelpers.AddSceneObject(scene);
164 SceneObjectGroup grp4 = part4.ParentGroup; 164 SceneObjectPart part4 = grp4.RootPart;
165 165
166 grp1.AbsolutePosition = new Vector3(10, 10, 10); 166 grp1.AbsolutePosition = new Vector3(10, 10, 10);
167 grp2.AbsolutePosition = Vector3.Zero; 167 grp2.AbsolutePosition = Vector3.Zero;
@@ -286,7 +286,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
286 TestHelpers.InMethod(); 286 TestHelpers.InMethod();
287 //log4net.Config.XmlConfigurator.Configure(); 287 //log4net.Config.XmlConfigurator.Configure();
288 288
289 TestScene scene = SceneHelpers.SetupScene(); 289 TestScene scene = new SceneHelpers().SetupScene();
290 290
291 string rootPartName = "rootpart"; 291 string rootPartName = "rootpart";
292 UUID rootPartUuid = new UUID("00000000-0000-0000-0000-000000000001"); 292 UUID rootPartUuid = new UUID("00000000-0000-0000-0000-000000000001");
@@ -325,7 +325,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
325 TestHelpers.InMethod(); 325 TestHelpers.InMethod();
326 //log4net.Config.XmlConfigurator.Configure(); 326 //log4net.Config.XmlConfigurator.Configure();
327 327
328 TestScene scene = SceneHelpers.SetupScene(); 328 TestScene scene = new SceneHelpers().SetupScene();
329 329
330 string rootPartName = "rootpart"; 330 string rootPartName = "rootpart";
331 UUID rootPartUuid = new UUID("00000000-0000-0000-0000-000000000001"); 331 UUID rootPartUuid = new UUID("00000000-0000-0000-0000-000000000001");
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs
index b49c6e7..e931859 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs
@@ -52,8 +52,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
52 TestHelpers.InMethod(); 52 TestHelpers.InMethod();
53// log4net.Config.XmlConfigurator.Configure(); 53// log4net.Config.XmlConfigurator.Configure();
54 54
55 Scene scene = SceneHelpers.SetupScene(); 55 Scene scene = new SceneHelpers().SetupScene();
56 SceneObjectGroup g1 = SceneHelpers.AddSceneObject(scene).ParentGroup; 56 SceneObjectGroup g1 = SceneHelpers.AddSceneObject(scene);
57 57
58 g1.GroupResize(new Vector3(2, 3, 4)); 58 g1.GroupResize(new Vector3(2, 3, 4));
59 59
@@ -75,7 +75,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
75 TestHelpers.InMethod(); 75 TestHelpers.InMethod();
76 //log4net.Config.XmlConfigurator.Configure(); 76 //log4net.Config.XmlConfigurator.Configure();
77 77
78 Scene scene = SceneHelpers.SetupScene(); 78 Scene scene = new SceneHelpers().SetupScene();
79 79
80 SceneObjectGroup g1 = SceneHelpers.CreateSceneObject(2, UUID.Zero); 80 SceneObjectGroup g1 = SceneHelpers.CreateSceneObject(2, UUID.Zero);
81 g1.RootPart.Scale = new Vector3(2, 3, 4); 81 g1.RootPart.Scale = new Vector3(2, 3, 4);
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectScriptTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectScriptTests.cs
index c582cf6..d2361f8 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectScriptTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectScriptTests.cs
@@ -52,7 +52,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
52// UUID itemId = TestHelpers.ParseTail(0x2); 52// UUID itemId = TestHelpers.ParseTail(0x2);
53 string itemName = "Test Script Item"; 53 string itemName = "Test Script Item";
54 54
55 Scene scene = SceneHelpers.SetupScene(); 55 Scene scene = new SceneHelpers().SetupScene();
56 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId); 56 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId);
57 scene.AddNewSceneObject(so, true); 57 scene.AddNewSceneObject(so, true);
58 58
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs
new file mode 100644
index 0000000..6d255aa
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs
@@ -0,0 +1,154 @@
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.Threading;
31using NUnit.Framework;
32using OpenMetaverse;
33using OpenSim.Framework;
34using OpenSim.Framework.Communications;
35using OpenSim.Region.Framework.Scenes;
36using OpenSim.Tests.Common;
37using OpenSim.Tests.Common.Mock;
38
39namespace OpenSim.Region.Framework.Scenes.Tests
40{
41 /// <summary>
42 /// Spatial scene object tests (will eventually cover root and child part position, rotation properties, etc.)
43 /// </summary>
44 [TestFixture]
45 public class SceneObjectSpatialTests
46 {
47 TestScene m_scene;
48 UUID m_ownerId = TestHelpers.ParseTail(0x1);
49
50 [SetUp]
51 public void SetUp()
52 {
53 m_scene = new SceneHelpers().SetupScene();
54 }
55
56 [Test]
57 public void TestGetSceneObjectGroupPosition()
58 {
59 TestHelpers.InMethod();
60
61 Vector3 position = new Vector3(10, 20, 30);
62
63 SceneObjectGroup so
64 = SceneHelpers.CreateSceneObject(1, m_ownerId, "obj1", 0x10);
65 so.AbsolutePosition = position;
66 m_scene.AddNewSceneObject(so, false);
67
68 Assert.That(so.AbsolutePosition, Is.EqualTo(position));
69 }
70
71 [Test]
72 public void TestGetRootPartPosition()
73 {
74 TestHelpers.InMethod();
75
76 Vector3 partPosition = new Vector3(10, 20, 30);
77
78 SceneObjectGroup so
79 = SceneHelpers.CreateSceneObject(1, m_ownerId, "obj1", 0x10);
80 so.AbsolutePosition = partPosition;
81 m_scene.AddNewSceneObject(so, false);
82
83 Assert.That(so.RootPart.AbsolutePosition, Is.EqualTo(partPosition));
84 Assert.That(so.RootPart.GroupPosition, Is.EqualTo(partPosition));
85 Assert.That(so.RootPart.GetWorldPosition(), Is.EqualTo(partPosition));
86 Assert.That(so.RootPart.RelativePosition, Is.EqualTo(partPosition));
87 Assert.That(so.RootPart.OffsetPosition, Is.EqualTo(Vector3.Zero));
88 }
89
90 [Test]
91 public void TestGetChildPartPosition()
92 {
93 TestHelpers.InMethod();
94
95 Vector3 rootPartPosition = new Vector3(10, 20, 30);
96 Vector3 childOffsetPosition = new Vector3(2, 3, 4);
97
98 SceneObjectGroup so
99 = SceneHelpers.CreateSceneObject(2, m_ownerId, "obj1", 0x10);
100 so.AbsolutePosition = rootPartPosition;
101 so.Parts[1].OffsetPosition = childOffsetPosition;
102
103 m_scene.AddNewSceneObject(so, false);
104
105 // Calculate child absolute position.
106 Vector3 childPosition = new Vector3(rootPartPosition + childOffsetPosition);
107
108 SceneObjectPart childPart = so.Parts[1];
109 Assert.That(childPart.AbsolutePosition, Is.EqualTo(childPosition));
110 Assert.That(childPart.GroupPosition, Is.EqualTo(rootPartPosition));
111 Assert.That(childPart.GetWorldPosition(), Is.EqualTo(childPosition));
112 Assert.That(childPart.RelativePosition, Is.EqualTo(childOffsetPosition));
113 Assert.That(childPart.OffsetPosition, Is.EqualTo(childOffsetPosition));
114 }
115
116 [Test]
117 public void TestGetChildPartPositionAfterObjectRotation()
118 {
119 TestHelpers.InMethod();
120
121 Vector3 rootPartPosition = new Vector3(10, 20, 30);
122 Vector3 childOffsetPosition = new Vector3(2, 3, 4);
123
124 SceneObjectGroup so
125 = SceneHelpers.CreateSceneObject(2, m_ownerId, "obj1", 0x10);
126 so.AbsolutePosition = rootPartPosition;
127 so.Parts[1].OffsetPosition = childOffsetPosition;
128
129 m_scene.AddNewSceneObject(so, false);
130
131 so.UpdateGroupRotationR(Quaternion.CreateFromEulers(0, 0, -90 * Utils.DEG_TO_RAD));
132
133 // Calculate child absolute position.
134 Vector3 rotatedChildOffsetPosition
135 = new Vector3(childOffsetPosition.Y, -childOffsetPosition.X, childOffsetPosition.Z);
136
137 Vector3 childPosition = new Vector3(rootPartPosition + rotatedChildOffsetPosition);
138
139 SceneObjectPart childPart = so.Parts[1];
140
141 // FIXME: Should be childPosition after rotation?
142 Assert.That(childPart.AbsolutePosition, Is.EqualTo(rootPartPosition + childOffsetPosition));
143
144 Assert.That(childPart.GroupPosition, Is.EqualTo(rootPartPosition));
145 Assert.That(childPart.GetWorldPosition(), Is.EqualTo(childPosition));
146
147 // Relative to root part as (0, 0, 0)
148 Assert.That(childPart.RelativePosition, Is.EqualTo(childOffsetPosition));
149
150 // Relative to root part as (0, 0, 0)
151 Assert.That(childPart.OffsetPosition, Is.EqualTo(childOffsetPosition));
152 }
153 }
154} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs
index 2a342d5..742c769 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic;
29using System.Reflection; 30using System.Reflection;
30using NUnit.Framework; 31using NUnit.Framework;
31using OpenMetaverse; 32using OpenMetaverse;
@@ -43,24 +44,141 @@ namespace OpenSim.Region.Framework.Scenes.Tests
43 [TestFixture] 44 [TestFixture]
44 public class SceneObjectStatusTests 45 public class SceneObjectStatusTests
45 { 46 {
47 private TestScene m_scene;
48 private UUID m_ownerId = TestHelpers.ParseTail(0x1);
49 private SceneObjectGroup m_so1;
50 private SceneObjectGroup m_so2;
51
52 [SetUp]
53 public void Init()
54 {
55 m_scene = new SceneHelpers().SetupScene();
56 m_so1 = SceneHelpers.CreateSceneObject(1, m_ownerId, "so1", 0x10);
57 m_so2 = SceneHelpers.CreateSceneObject(1, m_ownerId, "so2", 0x20);
58 }
59
46 [Test] 60 [Test]
47 public void TestSetPhantom() 61 public void TestSetPhantomSinglePrim()
48 { 62 {
49 TestHelpers.InMethod(); 63 TestHelpers.InMethod();
50 64
51// Scene scene = SceneSetupHelpers.SetupScene(); 65 m_scene.AddSceneObject(m_so1);
52 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, UUID.Zero); 66
53 SceneObjectPart rootPart = so.RootPart; 67 SceneObjectPart rootPart = m_so1.RootPart;
54 Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None)); 68 Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None));
55 69
56 so.ScriptSetPhantomStatus(true); 70 m_so1.ScriptSetPhantomStatus(true);
57 71
58// Console.WriteLine("so.RootPart.Flags [{0}]", so.RootPart.Flags); 72// Console.WriteLine("so.RootPart.Flags [{0}]", so.RootPart.Flags);
59 Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Phantom)); 73 Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Phantom));
60 74
61 so.ScriptSetPhantomStatus(false); 75 m_so1.ScriptSetPhantomStatus(false);
62 76
63 Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None)); 77 Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None));
64 } 78 }
79
80 [Test]
81 public void TestSetPhysicsSinglePrim()
82 {
83 TestHelpers.InMethod();
84
85 m_scene.AddSceneObject(m_so1);
86
87 SceneObjectPart rootPart = m_so1.RootPart;
88 Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None));
89
90 m_so1.ScriptSetPhysicsStatus(true);
91
92// Console.WriteLine("so.RootPart.Flags [{0}]", so.RootPart.Flags);
93 Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Physics));
94
95 m_so1.ScriptSetPhysicsStatus(false);
96
97 Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None));
98 }
99
100 [Test]
101 public void TestSetPhysicsLinkset()
102 {
103 TestHelpers.InMethod();
104
105 m_scene.AddSceneObject(m_so1);
106 m_scene.AddSceneObject(m_so2);
107
108 m_scene.LinkObjects(m_ownerId, m_so1.LocalId, new List<uint>() { m_so2.LocalId });
109
110 m_so1.ScriptSetPhysicsStatus(true);
111
112 Assert.That(m_so1.RootPart.Flags, Is.EqualTo(PrimFlags.Physics));
113 Assert.That(m_so1.Parts[1].Flags, Is.EqualTo(PrimFlags.Physics));
114
115 m_so1.ScriptSetPhysicsStatus(false);
116
117 Assert.That(m_so1.RootPart.Flags, Is.EqualTo(PrimFlags.None));
118 Assert.That(m_so1.Parts[1].Flags, Is.EqualTo(PrimFlags.None));
119
120 m_so1.ScriptSetPhysicsStatus(true);
121
122 Assert.That(m_so1.RootPart.Flags, Is.EqualTo(PrimFlags.Physics));
123 Assert.That(m_so1.Parts[1].Flags, Is.EqualTo(PrimFlags.Physics));
124 }
125
126 /// <summary>
127 /// Test that linking results in the correct physical status for all linkees.
128 /// </summary>
129 [Test]
130 public void TestLinkPhysicsBothPhysical()
131 {
132 TestHelpers.InMethod();
133
134 m_scene.AddSceneObject(m_so1);
135 m_scene.AddSceneObject(m_so2);
136
137 m_so1.ScriptSetPhysicsStatus(true);
138 m_so2.ScriptSetPhysicsStatus(true);
139
140 m_scene.LinkObjects(m_ownerId, m_so1.LocalId, new List<uint>() { m_so2.LocalId });
141
142 Assert.That(m_so1.RootPart.Flags, Is.EqualTo(PrimFlags.Physics));
143 Assert.That(m_so1.Parts[1].Flags, Is.EqualTo(PrimFlags.Physics));
144 }
145
146 /// <summary>
147 /// Test that linking results in the correct physical status for all linkees.
148 /// </summary>
149 [Test]
150 public void TestLinkPhysicsRootPhysicalOnly()
151 {
152 TestHelpers.InMethod();
153
154 m_scene.AddSceneObject(m_so1);
155 m_scene.AddSceneObject(m_so2);
156
157 m_so1.ScriptSetPhysicsStatus(true);
158
159 m_scene.LinkObjects(m_ownerId, m_so1.LocalId, new List<uint>() { m_so2.LocalId });
160
161 Assert.That(m_so1.RootPart.Flags, Is.EqualTo(PrimFlags.Physics));
162 Assert.That(m_so1.Parts[1].Flags, Is.EqualTo(PrimFlags.Physics));
163 }
164
165 /// <summary>
166 /// Test that linking results in the correct physical status for all linkees.
167 /// </summary>
168 [Test]
169 public void TestLinkPhysicsChildPhysicalOnly()
170 {
171 TestHelpers.InMethod();
172
173 m_scene.AddSceneObject(m_so1);
174 m_scene.AddSceneObject(m_so2);
175
176 m_so2.ScriptSetPhysicsStatus(true);
177
178 m_scene.LinkObjects(m_ownerId, m_so1.LocalId, new List<uint>() { m_so2.LocalId });
179
180 Assert.That(m_so1.RootPart.Flags, Is.EqualTo(PrimFlags.None));
181 Assert.That(m_so1.Parts[1].Flags, Is.EqualTo(PrimFlags.None));
182 }
65 } 183 }
66} \ No newline at end of file 184} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs
index c13d82e..c7eaff9 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs
@@ -58,7 +58,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
58 58
59 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001"); 59 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001");
60 60
61 TestScene scene = SceneHelpers.SetupScene(); 61 TestScene scene = new SceneHelpers().SetupScene();
62 IConfigSource configSource = new IniConfigSource(); 62 IConfigSource configSource = new IniConfigSource();
63 63
64 IConfig startupConfig = configSource.AddConfig("Startup"); 64 IConfig startupConfig = configSource.AddConfig("Startup");
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
index ed9b179..02c45ef 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
@@ -67,10 +67,12 @@ namespace OpenSim.Region.Framework.Scenes.Tests
67 public void Init() 67 public void Init()
68 { 68 {
69 TestHelpers.InMethod(); 69 TestHelpers.InMethod();
70 70
71 scene = SceneHelpers.SetupScene("Neighbour x", UUID.Random(), 1000, 1000); 71 SceneHelpers sh = new SceneHelpers();
72 scene2 = SceneHelpers.SetupScene("Neighbour x+1", UUID.Random(), 1001, 1000); 72
73 scene3 = SceneHelpers.SetupScene("Neighbour x-1", UUID.Random(), 999, 1000); 73 scene = sh.SetupScene("Neighbour x", UUID.Random(), 1000, 1000);
74 scene2 = sh.SetupScene("Neighbour x+1", UUID.Random(), 1001, 1000);
75 scene3 = sh.SetupScene("Neighbour x-1", UUID.Random(), 999, 1000);
74 76
75 ISharedRegionModule interregionComms = new LocalSimulationConnectorModule(); 77 ISharedRegionModule interregionComms = new LocalSimulationConnectorModule();
76 interregionComms.Initialise(new IniConfigSource()); 78 interregionComms.Initialise(new IniConfigSource());
@@ -99,9 +101,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests
99 public void TestCloseAgent() 101 public void TestCloseAgent()
100 { 102 {
101 TestHelpers.InMethod(); 103 TestHelpers.InMethod();
102// log4net.Config.XmlConfigurator.Configure(); 104// TestHelpers.EnableLogging();
103 105
104 TestScene scene = SceneHelpers.SetupScene(); 106 TestScene scene = new SceneHelpers().SetupScene();
105 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); 107 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1));
106 108
107 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Not.Null); 109 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Not.Null);
@@ -112,6 +114,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
112 Assert.That(scene.GetScenePresence(sp.UUID), Is.Null); 114 Assert.That(scene.GetScenePresence(sp.UUID), Is.Null);
113 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null); 115 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null);
114 Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(0)); 116 Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(0));
117
118// TestHelpers.DisableLogging();
115 } 119 }
116 120
117 [Test] 121 [Test]
@@ -126,7 +130,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
126 IConfig config = configSource.AddConfig("Modules"); 130 IConfig config = configSource.AddConfig("Modules");
127 config.Set("SimulationServices", "LocalSimulationConnectorModule"); 131 config.Set("SimulationServices", "LocalSimulationConnectorModule");
128 132
129 TestScene scene = SceneHelpers.SetupScene(); 133 SceneHelpers sceneHelpers = new SceneHelpers();
134 TestScene scene = sceneHelpers.SetupScene();
130 SceneHelpers.SetupSceneModules(scene, configSource, lsc); 135 SceneHelpers.SetupSceneModules(scene, configSource, lsc);
131 136
132 UUID agentId = TestHelpers.ParseTail(0x01); 137 UUID agentId = TestHelpers.ParseTail(0x01);
@@ -176,8 +181,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
176 181
177// UUID agent1Id = UUID.Parse("00000000-0000-0000-0000-000000000001"); 182// UUID agent1Id = UUID.Parse("00000000-0000-0000-0000-000000000001");
178 183
179 TestScene myScene1 = SceneHelpers.SetupScene("Neighbour y", UUID.Random(), 1000, 1000); 184 TestScene myScene1 = new SceneHelpers().SetupScene("Neighbour y", UUID.Random(), 1000, 1000);
180 TestScene myScene2 = SceneHelpers.SetupScene("Neighbour y + 1", UUID.Random(), 1001, 1000); 185 TestScene myScene2 = new SceneHelpers().SetupScene("Neighbour y + 1", UUID.Random(), 1001, 1000);
181 186
182 IConfigSource configSource = new IniConfigSource(); 187 IConfigSource configSource = new IniConfigSource();
183 IConfig config = configSource.AddConfig("Startup"); 188 IConfig config = configSource.AddConfig("Startup");
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs
index 89f8007..646e5fa 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs
@@ -59,7 +59,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
59 TestHelpers.InMethod(); 59 TestHelpers.InMethod();
60// log4net.Config.XmlConfigurator.Configure(); 60// log4net.Config.XmlConfigurator.Configure();
61 61
62 TestScene scene = SceneHelpers.SetupScene(); 62 TestScene scene = new SceneHelpers().SetupScene();
63 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); 63 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1));
64 sp.Flying = true; 64 sp.Flying = true;
65 sp.PhysicsCollisionUpdate(new CollisionEventUpdate()); 65 sp.PhysicsCollisionUpdate(new CollisionEventUpdate());
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs
index cfea10d..1d1ff88 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs
@@ -64,7 +64,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
64 [SetUp] 64 [SetUp]
65 public void Init() 65 public void Init()
66 { 66 {
67 m_scene = SceneHelpers.SetupScene(); 67 m_scene = new SceneHelpers().SetupScene();
68 } 68 }
69 69
70 [Test] 70 [Test]
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
index b7b8db4..493ab70 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic;
29using System.Reflection; 30using System.Reflection;
30using Nini.Config; 31using Nini.Config;
31using NUnit.Framework; 32using NUnit.Framework;
@@ -50,7 +51,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
50 [SetUp] 51 [SetUp]
51 public void Init() 52 public void Init()
52 { 53 {
53 m_scene = SceneHelpers.SetupScene(); 54 m_scene = new SceneHelpers().SetupScene();
54 m_sp = SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1)); 55 m_sp = SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1));
55 } 56 }
56 57
@@ -64,11 +65,13 @@ namespace OpenSim.Region.Framework.Scenes.Tests
64 Vector3 startPos = new Vector3(10.1f, 0, 0); 65 Vector3 startPos = new Vector3(10.1f, 0, 0);
65 m_sp.AbsolutePosition = startPos; 66 m_sp.AbsolutePosition = startPos;
66 67
67 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene); 68 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart;
68 69
69 m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero); 70 m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero);
70 71
71 Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); 72 Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero));
73 Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(0));
74 Assert.That(part.GetSittingAvatars(), Is.Null);
72 Assert.That(m_sp.ParentID, Is.EqualTo(0)); 75 Assert.That(m_sp.ParentID, Is.EqualTo(0));
73 } 76 }
74 77
@@ -82,11 +85,17 @@ namespace OpenSim.Region.Framework.Scenes.Tests
82 Vector3 startPos = new Vector3(9.9f, 0, 0); 85 Vector3 startPos = new Vector3(9.9f, 0, 0);
83 m_sp.AbsolutePosition = startPos; 86 m_sp.AbsolutePosition = startPos;
84 87
85 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene); 88 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart;
86 89
87 m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero); 90 m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero);
88 91
92 Assert.That(m_sp.PhysicsActor, Is.Null);
93
89 Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); 94 Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero));
95 Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(1));
96 HashSet<UUID> sittingAvatars = part.GetSittingAvatars();
97 Assert.That(sittingAvatars.Count, Is.EqualTo(1));
98 Assert.That(sittingAvatars.Contains(m_sp.UUID));
90 Assert.That(m_sp.ParentID, Is.EqualTo(part.LocalId)); 99 Assert.That(m_sp.ParentID, Is.EqualTo(part.LocalId));
91 } 100 }
92 101
@@ -100,14 +109,10 @@ namespace OpenSim.Region.Framework.Scenes.Tests
100 Vector3 startPos = new Vector3(1, 1, 1); 109 Vector3 startPos = new Vector3(1, 1, 1);
101 m_sp.AbsolutePosition = startPos; 110 m_sp.AbsolutePosition = startPos;
102 111
103 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene); 112 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart;
104 113
105 m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero); 114 m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero);
106 115
107 Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero));
108 Assert.That(m_sp.ParentID, Is.EqualTo(part.LocalId));
109 Assert.That(m_sp.PhysicsActor, Is.Null);
110
111 // FIXME: This is different for live avatars - z position is adjusted. This is half the height of the 116 // FIXME: This is different for live avatars - z position is adjusted. This is half the height of the
112 // default avatar. 117 // default avatar.
113 // Curiously, Vector3.ToString() will not display the last two places of the float. For example, 118 // Curiously, Vector3.ToString() will not display the last two places of the float. For example,
@@ -119,6 +124,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
119 m_sp.StandUp(); 124 m_sp.StandUp();
120 125
121 Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); 126 Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero));
127 Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(0));
128 Assert.That(part.GetSittingAvatars(), Is.Null);
122 Assert.That(m_sp.ParentID, Is.EqualTo(0)); 129 Assert.That(m_sp.ParentID, Is.EqualTo(0));
123 Assert.That(m_sp.PhysicsActor, Is.Not.Null); 130 Assert.That(m_sp.PhysicsActor, Is.Not.Null);
124 } 131 }
@@ -133,7 +140,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
133 Vector3 startPos = new Vector3(128, 128, 30); 140 Vector3 startPos = new Vector3(128, 128, 30);
134 m_sp.AbsolutePosition = startPos; 141 m_sp.AbsolutePosition = startPos;
135 142
136 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene); 143 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart;
137 part.SitTargetPosition = new Vector3(0, 0, 1); 144 part.SitTargetPosition = new Vector3(0, 0, 1);
138 145
139 m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero); 146 m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero);
@@ -145,11 +152,20 @@ namespace OpenSim.Region.Framework.Scenes.Tests
145 Is.EqualTo(part.AbsolutePosition + part.SitTargetPosition + ScenePresence.SIT_TARGET_ADJUSTMENT)); 152 Is.EqualTo(part.AbsolutePosition + part.SitTargetPosition + ScenePresence.SIT_TARGET_ADJUSTMENT));
146 Assert.That(m_sp.PhysicsActor, Is.Null); 153 Assert.That(m_sp.PhysicsActor, Is.Null);
147 154
155 Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(1));
156 HashSet<UUID> sittingAvatars = part.GetSittingAvatars();
157 Assert.That(sittingAvatars.Count, Is.EqualTo(1));
158 Assert.That(sittingAvatars.Contains(m_sp.UUID));
159
148 m_sp.StandUp(); 160 m_sp.StandUp();
149 161
150 Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); 162 Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero));
151 Assert.That(m_sp.ParentID, Is.EqualTo(0)); 163 Assert.That(m_sp.ParentID, Is.EqualTo(0));
152 Assert.That(m_sp.PhysicsActor, Is.Not.Null); 164 Assert.That(m_sp.PhysicsActor, Is.Not.Null);
165
166 Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero));
167 Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(0));
168 Assert.That(part.GetSittingAvatars(), Is.Null);
153 } 169 }
154 170
155 [Test] 171 [Test]
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
index bebc10c..a407f01 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
@@ -34,10 +34,14 @@ using OpenSim.Framework;
34using OpenSim.Framework.Communications; 34using OpenSim.Framework.Communications;
35using OpenSim.Framework.Servers; 35using OpenSim.Framework.Servers;
36using OpenSim.Region.Framework.Interfaces; 36using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.CoreModules.Framework;
38using OpenSim.Region.CoreModules.Framework.EntityTransfer;
37using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; 39using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
40using OpenSim.Region.CoreModules.World.Permissions;
38using OpenSim.Tests.Common; 41using OpenSim.Tests.Common;
39using OpenSim.Tests.Common.Mock; 42using OpenSim.Tests.Common.Mock;
40using System.Threading; 43using System.IO;
44using System.Text;
41 45
42namespace OpenSim.Region.Framework.Scenes.Tests 46namespace OpenSim.Region.Framework.Scenes.Tests
43{ 47{
@@ -47,145 +51,367 @@ namespace OpenSim.Region.Framework.Scenes.Tests
47 [TestFixture] 51 [TestFixture]
48 public class ScenePresenceTeleportTests 52 public class ScenePresenceTeleportTests
49 { 53 {
50 /// <summary> 54 [TestFixtureSetUp]
51 /// Test a teleport between two regions that are not neighbours and do not share any neighbours in common. 55 public void FixtureInit()
52 /// </summary> 56 {
53 /// Does not yet do what is says on the tin. 57 // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread.
54 /// Commenting for now 58 Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest;
55 //[Test, LongRunning] 59 }
56 public void TestSimpleNotNeighboursTeleport() 60
61 [TestFixtureTearDown]
62 public void TearDown()
63 {
64 // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple
65 // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression
66 // tests really shouldn't).
67 Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
68 }
69
70 [Test]
71 public void TestSameRegionTeleport()
57 { 72 {
58 TestHelpers.InMethod(); 73 TestHelpers.InMethod();
59 ThreadRunResults results = new ThreadRunResults(); 74// log4net.Config.XmlConfigurator.Configure();
60 results.Result = false; 75
61 results.Message = "Test did not run"; 76 EntityTransferModule etm = new EntityTransferModule();
62 TestRunning testClass = new TestRunning(results); 77
78 IConfigSource config = new IniConfigSource();
79 config.AddConfig("Modules");
80 // Not strictly necessary since FriendsModule assumes it is the default (!)
81 config.Configs["Modules"].Set("EntityTransferModule", etm.Name);
82
83 TestScene scene = new SceneHelpers().SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
84 SceneHelpers.SetupSceneModules(scene, config, etm);
85
86 Vector3 teleportPosition = new Vector3(10, 11, 12);
87 Vector3 teleportLookAt = new Vector3(20, 21, 22);
88
89 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1));
90 sp.AbsolutePosition = new Vector3(30, 31, 32);
91 scene.RequestTeleportLocation(
92 sp.ControllingClient,
93 scene.RegionInfo.RegionHandle,
94 teleportPosition,
95 teleportLookAt,
96 (uint)TeleportFlags.ViaLocation);
63 97
64 Thread testThread = new Thread(testClass.run); 98 Assert.That(sp.AbsolutePosition, Is.EqualTo(teleportPosition));
65 99
66 // Seems kind of redundant to start a thread and then join it, however.. We need to protect against 100 Assert.That(scene.GetRootAgentCount(), Is.EqualTo(1));
67 // A thread abort exception in the simulator code. 101 Assert.That(scene.GetChildAgentCount(), Is.EqualTo(0));
68 testThread.Start();
69 testThread.Join();
70 102
71 Assert.That(testClass.results.Result, Is.EqualTo(true), testClass.results.Message); 103 // Lookat is sent to the client only - sp.Lookat does not yield the same thing (calculation from camera
72 // Console.WriteLine("Beginning test {0}", MethodBase.GetCurrentMethod()); 104 // position instead).
105// Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt));
73 } 106 }
74 107
75 [TearDown] 108 [Test]
76 public void TearDown() 109 public void TestSameSimulatorSeparatedRegionsTeleport()
77 { 110 {
78 try 111 TestHelpers.InMethod();
79 { 112// log4net.Config.XmlConfigurator.Configure();
80 if (MainServer.Instance != null) MainServer.Instance.Stop(); 113
81 } 114 UUID userId = TestHelpers.ParseTail(0x1);
82 catch (NullReferenceException) 115
83 { } 116 EntityTransferModule etmA = new EntityTransferModule();
117 EntityTransferModule etmB = new EntityTransferModule();
118 LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
119
120 IConfigSource config = new IniConfigSource();
121 IConfig modulesConfig = config.AddConfig("Modules");
122 modulesConfig.Set("EntityTransferModule", etmA.Name);
123 modulesConfig.Set("SimulationServices", lscm.Name);
124 IConfig entityTransferConfig = config.AddConfig("EntityTransfer");
125
126 // In order to run a single threaded regression test we do not want the entity transfer module waiting
127 // for a callback from the destination scene before removing its avatar data.
128 entityTransferConfig.Set("wait_for_callback", false);
129
130 SceneHelpers sh = new SceneHelpers();
131 TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
132 TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1002, 1000);
133
134 SceneHelpers.SetupSceneModules(sceneA, config, etmA);
135 SceneHelpers.SetupSceneModules(sceneB, config, etmB);
136 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
137
138 Vector3 teleportPosition = new Vector3(10, 11, 12);
139 Vector3 teleportLookAt = new Vector3(20, 21, 22);
140
141 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId, sh.SceneManager);
142 sp.AbsolutePosition = new Vector3(30, 31, 32);
143
144 // XXX: A very nasty hack to tell the client about the destination scene without having to crank the whole
145 // UDP stack (?)
146// ((TestClient)sp.ControllingClient).TeleportTargetScene = sceneB;
147
148 sceneA.RequestTeleportLocation(
149 sp.ControllingClient,
150 sceneB.RegionInfo.RegionHandle,
151 teleportPosition,
152 teleportLookAt,
153 (uint)TeleportFlags.ViaLocation);
154
155 ((TestClient)sp.ControllingClient).CompleteTeleportClientSide();
156
157 Assert.That(sceneA.GetScenePresence(userId), Is.Null);
158
159 ScenePresence sceneBSp = sceneB.GetScenePresence(userId);
160 Assert.That(sceneBSp, Is.Not.Null);
161 Assert.That(sceneBSp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneB.RegionInfo.RegionName));
162 Assert.That(sceneBSp.AbsolutePosition, Is.EqualTo(teleportPosition));
163
164 Assert.That(sceneA.GetRootAgentCount(), Is.EqualTo(0));
165 Assert.That(sceneA.GetChildAgentCount(), Is.EqualTo(0));
166 Assert.That(sceneB.GetRootAgentCount(), Is.EqualTo(1));
167 Assert.That(sceneB.GetChildAgentCount(), Is.EqualTo(0));
168
169 // TODO: Add assertions to check correct circuit details in both scenes.
170
171 // Lookat is sent to the client only - sp.Lookat does not yield the same thing (calculation from camera
172 // position instead).
173// Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt));
84 } 174 }
85 175
86 } 176 /// <summary>
177 /// Test teleport procedures when the target simulator returns false when queried about access.
178 /// </summary>
179 [Test]
180 public void TestSameSimulatorSeparatedRegionsQueryAccessFails()
181 {
182 TestHelpers.InMethod();
183// TestHelpers.EnableLogging();
87 184
88 public class ThreadRunResults 185 UUID userId = TestHelpers.ParseTail(0x1);
89 { 186 Vector3 preTeleportPosition = new Vector3(30, 31, 32);
90 public bool Result = false;
91 public string Message = string.Empty;
92 }
93 187
94 public class TestRunning 188 EntityTransferModule etmA = new EntityTransferModule();
95 { 189 EntityTransferModule etmB = new EntityTransferModule();
96 public ThreadRunResults results; 190
97 public TestRunning(ThreadRunResults t) 191 LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
192
193 IConfigSource config = new IniConfigSource();
194 config.AddConfig("Modules");
195 config.Configs["Modules"].Set("EntityTransferModule", etmA.Name);
196 config.Configs["Modules"].Set("SimulationServices", lscm.Name);
197
198 config.AddConfig("EntityTransfer");
199
200 // In order to run a single threaded regression test we do not want the entity transfer module waiting
201 // for a callback from the destination scene before removing its avatar data.
202 config.Configs["EntityTransfer"].Set("wait_for_callback", false);
203
204 config.AddConfig("Startup");
205 config.Configs["Startup"].Set("serverside_object_permissions", true);
206
207 SceneHelpers sh = new SceneHelpers();
208 TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
209 TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1002, 1000);
210
211 SceneHelpers.SetupSceneModules(sceneA, config, etmA );
212
213 // We need to set up the permisions module on scene B so that our later use of agent limit to deny
214 // QueryAccess won't succeed anyway because administrators are always allowed in and the default
215 // IsAdministrator if no permissions module is present is true.
216 SceneHelpers.SetupSceneModules(sceneB, config, new object[] { new PermissionsModule(), etmB });
217
218 // Shared scene modules
219 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
220
221 Vector3 teleportPosition = new Vector3(10, 11, 12);
222 Vector3 teleportLookAt = new Vector3(20, 21, 22);
223
224 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId, sh.SceneManager);
225 sp.AbsolutePosition = preTeleportPosition;
226
227 // Make sceneB return false on query access
228 sceneB.RegionInfo.RegionSettings.AgentLimit = 0;
229
230 sceneA.RequestTeleportLocation(
231 sp.ControllingClient,
232 sceneB.RegionInfo.RegionHandle,
233 teleportPosition,
234 teleportLookAt,
235 (uint)TeleportFlags.ViaLocation);
236
237// ((TestClient)sp.ControllingClient).CompleteTeleportClientSide();
238
239 Assert.That(sceneB.GetScenePresence(userId), Is.Null);
240
241 ScenePresence sceneASp = sceneA.GetScenePresence(userId);
242 Assert.That(sceneASp, Is.Not.Null);
243 Assert.That(sceneASp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneA.RegionInfo.RegionName));
244 Assert.That(sceneASp.AbsolutePosition, Is.EqualTo(preTeleportPosition));
245
246 Assert.That(sceneA.GetRootAgentCount(), Is.EqualTo(1));
247 Assert.That(sceneA.GetChildAgentCount(), Is.EqualTo(0));
248 Assert.That(sceneB.GetRootAgentCount(), Is.EqualTo(0));
249 Assert.That(sceneB.GetChildAgentCount(), Is.EqualTo(0));
250
251 // TODO: Add assertions to check correct circuit details in both scenes.
252
253 // Lookat is sent to the client only - sp.Lookat does not yield the same thing (calculation from camera
254 // position instead).
255// Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt));
256
257// TestHelpers.DisableLogging();
258 }
259
260 /// <summary>
261 /// Test teleport procedures when the target simulator create agent step is refused.
262 /// </summary>
263 [Test]
264 public void TestSameSimulatorSeparatedRegionsCreateAgentFails()
98 { 265 {
99 results = t; 266 TestHelpers.InMethod();
267// TestHelpers.EnableLogging();
268
269 UUID userId = TestHelpers.ParseTail(0x1);
270 Vector3 preTeleportPosition = new Vector3(30, 31, 32);
271
272 EntityTransferModule etmA = new EntityTransferModule();
273 EntityTransferModule etmB = new EntityTransferModule();
274 LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
275
276 IConfigSource config = new IniConfigSource();
277 config.AddConfig("Modules");
278 config.Configs["Modules"].Set("EntityTransferModule", etmA.Name);
279 config.Configs["Modules"].Set("SimulationServices", lscm.Name);
280
281 config.AddConfig("EntityTransfer");
282
283 // In order to run a single threaded regression test we do not want the entity transfer module waiting
284 // for a callback from the destination scene before removing its avatar data.
285 config.Configs["EntityTransfer"].Set("wait_for_callback", false);
286
287 SceneHelpers sh = new SceneHelpers();
288 TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
289 TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1002, 1000);
290
291 SceneHelpers.SetupSceneModules(sceneA, config, etmA);
292 SceneHelpers.SetupSceneModules(sceneB, config, etmB);
293
294 // Shared scene modules
295 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
296
297 Vector3 teleportPosition = new Vector3(10, 11, 12);
298 Vector3 teleportLookAt = new Vector3(20, 21, 22);
299
300 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId, sh.SceneManager);
301 sp.AbsolutePosition = preTeleportPosition;
302
303 // Make sceneB refuse CreateAgent
304 sceneB.LoginsDisabled = true;
305
306 sceneA.RequestTeleportLocation(
307 sp.ControllingClient,
308 sceneB.RegionInfo.RegionHandle,
309 teleportPosition,
310 teleportLookAt,
311 (uint)TeleportFlags.ViaLocation);
312
313// ((TestClient)sp.ControllingClient).CompleteTeleportClientSide();
314
315 Assert.That(sceneB.GetScenePresence(userId), Is.Null);
316
317 ScenePresence sceneASp = sceneA.GetScenePresence(userId);
318 Assert.That(sceneASp, Is.Not.Null);
319 Assert.That(sceneASp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneA.RegionInfo.RegionName));
320 Assert.That(sceneASp.AbsolutePosition, Is.EqualTo(preTeleportPosition));
321
322 Assert.That(sceneA.GetRootAgentCount(), Is.EqualTo(1));
323 Assert.That(sceneA.GetChildAgentCount(), Is.EqualTo(0));
324 Assert.That(sceneB.GetRootAgentCount(), Is.EqualTo(0));
325 Assert.That(sceneB.GetChildAgentCount(), Is.EqualTo(0));
326
327 // TODO: Add assertions to check correct circuit details in both scenes.
328
329 // Lookat is sent to the client only - sp.Lookat does not yield the same thing (calculation from camera
330 // position instead).
331// Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt));
332
333// TestHelpers.DisableLogging();
100 } 334 }
101 public void run(object o) 335
336 [Test]
337 public void TestSameSimulatorNeighbouringRegionsTeleport()
102 { 338 {
103 339 TestHelpers.InMethod();
104 //results.Result = true; 340// TestHelpers.EnableLogging();
105 log4net.Config.XmlConfigurator.Configure(); 341
106 342 UUID userId = TestHelpers.ParseTail(0x1);
107 UUID sceneAId = UUID.Parse("00000000-0000-0000-0000-000000000100"); 343
108 UUID sceneBId = UUID.Parse("00000000-0000-0000-0000-000000000200"); 344 EntityTransferModule etmA = new EntityTransferModule();
109 345 EntityTransferModule etmB = new EntityTransferModule();
110 // shared module 346 LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
111 ISharedRegionModule interregionComms = new LocalSimulationConnectorModule(); 347
112 348 IConfigSource config = new IniConfigSource();
113 349 IConfig modulesConfig = config.AddConfig("Modules");
114 Scene sceneB = SceneHelpers.SetupScene("sceneB", sceneBId, 1010, 1010); 350 modulesConfig.Set("EntityTransferModule", etmA.Name);
115 SceneHelpers.SetupSceneModules(sceneB, new IniConfigSource(), interregionComms); 351 modulesConfig.Set("SimulationServices", lscm.Name);
116 sceneB.RegisterRegionWithGrid(); 352 IConfig entityTransferConfig = config.AddConfig("EntityTransfer");
117 353
118 Scene sceneA = SceneHelpers.SetupScene("sceneA", sceneAId, 1000, 1000); 354 // In order to run a single threaded regression test we do not want the entity transfer module waiting
119 SceneHelpers.SetupSceneModules(sceneA, new IniConfigSource(), interregionComms); 355 // for a callback from the destination scene before removing its avatar data.
120 sceneA.RegisterRegionWithGrid(); 356 entityTransferConfig.Set("wait_for_callback", false);
121 357
122 UUID agentId = UUID.Parse("00000000-0000-0000-0000-000000000041"); 358 SceneHelpers sh = new SceneHelpers();
123 TestClient client = (TestClient)SceneHelpers.AddScenePresence(sceneA, agentId).ControllingClient; 359 TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
124 360 TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1001, 1000);
125 ICapabilitiesModule sceneACapsModule = sceneA.RequestModuleInterface<ICapabilitiesModule>(); 361
126 362 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
127 results.Result = (sceneACapsModule.GetCapsPath(agentId) == client.CapsSeedUrl); 363 SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA);
128 364 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB);
129 if (!results.Result) 365
130 { 366 Vector3 teleportPosition = new Vector3(10, 11, 12);
131 results.Message = "Incorrect caps object path set up in sceneA"; 367 Vector3 teleportLookAt = new Vector3(20, 21, 22);
132 return; 368
133 } 369 ScenePresence originalSp = SceneHelpers.AddScenePresence(sceneA, userId, sh.SceneManager);
134 370 originalSp.AbsolutePosition = new Vector3(30, 31, 32);
135 /* 371
136 Assert.That( 372 ScenePresence beforeSceneASp = sceneA.GetScenePresence(userId);
137 sceneACapsModule.GetCapsPath(agentId), 373 Assert.That(beforeSceneASp, Is.Not.Null);
138 Is.EqualTo(client.CapsSeedUrl), 374 Assert.That(beforeSceneASp.IsChildAgent, Is.False);
139 "Incorrect caps object path set up in sceneA"); 375
140 */ 376 ScenePresence beforeSceneBSp = sceneB.GetScenePresence(userId);
141 // FIXME: This is a hack to get the test working - really the normal OpenSim mechanisms should be used. 377 Assert.That(beforeSceneBSp, Is.Not.Null);
142 378 Assert.That(beforeSceneBSp.IsChildAgent, Is.True);
143 379
144 client.TeleportTargetScene = sceneB; 380 // XXX: A very nasty hack to tell the client about the destination scene without having to crank the whole
145 client.Teleport(sceneB.RegionInfo.RegionHandle, new Vector3(100, 100, 100), new Vector3(40, 40, 40)); 381 // UDP stack (?)
146 382// ((TestClient)beforeSceneASp.ControllingClient).TeleportTargetScene = sceneB;
147 results.Result = (sceneB.GetScenePresence(agentId) != null); 383
148 if (!results.Result) 384 sceneA.RequestTeleportLocation(
149 { 385 beforeSceneASp.ControllingClient,
150 results.Message = "Client does not have an agent in sceneB"; 386 sceneB.RegionInfo.RegionHandle,
151 return; 387 teleportPosition,
152 } 388 teleportLookAt,
153 389 (uint)TeleportFlags.ViaLocation);
154 //Assert.That(sceneB.GetScenePresence(agentId), Is.Not.Null, "Client does not have an agent in sceneB"); 390
155 391 ((TestClient)beforeSceneASp.ControllingClient).CompleteTeleportClientSide();
156 //Assert.That(sceneA.GetScenePresence(agentId), Is.Null, "Client still had an agent in sceneA"); 392
157 393 ScenePresence afterSceneASp = sceneA.GetScenePresence(userId);
158 results.Result = (sceneA.GetScenePresence(agentId) == null); 394 Assert.That(afterSceneASp, Is.Not.Null);
159 if (!results.Result) 395 Assert.That(afterSceneASp.IsChildAgent, Is.True);
160 { 396
161 results.Message = "Client still had an agent in sceneA"; 397 ScenePresence afterSceneBSp = sceneB.GetScenePresence(userId);
162 return; 398 Assert.That(afterSceneBSp, Is.Not.Null);
163 } 399 Assert.That(afterSceneBSp.IsChildAgent, Is.False);
164 400 Assert.That(afterSceneBSp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneB.RegionInfo.RegionName));
165 ICapabilitiesModule sceneBCapsModule = sceneB.RequestModuleInterface<ICapabilitiesModule>(); 401 Assert.That(afterSceneBSp.AbsolutePosition, Is.EqualTo(teleportPosition));
166 402
167 403 Assert.That(sceneA.GetRootAgentCount(), Is.EqualTo(0));
168 results.Result = ("http://" + sceneB.RegionInfo.ExternalHostName + ":" + sceneB.RegionInfo.HttpPort + 404 Assert.That(sceneA.GetChildAgentCount(), Is.EqualTo(1));
169 "/CAPS/" + sceneBCapsModule.GetCapsPath(agentId) + "0000/" == client.CapsSeedUrl); 405 Assert.That(sceneB.GetRootAgentCount(), Is.EqualTo(1));
170 if (!results.Result) 406 Assert.That(sceneB.GetChildAgentCount(), Is.EqualTo(0));
171 { 407
172 results.Message = "Incorrect caps object path set up in sceneB"; 408 // TODO: Add assertions to check correct circuit details in both scenes.
173 return; 409
174 } 410 // Lookat is sent to the client only - sp.Lookat does not yield the same thing (calculation from camera
175 411 // position instead).
176 // Temporary assertion - caps url construction should at least be doable through a method. 412// Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt));
177 /* 413
178 Assert.That( 414// TestHelpers.DisableLogging();
179 "http://" + sceneB.RegionInfo.ExternalHostName + ":" + sceneB.RegionInfo.HttpPort + "/CAPS/" + sceneBCapsModule.GetCapsPath(agentId) + "0000/",
180 Is.EqualTo(client.CapsSeedUrl),
181 "Incorrect caps object path set up in sceneB");
182 */
183 // This assertion will currently fail since we don't remove the caps paths when no longer needed
184 //Assert.That(sceneACapsModule.GetCapsPath(agentId), Is.Null, "sceneA still had a caps object path");
185
186 // TODO: Check that more of everything is as it should be
187
188 // TODO: test what happens if we try to teleport to a region that doesn't exist
189 } 415 }
190 } 416 }
191} 417} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
index 5c9a77d..d722a09 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
@@ -60,7 +60,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
60 { 60 {
61 TestHelpers.InMethod(); 61 TestHelpers.InMethod();
62 62
63 Scene scene = SceneHelpers.SetupScene(); 63 Scene scene = new SceneHelpers().SetupScene();
64 scene.Update(1); 64 scene.Update(1);
65 65
66 Assert.That(scene.Frame, Is.EqualTo(1)); 66 Assert.That(scene.Frame, Is.EqualTo(1));
diff --git a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
index 55c80f5..a51e4e3 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
@@ -58,7 +58,7 @@ namespace OpenSim.Region.Framework.Tests
58 TestHelpers.InMethod(); 58 TestHelpers.InMethod();
59// log4net.Config.XmlConfigurator.Configure(); 59// log4net.Config.XmlConfigurator.Configure();
60 60
61 Scene scene = SceneHelpers.SetupScene(); 61 Scene scene = new SceneHelpers().SetupScene();
62 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene); 62 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene);
63 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, user1.PrincipalID); 63 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, user1.PrincipalID);
64 SceneObjectPart sop1 = sog1.RootPart; 64 SceneObjectPart sop1 = sog1.RootPart;
@@ -81,7 +81,7 @@ namespace OpenSim.Region.Framework.Tests
81 TestHelpers.InMethod(); 81 TestHelpers.InMethod();
82// log4net.Config.XmlConfigurator.Configure(); 82// log4net.Config.XmlConfigurator.Configure();
83 83
84 Scene scene = SceneHelpers.SetupScene(); 84 Scene scene = new SceneHelpers().SetupScene();
85 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene); 85 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene);
86 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, user1.PrincipalID); 86 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, user1.PrincipalID);
87 SceneObjectPart sop1 = sog1.RootPart; 87 SceneObjectPart sop1 = sog1.RootPart;
@@ -124,11 +124,13 @@ namespace OpenSim.Region.Framework.Tests
124 TestHelpers.InMethod(); 124 TestHelpers.InMethod();
125// log4net.Config.XmlConfigurator.Configure(); 125// log4net.Config.XmlConfigurator.Configure();
126 126
127 Scene scene = SceneHelpers.SetupScene(); 127 Scene scene = new SceneHelpers().SetupScene();
128 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene); 128 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene);
129 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, user1.PrincipalID); 129 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, user1.PrincipalID);
130 SceneObjectPart sop1 = sog1.RootPart; 130 SceneObjectPart sop1 = sog1.RootPart;
131 TaskInventoryItem sopItem1 = TaskInventoryHelpers.AddNotecard(scene, sop1); 131 TaskInventoryItem sopItem1
132 = TaskInventoryHelpers.AddNotecard(
133 scene, sop1, "ncItem", TestHelpers.ParseTail(0x800), TestHelpers.ParseTail(0x900));
132 134
133 InventoryFolderBase folder 135 InventoryFolderBase folder
134 = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, user1.PrincipalID, "Objects")[0]; 136 = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, user1.PrincipalID, "Objects")[0];
@@ -153,11 +155,14 @@ namespace OpenSim.Region.Framework.Tests
153 TestHelpers.InMethod(); 155 TestHelpers.InMethod();
154// log4net.Config.XmlConfigurator.Configure(); 156// log4net.Config.XmlConfigurator.Configure();
155 157
156 Scene scene = SceneHelpers.SetupScene(); 158 Scene scene = new SceneHelpers().SetupScene();
157 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene); 159 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene);
158 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, user1.PrincipalID); 160 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, user1.PrincipalID);
161
159 SceneObjectPart sop1 = sog1.RootPart; 162 SceneObjectPart sop1 = sog1.RootPart;
160 TaskInventoryItem sopItem1 = TaskInventoryHelpers.AddNotecard(scene, sop1); 163 TaskInventoryItem sopItem1
164 = TaskInventoryHelpers.AddNotecard(
165 scene, sop1, "ncItem", TestHelpers.ParseTail(0x800), TestHelpers.ParseTail(0x900));
161 166
162 // Perform test 167 // Perform test
163 scene.MoveTaskInventoryItem(user1.PrincipalID, UUID.Zero, sop1, sopItem1.ItemID); 168 scene.MoveTaskInventoryItem(user1.PrincipalID, UUID.Zero, sop1, sopItem1.ItemID);
diff --git a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs
index 55fc1e7..44d2d45 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs
@@ -58,7 +58,7 @@ namespace OpenSim.Region.Framework.Tests
58 TestHelpers.InMethod(); 58 TestHelpers.InMethod();
59// log4net.Config.XmlConfigurator.Configure(); 59// log4net.Config.XmlConfigurator.Configure();
60 60
61 Scene scene = SceneHelpers.SetupScene(); 61 Scene scene = new SceneHelpers().SetupScene();
62 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001)); 62 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001));
63 UserAccount user2 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1002)); 63 UserAccount user2 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1002));
64 InventoryItemBase item1 = UserInventoryHelpers.CreateInventoryItem(scene, "item1", user1.PrincipalID); 64 InventoryItemBase item1 = UserInventoryHelpers.CreateInventoryItem(scene, "item1", user1.PrincipalID);
@@ -85,7 +85,7 @@ namespace OpenSim.Region.Framework.Tests
85 TestHelpers.InMethod(); 85 TestHelpers.InMethod();
86// log4net.Config.XmlConfigurator.Configure(); 86// log4net.Config.XmlConfigurator.Configure();
87 87
88 Scene scene = SceneHelpers.SetupScene(); 88 Scene scene = new SceneHelpers().SetupScene();
89 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001)); 89 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001));
90 UserAccount user2 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1002)); 90 UserAccount user2 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1002));
91 InventoryFolderBase folder1 91 InventoryFolderBase folder1
diff --git a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
index d9fe87c..198e487 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
@@ -47,7 +47,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
47 public void Init() 47 public void Init()
48 { 48 {
49 // FIXME: We don't need a full scene here - it would be enough to set up the asset service. 49 // FIXME: We don't need a full scene here - it would be enough to set up the asset service.
50 Scene scene = SceneHelpers.SetupScene(); 50 Scene scene = new SceneHelpers().SetupScene();
51 m_assetService = scene.AssetService; 51 m_assetService = scene.AssetService;
52 m_uuidGatherer = new UuidGatherer(m_assetService); 52 m_uuidGatherer = new UuidGatherer(m_assetService);
53 } 53 }
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index eac8e84..17a210b 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -44,7 +44,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
44{ 44{
45 public delegate void OnIRCClientReadyDelegate(IRCClientView cv); 45 public delegate void OnIRCClientReadyDelegate(IRCClientView cv);
46 46
47 public class IRCClientView : IClientAPI, IClientCore, IClientIPEndpoint 47 public class IRCClientView : IClientAPI, IClientCore
48 { 48 {
49 public event OnIRCClientReadyDelegate OnIRCReady; 49 public event OnIRCClientReadyDelegate OnIRCReady;
50 50
@@ -1440,11 +1440,6 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1440 Disconnect(); 1440 Disconnect();
1441 } 1441 }
1442 1442
1443 public EndPoint GetClientEP()
1444 {
1445 return null;
1446 }
1447
1448 public ClientInfo GetClientInfo() 1443 public ClientInfo GetClientInfo()
1449 { 1444 {
1450 return new ClientInfo(); 1445 return new ClientInfo();
@@ -1635,11 +1630,6 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1635 1630
1636 } 1631 }
1637 1632
1638 public void KillEndDone()
1639 {
1640
1641 }
1642
1643 public bool AddGenericPacketHandler(string MethodName, GenericMessage handler) 1633 public bool AddGenericPacketHandler(string MethodName, GenericMessage handler)
1644 { 1634 {
1645 return true; 1635 return true;
@@ -1647,15 +1637,6 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1647 1637
1648 #endregion 1638 #endregion
1649 1639
1650 #region Implementation of IClientIPEndpoint
1651
1652 public IPAddress EndPoint
1653 {
1654 get { return ((IPEndPoint) m_client.Client.RemoteEndPoint).Address; }
1655 }
1656
1657 #endregion
1658
1659 public void SendRebakeAvatarTextures(UUID textureID) 1640 public void SendRebakeAvatarTextures(UUID textureID)
1660 { 1641 {
1661 } 1642 }
diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs
new file mode 100644
index 0000000..1b9e3ac
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs
@@ -0,0 +1,195 @@
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.Linq;
31using System.Reflection;
32using System.Text;
33using log4net;
34using Mono.Addins;
35using Nini.Config;
36using OpenMetaverse;
37using OpenSim.Framework;
38using OpenSim.Framework.Console;
39using OpenSim.Framework.Statistics;
40using OpenSim.Region.ClientStack.LindenUDP;
41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes;
43
44namespace OpenSim.Region.OptionalModules.Avatar.Attachments
45{
46 /// <summary>
47 /// A module that just holds commands for inspecting avatar appearance.
48 /// </summary>
49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AttachmentsCommandModule")]
50 public class AttachmentsCommandModule : ISharedRegionModule
51 {
52// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
54 private List<Scene> m_scenes = new List<Scene>();
55// private IAvatarFactoryModule m_avatarFactory;
56
57 public string Name { get { return "Attachments Command Module"; } }
58
59 public Type ReplaceableInterface { get { return null; } }
60
61 public void Initialise(IConfigSource source)
62 {
63// m_log.DebugFormat("[ATTACHMENTS COMMAND MODULE]: INITIALIZED MODULE");
64 }
65
66 public void PostInitialise()
67 {
68// m_log.DebugFormat("[ATTACHMENTS COMMAND MODULE]: POST INITIALIZED MODULE");
69 }
70
71 public void Close()
72 {
73// m_log.DebugFormat("[ATTACHMENTS COMMAND MODULE]: CLOSED MODULE");
74 }
75
76 public void AddRegion(Scene scene)
77 {
78// m_log.DebugFormat("[ATTACHMENTS COMMAND MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName);
79 }
80
81 public void RemoveRegion(Scene scene)
82 {
83// m_log.DebugFormat("[ATTACHMENTS COMMAND MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName);
84
85 lock (m_scenes)
86 m_scenes.Remove(scene);
87 }
88
89 public void RegionLoaded(Scene scene)
90 {
91// m_log.DebugFormat("[ATTACHMENTS COMMAND MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName);
92
93 lock (m_scenes)
94 m_scenes.Add(scene);
95
96 scene.AddCommand(
97 "Users", this, "attachments show",
98 "attachments show [<first-name> <last-name>]",
99 "Show attachment information for avatars in this simulator.",
100 HandleShowAttachmentsCommand);
101 }
102
103 protected void HandleShowAttachmentsCommand(string module, string[] cmd)
104 {
105 if (cmd.Length != 2 && cmd.Length < 4)
106 {
107 MainConsole.Instance.OutputFormat("Usage: attachments show [<first-name> <last-name>]");
108 return;
109 }
110
111 bool targetNameSupplied = false;
112 string optionalTargetFirstName = null;
113 string optionalTargetLastName = null;
114
115 if (cmd.Length >= 4)
116 {
117 targetNameSupplied = true;
118 optionalTargetFirstName = cmd[2];
119 optionalTargetLastName = cmd[3];
120 }
121
122 StringBuilder sb = new StringBuilder();
123
124 lock (m_scenes)
125 {
126 foreach (Scene scene in m_scenes)
127 {
128 if (targetNameSupplied)
129 {
130 ScenePresence sp = scene.GetScenePresence(optionalTargetFirstName, optionalTargetLastName);
131 if (sp != null && !sp.IsChildAgent)
132 GetAttachmentsReport(sp, sb);
133 }
134 else
135 {
136 scene.ForEachRootScenePresence(sp => GetAttachmentsReport(sp, sb));
137 }
138 }
139 }
140
141 MainConsole.Instance.Output(sb.ToString());
142 }
143
144 private void GetAttachmentsReport(ScenePresence sp, StringBuilder sb)
145 {
146 sb.AppendFormat("Attachments for {0}\n", sp.Name);
147
148 ConsoleDisplayTable ct = new ConsoleDisplayTable() { Indent = 2 };
149 ct.Columns.Add(new ConsoleDisplayTableColumn("Attachment Name", 36));
150 ct.Columns.Add(new ConsoleDisplayTableColumn("Local ID", 10));
151 ct.Columns.Add(new ConsoleDisplayTableColumn("Item ID", 36));
152 ct.Columns.Add(new ConsoleDisplayTableColumn("Attach Point", 14));
153 ct.Columns.Add(new ConsoleDisplayTableColumn("Position", 15));
154
155// sb.AppendFormat(
156// " {0,-36} {1,-10} {2,-36} {3,-14} {4,-15}\n",
157// "Attachment Name", "Local ID", "Item ID", "Attach Point", "Position");
158
159 List<SceneObjectGroup> attachmentObjects = sp.GetAttachments();
160 foreach (SceneObjectGroup attachmentObject in attachmentObjects)
161 {
162// InventoryItemBase attachmentItem
163// = m_scenes[0].InventoryService.GetItem(new InventoryItemBase(attachmentObject.FromItemID));
164
165// if (attachmentItem == null)
166// {
167// sb.AppendFormat(
168// "WARNING: Couldn't find attachment for item {0} at point {1}\n",
169// attachmentData.ItemID, (AttachmentPoint)attachmentData.AttachPoint);
170// continue;
171// }
172// else
173// {
174// sb.AppendFormat(
175// " {0,-36} {1,-10} {2,-36} {3,-14} {4,-15}\n",
176// attachmentObject.Name, attachmentObject.LocalId, attachmentObject.FromItemID,
177// (AttachmentPoint)attachmentObject.AttachmentPoint, attachmentObject.RootPart.AttachedPos);
178 ct.Rows.Add(
179 new ConsoleDisplayTableRow(
180 new List<string>()
181 {
182 attachmentObject.Name,
183 attachmentObject.LocalId.ToString(),
184 attachmentObject.FromItemID.ToString(),
185 ((AttachmentPoint)attachmentObject.AttachmentPoint).ToString(),
186 attachmentObject.RootPart.AttachedPos.ToString()
187 }));
188// }
189 }
190
191 ct.AddToStringBuilder(sb);
192 sb.Append("\n");
193 }
194 }
195} \ No newline at end of file
diff --git a/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs b/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs
index e68f9d0..2602050 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs
@@ -58,6 +58,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Friends
58 private Scene m_scene; 58 private Scene m_scene;
59 private IFriendsModule m_friendsModule; 59 private IFriendsModule m_friendsModule;
60 private IUserManagement m_userManagementModule; 60 private IUserManagement m_userManagementModule;
61 private IPresenceService m_presenceService;
61 62
62// private IAvatarFactoryModule m_avatarFactory; 63// private IAvatarFactoryModule m_avatarFactory;
63 64
@@ -99,8 +100,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Friends
99 100
100 m_friendsModule = m_scene.RequestModuleInterface<IFriendsModule>(); 101 m_friendsModule = m_scene.RequestModuleInterface<IFriendsModule>();
101 m_userManagementModule = m_scene.RequestModuleInterface<IUserManagement>(); 102 m_userManagementModule = m_scene.RequestModuleInterface<IUserManagement>();
103 m_presenceService = m_scene.RequestModuleInterface<IPresenceService>();
102 104
103 if (m_friendsModule != null && m_userManagementModule != null) 105 if (m_friendsModule != null && m_userManagementModule != null && m_presenceService != null)
104 { 106 {
105 m_scene.AddCommand( 107 m_scene.AddCommand(
106 "Friends", this, "friends show", 108 "Friends", this, "friends show",
@@ -162,7 +164,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Friends
162 164
163 MainConsole.Instance.OutputFormat("Friends for {0} {1} {2}:", firstName, lastName, userId); 165 MainConsole.Instance.OutputFormat("Friends for {0} {1} {2}:", firstName, lastName, userId);
164 166
165 MainConsole.Instance.OutputFormat("UUID, Name, MyFlags, TheirFlags"); 167 MainConsole.Instance.OutputFormat(
168 "{0,-36} {1,-36} {2,-7} {3,7} {4,10}", "UUID", "Name", "Status", "MyFlags", "TheirFlags");
166 169
167 foreach (FriendInfo friend in friends) 170 foreach (FriendInfo friend in friends)
168 { 171 {
@@ -175,14 +178,22 @@ namespace OpenSim.Region.OptionalModules.Avatar.Friends
175 178
176 UUID friendId; 179 UUID friendId;
177 string friendName; 180 string friendName;
181 string onlineText;
178 182
179 if (UUID.TryParse(friend.Friend, out friendId)) 183 if (UUID.TryParse(friend.Friend, out friendId))
180 friendName = m_userManagementModule.GetUserName(friendId); 184 friendName = m_userManagementModule.GetUserName(friendId);
181 else 185 else
182 friendName = friend.Friend; 186 friendName = friend.Friend;
183 187
188 OpenSim.Services.Interfaces.PresenceInfo[] pi = m_presenceService.GetAgents(new string[] { friend.Friend });
189 if (pi.Length > 0)
190 onlineText = "online";
191 else
192 onlineText = "offline";
193
184 MainConsole.Instance.OutputFormat( 194 MainConsole.Instance.OutputFormat(
185 "{0} {1} {2} {3}", friend.Friend, friendName, friend.MyFlags, friend.TheirFlags); 195 "{0,-36} {1,-36} {2,-7} {3,-7} {4,-10}",
196 friend.Friend, friendName, onlineText, friend.MyFlags, friend.TheirFlags);
186 } 197 }
187 } 198 }
188 } 199 }
diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
index 8af3652..7b20446 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
@@ -306,30 +306,35 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
306 agentID, caps, scene.RegionInfo.RegionName); 306 agentID, caps, scene.RegionInfo.RegionName);
307 307
308 string capsBase = "/CAPS/" + caps.CapsObjectPath; 308 string capsBase = "/CAPS/" + caps.CapsObjectPath;
309 caps.RegisterHandler("ProvisionVoiceAccountRequest", 309 caps.RegisterHandler(
310 new RestStreamHandler("POST", capsBase + m_provisionVoiceAccountRequestPath, 310 "ProvisionVoiceAccountRequest",
311 delegate(string request, string path, string param, 311 new RestStreamHandler(
312 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 312 "POST",
313 { 313 capsBase + m_provisionVoiceAccountRequestPath,
314 return ProvisionVoiceAccountRequest(scene, request, path, param, 314 (request, path, param, httpRequest, httpResponse)
315 agentID, caps); 315 => ProvisionVoiceAccountRequest(scene, request, path, param, agentID, caps),
316 })); 316 "ProvisionVoiceAccountRequest",
317 caps.RegisterHandler("ParcelVoiceInfoRequest", 317 agentID.ToString()));
318 new RestStreamHandler("POST", capsBase + m_parcelVoiceInfoRequestPath, 318
319 delegate(string request, string path, string param, 319 caps.RegisterHandler(
320 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 320 "ParcelVoiceInfoRequest",
321 { 321 new RestStreamHandler(
322 return ParcelVoiceInfoRequest(scene, request, path, param, 322 "POST",
323 agentID, caps); 323 capsBase + m_parcelVoiceInfoRequestPath,
324 })); 324 (request, path, param, httpRequest, httpResponse)
325 caps.RegisterHandler("ChatSessionRequest", 325 => ParcelVoiceInfoRequest(scene, request, path, param, agentID, caps),
326 new RestStreamHandler("POST", capsBase + m_chatSessionRequestPath, 326 "ParcelVoiceInfoRequest",
327 delegate(string request, string path, string param, 327 agentID.ToString()));
328 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 328
329 { 329 caps.RegisterHandler(
330 return ChatSessionRequest(scene, request, path, param, 330 "ChatSessionRequest",
331 agentID, caps); 331 new RestStreamHandler(
332 })); 332 "POST",
333 capsBase + m_chatSessionRequestPath,
334 (request, path, param, httpRequest, httpResponse)
335 => ChatSessionRequest(scene, request, path, param, agentID, caps),
336 "ChatSessionRequest",
337 agentID.ToString()));
333 } 338 }
334 339
335 /// <summary> 340 /// <summary>
@@ -818,11 +823,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
818 m_log.DebugFormat("[FreeSwitchVoice]: Region:Parcel \"{0}\": parcel id {1}: using channel name {2}", 823 m_log.DebugFormat("[FreeSwitchVoice]: Region:Parcel \"{0}\": parcel id {1}: using channel name {2}",
819 landName, land.LocalID, landUUID); 824 landName, land.LocalID, landUUID);
820 } 825 }
821 System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
822 826
823 // slvoice handles the sip address differently if it begins with confctl, hiding it from the user in the friends list. however it also disables 827 // slvoice handles the sip address differently if it begins with confctl, hiding it from the user in the friends list. however it also disables
824 // the personal speech indicators as well unless some siren14-3d codec magic happens. we dont have siren143d so we'll settle for the personal speech indicator. 828 // the personal speech indicators as well unless some siren14-3d codec magic happens. we dont have siren143d so we'll settle for the personal speech indicator.
825 channelUri = String.Format("sip:conf-{0}@{1}", "x" + Convert.ToBase64String(encoding.GetBytes(landUUID)), m_freeSwitchRealm); 829 channelUri = String.Format("sip:conf-{0}@{1}", "x" + Convert.ToBase64String(Encoding.ASCII.GetBytes(landUUID)), m_freeSwitchRealm);
826 830
827 lock (m_ParcelAddress) 831 lock (m_ParcelAddress)
828 { 832 {
diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
index 4dbac1d..396d4c5 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
@@ -406,30 +406,36 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
406 m_log.DebugFormat("[VivoxVoice] OnRegisterCaps: agentID {0} caps {1}", agentID, caps); 406 m_log.DebugFormat("[VivoxVoice] OnRegisterCaps: agentID {0} caps {1}", agentID, caps);
407 407
408 string capsBase = "/CAPS/" + caps.CapsObjectPath; 408 string capsBase = "/CAPS/" + caps.CapsObjectPath;
409 caps.RegisterHandler("ProvisionVoiceAccountRequest", 409
410 new RestStreamHandler("POST", capsBase + m_provisionVoiceAccountRequestPath, 410 caps.RegisterHandler(
411 delegate(string request, string path, string param, 411 "ProvisionVoiceAccountRequest",
412 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 412 new RestStreamHandler(
413 { 413 "POST",
414 return ProvisionVoiceAccountRequest(scene, request, path, param, 414 capsBase + m_provisionVoiceAccountRequestPath,
415 agentID, caps); 415 (request, path, param, httpRequest, httpResponse)
416 })); 416 => ProvisionVoiceAccountRequest(scene, request, path, param, agentID, caps),
417 caps.RegisterHandler("ParcelVoiceInfoRequest", 417 "ProvisionVoiceAccountRequest",
418 new RestStreamHandler("POST", capsBase + m_parcelVoiceInfoRequestPath, 418 agentID.ToString()));
419 delegate(string request, string path, string param, 419
420 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 420 caps.RegisterHandler(
421 { 421 "ParcelVoiceInfoRequest",
422 return ParcelVoiceInfoRequest(scene, request, path, param, 422 new RestStreamHandler(
423 agentID, caps); 423 "POST",
424 })); 424 capsBase + m_parcelVoiceInfoRequestPath,
425 caps.RegisterHandler("ChatSessionRequest", 425 (request, path, param, httpRequest, httpResponse)
426 new RestStreamHandler("POST", capsBase + m_chatSessionRequestPath, 426 => ParcelVoiceInfoRequest(scene, request, path, param, agentID, caps),
427 delegate(string request, string path, string param, 427 "ParcelVoiceInfoRequest",
428 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 428 agentID.ToString()));
429 { 429
430 return ChatSessionRequest(scene, request, path, param, 430 caps.RegisterHandler(
431 agentID, caps); 431 "ChatSessionRequest",
432 })); 432 new RestStreamHandler(
433 "POST",
434 capsBase + m_chatSessionRequestPath,
435 (request, path, param, httpRequest, httpResponse)
436 => ChatSessionRequest(scene, request, path, param, agentID, caps),
437 "ChatSessionRequest",
438 agentID.ToString()));
433 } 439 }
434 440
435 /// <summary> 441 /// <summary>
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs
index 130513d..5d57f70 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs
@@ -1401,9 +1401,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1401 { 1401 {
1402 response = WebUtil.PostToService(m_groupsServerURI, requestArgs); 1402 response = WebUtil.PostToService(m_groupsServerURI, requestArgs);
1403 } 1403 }
1404 catch (Exception e) 1404 catch (Exception)
1405 { 1405 {
1406 m_log.InfoFormat("[SIMIAN GROUPS CONNECTOR] request failed {0}",CacheKey); 1406 m_log.ErrorFormat("[SIMIAN GROUPS CONNECTOR]: request failed {0}", CacheKey);
1407 } 1407 }
1408 1408
1409 // and cache the response 1409 // and cache the response
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs
index d2f6327..ac638f1 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs
@@ -50,7 +50,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups.Tests
50 TestHelpers.InMethod(); 50 TestHelpers.InMethod();
51// log4net.Config.XmlConfigurator.Configure(); 51// log4net.Config.XmlConfigurator.Configure();
52 52
53 TestScene scene = SceneHelpers.SetupScene(); 53 TestScene scene = new SceneHelpers().SetupScene();
54 IConfigSource configSource = new IniConfigSource(); 54 IConfigSource configSource = new IniConfigSource();
55 IConfig config = configSource.AddConfig("Groups"); 55 IConfig config = configSource.AddConfig("Groups");
56 config.Set("Enabled", true); 56 config.Set("Enabled", true);
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs
index 52fc27d..61aaf04 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs
@@ -1120,7 +1120,6 @@ namespace Nwc.XmlRpc
1120 /// <summary>Class supporting the request side of an XML-RPC transaction.</summary> 1120 /// <summary>Class supporting the request side of an XML-RPC transaction.</summary>
1121 public class ConfigurableKeepAliveXmlRpcRequest : XmlRpcRequest 1121 public class ConfigurableKeepAliveXmlRpcRequest : XmlRpcRequest
1122 { 1122 {
1123 private Encoding _encoding = new ASCIIEncoding();
1124 private XmlRpcRequestSerializer _serializer = new XmlRpcRequestSerializer(); 1123 private XmlRpcRequestSerializer _serializer = new XmlRpcRequestSerializer();
1125 private XmlRpcResponseDeserializer _deserializer = new XmlRpcResponseDeserializer(); 1124 private XmlRpcResponseDeserializer _deserializer = new XmlRpcResponseDeserializer();
1126 private bool _disableKeepAlive = true; 1125 private bool _disableKeepAlive = true;
@@ -1153,7 +1152,7 @@ namespace Nwc.XmlRpc
1153 request.KeepAlive = !_disableKeepAlive; 1152 request.KeepAlive = !_disableKeepAlive;
1154 1153
1155 Stream stream = request.GetRequestStream(); 1154 Stream stream = request.GetRequestStream();
1156 XmlTextWriter xml = new XmlTextWriter(stream, _encoding); 1155 XmlTextWriter xml = new XmlTextWriter(stream, Encoding.ASCII);
1157 _serializer.Serialize(xml, this); 1156 _serializer.Serialize(xml, this);
1158 xml.Flush(); 1157 xml.Flush();
1159 xml.Close(); 1158 xml.Close();
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs
new file mode 100644
index 0000000..34894ba
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs
@@ -0,0 +1,500 @@
1/*
2 * Copyright (c) Contributors
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 OpenSim 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 */
27using Mono.Addins;
28
29using System;
30using System.Reflection;
31using System.Threading;
32using System.Text;
33using System.Net;
34using System.Net.Sockets;
35using log4net;
36using Nini.Config;
37using OpenMetaverse;
38using OpenMetaverse.StructuredData;
39using OpenSim.Framework;
40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes;
42using System.Collections.Generic;
43using System.Text.RegularExpressions;
44
45namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
46{
47 public class JsonStore
48 {
49 private static readonly ILog m_log =
50 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51
52 private OSD m_ValueStore;
53
54 protected class TakeValueCallbackClass
55 {
56 public string Path { get; set; }
57 public bool UseJson { get; set; }
58 public TakeValueCallback Callback { get; set; }
59
60 public TakeValueCallbackClass(string spath, bool usejson, TakeValueCallback cback)
61 {
62 Path = spath;
63 UseJson = usejson;
64 Callback = cback;
65 }
66 }
67
68 protected List<TakeValueCallbackClass> m_TakeStore;
69 protected List<TakeValueCallbackClass> m_ReadStore;
70
71
72 // -----------------------------------------------------------------
73 /// <summary>
74 ///
75 /// </summary>
76 // -----------------------------------------------------------------
77 public JsonStore() : this("") {}
78
79 public JsonStore(string value)
80 {
81 m_TakeStore = new List<TakeValueCallbackClass>();
82 m_ReadStore = new List<TakeValueCallbackClass>();
83
84 if (String.IsNullOrEmpty(value))
85 m_ValueStore = new OSDMap();
86 else
87 m_ValueStore = OSDParser.DeserializeJson(value);
88 }
89
90 // -----------------------------------------------------------------
91 /// <summary>
92 ///
93 /// </summary>
94 // -----------------------------------------------------------------
95 public bool TestPath(string expr, bool useJson)
96 {
97 Stack<string> path = ParsePathExpression(expr);
98 OSD result = ProcessPathExpression(m_ValueStore,path);
99
100 if (result == null)
101 return false;
102
103 if (useJson || result.Type == OSDType.String)
104 return true;
105
106 return false;
107 }
108
109 // -----------------------------------------------------------------
110 /// <summary>
111 ///
112 /// </summary>
113 // -----------------------------------------------------------------
114 public bool GetValue(string expr, out string value, bool useJson)
115 {
116 Stack<string> path = ParsePathExpression(expr);
117 OSD result = ProcessPathExpression(m_ValueStore,path);
118 return ConvertOutputValue(result,out value,useJson);
119 }
120
121
122 // -----------------------------------------------------------------
123 /// <summary>
124 ///
125 /// </summary>
126 // -----------------------------------------------------------------
127 public bool RemoveValue(string expr)
128 {
129 return SetValueFromExpression(expr,null);
130 }
131
132 // -----------------------------------------------------------------
133 /// <summary>
134 ///
135 /// </summary>
136 // -----------------------------------------------------------------
137 public bool SetValue(string expr, string value, bool useJson)
138 {
139 OSD ovalue = useJson ? OSDParser.DeserializeJson(value) : new OSDString(value);
140 return SetValueFromExpression(expr,ovalue);
141 }
142
143 // -----------------------------------------------------------------
144 /// <summary>
145 ///
146 /// </summary>
147 // -----------------------------------------------------------------
148 public bool TakeValue(string expr, bool useJson, TakeValueCallback cback)
149 {
150 Stack<string> path = ParsePathExpression(expr);
151 string pexpr = PathExpressionToKey(path);
152
153 OSD result = ProcessPathExpression(m_ValueStore,path);
154 if (result == null)
155 {
156 m_TakeStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback));
157 return false;
158 }
159
160 string value = String.Empty;
161 if (! ConvertOutputValue(result,out value,useJson))
162 {
163 // the structure does not match the request so i guess we'll wait
164 m_TakeStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback));
165 return false;
166 }
167
168 SetValueFromExpression(expr,null);
169 cback(value);
170
171 return true;
172 }
173
174 // -----------------------------------------------------------------
175 /// <summary>
176 ///
177 /// </summary>
178 // -----------------------------------------------------------------
179 public bool ReadValue(string expr, bool useJson, TakeValueCallback cback)
180 {
181 Stack<string> path = ParsePathExpression(expr);
182 string pexpr = PathExpressionToKey(path);
183
184 OSD result = ProcessPathExpression(m_ValueStore,path);
185 if (result == null)
186 {
187 m_ReadStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback));
188 return false;
189 }
190
191 string value = String.Empty;
192 if (! ConvertOutputValue(result,out value,useJson))
193 {
194 // the structure does not match the request so i guess we'll wait
195 m_ReadStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback));
196 return false;
197 }
198
199 cback(value);
200
201 return true;
202 }
203
204 // -----------------------------------------------------------------
205 /// <summary>
206 ///
207 /// </summary>
208 // -----------------------------------------------------------------
209 protected bool SetValueFromExpression(string expr, OSD ovalue)
210 {
211 Stack<string> path = ParsePathExpression(expr);
212 if (path.Count == 0)
213 {
214 m_ValueStore = ovalue;
215 return true;
216 }
217
218 string pkey = path.Pop();
219 string pexpr = PathExpressionToKey(path);
220 if (pexpr != "")
221 pexpr += ".";
222
223 OSD result = ProcessPathExpression(m_ValueStore,path);
224 if (result == null)
225 return false;
226
227 Regex aPattern = new Regex("\\[([0-9]+|\\+)\\]");
228 MatchCollection amatches = aPattern.Matches(pkey,0);
229
230 if (amatches.Count > 0)
231 {
232 if (result.Type != OSDType.Array)
233 return false;
234
235 OSDArray amap = result as OSDArray;
236
237 Match match = amatches[0];
238 GroupCollection groups = match.Groups;
239 string akey = groups[1].Value;
240
241 if (akey == "+")
242 {
243 string npkey = String.Format("[{0}]",amap.Count);
244
245 amap.Add(ovalue);
246 InvokeNextCallback(pexpr + npkey);
247 return true;
248 }
249
250 int aval = Convert.ToInt32(akey);
251 if (0 <= aval && aval < amap.Count)
252 {
253 if (ovalue == null)
254 amap.RemoveAt(aval);
255 else
256 {
257 amap[aval] = ovalue;
258 InvokeNextCallback(pexpr + pkey);
259 }
260 return true;
261 }
262
263 return false;
264 }
265
266 Regex hPattern = new Regex("{([^}]+)}");
267 MatchCollection hmatches = hPattern.Matches(pkey,0);
268
269 if (hmatches.Count > 0)
270 {
271 Match match = hmatches[0];
272 GroupCollection groups = match.Groups;
273 string hkey = groups[1].Value;
274
275 if (result is OSDMap)
276 {
277 OSDMap hmap = result as OSDMap;
278 if (ovalue != null)
279 {
280 hmap[hkey] = ovalue;
281 InvokeNextCallback(pexpr + pkey);
282 }
283 else if (hmap.ContainsKey(hkey))
284 hmap.Remove(hkey);
285
286 return true;
287 }
288
289 return false;
290 }
291
292 // Shouldn't get here if the path was checked correctly
293 m_log.WarnFormat("[JsonStore] invalid path expression");
294 return false;
295 }
296
297 // -----------------------------------------------------------------
298 /// <summary>
299 ///
300 /// </summary>
301 // -----------------------------------------------------------------
302 protected bool InvokeNextCallback(string pexpr)
303 {
304 // Process all of the reads that match the expression first
305 List<TakeValueCallbackClass> reads =
306 m_ReadStore.FindAll(delegate(TakeValueCallbackClass tb) { return pexpr.StartsWith(tb.Path); });
307
308 foreach (TakeValueCallbackClass readcb in reads)
309 {
310 m_ReadStore.Remove(readcb);
311 ReadValue(readcb.Path,readcb.UseJson,readcb.Callback);
312 }
313
314 // Process one take next
315 TakeValueCallbackClass takecb =
316 m_TakeStore.Find(delegate(TakeValueCallbackClass tb) { return pexpr.StartsWith(tb.Path); });
317
318 if (takecb != null)
319 {
320 m_TakeStore.Remove(takecb);
321 TakeValue(takecb.Path,takecb.UseJson,takecb.Callback);
322
323 return true;
324 }
325
326 return false;
327 }
328
329 // -----------------------------------------------------------------
330 /// <summary>
331 /// Parse the path expression and put the components into a stack. We
332 /// use a stack because we process the path in inverse order later
333 /// </summary>
334 // -----------------------------------------------------------------
335 protected static Stack<string> ParsePathExpression(string path)
336 {
337 Stack<string> m_path = new Stack<string>();
338
339 // add front and rear separators
340 path = "." + path + ".";
341
342 // add separators for quoted paths
343 Regex pass1 = new Regex("{[^}]+}");
344 path = pass1.Replace(path,".$0.",-1,0);
345
346 // add separators for array references
347 Regex pass2 = new Regex("(\\[[0-9]+\\]|\\[\\+\\])");
348 path = pass2.Replace(path,".$0.",-1,0);
349
350 // add quotes to bare identifier
351 Regex pass3 = new Regex("\\.([a-zA-Z]+)");
352 path = pass3.Replace(path,".{$1}",-1,0);
353
354 // remove extra separators
355 Regex pass4 = new Regex("\\.+");
356 path = pass4.Replace(path,".",-1,0);
357
358 Regex validate = new Regex("^\\.(({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])\\.)+$");
359 if (validate.IsMatch(path))
360 {
361 Regex parser = new Regex("\\.({[^}]+}|\\[[0-9]+\\]|\\[\\+\\]+)");
362 MatchCollection matches = parser.Matches(path,0);
363 foreach (Match match in matches)
364 m_path.Push(match.Groups[1].Value);
365 }
366
367 return m_path;
368 }
369
370 // -----------------------------------------------------------------
371 /// <summary>
372 ///
373 /// </summary>
374 /// <param>path is a stack where the top level of the path is at the bottom of the stack</param>
375 // -----------------------------------------------------------------
376 protected static OSD ProcessPathExpression(OSD map, Stack<string> path)
377 {
378 if (path.Count == 0)
379 return map;
380
381 string pkey = path.Pop();
382
383 OSD rmap = ProcessPathExpression(map,path);
384 if (rmap == null)
385 return null;
386
387 // ---------- Check for an array index ----------
388 Regex aPattern = new Regex("\\[([0-9]+)\\]");
389 MatchCollection amatches = aPattern.Matches(pkey,0);
390
391 if (amatches.Count > 0)
392 {
393 if (rmap.Type != OSDType.Array)
394 {
395 m_log.WarnFormat("[JsonStore] wrong type for key {2}, expecting {0}, got {1}",OSDType.Array,rmap.Type,pkey);
396 return null;
397 }
398
399 OSDArray amap = rmap as OSDArray;
400
401 Match match = amatches[0];
402 GroupCollection groups = match.Groups;
403 string akey = groups[1].Value;
404 int aval = Convert.ToInt32(akey);
405
406 if (aval < amap.Count)
407 return (OSD) amap[aval];
408
409 return null;
410 }
411
412 // ---------- Check for a hash index ----------
413 Regex hPattern = new Regex("{([^}]+)}");
414 MatchCollection hmatches = hPattern.Matches(pkey,0);
415
416 if (hmatches.Count > 0)
417 {
418 if (rmap.Type != OSDType.Map)
419 {
420 m_log.WarnFormat("[JsonStore] wrong type for key {2}, expecting {0}, got {1}",OSDType.Map,rmap.Type,pkey);
421 return null;
422 }
423
424 OSDMap hmap = rmap as OSDMap;
425
426 Match match = hmatches[0];
427 GroupCollection groups = match.Groups;
428 string hkey = groups[1].Value;
429
430 if (hmap.ContainsKey(hkey))
431 return (OSD) hmap[hkey];
432
433 return null;
434 }
435
436 // Shouldn't get here if the path was checked correctly
437 m_log.WarnFormat("[JsonStore] Path type (unknown) does not match the structure");
438 return null;
439 }
440
441 // -----------------------------------------------------------------
442 /// <summary>
443 ///
444 /// </summary>
445 // -----------------------------------------------------------------
446 protected static bool ConvertOutputValue(OSD result, out string value, bool useJson)
447 {
448 value = String.Empty;
449
450 // If we couldn't process the path
451 if (result == null)
452 return false;
453
454 if (useJson)
455 {
456 // The path pointed to an intermediate hash structure
457 if (result.Type == OSDType.Map)
458 {
459 value = OSDParser.SerializeJsonString(result as OSDMap);
460 return true;
461 }
462
463 // The path pointed to an intermediate hash structure
464 if (result.Type == OSDType.Array)
465 {
466 value = OSDParser.SerializeJsonString(result as OSDArray);
467 return true;
468 }
469
470 value = "'" + result.AsString() + "'";
471 return true;
472 }
473
474 if (result.Type == OSDType.String)
475 {
476 value = result.AsString();
477 return true;
478 }
479
480 return false;
481 }
482
483 // -----------------------------------------------------------------
484 /// <summary>
485 ///
486 /// </summary>
487 // -----------------------------------------------------------------
488 protected static string PathExpressionToKey(Stack<string> path)
489 {
490 if (path.Count == 0)
491 return "";
492
493 string pkey = "";
494 foreach (string k in path)
495 pkey = (pkey == "") ? k : (k + "." + pkey);
496
497 return pkey;
498 }
499 }
500}
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
new file mode 100644
index 0000000..311531c
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
@@ -0,0 +1,430 @@
1/*
2 * Copyright (c) Contributors
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 OpenSim 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 */
27using Mono.Addins;
28
29using System;
30using System.Reflection;
31using System.Threading;
32using System.Text;
33using System.Net;
34using System.Net.Sockets;
35using log4net;
36using Nini.Config;
37using OpenMetaverse;
38using OpenMetaverse.StructuredData;
39using OpenSim.Framework;
40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes;
42using System.Collections.Generic;
43using System.Text.RegularExpressions;
44
45
46namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
47{
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "JsonStoreModule")]
49
50 public class JsonStoreModule : INonSharedRegionModule, IJsonStoreModule
51 {
52 private static readonly ILog m_log =
53 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54
55 private IConfig m_config = null;
56 private bool m_enabled = false;
57 private Scene m_scene = null;
58
59 private Dictionary<UUID,JsonStore> m_JsonValueStore;
60 private UUID m_sharedStore;
61
62#region IRegionModule Members
63
64 // -----------------------------------------------------------------
65 /// <summary>
66 /// Name of this shared module is it's class name
67 /// </summary>
68 // -----------------------------------------------------------------
69 public string Name
70 {
71 get { return this.GetType().Name; }
72 }
73
74 // -----------------------------------------------------------------
75 /// <summary>
76 /// Initialise this shared module
77 /// </summary>
78 /// <param name="scene">this region is getting initialised</param>
79 /// <param name="source">nini config, we are not using this</param>
80 // -----------------------------------------------------------------
81 public void Initialise(IConfigSource config)
82 {
83 try
84 {
85 if ((m_config = config.Configs["JsonStore"]) == null)
86 {
87 // There is no configuration, the module is disabled
88 // m_log.InfoFormat("[JsonStore] no configuration info");
89 return;
90 }
91
92 m_enabled = m_config.GetBoolean("Enabled", m_enabled);
93 }
94 catch (Exception e)
95 {
96 m_log.ErrorFormat("[JsonStore] initialization error: {0}",e.Message);
97 return;
98 }
99
100 if (m_enabled)
101 m_log.DebugFormat("[JsonStore] module is enabled");
102 }
103
104 // -----------------------------------------------------------------
105 /// <summary>
106 /// everything is loaded, perform post load configuration
107 /// </summary>
108 // -----------------------------------------------------------------
109 public void PostInitialise()
110 {
111 }
112
113 // -----------------------------------------------------------------
114 /// <summary>
115 /// Nothing to do on close
116 /// </summary>
117 // -----------------------------------------------------------------
118 public void Close()
119 {
120 }
121
122 // -----------------------------------------------------------------
123 /// <summary>
124 /// </summary>
125 // -----------------------------------------------------------------
126 public void AddRegion(Scene scene)
127 {
128 if (m_enabled)
129 {
130 m_scene = scene;
131 m_scene.RegisterModuleInterface<IJsonStoreModule>(this);
132
133 m_sharedStore = UUID.Zero;
134 m_JsonValueStore = new Dictionary<UUID,JsonStore>();
135 m_JsonValueStore.Add(m_sharedStore,new JsonStore(""));
136 }
137 }
138
139 // -----------------------------------------------------------------
140 /// <summary>
141 /// </summary>
142 // -----------------------------------------------------------------
143 public void RemoveRegion(Scene scene)
144 {
145 // need to remove all references to the scene in the subscription
146 // list to enable full garbage collection of the scene object
147 }
148
149 // -----------------------------------------------------------------
150 /// <summary>
151 /// Called when all modules have been added for a region. This is
152 /// where we hook up events
153 /// </summary>
154 // -----------------------------------------------------------------
155 public void RegionLoaded(Scene scene)
156 {
157 if (m_enabled) {}
158 }
159
160 /// -----------------------------------------------------------------
161 /// <summary>
162 /// </summary>
163 // -----------------------------------------------------------------
164 public Type ReplaceableInterface
165 {
166 get { return null; }
167 }
168
169#endregion
170
171#region ScriptInvocationInteface
172
173 // -----------------------------------------------------------------
174 /// <summary>
175 ///
176 /// </summary>
177 // -----------------------------------------------------------------
178 public bool CreateStore(string value, out UUID result)
179 {
180 result = UUID.Zero;
181
182 if (! m_enabled) return false;
183
184 UUID uuid = UUID.Random();
185 JsonStore map = null;
186
187 try
188 {
189 map = new JsonStore(value);
190 }
191 catch (Exception e)
192 {
193 m_log.InfoFormat("[JsonStore] Unable to initialize store from {0}; {1}",value,e.Message);
194 return false;
195 }
196
197 lock (m_JsonValueStore)
198 m_JsonValueStore.Add(uuid,map);
199
200 result = uuid;
201 return true;
202 }
203
204 // -----------------------------------------------------------------
205 /// <summary>
206 ///
207 /// </summary>
208 // -----------------------------------------------------------------
209 public bool DestroyStore(UUID storeID)
210 {
211 if (! m_enabled) return false;
212
213 lock (m_JsonValueStore)
214 m_JsonValueStore.Remove(storeID);
215
216 return true;
217 }
218
219 // -----------------------------------------------------------------
220 /// <summary>
221 ///
222 /// </summary>
223 // -----------------------------------------------------------------
224 public bool TestPath(UUID storeID, string path, bool useJson)
225 {
226 if (! m_enabled) return false;
227
228 JsonStore map = null;
229 lock (m_JsonValueStore)
230 {
231 if (! m_JsonValueStore.TryGetValue(storeID,out map))
232 {
233 m_log.InfoFormat("[JsonStore] Missing store {0}",storeID);
234 return true;
235 }
236 }
237
238 try
239 {
240 lock (map)
241 return map.TestPath(path,useJson);
242 }
243 catch (Exception e)
244 {
245 m_log.InfoFormat("[JsonStore] Path test failed for {0} in {1}; {2}",path,storeID,e.Message);
246 }
247
248 return false;
249 }
250
251 // -----------------------------------------------------------------
252 /// <summary>
253 ///
254 /// </summary>
255 // -----------------------------------------------------------------
256 public bool SetValue(UUID storeID, string path, string value, bool useJson)
257 {
258 if (! m_enabled) return false;
259
260 JsonStore map = null;
261 lock (m_JsonValueStore)
262 {
263 if (! m_JsonValueStore.TryGetValue(storeID,out map))
264 {
265 m_log.InfoFormat("[JsonStore] Missing store {0}",storeID);
266 return false;
267 }
268 }
269
270 try
271 {
272 lock (map)
273 if (map.SetValue(path,value,useJson))
274 return true;
275 }
276 catch (Exception e)
277 {
278 m_log.InfoFormat("[JsonStore] Unable to assign {0} to {1} in {2}; {3}",value,path,storeID,e.Message);
279 }
280
281 return false;
282 }
283
284 // -----------------------------------------------------------------
285 /// <summary>
286 ///
287 /// </summary>
288 // -----------------------------------------------------------------
289 public bool RemoveValue(UUID storeID, string path)
290 {
291 if (! m_enabled) return false;
292
293 JsonStore map = null;
294 lock (m_JsonValueStore)
295 {
296 if (! m_JsonValueStore.TryGetValue(storeID,out map))
297 {
298 m_log.InfoFormat("[JsonStore] Missing store {0}",storeID);
299 return false;
300 }
301 }
302
303 try
304 {
305 lock (map)
306 if (map.RemoveValue(path))
307 return true;
308 }
309 catch (Exception e)
310 {
311 m_log.InfoFormat("[JsonStore] Unable to remove {0} in {1}; {2}",path,storeID,e.Message);
312 }
313
314 return false;
315 }
316
317 // -----------------------------------------------------------------
318 /// <summary>
319 ///
320 /// </summary>
321 // -----------------------------------------------------------------
322 public bool GetValue(UUID storeID, string path, bool useJson, out string value)
323 {
324 value = String.Empty;
325
326 if (! m_enabled) return false;
327
328 JsonStore map = null;
329 lock (m_JsonValueStore)
330 {
331 if (! m_JsonValueStore.TryGetValue(storeID,out map))
332 return false;
333 }
334
335 try
336 {
337 lock (map)
338 {
339 return map.GetValue(path, out value, useJson);
340 }
341 }
342 catch (Exception e)
343 {
344 m_log.InfoFormat("[JsonStore] unable to retrieve value; {0}",e.Message);
345 }
346
347 return false;
348 }
349
350 // -----------------------------------------------------------------
351 /// <summary>
352 ///
353 /// </summary>
354 // -----------------------------------------------------------------
355 public void TakeValue(UUID storeID, string path, bool useJson, TakeValueCallback cback)
356 {
357 if (! m_enabled)
358 {
359 cback(String.Empty);
360 return;
361 }
362
363 JsonStore map = null;
364 lock (m_JsonValueStore)
365 {
366 if (! m_JsonValueStore.TryGetValue(storeID,out map))
367 {
368 cback(String.Empty);
369 return;
370 }
371 }
372
373 try
374 {
375 lock (map)
376 {
377 map.TakeValue(path, useJson, cback);
378 return;
379 }
380 }
381 catch (Exception e)
382 {
383 m_log.InfoFormat("[JsonStore] unable to retrieve value; {0}",e.ToString());
384 }
385
386 cback(String.Empty);
387 }
388
389 // -----------------------------------------------------------------
390 /// <summary>
391 ///
392 /// </summary>
393 // -----------------------------------------------------------------
394 public void ReadValue(UUID storeID, string path, bool useJson, TakeValueCallback cback)
395 {
396 if (! m_enabled)
397 {
398 cback(String.Empty);
399 return;
400 }
401
402 JsonStore map = null;
403 lock (m_JsonValueStore)
404 {
405 if (! m_JsonValueStore.TryGetValue(storeID,out map))
406 {
407 cback(String.Empty);
408 return;
409 }
410 }
411
412 try
413 {
414 lock (map)
415 {
416 map.ReadValue(path, useJson, cback);
417 return;
418 }
419 }
420 catch (Exception e)
421 {
422 m_log.InfoFormat("[JsonStore] unable to retrieve value; {0}",e.ToString());
423 }
424
425 cback(String.Empty);
426 }
427
428#endregion
429 }
430}
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
new file mode 100644
index 0000000..eaba816
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
@@ -0,0 +1,498 @@
1/*
2 * Copyright (c) Contributors
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 OpenSim 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 */
27using Mono.Addins;
28
29using System;
30using System.Reflection;
31using System.Threading;
32using System.Text;
33using System.Net;
34using System.Net.Sockets;
35using log4net;
36using Nini.Config;
37using OpenMetaverse;
38using OpenMetaverse.StructuredData;
39using OpenSim.Framework;
40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes;
42using System.Collections.Generic;
43using System.Text.RegularExpressions;
44
45namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
46{
47 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "JsonStoreScriptModule")]
48
49 public class JsonStoreScriptModule : INonSharedRegionModule
50 {
51 private static readonly ILog m_log =
52 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
54 private IConfig m_config = null;
55 private bool m_enabled = false;
56 private Scene m_scene = null;
57
58 private IScriptModuleComms m_comms;
59 private IJsonStoreModule m_store;
60
61#region IRegionModule Members
62
63 // -----------------------------------------------------------------
64 /// <summary>
65 /// Name of this shared module is it's class name
66 /// </summary>
67 // -----------------------------------------------------------------
68 public string Name
69 {
70 get { return this.GetType().Name; }
71 }
72
73 // -----------------------------------------------------------------
74 /// <summary>
75 /// Initialise this shared module
76 /// </summary>
77 /// <param name="scene">this region is getting initialised</param>
78 /// <param name="source">nini config, we are not using this</param>
79 // -----------------------------------------------------------------
80 public void Initialise(IConfigSource config)
81 {
82 try
83 {
84 if ((m_config = config.Configs["JsonStore"]) == null)
85 {
86 // There is no configuration, the module is disabled
87 // m_log.InfoFormat("[JsonStoreScripts] no configuration info");
88 return;
89 }
90
91 m_enabled = m_config.GetBoolean("Enabled", m_enabled);
92 }
93 catch (Exception e)
94 {
95 m_log.ErrorFormat("[JsonStoreScripts] initialization error: {0}",e.Message);
96 return;
97 }
98
99 if (m_enabled)
100 m_log.DebugFormat("[JsonStoreScripts] module is enabled");
101 }
102
103 // -----------------------------------------------------------------
104 /// <summary>
105 /// everything is loaded, perform post load configuration
106 /// </summary>
107 // -----------------------------------------------------------------
108 public void PostInitialise()
109 {
110 }
111
112 // -----------------------------------------------------------------
113 /// <summary>
114 /// Nothing to do on close
115 /// </summary>
116 // -----------------------------------------------------------------
117 public void Close()
118 {
119 }
120
121 // -----------------------------------------------------------------
122 /// <summary>
123 /// </summary>
124 // -----------------------------------------------------------------
125 public void AddRegion(Scene scene)
126 {
127 }
128
129 // -----------------------------------------------------------------
130 /// <summary>
131 /// </summary>
132 // -----------------------------------------------------------------
133 public void RemoveRegion(Scene scene)
134 {
135 // need to remove all references to the scene in the subscription
136 // list to enable full garbage collection of the scene object
137 }
138
139 // -----------------------------------------------------------------
140 /// <summary>
141 /// Called when all modules have been added for a region. This is
142 /// where we hook up events
143 /// </summary>
144 // -----------------------------------------------------------------
145 public void RegionLoaded(Scene scene)
146 {
147 if (m_enabled)
148 {
149 m_scene = scene;
150 m_comms = m_scene.RequestModuleInterface<IScriptModuleComms>();
151 if (m_comms == null)
152 {
153 m_log.ErrorFormat("[JsonStoreScripts] ScriptModuleComms interface not defined");
154 m_enabled = false;
155 return;
156 }
157
158 m_store = m_scene.RequestModuleInterface<IJsonStoreModule>();
159 if (m_store == null)
160 {
161 m_log.ErrorFormat("[JsonStoreScripts] JsonModule interface not defined");
162 m_enabled = false;
163 return;
164 }
165
166 try
167 {
168 m_comms.RegisterScriptInvocation(this,"JsonCreateStore");
169 m_comms.RegisterScriptInvocation(this,"JsonDestroyStore");
170
171 m_comms.RegisterScriptInvocation(this,"JsonReadNotecard");
172 m_comms.RegisterScriptInvocation(this,"JsonWriteNotecard");
173
174 m_comms.RegisterScriptInvocation(this,"JsonTestPath");
175 m_comms.RegisterScriptInvocation(this,"JsonTestPathJson");
176
177 m_comms.RegisterScriptInvocation(this,"JsonGetValue");
178 m_comms.RegisterScriptInvocation(this,"JsonGetValueJson");
179
180 m_comms.RegisterScriptInvocation(this,"JsonTakeValue");
181 m_comms.RegisterScriptInvocation(this,"JsonTakeValueJson");
182
183 m_comms.RegisterScriptInvocation(this,"JsonReadValue");
184 m_comms.RegisterScriptInvocation(this,"JsonReadValueJson");
185
186 m_comms.RegisterScriptInvocation(this,"JsonSetValue");
187 m_comms.RegisterScriptInvocation(this,"JsonSetValueJson");
188
189 m_comms.RegisterScriptInvocation(this,"JsonRemoveValue");
190 }
191 catch (Exception e)
192 {
193 // See http://opensimulator.org/mantis/view.php?id=5971 for more information
194 m_log.WarnFormat("[JsonStroreScripts] script method registration failed; {0}",e.Message);
195 m_enabled = false;
196 }
197 }
198 }
199
200 /// -----------------------------------------------------------------
201 /// <summary>
202 /// </summary>
203 // -----------------------------------------------------------------
204 public Type ReplaceableInterface
205 {
206 get { return null; }
207 }
208
209#endregion
210
211#region ScriptInvocationInteface
212 // -----------------------------------------------------------------
213 /// <summary>
214 ///
215 /// </summary>
216 // -----------------------------------------------------------------
217 protected void GenerateRuntimeError(string msg)
218 {
219 throw new Exception("JsonStore Runtime Error: " + msg);
220 }
221
222 // -----------------------------------------------------------------
223 /// <summary>
224 ///
225 /// </summary>
226 // -----------------------------------------------------------------
227 protected UUID JsonCreateStore(UUID hostID, UUID scriptID, string value)
228 {
229 UUID uuid = UUID.Zero;
230 if (! m_store.CreateStore(value, out uuid))
231 GenerateRuntimeError("Failed to create Json store");
232
233 return uuid;
234 }
235
236 // -----------------------------------------------------------------
237 /// <summary>
238 ///
239 /// </summary>
240 // -----------------------------------------------------------------
241 protected int JsonDestroyStore(UUID hostID, UUID scriptID, UUID storeID)
242 {
243 return m_store.DestroyStore(storeID) ? 1 : 0;
244 }
245
246 // -----------------------------------------------------------------
247 /// <summary>
248 ///
249 /// </summary>
250 // -----------------------------------------------------------------
251 protected UUID JsonReadNotecard(UUID hostID, UUID scriptID, UUID storeID, string path, UUID assetID)
252 {
253 UUID reqID = UUID.Random();
254 Util.FireAndForget(delegate(object o) { DoJsonReadNotecard(reqID,hostID,scriptID,storeID,path,assetID); });
255 return reqID;
256 }
257
258 // -----------------------------------------------------------------
259 /// <summary>
260 ///
261 /// </summary>
262 // -----------------------------------------------------------------
263 protected UUID JsonWriteNotecard(UUID hostID, UUID scriptID, UUID storeID, string path, string name)
264 {
265 UUID reqID = UUID.Random();
266 Util.FireAndForget(delegate(object o) { DoJsonWriteNotecard(reqID,hostID,scriptID,storeID,path,name); });
267 return reqID;
268 }
269
270 // -----------------------------------------------------------------
271 /// <summary>
272 ///
273 /// </summary>
274 // -----------------------------------------------------------------
275 protected int JsonTestPath(UUID hostID, UUID scriptID, UUID storeID, string path)
276 {
277 return m_store.TestPath(storeID,path,false) ? 1 : 0;
278 }
279
280 protected int JsonTestPathJson(UUID hostID, UUID scriptID, UUID storeID, string path)
281 {
282 return m_store.TestPath(storeID,path,true) ? 1 : 0;
283 }
284
285 // -----------------------------------------------------------------
286 /// <summary>
287 ///
288 /// </summary>
289 // -----------------------------------------------------------------
290 protected int JsonSetValue(UUID hostID, UUID scriptID, UUID storeID, string path, string value)
291 {
292 return m_store.SetValue(storeID,path,value,false) ? 1 : 0;
293 }
294
295 protected int JsonSetValueJson(UUID hostID, UUID scriptID, UUID storeID, string path, string value)
296 {
297 return m_store.SetValue(storeID,path,value,true) ? 1 : 0;
298 }
299
300 // -----------------------------------------------------------------
301 /// <summary>
302 ///
303 /// </summary>
304 // -----------------------------------------------------------------
305 protected int JsonRemoveValue(UUID hostID, UUID scriptID, UUID storeID, string path)
306 {
307 return m_store.RemoveValue(storeID,path) ? 1 : 0;
308 }
309
310 // -----------------------------------------------------------------
311 /// <summary>
312 ///
313 /// </summary>
314 // -----------------------------------------------------------------
315 protected string JsonGetValue(UUID hostID, UUID scriptID, UUID storeID, string path)
316 {
317 string value = String.Empty;
318 m_store.GetValue(storeID,path,false,out value);
319 return value;
320 }
321
322 protected string JsonGetValueJson(UUID hostID, UUID scriptID, UUID storeID, string path)
323 {
324 string value = String.Empty;
325 m_store.GetValue(storeID,path,true, out value);
326 return value;
327 }
328
329 // -----------------------------------------------------------------
330 /// <summary>
331 ///
332 /// </summary>
333 // -----------------------------------------------------------------
334 protected UUID JsonTakeValue(UUID hostID, UUID scriptID, UUID storeID, string path)
335 {
336 UUID reqID = UUID.Random();
337 Util.FireAndForget(delegate(object o) { DoJsonTakeValue(scriptID,reqID,storeID,path,false); });
338 return reqID;
339 }
340
341 protected UUID JsonTakeValueJson(UUID hostID, UUID scriptID, UUID storeID, string path)
342 {
343 UUID reqID = UUID.Random();
344 Util.FireAndForget(delegate(object o) { DoJsonTakeValue(scriptID,reqID,storeID,path,true); });
345 return reqID;
346 }
347
348 private void DoJsonTakeValue(UUID scriptID, UUID reqID, UUID storeID, string path, bool useJson)
349 {
350 try
351 {
352 m_store.TakeValue(storeID,path,useJson,delegate(string value) { DispatchValue(scriptID,reqID,value); });
353 return;
354 }
355 catch (Exception e)
356 {
357 m_log.InfoFormat("[JsonStoreScripts] unable to retrieve value; {0}",e.ToString());
358 }
359
360 DispatchValue(scriptID,reqID,String.Empty);
361 }
362
363
364 // -----------------------------------------------------------------
365 /// <summary>
366 ///
367 /// </summary>
368 // -----------------------------------------------------------------
369 protected UUID JsonReadValue(UUID hostID, UUID scriptID, UUID storeID, string path)
370 {
371 UUID reqID = UUID.Random();
372 Util.FireAndForget(delegate(object o) { DoJsonReadValue(scriptID,reqID,storeID,path,false); });
373 return reqID;
374 }
375
376 protected UUID JsonReadValueJson(UUID hostID, UUID scriptID, UUID storeID, string path)
377 {
378 UUID reqID = UUID.Random();
379 Util.FireAndForget(delegate(object o) { DoJsonReadValue(scriptID,reqID,storeID,path,true); });
380 return reqID;
381 }
382
383 private void DoJsonReadValue(UUID scriptID, UUID reqID, UUID storeID, string path, bool useJson)
384 {
385 try
386 {
387 m_store.ReadValue(storeID,path,useJson,delegate(string value) { DispatchValue(scriptID,reqID,value); });
388 return;
389 }
390 catch (Exception e)
391 {
392 m_log.InfoFormat("[JsonStoreScripts] unable to retrieve value; {0}",e.ToString());
393 }
394
395 DispatchValue(scriptID,reqID,String.Empty);
396 }
397
398#endregion
399
400 // -----------------------------------------------------------------
401 /// <summary>
402 ///
403 /// </summary>
404 // -----------------------------------------------------------------
405 protected void DispatchValue(UUID scriptID, UUID reqID, string value)
406 {
407 m_comms.DispatchReply(scriptID,1,value,reqID.ToString());
408 }
409
410 // -----------------------------------------------------------------
411 /// <summary>
412 ///
413 /// </summary>
414 // -----------------------------------------------------------------
415 private void DoJsonReadNotecard(UUID reqID, UUID hostID, UUID scriptID, UUID storeID, string path, UUID assetID)
416 {
417 AssetBase a = m_scene.AssetService.Get(assetID.ToString());
418 if (a == null)
419 GenerateRuntimeError(String.Format("Unable to find notecard asset {0}",assetID));
420
421 if (a.Type != (sbyte)AssetType.Notecard)
422 GenerateRuntimeError(String.Format("Invalid notecard asset {0}",assetID));
423
424 m_log.DebugFormat("[JsonStoreScripts] read notecard in context {0}",storeID);
425
426 try
427 {
428 string jsondata = SLUtil.ParseNotecardToString(Encoding.UTF8.GetString(a.Data));
429 int result = m_store.SetValue(storeID, path, jsondata,true) ? 1 : 0;
430 m_comms.DispatchReply(scriptID,result, "", reqID.ToString());
431 return;
432 }
433 catch (Exception e)
434 {
435 m_log.WarnFormat("[JsonStoreScripts] Json parsing failed; {0}",e.Message);
436 }
437
438 GenerateRuntimeError(String.Format("Json parsing failed for {0}",assetID.ToString()));
439 m_comms.DispatchReply(scriptID,0,"",reqID.ToString());
440 }
441
442 // -----------------------------------------------------------------
443 /// <summary>
444 ///
445 /// </summary>
446 // -----------------------------------------------------------------
447 private void DoJsonWriteNotecard(UUID reqID, UUID hostID, UUID scriptID, UUID storeID, string path, string name)
448 {
449 string data;
450 if (! m_store.GetValue(storeID,path,true, out data))
451 {
452 m_comms.DispatchReply(scriptID,0,UUID.Zero.ToString(),reqID.ToString());
453 return;
454 }
455
456 SceneObjectPart host = m_scene.GetSceneObjectPart(hostID);
457
458 // Create new asset
459 UUID assetID = UUID.Random();
460 AssetBase asset = new AssetBase(assetID, name, (sbyte)AssetType.Notecard, host.OwnerID.ToString());
461 asset.Description = "Json store";
462
463 int textLength = data.Length;
464 data = "Linden text version 2\n{\nLLEmbeddedItems version 1\n{\ncount 0\n}\nText length "
465 + textLength.ToString() + "\n" + data + "}\n";
466
467 asset.Data = Util.UTF8.GetBytes(data);
468 m_scene.AssetService.Store(asset);
469
470 // Create Task Entry
471 TaskInventoryItem taskItem = new TaskInventoryItem();
472
473 taskItem.ResetIDs(host.UUID);
474 taskItem.ParentID = host.UUID;
475 taskItem.CreationDate = (uint)Util.UnixTimeSinceEpoch();
476 taskItem.Name = asset.Name;
477 taskItem.Description = asset.Description;
478 taskItem.Type = (int)AssetType.Notecard;
479 taskItem.InvType = (int)InventoryType.Notecard;
480 taskItem.OwnerID = host.OwnerID;
481 taskItem.CreatorID = host.OwnerID;
482 taskItem.BasePermissions = (uint)PermissionMask.All;
483 taskItem.CurrentPermissions = (uint)PermissionMask.All;
484 taskItem.EveryonePermissions = 0;
485 taskItem.NextPermissions = (uint)PermissionMask.All;
486 taskItem.GroupID = host.GroupID;
487 taskItem.GroupPermissions = 0;
488 taskItem.Flags = 0;
489 taskItem.PermsGranter = UUID.Zero;
490 taskItem.PermsMask = 0;
491 taskItem.AssetID = asset.FullID;
492
493 host.Inventory.AddInventoryItem(taskItem, false);
494
495 m_comms.DispatchReply(scriptID,1,assetID.ToString(),reqID.ToString());
496 }
497 }
498}
diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs
index 74f5208..03481d2 100644
--- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs
@@ -482,10 +482,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
482 // Convert to base64 482 // Convert to base64
483 // 483 //
484 string filetext = Convert.ToBase64String(data); 484 string filetext = Convert.ToBase64String(data);
485 485 Byte[] buf = Encoding.ASCII.GetBytes(filetext);
486 ASCIIEncoding enc = new ASCIIEncoding();
487
488 Byte[] buf = enc.GetBytes(filetext);
489 486
490 m_log.Info("MRM 9"); 487 m_log.Info("MRM 9");
491 488
diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SPAvatar.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SPAvatar.cs
index 922eaaf..d192309 100644
--- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SPAvatar.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SPAvatar.cs
@@ -68,7 +68,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
68 public Vector3 WorldPosition 68 public Vector3 WorldPosition
69 { 69 {
70 get { return GetSP().AbsolutePosition; } 70 get { return GetSP().AbsolutePosition; }
71 set { GetSP().TeleportWithMomentum(value); } 71 set { GetSP().Teleport(value); }
72 } 72 }
73 73
74 public bool IsChildAgent 74 public bool IsChildAgent
diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
index 0b9f875..600cafb 100644
--- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
@@ -228,9 +228,10 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
228 // m_log.InfoFormat("[RegionReady]: Logins enabled for {0}, Oar {1}", 228 // m_log.InfoFormat("[RegionReady]: Logins enabled for {0}, Oar {1}",
229 // m_scene.RegionInfo.RegionName, m_oarFileLoading.ToString()); 229 // m_scene.RegionInfo.RegionName, m_oarFileLoading.ToString());
230 230
231 m_log.InfoFormat("[RegionReady]: Initialization complete - logins enabled for {0}", m_scene.RegionInfo.RegionName); 231 m_log.InfoFormat(
232 "[RegionReady]: INITIALIZATION COMPLETE FOR {0} - LOGINS ENABLED", m_scene.Name);
232 233
233 if ( m_uri != string.Empty ) 234 if (m_uri != string.Empty)
234 { 235 {
235 RRAlert("enabled"); 236 RRAlert("enabled");
236 } 237 }
diff --git a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
index cab30de..74a85e2 100644
--- a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
@@ -38,7 +38,7 @@ using OpenMetaverse;
38using System.Linq; 38using System.Linq;
39using System.Linq.Expressions; 39using System.Linq.Expressions;
40 40
41namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms 41namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
42{ 42{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ScriptModuleCommsModule")] 43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ScriptModuleCommsModule")]
44 class ScriptModuleCommsModule : INonSharedRegionModule, IScriptModuleComms 44 class ScriptModuleCommsModule : INonSharedRegionModule, IScriptModuleComms
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index 8996865..97db7e1 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
@@ -76,22 +76,27 @@ namespace OpenSim.Region.OptionalModules.World.NPC
76 76
77 public void Say(string message) 77 public void Say(string message)
78 { 78 {
79 SendOnChatFromClient(message, ChatTypeEnum.Say); 79 SendOnChatFromClient(0, message, ChatTypeEnum.Say);
80 } 80 }
81 81
82 public void Shout(string message) 82 public void Say(int channel, string message)
83 { 83 {
84 SendOnChatFromClient(message, ChatTypeEnum.Shout); 84 SendOnChatFromClient(channel, message, ChatTypeEnum.Say);
85 } 85 }
86 86
87 public void Whisper(string message) 87 public void Shout(int channel, string message)
88 { 88 {
89 SendOnChatFromClient(message, ChatTypeEnum.Whisper); 89 SendOnChatFromClient(channel, message, ChatTypeEnum.Shout);
90 }
91
92 public void Whisper(int channel, string message)
93 {
94 SendOnChatFromClient(channel, message, ChatTypeEnum.Whisper);
90 } 95 }
91 96
92 public void Broadcast(string message) 97 public void Broadcast(string message)
93 { 98 {
94 SendOnChatFromClient(message, ChatTypeEnum.Broadcast); 99 SendOnChatFromClient(0, message, ChatTypeEnum.Broadcast);
95 } 100 }
96 101
97 public void GiveMoney(UUID target, int amount) 102 public void GiveMoney(UUID target, int amount)
@@ -99,6 +104,45 @@ namespace OpenSim.Region.OptionalModules.World.NPC
99 OnMoneyTransferRequest(m_uuid, target, amount, 1, "Payment"); 104 OnMoneyTransferRequest(m_uuid, target, amount, 1, "Payment");
100 } 105 }
101 106
107 public bool Touch(UUID target)
108 {
109 SceneObjectPart part = m_scene.GetSceneObjectPart(target);
110 if (part == null)
111 return false;
112 bool objectTouchable = hasTouchEvents(part); // Only touch an object that is scripted to respond
113 if (!objectTouchable && !part.IsRoot)
114 objectTouchable = hasTouchEvents(part.ParentGroup.RootPart);
115 if (!objectTouchable)
116 return false;
117 // Set up the surface args as if the touch is from a client that does not support this
118 SurfaceTouchEventArgs surfaceArgs = new SurfaceTouchEventArgs();
119 surfaceArgs.FaceIndex = -1; // TOUCH_INVALID_FACE
120 surfaceArgs.Binormal = Vector3.Zero; // TOUCH_INVALID_VECTOR
121 surfaceArgs.Normal = Vector3.Zero; // TOUCH_INVALID_VECTOR
122 surfaceArgs.STCoord = new Vector3(-1.0f, -1.0f, 0.0f); // TOUCH_INVALID_TEXCOORD
123 surfaceArgs.UVCoord = surfaceArgs.STCoord; // TOUCH_INVALID_TEXCOORD
124 List<SurfaceTouchEventArgs> touchArgs = new List<SurfaceTouchEventArgs>();
125 touchArgs.Add(surfaceArgs);
126 Vector3 offset = part.OffsetPosition * -1.0f;
127 if (OnGrabObject == null)
128 return false;
129 OnGrabObject(part.LocalId, offset, this, touchArgs);
130 if (OnGrabUpdate != null)
131 OnGrabUpdate(part.UUID, offset, part.ParentGroup.RootPart.GroupPosition, this, touchArgs);
132 if (OnDeGrabObject != null)
133 OnDeGrabObject(part.LocalId, this, touchArgs);
134 return true;
135 }
136
137 private bool hasTouchEvents(SceneObjectPart part)
138 {
139 if ((part.ScriptEvents & scriptEvents.touch) != 0 ||
140 (part.ScriptEvents & scriptEvents.touch_start) != 0 ||
141 (part.ScriptEvents & scriptEvents.touch_end) != 0)
142 return true;
143 return false;
144 }
145
102 public void InstantMessage(UUID target, string message) 146 public void InstantMessage(UUID target, string message)
103 { 147 {
104 OnInstantMessage(this, new GridInstantMessage(m_scene, 148 OnInstantMessage(this, new GridInstantMessage(m_scene,
@@ -146,10 +190,18 @@ namespace OpenSim.Region.OptionalModules.World.NPC
146 190
147 #region Internal Functions 191 #region Internal Functions
148 192
149 private void SendOnChatFromClient(string message, ChatTypeEnum chatType) 193 private void SendOnChatFromClient(int channel, string message, ChatTypeEnum chatType)
150 { 194 {
195 if (channel == 0)
196 {
197 message = message.Trim();
198 if (string.IsNullOrEmpty(message))
199 {
200 return;
201 }
202 }
151 OSChatMessage chatFromClient = new OSChatMessage(); 203 OSChatMessage chatFromClient = new OSChatMessage();
152 chatFromClient.Channel = 0; 204 chatFromClient.Channel = channel;
153 chatFromClient.From = Name; 205 chatFromClient.From = Name;
154 chatFromClient.Message = message; 206 chatFromClient.Message = message;
155 chatFromClient.Position = StartPos; 207 chatFromClient.Position = StartPos;
@@ -900,11 +952,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC
900 { 952 {
901 } 953 }
902 954
903 public EndPoint GetClientEP()
904 {
905 return null;
906 }
907
908 public ClientInfo GetClientInfo() 955 public ClientInfo GetClientInfo()
909 { 956 {
910 return null; 957 return null;
@@ -1046,10 +1093,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC
1046 { 1093 {
1047 } 1094 }
1048 1095
1049 public void KillEndDone()
1050 {
1051 }
1052
1053 public void SendEventInfoReply (EventData info) 1096 public void SendEventInfoReply (EventData info)
1054 { 1097 {
1055 } 1098 }
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
index ebf5e84..b37aba3 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
@@ -155,18 +155,10 @@ namespace OpenSim.Region.OptionalModules.World.NPC
155 ScenePresence sp; 155 ScenePresence sp;
156 if (scene.TryGetScenePresence(npcAvatar.AgentId, out sp)) 156 if (scene.TryGetScenePresence(npcAvatar.AgentId, out sp))
157 { 157 {
158 m_log.DebugFormat(
159 "[NPC MODULE]: Successfully retrieved scene presence for NPC {0} {1}", sp.Name, sp.UUID);
160
161 sp.CompleteMovement(npcAvatar, false); 158 sp.CompleteMovement(npcAvatar, false);
162 m_avatars.Add(npcAvatar.AgentId, npcAvatar); 159 m_avatars.Add(npcAvatar.AgentId, npcAvatar);
160 m_log.DebugFormat("[NPC MODULE]: Created NPC {0} {1}", npcAvatar.AgentId, sp.Name);
163 } 161 }
164 else
165 {
166 m_log.WarnFormat("[NPC MODULE]: Could not find scene presence for NPC {0} {1}", sp.Name, sp.UUID);
167 npcAvatar.AgentId = UUID.Zero;
168 }
169
170 } 162 }
171 ev.Set(); 163 ev.Set();
172 }); 164 });
@@ -178,7 +170,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
178 return npcAvatar.AgentId; 170 return npcAvatar.AgentId;
179 } 171 }
180 172
181 public bool MoveToTarget(UUID agentID, Scene scene, Vector3 pos, bool noFly, bool landAtTarget) 173 public bool MoveToTarget(UUID agentID, Scene scene, Vector3 pos, bool noFly, bool landAtTarget, bool running)
182 { 174 {
183 lock (m_avatars) 175 lock (m_avatars)
184 { 176 {
@@ -192,6 +184,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
192 sp.Name, pos, scene.RegionInfo.RegionName, noFly, landAtTarget); 184 sp.Name, pos, scene.RegionInfo.RegionName, noFly, landAtTarget);
193 185
194 sp.MoveToTarget(pos, noFly, landAtTarget); 186 sp.MoveToTarget(pos, noFly, landAtTarget);
187 sp.SetAlwaysRun = running;
195 188
196 return true; 189 return true;
197 } 190 }
@@ -221,6 +214,29 @@ namespace OpenSim.Region.OptionalModules.World.NPC
221 214
222 public bool Say(UUID agentID, Scene scene, string text) 215 public bool Say(UUID agentID, Scene scene, string text)
223 { 216 {
217 return Say(agentID, scene, text, 0);
218 }
219
220 public bool Say(UUID agentID, Scene scene, string text, int channel)
221 {
222 lock (m_avatars)
223 {
224 if (m_avatars.ContainsKey(agentID))
225 {
226 ScenePresence sp;
227 scene.TryGetScenePresence(agentID, out sp);
228
229 m_avatars[agentID].Say(channel, text);
230
231 return true;
232 }
233 }
234
235 return false;
236 }
237
238 public bool Shout(UUID agentID, Scene scene, string text, int channel)
239 {
224 lock (m_avatars) 240 lock (m_avatars)
225 { 241 {
226 if (m_avatars.ContainsKey(agentID)) 242 if (m_avatars.ContainsKey(agentID))
@@ -228,7 +244,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
228 ScenePresence sp; 244 ScenePresence sp;
229 scene.TryGetScenePresence(agentID, out sp); 245 scene.TryGetScenePresence(agentID, out sp);
230 246
231 m_avatars[agentID].Say(text); 247 m_avatars[agentID].Shout(channel, text);
232 248
233 return true; 249 return true;
234 } 250 }
@@ -255,6 +271,24 @@ namespace OpenSim.Region.OptionalModules.World.NPC
255 return false; 271 return false;
256 } 272 }
257 273
274 public bool Whisper(UUID agentID, Scene scene, string text, int channel)
275 {
276 lock (m_avatars)
277 {
278 if (m_avatars.ContainsKey(agentID))
279 {
280 ScenePresence sp;
281 scene.TryGetScenePresence(agentID, out sp);
282
283 m_avatars[agentID].Whisper(channel, text);
284
285 return true;
286 }
287 }
288
289 return false;
290 }
291
258 public bool Stand(UUID agentID, Scene scene) 292 public bool Stand(UUID agentID, Scene scene)
259 { 293 {
260 lock (m_avatars) 294 lock (m_avatars)
@@ -272,6 +306,16 @@ namespace OpenSim.Region.OptionalModules.World.NPC
272 return false; 306 return false;
273 } 307 }
274 308
309 public bool Touch(UUID agentID, UUID objectID)
310 {
311 lock (m_avatars)
312 {
313 if (m_avatars.ContainsKey(agentID))
314 return m_avatars[agentID].Touch(objectID);
315 return false;
316 }
317 }
318
275 public UUID GetOwner(UUID agentID) 319 public UUID GetOwner(UUID agentID)
276 { 320 {
277 lock (m_avatars) 321 lock (m_avatars)
@@ -308,7 +352,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
308 scene.RemoveClient(agentID, false); 352 scene.RemoveClient(agentID, false);
309 m_avatars.Remove(agentID); 353 m_avatars.Remove(agentID);
310 354
311// m_log.DebugFormat("[NPC MODULE]: Removed {0} {1}", agentID, av.Name); 355 m_log.DebugFormat("[NPC MODULE]: Removed NPC {0} {1}", agentID, av.Name);
312 return true; 356 return true;
313 } 357 }
314 } 358 }
diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
index eea0b2e..9179966 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
@@ -85,7 +85,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
85 m_attMod = new AttachmentsModule(); 85 m_attMod = new AttachmentsModule();
86 m_npcMod = new NPCModule(); 86 m_npcMod = new NPCModule();
87 87
88 m_scene = SceneHelpers.SetupScene(); 88 m_scene = new SceneHelpers().SetupScene();
89 SceneHelpers.SetupSceneModules(m_scene, config, m_afMod, m_umMod, m_attMod, m_npcMod, new BasicInventoryAccessModule()); 89 SceneHelpers.SetupSceneModules(m_scene, config, m_afMod, m_umMod, m_attMod, m_npcMod, new BasicInventoryAccessModule());
90 } 90 }
91 91
@@ -242,7 +242,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
242 Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos)); 242 Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos));
243 243
244 Vector3 targetPos = startPos + new Vector3(0, 10, 0); 244 Vector3 targetPos = startPos + new Vector3(0, 10, 0);
245 m_npcMod.MoveToTarget(npc.UUID, m_scene, targetPos, false, false); 245 m_npcMod.MoveToTarget(npc.UUID, m_scene, targetPos, false, false, false);
246 246
247 Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos)); 247 Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos));
248 //Assert.That(npc.Rotation, Is.EqualTo(new Quaternion(0, 0, 0.7071068f, 0.7071068f))); 248 //Assert.That(npc.Rotation, Is.EqualTo(new Quaternion(0, 0, 0.7071068f, 0.7071068f)));
@@ -267,7 +267,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
267 // Try a second movement 267 // Try a second movement
268 startPos = npc.AbsolutePosition; 268 startPos = npc.AbsolutePosition;
269 targetPos = startPos + new Vector3(10, 0, 0); 269 targetPos = startPos + new Vector3(10, 0, 0);
270 m_npcMod.MoveToTarget(npc.UUID, m_scene, targetPos, false, false); 270 m_npcMod.MoveToTarget(npc.UUID, m_scene, targetPos, false, false, false);
271 271
272 Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos)); 272 Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos));
273// Assert.That(npc.Rotation, Is.EqualTo(new Quaternion(0, 0, 0, 1))); 273// Assert.That(npc.Rotation, Is.EqualTo(new Quaternion(0, 0, 0, 1)));
@@ -301,7 +301,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
301 UUID npcId = m_npcMod.CreateNPC("John", "Smith", startPos, UUID.Zero, true, m_scene, sp.Appearance); 301 UUID npcId = m_npcMod.CreateNPC("John", "Smith", startPos, UUID.Zero, true, m_scene, sp.Appearance);
302 302
303 ScenePresence npc = m_scene.GetScenePresence(npcId); 303 ScenePresence npc = m_scene.GetScenePresence(npcId);
304 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene); 304 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart;
305 305
306 part.SitTargetPosition = new Vector3(0, 0, 1); 306 part.SitTargetPosition = new Vector3(0, 0, 1);
307 m_npcMod.Sit(npc.UUID, part.UUID, m_scene); 307 m_npcMod.Sit(npc.UUID, part.UUID, m_scene);
@@ -333,7 +333,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
333 UUID npcId = m_npcMod.CreateNPC("John", "Smith", startPos, UUID.Zero, true, m_scene, sp.Appearance); 333 UUID npcId = m_npcMod.CreateNPC("John", "Smith", startPos, UUID.Zero, true, m_scene, sp.Appearance);
334 334
335 ScenePresence npc = m_scene.GetScenePresence(npcId); 335 ScenePresence npc = m_scene.GetScenePresence(npcId);
336 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene); 336 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart;
337 337
338 m_npcMod.Sit(npc.UUID, part.UUID, m_scene); 338 m_npcMod.Sit(npc.UUID, part.UUID, m_scene);
339 339
diff --git a/OpenSim/Region/OptionalModules/World/WorldView/WorldViewModule.cs b/OpenSim/Region/OptionalModules/World/WorldView/WorldViewModule.cs
index 48c242d..1aee39a 100644
--- a/OpenSim/Region/OptionalModules/World/WorldView/WorldViewModule.cs
+++ b/OpenSim/Region/OptionalModules/World/WorldView/WorldViewModule.cs
@@ -113,14 +113,15 @@ namespace OpenSim.Region.OptionalModules.World.WorldView
113 if (!m_Enabled) 113 if (!m_Enabled)
114 return new Byte[0]; 114 return new Byte[0];
115 115
116 Bitmap bmp = m_Generator.CreateViewImage(pos, rot, fov, width, 116 using (Bitmap bmp = m_Generator.CreateViewImage(pos, rot, fov, width, height, usetex))
117 height, usetex); 117 {
118 118 using (MemoryStream str = new MemoryStream())
119 MemoryStream str = new MemoryStream(); 119 {
120 120 bmp.Save(str, ImageFormat.Jpeg);
121 bmp.Save(str, ImageFormat.Jpeg);
122 121
123 return str.ToArray(); 122 return str.ToArray();
123 }
124 }
124 } 125 }
125 } 126 }
126} 127}
diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs
index b1a3ff9..e43136a 100644
--- a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs
+++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs
@@ -36,13 +36,7 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
36{ 36{
37 public class BasicActor : PhysicsActor 37 public class BasicActor : PhysicsActor
38 { 38 {
39 private Vector3 _position;
40 private Vector3 _velocity;
41 private Vector3 _acceleration;
42 private Vector3 _size; 39 private Vector3 _size;
43 private Vector3 m_rotationalVelocity;
44 private bool flying;
45 private bool iscolliding;
46 40
47 public BasicActor(Vector3 size) 41 public BasicActor(Vector3 size)
48 { 42 {
@@ -55,11 +49,7 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
55 set { return; } 49 set { return; }
56 } 50 }
57 51
58 public override Vector3 RotationalVelocity 52 public override Vector3 RotationalVelocity { get; set; }
59 {
60 get { return m_rotationalVelocity; }
61 set { m_rotationalVelocity = value; }
62 }
63 53
64 public override bool SetAlwaysRun 54 public override bool SetAlwaysRun
65 { 55 {
@@ -105,17 +95,9 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
105 set { return; } 95 set { return; }
106 } 96 }
107 97
108 public override bool Flying 98 public override bool Flying { get; set; }
109 {
110 get { return flying; }
111 set { flying = value; }
112 }
113 99
114 public override bool IsColliding 100 public override bool IsColliding { get; set; }
115 {
116 get { return iscolliding; }
117 set { iscolliding = value; }
118 }
119 101
120 public override bool CollidingGround 102 public override bool CollidingGround
121 { 103 {
@@ -134,11 +116,7 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
134 get { return false; } 116 get { return false; }
135 } 117 }
136 118
137 public override Vector3 Position 119 public override Vector3 Position { get; set; }
138 {
139 get { return _position; }
140 set { _position = value; }
141 }
142 120
143 public override Vector3 Size 121 public override Vector3 Size
144 { 122 {
@@ -206,11 +184,7 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
206 get { return Vector3.Zero; } 184 get { return Vector3.Zero; }
207 } 185 }
208 186
209 public override Vector3 Velocity 187 public override Vector3 Velocity { get; set; }
210 {
211 get { return _velocity; }
212 set { _velocity = value; }
213 }
214 188
215 public override Vector3 Torque 189 public override Vector3 Torque
216 { 190 {
@@ -230,11 +204,7 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
230 set { } 204 set { }
231 } 205 }
232 206
233 public override Vector3 Acceleration 207 public override Vector3 Acceleration { get; set; }
234 {
235 get { return _acceleration; }
236 set { _acceleration = value; }
237 }
238 208
239 public override bool Kinematic 209 public override bool Kinematic
240 { 210 {
diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPrim.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPrim.cs
new file mode 100644
index 0000000..47d7df3
--- /dev/null
+++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPrim.cs
@@ -0,0 +1,315 @@
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 Nini.Config;
31using OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Region.Physics.Manager;
34
35namespace OpenSim.Region.Physics.BasicPhysicsPlugin
36{
37 public class BasicPhysicsPrim : PhysicsActor
38 {
39 private Vector3 _size;
40// private PrimitiveBaseShape _shape;
41
42 public BasicPhysicsPrim(
43 string name, uint localId, Vector3 position, Vector3 size, Quaternion orientation, PrimitiveBaseShape shape)
44 {
45 Name = name;
46 LocalID = localId;
47 Position = position;
48 Size = size;
49 Orientation = orientation;
50 Shape = shape;
51 }
52
53 public override int PhysicsActorType
54 {
55 get { return (int) ActorTypes.Agent; }
56 set { return; }
57 }
58
59 public override Vector3 RotationalVelocity { get; set; }
60
61 public override bool SetAlwaysRun
62 {
63 get { return false; }
64 set { return; }
65 }
66
67 public override uint LocalID
68 {
69 set { return; }
70 }
71
72 public override bool Grabbed
73 {
74 set { return; }
75 }
76
77 public override bool Selected
78 {
79 set { return; }
80 }
81
82 public override float Buoyancy
83 {
84 get { return 0f; }
85 set { return; }
86 }
87
88 public override bool FloatOnWater
89 {
90 set { return; }
91 }
92
93 public override bool IsPhysical
94 {
95 get { return false; }
96 set { return; }
97 }
98
99 public override bool ThrottleUpdates
100 {
101 get { return false; }
102 set { return; }
103 }
104
105 public override bool Flying { get; set; }
106
107 public override bool IsColliding { get; set; }
108
109 public override bool CollidingGround
110 {
111 get { return false; }
112 set { return; }
113 }
114
115 public override bool CollidingObj
116 {
117 get { return false; }
118 set { return; }
119 }
120
121 public override bool Stopped
122 {
123 get { return false; }
124 }
125
126 public override Vector3 Position { get; set; }
127
128 public override Vector3 Size
129 {
130 get { return _size; }
131 set {
132 _size = value;
133 _size.Z = _size.Z / 2.0f;
134 }
135 }
136
137 public override PrimitiveBaseShape Shape
138 {
139// set { _shape = value; }
140 set {}
141 }
142
143 public override float Mass
144 {
145 get { return 0f; }
146 }
147
148 public override Vector3 Force
149 {
150 get { return Vector3.Zero; }
151 set { return; }
152 }
153
154 public override int VehicleType
155 {
156 get { return 0; }
157 set { return; }
158 }
159
160 public override void VehicleFloatParam(int param, float value)
161 {
162
163 }
164
165 public override void VehicleVectorParam(int param, Vector3 value)
166 {
167
168 }
169
170 public override void VehicleRotationParam(int param, Quaternion rotation)
171 {
172
173 }
174
175 public override void VehicleFlags(int param, bool remove)
176 {
177
178 }
179
180 public override void SetVolumeDetect(int param)
181 {
182
183 }
184
185 public override Vector3 CenterOfMass
186 {
187 get { return Vector3.Zero; }
188 }
189
190 public override Vector3 GeometricCenter
191 {
192 get { return Vector3.Zero; }
193 }
194
195 public override Vector3 Velocity { get; set; }
196
197 public override Vector3 Torque
198 {
199 get { return Vector3.Zero; }
200 set { return; }
201 }
202
203 public override float CollisionScore
204 {
205 get { return 0f; }
206 set { }
207 }
208
209 public override Quaternion Orientation { get; set; }
210
211 public override Vector3 Acceleration { get; set; }
212
213 public override bool Kinematic
214 {
215 get { return true; }
216 set { }
217 }
218
219 public override void link(PhysicsActor obj)
220 {
221 }
222
223 public override void delink()
224 {
225 }
226
227 public override void LockAngularMotion(Vector3 axis)
228 {
229 }
230
231 public override void AddForce(Vector3 force, bool pushforce)
232 {
233 }
234
235 public override void AddAngularForce(Vector3 force, bool pushforce)
236 {
237 }
238
239 public override void SetMomentum(Vector3 momentum)
240 {
241 }
242
243 public override void CrossingFailure()
244 {
245 }
246
247 public override Vector3 PIDTarget
248 {
249 set { return; }
250 }
251
252 public override bool PIDActive
253 {
254 set { return; }
255 }
256
257 public override float PIDTau
258 {
259 set { return; }
260 }
261
262 public override float PIDHoverHeight
263 {
264 set { return; }
265 }
266
267 public override bool PIDHoverActive
268 {
269 set { return; }
270 }
271
272 public override PIDHoverType PIDHoverType
273 {
274 set { return; }
275 }
276
277 public override float PIDHoverTau
278 {
279 set { return; }
280 }
281
282 public override Quaternion APIDTarget
283 {
284 set { return; }
285 }
286
287 public override bool APIDActive
288 {
289 set { return; }
290 }
291
292 public override float APIDStrength
293 {
294 set { return; }
295 }
296
297 public override float APIDDamping
298 {
299 set { return; }
300 }
301
302 public override void SubscribeEvents(int ms)
303 {
304 }
305
306 public override void UnSubscribeEvents()
307 {
308 }
309
310 public override bool SubscribedEvents()
311 {
312 return false;
313 }
314 }
315}
diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs
index 2e14216..f5826ed 100644
--- a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs
+++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs
@@ -34,9 +34,17 @@ using OpenSim.Region.Physics.Manager;
34 34
35namespace OpenSim.Region.Physics.BasicPhysicsPlugin 35namespace OpenSim.Region.Physics.BasicPhysicsPlugin
36{ 36{
37 /// <summary>
38 /// This is an incomplete extremely basic physics implementation
39 /// </summary>
40 /// <remarks>
41 /// Not useful for anything at the moment apart from some regression testing in other components where some form
42 /// of physics plugin is needed.
43 /// </remarks>
37 public class BasicScene : PhysicsScene 44 public class BasicScene : PhysicsScene
38 { 45 {
39 private List<BasicActor> _actors = new List<BasicActor>(); 46 private List<BasicActor> _actors = new List<BasicActor>();
47 private List<BasicPhysicsPrim> _prims = new List<BasicPhysicsPrim>();
40 private float[] _heightMap; 48 private float[] _heightMap;
41 49
42 //protected internal string sceneIdentifier; 50 //protected internal string sceneIdentifier;
@@ -50,10 +58,19 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
50 { 58 {
51 } 59 }
52 60
53 public override void Dispose() 61 public override void Dispose() {}
62
63 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
64 Vector3 size, Quaternion rotation, bool isPhysical, uint localid)
54 { 65 {
66 BasicPhysicsPrim prim = new BasicPhysicsPrim(primName, localid, position, size, rotation, pbs);
67 prim.IsPhysical = isPhysical;
68
69 _prims.Add(prim);
55 70
71 return prim;
56 } 72 }
73
57 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) 74 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying)
58 { 75 {
59 BasicActor act = new BasicActor(size); 76 BasicActor act = new BasicActor(size);
@@ -63,30 +80,18 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
63 return act; 80 return act;
64 } 81 }
65 82
66 public override void RemovePrim(PhysicsActor prim) 83 public override void RemovePrim(PhysicsActor actor)
67 { 84 {
85 BasicPhysicsPrim prim = (BasicPhysicsPrim)actor;
86 if (_prims.Contains(prim))
87 _prims.Remove(prim);
68 } 88 }
69 89
70 public override void RemoveAvatar(PhysicsActor actor) 90 public override void RemoveAvatar(PhysicsActor actor)
71 { 91 {
72 BasicActor act = (BasicActor) actor; 92 BasicActor act = (BasicActor)actor;
73 if (_actors.Contains(act)) 93 if (_actors.Contains(act))
74 {
75 _actors.Remove(act); 94 _actors.Remove(act);
76 }
77 }
78
79/*
80 public override PhysicsActor AddPrim(Vector3 position, Vector3 size, Quaternion rotation)
81 {
82 return null;
83 }
84*/
85
86 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
87 Vector3 size, Quaternion rotation, bool isPhysical, uint localid)
88 {
89 return null;
90 } 95 }
91 96
92 public override void AddPhysicsActorTaint(PhysicsActor prim) 97 public override void AddPhysicsActorTaint(PhysicsActor prim)
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index b08d5db..dc0c008 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -74,7 +74,7 @@ public class BSCharacter : PhysicsActor
74 private float _buoyancy; 74 private float _buoyancy;
75 75
76 private int _subscribedEventsMs = 0; 76 private int _subscribedEventsMs = 0;
77 private int _lastCollisionTime = 0; 77 private int _nextCollisionOkTime = 0;
78 78
79 private Vector3 _PIDTarget; 79 private Vector3 _PIDTarget;
80 private bool _usePID; 80 private bool _usePID;
@@ -360,17 +360,22 @@ public class BSCharacter : PhysicsActor
360 } 360 }
361 //m_lastUpdateSent = false; 361 //m_lastUpdateSent = false;
362 } 362 }
363
363 public override void AddAngularForce(Vector3 force, bool pushforce) { 364 public override void AddAngularForce(Vector3 force, bool pushforce) {
364 } 365 }
365 public override void SetMomentum(Vector3 momentum) { 366 public override void SetMomentum(Vector3 momentum) {
366 } 367 }
368
369 // Turn on collision events at a rate no faster than one every the given milliseconds
367 public override void SubscribeEvents(int ms) { 370 public override void SubscribeEvents(int ms) {
368 _subscribedEventsMs = ms; 371 _subscribedEventsMs = ms;
369 _lastCollisionTime = Util.EnvironmentTickCount() - _subscribedEventsMs; // make first collision happen 372 _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs; // make first collision happen
370 } 373 }
374 // Stop collision events
371 public override void UnSubscribeEvents() { 375 public override void UnSubscribeEvents() {
372 _subscribedEventsMs = 0; 376 _subscribedEventsMs = 0;
373 } 377 }
378 // Return 'true' if someone has subscribed to events
374 public override bool SubscribedEvents() { 379 public override bool SubscribedEvents() {
375 return (_subscribedEventsMs > 0); 380 return (_subscribedEventsMs > 0);
376 } 381 }
@@ -386,47 +391,57 @@ public class BSCharacter : PhysicsActor
386 _mass = _density * _avatarVolume; 391 _mass = _density * _avatarVolume;
387 } 392 }
388 393
394 // Set to 'true' if the individual changed items should be checked
395 // (someday RequestPhysicsTerseUpdate() will take a bitmap of changed properties)
396 const bool SHOULD_CHECK_FOR_INDIVIDUAL_CHANGES = false;
397
389 // The physics engine says that properties have updated. Update same and inform 398 // The physics engine says that properties have updated. Update same and inform
390 // the world that things have changed. 399 // the world that things have changed.
391 public void UpdateProperties(EntityProperties entprop) 400 public void UpdateProperties(EntityProperties entprop)
392 { 401 {
393 bool changed = false; 402 bool changed = false;
394 // we assign to the local variables so the normal set action does not happen 403 if (SHOULD_CHECK_FOR_INDIVIDUAL_CHANGES) {
395 if (_position != entprop.Position) 404 // we assign to the local variables so the normal set action does not happen
396 { 405 if (_position != entprop.Position) {
397 _position = entprop.Position; 406 _position = entprop.Position;
398 changed = true; 407 changed = true;
408 }
409 if (_orientation != entprop.Rotation) {
410 _orientation = entprop.Rotation;
411 changed = true;
412 }
413 if (_velocity != entprop.Velocity) {
414 _velocity = entprop.Velocity;
415 changed = true;
416 }
417 if (_acceleration != entprop.Acceleration) {
418 _acceleration = entprop.Acceleration;
419 changed = true;
420 }
421 if (_rotationalVelocity != entprop.RotationalVelocity) {
422 _rotationalVelocity = entprop.RotationalVelocity;
423 changed = true;
424 }
425 if (changed) {
426 // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
427 // Avatar movement is not done by generating this event. There is code in the heartbeat
428 // loop that updates avatars.
429 // base.RequestPhysicsterseUpdate();
430 }
399 } 431 }
400 if (_orientation != entprop.Rotation) 432 else {
401 { 433 _position = entprop.Position;
402 _orientation = entprop.Rotation; 434 _orientation = entprop.Rotation;
403 changed = true;
404 }
405 if (_velocity != entprop.Velocity)
406 {
407 _velocity = entprop.Velocity; 435 _velocity = entprop.Velocity;
408 changed = true;
409 }
410 if (_acceleration != entprop.Acceleration)
411 {
412 _acceleration = entprop.Acceleration; 436 _acceleration = entprop.Acceleration;
413 changed = true;
414 }
415 if (_rotationalVelocity != entprop.RotationalVelocity)
416 {
417 _rotationalVelocity = entprop.RotationalVelocity; 437 _rotationalVelocity = entprop.RotationalVelocity;
418 changed = true;
419 }
420 if (changed)
421 {
422 // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
423 // Avatar movement is not done by generating this event. There is a system that
424 // checks for avatar updates each heartbeat loop.
425 // base.RequestPhysicsterseUpdate(); 438 // base.RequestPhysicsterseUpdate();
426 } 439 }
427 } 440 }
428 441
429 // Called by the scene when a collision with this object is reported 442 // Called by the scene when a collision with this object is reported
443 // The collision, if it should be reported to the character, is placed in a collection
444 // that will later be sent to the simulator when SendCollisions() is called.
430 CollisionEventUpdate collisionCollection = null; 445 CollisionEventUpdate collisionCollection = null;
431 public void Collide(uint collidingWith, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth) 446 public void Collide(uint collidingWith, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth)
432 { 447 {
@@ -440,29 +455,34 @@ public class BSCharacter : PhysicsActor
440 } 455 }
441 456
442 // throttle collisions to the rate specified in the subscription 457 // throttle collisions to the rate specified in the subscription
443 if (_subscribedEventsMs == 0) return; // don't want collisions 458 if (_subscribedEventsMs != 0) {
444 int nowTime = _scene.SimulationNowTime; 459 int nowTime = _scene.SimulationNowTime;
445 if (nowTime < (_lastCollisionTime + _subscribedEventsMs)) return; 460 if (nowTime >= _nextCollisionOkTime) {
446 _lastCollisionTime = nowTime; 461 _nextCollisionOkTime = nowTime + _subscribedEventsMs;
447 462
448 if (collisionCollection == null) 463 if (collisionCollection == null)
449 collisionCollection = new CollisionEventUpdate(); 464 collisionCollection = new CollisionEventUpdate();
450 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); 465 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
466 }
467 }
451 } 468 }
452 469
453 public void SendCollisions() 470 public void SendCollisions()
454 { 471 {
455 // if (collisionCollection != null) 472 /*
456 // { 473 if (collisionCollection != null && collisionCollection.Count > 0)
457 // base.SendCollisionUpdate(collisionCollection); 474 {
458 // collisionCollection = null; 475 base.SendCollisionUpdate(collisionCollection);
459 // } 476 collisionCollection = null;
477 }
478 */
460 // Kludge to make a collision call even if there are no collisions. 479 // Kludge to make a collision call even if there are no collisions.
461 // This causes the avatar animation to get updated. 480 // This causes the avatar animation to get updated.
462 if (collisionCollection == null) 481 if (collisionCollection == null)
463 collisionCollection = new CollisionEventUpdate(); 482 collisionCollection = new CollisionEventUpdate();
464 base.SendCollisionUpdate(collisionCollection); 483 base.SendCollisionUpdate(collisionCollection);
465 collisionCollection = null; 484 collisionCollection.Clear();
485 // End kludge
466 } 486 }
467 487
468} 488}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs
index 0730824..0f027b8 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs
@@ -32,6 +32,14 @@ using OpenMetaverse;
32 32
33namespace OpenSim.Region.Physics.BulletSPlugin 33namespace OpenSim.Region.Physics.BulletSPlugin
34{ 34{
35 /// <summary>
36 /// Entry for a port of Bullet (http://bulletphysics.org/) to OpenSim.
37 /// This module interfaces to an unmanaged C++ library which makes the
38 /// actual calls into the Bullet physics engine.
39 /// The unmanaged library is found in opensim-libs::trunk/unmanaged/BulletSim/.
40 /// The unmanaged library is compiled and linked statically with Bullet
41 /// to create BulletSim.dll and libBulletSim.so (for both 32 and 64 bit).
42 /// </summary>
35public class BSPlugin : IPhysicsPlugin 43public class BSPlugin : IPhysicsPlugin
36{ 44{
37 //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 45 //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
@@ -53,6 +61,9 @@ public class BSPlugin : IPhysicsPlugin
53 { 61 {
54 if (Util.IsWindows()) 62 if (Util.IsWindows())
55 Util.LoadArchSpecificWindowsDll("BulletSim.dll"); 63 Util.LoadArchSpecificWindowsDll("BulletSim.dll");
64 // If not Windows, loading is performed by the
65 // Mono loader as specified in
66 // "bin/Physics/OpenSim.Region.Physics.BulletSPlugin.dll.config".
56 67
57 _mScene = new BSScene(sceneIdentifier); 68 _mScene = new BSScene(sceneIdentifier);
58 } 69 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 248d1f2..130f1ca 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -90,7 +90,7 @@ public sealed class BSPrim : PhysicsActor
90 private BSPrim _parentPrim; 90 private BSPrim _parentPrim;
91 91
92 private int _subscribedEventsMs = 0; 92 private int _subscribedEventsMs = 0;
93 private int _lastCollisionTime = 0; 93 private int _nextCollisionOkTime = 0;
94 long _collidingStep; 94 long _collidingStep;
95 long _collidingGroundStep; 95 long _collidingGroundStep;
96 96
@@ -597,7 +597,8 @@ public sealed class BSPrim : PhysicsActor
597 } 597 }
598 public override void SubscribeEvents(int ms) { 598 public override void SubscribeEvents(int ms) {
599 _subscribedEventsMs = ms; 599 _subscribedEventsMs = ms;
600 _lastCollisionTime = Util.EnvironmentTickCount() - _subscribedEventsMs; // make first collision happen 600 // make sure first collision happens
601 _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs;
601 } 602 }
602 public override void UnSubscribeEvents() { 603 public override void UnSubscribeEvents() {
603 _subscribedEventsMs = 0; 604 _subscribedEventsMs = 0;
@@ -1338,23 +1339,27 @@ public sealed class BSPrim : PhysicsActor
1338 _collidingGroundStep = _scene.SimulationStep; 1339 _collidingGroundStep = _scene.SimulationStep;
1339 } 1340 }
1340 1341
1341 if (_subscribedEventsMs == 0) return; // nothing in the object is waiting for collision events 1342 // if someone is subscribed to collision events....
1342 // throttle the collisions to the number of milliseconds specified in the subscription 1343 if (_subscribedEventsMs != 0) {
1343 int nowTime = _scene.SimulationNowTime; 1344 // throttle the collisions to the number of milliseconds specified in the subscription
1344 if (nowTime < (_lastCollisionTime + _subscribedEventsMs)) return; 1345 int nowTime = _scene.SimulationNowTime;
1345 _lastCollisionTime = nowTime; 1346 if (nowTime >= _nextCollisionOkTime) {
1347 _nextCollisionOkTime = nowTime + _subscribedEventsMs;
1346 1348
1347 if (collisionCollection == null) 1349 if (collisionCollection == null)
1348 collisionCollection = new CollisionEventUpdate(); 1350 collisionCollection = new CollisionEventUpdate();
1349 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); 1351 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
1352 }
1353 }
1350 } 1354 }
1351 1355
1356 // The scene is telling us it's time to pass our collected collisions into the simulator
1352 public void SendCollisions() 1357 public void SendCollisions()
1353 { 1358 {
1354 if (collisionCollection != null) 1359 if (collisionCollection != null && collisionCollection.Count > 0)
1355 { 1360 {
1356 base.SendCollisionUpdate(collisionCollection); 1361 base.SendCollisionUpdate(collisionCollection);
1357 collisionCollection = null; 1362 collisionCollection.Clear();
1358 } 1363 }
1359 } 1364 }
1360} 1365}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 94a0ccf..417cb5f 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -52,6 +52,7 @@ using OpenSim.Region.Framework;
52// Should prim.link() and prim.delink() membership checking happen at taint time? 52// Should prim.link() and prim.delink() membership checking happen at taint time?
53// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once 53// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once
54// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect 54// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect
55// Use collision masks for collision with terrain and phantom objects
55// Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions) 56// Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions)
56// Implement LockAngularMotion 57// Implement LockAngularMotion
57// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) 58// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation)
@@ -62,9 +63,6 @@ using OpenSim.Region.Framework;
62// Multiple contact points on collision? 63// Multiple contact points on collision?
63// See code in ode::near... calls to collision_accounting_events() 64// See code in ode::near... calls to collision_accounting_events()
64// (This might not be a problem. ODE collects all the collisions with one object in one tick.) 65// (This might not be a problem. ODE collects all the collisions with one object in one tick.)
65// Use collision masks for collision with terrain and phantom objects
66// Figure out how to not allocate a new Dictionary and List for every collision
67// in BSPrim.Collide() and BSCharacter.Collide(). Can the same ones be reused?
68// Raycast 66// Raycast
69// 67//
70namespace OpenSim.Region.Physics.BulletSPlugin 68namespace OpenSim.Region.Physics.BulletSPlugin
@@ -405,6 +403,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
405 // prevent simulation until we've been initialized 403 // prevent simulation until we've been initialized
406 if (!m_initialized) return 10.0f; 404 if (!m_initialized) return 10.0f;
407 405
406 long simulateStartTime = Util.EnvironmentTickCount();
407
408 // update the prim states while we know the physics engine is not busy 408 // update the prim states while we know the physics engine is not busy
409 ProcessTaints(); 409 ProcessTaints();
410 410
@@ -437,13 +437,18 @@ public class BSScene : PhysicsScene, IPhysicsParameters
437 } 437 }
438 } 438 }
439 439
440 // The SendCollision's batch up the collisions on the objects. Now push the collisions into the simulator. 440 // The above SendCollision's batch up the collisions on the objects.
441 // Now push the collisions into the simulator.
441 foreach (BSPrim bsp in m_primsWithCollisions) 442 foreach (BSPrim bsp in m_primsWithCollisions)
442 bsp.SendCollisions(); 443 bsp.SendCollisions();
443 m_primsWithCollisions.Clear(); 444 m_primsWithCollisions.Clear();
445
446 // This is a kludge to get avatar movement updated.
447 // Don't send collisions only if there were collisions -- send everytime.
448 // ODE sends collisions even if there are none and this is used to update
449 // avatar animations and stuff.
444 // foreach (BSCharacter bsc in m_avatarsWithCollisions) 450 // foreach (BSCharacter bsc in m_avatarsWithCollisions)
445 // bsc.SendCollisions(); 451 // bsc.SendCollisions();
446 // This is a kludge to get avatar movement updated. ODE sends collisions even if there isn't any
447 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars) 452 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars)
448 kvp.Value.SendCollisions(); 453 kvp.Value.SendCollisions();
449 m_avatarsWithCollisions.Clear(); 454 m_avatarsWithCollisions.Clear();
@@ -465,10 +470,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
465 if (m_avatars.TryGetValue(entprop.ID, out actor)) 470 if (m_avatars.TryGetValue(entprop.ID, out actor))
466 { 471 {
467 actor.UpdateProperties(entprop); 472 actor.UpdateProperties(entprop);
473 continue;
468 } 474 }
469 } 475 }
470 } 476 }
471 477
478 // If enabled, call into the physics engine to dump statistics
472 if (m_detailedStatsStep > 0) 479 if (m_detailedStatsStep > 0)
473 { 480 {
474 if ((m_simulationStep % m_detailedStatsStep) == 0) 481 if ((m_simulationStep % m_detailedStatsStep) == 0)
@@ -477,6 +484,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
477 } 484 }
478 } 485 }
479 486
487 // this is a waste since the outside routine also calcuates the physics simulation
488 // period. TODO: There should be a way of computing physics frames from simulator computation.
489 // long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime);
490 // return (timeStep * (float)simulateTotalTime);
491
480 // TODO: FIX THIS: fps calculation wrong. This calculation always returns about 1 in normal operation. 492 // TODO: FIX THIS: fps calculation wrong. This calculation always returns about 1 in normal operation.
481 return timeStep / (numSubSteps * m_fixedTimeStep) * 1000f; 493 return timeStep / (numSubSteps * m_fixedTimeStep) * 1000f;
482 } 494 }
@@ -528,6 +540,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
528 public override void SetWaterLevel(float baseheight) 540 public override void SetWaterLevel(float baseheight)
529 { 541 {
530 m_waterLevel = baseheight; 542 m_waterLevel = baseheight;
543 // TODO: pass to physics engine so things will float?
531 } 544 }
532 public float GetWaterLevel() 545 public float GetWaterLevel()
533 { 546 {
diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
index d10a2aa..cfede55 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
@@ -241,8 +241,22 @@ namespace OpenSim.Region.Physics.Manager
241 241
242 public abstract void AddPhysicsActorTaint(PhysicsActor prim); 242 public abstract void AddPhysicsActorTaint(PhysicsActor prim);
243 243
244 /// <summary>
245 /// Perform a simulation of the current physics scene over the given timestep.
246 /// </summary>
247 /// <param name="timeStep"></param>
248 /// <returns>The number of frames simulated over that period.</returns>
244 public abstract float Simulate(float timeStep); 249 public abstract float Simulate(float timeStep);
245 250
251 /// <summary>
252 /// Get statistics about this scene.
253 /// </summary>
254 /// <remarks>This facility is currently experimental and subject to change.</remarks>
255 /// <returns>
256 /// A dictionary where the key is the statistic name. If no statistics are supplied then returns null.
257 /// </returns>
258 public virtual Dictionary<string, float> GetStats() { return null; }
259
246 public abstract void GetResults(); 260 public abstract void GetResults();
247 261
248 public abstract void SetTerrain(float[] heightMap); 262 public abstract void SetTerrain(float[] heightMap);
diff --git a/OpenSim/Region/Physics/Meshing/PrimMesher.cs b/OpenSim/Region/Physics/Meshing/PrimMesher.cs
index 53022ad..4049ee1 100644
--- a/OpenSim/Region/Physics/Meshing/PrimMesher.cs
+++ b/OpenSim/Region/Physics/Meshing/PrimMesher.cs
@@ -236,6 +236,13 @@ namespace PrimMesher
236 this.U = u; 236 this.U = u;
237 this.V = v; 237 this.V = v;
238 } 238 }
239
240 public UVCoord Flip()
241 {
242 this.U = 1.0f - this.U;
243 this.V = 1.0f - this.V;
244 return this;
245 }
239 } 246 }
240 247
241 public struct Face 248 public struct Face
@@ -603,40 +610,40 @@ namespace PrimMesher
603 /// <summary> 610 /// <summary>
604 /// generates a profile for extrusion 611 /// generates a profile for extrusion
605 /// </summary> 612 /// </summary>
606 internal class Profile 613 public class Profile
607 { 614 {
608 private const float twoPi = 2.0f * (float)Math.PI; 615 private const float twoPi = 2.0f * (float)Math.PI;
609 616
610 internal string errorMessage = null; 617 public string errorMessage = null;
611 618
612 internal List<Coord> coords; 619 public List<Coord> coords;
613 internal List<Face> faces; 620 public List<Face> faces;
614 internal List<Coord> vertexNormals; 621 public List<Coord> vertexNormals;
615 internal List<float> us; 622 public List<float> us;
616 internal List<UVCoord> faceUVs; 623 public List<UVCoord> faceUVs;
617 internal List<int> faceNumbers; 624 public List<int> faceNumbers;
618 625
619 // use these for making individual meshes for each prim face 626 // use these for making individual meshes for each prim face
620 internal List<int> outerCoordIndices = null; 627 public List<int> outerCoordIndices = null;
621 internal List<int> hollowCoordIndices = null; 628 public List<int> hollowCoordIndices = null;
622 internal List<int> cut1CoordIndices = null; 629 public List<int> cut1CoordIndices = null;
623 internal List<int> cut2CoordIndices = null; 630 public List<int> cut2CoordIndices = null;
624 631
625 internal Coord faceNormal = new Coord(0.0f, 0.0f, 1.0f); 632 public Coord faceNormal = new Coord(0.0f, 0.0f, 1.0f);
626 internal Coord cutNormal1 = new Coord(); 633 public Coord cutNormal1 = new Coord();
627 internal Coord cutNormal2 = new Coord(); 634 public Coord cutNormal2 = new Coord();
628 635
629 internal int numOuterVerts = 0; 636 public int numOuterVerts = 0;
630 internal int numHollowVerts = 0; 637 public int numHollowVerts = 0;
631 638
632 internal int outerFaceNumber = -1; 639 public int outerFaceNumber = -1;
633 internal int hollowFaceNumber = -1; 640 public int hollowFaceNumber = -1;
634 641
635 internal bool calcVertexNormals = false; 642 public bool calcVertexNormals = false;
636 internal int bottomFaceNumber = 0; 643 public int bottomFaceNumber = 0;
637 internal int numPrimFaces = 0; 644 public int numPrimFaces = 0;
638 645
639 internal Profile() 646 public Profile()
640 { 647 {
641 this.coords = new List<Coord>(); 648 this.coords = new List<Coord>();
642 this.faces = new List<Face>(); 649 this.faces = new List<Face>();
@@ -646,7 +653,7 @@ namespace PrimMesher
646 this.faceNumbers = new List<int>(); 653 this.faceNumbers = new List<int>();
647 } 654 }
648 655
649 internal Profile(int sides, float profileStart, float profileEnd, float hollow, int hollowSides, bool createFaces, bool calcVertexNormals) 656 public Profile(int sides, float profileStart, float profileEnd, float hollow, int hollowSides, bool createFaces, bool calcVertexNormals)
650 { 657 {
651 this.calcVertexNormals = calcVertexNormals; 658 this.calcVertexNormals = calcVertexNormals;
652 this.coords = new List<Coord>(); 659 this.coords = new List<Coord>();
@@ -657,7 +664,6 @@ namespace PrimMesher
657 this.faceNumbers = new List<int>(); 664 this.faceNumbers = new List<int>();
658 665
659 Coord center = new Coord(0.0f, 0.0f, 0.0f); 666 Coord center = new Coord(0.0f, 0.0f, 0.0f);
660 //bool hasCenter = false;
661 667
662 List<Coord> hollowCoords = new List<Coord>(); 668 List<Coord> hollowCoords = new List<Coord>();
663 List<Coord> hollowNormals = new List<Coord>(); 669 List<Coord> hollowNormals = new List<Coord>();
@@ -682,8 +688,8 @@ namespace PrimMesher
682 float yScale = 0.5f; 688 float yScale = 0.5f;
683 if (sides == 4) // corners of a square are sqrt(2) from center 689 if (sides == 4) // corners of a square are sqrt(2) from center
684 { 690 {
685 xScale = 0.707f; 691 xScale = 0.707107f;
686 yScale = 0.707f; 692 yScale = 0.707107f;
687 } 693 }
688 694
689 float startAngle = profileStart * twoPi; 695 float startAngle = profileStart * twoPi;
@@ -724,7 +730,6 @@ namespace PrimMesher
724 else if (!simpleFace) 730 else if (!simpleFace)
725 { 731 {
726 this.coords.Add(center); 732 this.coords.Add(center);
727 //hasCenter = true;
728 if (this.calcVertexNormals) 733 if (this.calcVertexNormals)
729 this.vertexNormals.Add(new Coord(0.0f, 0.0f, 1.0f)); 734 this.vertexNormals.Add(new Coord(0.0f, 0.0f, 1.0f));
730 this.us.Add(0.0f); 735 this.us.Add(0.0f);
@@ -752,7 +757,10 @@ namespace PrimMesher
752 else 757 else
753 hollowNormals.Add(new Coord(-angle.X, -angle.Y, 0.0f)); 758 hollowNormals.Add(new Coord(-angle.X, -angle.Y, 0.0f));
754 759
755 hollowUs.Add(angle.angle * hollow); 760 if (hollowSides == 4)
761 hollowUs.Add(angle.angle * hollow * 0.707107f);
762 else
763 hollowUs.Add(angle.angle * hollow);
756 } 764 }
757 } 765 }
758 } 766 }
@@ -829,9 +837,6 @@ namespace PrimMesher
829 837
830 if (createFaces) 838 if (createFaces)
831 { 839 {
832 //int numOuterVerts = this.coords.Count;
833 //numOuterVerts = this.coords.Count;
834 //int numHollowVerts = hollowCoords.Count;
835 int numTotalVerts = this.numOuterVerts + this.numHollowVerts; 840 int numTotalVerts = this.numOuterVerts + this.numHollowVerts;
836 841
837 if (this.numOuterVerts == this.numHollowVerts) 842 if (this.numOuterVerts == this.numHollowVerts)
@@ -993,11 +998,7 @@ namespace PrimMesher
993 if (startVert > 0) 998 if (startVert > 0)
994 this.faceNumbers.Add(-1); 999 this.faceNumbers.Add(-1);
995 for (int i = 0; i < this.numOuterVerts - 1; i++) 1000 for (int i = 0; i < this.numOuterVerts - 1; i++)
996 //this.faceNumbers.Add(sides < 5 ? faceNum++ : faceNum); 1001 this.faceNumbers.Add(sides < 5 && i <= sides ? faceNum++ : faceNum);
997 this.faceNumbers.Add(sides < 5 && i < sides ? faceNum++ : faceNum);
998
999 //if (!hasHollow && !hasProfileCut)
1000 // this.bottomFaceNumber = faceNum++;
1001 1002
1002 this.faceNumbers.Add(hasProfileCut ? -1 : faceNum++); 1003 this.faceNumbers.Add(hasProfileCut ? -1 : faceNum++);
1003 1004
@@ -1014,8 +1015,7 @@ namespace PrimMesher
1014 1015
1015 this.hollowFaceNumber = faceNum++; 1016 this.hollowFaceNumber = faceNum++;
1016 } 1017 }
1017 //if (hasProfileCut || hasHollow) 1018
1018 // this.bottomFaceNumber = faceNum++;
1019 this.bottomFaceNumber = faceNum++; 1019 this.bottomFaceNumber = faceNum++;
1020 1020
1021 if (hasHollow && hasProfileCut) 1021 if (hasHollow && hasProfileCut)
@@ -1030,19 +1030,19 @@ namespace PrimMesher
1030 1030
1031 } 1031 }
1032 1032
1033 internal void MakeFaceUVs() 1033 public void MakeFaceUVs()
1034 { 1034 {
1035 this.faceUVs = new List<UVCoord>(); 1035 this.faceUVs = new List<UVCoord>();
1036 foreach (Coord c in this.coords) 1036 foreach (Coord c in this.coords)
1037 this.faceUVs.Add(new UVCoord(0.5f + c.X, 0.5f - c.Y)); 1037 this.faceUVs.Add(new UVCoord(1.0f - (0.5f + c.X), 1.0f - (0.5f - c.Y)));
1038 } 1038 }
1039 1039
1040 internal Profile Copy() 1040 public Profile Copy()
1041 { 1041 {
1042 return this.Copy(true); 1042 return this.Copy(true);
1043 } 1043 }
1044 1044
1045 internal Profile Copy(bool needFaces) 1045 public Profile Copy(bool needFaces)
1046 { 1046 {
1047 Profile copy = new Profile(); 1047 Profile copy = new Profile();
1048 1048
@@ -1071,12 +1071,12 @@ namespace PrimMesher
1071 return copy; 1071 return copy;
1072 } 1072 }
1073 1073
1074 internal void AddPos(Coord v) 1074 public void AddPos(Coord v)
1075 { 1075 {
1076 this.AddPos(v.X, v.Y, v.Z); 1076 this.AddPos(v.X, v.Y, v.Z);
1077 } 1077 }
1078 1078
1079 internal void AddPos(float x, float y, float z) 1079 public void AddPos(float x, float y, float z)
1080 { 1080 {
1081 int i; 1081 int i;
1082 int numVerts = this.coords.Count; 1082 int numVerts = this.coords.Count;
@@ -1092,7 +1092,7 @@ namespace PrimMesher
1092 } 1092 }
1093 } 1093 }
1094 1094
1095 internal void AddRot(Quat q) 1095 public void AddRot(Quat q)
1096 { 1096 {
1097 int i; 1097 int i;
1098 int numVerts = this.coords.Count; 1098 int numVerts = this.coords.Count;
@@ -1113,7 +1113,7 @@ namespace PrimMesher
1113 } 1113 }
1114 } 1114 }
1115 1115
1116 internal void Scale(float x, float y) 1116 public void Scale(float x, float y)
1117 { 1117 {
1118 int i; 1118 int i;
1119 int numVerts = this.coords.Count; 1119 int numVerts = this.coords.Count;
@@ -1131,7 +1131,7 @@ namespace PrimMesher
1131 /// <summary> 1131 /// <summary>
1132 /// Changes order of the vertex indices and negates the center vertex normal. Does not alter vertex normals of radial vertices 1132 /// Changes order of the vertex indices and negates the center vertex normal. Does not alter vertex normals of radial vertices
1133 /// </summary> 1133 /// </summary>
1134 internal void FlipNormals() 1134 public void FlipNormals()
1135 { 1135 {
1136 int i; 1136 int i;
1137 int numFaces = this.faces.Count; 1137 int numFaces = this.faces.Count;
@@ -1171,7 +1171,7 @@ namespace PrimMesher
1171 } 1171 }
1172 } 1172 }
1173 1173
1174 internal void AddValue2FaceVertexIndices(int num) 1174 public void AddValue2FaceVertexIndices(int num)
1175 { 1175 {
1176 int numFaces = this.faces.Count; 1176 int numFaces = this.faces.Count;
1177 Face tmpFace; 1177 Face tmpFace;
@@ -1186,7 +1186,7 @@ namespace PrimMesher
1186 } 1186 }
1187 } 1187 }
1188 1188
1189 internal void AddValue2FaceNormalIndices(int num) 1189 public void AddValue2FaceNormalIndices(int num)
1190 { 1190 {
1191 if (this.calcVertexNormals) 1191 if (this.calcVertexNormals)
1192 { 1192 {
@@ -1204,7 +1204,7 @@ namespace PrimMesher
1204 } 1204 }
1205 } 1205 }
1206 1206
1207 internal void DumpRaw(String path, String name, String title) 1207 public void DumpRaw(String path, String name, String title)
1208 { 1208 {
1209 if (path == null) 1209 if (path == null)
1210 return; 1210 return;
@@ -1261,6 +1261,15 @@ namespace PrimMesher
1261 1261
1262 public void Create(PathType pathType, int steps) 1262 public void Create(PathType pathType, int steps)
1263 { 1263 {
1264 if (this.taperX > 0.999f)
1265 this.taperX = 0.999f;
1266 if (this.taperX < -0.999f)
1267 this.taperX = -0.999f;
1268 if (this.taperY > 0.999f)
1269 this.taperY = 0.999f;
1270 if (this.taperY < -0.999f)
1271 this.taperY = -0.999f;
1272
1264 if (pathType == PathType.Linear || pathType == PathType.Flexible) 1273 if (pathType == PathType.Linear || pathType == PathType.Flexible)
1265 { 1274 {
1266 int step = 0; 1275 int step = 0;
@@ -1273,12 +1282,12 @@ namespace PrimMesher
1273 1282
1274 float start = -0.5f; 1283 float start = -0.5f;
1275 float stepSize = length / (float)steps; 1284 float stepSize = length / (float)steps;
1276 float percentOfPathMultiplier = stepSize; 1285 float percentOfPathMultiplier = stepSize * 0.999999f;
1277 float xOffset = 0.0f; 1286 float xOffset = this.topShearX * this.pathCutBegin;
1278 float yOffset = 0.0f; 1287 float yOffset = this.topShearY * this.pathCutBegin;
1279 float zOffset = start; 1288 float zOffset = start;
1280 float xOffsetStepIncrement = this.topShearX / steps; 1289 float xOffsetStepIncrement = this.topShearX * length / steps;
1281 float yOffsetStepIncrement = this.topShearY / steps; 1290 float yOffsetStepIncrement = this.topShearY * length / steps;
1282 1291
1283 float percentOfPath = this.pathCutBegin; 1292 float percentOfPath = this.pathCutBegin;
1284 zOffset += percentOfPath; 1293 zOffset += percentOfPath;
@@ -1573,13 +1582,6 @@ namespace PrimMesher
1573 this.hollow = 0.99f; 1582 this.hollow = 0.99f;
1574 if (hollow < 0.0f) 1583 if (hollow < 0.0f)
1575 this.hollow = 0.0f; 1584 this.hollow = 0.0f;
1576
1577 //if (sphereMode)
1578 // this.hasProfileCut = this.profileEnd - this.profileStart < 0.4999f;
1579 //else
1580 // //this.hasProfileCut = (this.profileStart > 0.0f || this.profileEnd < 1.0f);
1581 // this.hasProfileCut = this.profileEnd - this.profileStart < 0.9999f;
1582 //this.hasHollow = (this.hollow > 0.001f);
1583 } 1585 }
1584 1586
1585 /// <summary> 1587 /// <summary>
@@ -1614,10 +1616,9 @@ namespace PrimMesher
1614 steps = (int)(steps * 4.5 * length); 1616 steps = (int)(steps * 4.5 * length);
1615 } 1617 }
1616 1618
1617 if (sphereMode) 1619 if (this.sphereMode)
1618 this.hasProfileCut = this.profileEnd - this.profileStart < 0.4999f; 1620 this.hasProfileCut = this.profileEnd - this.profileStart < 0.4999f;
1619 else 1621 else
1620 //this.hasProfileCut = (this.profileStart > 0.0f || this.profileEnd < 1.0f);
1621 this.hasProfileCut = this.profileEnd - this.profileStart < 0.9999f; 1622 this.hasProfileCut = this.profileEnd - this.profileStart < 0.9999f;
1622 this.hasHollow = (this.hollow > 0.001f); 1623 this.hasHollow = (this.hollow > 0.001f);
1623 1624
@@ -1630,6 +1631,22 @@ namespace PrimMesher
1630 1631
1631 float hollow = this.hollow; 1632 float hollow = this.hollow;
1632 1633
1634 if (pathType == PathType.Circular)
1635 {
1636 needEndFaces = false;
1637 if (this.pathCutBegin != 0.0f || this.pathCutEnd != 1.0f)
1638 needEndFaces = true;
1639 else if (this.taperX != 0.0f || this.taperY != 0.0f)
1640 needEndFaces = true;
1641 else if (this.skew != 0.0f)
1642 needEndFaces = true;
1643 else if (twistTotal != 0.0f)
1644 needEndFaces = true;
1645 else if (this.radius != 0.0f)
1646 needEndFaces = true;
1647 }
1648 else needEndFaces = true;
1649
1633 // sanity checks 1650 // sanity checks
1634 float initialProfileRot = 0.0f; 1651 float initialProfileRot = 0.0f;
1635 if (pathType == PathType.Circular) 1652 if (pathType == PathType.Circular)
@@ -1689,20 +1706,13 @@ namespace PrimMesher
1689 1706
1690 this.numPrimFaces = profile.numPrimFaces; 1707 this.numPrimFaces = profile.numPrimFaces;
1691 1708
1692 //profileOuterFaceNumber = profile.faceNumbers[0]; 1709 int cut1FaceNumber = profile.bottomFaceNumber + 1;
1693 //if (!needEndFaces) 1710 int cut2FaceNumber = cut1FaceNumber + 1;
1694 // profileOuterFaceNumber--; 1711 if (!needEndFaces)
1695 //profileOuterFaceNumber = needEndFaces ? 1 : 0; 1712 {
1696 1713 cut1FaceNumber -= 2;
1697 1714 cut2FaceNumber -= 2;
1698 //if (hasHollow) 1715 }
1699 //{
1700 // if (needEndFaces)
1701 // profileHollowFaceNumber = profile.faceNumbers[profile.numOuterVerts + 1];
1702 // else
1703 // profileHollowFaceNumber = profile.faceNumbers[profile.numOuterVerts] - 1;
1704 //}
1705
1706 1716
1707 profileOuterFaceNumber = profile.outerFaceNumber; 1717 profileOuterFaceNumber = profile.outerFaceNumber;
1708 if (!needEndFaces) 1718 if (!needEndFaces)
@@ -1732,7 +1742,8 @@ namespace PrimMesher
1732 1742
1733 Coord lastCutNormal1 = new Coord(); 1743 Coord lastCutNormal1 = new Coord();
1734 Coord lastCutNormal2 = new Coord(); 1744 Coord lastCutNormal2 = new Coord();
1735 float lastV = 1.0f; 1745 float thisV = 0.0f;
1746 float lastV = 0.0f;
1736 1747
1737 Path path = new Path(); 1748 Path path = new Path();
1738 path.twistBegin = twistBegin; 1749 path.twistBegin = twistBegin;
@@ -1754,23 +1765,6 @@ namespace PrimMesher
1754 1765
1755 path.Create(pathType, steps); 1766 path.Create(pathType, steps);
1756 1767
1757
1758 if (pathType == PathType.Circular)
1759 {
1760 needEndFaces = false;
1761 if (this.pathCutBegin != 0.0f || this.pathCutEnd != 1.0f)
1762 needEndFaces = true;
1763 else if (this.taperX != 0.0f || this.taperY != 0.0f)
1764 needEndFaces = true;
1765 else if (this.skew != 0.0f)
1766 needEndFaces = true;
1767 else if (twistTotal != 0.0f)
1768 needEndFaces = true;
1769 else if (this.radius != 0.0f)
1770 needEndFaces = true;
1771 }
1772 else needEndFaces = true;
1773
1774 for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++) 1768 for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++)
1775 { 1769 {
1776 PathNode node = path.pathNodes[nodeIndex]; 1770 PathNode node = path.pathNodes[nodeIndex];
@@ -1784,7 +1778,7 @@ namespace PrimMesher
1784 { 1778 {
1785 newLayer.FlipNormals(); 1779 newLayer.FlipNormals();
1786 1780
1787 // add the top faces to the viewerFaces list here 1781 // add the bottom faces to the viewerFaces list
1788 if (this.viewerMode) 1782 if (this.viewerMode)
1789 { 1783 {
1790 Coord faceNormal = newLayer.faceNormal; 1784 Coord faceNormal = newLayer.faceNormal;
@@ -1811,6 +1805,13 @@ namespace PrimMesher
1811 newViewerFace.uv2 = newLayer.faceUVs[face.v2]; 1805 newViewerFace.uv2 = newLayer.faceUVs[face.v2];
1812 newViewerFace.uv3 = newLayer.faceUVs[face.v3]; 1806 newViewerFace.uv3 = newLayer.faceUVs[face.v3];
1813 1807
1808 if (pathType == PathType.Linear)
1809 {
1810 newViewerFace.uv1.Flip();
1811 newViewerFace.uv2.Flip();
1812 newViewerFace.uv3.Flip();
1813 }
1814
1814 this.viewerFaces.Add(newViewerFace); 1815 this.viewerFaces.Add(newViewerFace);
1815 } 1816 }
1816 } 1817 }
@@ -1835,7 +1836,10 @@ namespace PrimMesher
1835 // fill faces between layers 1836 // fill faces between layers
1836 1837
1837 int numVerts = newLayer.coords.Count; 1838 int numVerts = newLayer.coords.Count;
1838 Face newFace = new Face(); 1839 Face newFace1 = new Face();
1840 Face newFace2 = new Face();
1841
1842 thisV = 1.0f - node.percentOfPath;
1839 1843
1840 if (nodeIndex > 0) 1844 if (nodeIndex > 0)
1841 { 1845 {
@@ -1853,14 +1857,23 @@ namespace PrimMesher
1853 1857
1854 int whichVert = i - startVert; 1858 int whichVert = i - startVert;
1855 1859
1856 newFace.v1 = i; 1860 newFace1.v1 = i;
1857 newFace.v2 = i - numVerts; 1861 newFace1.v2 = i - numVerts;
1858 newFace.v3 = iNext - numVerts; 1862 newFace1.v3 = iNext;
1859 this.faces.Add(newFace); 1863
1864 newFace1.n1 = newFace1.v1;
1865 newFace1.n2 = newFace1.v2;
1866 newFace1.n3 = newFace1.v3;
1867 this.faces.Add(newFace1);
1860 1868
1861 newFace.v2 = iNext - numVerts; 1869 newFace2.v1 = iNext;
1862 newFace.v3 = iNext; 1870 newFace2.v2 = i - numVerts;
1863 this.faces.Add(newFace); 1871 newFace2.v3 = iNext - numVerts;
1872
1873 newFace2.n1 = newFace2.v1;
1874 newFace2.n2 = newFace2.v2;
1875 newFace2.n3 = newFace2.v3;
1876 this.faces.Add(newFace2);
1864 1877
1865 if (this.viewerMode) 1878 if (this.viewerMode)
1866 { 1879 {
@@ -1873,10 +1886,16 @@ namespace PrimMesher
1873 ViewerFace newViewerFace1 = new ViewerFace(primFaceNum); 1886 ViewerFace newViewerFace1 = new ViewerFace(primFaceNum);
1874 ViewerFace newViewerFace2 = new ViewerFace(primFaceNum); 1887 ViewerFace newViewerFace2 = new ViewerFace(primFaceNum);
1875 1888
1876 float u1 = newLayer.us[whichVert]; 1889 int uIndex = whichVert;
1890 if (!hasHollow && sides > 4 && uIndex < newLayer.us.Count - 1)
1891 {
1892 uIndex++;
1893 }
1894
1895 float u1 = newLayer.us[uIndex];
1877 float u2 = 1.0f; 1896 float u2 = 1.0f;
1878 if (whichVert < newLayer.us.Count - 1) 1897 if (uIndex < (int)newLayer.us.Count - 1)
1879 u2 = newLayer.us[whichVert + 1]; 1898 u2 = newLayer.us[uIndex + 1];
1880 1899
1881 if (whichVert == cut1Vert || whichVert == cut2Vert) 1900 if (whichVert == cut1Vert || whichVert == cut2Vert)
1882 { 1901 {
@@ -1894,13 +1913,22 @@ namespace PrimMesher
1894 u1 -= (int)u1; 1913 u1 -= (int)u1;
1895 if (u2 < 0.1f) 1914 if (u2 < 0.1f)
1896 u2 = 1.0f; 1915 u2 = 1.0f;
1897 //this.profileOuterFaceNumber = primFaceNum;
1898 } 1916 }
1899 else if (whichVert > profile.coords.Count - profile.numHollowVerts - 1) 1917 }
1918
1919 if (this.sphereMode)
1920 {
1921 if (whichVert != cut1Vert && whichVert != cut2Vert)
1900 { 1922 {
1901 u1 *= 2.0f; 1923 u1 = u1 * 2.0f - 1.0f;
1902 u2 *= 2.0f; 1924 u2 = u2 * 2.0f - 1.0f;
1903 //this.profileHollowFaceNumber = primFaceNum; 1925
1926 if (whichVert >= newLayer.numOuterVerts)
1927 {
1928 u1 -= hollow;
1929 u2 -= hollow;
1930 }
1931
1904 } 1932 }
1905 } 1933 }
1906 1934
@@ -1908,37 +1936,39 @@ namespace PrimMesher
1908 newViewerFace1.uv2.U = u1; 1936 newViewerFace1.uv2.U = u1;
1909 newViewerFace1.uv3.U = u2; 1937 newViewerFace1.uv3.U = u2;
1910 1938
1911 newViewerFace1.uv1.V = 1.0f - node.percentOfPath; 1939 newViewerFace1.uv1.V = thisV;
1912 newViewerFace1.uv2.V = lastV; 1940 newViewerFace1.uv2.V = lastV;
1913 newViewerFace1.uv3.V = lastV; 1941 newViewerFace1.uv3.V = thisV;
1914 1942
1915 newViewerFace2.uv1.U = u1; 1943 newViewerFace2.uv1.U = u2;
1916 newViewerFace2.uv2.U = u2; 1944 newViewerFace2.uv2.U = u1;
1917 newViewerFace2.uv3.U = u2; 1945 newViewerFace2.uv3.U = u2;
1918 1946
1919 newViewerFace2.uv1.V = 1.0f - node.percentOfPath; 1947 newViewerFace2.uv1.V = thisV;
1920 newViewerFace2.uv2.V = lastV; 1948 newViewerFace2.uv2.V = lastV;
1921 newViewerFace2.uv3.V = 1.0f - node.percentOfPath; 1949 newViewerFace2.uv3.V = lastV;
1922 1950
1923 newViewerFace1.v1 = this.coords[i]; 1951 newViewerFace1.v1 = this.coords[newFace1.v1];
1924 newViewerFace1.v2 = this.coords[i - numVerts]; 1952 newViewerFace1.v2 = this.coords[newFace1.v2];
1925 newViewerFace1.v3 = this.coords[iNext - numVerts]; 1953 newViewerFace1.v3 = this.coords[newFace1.v3];
1926 1954
1927 newViewerFace2.v1 = this.coords[i]; 1955 newViewerFace2.v1 = this.coords[newFace2.v1];
1928 newViewerFace2.v2 = this.coords[iNext - numVerts]; 1956 newViewerFace2.v2 = this.coords[newFace2.v2];
1929 newViewerFace2.v3 = this.coords[iNext]; 1957 newViewerFace2.v3 = this.coords[newFace2.v3];
1930 1958
1931 newViewerFace1.coordIndex1 = i; 1959 newViewerFace1.coordIndex1 = newFace1.v1;
1932 newViewerFace1.coordIndex2 = i - numVerts; 1960 newViewerFace1.coordIndex2 = newFace1.v2;
1933 newViewerFace1.coordIndex3 = iNext - numVerts; 1961 newViewerFace1.coordIndex3 = newFace1.v3;
1934 1962
1935 newViewerFace2.coordIndex1 = i; 1963 newViewerFace2.coordIndex1 = newFace2.v1;
1936 newViewerFace2.coordIndex2 = iNext - numVerts; 1964 newViewerFace2.coordIndex2 = newFace2.v2;
1937 newViewerFace2.coordIndex3 = iNext; 1965 newViewerFace2.coordIndex3 = newFace2.v3;
1938 1966
1939 // profile cut faces 1967 // profile cut faces
1940 if (whichVert == cut1Vert) 1968 if (whichVert == cut1Vert)
1941 { 1969 {
1970 newViewerFace1.primFaceNumber = cut1FaceNumber;
1971 newViewerFace2.primFaceNumber = cut1FaceNumber;
1942 newViewerFace1.n1 = newLayer.cutNormal1; 1972 newViewerFace1.n1 = newLayer.cutNormal1;
1943 newViewerFace1.n2 = newViewerFace1.n3 = lastCutNormal1; 1973 newViewerFace1.n2 = newViewerFace1.n3 = lastCutNormal1;
1944 1974
@@ -1947,10 +1977,14 @@ namespace PrimMesher
1947 } 1977 }
1948 else if (whichVert == cut2Vert) 1978 else if (whichVert == cut2Vert)
1949 { 1979 {
1980 newViewerFace1.primFaceNumber = cut2FaceNumber;
1981 newViewerFace2.primFaceNumber = cut2FaceNumber;
1950 newViewerFace1.n1 = newLayer.cutNormal2; 1982 newViewerFace1.n1 = newLayer.cutNormal2;
1951 newViewerFace1.n2 = newViewerFace1.n3 = lastCutNormal2; 1983 newViewerFace1.n2 = lastCutNormal2;
1984 newViewerFace1.n3 = lastCutNormal2;
1952 1985
1953 newViewerFace2.n1 = newViewerFace2.n3 = newLayer.cutNormal2; 1986 newViewerFace2.n1 = newLayer.cutNormal2;
1987 newViewerFace2.n3 = newLayer.cutNormal2;
1954 newViewerFace2.n2 = lastCutNormal2; 1988 newViewerFace2.n2 = lastCutNormal2;
1955 } 1989 }
1956 1990
@@ -1963,13 +1997,13 @@ namespace PrimMesher
1963 } 1997 }
1964 else 1998 else
1965 { 1999 {
1966 newViewerFace1.n1 = this.normals[i]; 2000 newViewerFace1.n1 = this.normals[newFace1.n1];
1967 newViewerFace1.n2 = this.normals[i - numVerts]; 2001 newViewerFace1.n2 = this.normals[newFace1.n2];
1968 newViewerFace1.n3 = this.normals[iNext - numVerts]; 2002 newViewerFace1.n3 = this.normals[newFace1.n3];
1969 2003
1970 newViewerFace2.n1 = this.normals[i]; 2004 newViewerFace2.n1 = this.normals[newFace2.n1];
1971 newViewerFace2.n2 = this.normals[iNext - numVerts]; 2005 newViewerFace2.n2 = this.normals[newFace2.n2];
1972 newViewerFace2.n3 = this.normals[iNext]; 2006 newViewerFace2.n3 = this.normals[newFace2.n3];
1973 } 2007 }
1974 } 2008 }
1975 2009
@@ -1982,14 +2016,13 @@ namespace PrimMesher
1982 2016
1983 lastCutNormal1 = newLayer.cutNormal1; 2017 lastCutNormal1 = newLayer.cutNormal1;
1984 lastCutNormal2 = newLayer.cutNormal2; 2018 lastCutNormal2 = newLayer.cutNormal2;
1985 lastV = 1.0f - node.percentOfPath; 2019 lastV = thisV;
1986 2020
1987 if (needEndFaces && nodeIndex == path.pathNodes.Count - 1 && viewerMode) 2021 if (needEndFaces && nodeIndex == path.pathNodes.Count - 1 && viewerMode)
1988 { 2022 {
1989 // add the top faces to the viewerFaces list here 2023 // add the top faces to the viewerFaces list here
1990 Coord faceNormal = newLayer.faceNormal; 2024 Coord faceNormal = newLayer.faceNormal;
1991 ViewerFace newViewerFace = new ViewerFace(); 2025 ViewerFace newViewerFace = new ViewerFace(0);
1992 newViewerFace.primFaceNumber = 0;
1993 int numFaces = newLayer.faces.Count; 2026 int numFaces = newLayer.faces.Count;
1994 List<Face> faces = newLayer.faces; 2027 List<Face> faces = newLayer.faces;
1995 2028
@@ -2012,6 +2045,13 @@ namespace PrimMesher
2012 newViewerFace.uv2 = newLayer.faceUVs[face.v2 - coordsLen]; 2045 newViewerFace.uv2 = newLayer.faceUVs[face.v2 - coordsLen];
2013 newViewerFace.uv3 = newLayer.faceUVs[face.v3 - coordsLen]; 2046 newViewerFace.uv3 = newLayer.faceUVs[face.v3 - coordsLen];
2014 2047
2048 if (pathType == PathType.Linear)
2049 {
2050 newViewerFace.uv1.Flip();
2051 newViewerFace.uv2.Flip();
2052 newViewerFace.uv3.Flip();
2053 }
2054
2015 this.viewerFaces.Add(newViewerFace); 2055 this.viewerFaces.Add(newViewerFace);
2016 } 2056 }
2017 } 2057 }
diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
index 8397eb4..f3b0630 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
@@ -1261,14 +1261,20 @@ namespace OpenSim.Region.Physics.OdePlugin
1261 { 1261 {
1262 m_requestedUpdateFrequency = ms; 1262 m_requestedUpdateFrequency = ms;
1263 m_eventsubscription = ms; 1263 m_eventsubscription = ms;
1264 CollisionEventsThisFrame.Clear(); 1264
1265 // Don't clear collision event reporting here. This is called directly from scene code and so can lead
1266 // to a race condition with the simulate loop
1267
1265 _parent_scene.AddCollisionEventReporting(this); 1268 _parent_scene.AddCollisionEventReporting(this);
1266 } 1269 }
1267 1270
1268 public override void UnSubscribeEvents() 1271 public override void UnSubscribeEvents()
1269 { 1272 {
1270 CollisionEventsThisFrame.Clear();
1271 _parent_scene.RemoveCollisionEventReporting(this); 1273 _parent_scene.RemoveCollisionEventReporting(this);
1274
1275 // Don't clear collision event reporting here. This is called directly from scene code and so can lead
1276 // to a race condition with the simulate loop
1277
1272 m_requestedUpdateFrequency = 0; 1278 m_requestedUpdateFrequency = 0;
1273 m_eventsubscription = 0; 1279 m_eventsubscription = 0;
1274 } 1280 }
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
index 6f37347..a41c856 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
@@ -156,7 +156,15 @@ namespace OpenSim.Region.Physics.OdePlugin
156 /// </summary> 156 /// </summary>
157 public IntPtr m_targetSpace = IntPtr.Zero; 157 public IntPtr m_targetSpace = IntPtr.Zero;
158 158
159 /// <summary>
160 /// The prim geometry, used for collision detection.
161 /// </summary>
162 /// <remarks>
163 /// This is never null except for a brief period when the geometry needs to be replaced (due to resizing or
164 /// mesh change) or when the physical prim is being removed from the scene.
165 /// </remarks>
159 public IntPtr prim_geom { get; private set; } 166 public IntPtr prim_geom { get; private set; }
167
160 public IntPtr _triMeshData { get; private set; } 168 public IntPtr _triMeshData { get; private set; }
161 169
162 private IntPtr _linkJointGroup = IntPtr.Zero; 170 private IntPtr _linkJointGroup = IntPtr.Zero;
@@ -325,14 +333,12 @@ namespace OpenSim.Region.Physics.OdePlugin
325 { 333 {
326 prim_geom = geom; 334 prim_geom = geom;
327//Console.WriteLine("SetGeom to " + prim_geom + " for " + Name); 335//Console.WriteLine("SetGeom to " + prim_geom + " for " + Name);
328 if (prim_geom != IntPtr.Zero)
329 {
330 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
331 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
332 336
333 _parent_scene.geom_name_map[prim_geom] = Name; 337 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
334 _parent_scene.actor_name_map[prim_geom] = this; 338 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
335 } 339
340 _parent_scene.geom_name_map[prim_geom] = Name;
341 _parent_scene.actor_name_map[prim_geom] = this;
336 342
337 if (childPrim) 343 if (childPrim)
338 { 344 {
@@ -765,11 +771,8 @@ namespace OpenSim.Region.Physics.OdePlugin
765 m_collisionCategories &= ~CollisionCategories.Body; 771 m_collisionCategories &= ~CollisionCategories.Body;
766 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land); 772 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
767 773
768 if (prim_geom != IntPtr.Zero) 774 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
769 { 775 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
770 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
771 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
772 }
773 776
774 d.BodyDestroy(Body); 777 d.BodyDestroy(Body);
775 lock (childrenPrim) 778 lock (childrenPrim)
@@ -793,11 +796,8 @@ namespace OpenSim.Region.Physics.OdePlugin
793 m_collisionCategories &= ~CollisionCategories.Body; 796 m_collisionCategories &= ~CollisionCategories.Body;
794 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land); 797 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
795 798
796 if (prim_geom != IntPtr.Zero) 799 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
797 { 800 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
798 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
799 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
800 }
801 801
802 Body = IntPtr.Zero; 802 Body = IntPtr.Zero;
803 } 803 }
@@ -864,10 +864,7 @@ namespace OpenSim.Region.Physics.OdePlugin
864// _parent_scene.waitForSpaceUnlock(m_targetSpace); 864// _parent_scene.waitForSpaceUnlock(m_targetSpace);
865 try 865 try
866 { 866 {
867 if (prim_geom == IntPtr.Zero) 867 SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null));
868 {
869 SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null));
870 }
871 } 868 }
872 catch (AccessViolationException) 869 catch (AccessViolationException)
873 { 870 {
@@ -890,73 +887,67 @@ namespace OpenSim.Region.Physics.OdePlugin
890#if SPAM 887#if SPAM
891Console.WriteLine("ZProcessTaints for " + Name); 888Console.WriteLine("ZProcessTaints for " + Name);
892#endif 889#endif
890
891 // This must be processed as the very first taint so that later operations have a prim_geom to work with
892 // if this is a new prim.
893 if (m_taintadd) 893 if (m_taintadd)
894 {
895 changeadd(); 894 changeadd();
896 }
897
898 if (prim_geom != IntPtr.Zero)
899 {
900 if (!_position.ApproxEquals(m_taintposition, 0f))
901 changemove();
902 895
903 if (m_taintrot != _orientation) 896 if (!_position.ApproxEquals(m_taintposition, 0f))
904 { 897 changemove();
905 if (childPrim && IsPhysical) // For physical child prim... 898
906 { 899 if (m_taintrot != _orientation)
907 rotate(); 900 {
908 // KF: ODE will also rotate the parent prim! 901 if (childPrim && IsPhysical) // For physical child prim...
909 // so rotate the root back to where it was 902 {
910 OdePrim parent = (OdePrim)_parent; 903 rotate();
911 parent.rotate(); 904 // KF: ODE will also rotate the parent prim!
912 } 905 // so rotate the root back to where it was
913 else 906 OdePrim parent = (OdePrim)_parent;
914 { 907 parent.rotate();
915 //Just rotate the prim
916 rotate();
917 }
918 } 908 }
919 909 else
920 if (m_taintPhysics != IsPhysical && !(m_taintparent != _parent)) 910 {
921 changePhysicsStatus(); 911 //Just rotate the prim
912 rotate();
913 }
914 }
915
916 if (m_taintPhysics != IsPhysical && !(m_taintparent != _parent))
917 changePhysicsStatus();
922 918
923 if (!_size.ApproxEquals(m_taintsize, 0f)) 919 if (!_size.ApproxEquals(m_taintsize, 0f))
924 changesize(); 920 changesize();
925 921
926 if (m_taintshape) 922 if (m_taintshape)
927 changeshape(); 923 changeshape();
928 924
929 if (m_taintforce) 925 if (m_taintforce)
930 changeAddForce(); 926 changeAddForce();
931 927
932 if (m_taintaddangularforce) 928 if (m_taintaddangularforce)
933 changeAddAngularForce(); 929 changeAddAngularForce();
934 930
935 if (!m_taintTorque.ApproxEquals(Vector3.Zero, 0.001f)) 931 if (!m_taintTorque.ApproxEquals(Vector3.Zero, 0.001f))
936 changeSetTorque(); 932 changeSetTorque();
937 933
938 if (m_taintdisable) 934 if (m_taintdisable)
939 changedisable(); 935 changedisable();
940 936
941 if (m_taintselected != m_isSelected) 937 if (m_taintselected != m_isSelected)
942 changeSelectedStatus(); 938 changeSelectedStatus();
943 939
944 if (!m_taintVelocity.ApproxEquals(Vector3.Zero, 0.001f)) 940 if (!m_taintVelocity.ApproxEquals(Vector3.Zero, 0.001f))
945 changevelocity(); 941 changevelocity();
946 942
947 if (m_taintparent != _parent) 943 if (m_taintparent != _parent)
948 changelink(); 944 changelink();
949 945
950 if (m_taintCollidesWater != m_collidesWater) 946 if (m_taintCollidesWater != m_collidesWater)
951 changefloatonwater(); 947 changefloatonwater();
952 948
953 if (!m_angularlock.ApproxEquals(m_taintAngularLock,0f)) 949 if (!m_angularlock.ApproxEquals(m_taintAngularLock,0f))
954 changeAngularLock(); 950 changeAngularLock();
955 }
956 else
957 {
958 m_log.ErrorFormat("[PHYSICS]: The scene reused a disposed PhysActor for {0}! *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.)", Name);
959 }
960 } 951 }
961 952
962 /// <summary> 953 /// <summary>
@@ -1052,150 +1043,146 @@ Console.WriteLine("ZProcessTaints for " + Name);
1052 /// <param name="prim">Child prim</param> 1043 /// <param name="prim">Child prim</param>
1053 private void AddChildPrim(OdePrim prim) 1044 private void AddChildPrim(OdePrim prim)
1054 { 1045 {
1055//Console.WriteLine("AddChildPrim " + Name); 1046 if (LocalID == prim.LocalID)
1056 if (LocalID != prim.LocalID) 1047 return;
1048
1049 if (Body == IntPtr.Zero)
1057 { 1050 {
1058 if (Body == IntPtr.Zero) 1051 Body = d.BodyCreate(_parent_scene.world);
1052 setMass();
1053 }
1054
1055 lock (childrenPrim)
1056 {
1057 if (childrenPrim.Contains(prim))
1058 return;
1059
1060// m_log.DebugFormat(
1061// "[ODE PRIM]: Linking prim {0} {1} to {2} {3}", prim.Name, prim.LocalID, Name, LocalID);
1062
1063 childrenPrim.Add(prim);
1064
1065 foreach (OdePrim prm in childrenPrim)
1059 { 1066 {
1060 Body = d.BodyCreate(_parent_scene.world); 1067 d.Mass m2;
1061 setMass(); 1068 d.MassSetZero(out m2);
1069 d.MassSetBoxTotal(out m2, prim.CalculateMass(), prm._size.X, prm._size.Y, prm._size.Z);
1070
1071 d.Quaternion quat = new d.Quaternion();
1072 quat.W = prm._orientation.W;
1073 quat.X = prm._orientation.X;
1074 quat.Y = prm._orientation.Y;
1075 quat.Z = prm._orientation.Z;
1076
1077 d.Matrix3 mat = new d.Matrix3();
1078 d.RfromQ(out mat, ref quat);
1079 d.MassRotate(ref m2, ref mat);
1080 d.MassTranslate(ref m2, Position.X - prm.Position.X, Position.Y - prm.Position.Y, Position.Z - prm.Position.Z);
1081 d.MassAdd(ref pMass, ref m2);
1062 } 1082 }
1063 if (Body != IntPtr.Zero) 1083
1084 foreach (OdePrim prm in childrenPrim)
1064 { 1085 {
1065 lock (childrenPrim) 1086 prm.m_collisionCategories |= CollisionCategories.Body;
1066 { 1087 prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1067 if (!childrenPrim.Contains(prim))
1068 {
1069//Console.WriteLine("childrenPrim.Add " + prim);
1070 childrenPrim.Add(prim);
1071
1072 foreach (OdePrim prm in childrenPrim)
1073 {
1074 d.Mass m2;
1075 d.MassSetZero(out m2);
1076 d.MassSetBoxTotal(out m2, prim.CalculateMass(), prm._size.X, prm._size.Y, prm._size.Z);
1077
1078 d.Quaternion quat = new d.Quaternion();
1079 quat.W = prm._orientation.W;
1080 quat.X = prm._orientation.X;
1081 quat.Y = prm._orientation.Y;
1082 quat.Z = prm._orientation.Z;
1083
1084 d.Matrix3 mat = new d.Matrix3();
1085 d.RfromQ(out mat, ref quat);
1086 d.MassRotate(ref m2, ref mat);
1087 d.MassTranslate(ref m2, Position.X - prm.Position.X, Position.Y - prm.Position.Y, Position.Z - prm.Position.Z);
1088 d.MassAdd(ref pMass, ref m2);
1089 }
1090
1091 foreach (OdePrim prm in childrenPrim)
1092 {
1093 prm.m_collisionCategories |= CollisionCategories.Body;
1094 prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1095 1088
1096 if (prm.prim_geom == IntPtr.Zero)
1097 {
1098 m_log.WarnFormat(
1099 "[PHYSICS]: Unable to link one of the linkset elements {0} for parent {1}. No geom yet",
1100 prm.Name, prim.Name);
1101 continue;
1102 }
1103//Console.WriteLine(" GeomSetCategoryBits 1: " + prm.prim_geom + " - " + (int)prm.m_collisionCategories + " for " + Name); 1089//Console.WriteLine(" GeomSetCategoryBits 1: " + prm.prim_geom + " - " + (int)prm.m_collisionCategories + " for " + Name);
1104 d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories); 1090 d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories);
1105 d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags); 1091 d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags);
1106
1107 1092
1108 d.Quaternion quat = new d.Quaternion(); 1093 d.Quaternion quat = new d.Quaternion();
1109 quat.W = prm._orientation.W; 1094 quat.W = prm._orientation.W;
1110 quat.X = prm._orientation.X; 1095 quat.X = prm._orientation.X;
1111 quat.Y = prm._orientation.Y; 1096 quat.Y = prm._orientation.Y;
1112 quat.Z = prm._orientation.Z; 1097 quat.Z = prm._orientation.Z;
1113 1098
1114 d.Matrix3 mat = new d.Matrix3(); 1099 d.Matrix3 mat = new d.Matrix3();
1115 d.RfromQ(out mat, ref quat); 1100 d.RfromQ(out mat, ref quat);
1116 if (Body != IntPtr.Zero) 1101 if (Body != IntPtr.Zero)
1117 { 1102 {
1118 d.GeomSetBody(prm.prim_geom, Body); 1103 d.GeomSetBody(prm.prim_geom, Body);
1119 prm.childPrim = true; 1104 prm.childPrim = true;
1120 d.GeomSetOffsetWorldPosition(prm.prim_geom, prm.Position.X , prm.Position.Y, prm.Position.Z); 1105 d.GeomSetOffsetWorldPosition(prm.prim_geom, prm.Position.X , prm.Position.Y, prm.Position.Z);
1121 //d.GeomSetOffsetPosition(prim.prim_geom, 1106 //d.GeomSetOffsetPosition(prim.prim_geom,
1122 // (Position.X - prm.Position.X) - pMass.c.X, 1107 // (Position.X - prm.Position.X) - pMass.c.X,
1123 // (Position.Y - prm.Position.Y) - pMass.c.Y, 1108 // (Position.Y - prm.Position.Y) - pMass.c.Y,
1124 // (Position.Z - prm.Position.Z) - pMass.c.Z); 1109 // (Position.Z - prm.Position.Z) - pMass.c.Z);
1125 d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat); 1110 d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat);
1126 //d.GeomSetOffsetRotation(prm.prim_geom, ref mat); 1111 //d.GeomSetOffsetRotation(prm.prim_geom, ref mat);
1127 d.MassTranslate(ref pMass, -pMass.c.X, -pMass.c.Y, -pMass.c.Z); 1112 d.MassTranslate(ref pMass, -pMass.c.X, -pMass.c.Y, -pMass.c.Z);
1128 d.BodySetMass(Body, ref pMass); 1113 d.BodySetMass(Body, ref pMass);
1129 } 1114 }
1130 else 1115 else
1131 { 1116 {
1132 m_log.DebugFormat("[PHYSICS]: {0} ain't got no boooooooooddy, no body", Name); 1117 m_log.DebugFormat("[PHYSICS]: {0} ain't got no boooooooooddy, no body", Name);
1133 } 1118 }
1134 1119
1135 prm.m_interpenetrationcount = 0; 1120 prm.m_interpenetrationcount = 0;
1136 prm.m_collisionscore = 0; 1121 prm.m_collisionscore = 0;
1137 prm.m_disabled = false; 1122 prm.m_disabled = false;
1138 1123
1139 // The body doesn't already have a finite rotation mode set here 1124 // The body doesn't already have a finite rotation mode set here
1140 if ((!m_angularlock.ApproxEquals(Vector3.Zero, 0f)) && _parent == null) 1125 if ((!m_angularlock.ApproxEquals(Vector3.Zero, 0f)) && _parent == null)
1141 { 1126 {
1142 prm.createAMotor(m_angularlock); 1127 prm.createAMotor(m_angularlock);
1143 } 1128 }
1144 prm.Body = Body; 1129 prm.Body = Body;
1145 _parent_scene.ActivatePrim(prm); 1130 _parent_scene.ActivatePrim(prm);
1146 } 1131 }
1147 1132
1148 m_collisionCategories |= CollisionCategories.Body; 1133 m_collisionCategories |= CollisionCategories.Body;
1149 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); 1134 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1150 1135
1151//Console.WriteLine("GeomSetCategoryBits 2: " + prim_geom + " - " + (int)m_collisionCategories + " for " + Name); 1136//Console.WriteLine("GeomSetCategoryBits 2: " + prim_geom + " - " + (int)m_collisionCategories + " for " + Name);
1152 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); 1137 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1153//Console.WriteLine(" Post GeomSetCategoryBits 2"); 1138//Console.WriteLine(" Post GeomSetCategoryBits 2");
1154 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 1139 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1155
1156 d.Quaternion quat2 = new d.Quaternion();
1157 quat2.W = _orientation.W;
1158 quat2.X = _orientation.X;
1159 quat2.Y = _orientation.Y;
1160 quat2.Z = _orientation.Z;
1161
1162 d.Matrix3 mat2 = new d.Matrix3();
1163 d.RfromQ(out mat2, ref quat2);
1164 d.GeomSetBody(prim_geom, Body);
1165 d.GeomSetOffsetWorldPosition(prim_geom, Position.X - pMass.c.X, Position.Y - pMass.c.Y, Position.Z - pMass.c.Z);
1166 //d.GeomSetOffsetPosition(prim.prim_geom,
1167 // (Position.X - prm.Position.X) - pMass.c.X,
1168 // (Position.Y - prm.Position.Y) - pMass.c.Y,
1169 // (Position.Z - prm.Position.Z) - pMass.c.Z);
1170 //d.GeomSetOffsetRotation(prim_geom, ref mat2);
1171 d.MassTranslate(ref pMass, -pMass.c.X, -pMass.c.Y, -pMass.c.Z);
1172 d.BodySetMass(Body, ref pMass);
1173
1174 d.BodySetAutoDisableFlag(Body, true);
1175 d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
1176 1140
1177 m_interpenetrationcount = 0; 1141 d.Quaternion quat2 = new d.Quaternion();
1178 m_collisionscore = 0; 1142 quat2.W = _orientation.W;
1179 m_disabled = false; 1143 quat2.X = _orientation.X;
1144 quat2.Y = _orientation.Y;
1145 quat2.Z = _orientation.Z;
1180 1146
1181 // The body doesn't already have a finite rotation mode set here 1147 d.Matrix3 mat2 = new d.Matrix3();
1182 if ((!m_angularlock.ApproxEquals(Vector3.Zero, 0f)) && _parent == null) 1148 d.RfromQ(out mat2, ref quat2);
1183 { 1149 d.GeomSetBody(prim_geom, Body);
1184 createAMotor(m_angularlock); 1150 d.GeomSetOffsetWorldPosition(prim_geom, Position.X - pMass.c.X, Position.Y - pMass.c.Y, Position.Z - pMass.c.Z);
1185 } 1151 //d.GeomSetOffsetPosition(prim.prim_geom,
1186 d.BodySetPosition(Body, Position.X, Position.Y, Position.Z); 1152 // (Position.X - prm.Position.X) - pMass.c.X,
1187 if (m_vehicle.Type != Vehicle.TYPE_NONE) 1153 // (Position.Y - prm.Position.Y) - pMass.c.Y,
1188 m_vehicle.Enable(Body, _parent_scene); 1154 // (Position.Z - prm.Position.Z) - pMass.c.Z);
1155 //d.GeomSetOffsetRotation(prim_geom, ref mat2);
1156 d.MassTranslate(ref pMass, -pMass.c.X, -pMass.c.Y, -pMass.c.Z);
1157 d.BodySetMass(Body, ref pMass);
1189 1158
1190 _parent_scene.ActivatePrim(this); 1159 d.BodySetAutoDisableFlag(Body, true);
1191 } 1160 d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
1192 } 1161
1162 m_interpenetrationcount = 0;
1163 m_collisionscore = 0;
1164 m_disabled = false;
1165
1166 // The body doesn't already have a finite rotation mode set here
1167 if ((!m_angularlock.ApproxEquals(Vector3.Zero, 0f)) && _parent == null)
1168 {
1169 createAMotor(m_angularlock);
1193 } 1170 }
1171
1172 d.BodySetPosition(Body, Position.X, Position.Y, Position.Z);
1173
1174 if (m_vehicle.Type != Vehicle.TYPE_NONE)
1175 m_vehicle.Enable(Body, _parent_scene);
1176
1177 _parent_scene.ActivatePrim(this);
1194 } 1178 }
1195 } 1179 }
1196 1180
1197 private void ChildSetGeom(OdePrim odePrim) 1181 private void ChildSetGeom(OdePrim odePrim)
1198 { 1182 {
1183// m_log.DebugFormat(
1184// "[ODE PRIM]: ChildSetGeom {0} {1} for {2} {3}", odePrim.Name, odePrim.LocalID, Name, LocalID);
1185
1199 //if (IsPhysical && Body != IntPtr.Zero) 1186 //if (IsPhysical && Body != IntPtr.Zero)
1200 lock (childrenPrim) 1187 lock (childrenPrim)
1201 { 1188 {
@@ -1210,12 +1197,14 @@ Console.WriteLine("ZProcessTaints for " + Name);
1210 //prm.childPrim = false; 1197 //prm.childPrim = false;
1211 } 1198 }
1212 } 1199 }
1200
1213 disableBody(); 1201 disableBody();
1214 1202
1215 if (Body != IntPtr.Zero) 1203 // Spurious - Body == IntPtr.Zero after disableBody()
1216 { 1204// if (Body != IntPtr.Zero)
1217 _parent_scene.DeactivatePrim(this); 1205// {
1218 } 1206// _parent_scene.DeactivatePrim(this);
1207// }
1219 1208
1220 lock (childrenPrim) 1209 lock (childrenPrim)
1221 { 1210 {
@@ -1229,6 +1218,9 @@ Console.WriteLine("ZProcessTaints for " + Name);
1229 1218
1230 private void ChildDelink(OdePrim odePrim) 1219 private void ChildDelink(OdePrim odePrim)
1231 { 1220 {
1221// m_log.DebugFormat(
1222// "[ODE PRIM]: Delinking prim {0} {1} from {2} {3}", odePrim.Name, odePrim.LocalID, Name, LocalID);
1223
1232 // Okay, we have a delinked child.. need to rebuild the body. 1224 // Okay, we have a delinked child.. need to rebuild the body.
1233 lock (childrenPrim) 1225 lock (childrenPrim)
1234 { 1226 {
@@ -1243,6 +1235,7 @@ Console.WriteLine("ZProcessTaints for " + Name);
1243 //prm.childPrim = false; 1235 //prm.childPrim = false;
1244 } 1236 }
1245 } 1237 }
1238
1246 disableBody(); 1239 disableBody();
1247 1240
1248 lock (childrenPrim) 1241 lock (childrenPrim)
@@ -1251,10 +1244,11 @@ Console.WriteLine("ZProcessTaints for " + Name);
1251 childrenPrim.Remove(odePrim); 1244 childrenPrim.Remove(odePrim);
1252 } 1245 }
1253 1246
1254 if (Body != IntPtr.Zero) 1247 // Spurious - Body == IntPtr.Zero after disableBody()
1255 { 1248// if (Body != IntPtr.Zero)
1256 _parent_scene.DeactivatePrim(this); 1249// {
1257 } 1250// _parent_scene.DeactivatePrim(this);
1251// }
1258 1252
1259 lock (childrenPrim) 1253 lock (childrenPrim)
1260 { 1254 {
@@ -1303,11 +1297,8 @@ Console.WriteLine("ZProcessTaints for " + Name);
1303 disableBodySoft(); 1297 disableBodySoft();
1304 } 1298 }
1305 1299
1306 if (prim_geom != IntPtr.Zero) 1300 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1307 { 1301 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1308 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1309 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1310 }
1311 1302
1312 if (IsPhysical) 1303 if (IsPhysical)
1313 { 1304 {
@@ -1328,11 +1319,8 @@ Console.WriteLine("ZProcessTaints for " + Name);
1328 if (m_collidesWater) 1319 if (m_collidesWater)
1329 m_collisionFlags |= CollisionCategories.Water; 1320 m_collisionFlags |= CollisionCategories.Water;
1330 1321
1331 if (prim_geom != IntPtr.Zero) 1322 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1332 { 1323 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1333 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1334 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1335 }
1336 1324
1337 if (IsPhysical) 1325 if (IsPhysical)
1338 { 1326 {
@@ -1472,6 +1460,9 @@ Console.WriteLine("CreateGeom:");
1472 } 1460 }
1473 else 1461 else
1474 { 1462 {
1463 m_log.WarnFormat(
1464 "[ODE PRIM]: Called RemoveGeom() on {0} {1} where geometry was already null.", Name, LocalID);
1465
1475 return false; 1466 return false;
1476 } 1467 }
1477 } 1468 }
@@ -1505,16 +1496,13 @@ Console.WriteLine("changeadd 1");
1505#endif 1496#endif
1506 CreateGeom(m_targetSpace, mesh); 1497 CreateGeom(m_targetSpace, mesh);
1507 1498
1508 if (prim_geom != IntPtr.Zero) 1499 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1509 { 1500 d.Quaternion myrot = new d.Quaternion();
1510 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); 1501 myrot.X = _orientation.X;
1511 d.Quaternion myrot = new d.Quaternion(); 1502 myrot.Y = _orientation.Y;
1512 myrot.X = _orientation.X; 1503 myrot.Z = _orientation.Z;
1513 myrot.Y = _orientation.Y; 1504 myrot.W = _orientation.W;
1514 myrot.Z = _orientation.Z; 1505 d.GeomSetQuaternion(prim_geom, ref myrot);
1515 myrot.W = _orientation.W;
1516 d.GeomSetQuaternion(prim_geom, ref myrot);
1517 }
1518 1506
1519 if (IsPhysical && Body == IntPtr.Zero) 1507 if (IsPhysical && Body == IntPtr.Zero)
1520 enableBody(); 1508 enableBody();
@@ -1579,24 +1567,20 @@ Console.WriteLine(" JointCreateFixed");
1579 //m_log.Debug("[BUG]: race!"); 1567 //m_log.Debug("[BUG]: race!");
1580 //} 1568 //}
1581 } 1569 }
1582 else
1583 {
1584 // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
1585 // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
1586// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1587 1570
1588 IntPtr tempspace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position, m_targetSpace); 1571 // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
1589 m_targetSpace = tempspace; 1572 // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
1573// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1574
1575 IntPtr tempspace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position, m_targetSpace);
1576 m_targetSpace = tempspace;
1590 1577
1591// _parent_scene.waitForSpaceUnlock(m_targetSpace); 1578// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1592 if (prim_geom != IntPtr.Zero) 1579
1593 { 1580 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1594 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1595 1581
1596// _parent_scene.waitForSpaceUnlock(m_targetSpace); 1582// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1597 d.SpaceAdd(m_targetSpace, prim_geom); 1583 d.SpaceAdd(m_targetSpace, prim_geom);
1598 }
1599 }
1600 1584
1601 changeSelectedStatus(); 1585 changeSelectedStatus();
1602 1586
@@ -2047,18 +2031,16 @@ Console.WriteLine(" JointCreateFixed");
2047 { 2031 {
2048 m_collidesWater = m_taintCollidesWater; 2032 m_collidesWater = m_taintCollidesWater;
2049 2033
2050 if (prim_geom != IntPtr.Zero) 2034 if (m_collidesWater)
2051 { 2035 {
2052 if (m_collidesWater) 2036 m_collisionFlags |= CollisionCategories.Water;
2053 {
2054 m_collisionFlags |= CollisionCategories.Water;
2055 }
2056 else
2057 {
2058 m_collisionFlags &= ~CollisionCategories.Water;
2059 }
2060 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
2061 } 2037 }
2038 else
2039 {
2040 m_collisionFlags &= ~CollisionCategories.Water;
2041 }
2042
2043 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
2062 } 2044 }
2063 2045
2064 /// <summary> 2046 /// <summary>
diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
index 842ff91..32e81e2 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
@@ -30,20 +30,21 @@
30 30
31using System; 31using System;
32using System.Collections.Generic; 32using System.Collections.Generic;
33using System.Diagnostics;
34using System.IO;
35using System.Linq;
33using System.Reflection; 36using System.Reflection;
34using System.Runtime.InteropServices; 37using System.Runtime.InteropServices;
35using System.Threading; 38using System.Threading;
36using System.IO;
37using System.Diagnostics;
38using log4net; 39using log4net;
39using Nini.Config; 40using Nini.Config;
40using Ode.NET; 41using Ode.NET;
42using OpenMetaverse;
41#if USE_DRAWSTUFF 43#if USE_DRAWSTUFF
42using Drawstuff.NET; 44using Drawstuff.NET;
43#endif 45#endif
44using OpenSim.Framework; 46using OpenSim.Framework;
45using OpenSim.Region.Physics.Manager; 47using OpenSim.Region.Physics.Manager;
46using OpenMetaverse;
47 48
48namespace OpenSim.Region.Physics.OdePlugin 49namespace OpenSim.Region.Physics.OdePlugin
49{ 50{
@@ -54,15 +55,15 @@ namespace OpenSim.Region.Physics.OdePlugin
54 End = 2 55 End = 2
55 } 56 }
56 57
57 public struct sCollisionData 58// public struct sCollisionData
58 { 59// {
59 public uint ColliderLocalId; 60// public uint ColliderLocalId;
60 public uint CollidedWithLocalId; 61// public uint CollidedWithLocalId;
61 public int NumberOfCollisions; 62// public int NumberOfCollisions;
62 public int CollisionType; 63// public int CollisionType;
63 public int StatusIndicator; 64// public int StatusIndicator;
64 public int lastframe; 65// public int lastframe;
65 } 66// }
66 67
67 [Flags] 68 [Flags]
68 public enum CollisionCategories : int 69 public enum CollisionCategories : int
@@ -131,6 +132,135 @@ namespace OpenSim.Region.Physics.OdePlugin
131 /// </remarks> 132 /// </remarks>
132 internal static Object UniversalColliderSyncObject = new Object(); 133 internal static Object UniversalColliderSyncObject = new Object();
133 134
135 /// <summary>
136 /// Is stats collecting enabled for this ODE scene?
137 /// </summary>
138 public bool CollectStats { get; set; }
139
140 /// <summary>
141 /// Statistics for this scene.
142 /// </summary>
143 private Dictionary<string, float> m_stats = new Dictionary<string, float>();
144
145 /// <summary>
146 /// Stat name for total number of avatars in this ODE scene.
147 /// </summary>
148 public const string ODETotalAvatarsStatName = "ODETotalAvatars";
149
150 /// <summary>
151 /// Stat name for total number of prims in this ODE scene.
152 /// </summary>
153 public const string ODETotalPrimsStatName = "ODETotalPrims";
154
155 /// <summary>
156 /// Stat name for total number of prims with active physics in this ODE scene.
157 /// </summary>
158 public const string ODEActivePrimsStatName = "ODEActivePrims";
159
160 /// <summary>
161 /// Stat name for the total time spent in ODE frame processing.
162 /// </summary>
163 /// <remarks>
164 /// A sanity check for the main scene loop physics time.
165 /// </remarks>
166 public const string ODETotalFrameMsStatName = "ODETotalFrameMS";
167
168 /// <summary>
169 /// Stat name for time spent processing avatar taints per frame
170 /// </summary>
171 public const string ODEAvatarTaintMsStatName = "ODEAvatarTaintFrameMS";
172
173 /// <summary>
174 /// Stat name for time spent processing prim taints per frame
175 /// </summary>
176 public const string ODEPrimTaintMsStatName = "ODEPrimTaintFrameMS";
177
178 /// <summary>
179 /// Stat name for time spent calculating avatar forces per frame.
180 /// </summary>
181 public const string ODEAvatarForcesFrameMsStatName = "ODEAvatarForcesFrameMS";
182
183 /// <summary>
184 /// Stat name for time spent calculating prim forces per frame
185 /// </summary>
186 public const string ODEPrimForcesFrameMsStatName = "ODEPrimForcesFrameMS";
187
188 /// <summary>
189 /// Stat name for time spent fulfilling raycasting requests per frame
190 /// </summary>
191 public const string ODERaycastingFrameMsStatName = "ODERaycastingFrameMS";
192
193 /// <summary>
194 /// Stat name for time spent in native code that actually steps through the simulation.
195 /// </summary>
196 public const string ODENativeStepFrameMsStatName = "ODENativeStepFrameMS";
197
198 /// <summary>
199 /// Stat name for the number of milliseconds that ODE spends in native space collision code.
200 /// </summary>
201 public const string ODENativeSpaceCollisionFrameMsStatName = "ODENativeSpaceCollisionFrameMS";
202
203 /// <summary>
204 /// Stat name for milliseconds that ODE spends in native geom collision code.
205 /// </summary>
206 public const string ODENativeGeomCollisionFrameMsStatName = "ODENativeGeomCollisionFrameMS";
207
208 /// <summary>
209 /// Time spent in collision processing that is not spent in native space or geom collision code.
210 /// </summary>
211 public const string ODEOtherCollisionFrameMsStatName = "ODEOtherCollisionFrameMS";
212
213 /// <summary>
214 /// Stat name for time spent notifying listeners of collisions
215 /// </summary>
216 public const string ODECollisionNotificationFrameMsStatName = "ODECollisionNotificationFrameMS";
217
218 /// <summary>
219 /// Stat name for milliseconds spent updating avatar position and velocity
220 /// </summary>
221 public const string ODEAvatarUpdateFrameMsStatName = "ODEAvatarUpdateFrameMS";
222
223 /// <summary>
224 /// Stat name for the milliseconds spent updating prim position and velocity
225 /// </summary>
226 public const string ODEPrimUpdateFrameMsStatName = "ODEPrimUpdateFrameMS";
227
228 /// <summary>
229 /// Stat name for avatar collisions with another entity.
230 /// </summary>
231 public const string ODEAvatarContactsStatsName = "ODEAvatarContacts";
232
233 /// <summary>
234 /// Stat name for prim collisions with another entity.
235 /// </summary>
236 public const string ODEPrimContactsStatName = "ODEPrimContacts";
237
238 /// <summary>
239 /// Used to hold tick numbers for stat collection purposes.
240 /// </summary>
241 private int m_nativeCollisionStartTick;
242
243 /// <summary>
244 /// A messy way to tell if we need to avoid adding a collision time because this was already done in the callback.
245 /// </summary>
246 private bool m_inCollisionTiming;
247
248 /// <summary>
249 /// A temporary holder for the number of avatar collisions in a frame, so we can work out how many object
250 /// collisions occured using the _perloopcontact if stats collection is enabled.
251 /// </summary>
252 private int m_tempAvatarCollisionsThisFrame;
253
254 /// <summary>
255 /// Used in calculating physics frame time dilation
256 /// </summary>
257 private int tickCountFrameRun;
258
259 /// <summary>
260 /// Used in calculating physics frame time dilation
261 /// </summary>
262 private int latertickcount;
263
134 private Random fluidRandomizer = new Random(Environment.TickCount); 264 private Random fluidRandomizer = new Random(Environment.TickCount);
135 265
136 private const uint m_regionWidth = Constants.RegionSize; 266 private const uint m_regionWidth = Constants.RegionSize;
@@ -257,12 +387,12 @@ namespace OpenSim.Region.Physics.OdePlugin
257 /// <summary> 387 /// <summary>
258 /// A dictionary of actors that should receive collision events. 388 /// A dictionary of actors that should receive collision events.
259 /// </summary> 389 /// </summary>
260 private readonly Dictionary<uint, PhysicsActor> _collisionEventPrim = new Dictionary<uint, PhysicsActor>(); 390 private readonly Dictionary<uint, PhysicsActor> m_collisionEventActors = new Dictionary<uint, PhysicsActor>();
261 391
262 /// <summary> 392 /// <summary>
263 /// A dictionary of collision event changes that are waiting to be processed. 393 /// A dictionary of collision event changes that are waiting to be processed.
264 /// </summary> 394 /// </summary>
265 private readonly Dictionary<uint, PhysicsActor> _collisionEventPrimChanges = new Dictionary<uint, PhysicsActor>(); 395 private readonly Dictionary<uint, PhysicsActor> m_collisionEventActorsChanges = new Dictionary<uint, PhysicsActor>();
266 396
267 /// <summary> 397 /// <summary>
268 /// Maps a unique geometry id (a memory location) to a physics actor name. 398 /// Maps a unique geometry id (a memory location) to a physics actor name.
@@ -345,9 +475,6 @@ namespace OpenSim.Region.Physics.OdePlugin
345 private OdePrim cp1; 475 private OdePrim cp1;
346 private OdeCharacter cc2; 476 private OdeCharacter cc2;
347 private OdePrim cp2; 477 private OdePrim cp2;
348 private int tickCountFrameRun;
349
350 private int latertickcount=0;
351 //private int cStartStop = 0; 478 //private int cStartStop = 0;
352 //private string cDictKey = ""; 479 //private string cDictKey = "";
353 480
@@ -440,6 +567,8 @@ namespace OpenSim.Region.Physics.OdePlugin
440 // Initialize the mesh plugin 567 // Initialize the mesh plugin
441 public override void Initialise(IMesher meshmerizer, IConfigSource config) 568 public override void Initialise(IMesher meshmerizer, IConfigSource config)
442 { 569 {
570 InitializeExtraStats();
571
443 mesher = meshmerizer; 572 mesher = meshmerizer;
444 m_config = config; 573 m_config = config;
445 // Defaults 574 // Defaults
@@ -464,6 +593,8 @@ namespace OpenSim.Region.Physics.OdePlugin
464 IConfig physicsconfig = m_config.Configs["ODEPhysicsSettings"]; 593 IConfig physicsconfig = m_config.Configs["ODEPhysicsSettings"];
465 if (physicsconfig != null) 594 if (physicsconfig != null)
466 { 595 {
596 CollectStats = physicsconfig.GetBoolean("collect_stats", false);
597
467 gravityx = physicsconfig.GetFloat("world_gravityx", 0f); 598 gravityx = physicsconfig.GetFloat("world_gravityx", 0f);
468 gravityy = physicsconfig.GetFloat("world_gravityy", 0f); 599 gravityy = physicsconfig.GetFloat("world_gravityy", 0f);
469 gravityz = physicsconfig.GetFloat("world_gravityz", -9.8f); 600 gravityz = physicsconfig.GetFloat("world_gravityz", -9.8f);
@@ -765,6 +896,62 @@ namespace OpenSim.Region.Physics.OdePlugin
765 #region Collision Detection 896 #region Collision Detection
766 897
767 /// <summary> 898 /// <summary>
899 /// Collides two geometries.
900 /// </summary>
901 /// <returns></returns>
902 /// <param name='geom1'></param>
903 /// <param name='geom2'>/param>
904 /// <param name='maxContacts'></param>
905 /// <param name='contactsArray'></param>
906 /// <param name='contactGeomSize'></param>
907 private int CollideGeoms(
908 IntPtr geom1, IntPtr geom2, int maxContacts, Ode.NET.d.ContactGeom[] contactsArray, int contactGeomSize)
909 {
910 int count;
911
912 lock (OdeScene.UniversalColliderSyncObject)
913 {
914 // We do this inside the lock so that we don't count any delay in acquiring it
915 if (CollectStats)
916 m_nativeCollisionStartTick = Util.EnvironmentTickCount();
917
918 count = d.Collide(geom1, geom2, maxContacts, contactsArray, contactGeomSize);
919 }
920
921 // We do this outside the lock so that any waiting threads aren't held up, though the effect is probably
922 // negligable
923 if (CollectStats)
924 m_stats[ODENativeGeomCollisionFrameMsStatName]
925 += Util.EnvironmentTickCountSubtract(m_nativeCollisionStartTick);
926
927 return count;
928 }
929
930 /// <summary>
931 /// Collide two spaces or a space and a geometry.
932 /// </summary>
933 /// <param name='space1'></param>
934 /// <param name='space2'>/param>
935 /// <param name='data'></param>
936 private void CollideSpaces(IntPtr space1, IntPtr space2, IntPtr data)
937 {
938 if (CollectStats)
939 {
940 m_inCollisionTiming = true;
941 m_nativeCollisionStartTick = Util.EnvironmentTickCount();
942 }
943
944 d.SpaceCollide2(space1, space2, data, nearCallback);
945
946 if (CollectStats && m_inCollisionTiming)
947 {
948 m_stats[ODENativeSpaceCollisionFrameMsStatName]
949 += Util.EnvironmentTickCountSubtract(m_nativeCollisionStartTick);
950 m_inCollisionTiming = false;
951 }
952 }
953
954 /// <summary>
768 /// This is our near callback. A geometry is near a body 955 /// This is our near callback. A geometry is near a body
769 /// </summary> 956 /// </summary>
770 /// <param name="space">The space that contains the geoms. Remember, spaces are also geoms</param> 957 /// <param name="space">The space that contains the geoms. Remember, spaces are also geoms</param>
@@ -772,6 +959,13 @@ namespace OpenSim.Region.Physics.OdePlugin
772 /// <param name="g2">another geometry or space</param> 959 /// <param name="g2">another geometry or space</param>
773 private void near(IntPtr space, IntPtr g1, IntPtr g2) 960 private void near(IntPtr space, IntPtr g1, IntPtr g2)
774 { 961 {
962 if (CollectStats && m_inCollisionTiming)
963 {
964 m_stats[ODENativeSpaceCollisionFrameMsStatName]
965 += Util.EnvironmentTickCountSubtract(m_nativeCollisionStartTick);
966 m_inCollisionTiming = false;
967 }
968
775// m_log.DebugFormat("[PHYSICS]: Colliding {0} and {1} in {2}", g1, g2, space); 969// m_log.DebugFormat("[PHYSICS]: Colliding {0} and {1} in {2}", g1, g2, space);
776 // no lock here! It's invoked from within Simulate(), which is thread-locked 970 // no lock here! It's invoked from within Simulate(), which is thread-locked
777 971
@@ -789,7 +983,7 @@ namespace OpenSim.Region.Physics.OdePlugin
789 // contact points in the space 983 // contact points in the space
790 try 984 try
791 { 985 {
792 d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback); 986 CollideSpaces(g1, g2, IntPtr.Zero);
793 } 987 }
794 catch (AccessViolationException) 988 catch (AccessViolationException)
795 { 989 {
@@ -832,6 +1026,7 @@ namespace OpenSim.Region.Physics.OdePlugin
832 1026
833 // Figure out how many contact points we have 1027 // Figure out how many contact points we have
834 int count = 0; 1028 int count = 0;
1029
835 try 1030 try
836 { 1031 {
837 // Colliding Geom To Geom 1032 // Colliding Geom To Geom
@@ -843,8 +1038,11 @@ namespace OpenSim.Region.Physics.OdePlugin
843 if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) 1038 if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
844 return; 1039 return;
845 1040
846 lock (OdeScene.UniversalColliderSyncObject) 1041 count = CollideGeoms(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf);
847 count = d.Collide(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf); 1042
1043 // All code after this is only relevant if we have any collisions
1044 if (count <= 0)
1045 return;
848 1046
849 if (count > contacts.Length) 1047 if (count > contacts.Length)
850 m_log.Error("[ODE SCENE]: Got " + count + " contacts when we asked for a maximum of " + contacts.Length); 1048 m_log.Error("[ODE SCENE]: Got " + count + " contacts when we asked for a maximum of " + contacts.Length);
@@ -1113,14 +1311,12 @@ namespace OpenSim.Region.Physics.OdePlugin
1113 { 1311 {
1114 _perloopContact.Add(curContact); 1312 _perloopContact.Add(curContact);
1115 1313
1116 // If we're colliding against terrain
1117 if (name1 == "Terrain" || name2 == "Terrain") 1314 if (name1 == "Terrain" || name2 == "Terrain")
1118 { 1315 {
1119 // If we're moving
1120 if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && 1316 if ((p2.PhysicsActorType == (int) ActorTypes.Agent) &&
1121 (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) 1317 (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f))
1122 { 1318 {
1123 // Use the movement terrain contact 1319 // Avatar is moving on terrain, use the movement terrain contact
1124 AvatarMovementTerrainContact.geom = curContact; 1320 AvatarMovementTerrainContact.geom = curContact;
1125 1321
1126 if (m_global_contactcount < maxContactsbeforedeath) 1322 if (m_global_contactcount < maxContactsbeforedeath)
@@ -1133,7 +1329,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1133 { 1329 {
1134 if (p2.PhysicsActorType == (int)ActorTypes.Agent) 1330 if (p2.PhysicsActorType == (int)ActorTypes.Agent)
1135 { 1331 {
1136 // Use the non moving terrain contact 1332 // Avatar is standing on terrain, use the non moving terrain contact
1137 TerrainContact.geom = curContact; 1333 TerrainContact.geom = curContact;
1138 1334
1139 if (m_global_contactcount < maxContactsbeforedeath) 1335 if (m_global_contactcount < maxContactsbeforedeath)
@@ -1228,13 +1424,11 @@ namespace OpenSim.Region.Physics.OdePlugin
1228 } 1424 }
1229 else 1425 else
1230 { 1426 {
1231 // we're colliding with prim or avatar
1232 // check if we're moving
1233 if ((p2.PhysicsActorType == (int)ActorTypes.Agent)) 1427 if ((p2.PhysicsActorType == (int)ActorTypes.Agent))
1234 { 1428 {
1235 if ((Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) 1429 if ((Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f))
1236 { 1430 {
1237 // Use the Movement prim contact 1431 // Avatar is moving on a prim, use the Movement prim contact
1238 AvatarMovementprimContact.geom = curContact; 1432 AvatarMovementprimContact.geom = curContact;
1239 1433
1240 if (m_global_contactcount < maxContactsbeforedeath) 1434 if (m_global_contactcount < maxContactsbeforedeath)
@@ -1245,9 +1439,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1245 } 1439 }
1246 else 1440 else
1247 { 1441 {
1248 // Use the non movement contact 1442 // Avatar is standing still on a prim, use the non movement contact
1249 contact.geom = curContact; 1443 contact.geom = curContact;
1250 _perloopContact.Add(curContact);
1251 1444
1252 if (m_global_contactcount < maxContactsbeforedeath) 1445 if (m_global_contactcount < maxContactsbeforedeath)
1253 { 1446 {
@@ -1355,7 +1548,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1355 break; 1548 break;
1356 } 1549 }
1357 } 1550 }
1358 //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth)); 1551 //m_log.DebugFormat("[Collision]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth));
1359 //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)); 1552 //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));
1360 } 1553 }
1361 } 1554 }
@@ -1578,7 +1771,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1578 // and we'll run it again on all of them. 1771 // and we'll run it again on all of them.
1579 try 1772 try
1580 { 1773 {
1581 d.SpaceCollide2(space, chr.Shell, IntPtr.Zero, nearCallback); 1774 CollideSpaces(space, chr.Shell, IntPtr.Zero);
1582 } 1775 }
1583 catch (AccessViolationException) 1776 catch (AccessViolationException)
1584 { 1777 {
@@ -1593,6 +1786,12 @@ namespace OpenSim.Region.Physics.OdePlugin
1593 //} 1786 //}
1594 } 1787 }
1595 1788
1789 if (CollectStats)
1790 {
1791 m_tempAvatarCollisionsThisFrame = _perloopContact.Count;
1792 m_stats[ODEAvatarContactsStatsName] += m_tempAvatarCollisionsThisFrame;
1793 }
1794
1596 List<OdePrim> removeprims = null; 1795 List<OdePrim> removeprims = null;
1597 foreach (OdePrim chr in _activeprims) 1796 foreach (OdePrim chr in _activeprims)
1598 { 1797 {
@@ -1604,7 +1803,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1604 { 1803 {
1605 if (space != IntPtr.Zero && chr.prim_geom != IntPtr.Zero && chr.m_taintremove == false) 1804 if (space != IntPtr.Zero && chr.prim_geom != IntPtr.Zero && chr.m_taintremove == false)
1606 { 1805 {
1607 d.SpaceCollide2(space, chr.prim_geom, IntPtr.Zero, nearCallback); 1806 CollideSpaces(space, chr.prim_geom, IntPtr.Zero);
1608 } 1807 }
1609 else 1808 else
1610 { 1809 {
@@ -1625,6 +1824,9 @@ namespace OpenSim.Region.Physics.OdePlugin
1625 } 1824 }
1626 } 1825 }
1627 1826
1827 if (CollectStats)
1828 m_stats[ODEPrimContactsStatName] += _perloopContact.Count - m_tempAvatarCollisionsThisFrame;
1829
1628 if (removeprims != null) 1830 if (removeprims != null)
1629 { 1831 {
1630 foreach (OdePrim chr in removeprims) 1832 foreach (OdePrim chr in removeprims)
@@ -1706,8 +1908,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1706 { 1908 {
1707// m_log.DebugFormat("[PHYSICS]: Adding {0} {1} to collision event reporting", obj.SOPName, obj.LocalID); 1909// m_log.DebugFormat("[PHYSICS]: Adding {0} {1} to collision event reporting", obj.SOPName, obj.LocalID);
1708 1910
1709 lock (_collisionEventPrimChanges) 1911 lock (m_collisionEventActorsChanges)
1710 _collisionEventPrimChanges[obj.LocalID] = obj; 1912 m_collisionEventActorsChanges[obj.LocalID] = obj;
1711 } 1913 }
1712 1914
1713 /// <summary> 1915 /// <summary>
@@ -1718,8 +1920,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1718 { 1920 {
1719// m_log.DebugFormat("[PHYSICS]: Removing {0} {1} from collision event reporting", obj.SOPName, obj.LocalID); 1921// m_log.DebugFormat("[PHYSICS]: Removing {0} {1} from collision event reporting", obj.SOPName, obj.LocalID);
1720 1922
1721 lock (_collisionEventPrimChanges) 1923 lock (m_collisionEventActorsChanges)
1722 _collisionEventPrimChanges[obj.LocalID] = null; 1924 m_collisionEventActorsChanges[obj.LocalID] = null;
1723 } 1925 }
1724 1926
1725 #region Add/Remove Entities 1927 #region Add/Remove Entities
@@ -2226,7 +2428,8 @@ namespace OpenSim.Region.Physics.OdePlugin
2226 /// <param name="prim"></param> 2428 /// <param name="prim"></param>
2227 internal void RemovePrimThreadLocked(OdePrim prim) 2429 internal void RemovePrimThreadLocked(OdePrim prim)
2228 { 2430 {
2229//Console.WriteLine("RemovePrimThreadLocked " + prim.m_primName); 2431// m_log.DebugFormat("[ODE SCENE]: Removing physical prim {0} {1}", prim.Name, prim.LocalID);
2432
2230 lock (prim) 2433 lock (prim)
2231 { 2434 {
2232 RemoveCollisionEventReporting(prim); 2435 RemoveCollisionEventReporting(prim);
@@ -2682,21 +2885,23 @@ namespace OpenSim.Region.Physics.OdePlugin
2682 2885
2683 /// <summary> 2886 /// <summary>
2684 /// This is our main simulate loop 2887 /// This is our main simulate loop
2888 /// </summary>
2889 /// <remarks>
2685 /// It's thread locked by a Mutex in the scene. 2890 /// It's thread locked by a Mutex in the scene.
2686 /// It holds Collisions, it instructs ODE to step through the physical reactions 2891 /// It holds Collisions, it instructs ODE to step through the physical reactions
2687 /// It moves the objects around in memory 2892 /// It moves the objects around in memory
2688 /// It calls the methods that report back to the object owners.. (scenepresence, SceneObjectGroup) 2893 /// It calls the methods that report back to the object owners.. (scenepresence, SceneObjectGroup)
2689 /// </summary> 2894 /// </remarks>
2690 /// <param name="timeStep"></param> 2895 /// <param name="timeStep"></param>
2691 /// <returns></returns> 2896 /// <returns>The number of frames simulated over that period.</returns>
2692 public override float Simulate(float timeStep) 2897 public override float Simulate(float timeStep)
2693 { 2898 {
2899 int startFrameTick = CollectStats ? Util.EnvironmentTickCount() : 0;
2900 int tempTick = 0, tempTick2 = 0;
2901
2694 if (framecount >= int.MaxValue) 2902 if (framecount >= int.MaxValue)
2695 framecount = 0; 2903 framecount = 0;
2696 2904
2697 //if (m_worldOffset != Vector3.Zero)
2698 // return 0;
2699
2700 framecount++; 2905 framecount++;
2701 2906
2702 float fps = 0; 2907 float fps = 0;
@@ -2704,7 +2909,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2704 float timeLeft = timeStep; 2909 float timeLeft = timeStep;
2705 2910
2706 //m_log.Info(timeStep.ToString()); 2911 //m_log.Info(timeStep.ToString());
2707// step_time += timeStep; 2912// step_time += timeSte
2708// 2913//
2709// // If We're loaded down by something else, 2914// // If We're loaded down by something else,
2710// // or debugging with the Visual Studio project on pause 2915// // or debugging with the Visual Studio project on pause
@@ -2725,17 +2930,17 @@ namespace OpenSim.Region.Physics.OdePlugin
2725 // We change _collisionEventPrimChanges to avoid locking _collisionEventPrim itself and causing potential 2930 // We change _collisionEventPrimChanges to avoid locking _collisionEventPrim itself and causing potential
2726 // deadlock if the collision event tries to lock something else later on which is already locked by a 2931 // deadlock if the collision event tries to lock something else later on which is already locked by a
2727 // caller that is adding or removing the collision event. 2932 // caller that is adding or removing the collision event.
2728 lock (_collisionEventPrimChanges) 2933 lock (m_collisionEventActorsChanges)
2729 { 2934 {
2730 foreach (KeyValuePair<uint, PhysicsActor> kvp in _collisionEventPrimChanges) 2935 foreach (KeyValuePair<uint, PhysicsActor> kvp in m_collisionEventActorsChanges)
2731 { 2936 {
2732 if (kvp.Value == null) 2937 if (kvp.Value == null)
2733 _collisionEventPrim.Remove(kvp.Key); 2938 m_collisionEventActors.Remove(kvp.Key);
2734 else 2939 else
2735 _collisionEventPrim[kvp.Key] = kvp.Value; 2940 m_collisionEventActors[kvp.Key] = kvp.Value;
2736 } 2941 }
2737 2942
2738 _collisionEventPrimChanges.Clear(); 2943 m_collisionEventActorsChanges.Clear();
2739 } 2944 }
2740 2945
2741 if (SupportsNINJAJoints) 2946 if (SupportsNINJAJoints)
@@ -2770,6 +2975,9 @@ namespace OpenSim.Region.Physics.OdePlugin
2770 { 2975 {
2771 try 2976 try
2772 { 2977 {
2978 if (CollectStats)
2979 tempTick = Util.EnvironmentTickCount();
2980
2773 lock (_taintedActors) 2981 lock (_taintedActors)
2774 { 2982 {
2775 foreach (OdeCharacter character in _taintedActors) 2983 foreach (OdeCharacter character in _taintedActors)
@@ -2778,6 +2986,13 @@ namespace OpenSim.Region.Physics.OdePlugin
2778 _taintedActors.Clear(); 2986 _taintedActors.Clear();
2779 } 2987 }
2780 2988
2989 if (CollectStats)
2990 {
2991 tempTick2 = Util.EnvironmentTickCount();
2992 m_stats[ODEAvatarTaintMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
2993 tempTick = tempTick2;
2994 }
2995
2781 lock (_taintedPrims) 2996 lock (_taintedPrims)
2782 { 2997 {
2783 foreach (OdePrim prim in _taintedPrims) 2998 foreach (OdePrim prim in _taintedPrims)
@@ -2808,6 +3023,13 @@ namespace OpenSim.Region.Physics.OdePlugin
2808 _taintedPrims.Clear(); 3023 _taintedPrims.Clear();
2809 } 3024 }
2810 3025
3026 if (CollectStats)
3027 {
3028 tempTick2 = Util.EnvironmentTickCount();
3029 m_stats[ODEPrimTaintMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
3030 tempTick = tempTick2;
3031 }
3032
2811 // Move characters 3033 // Move characters
2812 foreach (OdeCharacter actor in _characters) 3034 foreach (OdeCharacter actor in _characters)
2813 actor.Move(defects); 3035 actor.Move(defects);
@@ -2827,6 +3049,13 @@ namespace OpenSim.Region.Physics.OdePlugin
2827 defects.Clear(); 3049 defects.Clear();
2828 } 3050 }
2829 3051
3052 if (CollectStats)
3053 {
3054 tempTick2 = Util.EnvironmentTickCount();
3055 m_stats[ODEAvatarForcesFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
3056 tempTick = tempTick2;
3057 }
3058
2830 // Move other active objects 3059 // Move other active objects
2831 foreach (OdePrim prim in _activeprims) 3060 foreach (OdePrim prim in _activeprims)
2832 { 3061 {
@@ -2834,15 +3063,36 @@ namespace OpenSim.Region.Physics.OdePlugin
2834 prim.Move(timeStep); 3063 prim.Move(timeStep);
2835 } 3064 }
2836 3065
3066 if (CollectStats)
3067 {
3068 tempTick2 = Util.EnvironmentTickCount();
3069 m_stats[ODEPrimForcesFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
3070 tempTick = tempTick2;
3071 }
3072
2837 //if ((framecount % m_randomizeWater) == 0) 3073 //if ((framecount % m_randomizeWater) == 0)
2838 // randomizeWater(waterlevel); 3074 // randomizeWater(waterlevel);
2839 3075
2840 //int RayCastTimeMS = m_rayCastManager.ProcessQueuedRequests(); 3076 //int RayCastTimeMS = m_rayCastManager.ProcessQueuedRequests();
2841 m_rayCastManager.ProcessQueuedRequests(); 3077 m_rayCastManager.ProcessQueuedRequests();
2842 3078
3079 if (CollectStats)
3080 {
3081 tempTick2 = Util.EnvironmentTickCount();
3082 m_stats[ODERaycastingFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
3083 tempTick = tempTick2;
3084 }
3085
2843 collision_optimized(); 3086 collision_optimized();
2844 3087
2845 foreach (PhysicsActor obj in _collisionEventPrim.Values) 3088 if (CollectStats)
3089 {
3090 tempTick2 = Util.EnvironmentTickCount();
3091 m_stats[ODEOtherCollisionFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
3092 tempTick = tempTick2;
3093 }
3094
3095 foreach (PhysicsActor obj in m_collisionEventActors.Values)
2846 { 3096 {
2847// m_log.DebugFormat("[PHYSICS]: Assessing {0} {1} for collision events", obj.SOPName, obj.LocalID); 3097// m_log.DebugFormat("[PHYSICS]: Assessing {0} {1} for collision events", obj.SOPName, obj.LocalID);
2848 3098
@@ -2866,9 +3116,19 @@ namespace OpenSim.Region.Physics.OdePlugin
2866// "[PHYSICS]: Collision contacts to process this frame = {0}", m_global_contactcount); 3116// "[PHYSICS]: Collision contacts to process this frame = {0}", m_global_contactcount);
2867 3117
2868 m_global_contactcount = 0; 3118 m_global_contactcount = 0;
2869 3119
3120 if (CollectStats)
3121 {
3122 tempTick2 = Util.EnvironmentTickCount();
3123 m_stats[ODECollisionNotificationFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
3124 tempTick = tempTick2;
3125 }
3126
2870 d.WorldQuickStep(world, ODE_STEPSIZE); 3127 d.WorldQuickStep(world, ODE_STEPSIZE);
2871 3128
3129 if (CollectStats)
3130 m_stats[ODENativeStepFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick);
3131
2872 d.JointGroupEmpty(contactgroup); 3132 d.JointGroupEmpty(contactgroup);
2873 } 3133 }
2874 catch (Exception e) 3134 catch (Exception e)
@@ -2879,6 +3139,9 @@ namespace OpenSim.Region.Physics.OdePlugin
2879 timeLeft -= ODE_STEPSIZE; 3139 timeLeft -= ODE_STEPSIZE;
2880 } 3140 }
2881 3141
3142 if (CollectStats)
3143 tempTick = Util.EnvironmentTickCount();
3144
2882 foreach (OdeCharacter actor in _characters) 3145 foreach (OdeCharacter actor in _characters)
2883 { 3146 {
2884 if (actor.bad) 3147 if (actor.bad)
@@ -2902,6 +3165,13 @@ namespace OpenSim.Region.Physics.OdePlugin
2902 defects.Clear(); 3165 defects.Clear();
2903 } 3166 }
2904 3167
3168 if (CollectStats)
3169 {
3170 tempTick2 = Util.EnvironmentTickCount();
3171 m_stats[ODEAvatarUpdateFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
3172 tempTick = tempTick2;
3173 }
3174
2905 //if (timeStep < 0.2f) 3175 //if (timeStep < 0.2f)
2906 3176
2907 foreach (OdePrim prim in _activeprims) 3177 foreach (OdePrim prim in _activeprims)
@@ -2915,6 +3185,9 @@ namespace OpenSim.Region.Physics.OdePlugin
2915 } 3185 }
2916 } 3186 }
2917 3187
3188 if (CollectStats)
3189 m_stats[ODEPrimUpdateFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick);
3190
2918 //DumpJointInfo(); 3191 //DumpJointInfo();
2919 3192
2920 // Finished with all sim stepping. If requested, dump world state to file for debugging. 3193 // Finished with all sim stepping. If requested, dump world state to file for debugging.
@@ -2936,7 +3209,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2936 d.WorldExportDIF(world, fname, physics_logging_append_existing_logfile, prefix); 3209 d.WorldExportDIF(world, fname, physics_logging_append_existing_logfile, prefix);
2937 } 3210 }
2938 3211
2939 latertickcount = Util.EnvironmentTickCount() - tickCountFrameRun; 3212 latertickcount = Util.EnvironmentTickCountSubtract(tickCountFrameRun);
2940 3213
2941 // OpenSimulator above does 10 fps. 10 fps = means that the main thread loop and physics 3214 // OpenSimulator above does 10 fps. 10 fps = means that the main thread loop and physics
2942 // has a max of 100 ms to run theoretically. 3215 // has a max of 100 ms to run theoretically.
@@ -2954,6 +3227,9 @@ namespace OpenSim.Region.Physics.OdePlugin
2954 } 3227 }
2955 3228
2956 tickCountFrameRun = Util.EnvironmentTickCount(); 3229 tickCountFrameRun = Util.EnvironmentTickCount();
3230
3231 if (CollectStats)
3232 m_stats[ODETotalFrameMsStatName] += Util.EnvironmentTickCountSubtract(startFrameTick);
2957 } 3233 }
2958 3234
2959 return fps; 3235 return fps;
@@ -3189,7 +3465,7 @@ namespace OpenSim.Region.Physics.OdePlugin
3189 public override bool IsThreaded 3465 public override bool IsThreaded
3190 { 3466 {
3191 // for now we won't be multithreaded 3467 // for now we won't be multithreaded
3192 get { return (false); } 3468 get { return false; }
3193 } 3469 }
3194 3470
3195 #region ODE Specific Terrain Fixes 3471 #region ODE Specific Terrain Fixes
@@ -3765,26 +4041,19 @@ namespace OpenSim.Region.Physics.OdePlugin
3765 4041
3766 public override Dictionary<uint, float> GetTopColliders() 4042 public override Dictionary<uint, float> GetTopColliders()
3767 { 4043 {
3768 Dictionary<uint, float> returncolliders = new Dictionary<uint, float>(); 4044 Dictionary<uint, float> topColliders;
3769 int cnt = 0; 4045
3770 lock (_prims) 4046 lock (_prims)
3771 { 4047 {
3772 foreach (OdePrim prm in _prims) 4048 List<OdePrim> orderedPrims = new List<OdePrim>(_prims);
3773 { 4049 orderedPrims.OrderByDescending(p => p.CollisionScore).Take(25);
3774 if (prm.CollisionScore > 0) 4050 topColliders = orderedPrims.ToDictionary(p => p.LocalID, p => p.CollisionScore);
3775 { 4051
3776 returncolliders.Add(prm.LocalID, prm.CollisionScore); 4052 foreach (OdePrim p in _prims)
3777 cnt++; 4053 p.CollisionScore = 0;
3778 prm.CollisionScore = 0f;
3779 if (cnt > 25)
3780 {
3781 break;
3782 }
3783 }
3784 }
3785 } 4054 }
3786 4055
3787 return returncolliders; 4056 return topColliders;
3788 } 4057 }
3789 4058
3790 public override bool SupportsRayCast() 4059 public override bool SupportsRayCast()
@@ -3954,5 +4223,52 @@ namespace OpenSim.Region.Physics.OdePlugin
3954 ds.SetViewpoint(ref xyz, ref hpr); 4223 ds.SetViewpoint(ref xyz, ref hpr);
3955 } 4224 }
3956#endif 4225#endif
4226
4227 public override Dictionary<string, float> GetStats()
4228 {
4229 if (!CollectStats)
4230 return null;
4231
4232 Dictionary<string, float> returnStats;
4233
4234 lock (OdeLock)
4235 {
4236 returnStats = new Dictionary<string, float>(m_stats);
4237
4238 // FIXME: This is a SUPER DUMB HACK until we can establish stats that aren't subject to a division by
4239 // 3 from the SimStatsReporter.
4240 returnStats[ODETotalAvatarsStatName] = _characters.Count * 3;
4241 returnStats[ODETotalPrimsStatName] = _prims.Count * 3;
4242 returnStats[ODEActivePrimsStatName] = _activeprims.Count * 3;
4243
4244 InitializeExtraStats();
4245 }
4246
4247 returnStats[ODEOtherCollisionFrameMsStatName]
4248 = returnStats[ODEOtherCollisionFrameMsStatName]
4249 - returnStats[ODENativeSpaceCollisionFrameMsStatName]
4250 - returnStats[ODENativeGeomCollisionFrameMsStatName];
4251
4252 return returnStats;
4253 }
4254
4255 private void InitializeExtraStats()
4256 {
4257 m_stats[ODETotalFrameMsStatName] = 0;
4258 m_stats[ODEAvatarTaintMsStatName] = 0;
4259 m_stats[ODEPrimTaintMsStatName] = 0;
4260 m_stats[ODEAvatarForcesFrameMsStatName] = 0;
4261 m_stats[ODEPrimForcesFrameMsStatName] = 0;
4262 m_stats[ODERaycastingFrameMsStatName] = 0;
4263 m_stats[ODENativeStepFrameMsStatName] = 0;
4264 m_stats[ODENativeSpaceCollisionFrameMsStatName] = 0;
4265 m_stats[ODENativeGeomCollisionFrameMsStatName] = 0;
4266 m_stats[ODEOtherCollisionFrameMsStatName] = 0;
4267 m_stats[ODECollisionNotificationFrameMsStatName] = 0;
4268 m_stats[ODEAvatarContactsStatsName] = 0;
4269 m_stats[ODEPrimContactsStatName] = 0;
4270 m_stats[ODEAvatarUpdateFrameMsStatName] = 0;
4271 m_stats[ODEPrimUpdateFrameMsStatName] = 0;
4272 }
3957 } 4273 }
3958} \ No newline at end of file 4274} \ No newline at end of file
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
index d8d9554..204c4ff 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
@@ -43,9 +43,8 @@ using Mono.Addins;
43[assembly: AddinDependency("OpenSim", "0.5")] 43[assembly: AddinDependency("OpenSim", "0.5")]
44namespace OpenSim.Region.RegionCombinerModule 44namespace OpenSim.Region.RegionCombinerModule
45{ 45{
46
47 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
48 public class RegionCombinerModule : ISharedRegionModule 47 public class RegionCombinerModule : ISharedRegionModule, IRegionCombinerModule
49 { 48 {
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51 50
@@ -59,19 +58,33 @@ namespace OpenSim.Region.RegionCombinerModule
59 get { return null; } 58 get { return null; }
60 } 59 }
61 60
61 /// <summary>
62 /// Is this module enabled?
63 /// </summary>
64 private bool m_combineContiguousRegions = false;
65
66 /// <summary>
67 /// This holds the root regions for the megaregions.
68 /// </summary>
69 /// <remarks>
70 /// Usually there is only ever one megaregion (and hence only one entry here).
71 /// </remarks>
62 private Dictionary<UUID, RegionConnections> m_regions = new Dictionary<UUID, RegionConnections>(); 72 private Dictionary<UUID, RegionConnections> m_regions = new Dictionary<UUID, RegionConnections>();
63 private bool enabledYN = false; 73
74 /// <summary>
75 /// The scenes that comprise the megaregion.
76 /// </summary>
64 private Dictionary<UUID, Scene> m_startingScenes = new Dictionary<UUID, Scene>(); 77 private Dictionary<UUID, Scene> m_startingScenes = new Dictionary<UUID, Scene>();
65 78
66 public void Initialise(IConfigSource source) 79 public void Initialise(IConfigSource source)
67 { 80 {
68 IConfig myConfig = source.Configs["Startup"]; 81 IConfig myConfig = source.Configs["Startup"];
69 enabledYN = myConfig.GetBoolean("CombineContiguousRegions", false); 82 m_combineContiguousRegions = myConfig.GetBoolean("CombineContiguousRegions", false);
70 83
71 if (enabledYN) 84 MainConsole.Instance.Commands.AddCommand(
72 MainConsole.Instance.Commands.AddCommand( 85 "RegionCombinerModule", false, "fix-phantoms", "fix-phantoms",
73 "RegionCombinerModule", false, "fix-phantoms", "fix-phantoms", 86 "Fixes phantom objects after an import to a megaregion or a change from a megaregion back to normal regions",
74 "Fixes phantom objects after an import to megaregions", FixPhantoms); 87 FixPhantoms);
75 } 88 }
76 89
77 public void Close() 90 public void Close()
@@ -80,6 +93,8 @@ namespace OpenSim.Region.RegionCombinerModule
80 93
81 public void AddRegion(Scene scene) 94 public void AddRegion(Scene scene)
82 { 95 {
96 if (m_combineContiguousRegions)
97 scene.RegisterModuleInterface<IRegionCombinerModule>(this);
83 } 98 }
84 99
85 public void RemoveRegion(Scene scene) 100 public void RemoveRegion(Scene scene)
@@ -88,8 +103,113 @@ namespace OpenSim.Region.RegionCombinerModule
88 103
89 public void RegionLoaded(Scene scene) 104 public void RegionLoaded(Scene scene)
90 { 105 {
91 if (enabledYN) 106 lock (m_startingScenes)
107 m_startingScenes.Add(scene.RegionInfo.originRegionID, scene);
108
109 if (m_combineContiguousRegions)
110 {
92 RegionLoadedDoWork(scene); 111 RegionLoadedDoWork(scene);
112
113 scene.EventManager.OnNewPresence += NewPresence;
114 }
115 }
116
117 public bool IsRootForMegaregion(UUID regionId)
118 {
119 lock (m_regions)
120 return m_regions.ContainsKey(regionId);
121 }
122
123 public Vector2 GetSizeOfMegaregion(UUID regionId)
124 {
125 lock (m_regions)
126 {
127 if (m_regions.ContainsKey(regionId))
128 {
129 RegionConnections rootConn = m_regions[regionId];
130
131 return new Vector2((float)rootConn.XEnd, (float)rootConn.YEnd);
132 }
133 }
134
135 throw new Exception(string.Format("Region with id {0} not found", regionId));
136 }
137
138 private void NewPresence(ScenePresence presence)
139 {
140 if (presence.IsChildAgent)
141 {
142 byte[] throttleData;
143
144 try
145 {
146 throttleData = presence.ControllingClient.GetThrottlesPacked(1);
147 }
148 catch (NotImplementedException)
149 {
150 return;
151 }
152
153 if (throttleData == null)
154 return;
155
156 if (throttleData.Length == 0)
157 return;
158
159 if (throttleData.Length != 28)
160 return;
161
162 byte[] adjData;
163 int pos = 0;
164
165 if (!BitConverter.IsLittleEndian)
166 {
167 byte[] newData = new byte[7 * 4];
168 Buffer.BlockCopy(throttleData, 0, newData, 0, 7 * 4);
169
170 for (int i = 0; i < 7; i++)
171 Array.Reverse(newData, i * 4, 4);
172
173 adjData = newData;
174 }
175 else
176 {
177 adjData = throttleData;
178 }
179
180 // 0.125f converts from bits to bytes
181 int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
182 int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
183 int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
184 int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
185 int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
186 int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
187 int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
188 // State is a subcategory of task that we allocate a percentage to
189
190
191 //int total = resend + land + wind + cloud + task + texture + asset;
192
193 byte[] data = new byte[7 * 4];
194 int ii = 0;
195
196 Buffer.BlockCopy(Utils.FloatToBytes(resend), 0, data, ii, 4); ii += 4;
197 Buffer.BlockCopy(Utils.FloatToBytes(land * 50), 0, data, ii, 4); ii += 4;
198 Buffer.BlockCopy(Utils.FloatToBytes(wind), 0, data, ii, 4); ii += 4;
199 Buffer.BlockCopy(Utils.FloatToBytes(cloud), 0, data, ii, 4); ii += 4;
200 Buffer.BlockCopy(Utils.FloatToBytes(task), 0, data, ii, 4); ii += 4;
201 Buffer.BlockCopy(Utils.FloatToBytes(texture), 0, data, ii, 4); ii += 4;
202 Buffer.BlockCopy(Utils.FloatToBytes(asset), 0, data, ii, 4);
203
204 try
205 {
206 presence.ControllingClient.SetChildAgentThrottle(data);
207 }
208 catch (NotImplementedException)
209 {
210 return;
211 }
212 }
93 } 213 }
94 214
95 private void RegionLoadedDoWork(Scene scene) 215 private void RegionLoadedDoWork(Scene scene)
@@ -100,8 +220,6 @@ namespace OpenSim.Region.RegionCombinerModule
100 return; 220 return;
101 // 221 //
102*/ 222*/
103 lock (m_startingScenes)
104 m_startingScenes.Add(scene.RegionInfo.originRegionID, scene);
105 223
106 // Give each region a standard set of non-infinite borders 224 // Give each region a standard set of non-infinite borders
107 Border northBorder = new Border(); 225 Border northBorder = new Border();
@@ -124,24 +242,21 @@ namespace OpenSim.Region.RegionCombinerModule
124 westBorder.CrossDirection = Cardinals.W; 242 westBorder.CrossDirection = Cardinals.W;
125 scene.WestBorders[0] = westBorder; 243 scene.WestBorders[0] = westBorder;
126 244
127 245 RegionConnections newConn = new RegionConnections();
128 246 newConn.ConnectedRegions = new List<RegionData>();
129 RegionConnections regionConnections = new RegionConnections(); 247 newConn.RegionScene = scene;
130 regionConnections.ConnectedRegions = new List<RegionData>(); 248 newConn.RegionLandChannel = scene.LandChannel;
131 regionConnections.RegionScene = scene; 249 newConn.RegionId = scene.RegionInfo.originRegionID;
132 regionConnections.RegionLandChannel = scene.LandChannel; 250 newConn.X = scene.RegionInfo.RegionLocX;
133 regionConnections.RegionId = scene.RegionInfo.originRegionID; 251 newConn.Y = scene.RegionInfo.RegionLocY;
134 regionConnections.X = scene.RegionInfo.RegionLocX; 252 newConn.XEnd = (int)Constants.RegionSize;
135 regionConnections.Y = scene.RegionInfo.RegionLocY; 253 newConn.YEnd = (int)Constants.RegionSize;
136 regionConnections.XEnd = (int)Constants.RegionSize;
137 regionConnections.YEnd = (int)Constants.RegionSize;
138
139 254
140 lock (m_regions) 255 lock (m_regions)
141 { 256 {
142 bool connectedYN = false; 257 bool connectedYN = false;
143 258
144 foreach (RegionConnections conn in m_regions.Values) 259 foreach (RegionConnections rootConn in m_regions.Values)
145 { 260 {
146 #region commented 261 #region commented
147 /* 262 /*
@@ -306,13 +421,9 @@ namespace OpenSim.Region.RegionCombinerModule
306 //xxy 421 //xxy
307 //xxx 422 //xxx
308 423
309 424 if (rootConn.PosX + rootConn.XEnd >= newConn.PosX && rootConn.PosY >= newConn.PosY)
310 if ((((int)conn.X * (int)Constants.RegionSize) + conn.XEnd
311 >= (regionConnections.X * (int)Constants.RegionSize))
312 && (((int)conn.Y * (int)Constants.RegionSize)
313 >= (regionConnections.Y * (int)Constants.RegionSize)))
314 { 425 {
315 connectedYN = DoWorkForOneRegionOverPlusXY(conn, regionConnections, scene); 426 connectedYN = DoWorkForOneRegionOverPlusXY(rootConn, newConn, scene);
316 break; 427 break;
317 } 428 }
318 429
@@ -320,12 +431,9 @@ namespace OpenSim.Region.RegionCombinerModule
320 //xyx 431 //xyx
321 //xxx 432 //xxx
322 //xxx 433 //xxx
323 if ((((int)conn.X * (int)Constants.RegionSize) 434 if (rootConn.PosX >= newConn.PosX && rootConn.PosY + rootConn.YEnd >= newConn.PosY)
324 >= (regionConnections.X * (int)Constants.RegionSize))
325 && (((int)conn.Y * (int)Constants.RegionSize) + conn.YEnd
326 >= (regionConnections.Y * (int)Constants.RegionSize)))
327 { 435 {
328 connectedYN = DoWorkForOneRegionOverXPlusY(conn, regionConnections, scene); 436 connectedYN = DoWorkForOneRegionOverXPlusY(rootConn, newConn, scene);
329 break; 437 break;
330 } 438 }
331 439
@@ -333,12 +441,9 @@ namespace OpenSim.Region.RegionCombinerModule
333 //xxy 441 //xxy
334 //xxx 442 //xxx
335 //xxx 443 //xxx
336 if ((((int)conn.X * (int)Constants.RegionSize) + conn.XEnd 444 if (rootConn.PosX + rootConn.XEnd >= newConn.PosX && rootConn.PosY + rootConn.YEnd >= newConn.PosY)
337 >= (regionConnections.X * (int)Constants.RegionSize))
338 && (((int)conn.Y * (int)Constants.RegionSize) + conn.YEnd
339 >= (regionConnections.Y * (int)Constants.RegionSize)))
340 { 445 {
341 connectedYN = DoWorkForOneRegionOverPlusXPlusY(conn, regionConnections, scene); 446 connectedYN = DoWorkForOneRegionOverPlusXPlusY(rootConn, newConn, scene);
342 break; 447 break;
343 448
344 } 449 }
@@ -347,66 +452,63 @@ namespace OpenSim.Region.RegionCombinerModule
347 // If !connectYN means that this region is a root region 452 // If !connectYN means that this region is a root region
348 if (!connectedYN) 453 if (!connectedYN)
349 { 454 {
350 DoWorkForRootRegion(regionConnections, scene); 455 DoWorkForRootRegion(newConn, scene);
351
352 } 456 }
353 } 457 }
458
354 // Set up infinite borders around the entire AABB of the combined ConnectedRegions 459 // Set up infinite borders around the entire AABB of the combined ConnectedRegions
355 AdjustLargeRegionBounds(); 460 AdjustLargeRegionBounds();
356 } 461 }
357 462
358 private bool DoWorkForOneRegionOverPlusXY(RegionConnections conn, RegionConnections regionConnections, Scene scene) 463 private bool DoWorkForOneRegionOverPlusXY(RegionConnections rootConn, RegionConnections newConn, Scene scene)
359 { 464 {
360 Vector3 offset = Vector3.Zero; 465 Vector3 offset = Vector3.Zero;
361 offset.X = (((regionConnections.X * (int)Constants.RegionSize)) - 466 offset.X = newConn.PosX - rootConn.PosX;
362 ((conn.X * (int)Constants.RegionSize))); 467 offset.Y = newConn.PosY - rootConn.PosY;
363 offset.Y = (((regionConnections.Y * (int)Constants.RegionSize)) -
364 ((conn.Y * (int)Constants.RegionSize)));
365 468
366 Vector3 extents = Vector3.Zero; 469 Vector3 extents = Vector3.Zero;
367 extents.Y = conn.YEnd; 470 extents.Y = rootConn.YEnd;
368 extents.X = conn.XEnd + regionConnections.XEnd; 471 extents.X = rootConn.XEnd + newConn.XEnd;
369 472
370 conn.UpdateExtents(extents); 473 rootConn.UpdateExtents(extents);
371 474
372 m_log.DebugFormat("Scene: {0} to the west of Scene{1} Offset: {2}. Extents:{3}", 475 m_log.DebugFormat(
373 conn.RegionScene.RegionInfo.RegionName, 476 "[REGION COMBINER MODULE]: Root region {0} is to the west of region {1}, Offset: {2}, Extents: {3}",
374 regionConnections.RegionScene.RegionInfo.RegionName, offset, extents); 477 rootConn.RegionScene.RegionInfo.RegionName,
478 newConn.RegionScene.RegionInfo.RegionName, offset, extents);
375 479
376 scene.BordersLocked = true; 480 scene.BordersLocked = true;
377 conn.RegionScene.BordersLocked = true; 481 rootConn.RegionScene.BordersLocked = true;
378 482
379 RegionData ConnectedRegion = new RegionData(); 483 RegionData ConnectedRegion = new RegionData();
380 ConnectedRegion.Offset = offset; 484 ConnectedRegion.Offset = offset;
381 ConnectedRegion.RegionId = scene.RegionInfo.originRegionID; 485 ConnectedRegion.RegionId = scene.RegionInfo.originRegionID;
382 ConnectedRegion.RegionScene = scene; 486 ConnectedRegion.RegionScene = scene;
383 conn.ConnectedRegions.Add(ConnectedRegion); 487 rootConn.ConnectedRegions.Add(ConnectedRegion);
384 488
385 // Inform root region Physics about the extents of this region 489 // Inform root region Physics about the extents of this region
386 conn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents); 490 rootConn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents);
387 491
388 // Inform Child region that it needs to forward it's terrain to the root region 492 // Inform Child region that it needs to forward it's terrain to the root region
389 scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset, Vector3.Zero); 493 scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero);
390 494
391 // Extend the borders as appropriate 495 // Extend the borders as appropriate
392 lock (conn.RegionScene.EastBorders) 496 lock (rootConn.RegionScene.EastBorders)
393 conn.RegionScene.EastBorders[0].BorderLine.Z += (int)Constants.RegionSize; 497 rootConn.RegionScene.EastBorders[0].BorderLine.Z += (int)Constants.RegionSize;
394 498
395 lock (conn.RegionScene.NorthBorders) 499 lock (rootConn.RegionScene.NorthBorders)
396 conn.RegionScene.NorthBorders[0].BorderLine.Y += (int)Constants.RegionSize; 500 rootConn.RegionScene.NorthBorders[0].BorderLine.Y += (int)Constants.RegionSize;
397 501
398 lock (conn.RegionScene.SouthBorders) 502 lock (rootConn.RegionScene.SouthBorders)
399 conn.RegionScene.SouthBorders[0].BorderLine.Y += (int)Constants.RegionSize; 503 rootConn.RegionScene.SouthBorders[0].BorderLine.Y += (int)Constants.RegionSize;
400 504
401 lock (scene.WestBorders) 505 lock (scene.WestBorders)
402 { 506 {
403 507 scene.WestBorders[0].BorderLine.Z = (int)((scene.RegionInfo.RegionLocX - rootConn.RegionScene.RegionInfo.RegionLocX) * (int)Constants.RegionSize); //auto teleport West
404
405 scene.WestBorders[0].BorderLine.Z = (int)((scene.RegionInfo.RegionLocX - conn.RegionScene.RegionInfo.RegionLocX) * (int)Constants.RegionSize); //auto teleport West
406 508
407 // Trigger auto teleport to root region 509 // Trigger auto teleport to root region
408 scene.WestBorders[0].TriggerRegionX = conn.RegionScene.RegionInfo.RegionLocX; 510 scene.WestBorders[0].TriggerRegionX = rootConn.RegionScene.RegionInfo.RegionLocX;
409 scene.WestBorders[0].TriggerRegionY = conn.RegionScene.RegionInfo.RegionLocY; 511 scene.WestBorders[0].TriggerRegionY = rootConn.RegionScene.RegionInfo.RegionLocY;
410 } 512 }
411 513
412 // Reset Terrain.. since terrain loads before we get here, we need to load 514 // Reset Terrain.. since terrain loads before we get here, we need to load
@@ -415,56 +517,58 @@ namespace OpenSim.Region.RegionCombinerModule
415 scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised()); 517 scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
416 518
417 // Unlock borders 519 // Unlock borders
418 conn.RegionScene.BordersLocked = false; 520 rootConn.RegionScene.BordersLocked = false;
419 scene.BordersLocked = false; 521 scene.BordersLocked = false;
420 522
421 // Create a client event forwarder and add this region's events to the root region. 523 // Create a client event forwarder and add this region's events to the root region.
422 if (conn.ClientEventForwarder != null) 524 if (rootConn.ClientEventForwarder != null)
423 conn.ClientEventForwarder.AddSceneToEventForwarding(scene); 525 rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene);
424 526
425 return true; 527 return true;
426 } 528 }
427 529
428 private bool DoWorkForOneRegionOverXPlusY(RegionConnections conn, RegionConnections regionConnections, Scene scene) 530 private bool DoWorkForOneRegionOverXPlusY(RegionConnections rootConn, RegionConnections newConn, Scene scene)
429 { 531 {
430 Vector3 offset = Vector3.Zero; 532 Vector3 offset = Vector3.Zero;
431 offset.X = (((regionConnections.X * (int)Constants.RegionSize)) - 533 offset.X = newConn.PosX - rootConn.PosX;
432 ((conn.X * (int)Constants.RegionSize))); 534 offset.Y = newConn.PosY - rootConn.PosY;
433 offset.Y = (((regionConnections.Y * (int)Constants.RegionSize)) -
434 ((conn.Y * (int)Constants.RegionSize)));
435 535
436 Vector3 extents = Vector3.Zero; 536 Vector3 extents = Vector3.Zero;
437 extents.Y = regionConnections.YEnd + conn.YEnd; 537 extents.Y = newConn.YEnd + rootConn.YEnd;
438 extents.X = conn.XEnd; 538 extents.X = rootConn.XEnd;
439 conn.UpdateExtents(extents); 539 rootConn.UpdateExtents(extents);
440 540
441 scene.BordersLocked = true; 541 scene.BordersLocked = true;
442 conn.RegionScene.BordersLocked = true; 542 rootConn.RegionScene.BordersLocked = true;
443 543
444 RegionData ConnectedRegion = new RegionData(); 544 RegionData ConnectedRegion = new RegionData();
445 ConnectedRegion.Offset = offset; 545 ConnectedRegion.Offset = offset;
446 ConnectedRegion.RegionId = scene.RegionInfo.originRegionID; 546 ConnectedRegion.RegionId = scene.RegionInfo.originRegionID;
447 ConnectedRegion.RegionScene = scene; 547 ConnectedRegion.RegionScene = scene;
448 conn.ConnectedRegions.Add(ConnectedRegion); 548 rootConn.ConnectedRegions.Add(ConnectedRegion);
549
550 m_log.DebugFormat(
551 "[REGION COMBINER MODULE]: Root region {0} is to the south of region {1}, Offset: {2}, Extents: {3}",
552 rootConn.RegionScene.RegionInfo.RegionName,
553 newConn.RegionScene.RegionInfo.RegionName, offset, extents);
554
555 rootConn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents);
556 scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero);
449 557
450 m_log.DebugFormat("Scene: {0} to the northeast of Scene{1} Offset: {2}. Extents:{3}", 558 lock (rootConn.RegionScene.NorthBorders)
451 conn.RegionScene.RegionInfo.RegionName, 559 rootConn.RegionScene.NorthBorders[0].BorderLine.Z += (int)Constants.RegionSize;
452 regionConnections.RegionScene.RegionInfo.RegionName, offset, extents);
453 560
454 conn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents); 561 lock (rootConn.RegionScene.EastBorders)
455 scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset, Vector3.Zero); 562 rootConn.RegionScene.EastBorders[0].BorderLine.Y += (int)Constants.RegionSize;
563
564 lock (rootConn.RegionScene.WestBorders)
565 rootConn.RegionScene.WestBorders[0].BorderLine.Y += (int)Constants.RegionSize;
456 566
457 lock (conn.RegionScene.NorthBorders)
458 conn.RegionScene.NorthBorders[0].BorderLine.Z += (int)Constants.RegionSize;
459 lock (conn.RegionScene.EastBorders)
460 conn.RegionScene.EastBorders[0].BorderLine.Y += (int)Constants.RegionSize;
461 lock (conn.RegionScene.WestBorders)
462 conn.RegionScene.WestBorders[0].BorderLine.Y += (int)Constants.RegionSize;
463 lock (scene.SouthBorders) 567 lock (scene.SouthBorders)
464 { 568 {
465 scene.SouthBorders[0].BorderLine.Z = (int)((scene.RegionInfo.RegionLocY - conn.RegionScene.RegionInfo.RegionLocY) * (int)Constants.RegionSize); //auto teleport south 569 scene.SouthBorders[0].BorderLine.Z = (int)((scene.RegionInfo.RegionLocY - rootConn.RegionScene.RegionInfo.RegionLocY) * (int)Constants.RegionSize); //auto teleport south
466 scene.SouthBorders[0].TriggerRegionX = conn.RegionScene.RegionInfo.RegionLocX; 570 scene.SouthBorders[0].TriggerRegionX = rootConn.RegionScene.RegionInfo.RegionLocX;
467 scene.SouthBorders[0].TriggerRegionY = conn.RegionScene.RegionInfo.RegionLocY; 571 scene.SouthBorders[0].TriggerRegionY = rootConn.RegionScene.RegionInfo.RegionLocY;
468 } 572 }
469 573
470 // Reset Terrain.. since terrain normally loads first. 574 // Reset Terrain.. since terrain normally loads first.
@@ -473,83 +577,92 @@ namespace OpenSim.Region.RegionCombinerModule
473 //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised()); 577 //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
474 578
475 scene.BordersLocked = false; 579 scene.BordersLocked = false;
476 conn.RegionScene.BordersLocked = false; 580 rootConn.RegionScene.BordersLocked = false;
477 if (conn.ClientEventForwarder != null) 581
478 conn.ClientEventForwarder.AddSceneToEventForwarding(scene); 582 if (rootConn.ClientEventForwarder != null)
583 rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene);
584
479 return true; 585 return true;
480 } 586 }
481 587
482 private bool DoWorkForOneRegionOverPlusXPlusY(RegionConnections conn, RegionConnections regionConnections, Scene scene) 588 private bool DoWorkForOneRegionOverPlusXPlusY(RegionConnections rootConn, RegionConnections newConn, Scene scene)
483 { 589 {
484 Vector3 offset = Vector3.Zero; 590 Vector3 offset = Vector3.Zero;
485 offset.X = (((regionConnections.X * (int)Constants.RegionSize)) - 591 offset.X = newConn.PosX - rootConn.PosX;
486 ((conn.X * (int)Constants.RegionSize))); 592 offset.Y = newConn.PosY - rootConn.PosY;
487 offset.Y = (((regionConnections.Y * (int)Constants.RegionSize)) -
488 ((conn.Y * (int)Constants.RegionSize)));
489 593
490 Vector3 extents = Vector3.Zero; 594 Vector3 extents = Vector3.Zero;
491 extents.Y = regionConnections.YEnd + conn.YEnd; 595
492 extents.X = regionConnections.XEnd + conn.XEnd; 596 // We do not want to inflate the extents for regions strictly to the NE of the root region, since this
493 conn.UpdateExtents(extents); 597 // would double count regions strictly to the north and east that have already been added.
598// extents.Y = regionConnections.YEnd + conn.YEnd;
599// extents.X = regionConnections.XEnd + conn.XEnd;
600// conn.UpdateExtents(extents);
601
602 extents.Y = rootConn.YEnd;
603 extents.X = rootConn.XEnd;
494 604
495 scene.BordersLocked = true; 605 scene.BordersLocked = true;
496 conn.RegionScene.BordersLocked = true; 606 rootConn.RegionScene.BordersLocked = true;
497 607
498 RegionData ConnectedRegion = new RegionData(); 608 RegionData ConnectedRegion = new RegionData();
499 ConnectedRegion.Offset = offset; 609 ConnectedRegion.Offset = offset;
500 ConnectedRegion.RegionId = scene.RegionInfo.originRegionID; 610 ConnectedRegion.RegionId = scene.RegionInfo.originRegionID;
501 ConnectedRegion.RegionScene = scene; 611 ConnectedRegion.RegionScene = scene;
502 612
503 conn.ConnectedRegions.Add(ConnectedRegion); 613 rootConn.ConnectedRegions.Add(ConnectedRegion);
614
615 m_log.DebugFormat(
616 "[REGION COMBINER MODULE]: Region {0} is to the southwest of Scene {1}, Offset: {2}, Extents: {3}",
617 rootConn.RegionScene.RegionInfo.RegionName,
618 newConn.RegionScene.RegionInfo.RegionName, offset, extents);
504 619
505 m_log.DebugFormat("Scene: {0} to the NorthEast of Scene{1} Offset: {2}. Extents:{3}", 620 rootConn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents);
506 conn.RegionScene.RegionInfo.RegionName, 621 scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero);
507 regionConnections.RegionScene.RegionInfo.RegionName, offset, extents);
508 622
509 conn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents); 623 lock (rootConn.RegionScene.NorthBorders)
510 scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset, Vector3.Zero);
511 lock (conn.RegionScene.NorthBorders)
512 { 624 {
513 if (conn.RegionScene.NorthBorders.Count == 1)// && 2) 625 if (rootConn.RegionScene.NorthBorders.Count == 1)// && 2)
514 { 626 {
515 //compound border 627 //compound border
516 // already locked above 628 // already locked above
517 conn.RegionScene.NorthBorders[0].BorderLine.Z += (int)Constants.RegionSize; 629 rootConn.RegionScene.NorthBorders[0].BorderLine.Z += (int)Constants.RegionSize;
630
631 lock (rootConn.RegionScene.EastBorders)
632 rootConn.RegionScene.EastBorders[0].BorderLine.Y += (int)Constants.RegionSize;
518 633
519 lock (conn.RegionScene.EastBorders) 634 lock (rootConn.RegionScene.WestBorders)
520 conn.RegionScene.EastBorders[0].BorderLine.Y += (int)Constants.RegionSize; 635 rootConn.RegionScene.WestBorders[0].BorderLine.Y += (int)Constants.RegionSize;
521 lock (conn.RegionScene.WestBorders)
522 conn.RegionScene.WestBorders[0].BorderLine.Y += (int)Constants.RegionSize;
523 } 636 }
524 } 637 }
525 638
526 lock (scene.SouthBorders) 639 lock (scene.SouthBorders)
527 { 640 {
528 scene.SouthBorders[0].BorderLine.Z = (int)((scene.RegionInfo.RegionLocY - conn.RegionScene.RegionInfo.RegionLocY) * (int)Constants.RegionSize); //auto teleport south 641 scene.SouthBorders[0].BorderLine.Z = (int)((scene.RegionInfo.RegionLocY - rootConn.RegionScene.RegionInfo.RegionLocY) * (int)Constants.RegionSize); //auto teleport south
529 scene.SouthBorders[0].TriggerRegionX = conn.RegionScene.RegionInfo.RegionLocX; 642 scene.SouthBorders[0].TriggerRegionX = rootConn.RegionScene.RegionInfo.RegionLocX;
530 scene.SouthBorders[0].TriggerRegionY = conn.RegionScene.RegionInfo.RegionLocY; 643 scene.SouthBorders[0].TriggerRegionY = rootConn.RegionScene.RegionInfo.RegionLocY;
531 } 644 }
532 645
533 lock (conn.RegionScene.EastBorders) 646 lock (rootConn.RegionScene.EastBorders)
534 { 647 {
535 if (conn.RegionScene.EastBorders.Count == 1)// && conn.RegionScene.EastBorders.Count == 2) 648 if (rootConn.RegionScene.EastBorders.Count == 1)// && conn.RegionScene.EastBorders.Count == 2)
536 { 649 {
537 650
538 conn.RegionScene.EastBorders[0].BorderLine.Z += (int)Constants.RegionSize; 651 rootConn.RegionScene.EastBorders[0].BorderLine.Z += (int)Constants.RegionSize;
539 lock (conn.RegionScene.NorthBorders)
540 conn.RegionScene.NorthBorders[0].BorderLine.Y += (int)Constants.RegionSize;
541 lock (conn.RegionScene.SouthBorders)
542 conn.RegionScene.SouthBorders[0].BorderLine.Y += (int)Constants.RegionSize;
543 652
653 lock (rootConn.RegionScene.NorthBorders)
654 rootConn.RegionScene.NorthBorders[0].BorderLine.Y += (int)Constants.RegionSize;
544 655
656 lock (rootConn.RegionScene.SouthBorders)
657 rootConn.RegionScene.SouthBorders[0].BorderLine.Y += (int)Constants.RegionSize;
545 } 658 }
546 } 659 }
547 660
548 lock (scene.WestBorders) 661 lock (scene.WestBorders)
549 { 662 {
550 scene.WestBorders[0].BorderLine.Z = (int)((scene.RegionInfo.RegionLocX - conn.RegionScene.RegionInfo.RegionLocX) * (int)Constants.RegionSize); //auto teleport West 663 scene.WestBorders[0].BorderLine.Z = (int)((scene.RegionInfo.RegionLocX - rootConn.RegionScene.RegionInfo.RegionLocX) * (int)Constants.RegionSize); //auto teleport West
551 scene.WestBorders[0].TriggerRegionX = conn.RegionScene.RegionInfo.RegionLocX; 664 scene.WestBorders[0].TriggerRegionX = rootConn.RegionScene.RegionInfo.RegionLocX;
552 scene.WestBorders[0].TriggerRegionY = conn.RegionScene.RegionInfo.RegionLocY; 665 scene.WestBorders[0].TriggerRegionY = rootConn.RegionScene.RegionInfo.RegionLocY;
553 } 666 }
554 667
555 /* 668 /*
@@ -568,46 +681,50 @@ namespace OpenSim.Region.RegionCombinerModule
568 scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised()); 681 scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
569 //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised()); 682 //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
570 scene.BordersLocked = false; 683 scene.BordersLocked = false;
571 conn.RegionScene.BordersLocked = false; 684 rootConn.RegionScene.BordersLocked = false;
572 685
573 if (conn.ClientEventForwarder != null) 686 if (rootConn.ClientEventForwarder != null)
574 conn.ClientEventForwarder.AddSceneToEventForwarding(scene); 687 rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene);
575 688
576 return true; 689 return true;
577 690
578 //scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset,extents); 691 //scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset,extents);
579
580 } 692 }
581 693
582 private void DoWorkForRootRegion(RegionConnections regionConnections, Scene scene) 694 private void DoWorkForRootRegion(RegionConnections rootConn, Scene scene)
583 { 695 {
696 m_log.DebugFormat("[REGION COMBINER MODULE]: Adding root region {0}", scene.RegionInfo.RegionName);
697
584 RegionData rdata = new RegionData(); 698 RegionData rdata = new RegionData();
585 rdata.Offset = Vector3.Zero; 699 rdata.Offset = Vector3.Zero;
586 rdata.RegionId = scene.RegionInfo.originRegionID; 700 rdata.RegionId = scene.RegionInfo.originRegionID;
587 rdata.RegionScene = scene; 701 rdata.RegionScene = scene;
588 // save it's land channel 702 // save it's land channel
589 regionConnections.RegionLandChannel = scene.LandChannel; 703 rootConn.RegionLandChannel = scene.LandChannel;
590 704
591 // Substitue our landchannel 705 // Substitue our landchannel
592 RegionCombinerLargeLandChannel lnd = new RegionCombinerLargeLandChannel(rdata, scene.LandChannel, 706 RegionCombinerLargeLandChannel lnd = new RegionCombinerLargeLandChannel(rdata, scene.LandChannel,
593 regionConnections.ConnectedRegions); 707 rootConn.ConnectedRegions);
708
594 scene.LandChannel = lnd; 709 scene.LandChannel = lnd;
710
595 // Forward the permissions modules of each of the connected regions to the root region 711 // Forward the permissions modules of each of the connected regions to the root region
596 lock (m_regions) 712 lock (m_regions)
597 { 713 {
598 foreach (RegionData r in regionConnections.ConnectedRegions) 714 foreach (RegionData r in rootConn.ConnectedRegions)
599 { 715 {
600 ForwardPermissionRequests(regionConnections, r.RegionScene); 716 ForwardPermissionRequests(rootConn, r.RegionScene);
601 } 717 }
602 }
603 // Create the root region's Client Event Forwarder
604 regionConnections.ClientEventForwarder = new RegionCombinerClientEventForwarder(regionConnections);
605
606 // Sets up the CoarseLocationUpdate forwarder for this root region
607 scene.EventManager.OnNewPresence += SetCourseLocationDelegate;
608 718
609 // Adds this root region to a dictionary of regions that are connectable 719 // Create the root region's Client Event Forwarder
610 m_regions.Add(scene.RegionInfo.originRegionID, regionConnections); 720 rootConn.ClientEventForwarder = new RegionCombinerClientEventForwarder(rootConn);
721
722 // Sets up the CoarseLocationUpdate forwarder for this root region
723 scene.EventManager.OnNewPresence += SetCourseLocationDelegate;
724
725 // Adds this root region to a dictionary of regions that are connectable
726 m_regions.Add(scene.RegionInfo.originRegionID, rootConn);
727 }
611 } 728 }
612 729
613 private void SetCourseLocationDelegate(ScenePresence presence) 730 private void SetCourseLocationDelegate(ScenePresence presence)
@@ -864,6 +981,7 @@ namespace OpenSim.Region.RegionCombinerModule
864 return true; 981 return true;
865 } 982 }
866 } 983 }
984
867 oborder = null; 985 oborder = null;
868 return false; 986 return false;
869 } 987 }
@@ -873,14 +991,19 @@ namespace OpenSim.Region.RegionCombinerModule
873 pPosition = pPosition/(int) Constants.RegionSize; 991 pPosition = pPosition/(int) Constants.RegionSize;
874 int OffsetX = (int) pPosition.X; 992 int OffsetX = (int) pPosition.X;
875 int OffsetY = (int) pPosition.Y; 993 int OffsetY = (int) pPosition.Y;
876 foreach (RegionConnections regConn in m_regions.Values) 994
995 lock (m_regions)
877 { 996 {
878 foreach (RegionData reg in regConn.ConnectedRegions) 997 foreach (RegionConnections regConn in m_regions.Values)
879 { 998 {
880 if (reg.Offset.X == OffsetX && reg.Offset.Y == OffsetY) 999 foreach (RegionData reg in regConn.ConnectedRegions)
881 return reg; 1000 {
1001 if (reg.Offset.X == OffsetX && reg.Offset.Y == OffsetY)
1002 return reg;
1003 }
882 } 1004 }
883 } 1005 }
1006
884 return new RegionData(); 1007 return new RegionData();
885 } 1008 }
886 1009
@@ -936,18 +1059,19 @@ namespace OpenSim.Region.RegionCombinerModule
936 } 1059 }
937 1060
938 #region console commands 1061 #region console commands
1062
939 public void FixPhantoms(string module, string[] cmdparams) 1063 public void FixPhantoms(string module, string[] cmdparams)
940 { 1064 {
941 List<Scene> scenes = new List<Scene>(m_startingScenes.Values); 1065 List<Scene> scenes = new List<Scene>(m_startingScenes.Values);
1066
942 foreach (Scene s in scenes) 1067 foreach (Scene s in scenes)
943 { 1068 {
944 s.ForEachSOG(delegate(SceneObjectGroup e) 1069 MainConsole.Instance.OutputFormat("Fixing phantoms for {0}", s.RegionInfo.RegionName);
945 { 1070
946 e.AbsolutePosition = e.AbsolutePosition; 1071 s.ForEachSOG(so => so.AbsolutePosition = so.AbsolutePosition);
947 }
948 );
949 } 1072 }
950 } 1073 }
1074
951 #endregion 1075 #endregion
952 } 1076 }
953} 1077}
diff --git a/OpenSim/Region/RegionCombinerModule/RegionConnections.cs b/OpenSim/Region/RegionCombinerModule/RegionConnections.cs
index 3aa9f20..fba51d2 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionConnections.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionConnections.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using OpenMetaverse; 30using OpenMetaverse;
31using OpenSim.Framework;
31using OpenSim.Region.Framework.Interfaces; 32using OpenSim.Region.Framework.Interfaces;
32using OpenSim.Region.Framework.Scenes; 33using OpenSim.Region.Framework.Scenes;
33 34
@@ -49,17 +50,45 @@ namespace OpenSim.Region.RegionCombinerModule
49 /// LargeLandChannel for combined region 50 /// LargeLandChannel for combined region
50 /// </summary> 51 /// </summary>
51 public ILandChannel RegionLandChannel; 52 public ILandChannel RegionLandChannel;
53
54 /// <summary>
55 /// The x map co-ordinate for this region (where each co-ordinate is a Constants.RegionSize block).
56 /// </summary>
52 public uint X; 57 public uint X;
58
59 /// <summary>
60 /// The y co-ordinate for this region (where each cor-odinate is a Constants.RegionSize block).
61 /// </summary>
53 public uint Y; 62 public uint Y;
54 public int XEnd; 63
55 public int YEnd; 64 /// <summary>
65 /// The X meters position of this connection.
66 /// </summary>
67 public uint PosX { get { return X * Constants.RegionSize; } }
68
69 /// <summary>
70 /// The Y meters co-ordinate of this connection.
71 /// </summary>
72 public uint PosY { get { return Y * Constants.RegionSize; } }
73
74 /// <summary>
75 /// The size of the megaregion in meters.
76 /// </summary>
77 public uint XEnd;
78
79 /// <summary>
80 /// The size of the megaregion in meters.
81 /// </summary>
82 public uint YEnd;
83
56 public List<RegionData> ConnectedRegions; 84 public List<RegionData> ConnectedRegions;
57 public RegionCombinerPermissionModule PermissionModule; 85 public RegionCombinerPermissionModule PermissionModule;
58 public RegionCombinerClientEventForwarder ClientEventForwarder; 86 public RegionCombinerClientEventForwarder ClientEventForwarder;
87
59 public void UpdateExtents(Vector3 extents) 88 public void UpdateExtents(Vector3 extents)
60 { 89 {
61 XEnd = (int)extents.X; 90 XEnd = (uint)extents.X;
62 YEnd = (int)extents.Y; 91 YEnd = (uint)extents.Y;
63 } 92 }
64 } 93 }
65} \ No newline at end of file 94} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptApi.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptApi.cs
index bb5bacc..2027ca6 100644
--- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptApi.cs
+++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptApi.cs
@@ -27,17 +27,22 @@
27 27
28using System; 28using System;
29using OpenMetaverse; 29using OpenMetaverse;
30using OpenSim.Framework;
30using OpenSim.Region.Framework.Scenes; 31using OpenSim.Region.Framework.Scenes;
31 32
32
33namespace OpenSim.Region.ScriptEngine.Interfaces 33namespace OpenSim.Region.ScriptEngine.Interfaces
34{ 34{
35 public interface IScriptApi 35 public interface IScriptApi
36 { 36 {
37 // 37 /// <summary>
38 // Each API has an identifier, which is used to load the 38 /// Initialize the API
39 // proper runtime assembly at load time. 39 /// </summary>
40 // 40 /// <remarks>
41 void Initialize(IScriptEngine engine, SceneObjectPart part, uint localID, UUID item); 41 /// Each API has an identifier, which is used to load the
42 /// proper runtime assembly at load time.
43 /// <param name='engine'>/param>
44 /// <param name='part'></param>
45 /// <param name='item'></param>
46 void Initialize(IScriptEngine engine, SceneObjectPart part, TaskInventoryItem item);
42 } 47 }
43} 48} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
index b04f6b6..ec13b6c 100644
--- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
@@ -64,6 +64,16 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
64 bool Running { get; set; } 64 bool Running { get; set; }
65 65
66 /// <summary> 66 /// <summary>
67 /// Gets or sets a value indicating whether this
68 /// <see cref="OpenSim.Region.ScriptEngine.Interfaces.IScriptInstance"/> is run.
69 /// For viewer script editor control
70 /// </summary>
71 /// <value>
72 /// <c>true</c> if run; otherwise, <c>false</c>.
73 /// </value>
74 bool Run { get; set; }
75
76 /// <summary>
67 /// Is the script suspended? 77 /// Is the script suspended?
68 /// </summary> 78 /// </summary>
69 bool Suspended { get; set; } 79 bool Suspended { get; set; }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/ApiManager.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/ApiManager.cs
index 47ed6ba..684138f 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/ApiManager.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/ApiManager.cs
@@ -29,42 +29,43 @@ using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Reflection; 31using System.Reflection;
32using log4net;
32using OpenSim.Region.ScriptEngine.Interfaces; 33using OpenSim.Region.ScriptEngine.Interfaces;
33 34
34namespace OpenSim.Region.ScriptEngine.Shared.Api 35namespace OpenSim.Region.ScriptEngine.Shared.Api
35{ 36{
36 public class ApiManager 37 public class ApiManager
37 { 38 {
39// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
40
38 private Dictionary<string,Type> m_Apis = new Dictionary<string,Type>(); 41 private Dictionary<string,Type> m_Apis = new Dictionary<string,Type>();
39 42
40 public string[] GetApis() 43 public string[] GetApis()
41 { 44 {
42 if (m_Apis.Count > 0) 45 if (m_Apis.Count <= 0)
43 { 46 {
44 List<string> l = new List<string>(m_Apis.Keys); 47 Assembly a = Assembly.GetExecutingAssembly();
45 return l.ToArray();
46 }
47 48
48 Assembly a = Assembly.GetExecutingAssembly(); 49 Type[] types = a.GetExportedTypes();
49 50
50 Type[] types = a.GetExportedTypes(); 51 foreach (Type t in types)
51
52 foreach (Type t in types)
53 {
54 string name = t.ToString();
55 int idx = name.LastIndexOf('.');
56 if (idx != -1)
57 name = name.Substring(idx+1);
58
59 if (name.EndsWith("_Api"))
60 { 52 {
61 name = name.Substring(0, name.Length - 4); 53 string name = t.ToString();
62 m_Apis[name] = t; 54 int idx = name.LastIndexOf('.');
55 if (idx != -1)
56 name = name.Substring(idx+1);
57
58 if (name.EndsWith("_Api"))
59 {
60 name = name.Substring(0, name.Length - 4);
61 m_Apis[name] = t;
62 }
63 } 63 }
64 } 64 }
65 65
66 List<string> ret = new List<string>(m_Apis.Keys); 66// m_log.DebugFormat("[API MANAGER]: Found {0} apis", m_Apis.Keys.Count);
67 return ret.ToArray(); 67
68 return new List<string>(m_Apis.Keys).ToArray();
68 } 69 }
69 70
70 public IScriptApi CreateApi(string api) 71 public IScriptApi CreateApi(string api)
@@ -76,4 +77,4 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
76 return ret; 77 return ret;
77 } 78 }
78 } 79 }
79} 80} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
index 3cbdde5..693992a 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
@@ -233,17 +233,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
233 m_Timer[engine].UnSetTimerEvents(localID, itemID); 233 m_Timer[engine].UnSetTimerEvents(localID, itemID);
234 234
235 // Remove from: HttpRequest 235 // Remove from: HttpRequest
236 IHttpRequestModule iHttpReq = 236 IHttpRequestModule iHttpReq = engine.World.RequestModuleInterface<IHttpRequestModule>();
237 engine.World.RequestModuleInterface<IHttpRequestModule>(); 237 if (iHttpReq != null)
238 iHttpReq.StopHttpRequest(localID, itemID); 238 iHttpReq.StopHttpRequest(localID, itemID);
239 239
240 IWorldComm comms = engine.World.RequestModuleInterface<IWorldComm>(); 240 IWorldComm comms = engine.World.RequestModuleInterface<IWorldComm>();
241 if (comms != null) 241 if (comms != null)
242 comms.DeleteListener(itemID); 242 comms.DeleteListener(itemID);
243 243
244 IXMLRPC xmlrpc = engine.World.RequestModuleInterface<IXMLRPC>(); 244 IXMLRPC xmlrpc = engine.World.RequestModuleInterface<IXMLRPC>();
245 xmlrpc.DeleteChannels(itemID); 245 if (xmlrpc != null)
246 xmlrpc.CancelSRDRequests(itemID); 246 {
247 xmlrpc.DeleteChannels(itemID);
248 xmlrpc.CancelSRDRequests(itemID);
249 }
247 250
248 // Remove Sensors 251 // Remove Sensors
249 m_SensorRepeat[engine].UnSetSenseRepeaterEvents(localID, itemID); 252 m_SensorRepeat[engine].UnSetSenseRepeaterEvents(localID, itemID);
@@ -325,7 +328,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
325 { 328 {
326 List<Object> data = new List<Object>(); 329 List<Object> data = new List<Object>();
327 330
328 Object[] listeners=m_Listener[engine].GetSerializationData(itemID); 331 Object[] listeners = m_Listener[engine].GetSerializationData(itemID);
329 if (listeners.Length > 0) 332 if (listeners.Length > 0)
330 { 333 {
331 data.Add("listener"); 334 data.Add("listener");
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs
index 489c1c6..b5fa6de 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs
@@ -59,16 +59,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
59 { 59 {
60 internal IScriptEngine m_ScriptEngine; 60 internal IScriptEngine m_ScriptEngine;
61 internal SceneObjectPart m_host; 61 internal SceneObjectPart m_host;
62 internal uint m_localID; 62 internal TaskInventoryItem m_item;
63 internal UUID m_itemID;
64 internal bool m_CMFunctionsEnabled = false; 63 internal bool m_CMFunctionsEnabled = false;
65 64
66 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) 65 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item)
67 { 66 {
68 m_ScriptEngine = ScriptEngine; 67 m_ScriptEngine = ScriptEngine;
69 m_host = host; 68 m_host = host;
70 m_localID = localID; 69 m_item = item;
71 m_itemID = itemID;
72 70
73 if (m_ScriptEngine.Config.GetBoolean("AllowCareminsterFunctions", false)) 71 if (m_ScriptEngine.Config.GetBoolean("AllowCareminsterFunctions", false))
74 m_CMFunctionsEnabled = true; 72 m_CMFunctionsEnabled = true;
@@ -95,7 +93,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
95 public string cmDetectedCountry(int number) 93 public string cmDetectedCountry(int number)
96 { 94 {
97 m_host.AddScriptLPS(1); 95 m_host.AddScriptLPS(1);
98 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, number); 96 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
99 if (detectedParams == null) 97 if (detectedParams == null)
100 return String.Empty; 98 return String.Empty;
101 return detectedParams.Country; 99 return detectedParams.Country;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 595dd8a..6ec3081 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -88,8 +88,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
88 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 88 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
89 protected IScriptEngine m_ScriptEngine; 89 protected IScriptEngine m_ScriptEngine;
90 protected SceneObjectPart m_host; 90 protected SceneObjectPart m_host;
91 protected uint m_localID; 91
92 protected UUID m_itemID; 92 /// <summary>
93 /// The item that hosts this script
94 /// </summary>
95 protected TaskInventoryItem m_item;
96
93 protected bool throwErrorOnNotImplemented = true; 97 protected bool throwErrorOnNotImplemented = true;
94 protected AsyncCommandManager AsyncCommands = null; 98 protected AsyncCommandManager AsyncCommands = null;
95 protected float m_ScriptDelayFactor = 1.0f; 99 protected float m_ScriptDelayFactor = 1.0f;
@@ -107,6 +111,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
107 protected IUrlModule m_UrlModule = null; 111 protected IUrlModule m_UrlModule = null;
108 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = 112 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache =
109 new Dictionary<UUID, UserInfoCacheEntry>(); 113 new Dictionary<UUID, UserInfoCacheEntry>();
114 protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp.
110 115
111// protected Timer m_ShoutSayTimer; 116// protected Timer m_ShoutSayTimer;
112 protected int m_SayShoutCount = 0; 117 protected int m_SayShoutCount = 0;
@@ -134,7 +139,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
134 {"TURNRIGHT", "Turning Right"} 139 {"TURNRIGHT", "Turning Right"}
135 }; 140 };
136 141
137 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) 142 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item)
138 { 143 {
139/* 144/*
140 m_ShoutSayTimer = new Timer(1000); 145 m_ShoutSayTimer = new Timer(1000);
@@ -146,10 +151,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
146 151
147 m_ScriptEngine = ScriptEngine; 152 m_ScriptEngine = ScriptEngine;
148 m_host = host; 153 m_host = host;
149 m_localID = localID; 154 m_item = item;
150 m_itemID = itemID;
151 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false); 155 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
152 156
157 LoadLimits(); // read script limits from config.
158
159 m_TransferModule =
160 m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>();
161 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>();
162
163 AsyncCommands = new AsyncCommandManager(ScriptEngine);
164 }
165
166 /* load configuration items that affect script, object and run-time behavior. */
167 private void LoadLimits()
168 {
153 m_ScriptDelayFactor = 169 m_ScriptDelayFactor =
154 m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f); 170 m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f);
155 m_ScriptDistanceFactor = 171 m_ScriptDistanceFactor =
@@ -162,12 +178,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
162 m_ScriptEngine.Config.GetInt("NotecardLineReadCharsMax", 255); 178 m_ScriptEngine.Config.GetInt("NotecardLineReadCharsMax", 255);
163 if (m_notecardLineReadCharsMax > 65535) 179 if (m_notecardLineReadCharsMax > 65535)
164 m_notecardLineReadCharsMax = 65535; 180 m_notecardLineReadCharsMax = 65535;
165 181 // load limits for particular subsystems.
166 m_TransferModule = 182 IConfig SMTPConfig;
167 m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>(); 183 if ((SMTPConfig = m_ScriptEngine.ConfigSource.Configs["SMTP"]) != null) {
168 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>(); 184 // there's an smtp config, so load in the snooze time.
169 185 EMAIL_PAUSE_TIME = SMTPConfig.GetInt("email_pause_time", EMAIL_PAUSE_TIME);
170 AsyncCommands = new AsyncCommandManager(ScriptEngine); 186 }
171 } 187 }
172 188
173 public override Object InitializeLifetimeService() 189 public override Object InitializeLifetimeService()
@@ -199,7 +215,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
199 [DebuggerNonUserCode] 215 [DebuggerNonUserCode]
200 public void state(string newState) 216 public void state(string newState)
201 { 217 {
202 m_ScriptEngine.SetState(m_itemID, newState); 218 m_ScriptEngine.SetState(m_item.ItemID, newState);
203 } 219 }
204 220
205 /// <summary> 221 /// <summary>
@@ -210,7 +226,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
210 public void llResetScript() 226 public void llResetScript()
211 { 227 {
212 m_host.AddScriptLPS(1); 228 m_host.AddScriptLPS(1);
213 m_ScriptEngine.ApiResetScript(m_itemID); 229 m_ScriptEngine.ApiResetScript(m_item.ItemID);
214 } 230 }
215 231
216 public void llResetOtherScript(string name) 232 public void llResetOtherScript(string name)
@@ -219,7 +235,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
219 235
220 m_host.AddScriptLPS(1); 236 m_host.AddScriptLPS(1);
221 237
222 if ((item = ScriptByName(name)) != UUID.Zero) 238 if ((item = GetScriptByName(name)) != UUID.Zero)
223 m_ScriptEngine.ResetScript(item); 239 m_ScriptEngine.ResetScript(item);
224 else 240 else
225 ShoutError("llResetOtherScript: script "+name+" not found"); 241 ShoutError("llResetOtherScript: script "+name+" not found");
@@ -231,7 +247,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
231 247
232 m_host.AddScriptLPS(1); 248 m_host.AddScriptLPS(1);
233 249
234 if ((item = ScriptByName(name)) != UUID.Zero) 250 if ((item = GetScriptByName(name)) != UUID.Zero)
235 { 251 {
236 return m_ScriptEngine.GetScriptState(item) ?1:0; 252 return m_ScriptEngine.GetScriptState(item) ?1:0;
237 } 253 }
@@ -253,7 +269,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
253 // These functions are supposed to be robust, 269 // These functions are supposed to be robust,
254 // so get the state one step at a time. 270 // so get the state one step at a time.
255 271
256 if ((item = ScriptByName(name)) != UUID.Zero) 272 if ((item = GetScriptByName(name)) != UUID.Zero)
257 { 273 {
258 m_ScriptEngine.SetScriptState(item, run == 0 ? false : true); 274 m_ScriptEngine.SetScriptState(item, run == 0 ? false : true);
259 } 275 }
@@ -362,77 +378,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
362 } 378 }
363 } 379 }
364 380
365 protected UUID InventorySelf()
366 {
367 UUID invItemID = new UUID();
368 bool unlock = false;
369 if (!m_host.TaskInventory.IsReadLockedByMe())
370 {
371 m_host.TaskInventory.LockItemsForRead(true);
372 unlock = true;
373 }
374 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
375 {
376 if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID)
377 {
378 invItemID = inv.Key;
379 break;
380 }
381 }
382 if (unlock)
383 {
384 m_host.TaskInventory.LockItemsForRead(false);
385 }
386 return invItemID;
387 }
388
389 protected UUID InventoryKey(string name, int type) 381 protected UUID InventoryKey(string name, int type)
390 { 382 {
391 m_host.AddScriptLPS(1); 383 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name);
392 m_host.TaskInventory.LockItemsForRead(true);
393
394 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
395 {
396 if (inv.Value.Name == name)
397 {
398 m_host.TaskInventory.LockItemsForRead(false);
399
400 if (inv.Value.Type != type)
401 {
402 return UUID.Zero;
403 }
404
405 return inv.Value.AssetID;
406 }
407 }
408
409 m_host.TaskInventory.LockItemsForRead(false);
410 return UUID.Zero;
411 }
412
413 protected UUID InventoryKey(string name)
414 {
415 m_host.AddScriptLPS(1);
416
417
418 m_host.TaskInventory.LockItemsForRead(true);
419 384
420 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 385 if (item != null && item.Type == type)
421 { 386 return item.AssetID;
422 if (inv.Value.Name == name) 387 else
423 { 388 return UUID.Zero;
424 m_host.TaskInventory.LockItemsForRead(false);
425 return inv.Value.AssetID;
426 }
427 }
428
429 m_host.TaskInventory.LockItemsForRead(false);
430
431
432 return UUID.Zero;
433 } 389 }
434 390
435
436 /// <summary> 391 /// <summary>
437 /// accepts a valid UUID, -or- a name of an inventory item. 392 /// accepts a valid UUID, -or- a name of an inventory item.
438 /// Returns a valid UUID or UUID.Zero if key invalid and item not found 393 /// Returns a valid UUID or UUID.Zero if key invalid and item not found
@@ -442,19 +397,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
442 /// <returns></returns> 397 /// <returns></returns>
443 protected UUID KeyOrName(string k) 398 protected UUID KeyOrName(string k)
444 { 399 {
445 UUID key = UUID.Zero; 400 UUID key;
446 401
447 // if we can parse the string as a key, use it. 402 // if we can parse the string as a key, use it.
448 if (UUID.TryParse(k, out key))
449 {
450 return key;
451 }
452 // else try to locate the name in inventory of object. found returns key, 403 // else try to locate the name in inventory of object. found returns key,
453 // not found returns UUID.Zero which will translate to the default particle texture 404 // not found returns UUID.Zero
454 else 405 if (!UUID.TryParse(k, out key))
455 { 406 {
456 return InventoryKey(k); 407 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(k);
408
409 if (item != null)
410 key = item.AssetID;
411 else
412 key = UUID.Zero;
457 } 413 }
414
415 return key;
458 } 416 }
459 417
460 // convert a LSL_Rotation to a Quaternion 418 // convert a LSL_Rotation to a Quaternion
@@ -559,15 +517,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
559 return LSL_Vector.Norm(v); 517 return LSL_Vector.Norm(v);
560 } 518 }
561 519
562 public LSL_Float llVecDist(LSL_Vector a, LSL_Vector b) 520 private double VecDist(LSL_Vector a, LSL_Vector b)
563 { 521 {
564 m_host.AddScriptLPS(1);
565 double dx = a.x - b.x; 522 double dx = a.x - b.x;
566 double dy = a.y - b.y; 523 double dy = a.y - b.y;
567 double dz = a.z - b.z; 524 double dz = a.z - b.z;
568 return Math.Sqrt(dx * dx + dy * dy + dz * dz); 525 return Math.Sqrt(dx * dx + dy * dy + dz * dz);
569 } 526 }
570 527
528 public LSL_Float llVecDist(LSL_Vector a, LSL_Vector b)
529 {
530 m_host.AddScriptLPS(1);
531 return VecDist(a, b);
532 }
533
571 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke 534 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
572 535
573 // Utility function for llRot2Euler 536 // Utility function for llRot2Euler
@@ -1010,7 +973,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1010 UUID.TryParse(ID, out keyID); 973 UUID.TryParse(ID, out keyID);
1011 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); 974 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
1012 if (wComm != null) 975 if (wComm != null)
1013 return wComm.Listen(m_localID, m_itemID, m_host.UUID, channelID, name, keyID, msg); 976 return wComm.Listen(m_host.LocalId, m_item.ItemID, m_host.UUID, channelID, name, keyID, msg);
1014 else 977 else
1015 return -1; 978 return -1;
1016 } 979 }
@@ -1020,7 +983,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1020 m_host.AddScriptLPS(1); 983 m_host.AddScriptLPS(1);
1021 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); 984 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
1022 if (wComm != null) 985 if (wComm != null)
1023 wComm.ListenControl(m_itemID, number, active); 986 wComm.ListenControl(m_item.ItemID, number, active);
1024 } 987 }
1025 988
1026 public void llListenRemove(int number) 989 public void llListenRemove(int number)
@@ -1028,7 +991,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1028 m_host.AddScriptLPS(1); 991 m_host.AddScriptLPS(1);
1029 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); 992 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
1030 if (wComm != null) 993 if (wComm != null)
1031 wComm.ListenRemove(m_itemID, number); 994 wComm.ListenRemove(m_item.ItemID, number);
1032 } 995 }
1033 996
1034 public void llSensor(string name, string id, int type, double range, double arc) 997 public void llSensor(string name, string id, int type, double range, double arc)
@@ -1037,7 +1000,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1037 UUID keyID = UUID.Zero; 1000 UUID keyID = UUID.Zero;
1038 UUID.TryParse(id, out keyID); 1001 UUID.TryParse(id, out keyID);
1039 1002
1040 AsyncCommands.SensorRepeatPlugin.SenseOnce(m_localID, m_itemID, name, keyID, type, range, arc, m_host); 1003 AsyncCommands.SensorRepeatPlugin.SenseOnce(m_host.LocalId, m_item.ItemID, name, keyID, type, range, arc, m_host);
1041 } 1004 }
1042 1005
1043 public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate) 1006 public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate)
@@ -1046,13 +1009,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1046 UUID keyID = UUID.Zero; 1009 UUID keyID = UUID.Zero;
1047 UUID.TryParse(id, out keyID); 1010 UUID.TryParse(id, out keyID);
1048 1011
1049 AsyncCommands.SensorRepeatPlugin.SetSenseRepeatEvent(m_localID, m_itemID, name, keyID, type, range, arc, rate, m_host); 1012 AsyncCommands.SensorRepeatPlugin.SetSenseRepeatEvent(m_host.LocalId, m_item.ItemID, name, keyID, type, range, arc, rate, m_host);
1050 } 1013 }
1051 1014
1052 public void llSensorRemove() 1015 public void llSensorRemove()
1053 { 1016 {
1054 m_host.AddScriptLPS(1); 1017 m_host.AddScriptLPS(1);
1055 AsyncCommands.SensorRepeatPlugin.UnSetSenseRepeaterEvents(m_localID, m_itemID); 1018 AsyncCommands.SensorRepeatPlugin.UnSetSenseRepeaterEvents(m_host.LocalId, m_item.ItemID);
1056 } 1019 }
1057 1020
1058 public string resolveName(UUID objecUUID) 1021 public string resolveName(UUID objecUUID)
@@ -1093,7 +1056,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1093 public LSL_String llDetectedName(int number) 1056 public LSL_String llDetectedName(int number)
1094 { 1057 {
1095 m_host.AddScriptLPS(1); 1058 m_host.AddScriptLPS(1);
1096 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, number); 1059 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
1097 if (detectedParams == null) 1060 if (detectedParams == null)
1098 return String.Empty; 1061 return String.Empty;
1099 return detectedParams.Name; 1062 return detectedParams.Name;
@@ -1102,7 +1065,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1102 public LSL_String llDetectedKey(int number) 1065 public LSL_String llDetectedKey(int number)
1103 { 1066 {
1104 m_host.AddScriptLPS(1); 1067 m_host.AddScriptLPS(1);
1105 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, number); 1068 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
1106 if (detectedParams == null) 1069 if (detectedParams == null)
1107 return String.Empty; 1070 return String.Empty;
1108 return detectedParams.Key.ToString(); 1071 return detectedParams.Key.ToString();
@@ -1111,7 +1074,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1111 public LSL_String llDetectedOwner(int number) 1074 public LSL_String llDetectedOwner(int number)
1112 { 1075 {
1113 m_host.AddScriptLPS(1); 1076 m_host.AddScriptLPS(1);
1114 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, number); 1077 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
1115 if (detectedParams == null) 1078 if (detectedParams == null)
1116 return String.Empty; 1079 return String.Empty;
1117 return detectedParams.Owner.ToString(); 1080 return detectedParams.Owner.ToString();
@@ -1120,7 +1083,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1120 public LSL_Integer llDetectedType(int number) 1083 public LSL_Integer llDetectedType(int number)
1121 { 1084 {
1122 m_host.AddScriptLPS(1); 1085 m_host.AddScriptLPS(1);
1123 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, number); 1086 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
1124 if (detectedParams == null) 1087 if (detectedParams == null)
1125 return 0; 1088 return 0;
1126 return new LSL_Integer(detectedParams.Type); 1089 return new LSL_Integer(detectedParams.Type);
@@ -1129,7 +1092,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1129 public LSL_Vector llDetectedPos(int number) 1092 public LSL_Vector llDetectedPos(int number)
1130 { 1093 {
1131 m_host.AddScriptLPS(1); 1094 m_host.AddScriptLPS(1);
1132 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, number); 1095 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
1133 if (detectedParams == null) 1096 if (detectedParams == null)
1134 return new LSL_Vector(); 1097 return new LSL_Vector();
1135 return detectedParams.Position; 1098 return detectedParams.Position;
@@ -1138,7 +1101,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1138 public LSL_Vector llDetectedVel(int number) 1101 public LSL_Vector llDetectedVel(int number)
1139 { 1102 {
1140 m_host.AddScriptLPS(1); 1103 m_host.AddScriptLPS(1);
1141 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, number); 1104 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
1142 if (detectedParams == null) 1105 if (detectedParams == null)
1143 return new LSL_Vector(); 1106 return new LSL_Vector();
1144 return detectedParams.Velocity; 1107 return detectedParams.Velocity;
@@ -1147,7 +1110,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1147 public LSL_Vector llDetectedGrab(int number) 1110 public LSL_Vector llDetectedGrab(int number)
1148 { 1111 {
1149 m_host.AddScriptLPS(1); 1112 m_host.AddScriptLPS(1);
1150 DetectParams parms = m_ScriptEngine.GetDetectParams(m_itemID, number); 1113 DetectParams parms = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
1151 if (parms == null) 1114 if (parms == null)
1152 return new LSL_Vector(0, 0, 0); 1115 return new LSL_Vector(0, 0, 0);
1153 1116
@@ -1157,7 +1120,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1157 public LSL_Rotation llDetectedRot(int number) 1120 public LSL_Rotation llDetectedRot(int number)
1158 { 1121 {
1159 m_host.AddScriptLPS(1); 1122 m_host.AddScriptLPS(1);
1160 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, number); 1123 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
1161 if (detectedParams == null) 1124 if (detectedParams == null)
1162 return new LSL_Rotation(); 1125 return new LSL_Rotation();
1163 return detectedParams.Rotation; 1126 return detectedParams.Rotation;
@@ -1166,7 +1129,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1166 public LSL_Integer llDetectedGroup(int number) 1129 public LSL_Integer llDetectedGroup(int number)
1167 { 1130 {
1168 m_host.AddScriptLPS(1); 1131 m_host.AddScriptLPS(1);
1169 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, number); 1132 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
1170 if (detectedParams == null) 1133 if (detectedParams == null)
1171 return new LSL_Integer(0); 1134 return new LSL_Integer(0);
1172 if (m_host.GroupID == detectedParams.Group) 1135 if (m_host.GroupID == detectedParams.Group)
@@ -1177,7 +1140,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1177 public LSL_Integer llDetectedLinkNumber(int number) 1140 public LSL_Integer llDetectedLinkNumber(int number)
1178 { 1141 {
1179 m_host.AddScriptLPS(1); 1142 m_host.AddScriptLPS(1);
1180 DetectParams parms = m_ScriptEngine.GetDetectParams(m_itemID, number); 1143 DetectParams parms = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
1181 if (parms == null) 1144 if (parms == null)
1182 return new LSL_Integer(0); 1145 return new LSL_Integer(0);
1183 1146
@@ -1190,7 +1153,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1190 public LSL_Vector llDetectedTouchBinormal(int index) 1153 public LSL_Vector llDetectedTouchBinormal(int index)
1191 { 1154 {
1192 m_host.AddScriptLPS(1); 1155 m_host.AddScriptLPS(1);
1193 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, index); 1156 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
1194 if (detectedParams == null) 1157 if (detectedParams == null)
1195 return new LSL_Vector(); 1158 return new LSL_Vector();
1196 return detectedParams.TouchBinormal; 1159 return detectedParams.TouchBinormal;
@@ -1202,7 +1165,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1202 public LSL_Integer llDetectedTouchFace(int index) 1165 public LSL_Integer llDetectedTouchFace(int index)
1203 { 1166 {
1204 m_host.AddScriptLPS(1); 1167 m_host.AddScriptLPS(1);
1205 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, index); 1168 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
1206 if (detectedParams == null) 1169 if (detectedParams == null)
1207 return new LSL_Integer(-1); 1170 return new LSL_Integer(-1);
1208 return new LSL_Integer(detectedParams.TouchFace); 1171 return new LSL_Integer(detectedParams.TouchFace);
@@ -1214,7 +1177,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1214 public LSL_Vector llDetectedTouchNormal(int index) 1177 public LSL_Vector llDetectedTouchNormal(int index)
1215 { 1178 {
1216 m_host.AddScriptLPS(1); 1179 m_host.AddScriptLPS(1);
1217 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, index); 1180 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
1218 if (detectedParams == null) 1181 if (detectedParams == null)
1219 return new LSL_Vector(); 1182 return new LSL_Vector();
1220 return detectedParams.TouchNormal; 1183 return detectedParams.TouchNormal;
@@ -1226,7 +1189,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1226 public LSL_Vector llDetectedTouchPos(int index) 1189 public LSL_Vector llDetectedTouchPos(int index)
1227 { 1190 {
1228 m_host.AddScriptLPS(1); 1191 m_host.AddScriptLPS(1);
1229 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, index); 1192 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
1230 if (detectedParams == null) 1193 if (detectedParams == null)
1231 return new LSL_Vector(); 1194 return new LSL_Vector();
1232 return detectedParams.TouchPos; 1195 return detectedParams.TouchPos;
@@ -1238,7 +1201,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1238 public LSL_Vector llDetectedTouchST(int index) 1201 public LSL_Vector llDetectedTouchST(int index)
1239 { 1202 {
1240 m_host.AddScriptLPS(1); 1203 m_host.AddScriptLPS(1);
1241 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, index); 1204 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
1242 if (detectedParams == null) 1205 if (detectedParams == null)
1243 return new LSL_Vector(-1.0, -1.0, 0.0); 1206 return new LSL_Vector(-1.0, -1.0, 0.0);
1244 return detectedParams.TouchST; 1207 return detectedParams.TouchST;
@@ -1250,7 +1213,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1250 public LSL_Vector llDetectedTouchUV(int index) 1213 public LSL_Vector llDetectedTouchUV(int index)
1251 { 1214 {
1252 m_host.AddScriptLPS(1); 1215 m_host.AddScriptLPS(1);
1253 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, index); 1216 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
1254 if (detectedParams == null) 1217 if (detectedParams == null)
1255 return new LSL_Vector(-1.0, -1.0, 0.0); 1218 return new LSL_Vector(-1.0, -1.0, 0.0);
1256 return detectedParams.TouchUV; 1219 return detectedParams.TouchUV;
@@ -1433,6 +1396,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1433 } 1396 }
1434 } 1397 }
1435 1398
1399 private bool IsPhysical()
1400 {
1401 return ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) == (uint)PrimFlags.Physics);
1402 }
1403
1436 public LSL_Integer llGetStatus(int status) 1404 public LSL_Integer llGetStatus(int status)
1437 { 1405 {
1438 m_host.AddScriptLPS(1); 1406 m_host.AddScriptLPS(1);
@@ -1440,11 +1408,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1440 switch (status) 1408 switch (status)
1441 { 1409 {
1442 case ScriptBaseClass.STATUS_PHYSICS: 1410 case ScriptBaseClass.STATUS_PHYSICS:
1443 if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) == (uint)PrimFlags.Physics) 1411 return IsPhysical() ? 1 : 0;
1444 {
1445 return 1;
1446 }
1447 return 0;
1448 1412
1449 case ScriptBaseClass.STATUS_PHANTOM: 1413 case ScriptBaseClass.STATUS_PHANTOM:
1450 if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) == (uint)PrimFlags.Phantom) 1414 if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) == (uint)PrimFlags.Phantom)
@@ -1962,6 +1926,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1962 rgb.x = texcolor.R; 1926 rgb.x = texcolor.R;
1963 rgb.y = texcolor.G; 1927 rgb.y = texcolor.G;
1964 rgb.z = texcolor.B; 1928 rgb.z = texcolor.B;
1929
1965 return rgb; 1930 return rgb;
1966 } 1931 }
1967 else 1932 else
@@ -2196,11 +2161,68 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2196 { 2161 {
2197 m_host.AddScriptLPS(1); 2162 m_host.AddScriptLPS(1);
2198 2163
2199 SetPos(m_host, pos); 2164 SetPos(m_host, pos, true);
2200 2165
2201 ScriptSleep(200); 2166 ScriptSleep(200);
2202 } 2167 }
2203 2168
2169 /// <summary>
2170 /// Tries to move the entire object so that the root prim is within 0.1m of position. http://wiki.secondlife.com/wiki/LlSetRegionPos
2171 /// Documentation indicates that the use of x/y coordinates up to 10 meters outside the bounds of a region will work but do not specify what happens if there is no adjacent region for the object to move into.
2172 /// Uses the RegionSize constant here rather than hard-coding 266.0 to alert any developer modifying OpenSim to support variable-sized regions that this method will need tweaking.
2173 /// </summary>
2174 /// <param name="pos"></param>
2175 /// <returns>1 if successful, 0 otherwise.</returns>
2176 public LSL_Integer llSetRegionPos(LSL_Vector pos)
2177 {
2178 m_host.AddScriptLPS(1);
2179
2180 // BEGIN WORKAROUND
2181 // IF YOU GET REGION CROSSINGS WORKING WITH THIS FUNCTION, REPLACE THE WORKAROUND.
2182 //
2183 // This workaround is to prevent silent failure of this function.
2184 // According to the specification on the SL Wiki, providing a position outside of the
2185 if (pos.x < 0 || pos.x > Constants.RegionSize || pos.y < 0 || pos.y > Constants.RegionSize)
2186 {
2187 return 0;
2188 }
2189 // END WORK AROUND
2190 else if ( // this is not part of the workaround if-block because it's not related to the workaround.
2191 IsPhysical() ||
2192 m_host.ParentGroup.IsAttachment || // return FALSE if attachment
2193 (
2194 pos.x < -10.0 || // return FALSE if more than 10 meters into a west-adjacent region.
2195 pos.x > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a east-adjacent region.
2196 pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region.
2197 pos.y > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a north-adjacent region.
2198 pos.z > 4096 // return FALSE if altitude than 4096m
2199 )
2200 )
2201 {
2202 return 0;
2203 }
2204
2205 // if we reach this point, then the object is not physical, it's not an attachment, and the destination is within the valid range.
2206 // this could possibly be done in the above else-if block, but we're doing the check here to keep the code easier to read.
2207
2208 Vector3 objectPos = m_host.ParentGroup.RootPart.AbsolutePosition;
2209 LandData here = World.GetLandData((float)objectPos.X, (float)objectPos.Y);
2210 LandData there = World.GetLandData((float)pos.x, (float)pos.y);
2211
2212 // we're only checking prim limits if it's moving to a different parcel under the assumption that if the object got onto the parcel without exceeding the prim limits.
2213
2214 bool sameParcel = here.GlobalID == there.GlobalID;
2215
2216 if (!sameParcel && !World.Permissions.CanObjectEntry(m_host.UUID, false, new Vector3((float)pos.x, (float)pos.y, (float)pos.z)))
2217 {
2218 return 0;
2219 }
2220
2221 SetPos(m_host.ParentGroup.RootPart, pos, false);
2222
2223 return VecDist(pos, llGetRootPosition()) <= 0.1 ? 1 : 0;
2224 }
2225
2204 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) 2226 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
2205 // note linked setpos is capped "differently" 2227 // note linked setpos is capped "differently"
2206 private LSL_Vector SetPosAdjust(LSL_Vector start, LSL_Vector end) 2228 private LSL_Vector SetPosAdjust(LSL_Vector start, LSL_Vector end)
@@ -2232,55 +2254,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2232 return real_vec; 2254 return real_vec;
2233 } 2255 }
2234 2256
2235 public LSL_Integer llSetRegionPos(LSL_Vector pos) 2257 /// <summary>
2236 { 2258 /// set object position, optionally capping the distance.
2237 return new LSL_Integer(SetRegionPos(m_host, pos)); 2259 /// </summary>
2238 } 2260 /// <param name="part"></param>
2239 2261 /// <param name="targetPos"></param>
2240 protected int SetRegionPos(SceneObjectPart part, LSL_Vector targetPos) 2262 /// <param name="adjust">if TRUE, will cap the distance to 10m.</param>
2241 { 2263 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos, bool adjust)
2242 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2243 return 0;
2244
2245 SceneObjectGroup grp = part.ParentGroup;
2246
2247 if (grp.IsAttachment)
2248 return 0;
2249
2250 if (grp.RootPart.PhysActor != null && grp.RootPart.PhysActor.IsPhysical)
2251 return 0;
2252
2253 if (targetPos.x < -10.0f || targetPos.x >= (float)Constants.RegionSize || targetPos.y < -10.0f || targetPos.y >= (float)Constants.RegionSize || targetPos.z < 0 || targetPos.z >= 4096.0f)
2254 return 0;
2255
2256 float constrainedX = (float)targetPos.x;
2257 float constrainedY = (float)targetPos.y;
2258
2259 if (constrainedX < 0.0f)
2260 constrainedX = 0.0f;
2261 if (constrainedY < 0.0f)
2262 constrainedY = 0.0f;
2263 if (constrainedX >= (float)Constants.RegionSize)
2264 constrainedX = (float)Constants.RegionSize - 0.1f;
2265 if (constrainedY >= (float)Constants.RegionSize)
2266 constrainedY = (float)Constants.RegionSize -0.1f;
2267
2268 float ground = World.GetGroundHeight(constrainedX, constrainedY);
2269
2270 if (targetPos.z < ground)
2271 targetPos.z = ground;
2272
2273 Vector3 dest = new Vector3((float)targetPos.x, (float)targetPos.y, (float)targetPos.z);
2274
2275 if (!World.Permissions.CanObjectEntry(grp.UUID, false, dest))
2276 return 0;
2277
2278 grp.UpdateGroupPosition(dest);
2279
2280 return 1;
2281 }
2282
2283 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos)
2284 { 2264 {
2285 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) 2265 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2286 return; 2266 return;
@@ -3044,20 +3024,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3044 3024
3045 public LSL_Integer llGiveMoney(string destination, int amount) 3025 public LSL_Integer llGiveMoney(string destination, int amount)
3046 { 3026 {
3047 UUID invItemID=InventorySelf();
3048 if (invItemID == UUID.Zero)
3049 return 0;
3050
3051 m_host.AddScriptLPS(1); 3027 m_host.AddScriptLPS(1);
3052 3028
3053 m_host.TaskInventory.LockItemsForRead(true); 3029 if (m_item.PermsGranter == UUID.Zero)
3054 TaskInventoryItem item = m_host.TaskInventory[invItemID];
3055 m_host.TaskInventory.LockItemsForRead(false);
3056
3057 if (item.PermsGranter == UUID.Zero)
3058 return 0; 3030 return 0;
3059 3031
3060 if ((item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0) 3032 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
3061 { 3033 {
3062 LSLError("No permissions to give money"); 3034 LSLError("No permissions to give money");
3063 return 0; 3035 return 0;
@@ -3120,74 +3092,72 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3120 { 3092 {
3121 m_host.AddScriptLPS(1); 3093 m_host.AddScriptLPS(1);
3122 3094
3123 Util.FireAndForget(delegate (object x) 3095 Util.FireAndForget(x =>
3124 { 3096 {
3125 if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s)) 3097 if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s))
3126 return; 3098 return;
3099
3127 float dist = (float)llVecDist(llGetPos(), pos); 3100 float dist = (float)llVecDist(llGetPos(), pos);
3128 3101
3129 if (dist > m_ScriptDistanceFactor * 10.0f) 3102 if (dist > m_ScriptDistanceFactor * 10.0f)
3130 return; 3103 return;
3131 3104
3132 //Clone is thread-safe 3105 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(inventory);
3133 TaskInventoryDictionary partInventory = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
3134 3106
3135 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in partInventory) 3107 if (item == null)
3136 { 3108 {
3137 if (inv.Value.Name == inventory) 3109 llSay(0, "Could not find object " + inventory);
3138 { 3110 return;
3139 // make sure we're an object. 3111 }
3140 if (inv.Value.InvType != (int)InventoryType.Object)
3141 {
3142 llSay(0, "Unable to create requested object. Object is missing from database.");
3143 return;
3144 }
3145 3112
3146 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z); 3113 if (item.InvType != (int)InventoryType.Object)
3147 Vector3 llvel = new Vector3((float)vel.x, (float)vel.y, (float)vel.z); 3114 {
3115 llSay(0, "Unable to create requested object. Object is missing from database.");
3116 return;
3117 }
3148 3118
3149 // need the magnitude later 3119 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
3150 // float velmag = (float)Util.GetMagnitude(llvel); 3120 Vector3 llvel = new Vector3((float)vel.x, (float)vel.y, (float)vel.z);
3151 3121
3152 SceneObjectGroup new_group = World.RezObject(m_host, inv.Value, llpos, Rot2Quaternion(rot), llvel, param); 3122 // need the magnitude later
3123 // float velmag = (float)Util.GetMagnitude(llvel);
3153 3124
3154 // If either of these are null, then there was an unknown error. 3125 SceneObjectGroup new_group = World.RezObject(m_host, item, llpos, Rot2Quaternion(rot), llvel, param);
3155 if (new_group == null)
3156 continue;
3157 3126
3158 // objects rezzed with this method are die_at_edge by default. 3127 // If either of these are null, then there was an unknown error.
3159 new_group.RootPart.SetDieAtEdge(true); 3128 if (new_group == null)
3129 return;
3160 3130
3161 new_group.ResumeScripts(); 3131 // objects rezzed with this method are die_at_edge by default.
3132 new_group.RootPart.SetDieAtEdge(true);
3162 3133
3163 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams( 3134 new_group.ResumeScripts();
3164 "object_rez", new Object[] {
3165 new LSL_String(
3166 new_group.RootPart.UUID.ToString()) },
3167 new DetectParams[0]));
3168 3135
3169 // do recoil 3136 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
3170 SceneObjectGroup hostgrp = m_host.ParentGroup; 3137 "object_rez", new Object[] {
3171 if (hostgrp == null) 3138 new LSL_String(
3172 return; 3139 new_group.RootPart.UUID.ToString()) },
3140 new DetectParams[0]));
3141
3142 // do recoil
3143 SceneObjectGroup hostgrp = m_host.ParentGroup;
3144 if (hostgrp == null)
3145 return;
3173 3146
3174 if (hostgrp.IsAttachment) // don't recoil avatars 3147 if (hostgrp.IsAttachment) // don't recoil avatars
3175 return; 3148 return;
3176 3149
3177 PhysicsActor pa = new_group.RootPart.PhysActor; 3150 PhysicsActor pa = new_group.RootPart.PhysActor;
3178 3151
3179 if (pa != null && pa.IsPhysical && llvel != Vector3.Zero) 3152 if (pa != null && pa.IsPhysical && llvel != Vector3.Zero)
3180 { 3153 {
3181 float groupmass = new_group.GetMass(); 3154 float groupmass = new_group.GetMass();
3182 llvel *= -groupmass; 3155 llvel *= -groupmass;
3183 llApplyImpulse(new LSL_Vector(llvel.X, llvel.Y,llvel.Z), 0); 3156 llApplyImpulse(new LSL_Vector(llvel.X, llvel.Y,llvel.Z), 0);
3184 }
3185 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
3186 return;
3187 }
3188 } 3157 }
3158 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
3159 return;
3189 3160
3190 llSay(0, "Could not find object " + inventory);
3191 }); 3161 });
3192 3162
3193 //ScriptSleep((int)((groupmass * velmag) / 10)); 3163 //ScriptSleep((int)((groupmass * velmag) / 10));
@@ -3251,11 +3221,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3251 sec = m_MinTimerInterval; 3221 sec = m_MinTimerInterval;
3252 m_host.AddScriptLPS(1); 3222 m_host.AddScriptLPS(1);
3253 // Setting timer repeat 3223 // Setting timer repeat
3254 AsyncCommands.TimerPlugin.SetTimerEvent(m_localID, m_itemID, sec); 3224 AsyncCommands.TimerPlugin.SetTimerEvent(m_host.LocalId, m_item.ItemID, sec);
3255 } 3225 }
3256 3226
3257 public virtual void llSleep(double sec) 3227 public virtual void llSleep(double sec)
3258 { 3228 {
3229// m_log.Info("llSleep snoozing " + sec + "s.");
3259 m_host.AddScriptLPS(1); 3230 m_host.AddScriptLPS(1);
3260 Thread.Sleep((int)(sec * 1000)); 3231 Thread.Sleep((int)(sec * 1000));
3261 } 3232 }
@@ -3314,29 +3285,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3314 3285
3315 public void llTakeControls(int controls, int accept, int pass_on) 3286 public void llTakeControls(int controls, int accept, int pass_on)
3316 { 3287 {
3317 TaskInventoryItem item; 3288 if (m_item.PermsGranter != UUID.Zero)
3318
3319 m_host.TaskInventory.LockItemsForRead(true);
3320 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3321 { 3289 {
3322 m_host.TaskInventory.LockItemsForRead(false); 3290 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
3323 return;
3324 }
3325 else
3326 {
3327 item = m_host.TaskInventory[InventorySelf()];
3328 }
3329 m_host.TaskInventory.LockItemsForRead(false);
3330
3331 if (item.PermsGranter != UUID.Zero)
3332 {
3333 ScenePresence presence = World.GetScenePresence(item.PermsGranter);
3334 3291
3335 if (presence != null) 3292 if (presence != null)
3336 { 3293 {
3337 if ((item.PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0) 3294 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)
3338 { 3295 {
3339 presence.RegisterControlEventsToScript(controls, accept, pass_on, m_localID, m_itemID); 3296 presence.RegisterControlEventsToScript(controls, accept, pass_on, m_host.LocalId, m_item.ItemID);
3340 } 3297 }
3341 } 3298 }
3342 } 3299 }
@@ -3346,38 +3303,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3346 3303
3347 public void llReleaseControls() 3304 public void llReleaseControls()
3348 { 3305 {
3349 TaskInventoryItem item;
3350
3351 m_host.TaskInventory.LockItemsForRead(true);
3352 lock (m_host.TaskInventory)
3353 {
3354
3355 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3356 {
3357 m_host.TaskInventory.LockItemsForRead(false);
3358 return;
3359 }
3360 else
3361 {
3362 item = m_host.TaskInventory[InventorySelf()];
3363 }
3364 }
3365 m_host.TaskInventory.LockItemsForRead(false);
3366
3367 m_host.AddScriptLPS(1); 3306 m_host.AddScriptLPS(1);
3368 3307
3369 if (item.PermsGranter != UUID.Zero) 3308 if (m_item.PermsGranter != UUID.Zero)
3370 { 3309 {
3371 ScenePresence presence = World.GetScenePresence(item.PermsGranter); 3310 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
3372 3311
3373 if (presence != null) 3312 if (presence != null)
3374 { 3313 {
3375 if ((item.PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0) 3314 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)
3376 { 3315 {
3377 // Unregister controls from Presence 3316 // Unregister controls from Presence
3378 presence.UnRegisterControlEventsToScript(m_localID, m_itemID); 3317 presence.UnRegisterControlEventsToScript(m_host.LocalId, m_item.ItemID);
3379 // Remove Take Control permission. 3318 // Remove Take Control permission.
3380 item.PermsMask &= ~ScriptBaseClass.PERMISSION_TAKE_CONTROLS; 3319 m_item.PermsMask &= ~ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
3381 } 3320 }
3382 } 3321 }
3383 } 3322 }
@@ -3390,86 +3329,68 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3390 m_UrlModule.ReleaseURL(url); 3329 m_UrlModule.ReleaseURL(url);
3391 } 3330 }
3392 3331
3393 public void llAttachToAvatar(int attachment) 3332 /// <summary>
3333 /// Attach the object containing this script to the avatar that owns it.
3334 /// </summary>
3335 /// <param name='attachment'>The attachment point (e.g. ATTACH_CHEST)</param>
3336 /// <returns>true if the attach suceeded, false if it did not</returns>
3337 public bool AttachToAvatar(int attachmentPoint)
3394 { 3338 {
3395 m_host.AddScriptLPS(1); 3339 SceneObjectGroup grp = m_host.ParentGroup;
3396 3340 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
3397 TaskInventoryItem item;
3398 3341
3399 m_host.TaskInventory.LockItemsForRead(true); 3342 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
3400 3343
3401 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3344 if (attachmentsModule != null)
3402 { 3345 return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, true);
3403 m_host.TaskInventory.LockItemsForRead(false);
3404 return;
3405 }
3406 else 3346 else
3407 { 3347 return false;
3408 item = m_host.TaskInventory[InventorySelf()]; 3348 }
3409 }
3410
3411 m_host.TaskInventory.LockItemsForRead(false);
3412 3349
3413 if (item.PermsGranter != m_host.OwnerID) 3350 /// <summary>
3414 return; 3351 /// Detach the object containing this script from the avatar it is attached to.
3352 /// </summary>
3353 /// <remarks>
3354 /// Nothing happens if the object is not attached.
3355 /// </remarks>
3356 public void DetachFromAvatar()
3357 {
3358 Util.FireAndForget(DetachWrapper, m_host);
3359 }
3415 3360
3416 if ((item.PermsMask & ScriptBaseClass.PERMISSION_ATTACH) != 0) 3361 private void DetachWrapper(object o)
3362 {
3363 if (World.AttachmentsModule != null)
3417 { 3364 {
3418 SceneObjectGroup grp = m_host.ParentGroup; 3365 SceneObjectPart host = (SceneObjectPart)o;
3419 3366 ScenePresence presence = World.GetScenePresence(host.OwnerID);
3420 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 3367 World.AttachmentsModule.DetachSingleAttachmentToInv(presence, host.ParentGroup);
3421
3422 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
3423 if (attachmentsModule != null)
3424 attachmentsModule.AttachObject(presence, grp, (uint)attachment, false, true);
3425 } 3368 }
3426 } 3369 }
3427 3370
3428 public void llDetachFromAvatar() 3371 public void llAttachToAvatar(int attachmentPoint)
3429 { 3372 {
3430 m_host.AddScriptLPS(1); 3373 m_host.AddScriptLPS(1);
3431 3374
3432 if (m_host.ParentGroup.AttachmentPoint == 0) 3375 if (m_item.PermsGranter != m_host.OwnerID)
3433 return; 3376 return;
3434 3377
3435 TaskInventoryItem item; 3378 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_ATTACH) != 0)
3379 AttachToAvatar(attachmentPoint);
3380 }
3436 3381
3437 m_host.TaskInventory.LockItemsForRead(true); 3382 public void llDetachFromAvatar()
3383 {
3384 m_host.AddScriptLPS(1);
3438 3385
3439 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3386 if (m_host.ParentGroup.AttachmentPoint == 0)
3440 {
3441 m_host.TaskInventory.LockItemsForRead(false);
3442 return; 3387 return;
3443 }
3444 else
3445 {
3446 item = m_host.TaskInventory[InventorySelf()];
3447 }
3448 m_host.TaskInventory.LockItemsForRead(false);
3449 3388
3450 3389 if (m_item.PermsGranter != m_host.OwnerID)
3451 if (item.PermsGranter != m_host.OwnerID)
3452 return; 3390 return;
3453 3391
3454 if ((item.PermsMask & ScriptBaseClass.PERMISSION_ATTACH) != 0) 3392 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_ATTACH) != 0)
3455 { 3393 DetachFromAvatar();
3456 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
3457 if (attachmentsModule != null)
3458 Util.FireAndForget(DetachWrapper, m_host);
3459 }
3460 }
3461
3462 private void DetachWrapper(object o)
3463 {
3464 SceneObjectPart host = (SceneObjectPart)o;
3465
3466 SceneObjectGroup grp = host.ParentGroup;
3467 UUID itemID = grp.FromItemID;
3468 ScenePresence presence = World.GetScenePresence(host.OwnerID);
3469
3470 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
3471 if (attachmentsModule != null)
3472 attachmentsModule.DetachSingleAttachmentToInv(presence, itemID);
3473 } 3394 }
3474 3395
3475 public void llTakeCamera(string avatar) 3396 public void llTakeCamera(string avatar)
@@ -3590,7 +3511,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3590 } 3511 }
3591 3512
3592 emailModule.SendEmail(m_host.UUID, address, subject, message); 3513 emailModule.SendEmail(m_host.UUID, address, subject, message);
3593 ScriptSleep(15000); 3514 ScriptSleep(EMAIL_PAUSE_TIME * 1000);
3594 } 3515 }
3595 3516
3596 public void llGetNextEmail(string address, string subject) 3517 public void llGetNextEmail(string address, string subject)
@@ -3627,6 +3548,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3627 return m_host.UUID.ToString(); 3548 return m_host.UUID.ToString();
3628 } 3549 }
3629 3550
3551 public LSL_Key llGenerateKey()
3552 {
3553 m_host.AddScriptLPS(1);
3554 return UUID.Random().ToString();
3555 }
3556
3630 public void llSetBuoyancy(double buoyancy) 3557 public void llSetBuoyancy(double buoyancy)
3631 { 3558 {
3632 m_host.AddScriptLPS(1); 3559 m_host.AddScriptLPS(1);
@@ -3673,7 +3600,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3673 m_host.AddScriptLPS(1); 3600 m_host.AddScriptLPS(1);
3674 try 3601 try
3675 { 3602 {
3676 m_ScriptEngine.SetMinEventDelay(m_itemID, delay); 3603 m_ScriptEngine.SetMinEventDelay(m_item.ItemID, delay);
3677 } 3604 }
3678 catch (NotImplementedException) 3605 catch (NotImplementedException)
3679 { 3606 {
@@ -3726,29 +3653,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3726 { 3653 {
3727 m_host.AddScriptLPS(1); 3654 m_host.AddScriptLPS(1);
3728 3655
3729 UUID invItemID = InventorySelf(); 3656 if (m_item.PermsGranter == UUID.Zero)
3730 if (invItemID == UUID.Zero)
3731 return; 3657 return;
3732 3658
3733 TaskInventoryItem item; 3659 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0)
3734
3735 m_host.TaskInventory.LockItemsForRead(true);
3736 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3737 { 3660 {
3738 m_host.TaskInventory.LockItemsForRead(false); 3661 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
3739 return;
3740 }
3741 else
3742 {
3743 item = m_host.TaskInventory[InventorySelf()];
3744 }
3745 m_host.TaskInventory.LockItemsForRead(false);
3746 if (item.PermsGranter == UUID.Zero)
3747 return;
3748
3749 if ((item.PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0)
3750 {
3751 ScenePresence presence = World.GetScenePresence(item.PermsGranter);
3752 3662
3753 if (presence != null) 3663 if (presence != null)
3754 { 3664 {
@@ -3766,41 +3676,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3766 { 3676 {
3767 m_host.AddScriptLPS(1); 3677 m_host.AddScriptLPS(1);
3768 3678
3769 UUID invItemID=InventorySelf(); 3679 if (m_item.PermsGranter == UUID.Zero)
3770 if (invItemID == UUID.Zero)
3771 return;
3772
3773 TaskInventoryItem item;
3774
3775 m_host.TaskInventory.LockItemsForRead(true);
3776 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3777 {
3778 m_host.TaskInventory.LockItemsForRead(false);
3779 return;
3780 }
3781 else
3782 {
3783 item = m_host.TaskInventory[InventorySelf()];
3784 }
3785 m_host.TaskInventory.LockItemsForRead(false);
3786
3787
3788 if (item.PermsGranter == UUID.Zero)
3789 return; 3680 return;
3790 3681
3791 if ((item.PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0) 3682 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0)
3792 { 3683 {
3793 UUID animID = new UUID(); 3684 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
3794
3795 if (!UUID.TryParse(anim, out animID))
3796 {
3797 animID=InventoryKey(anim);
3798 }
3799
3800 ScenePresence presence = World.GetScenePresence(item.PermsGranter);
3801 3685
3802 if (presence != null) 3686 if (presence != null)
3803 { 3687 {
3688 UUID animID = KeyOrName(anim);
3689
3804 if (animID == UUID.Zero) 3690 if (animID == UUID.Zero)
3805 presence.Animator.RemoveAnimation(anim); 3691 presence.Animator.RemoveAnimation(anim);
3806 else 3692 else
@@ -3833,44 +3719,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3833 public LSL_Integer llGetStartParameter() 3719 public LSL_Integer llGetStartParameter()
3834 { 3720 {
3835 m_host.AddScriptLPS(1); 3721 m_host.AddScriptLPS(1);
3836 return m_ScriptEngine.GetStartParameter(m_itemID); 3722 return m_ScriptEngine.GetStartParameter(m_item.ItemID);
3837 } 3723 }
3838 3724
3839 public void llRequestPermissions(string agent, int perm) 3725 public void llRequestPermissions(string agent, int perm)
3840 { 3726 {
3841 UUID agentID = new UUID(); 3727 UUID agentID;
3842 3728
3843 if (!UUID.TryParse(agent, out agentID)) 3729 if (!UUID.TryParse(agent, out agentID))
3844 return; 3730 return;
3845 3731
3846 UUID invItemID = InventorySelf();
3847
3848 if (invItemID == UUID.Zero)
3849 return; // Not in a prim? How??
3850
3851 TaskInventoryItem item;
3852
3853
3854 m_host.TaskInventory.LockItemsForRead(true);
3855 if (!m_host.TaskInventory.ContainsKey(invItemID))
3856 {
3857 m_host.TaskInventory.LockItemsForRead(false);
3858 return;
3859 }
3860 else
3861 {
3862 item = m_host.TaskInventory[invItemID];
3863 }
3864 m_host.TaskInventory.LockItemsForRead(false);
3865
3866 if (agentID == UUID.Zero || perm == 0) // Releasing permissions 3732 if (agentID == UUID.Zero || perm == 0) // Releasing permissions
3867 { 3733 {
3868 llReleaseControls(); 3734 llReleaseControls();
3869 3735
3870 item.PermsGranter = UUID.Zero; 3736 m_item.PermsGranter = UUID.Zero;
3871 item.PermsMask = 0; 3737 m_item.PermsMask = 0;
3872 3738
3873 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3739 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3874 "run_time_permissions", new Object[] { 3740 "run_time_permissions", new Object[] {
3875 new LSL_Integer(0) }, 3741 new LSL_Integer(0) },
3876 new DetectParams[0])); 3742 new DetectParams[0]));
@@ -3878,7 +3744,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3878 return; 3744 return;
3879 } 3745 }
3880 3746
3881 if (item.PermsGranter != agentID || (perm & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) 3747 if (m_item.PermsGranter != agentID || (perm & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
3882 llReleaseControls(); 3748 llReleaseControls();
3883 3749
3884 m_host.AddScriptLPS(1); 3750 m_host.AddScriptLPS(1);
@@ -3895,11 +3761,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3895 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3761 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3896 { 3762 {
3897 m_host.TaskInventory.LockItemsForWrite(true); 3763 m_host.TaskInventory.LockItemsForWrite(true);
3898 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3764 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3899 m_host.TaskInventory[invItemID].PermsMask = perm; 3765 m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
3900 m_host.TaskInventory.LockItemsForWrite(false); 3766 m_host.TaskInventory.LockItemsForWrite(false);
3901 3767
3902 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3768 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3903 "run_time_permissions", new Object[] { 3769 "run_time_permissions", new Object[] {
3904 new LSL_Integer(perm) }, 3770 new LSL_Integer(perm) },
3905 new DetectParams[0])); 3771 new DetectParams[0]));
@@ -3934,11 +3800,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3934 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3800 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3935 { 3801 {
3936 m_host.TaskInventory.LockItemsForWrite(true); 3802 m_host.TaskInventory.LockItemsForWrite(true);
3937 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3803 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3938 m_host.TaskInventory[invItemID].PermsMask = perm; 3804 m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
3939 m_host.TaskInventory.LockItemsForWrite(false); 3805 m_host.TaskInventory.LockItemsForWrite(false);
3940 3806
3941 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3807 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3942 "run_time_permissions", new Object[] { 3808 "run_time_permissions", new Object[] {
3943 new LSL_Integer(perm) }, 3809 new LSL_Integer(perm) },
3944 new DetectParams[0])); 3810 new DetectParams[0]));
@@ -3949,9 +3815,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3949 } 3815 }
3950 3816
3951 ScenePresence presence = World.GetScenePresence(agentID); 3817 ScenePresence presence = World.GetScenePresence(agentID);
3952
3953 if (presence != null) 3818 if (presence != null)
3954 { 3819 {
3820 // If permissions are being requested from an NPC and were not implicitly granted above then
3821 // auto grant all reuqested permissions if the script is owned by the NPC or the NPCs owner
3822 INPCModule npcModule = World.RequestModuleInterface<INPCModule>();
3823 if (npcModule != null && npcModule.IsNPC(agentID, World))
3824 {
3825 if (agentID == m_host.ParentGroup.OwnerID || npcModule.GetOwner(agentID) == m_host.ParentGroup.OwnerID)
3826 {
3827 lock (m_host.TaskInventory)
3828 {
3829 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3830 m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
3831 }
3832
3833 m_ScriptEngine.PostScriptEvent(
3834 m_item.ItemID,
3835 new EventParams(
3836 "run_time_permissions", new Object[] { new LSL_Integer(perm) }, new DetectParams[0]));
3837 }
3838
3839 // it is an NPC, exit even if the permissions werent granted above, they are not going to answer
3840 // the question!
3841 return;
3842 }
3843
3955 string ownerName = resolveName(m_host.ParentGroup.RootPart.OwnerID); 3844 string ownerName = resolveName(m_host.ParentGroup.RootPart.OwnerID);
3956 if (ownerName == String.Empty) 3845 if (ownerName == String.Empty)
3957 ownerName = "(hippos)"; 3846 ownerName = "(hippos)";
@@ -3959,8 +3848,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3959 if (!m_waitingForScriptAnswer) 3848 if (!m_waitingForScriptAnswer)
3960 { 3849 {
3961 m_host.TaskInventory.LockItemsForWrite(true); 3850 m_host.TaskInventory.LockItemsForWrite(true);
3962 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3851 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3963 m_host.TaskInventory[invItemID].PermsMask = 0; 3852 m_host.TaskInventory[m_item.ItemID].PermsMask = 0;
3964 m_host.TaskInventory.LockItemsForWrite(false); 3853 m_host.TaskInventory.LockItemsForWrite(false);
3965 3854
3966 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; 3855 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
@@ -3968,16 +3857,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3968 } 3857 }
3969 3858
3970 presence.ControllingClient.SendScriptQuestion( 3859 presence.ControllingClient.SendScriptQuestion(
3971 m_host.UUID, m_host.ParentGroup.RootPart.Name, ownerName, invItemID, perm); 3860 m_host.UUID, m_host.ParentGroup.RootPart.Name, ownerName, m_item.ItemID, perm);
3972 3861
3973 return; 3862 return;
3974 } 3863 }
3975 3864
3976 // Requested agent is not in range, refuse perms 3865 // Requested agent is not in range, refuse perms
3977 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3866 m_ScriptEngine.PostScriptEvent(
3978 "run_time_permissions", new Object[] { 3867 m_item.ItemID,
3979 new LSL_Integer(0) }, 3868 new EventParams("run_time_permissions", new Object[] { new LSL_Integer(0) }, new DetectParams[0]));
3980 new DetectParams[0]));
3981 } 3869 }
3982 3870
3983 void handleScriptAnswer(IClientAPI client, UUID taskID, UUID itemID, int answer) 3871 void handleScriptAnswer(IClientAPI client, UUID taskID, UUID itemID, int answer)
@@ -3985,24 +3873,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3985 if (taskID != m_host.UUID) 3873 if (taskID != m_host.UUID)
3986 return; 3874 return;
3987 3875
3988 UUID invItemID = InventorySelf(); 3876 client.OnScriptAnswer -= handleScriptAnswer;
3989 3877 m_waitingForScriptAnswer = false;
3990 if (invItemID == UUID.Zero)
3991 return;
3992
3993 client.OnScriptAnswer-=handleScriptAnswer;
3994 m_waitingForScriptAnswer=false;
3995 3878
3996 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) 3879 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
3997 llReleaseControls(); 3880 llReleaseControls();
3998 3881
3999
4000 m_host.TaskInventory.LockItemsForWrite(true); 3882 m_host.TaskInventory.LockItemsForWrite(true);
4001 m_host.TaskInventory[invItemID].PermsMask = answer; 3883 m_host.TaskInventory[m_item.ItemID].PermsMask = answer;
4002 m_host.TaskInventory.LockItemsForWrite(false); 3884 m_host.TaskInventory.LockItemsForWrite(false);
4003 3885
4004 3886 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
4005 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
4006 "run_time_permissions", new Object[] { 3887 "run_time_permissions", new Object[] {
4007 new LSL_Integer(answer) }, 3888 new LSL_Integer(answer) },
4008 new DetectParams[0])); 3889 new DetectParams[0]));
@@ -4012,41 +3893,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4012 { 3893 {
4013 m_host.AddScriptLPS(1); 3894 m_host.AddScriptLPS(1);
4014 3895
4015 m_host.TaskInventory.LockItemsForRead(true); 3896 return m_item.PermsGranter.ToString();
4016
4017 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
4018 {
4019 if (item.Type == 10 && item.ItemID == m_itemID)
4020 {
4021 m_host.TaskInventory.LockItemsForRead(false);
4022 return item.PermsGranter.ToString();
4023 }
4024 }
4025 m_host.TaskInventory.LockItemsForRead(false);
4026
4027 return UUID.Zero.ToString();
4028 } 3897 }
4029 3898
4030 public LSL_Integer llGetPermissions() 3899 public LSL_Integer llGetPermissions()
4031 { 3900 {
4032 m_host.AddScriptLPS(1); 3901 m_host.AddScriptLPS(1);
4033 3902
4034 m_host.TaskInventory.LockItemsForRead(true); 3903 int perms = m_item.PermsMask;
4035 3904
4036 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 3905 if (m_automaticLinkPermission)
4037 { 3906 perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS;
4038 if (item.Type == 10 && item.ItemID == m_itemID)
4039 {
4040 int perms = item.PermsMask;
4041 if (m_automaticLinkPermission)
4042 perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS;
4043 m_host.TaskInventory.LockItemsForRead(false);
4044 return perms;
4045 }
4046 }
4047 m_host.TaskInventory.LockItemsForRead(false);
4048 3907
4049 return 0; 3908 return perms;
4050 } 3909 }
4051 3910
4052 public LSL_Integer llGetLinkNumber() 3911 public LSL_Integer llGetLinkNumber()
@@ -4084,18 +3943,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4084 public void llCreateLink(string target, int parent) 3943 public void llCreateLink(string target, int parent)
4085 { 3944 {
4086 m_host.AddScriptLPS(1); 3945 m_host.AddScriptLPS(1);
4087 UUID invItemID = InventorySelf(); 3946
4088 UUID targetID; 3947 UUID targetID;
4089 3948
4090 if (!UUID.TryParse(target, out targetID)) 3949 if (!UUID.TryParse(target, out targetID))
4091 return; 3950 return;
4092 3951
4093 TaskInventoryItem item; 3952 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4094 m_host.TaskInventory.LockItemsForRead(true);
4095 item = m_host.TaskInventory[invItemID];
4096 m_host.TaskInventory.LockItemsForRead(false);
4097
4098 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4099 && !m_automaticLinkPermission) 3953 && !m_automaticLinkPermission)
4100 { 3954 {
4101 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!"); 3955 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
@@ -4103,7 +3957,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4103 } 3957 }
4104 3958
4105 IClientAPI client = null; 3959 IClientAPI client = null;
4106 ScenePresence sp = World.GetScenePresence(item.PermsGranter); 3960 ScenePresence sp = World.GetScenePresence(m_item.PermsGranter);
4107 if (sp != null) 3961 if (sp != null)
4108 client = sp.ControllingClient; 3962 client = sp.ControllingClient;
4109 3963
@@ -4149,18 +4003,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4149 public void llBreakLink(int linknum) 4003 public void llBreakLink(int linknum)
4150 { 4004 {
4151 m_host.AddScriptLPS(1); 4005 m_host.AddScriptLPS(1);
4152 UUID invItemID = InventorySelf();
4153 4006
4154 m_host.TaskInventory.LockItemsForRead(true); 4007 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4155 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 4008 && !m_automaticLinkPermission)
4156 && !m_automaticLinkPermission) 4009 {
4157 { 4010 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
4158 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!"); 4011 return;
4159 m_host.TaskInventory.LockItemsForRead(false); 4012 }
4160 return; 4013
4161 }
4162 m_host.TaskInventory.LockItemsForRead(false);
4163
4164 if (linknum < ScriptBaseClass.LINK_THIS) 4014 if (linknum < ScriptBaseClass.LINK_THIS)
4165 return; 4015 return;
4166 4016
@@ -4259,12 +4109,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4259 { 4109 {
4260 m_host.AddScriptLPS(1); 4110 m_host.AddScriptLPS(1);
4261 4111
4262 UUID invItemID = InventorySelf(); 4112 TaskInventoryItem item = m_item;
4263
4264 TaskInventoryItem item;
4265 m_host.TaskInventory.LockItemsForRead(true);
4266 item = m_host.TaskInventory[invItemID];
4267 m_host.TaskInventory.LockItemsForRead(false);
4268 4113
4269 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 4114 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4270 && !m_automaticLinkPermission) 4115 && !m_automaticLinkPermission)
@@ -4461,11 +4306,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4461 public void llGiveInventory(string destination, string inventory) 4306 public void llGiveInventory(string destination, string inventory)
4462 { 4307 {
4463 m_host.AddScriptLPS(1); 4308 m_host.AddScriptLPS(1);
4464 bool found = false; 4309
4465 UUID destId = UUID.Zero; 4310 UUID destId = UUID.Zero;
4466 UUID objId = UUID.Zero;
4467 int assetType = 0;
4468 string objName = String.Empty;
4469 4311
4470 if (!UUID.TryParse(destination, out destId)) 4312 if (!UUID.TryParse(destination, out destId))
4471 { 4313 {
@@ -4473,28 +4315,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4473 return; 4315 return;
4474 } 4316 }
4475 4317
4476 // move the first object found with this inventory name 4318 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(inventory);
4477 m_host.TaskInventory.LockItemsForRead(true);
4478 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
4479 {
4480 if (inv.Value.Name == inventory)
4481 {
4482 found = true;
4483 objId = inv.Key;
4484 assetType = inv.Value.Type;
4485 objName = inv.Value.Name;
4486 break;
4487 }
4488 }
4489 m_host.TaskInventory.LockItemsForRead(false);
4490 4319
4491 if (!found) 4320 if (item == null)
4492 { 4321 {
4493 llSay(0, String.Format("Could not find object '{0}'", inventory)); 4322 llSay(0, String.Format("Could not find object '{0}'", inventory));
4494 return; 4323 return;
4495// throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory)); 4324// throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
4496 } 4325 }
4497 4326
4327 UUID objId = item.ItemID;
4328
4498 // check if destination is an object 4329 // check if destination is an object
4499 if (World.GetSceneObjectPart(destId) != null) 4330 if (World.GetSceneObjectPart(destId) != null)
4500 { 4331 {
@@ -4526,14 +4357,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4526 return; 4357 return;
4527 4358
4528 byte[] bucket = new byte[1]; 4359 byte[] bucket = new byte[1];
4529 bucket[0] = (byte)assetType; 4360 bucket[0] = (byte)item.Type;
4530 //byte[] objBytes = agentItem.ID.GetBytes(); 4361 //byte[] objBytes = agentItem.ID.GetBytes();
4531 //Array.Copy(objBytes, 0, bucket, 1, 16); 4362 //Array.Copy(objBytes, 0, bucket, 1, 16);
4532 4363
4533 GridInstantMessage msg = new GridInstantMessage(World, 4364 GridInstantMessage msg = new GridInstantMessage(World,
4534 m_host.OwnerID, m_host.Name, destId, 4365 m_host.OwnerID, m_host.Name, destId,
4535 (byte)InstantMessageDialog.TaskInventoryOffered, 4366 (byte)InstantMessageDialog.TaskInventoryOffered,
4536 false, objName+". "+m_host.Name+" is located at "+ 4367 false, item.Name+". "+m_host.Name+" is located at "+
4537 World.RegionInfo.RegionName+" "+ 4368 World.RegionInfo.RegionName+" "+
4538 m_host.AbsolutePosition.ToString(), 4369 m_host.AbsolutePosition.ToString(),
4539 agentItem.ID, true, m_host.AbsolutePosition, 4370 agentItem.ID, true, m_host.AbsolutePosition,
@@ -4561,27 +4392,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4561 { 4392 {
4562 m_host.AddScriptLPS(1); 4393 m_host.AddScriptLPS(1);
4563 4394
4564 List<TaskInventoryItem> inv; 4395 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name);
4565 try 4396
4566 { 4397 if (item == null)
4567 m_host.TaskInventory.LockItemsForRead(true); 4398 return;
4568 inv = new List<TaskInventoryItem>(m_host.TaskInventory.Values); 4399
4569 } 4400 if (item.ItemID == m_item.ItemID)
4570 finally 4401 throw new ScriptDeleteException();
4571 { 4402 else
4572 m_host.TaskInventory.LockItemsForRead(false); 4403 m_host.Inventory.RemoveInventoryItem(item.ItemID);
4573 }
4574 foreach (TaskInventoryItem item in inv)
4575 {
4576 if (item.Name == name)
4577 {
4578 if (item.ItemID == m_itemID)
4579 throw new ScriptDeleteException();
4580 else
4581 m_host.Inventory.RemoveInventoryItem(item.ItemID);
4582 return;
4583 }
4584 }
4585 } 4404 }
4586 4405
4587 public void llSetText(string text, LSL_Vector color, double alpha) 4406 public void llSetText(string text, LSL_Vector color, double alpha)
@@ -4709,8 +4528,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4709 UUID rq = UUID.Random(); 4528 UUID rq = UUID.Random();
4710 4529
4711 UUID tid = AsyncCommands. 4530 UUID tid = AsyncCommands.
4712 DataserverPlugin.RegisterRequest(m_localID, 4531 DataserverPlugin.RegisterRequest(m_host.LocalId,
4713 m_itemID, rq.ToString()); 4532 m_item.ItemID, rq.ToString());
4714 4533
4715 AsyncCommands. 4534 AsyncCommands.
4716 DataserverPlugin.DataserverReply(rq.ToString(), reply); 4535 DataserverPlugin.DataserverReply(rq.ToString(), reply);
@@ -4729,16 +4548,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4729 { 4548 {
4730 m_host.AddScriptLPS(1); 4549 m_host.AddScriptLPS(1);
4731 4550
4732 //Clone is thread safe 4551 foreach (TaskInventoryItem item in m_host.Inventory.GetInventoryItems())
4733 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
4734
4735 foreach (TaskInventoryItem item in itemDictionary.Values)
4736 { 4552 {
4737 if (item.Type == 3 && item.Name == name) 4553 if (item.Type == 3 && item.Name == name)
4738 { 4554 {
4739 UUID tid = AsyncCommands. 4555 UUID tid = AsyncCommands.
4740 DataserverPlugin.RegisterRequest(m_localID, 4556 DataserverPlugin.RegisterRequest(m_host.LocalId,
4741 m_itemID, item.AssetID.ToString()); 4557 m_item.ItemID, item.AssetID.ToString());
4742 4558
4743 Vector3 region = new Vector3( 4559 Vector3 region = new Vector3(
4744 World.RegionInfo.RegionLocX * Constants.RegionSize, 4560 World.RegionInfo.RegionLocX * Constants.RegionSize,
@@ -4764,6 +4580,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4764 return tid.ToString(); 4580 return tid.ToString();
4765 } 4581 }
4766 } 4582 }
4583
4767 ScriptSleep(1000); 4584 ScriptSleep(1000);
4768 return String.Empty; 4585 return String.Empty;
4769 } 4586 }
@@ -4956,19 +4773,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4956 UUID soundId = UUID.Zero; 4773 UUID soundId = UUID.Zero;
4957 if (!UUID.TryParse(impact_sound, out soundId)) 4774 if (!UUID.TryParse(impact_sound, out soundId))
4958 { 4775 {
4959 m_host.TaskInventory.LockItemsForRead(true); 4776 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(impact_sound);
4960 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4777
4961 { 4778 if (item != null && item.Type == (int)AssetType.Sound)
4962 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound) 4779 soundId = item.AssetID;
4963 {
4964 soundId = item.AssetID;
4965 break;
4966 }
4967 }
4968 m_host.TaskInventory.LockItemsForRead(false);
4969 } 4780 }
4970 m_host.CollisionSoundVolume = (float)impact_volume; 4781
4971 m_host.CollisionSound = soundId; 4782 m_host.CollisionSound = soundId;
4783 m_host.CollisionSoundVolume = (float)impact_volume;
4972 m_host.CollisionSoundType = 1; 4784 m_host.CollisionSoundType = 1;
4973 } 4785 }
4974 4786
@@ -5010,10 +4822,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5010 UUID partItemID; 4822 UUID partItemID;
5011 foreach (SceneObjectPart part in parts) 4823 foreach (SceneObjectPart part in parts)
5012 { 4824 {
5013 //Clone is thread safe 4825 foreach (TaskInventoryItem item in part.Inventory.GetInventoryItems())
5014 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
5015
5016 foreach (TaskInventoryItem item in itemsDictionary.Values)
5017 { 4826 {
5018 if (item.Type == ScriptBaseClass.INVENTORY_SCRIPT) 4827 if (item.Type == ScriptBaseClass.INVENTORY_SCRIPT)
5019 { 4828 {
@@ -5211,22 +5020,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5211 5020
5212 public LSL_String llGetScriptName() 5021 public LSL_String llGetScriptName()
5213 { 5022 {
5214 string result = String.Empty;
5215
5216 m_host.AddScriptLPS(1); 5023 m_host.AddScriptLPS(1);
5217 5024
5218 m_host.TaskInventory.LockItemsForRead(true); 5025 return m_item.Name != null ? m_item.Name : String.Empty;
5219 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
5220 {
5221 if (item.Type == 10 && item.ItemID == m_itemID)
5222 {
5223 result = item.Name!=null?item.Name:String.Empty;
5224 break;
5225 }
5226 }
5227 m_host.TaskInventory.LockItemsForRead(false);
5228
5229 return result;
5230 } 5026 }
5231 5027
5232 public LSL_Integer llGetLinkNumberOfSides(int link) 5028 public LSL_Integer llGetLinkNumberOfSides(int link)
@@ -5397,22 +5193,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5397 { 5193 {
5398 m_host.AddScriptLPS(1); 5194 m_host.AddScriptLPS(1);
5399 5195
5400 m_host.TaskInventory.LockItemsForRead(true); 5196 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name);
5401 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 5197
5198 if (item == null)
5199 return UUID.Zero.ToString();
5200
5201 if ((item.CurrentPermissions
5202 & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
5203 == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
5402 { 5204 {
5403 if (inv.Value.Name == name) 5205 return item.AssetID.ToString();
5404 {
5405 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
5406 {
5407 m_host.TaskInventory.LockItemsForRead(false);
5408 return inv.Value.AssetID.ToString();
5409 }
5410 else
5411 {
5412 m_host.TaskInventory.LockItemsForRead(false);
5413 return UUID.Zero.ToString();
5414 }
5415 }
5416 } 5206 }
5417 m_host.TaskInventory.LockItemsForRead(false); 5207 m_host.TaskInventory.LockItemsForRead(false);
5418 5208
@@ -6360,7 +6150,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6360 } 6150 }
6361 } 6151 }
6362 } 6152 }
6363 List<UUID> presenceIds = new List<UUID>();
6364 6153
6365 World.ForEachRootScenePresence( 6154 World.ForEachRootScenePresence(
6366 delegate (ScenePresence ssp) 6155 delegate (ScenePresence ssp)
@@ -6511,7 +6300,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6511 if (m_host.OwnerID == land.LandData.OwnerID) 6300 if (m_host.OwnerID == land.LandData.OwnerID)
6512 { 6301 {
6513 Vector3 pos = World.GetNearestAllowedPosition(presence, land); 6302 Vector3 pos = World.GetNearestAllowedPosition(presence, land);
6514 presence.TeleportWithMomentum(pos); 6303 presence.TeleportWithMomentum(pos, null);
6515 presence.ControllingClient.SendAlertMessage("You have been ejected from this land"); 6304 presence.ControllingClient.SendAlertMessage("You have been ejected from this land");
6516 } 6305 }
6517 } 6306 }
@@ -7036,22 +6825,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7036 } 6825 }
7037 } 6826 }
7038 6827
7039 protected UUID GetTaskInventoryItem(string name)
7040 {
7041 m_host.TaskInventory.LockItemsForRead(true);
7042 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
7043 {
7044 if (inv.Value.Name == name)
7045 {
7046 m_host.TaskInventory.LockItemsForRead(false);
7047 return inv.Key;
7048 }
7049 }
7050 m_host.TaskInventory.LockItemsForRead(false);
7051
7052 return UUID.Zero;
7053 }
7054
7055 public void llGiveInventoryList(string destination, string category, LSL_List inventory) 6828 public void llGiveInventoryList(string destination, string category, LSL_List inventory)
7056 { 6829 {
7057 m_host.AddScriptLPS(1); 6830 m_host.AddScriptLPS(1);
@@ -7064,16 +6837,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7064 6837
7065 foreach (Object item in inventory.Data) 6838 foreach (Object item in inventory.Data)
7066 { 6839 {
6840 string rawItemString = item.ToString();
6841
7067 UUID itemID; 6842 UUID itemID;
7068 if (UUID.TryParse(item.ToString(), out itemID)) 6843 if (UUID.TryParse(rawItemString, out itemID))
7069 { 6844 {
7070 itemList.Add(itemID); 6845 itemList.Add(itemID);
7071 } 6846 }
7072 else 6847 else
7073 { 6848 {
7074 itemID = GetTaskInventoryItem(item.ToString()); 6849 TaskInventoryItem taskItem = m_host.Inventory.GetInventoryItem(rawItemString);
7075 if (itemID != UUID.Zero) 6850
7076 itemList.Add(itemID); 6851 if (taskItem != null)
6852 itemList.Add(taskItem.ItemID);
7077 } 6853 }
7078 } 6854 }
7079 6855
@@ -7395,9 +7171,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7395 public void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param) 7171 public void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param)
7396 { 7172 {
7397 m_host.AddScriptLPS(1); 7173 m_host.AddScriptLPS(1);
7398 bool found = false; 7174
7399 UUID destId = UUID.Zero; 7175 UUID destId = UUID.Zero;
7400 UUID srcId = UUID.Zero;
7401 7176
7402 if (!UUID.TryParse(target, out destId)) 7177 if (!UUID.TryParse(target, out destId))
7403 { 7178 {
@@ -7412,25 +7187,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7412 } 7187 }
7413 7188
7414 // copy the first script found with this inventory name 7189 // copy the first script found with this inventory name
7415 TaskInventoryItem scriptItem = null; 7190 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name);
7416 m_host.TaskInventory.LockItemsForRead(true);
7417 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
7418 {
7419 if (inv.Value.Name == name)
7420 {
7421 // make sure the object is a script
7422 if (10 == inv.Value.Type)
7423 {
7424 found = true;
7425 srcId = inv.Key;
7426 scriptItem = inv.Value;
7427 break;
7428 }
7429 }
7430 }
7431 m_host.TaskInventory.LockItemsForRead(false);
7432 7191
7433 if (!found) 7192 // make sure the object is a script
7193 if (item == null || item.Type != 10)
7434 { 7194 {
7435 llSay(0, "Could not find script " + name); 7195 llSay(0, "Could not find script " + name);
7436 return; 7196 return;
@@ -7439,13 +7199,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7439 SceneObjectPart dest = World.GetSceneObjectPart(destId); 7199 SceneObjectPart dest = World.GetSceneObjectPart(destId);
7440 if (dest != null) 7200 if (dest != null)
7441 { 7201 {
7442 if ((scriptItem.BasePermissions & (uint)PermissionMask.Transfer) != 0 || dest.ParentGroup.RootPart.OwnerID == m_host.ParentGroup.RootPart.OwnerID) 7202 if ((item.BasePermissions & (uint)PermissionMask.Transfer) != 0 || dest.ParentGroup.RootPart.OwnerID == m_host.ParentGroup.RootPart.OwnerID)
7443 { 7203 {
7444 // the rest of the permission checks are done in RezScript, so check the pin there as well 7204 // the rest of the permission checks are done in RezScript, so check the pin there as well
7445 World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param); 7205 World.RezScriptFromPrim(item.ItemID, m_host, destId, pin, running, start_param);
7446 7206
7447 if ((scriptItem.BasePermissions & (uint)PermissionMask.Copy) == 0) 7207 if ((item.BasePermissions & (uint)PermissionMask.Copy) == 0)
7448 m_host.Inventory.RemoveInventoryItem(srcId); 7208 m_host.Inventory.RemoveInventoryItem(item.ItemID);
7449 } 7209 }
7450 } 7210 }
7451 // this will cause the delay even if the script pin or permissions were wrong - seems ok 7211 // this will cause the delay even if the script pin or permissions were wrong - seems ok
@@ -7458,14 +7218,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7458 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); 7218 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
7459 if (xmlrpcMod.IsEnabled()) 7219 if (xmlrpcMod.IsEnabled())
7460 { 7220 {
7461 UUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_localID, m_itemID, UUID.Zero); 7221 UUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_host.LocalId, m_item.ItemID, UUID.Zero);
7462 IXmlRpcRouter xmlRpcRouter = m_ScriptEngine.World.RequestModuleInterface<IXmlRpcRouter>(); 7222 IXmlRpcRouter xmlRpcRouter = m_ScriptEngine.World.RequestModuleInterface<IXmlRpcRouter>();
7463 if (xmlRpcRouter != null) 7223 if (xmlRpcRouter != null)
7464 { 7224 {
7465 string ExternalHostName = m_ScriptEngine.World.RegionInfo.ExternalHostName; 7225 string ExternalHostName = m_ScriptEngine.World.RegionInfo.ExternalHostName;
7466 7226
7467 xmlRpcRouter.RegisterNewReceiver(m_ScriptEngine.ScriptModule, channelID, m_host.UUID, 7227 xmlRpcRouter.RegisterNewReceiver(m_ScriptEngine.ScriptModule, channelID, m_host.UUID,
7468 m_itemID, String.Format("http://{0}:{1}/", ExternalHostName, 7228 m_item.ItemID, String.Format("http://{0}:{1}/", ExternalHostName,
7469 xmlrpcMod.Port.ToString())); 7229 xmlrpcMod.Port.ToString()));
7470 } 7230 }
7471 object[] resobj = new object[] 7231 object[] resobj = new object[]
@@ -7477,7 +7237,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7477 new LSL_Integer(0), 7237 new LSL_Integer(0),
7478 new LSL_String(String.Empty) 7238 new LSL_String(String.Empty)
7479 }; 7239 };
7480 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams("remote_data", resobj, 7240 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams("remote_data", resobj,
7481 new DetectParams[0])); 7241 new DetectParams[0]));
7482 } 7242 }
7483 ScriptSleep(1000); 7243 ScriptSleep(1000);
@@ -7488,7 +7248,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7488 m_host.AddScriptLPS(1); 7248 m_host.AddScriptLPS(1);
7489 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); 7249 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
7490 ScriptSleep(3000); 7250 ScriptSleep(3000);
7491 return (xmlrpcMod.SendRemoteData(m_localID, m_itemID, channel, dest, idata, sdata)).ToString(); 7251 return (xmlrpcMod.SendRemoteData(m_host.LocalId, m_item.ItemID, channel, dest, idata, sdata)).ToString();
7492 } 7252 }
7493 7253
7494 public void llRemoteDataReply(string channel, string message_id, string sdata, int idata) 7254 public void llRemoteDataReply(string channel, string message_id, string sdata, int idata)
@@ -8475,7 +8235,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8475 return; 8235 return;
8476 face = (int)rules.GetLSLIntegerItem(idx++); 8236 face = (int)rules.GetLSLIntegerItem(idx++);
8477 int shiny = (int)rules.GetLSLIntegerItem(idx++); 8237 int shiny = (int)rules.GetLSLIntegerItem(idx++);
8478 Bumpiness bump = (Bumpiness)Convert.ToByte((int)rules.GetLSLIntegerItem(idx++)); 8238 Bumpiness bump = (Bumpiness)(int)rules.GetLSLIntegerItem(idx++);
8479 8239
8480 SetShiny(part, face, shiny, bump); 8240 SetShiny(part, face, shiny, bump);
8481 8241
@@ -10317,7 +10077,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10317 public LSL_String llGetSimulatorHostname() 10077 public LSL_String llGetSimulatorHostname()
10318 { 10078 {
10319 m_host.AddScriptLPS(1); 10079 m_host.AddScriptLPS(1);
10320 return System.Environment.MachineName; 10080 IUrlModule UrlModule = World.RequestModuleInterface<IUrlModule>();
10081 return UrlModule.ExternalHostNameForLSL;
10321 } 10082 }
10322 10083
10323 // <summary> 10084 // <summary>
@@ -10554,92 +10315,82 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10554 } 10315 }
10555 } 10316 }
10556 10317
10557 public LSL_Integer llGetInventoryPermMask(string item, int mask) 10318 public LSL_Integer llGetInventoryPermMask(string itemName, int mask)
10558 { 10319 {
10559 m_host.AddScriptLPS(1); 10320 m_host.AddScriptLPS(1);
10560 10321
10561 m_host.TaskInventory.LockItemsForRead(true); 10322 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(itemName);
10562 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 10323
10324 if (item == null)
10325 return -1;
10326
10327 switch (mask)
10563 { 10328 {
10564 if (inv.Value.Name == item) 10329 case 0:
10565 { 10330 return (int)item.BasePermissions;
10566 m_host.TaskInventory.LockItemsForRead(false); 10331 case 1:
10567 switch (mask) 10332 return (int)item.CurrentPermissions;
10568 { 10333 case 2:
10569 case 0: 10334 return (int)item.GroupPermissions;
10570 return (int)inv.Value.BasePermissions; 10335 case 3:
10571 case 1: 10336 return (int)item.EveryonePermissions;
10572 return (int)inv.Value.CurrentPermissions; 10337 case 4:
10573 case 2: 10338 return (int)item.NextPermissions;
10574 return (int)inv.Value.GroupPermissions;
10575 case 3:
10576 return (int)inv.Value.EveryonePermissions;
10577 case 4:
10578 return (int)inv.Value.NextPermissions;
10579 }
10580 }
10581 } 10339 }
10582 m_host.TaskInventory.LockItemsForRead(false); 10340 m_host.TaskInventory.LockItemsForRead(false);
10583 10341
10584 return -1; 10342 return -1;
10585 } 10343 }
10586 10344
10587 public void llSetInventoryPermMask(string item, int mask, int value) 10345 public void llSetInventoryPermMask(string itemName, int mask, int value)
10588 { 10346 {
10589 m_host.AddScriptLPS(1); 10347 m_host.AddScriptLPS(1);
10348
10590 if (m_ScriptEngine.Config.GetBoolean("AllowGodFunctions", false)) 10349 if (m_ScriptEngine.Config.GetBoolean("AllowGodFunctions", false))
10591 { 10350 {
10592 if (World.Permissions.CanRunConsoleCommand(m_host.OwnerID)) 10351 if (World.Permissions.CanRunConsoleCommand(m_host.OwnerID))
10593 { 10352 {
10594 lock (m_host.TaskInventory) 10353 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(itemName);
10354
10355 if (item != null)
10595 { 10356 {
10596 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 10357 switch (mask)
10597 { 10358 {
10598 if (inv.Value.Name == item) 10359 case 0:
10599 { 10360 item.BasePermissions = (uint)value;
10600 switch (mask) 10361 break;
10601 { 10362 case 1:
10602 case 0: 10363 item.CurrentPermissions = (uint)value;
10603 inv.Value.BasePermissions = (uint)value; 10364 break;
10604 break; 10365 case 2:
10605 case 1: 10366 item.GroupPermissions = (uint)value;
10606 inv.Value.CurrentPermissions = (uint)value; 10367 break;
10607 break; 10368 case 3:
10608 case 2: 10369 item.EveryonePermissions = (uint)value;
10609 inv.Value.GroupPermissions = (uint)value; 10370 break;
10610 break; 10371 case 4:
10611 case 3: 10372 item.NextPermissions = (uint)value;
10612 inv.Value.EveryonePermissions = (uint)value; 10373 break;
10613 break;
10614 case 4:
10615 inv.Value.NextPermissions = (uint)value;
10616 break;
10617 }
10618 }
10619 } 10374 }
10620 } 10375 }
10621 } 10376 }
10622 } 10377 }
10623 } 10378 }
10624 10379
10625 public LSL_String llGetInventoryCreator(string item) 10380 public LSL_String llGetInventoryCreator(string itemName)
10626 { 10381 {
10627 m_host.AddScriptLPS(1); 10382 m_host.AddScriptLPS(1);
10628 10383
10629 m_host.TaskInventory.LockItemsForRead(true); 10384 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(itemName);
10630 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 10385
10386 if (item == null)
10631 { 10387 {
10632 if (inv.Value.Name == item) 10388 llSay(0, "No item name '" + item + "'");
10633 {
10634 m_host.TaskInventory.LockItemsForRead(false);
10635 return inv.Value.CreatorID.ToString();
10636 }
10637 }
10638 m_host.TaskInventory.LockItemsForRead(false);
10639 10389
10640 llSay(0, "No item name '" + item + "'"); 10390 return String.Empty;
10391 }
10641 10392
10642 return String.Empty; 10393 return item.CreatorID.ToString();
10643 } 10394 }
10644 10395
10645 public void llOwnerSay(string msg) 10396 public void llOwnerSay(string msg)
@@ -10656,13 +10407,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10656 { 10407 {
10657 m_host.AddScriptLPS(1); 10408 m_host.AddScriptLPS(1);
10658 if (m_UrlModule != null) 10409 if (m_UrlModule != null)
10659 return m_UrlModule.RequestSecureURL(m_ScriptEngine.ScriptModule, m_host, m_itemID).ToString(); 10410 return m_UrlModule.RequestSecureURL(m_ScriptEngine.ScriptModule, m_host, m_item.ItemID).ToString();
10660 return UUID.Zero.ToString(); 10411 return UUID.Zero.ToString();
10661 } 10412 }
10662 10413
10663 public LSL_String llRequestSimulatorData(string simulator, int data) 10414 public LSL_String llRequestSimulatorData(string simulator, int data)
10664 { 10415 {
10665 IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_itemID, "OSSL"); 10416 IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_item.ItemID, "OSSL");
10666 10417
10667 try 10418 try
10668 { 10419 {
@@ -10672,7 +10423,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10672 10423
10673 GridRegion info; 10424 GridRegion info;
10674 10425
10675 if (m_ScriptEngine.World.RegionInfo.RegionName == simulator) 10426 if (m_ScriptEngine.World.RegionInfo.RegionName == simulator) //Det data for this simulator?
10427
10676 info = new GridRegion(m_ScriptEngine.World.RegionInfo); 10428 info = new GridRegion(m_ScriptEngine.World.RegionInfo);
10677 else 10429 else
10678 info = m_ScriptEngine.World.GridService.GetRegionByName(m_ScriptEngine.World.RegionInfo.ScopeID, simulator); 10430 info = m_ScriptEngine.World.GridService.GetRegionByName(m_ScriptEngine.World.RegionInfo.ScopeID, simulator);
@@ -10685,10 +10437,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10685 ScriptSleep(1000); 10437 ScriptSleep(1000);
10686 return UUID.Zero.ToString(); 10438 return UUID.Zero.ToString();
10687 } 10439 }
10688 reply = new LSL_Vector( 10440 if (m_ScriptEngine.World.RegionInfo.RegionName != simulator)
10689 info.RegionLocX, 10441 {
10690 info.RegionLocY, 10442 //Hypergrid Region co-ordinates
10691 0).ToString(); 10443 uint rx = 0, ry = 0;
10444 Utils.LongToUInts(Convert.ToUInt64(info.RegionSecret), out rx, out ry);
10445
10446 reply = new LSL_Vector(
10447 rx,
10448 ry,
10449 0).ToString();
10450 }
10451 else
10452 {
10453 //Local-cooridnates
10454 reply = new LSL_Vector(
10455 info.RegionLocX,
10456 info.RegionLocY,
10457 0).ToString();
10458 }
10692 break; 10459 break;
10693 case ScriptBaseClass.DATA_SIM_STATUS: 10460 case ScriptBaseClass.DATA_SIM_STATUS:
10694 if (info != null) 10461 if (info != null)
@@ -10724,7 +10491,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10724 UUID rq = UUID.Random(); 10491 UUID rq = UUID.Random();
10725 10492
10726 UUID tid = AsyncCommands. 10493 UUID tid = AsyncCommands.
10727 DataserverPlugin.RegisterRequest(m_localID, m_itemID, rq.ToString()); 10494 DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, rq.ToString());
10728 10495
10729 AsyncCommands. 10496 AsyncCommands.
10730 DataserverPlugin.DataserverReply(rq.ToString(), reply); 10497 DataserverPlugin.DataserverReply(rq.ToString(), reply);
@@ -10743,7 +10510,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10743 m_host.AddScriptLPS(1); 10510 m_host.AddScriptLPS(1);
10744 10511
10745 if (m_UrlModule != null) 10512 if (m_UrlModule != null)
10746 return m_UrlModule.RequestURL(m_ScriptEngine.ScriptModule, m_host, m_itemID).ToString(); 10513 return m_UrlModule.RequestURL(m_ScriptEngine.ScriptModule, m_host, m_item.ItemID).ToString();
10747 return UUID.Zero.ToString(); 10514 return UUID.Zero.ToString();
10748 } 10515 }
10749 10516
@@ -10779,7 +10546,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10779 // child agents have a mass of 1.0 10546 // child agents have a mass of 1.0
10780 return 1; 10547 return 1;
10781 else 10548 else
10782 return avatar.GetMass(); 10549 return (double)avatar.GetMass();
10783 } 10550 }
10784 catch (KeyNotFoundException) 10551 catch (KeyNotFoundException)
10785 { 10552 {
@@ -11183,18 +10950,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11183 { 10950 {
11184 m_host.AddScriptLPS(1); 10951 m_host.AddScriptLPS(1);
11185 10952
11186 m_host.TaskInventory.LockItemsForRead(true); 10953 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name);
11187 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
11188 {
11189 if (inv.Value.Name == name)
11190 {
11191 m_host.TaskInventory.LockItemsForRead(false);
11192 return inv.Value.Type;
11193 }
11194 }
11195 m_host.TaskInventory.LockItemsForRead(false);
11196 10954
11197 return -1; 10955 if (item == null)
10956 return -1;
10957
10958 return item.Type;
11198 } 10959 }
11199 10960
11200 public void llSetPayPrice(int price, LSL_List quick_pay_buttons) 10961 public void llSetPayPrice(int price, LSL_List quick_pay_buttons)
@@ -11222,32 +10983,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11222 public LSL_Vector llGetCameraPos() 10983 public LSL_Vector llGetCameraPos()
11223 { 10984 {
11224 m_host.AddScriptLPS(1); 10985 m_host.AddScriptLPS(1);
11225 UUID invItemID = InventorySelf();
11226 10986
11227 if (invItemID == UUID.Zero) 10987 if (m_item.PermsGranter == UUID.Zero)
11228 return new LSL_Vector(); 10988 return new LSL_Vector();
11229
11230 m_host.TaskInventory.LockItemsForRead(true);
11231
11232 UUID agentID = m_host.TaskInventory[invItemID].PermsGranter;
11233
11234// if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
11235 if (agentID == UUID.Zero)
11236 {
11237 m_host.TaskInventory.LockItemsForRead(false);
11238 return new LSL_Vector();
11239 }
11240 10989
11241 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) 10990 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
11242 { 10991 {
11243 ShoutError("No permissions to track the camera"); 10992 ShoutError("No permissions to track the camera");
11244 m_host.TaskInventory.LockItemsForRead(false);
11245 return new LSL_Vector(); 10993 return new LSL_Vector();
11246 } 10994 }
11247 m_host.TaskInventory.LockItemsForRead(false);
11248 10995
11249// ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10996// ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
11250 ScenePresence presence = World.GetScenePresence(agentID); 10997 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
11251 if (presence != null) 10998 if (presence != null)
11252 { 10999 {
11253 LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y, presence.CameraPosition.Z); 11000 LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y, presence.CameraPosition.Z);
@@ -11259,30 +11006,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11259 public LSL_Rotation llGetCameraRot() 11006 public LSL_Rotation llGetCameraRot()
11260 { 11007 {
11261 m_host.AddScriptLPS(1); 11008 m_host.AddScriptLPS(1);
11262 UUID invItemID = InventorySelf();
11263 if (invItemID == UUID.Zero)
11264 return new LSL_Rotation();
11265
11266 m_host.TaskInventory.LockItemsForRead(true);
11267 11009
11268 UUID agentID = m_host.TaskInventory[invItemID].PermsGranter; 11010 if (m_item.PermsGranter == UUID.Zero)
11011 return new LSL_Rotation();
11269 11012
11270// if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) 11013 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
11271 if (agentID == UUID.Zero)
11272 {
11273 m_host.TaskInventory.LockItemsForRead(false);
11274 return new LSL_Rotation();
11275 }
11276 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
11277 { 11014 {
11278 ShoutError("No permissions to track the camera"); 11015 ShoutError("No permissions to track the camera");
11279 m_host.TaskInventory.LockItemsForRead(false);
11280 return new LSL_Rotation(); 11016 return new LSL_Rotation();
11281 } 11017 }
11282 m_host.TaskInventory.LockItemsForRead(false);
11283 11018
11284// ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 11019// ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
11285 ScenePresence presence = World.GetScenePresence(agentID); 11020 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
11286 if (presence != null) 11021 if (presence != null)
11287 { 11022 {
11288 return new LSL_Rotation(presence.CameraRotation.X, presence.CameraRotation.Y, presence.CameraRotation.Z, presence.CameraRotation.W); 11023 return new LSL_Rotation(presence.CameraRotation.X, presence.CameraRotation.Y, presence.CameraRotation.Z, presence.CameraRotation.W);
@@ -11341,7 +11076,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11341 public void llMapDestination(string simname, LSL_Vector pos, LSL_Vector lookAt) 11076 public void llMapDestination(string simname, LSL_Vector pos, LSL_Vector lookAt)
11342 { 11077 {
11343 m_host.AddScriptLPS(1); 11078 m_host.AddScriptLPS(1);
11344 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, 0); 11079 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0);
11345 if (detectedParams == null) 11080 if (detectedParams == null)
11346 { 11081 {
11347 if (m_host.ParentGroup.IsAttachment == true) 11082 if (m_host.ParentGroup.IsAttachment == true)
@@ -11465,30 +11200,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11465 { 11200 {
11466 m_host.AddScriptLPS(1); 11201 m_host.AddScriptLPS(1);
11467 11202
11468 // our key in the object we are in
11469 UUID invItemID = InventorySelf();
11470 if (invItemID == UUID.Zero) return;
11471
11472 // the object we are in 11203 // the object we are in
11473 UUID objectID = m_host.ParentUUID; 11204 UUID objectID = m_host.ParentUUID;
11474 if (objectID == UUID.Zero) return; 11205 if (objectID == UUID.Zero)
11206 return;
11475 11207
11476 UUID agentID;
11477 m_host.TaskInventory.LockItemsForRead(true);
11478 // we need the permission first, to know which avatar we want to set the camera for 11208 // we need the permission first, to know which avatar we want to set the camera for
11479 agentID = m_host.TaskInventory[invItemID].PermsGranter; 11209 UUID agentID = m_item.PermsGranter;
11480 11210
11481 if (agentID == UUID.Zero) 11211 if (agentID == UUID.Zero)
11482 {
11483 m_host.TaskInventory.LockItemsForRead(false);
11484 return; 11212 return;
11485 } 11213
11486 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) 11214 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0)
11487 {
11488 m_host.TaskInventory.LockItemsForRead(false);
11489 return; 11215 return;
11490 }
11491 m_host.TaskInventory.LockItemsForRead(false);
11492 11216
11493 ScenePresence presence = World.GetScenePresence(agentID); 11217 ScenePresence presence = World.GetScenePresence(agentID);
11494 11218
@@ -11530,34 +11254,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11530 { 11254 {
11531 m_host.AddScriptLPS(1); 11255 m_host.AddScriptLPS(1);
11532 11256
11533 // our key in the object we are in
11534 UUID invItemID=InventorySelf();
11535 if (invItemID == UUID.Zero) return;
11536
11537 // the object we are in 11257 // the object we are in
11538 UUID objectID = m_host.ParentUUID; 11258 UUID objectID = m_host.ParentUUID;
11539 if (objectID == UUID.Zero) return; 11259 if (objectID == UUID.Zero)
11260 return;
11540 11261
11541 // we need the permission first, to know which avatar we want to clear the camera for 11262 // we need the permission first, to know which avatar we want to clear the camera for
11542 UUID agentID; 11263 UUID agentID = m_item.PermsGranter;
11543 m_host.TaskInventory.LockItemsForRead(true); 11264
11544 agentID = m_host.TaskInventory[invItemID].PermsGranter;
11545 if (agentID == UUID.Zero) 11265 if (agentID == UUID.Zero)
11546 {
11547 m_host.TaskInventory.LockItemsForRead(false);
11548 return; 11266 return;
11549 } 11267
11550 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) 11268 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0)
11551 {
11552 m_host.TaskInventory.LockItemsForRead(false);
11553 return; 11269 return;
11554 }
11555 m_host.TaskInventory.LockItemsForRead(false);
11556 11270
11557 ScenePresence presence = World.GetScenePresence(agentID); 11271 ScenePresence presence = World.GetScenePresence(agentID);
11558 11272
11559 // we are not interested in child-agents 11273 // we are not interested in child-agents
11560 if (presence.IsChildAgent) return; 11274 if (presence.IsChildAgent)
11275 return;
11561 11276
11562 presence.ControllingClient.SendClearFollowCamProperties(objectID); 11277 presence.ControllingClient.SendClearFollowCamProperties(objectID);
11563 } 11278 }
@@ -11748,8 +11463,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11748 } 11463 }
11749 } 11464 }
11750 11465
11751 UUID reqID = httpScriptMod. 11466 UUID reqID
11752 StartHttpRequest(m_localID, m_itemID, url, param, httpHeaders, body); 11467 = httpScriptMod.StartHttpRequest(m_host.LocalId, m_item.ItemID, url, param, httpHeaders, body);
11753 11468
11754 if (reqID != UUID.Zero) 11469 if (reqID != UUID.Zero)
11755 return reqID.ToString(); 11470 return reqID.ToString();
@@ -12003,19 +11718,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12003 break; 11718 break;
12004 // For the following 8 see the Object version below 11719 // For the following 8 see the Object version below
12005 case ScriptBaseClass.OBJECT_RUNNING_SCRIPT_COUNT: 11720 case ScriptBaseClass.OBJECT_RUNNING_SCRIPT_COUNT:
12006 ret.Add(new LSL_Integer(0)); 11721 ret.Add(new LSL_Integer(av.RunningScriptCount()));
12007 break; 11722 break;
12008 case ScriptBaseClass.OBJECT_TOTAL_SCRIPT_COUNT: 11723 case ScriptBaseClass.OBJECT_TOTAL_SCRIPT_COUNT:
12009 ret.Add(new LSL_Integer(0)); 11724 ret.Add(new LSL_Integer(av.ScriptCount()));
12010 break; 11725 break;
12011 case ScriptBaseClass.OBJECT_SCRIPT_MEMORY: 11726 case ScriptBaseClass.OBJECT_SCRIPT_MEMORY:
12012 ret.Add(new LSL_Integer(0)); 11727 ret.Add(new LSL_Integer(av.RunningScriptCount() * 16384));
12013 break; 11728 break;
12014 case ScriptBaseClass.OBJECT_SCRIPT_TIME: 11729 case ScriptBaseClass.OBJECT_SCRIPT_TIME:
12015 ret.Add(new LSL_Float(0)); 11730 ret.Add(new LSL_Float(av.ScriptExecutionTime() / 1000.0f));
12016 break; 11731 break;
12017 case ScriptBaseClass.OBJECT_PRIM_EQUIVALENCE: 11732 case ScriptBaseClass.OBJECT_PRIM_EQUIVALENCE:
12018 ret.Add(new LSL_Integer(0)); 11733 ret.Add(new LSL_Integer(1));
12019 break; 11734 break;
12020 case ScriptBaseClass.OBJECT_SERVER_COST: 11735 case ScriptBaseClass.OBJECT_SERVER_COST:
12021 ret.Add(new LSL_Float(0)); 11736 ret.Add(new LSL_Float(0));
@@ -12073,37 +11788,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12073 case ScriptBaseClass.OBJECT_CREATOR: 11788 case ScriptBaseClass.OBJECT_CREATOR:
12074 ret.Add(new LSL_String(obj.CreatorID.ToString())); 11789 ret.Add(new LSL_String(obj.CreatorID.ToString()));
12075 break; 11790 break;
12076 // The following 8 I have intentionaly coded to return zero. They are part of
12077 // "Land Impact" calculations. These calculations are probably not applicable
12078 // to OpenSim, required figures (cpu/memory usage) are not currently tracked
12079 // I have intentionally left these all at zero rather than return possibly
12080 // missleading numbers
12081 case ScriptBaseClass.OBJECT_RUNNING_SCRIPT_COUNT: 11791 case ScriptBaseClass.OBJECT_RUNNING_SCRIPT_COUNT:
12082 // in SL this currently includes crashed scripts 11792 ret.Add(new LSL_Integer(obj.ParentGroup.RunningScriptCount()));
12083 ret.Add(new LSL_Integer(0));
12084 break; 11793 break;
12085 case ScriptBaseClass.OBJECT_TOTAL_SCRIPT_COUNT: 11794 case ScriptBaseClass.OBJECT_TOTAL_SCRIPT_COUNT:
12086 ret.Add(new LSL_Integer(0)); 11795 ret.Add(new LSL_Integer(obj.ParentGroup.ScriptCount()));
12087 break; 11796 break;
12088 case ScriptBaseClass.OBJECT_SCRIPT_MEMORY: 11797 case ScriptBaseClass.OBJECT_SCRIPT_MEMORY:
12089 // The value returned in SL for mono scripts is 65536 * number of active scripts 11798 // The value returned in SL for mono scripts is 65536 * number of active scripts
12090 ret.Add(new LSL_Integer(0)); 11799 // and 16384 * number of active scripts for LSO. since llGetFreememory
11800 // is coded to give the LSO value use it here
11801 ret.Add(new LSL_Integer(obj.ParentGroup.RunningScriptCount() * 16384));
12091 break; 11802 break;
12092 case ScriptBaseClass.OBJECT_SCRIPT_TIME: 11803 case ScriptBaseClass.OBJECT_SCRIPT_TIME:
12093 // Average cpu time per simulator frame expended on all scripts in the objetc 11804 // Average cpu time in seconds per simulator frame expended on all scripts in the object
12094 ret.Add(new LSL_Float(0)); 11805 ret.Add(new LSL_Float(obj.ParentGroup.ScriptExecutionTime() / 1000.0f));
12095 break; 11806 break;
12096 case ScriptBaseClass.OBJECT_PRIM_EQUIVALENCE: 11807 case ScriptBaseClass.OBJECT_PRIM_EQUIVALENCE:
12097 // according to the SL wiki A prim or linkset will have prim 11808 // according to the SL wiki A prim or linkset will have prim
12098 // equivalent of the number of prims in a linkset if it does not 11809 // equivalent of the number of prims in a linkset if it does not
12099 // contain a mesh anywhere in the link set or is not a normal prim 11810 // contain a mesh anywhere in the link set or is not a normal prim
12100 // The value returned in SL for normal prims is prim count 11811 // The value returned in SL for normal prims is prim count
12101 ret.Add(new LSL_Integer(0)); 11812 ret.Add(new LSL_Integer(obj.ParentGroup.PrimCount));
12102 break; 11813 break;
12103 11814
12104 // costs below may need to be diferent for root parts, need to check 11815 // costs below may need to be diferent for root parts, need to check
12105 case ScriptBaseClass.OBJECT_SERVER_COST: 11816 case ScriptBaseClass.OBJECT_SERVER_COST:
12106 // The value returned in SL for normal prims is prim count 11817 // The linden calculation is here
11818 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Server_Weight
11819 // The value returned in SL for normal prims looks like the prim count
12107 ret.Add(new LSL_Float(0)); 11820 ret.Add(new LSL_Float(0));
12108 break; 11821 break;
12109 case ScriptBaseClass.OBJECT_STREAMING_COST: 11822 case ScriptBaseClass.OBJECT_STREAMING_COST:
@@ -12128,22 +11841,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12128 return new LSL_List(); 11841 return new LSL_List();
12129 } 11842 }
12130 11843
12131 internal UUID ScriptByName(string name) 11844 internal UUID GetScriptByName(string name)
12132 { 11845 {
12133 m_host.TaskInventory.LockItemsForRead(true); 11846 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name);
12134 11847
12135 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 11848 if (item == null || item.Type != 10)
12136 { 11849 return UUID.Zero;
12137 if (item.Type == 10 && item.Name == name)
12138 {
12139 m_host.TaskInventory.LockItemsForRead(false);
12140 return item.ItemID;
12141 }
12142 }
12143
12144 m_host.TaskInventory.LockItemsForRead(false);
12145 11850
12146 return UUID.Zero; 11851 return item.ItemID;
12147 } 11852 }
12148 11853
12149 internal void ShoutError(string msg) 11854 internal void ShoutError(string msg)
@@ -12183,21 +11888,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12183 { 11888 {
12184 m_host.AddScriptLPS(1); 11889 m_host.AddScriptLPS(1);
12185 11890
12186 //Clone is thread safe
12187 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
12188
12189 UUID assetID = UUID.Zero; 11891 UUID assetID = UUID.Zero;
12190 11892
12191 if (!UUID.TryParse(name, out assetID)) 11893 if (!UUID.TryParse(name, out assetID))
12192 { 11894 {
12193 foreach (TaskInventoryItem item in itemsDictionary.Values) 11895 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name);
12194 { 11896
12195 if (item.Type == 7 && item.Name == name) 11897 if (item != null && item.Type == 7)
12196 { 11898 assetID = item.AssetID;
12197 assetID = item.AssetID;
12198 break;
12199 }
12200 }
12201 } 11899 }
12202 11900
12203 if (assetID == UUID.Zero) 11901 if (assetID == UUID.Zero)
@@ -12209,7 +11907,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12209 } 11907 }
12210 11908
12211 // was: UUID tid = tid = AsyncCommands. 11909 // was: UUID tid = tid = AsyncCommands.
12212 UUID tid = AsyncCommands.DataserverPlugin.RegisterRequest(m_localID, m_itemID, assetID.ToString()); 11910 UUID tid = AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, assetID.ToString());
12213 11911
12214 if (NotecardCache.IsCached(assetID)) 11912 if (NotecardCache.IsCached(assetID))
12215 { 11913 {
@@ -12228,9 +11926,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12228 return; 11926 return;
12229 } 11927 }
12230 11928
12231 System.Text.UTF8Encoding enc = 11929 string data = Encoding.UTF8.GetString(a.Data);
12232 new System.Text.UTF8Encoding();
12233 string data = enc.GetString(a.Data);
12234 //m_log.Debug(data); 11930 //m_log.Debug(data);
12235 NotecardCache.Cache(id, data); 11931 NotecardCache.Cache(id, data);
12236 AsyncCommands. 11932 AsyncCommands.
@@ -12246,21 +11942,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12246 { 11942 {
12247 m_host.AddScriptLPS(1); 11943 m_host.AddScriptLPS(1);
12248 11944
12249 //Clone is thread safe
12250 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
12251
12252 UUID assetID = UUID.Zero; 11945 UUID assetID = UUID.Zero;
12253 11946
12254 if (!UUID.TryParse(name, out assetID)) 11947 if (!UUID.TryParse(name, out assetID))
12255 { 11948 {
12256 foreach (TaskInventoryItem item in itemsDictionary.Values) 11949 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name);
12257 { 11950
12258 if (item.Type == 7 && item.Name == name) 11951 if (item != null && item.Type == 7)
12259 { 11952 assetID = item.AssetID;
12260 assetID = item.AssetID;
12261 break;
12262 }
12263 }
12264 } 11953 }
12265 11954
12266 if (assetID == UUID.Zero) 11955 if (assetID == UUID.Zero)
@@ -12272,7 +11961,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12272 } 11961 }
12273 11962
12274 // was: UUID tid = tid = AsyncCommands. 11963 // was: UUID tid = tid = AsyncCommands.
12275 UUID tid = AsyncCommands.DataserverPlugin.RegisterRequest(m_localID, m_itemID, assetID.ToString()); 11964 UUID tid = AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, assetID.ToString());
12276 11965
12277 if (NotecardCache.IsCached(assetID)) 11966 if (NotecardCache.IsCached(assetID))
12278 { 11967 {
@@ -12290,9 +11979,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12290 return; 11979 return;
12291 } 11980 }
12292 11981
12293 System.Text.UTF8Encoding enc = 11982 string data = Encoding.UTF8.GetString(a.Data);
12294 new System.Text.UTF8Encoding();
12295 string data = enc.GetString(a.Data);
12296 //m_log.Debug(data); 11983 //m_log.Debug(data);
12297 NotecardCache.Cache(id, data); 11984 NotecardCache.Cache(id, data);
12298 AsyncCommands.DataserverPlugin.DataserverReply(id.ToString(), 11985 AsyncCommands.DataserverPlugin.DataserverReply(id.ToString(),
@@ -12356,7 +12043,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12356 { 12043 {
12357 UUID rq = UUID.Random(); 12044 UUID rq = UUID.Random();
12358 12045
12359 AsyncCommands.DataserverPlugin.RegisterRequest(m_localID, m_itemID, rq.ToString()); 12046 AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, rq.ToString());
12360 12047
12361 AsyncCommands.DataserverPlugin.DataserverReply(rq.ToString(), Name2Username(llKey2Name(id))); 12048 AsyncCommands.DataserverPlugin.DataserverReply(rq.ToString(), Name2Username(llKey2Name(id)));
12362 12049
@@ -12372,7 +12059,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12372 { 12059 {
12373 UUID rq = UUID.Random(); 12060 UUID rq = UUID.Random();
12374 12061
12375 AsyncCommands.DataserverPlugin.RegisterRequest(m_localID, m_itemID, rq.ToString()); 12062 AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, rq.ToString());
12376 12063
12377 AsyncCommands.DataserverPlugin.DataserverReply(rq.ToString(), llKey2Name(id)); 12064 AsyncCommands.DataserverPlugin.DataserverReply(rq.ToString(), llKey2Name(id));
12378 12065
@@ -12574,7 +12261,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12574 { 12261 {
12575 Tri t1 = new Tri(); 12262 Tri t1 = new Tri();
12576 Tri t2 = new Tri(); 12263 Tri t2 = new Tri();
12577 12264
12578 Vector3 p1 = new Vector3(x-1, y-1, (float)heightfield[x-1, y-1]); 12265 Vector3 p1 = new Vector3(x-1, y-1, (float)heightfield[x-1, y-1]);
12579 Vector3 p2 = new Vector3(x, y-1, (float)heightfield[x, y-1]); 12266 Vector3 p2 = new Vector3(x, y-1, (float)heightfield[x, y-1]);
12580 Vector3 p3 = new Vector3(x, y, (float)heightfield[x, y]); 12267 Vector3 p3 = new Vector3(x, y, (float)heightfield[x, y]);
@@ -12615,7 +12302,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12615 // sometimes 12302 // sometimes
12616 if (Math.Abs(b) < 0.000001) 12303 if (Math.Abs(b) < 0.000001)
12617 continue; 12304 continue;
12618 12305
12619 double r = a / b; 12306 double r = a / b;
12620 12307
12621 // ray points away from plane 12308 // ray points away from plane
@@ -12875,7 +12562,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12875 bool isAccount = false; 12562 bool isAccount = false;
12876 bool isGroup = false; 12563 bool isGroup = false;
12877 12564
12878 if (!estate.IsEstateOwner(m_host.OwnerID) || !estate.IsEstateManager(m_host.OwnerID)) 12565 if (!estate.IsEstateOwner(m_host.OwnerID) || !estate.IsEstateManagerOrOwner(m_host.OwnerID))
12879 return 0; 12566 return 0;
12880 12567
12881 UUID id = new UUID(); 12568 UUID id = new UUID();
@@ -12937,35 +12624,50 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12937 return 1; 12624 return 1;
12938 } 12625 }
12939 12626
12940 #region Not Implemented 12627 public LSL_Integer llGetMemoryLimit()
12941 // 12628 {
12942 // Listing the unimplemented lsl functions here, please move 12629 m_host.AddScriptLPS(1);
12943 // them from this region as they are completed 12630 // The value returned for LSO scripts in SL
12944 // 12631 return 16384;
12632 }
12945 12633
12946 public void llGetEnv(LSL_String name) 12634 public LSL_Integer llSetMemoryLimit(LSL_Integer limit)
12947 { 12635 {
12948 m_host.AddScriptLPS(1); 12636 m_host.AddScriptLPS(1);
12949 NotImplemented("llGetEnv"); 12637 // Treat as an LSO script
12638 return ScriptBaseClass.FALSE;
12950 } 12639 }
12951 12640
12952 public void llGetSPMaxMemory() 12641 public LSL_Integer llGetSPMaxMemory()
12953 { 12642 {
12954 m_host.AddScriptLPS(1); 12643 m_host.AddScriptLPS(1);
12955 NotImplemented("llGetSPMaxMemory"); 12644 // The value returned for LSO scripts in SL
12645 return 16384;
12956 } 12646 }
12957 12647
12958 public virtual LSL_Integer llGetUsedMemory() 12648 public virtual LSL_Integer llGetUsedMemory()
12959 { 12649 {
12960 m_host.AddScriptLPS(1); 12650 m_host.AddScriptLPS(1);
12961 NotImplemented("llGetUsedMemory"); 12651 // The value returned for LSO scripts in SL
12962 return 0; 12652 return 16384;
12963 } 12653 }
12964 12654
12965 public void llScriptProfiler(LSL_Integer flags) 12655 public void llScriptProfiler(LSL_Integer flags)
12966 { 12656 {
12967 m_host.AddScriptLPS(1); 12657 m_host.AddScriptLPS(1);
12968 //NotImplemented("llScriptProfiler"); 12658 // This does nothing for LSO scripts in SL
12659 }
12660
12661 #region Not Implemented
12662 //
12663 // Listing the unimplemented lsl functions here, please move
12664 // them from this region as they are completed
12665 //
12666
12667 public void llGetEnv(LSL_String name)
12668 {
12669 m_host.AddScriptLPS(1);
12670 NotImplemented("llGetEnv");
12969 } 12671 }
12970 12672
12971 public void llSetSoundQueueing(int queue) 12673 public void llSetSoundQueueing(int queue)
@@ -13045,8 +12747,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13045 12747
13046 try 12748 try
13047 { 12749 {
13048 UUID invItemID=InventorySelf(); 12750 TaskInventoryItem item = m_item;
13049 if (invItemID == UUID.Zero) 12751 if (item == null)
13050 { 12752 {
13051 replydata = "SERVICE_ERROR"; 12753 replydata = "SERVICE_ERROR";
13052 return; 12754 return;
@@ -13054,10 +12756,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13054 12756
13055 m_host.AddScriptLPS(1); 12757 m_host.AddScriptLPS(1);
13056 12758
13057 m_host.TaskInventory.LockItemsForRead(true);
13058 TaskInventoryItem item = m_host.TaskInventory[invItemID];
13059 m_host.TaskInventory.LockItemsForRead(false);
13060
13061 if (item.PermsGranter == UUID.Zero) 12759 if (item.PermsGranter == UUID.Zero)
13062 { 12760 {
13063 replydata = "MISSING_PERMISSION_DEBIT"; 12761 replydata = "MISSING_PERMISSION_DEBIT";
@@ -13099,7 +12797,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13099 } 12797 }
13100 finally 12798 finally
13101 { 12799 {
13102 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 12800 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
13103 "transaction_result", new Object[] { 12801 "transaction_result", new Object[] {
13104 new LSL_String(txn.ToString()), 12802 new LSL_String(txn.ToString()),
13105 new LSL_Integer(replycode), 12803 new LSL_Integer(replycode),
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
index 77a784d..795de80 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
@@ -58,17 +58,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
58 { 58 {
59 internal IScriptEngine m_ScriptEngine; 59 internal IScriptEngine m_ScriptEngine;
60 internal SceneObjectPart m_host; 60 internal SceneObjectPart m_host;
61 internal uint m_localID;
62 internal UUID m_itemID;
63 internal bool m_LSFunctionsEnabled = false; 61 internal bool m_LSFunctionsEnabled = false;
64 internal IScriptModuleComms m_comms = null; 62 internal IScriptModuleComms m_comms = null;
65 63
66 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) 64 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item)
67 { 65 {
68 m_ScriptEngine = ScriptEngine; 66 m_ScriptEngine = ScriptEngine;
69 m_host = host; 67 m_host = host;
70 m_localID = localID;
71 m_itemID = itemID;
72 68
73 if (m_ScriptEngine.Config.GetBoolean("AllowLightShareFunctions", false)) 69 if (m_ScriptEngine.Config.GetBoolean("AllowLightShareFunctions", false))
74 m_LSFunctionsEnabled = true; 70 m_LSFunctionsEnabled = true;
@@ -449,7 +445,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
449 LSShoutError("LightShare functions are not enabled."); 445 LSShoutError("LightShare functions are not enabled.");
450 return 0; 446 return 0;
451 } 447 }
452 if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) 448 if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200)
453 { 449 {
454 LSShoutError("lsSetWindlightScene can only be used by estate managers or owners."); 450 LSShoutError("lsSetWindlightScene can only be used by estate managers or owners.");
455 return 0; 451 return 0;
@@ -477,7 +473,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
477 LSShoutError("LightShare functions are not enabled."); 473 LSShoutError("LightShare functions are not enabled.");
478 return; 474 return;
479 } 475 }
480 if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) 476 if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200)
481 { 477 {
482 LSShoutError("lsSetWindlightScene can only be used by estate managers or owners."); 478 LSShoutError("lsSetWindlightScene can only be used by estate managers or owners.");
483 return; 479 return;
@@ -500,7 +496,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
500 LSShoutError("LightShare functions are not enabled."); 496 LSShoutError("LightShare functions are not enabled.");
501 return 0; 497 return 0;
502 } 498 }
503 if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) 499 if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200)
504 { 500 {
505 LSShoutError("lsSetWindlightSceneTargeted can only be used by estate managers or owners."); 501 LSShoutError("lsSetWindlightSceneTargeted can only be used by estate managers or owners.");
506 return 0; 502 return 0;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
index 7c07e15..4bd3dff 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
@@ -57,17 +57,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
57 { 57 {
58 internal IScriptEngine m_ScriptEngine; 58 internal IScriptEngine m_ScriptEngine;
59 internal SceneObjectPart m_host; 59 internal SceneObjectPart m_host;
60 internal uint m_localID; 60 internal TaskInventoryItem m_item;
61 internal UUID m_itemID;
62 internal bool m_MODFunctionsEnabled = false; 61 internal bool m_MODFunctionsEnabled = false;
63 internal IScriptModuleComms m_comms = null; 62 internal IScriptModuleComms m_comms = null;
64 63
65 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) 64 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item)
66 { 65 {
67 m_ScriptEngine = ScriptEngine; 66 m_ScriptEngine = ScriptEngine;
68 m_host = host; 67 m_host = host;
69 m_localID = localID; 68 m_item = item;
70 m_itemID = itemID;
71 69
72 if (m_ScriptEngine.Config.GetBoolean("AllowMODFunctions", false)) 70 if (m_ScriptEngine.Config.GetBoolean("AllowMODFunctions", false))
73 m_MODFunctionsEnabled = true; 71 m_MODFunctionsEnabled = true;
@@ -252,7 +250,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
252 // non-null but don't trust it completely 250 // non-null but don't trust it completely
253 try 251 try
254 { 252 {
255 object result = m_comms.InvokeOperation(m_host.UUID, m_itemID, fname, convertedParms); 253 object result = m_comms.InvokeOperation(m_host.UUID, m_item.ItemID, fname, convertedParms);
256 if (result != null) 254 if (result != null)
257 return result; 255 return result;
258 256
@@ -279,7 +277,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
279 277
280 UUID req = UUID.Random(); 278 UUID req = UUID.Random();
281 279
282 m_comms.RaiseEvent(m_itemID, req.ToString(), module, command, k); 280 m_comms.RaiseEvent(m_item.ItemID, req.ToString(), module, command, k);
283 281
284 return req.ToString(); 282 return req.ToString();
285 } 283 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 0dc2aa2..29d0342 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -126,13 +126,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
126 [Serializable] 126 [Serializable]
127 public class OSSL_Api : MarshalByRefObject, IOSSL_Api, IScriptApi 127 public class OSSL_Api : MarshalByRefObject, IOSSL_Api, IScriptApi
128 { 128 {
129// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 129 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
130
131 public const string GridInfoServiceConfigSectionName = "GridInfoService";
130 132
131 internal IScriptEngine m_ScriptEngine; 133 internal IScriptEngine m_ScriptEngine;
132 internal ILSL_Api m_LSL_Api = null; // get a reference to the LSL API so we can call methods housed there 134 internal ILSL_Api m_LSL_Api = null; // get a reference to the LSL API so we can call methods housed there
133 internal SceneObjectPart m_host; 135 internal SceneObjectPart m_host;
134 internal uint m_localID; 136 internal TaskInventoryItem m_item;
135 internal UUID m_itemID;
136 internal bool m_OSFunctionsEnabled = false; 137 internal bool m_OSFunctionsEnabled = false;
137 internal ThreatLevel m_MaxThreatLevel = ThreatLevel.VeryLow; 138 internal ThreatLevel m_MaxThreatLevel = ThreatLevel.VeryLow;
138 internal float m_ScriptDelayFactor = 1.0f; 139 internal float m_ScriptDelayFactor = 1.0f;
@@ -140,12 +141,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
140 internal bool m_debuggerSafe = false; 141 internal bool m_debuggerSafe = false;
141 internal Dictionary<string, FunctionPerms > m_FunctionPerms = new Dictionary<string, FunctionPerms >(); 142 internal Dictionary<string, FunctionPerms > m_FunctionPerms = new Dictionary<string, FunctionPerms >();
142 143
143 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) 144 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item)
144 { 145 {
145 m_ScriptEngine = ScriptEngine; 146 m_ScriptEngine = ScriptEngine;
146 m_host = host; 147 m_host = host;
147 m_localID = localID; 148 m_item = item;
148 m_itemID = itemID;
149 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false); 149 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
150 150
151 if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false)) 151 if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false))
@@ -218,12 +218,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
218 } 218 }
219 } 219 }
220 220
221 /// <summary>
222 /// Initialize the LSL interface.
223 /// </summary>
224 /// <remarks>
225 /// FIXME: This is an abomination. We should be able to set this up earlier but currently we have no
226 /// guarantee the interface is present on Initialize(). There needs to be another post initialize call from
227 /// ScriptInstance.
228 /// </remarks>
221 private void InitLSL() 229 private void InitLSL()
222 { 230 {
223 if (m_LSL_Api != null) 231 if (m_LSL_Api != null)
224 return; 232 return;
225 233
226 m_LSL_Api = (ILSL_Api)m_ScriptEngine.GetApi(m_itemID, "LSL"); 234 m_LSL_Api = (ILSL_Api)m_ScriptEngine.GetApi(m_item.ItemID, "LSL");
227 } 235 }
228 236
229 // 237 //
@@ -342,22 +350,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
342 return; 350 return;
343 } 351 }
344 352
345 TaskInventoryItem ti = m_host.Inventory.GetInventoryItem(m_itemID); 353 UUID ownerID = m_item.OwnerID;
346 if (ti == null)
347 {
348 OSSLError(
349 String.Format("{0} permission error. Can't find script in prim inventory.",
350 function));
351 }
352
353 UUID ownerID = ti.OwnerID;
354 354
355 //OSSL only may be used if objet is in the same group as the parcel 355 //OSSL only may be used if object is in the same group as the parcel
356 if (m_FunctionPerms[function].AllowedOwnerClasses.Contains("PARCEL_GROUP_MEMBER")) 356 if (m_FunctionPerms[function].AllowedOwnerClasses.Contains("PARCEL_GROUP_MEMBER"))
357 { 357 {
358 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); 358 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
359 359
360 if (land.LandData.GroupID == ti.GroupID && land.LandData.GroupID != UUID.Zero) 360 if (land.LandData.GroupID == m_item.GroupID && land.LandData.GroupID != UUID.Zero)
361 { 361 {
362 return; 362 return;
363 } 363 }
@@ -378,7 +378,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
378 if (m_FunctionPerms[function].AllowedOwnerClasses.Contains("ESTATE_MANAGER")) 378 if (m_FunctionPerms[function].AllowedOwnerClasses.Contains("ESTATE_MANAGER"))
379 { 379 {
380 //Only Estate Managers may use the function 380 //Only Estate Managers may use the function
381 if (World.RegionInfo.EstateSettings.IsEstateManager(ownerID) && World.RegionInfo.EstateSettings.EstateOwner != ownerID) 381 if (World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(ownerID) && World.RegionInfo.EstateSettings.EstateOwner != ownerID)
382 { 382 {
383 return; 383 return;
384 } 384 }
@@ -393,13 +393,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
393 } 393 }
394 } 394 }
395 395
396 if (!m_FunctionPerms[function].AllowedCreators.Contains(ti.CreatorID)) 396 if (!m_FunctionPerms[function].AllowedCreators.Contains(m_item.CreatorID))
397 OSSLError( 397 OSSLError(
398 String.Format("{0} permission denied. Script creator is not in the list of users allowed to execute this function and prim owner also has no permission.", 398 String.Format("{0} permission denied. Script creator is not in the list of users allowed to execute this function and prim owner also has no permission.",
399 function)); 399 function));
400 if (ti.CreatorID != ownerID) 400
401 if (m_item.CreatorID != ownerID)
401 { 402 {
402 if ((ti.CurrentPermissions & (uint)PermissionMask.Modify) != 0) 403 if ((m_item.CurrentPermissions & (uint)PermissionMask.Modify) != 0)
403 OSSLError( 404 OSSLError(
404 String.Format("{0} permission denied. Script permissions error.", 405 String.Format("{0} permission denied. Script permissions error.",
405 function)); 406 function));
@@ -730,11 +731,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
730 731
731 m_host.AddScriptLPS(1); 732 m_host.AddScriptLPS(1);
732 733
734 // For safety, we add another permission check here, and don't rely only on the standard OSSL permissions
733 if (World.Permissions.CanRunConsoleCommand(m_host.OwnerID)) 735 if (World.Permissions.CanRunConsoleCommand(m_host.OwnerID))
734 { 736 {
735 MainConsole.Instance.RunCommand(command); 737 MainConsole.Instance.RunCommand(command);
736 return true; 738 return true;
737 } 739 }
740
738 return false; 741 return false;
739 } 742 }
740 743
@@ -880,13 +883,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
880 if (World.Entities.ContainsKey((UUID)agent) && World.Entities[avatarID] is ScenePresence) 883 if (World.Entities.ContainsKey((UUID)agent) && World.Entities[avatarID] is ScenePresence)
881 { 884 {
882 ScenePresence target = (ScenePresence)World.Entities[avatarID]; 885 ScenePresence target = (ScenePresence)World.Entities[avatarID];
883 EndPoint ep = target.ControllingClient.GetClientEP(); 886 return target.ControllingClient.RemoteEndPoint.Address.ToString();
884 if (ep is IPEndPoint)
885 {
886 IPEndPoint ip = (IPEndPoint)ep;
887 return ip.Address.ToString();
888 }
889 } 887 }
888
890 // fall through case, just return nothing 889 // fall through case, just return nothing
891 return ""; 890 return "";
892 } 891 }
@@ -957,21 +956,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
957 UUID avatarID = (UUID)avatar; 956 UUID avatarID = (UUID)avatar;
958 957
959 m_host.AddScriptLPS(1); 958 m_host.AddScriptLPS(1);
959
960 // FIXME: What we really want to do here is factor out the similar code in llStopAnimation() to a common
961 // method (though see that doesn't do the is animation check, which is probably a bug) and have both
962 // these functions call that common code. However, this does mean navigating the brain-dead requirement
963 // of calling InitLSL()
960 if (World.Entities.ContainsKey(avatarID) && World.Entities[avatarID] is ScenePresence) 964 if (World.Entities.ContainsKey(avatarID) && World.Entities[avatarID] is ScenePresence)
961 { 965 {
962 ScenePresence target = (ScenePresence)World.Entities[avatarID]; 966 ScenePresence target = (ScenePresence)World.Entities[avatarID];
963 if (target != null) 967 if (target != null)
964 { 968 {
965 UUID animID = UUID.Zero; 969 UUID animID;
966 m_host.TaskInventory.LockItemsForRead(true); 970
967 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 971 if (!UUID.TryParse(animation, out animID))
968 { 972 {
969 if (inv.Value.Name == animation) 973 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(animation);
970 { 974 if (item != null && item.Type == (int)AssetType.Animation)
971 if (inv.Value.Type == (int)AssetType.Animation) 975 animID = item.AssetID;
972 animID = inv.Value.AssetID; 976 else
973 continue; 977 animID = UUID.Zero;
974 }
975 } 978 }
976 m_host.TaskInventory.LockItemsForRead(false); 979 m_host.TaskInventory.LockItemsForRead(false);
977 980
@@ -1178,7 +1181,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1178 CheckThreatLevel(ThreatLevel.High, "osSetStateEvents"); 1181 CheckThreatLevel(ThreatLevel.High, "osSetStateEvents");
1179 m_host.AddScriptLPS(1); 1182 m_host.AddScriptLPS(1);
1180 1183
1181 m_host.SetScriptEvents(m_itemID, events); 1184 m_host.SetScriptEvents(m_item.ItemID, events);
1182 } 1185 }
1183 1186
1184 public void osSetRegionWaterHeight(double height) 1187 public void osSetRegionWaterHeight(double height)
@@ -1186,12 +1189,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1186 CheckThreatLevel(ThreatLevel.High, "osSetRegionWaterHeight"); 1189 CheckThreatLevel(ThreatLevel.High, "osSetRegionWaterHeight");
1187 1190
1188 m_host.AddScriptLPS(1); 1191 m_host.AddScriptLPS(1);
1189 //Check to make sure that the script's owner is the estate manager/master 1192
1190 //World.Permissions.GenericEstatePermission( 1193 World.EventManager.TriggerRequestChangeWaterHeight((float)height);
1191 if (World.Permissions.IsGod(m_host.OwnerID))
1192 {
1193 World.EventManager.TriggerRequestChangeWaterHeight((float)height);
1194 }
1195 } 1194 }
1196 1195
1197 /// <summary> 1196 /// <summary>
@@ -1202,27 +1201,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1202 /// <param name="sunHour">The "Sun Hour" that is desired, 0...24, with 0 just after SunRise</param> 1201 /// <param name="sunHour">The "Sun Hour" that is desired, 0...24, with 0 just after SunRise</param>
1203 public void osSetRegionSunSettings(bool useEstateSun, bool sunFixed, double sunHour) 1202 public void osSetRegionSunSettings(bool useEstateSun, bool sunFixed, double sunHour)
1204 { 1203 {
1205 CheckThreatLevel(ThreatLevel.Nuisance, "osSetRegionSunSettings"); 1204 CheckThreatLevel(ThreatLevel.High, "osSetRegionSunSettings");
1206 1205
1207 m_host.AddScriptLPS(1); 1206 m_host.AddScriptLPS(1);
1208 //Check to make sure that the script's owner is the estate manager/master
1209 //World.Permissions.GenericEstatePermission(
1210 if (World.Permissions.IsGod(m_host.OwnerID))
1211 {
1212 while (sunHour > 24.0)
1213 sunHour -= 24.0;
1214 1207
1215 while (sunHour < 0) 1208 while (sunHour > 24.0)
1216 sunHour += 24.0; 1209 sunHour -= 24.0;
1217 1210
1211 while (sunHour < 0)
1212 sunHour += 24.0;
1218 1213
1219 World.RegionInfo.RegionSettings.UseEstateSun = useEstateSun; 1214 World.RegionInfo.RegionSettings.UseEstateSun = useEstateSun;
1220 World.RegionInfo.RegionSettings.SunPosition = sunHour + 6; // LL Region Sun Hour is 6 to 30 1215 World.RegionInfo.RegionSettings.SunPosition = sunHour + 6; // LL Region Sun Hour is 6 to 30
1221 World.RegionInfo.RegionSettings.FixedSun = sunFixed; 1216 World.RegionInfo.RegionSettings.FixedSun = sunFixed;
1222 World.RegionInfo.RegionSettings.Save(); 1217 World.RegionInfo.RegionSettings.Save();
1223 1218
1224 World.EventManager.TriggerEstateToolsSunUpdate(World.RegionInfo.RegionHandle, sunFixed, useEstateSun, (float)sunHour); 1219 World.EventManager.TriggerEstateToolsSunUpdate(
1225 } 1220 World.RegionInfo.RegionHandle, sunFixed, useEstateSun, (float)sunHour);
1226 } 1221 }
1227 1222
1228 /// <summary> 1223 /// <summary>
@@ -1232,26 +1227,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1232 /// <param name="sunHour">The "Sun Hour" that is desired, 0...24, with 0 just after SunRise</param> 1227 /// <param name="sunHour">The "Sun Hour" that is desired, 0...24, with 0 just after SunRise</param>
1233 public void osSetEstateSunSettings(bool sunFixed, double sunHour) 1228 public void osSetEstateSunSettings(bool sunFixed, double sunHour)
1234 { 1229 {
1235 CheckThreatLevel(ThreatLevel.Nuisance, "osSetEstateSunSettings"); 1230 CheckThreatLevel(ThreatLevel.High, "osSetEstateSunSettings");
1236 1231
1237 m_host.AddScriptLPS(1); 1232 m_host.AddScriptLPS(1);
1238 //Check to make sure that the script's owner is the estate manager/master
1239 //World.Permissions.GenericEstatePermission(
1240 if (World.Permissions.IsGod(m_host.OwnerID))
1241 {
1242 while (sunHour > 24.0)
1243 sunHour -= 24.0;
1244 1233
1245 while (sunHour < 0) 1234 while (sunHour > 24.0)
1246 sunHour += 24.0; 1235 sunHour -= 24.0;
1247 1236
1248 World.RegionInfo.EstateSettings.UseGlobalTime = !sunFixed; 1237 while (sunHour < 0)
1249 World.RegionInfo.EstateSettings.SunPosition = sunHour; 1238 sunHour += 24.0;
1250 World.RegionInfo.EstateSettings.FixedSun = sunFixed;
1251 World.RegionInfo.EstateSettings.Save();
1252 1239
1253 World.EventManager.TriggerEstateToolsSunUpdate(World.RegionInfo.RegionHandle, sunFixed, World.RegionInfo.RegionSettings.UseEstateSun, (float)sunHour); 1240 World.RegionInfo.EstateSettings.UseGlobalTime = !sunFixed;
1254 } 1241 World.RegionInfo.EstateSettings.SunPosition = sunHour;
1242 World.RegionInfo.EstateSettings.FixedSun = sunFixed;
1243 World.RegionInfo.EstateSettings.Save();
1244
1245 World.EventManager.TriggerEstateToolsSunUpdate(
1246 World.RegionInfo.RegionHandle, sunFixed, World.RegionInfo.RegionSettings.UseEstateSun, (float)sunHour);
1255 } 1247 }
1256 1248
1257 /// <summary> 1249 /// <summary>
@@ -1627,7 +1619,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1627 1619
1628 public Object osParseJSONNew(string JSON) 1620 public Object osParseJSONNew(string JSON)
1629 { 1621 {
1630 CheckThreatLevel(ThreatLevel.None, "osParseJSON"); 1622 CheckThreatLevel(ThreatLevel.None, "osParseJSONNew");
1631 1623
1632 m_host.AddScriptLPS(1); 1624 m_host.AddScriptLPS(1);
1633 1625
@@ -1681,9 +1673,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1681 CheckThreatLevel(ThreatLevel.Low, "osMessageObject"); 1673 CheckThreatLevel(ThreatLevel.Low, "osMessageObject");
1682 m_host.AddScriptLPS(1); 1674 m_host.AddScriptLPS(1);
1683 1675
1676 UUID objUUID;
1677 if (!UUID.TryParse(objectUUID, out objUUID)) // prior to patching, a thrown exception regarding invalid GUID format would be shouted instead.
1678 {
1679 OSSLShoutError("osMessageObject() cannot send messages to objects with invalid UUIDs");
1680 return;
1681 }
1682
1684 object[] resobj = new object[] { new LSL_Types.LSLString(m_host.UUID.ToString()), new LSL_Types.LSLString(message) }; 1683 object[] resobj = new object[] { new LSL_Types.LSLString(m_host.UUID.ToString()), new LSL_Types.LSLString(message) };
1685 1684
1686 SceneObjectPart sceneOP = World.GetSceneObjectPart(new UUID(objectUUID)); 1685 SceneObjectPart sceneOP = World.GetSceneObjectPart(objUUID);
1686
1687 if (sceneOP == null) // prior to patching, PostObjectEvent() would cause a throw exception to be shouted instead.
1688 {
1689 OSSLShoutError("osMessageObject() cannot send message to " + objUUID.ToString() + ", object was not found in scene.");
1690 return;
1691 }
1687 1692
1688 m_ScriptEngine.PostObjectEvent( 1693 m_ScriptEngine.PostObjectEvent(
1689 sceneOP.LocalId, new EventParams( 1694 sceneOP.LocalId, new EventParams(
@@ -1826,8 +1831,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1826 if (a == null) 1831 if (a == null)
1827 return UUID.Zero; 1832 return UUID.Zero;
1828 1833
1829 System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding(); 1834 string data = Encoding.UTF8.GetString(a.Data);
1830 string data = enc.GetString(a.Data);
1831 NotecardCache.Cache(assetID, data); 1835 NotecardCache.Cache(assetID, data);
1832 }; 1836 };
1833 1837
@@ -1980,7 +1984,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1980 { 1984 {
1981 string retval = String.Empty; 1985 string retval = String.Empty;
1982 IConfigSource config = m_ScriptEngine.ConfigSource; 1986 IConfigSource config = m_ScriptEngine.ConfigSource;
1983 string url = config.Configs["GridInfo"].GetString("GridInfoURI", String.Empty); 1987 string url = null;
1988
1989 IConfig gridInfoConfig = config.Configs["GridInfo"];
1990
1991 if (gridInfoConfig != null)
1992 url = gridInfoConfig.GetString("GridInfoURI", String.Empty);
1984 1993
1985 if (String.IsNullOrEmpty(url)) 1994 if (String.IsNullOrEmpty(url))
1986 return "Configuration Error!"; 1995 return "Configuration Error!";
@@ -2042,8 +2051,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2042 string nick = String.Empty; 2051 string nick = String.Empty;
2043 IConfigSource config = m_ScriptEngine.ConfigSource; 2052 IConfigSource config = m_ScriptEngine.ConfigSource;
2044 2053
2045 if (config.Configs["GridInfo"] != null) 2054 if (config.Configs[GridInfoServiceConfigSectionName] != null)
2046 nick = config.Configs["GridInfo"].GetString("gridnick", nick); 2055 nick = config.Configs[GridInfoServiceConfigSectionName].GetString("gridnick", nick);
2047 2056
2048 if (String.IsNullOrEmpty(nick)) 2057 if (String.IsNullOrEmpty(nick))
2049 nick = GridUserInfo(InfoType.Nick); 2058 nick = GridUserInfo(InfoType.Nick);
@@ -2059,8 +2068,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2059 string name = String.Empty; 2068 string name = String.Empty;
2060 IConfigSource config = m_ScriptEngine.ConfigSource; 2069 IConfigSource config = m_ScriptEngine.ConfigSource;
2061 2070
2062 if (config.Configs["GridInfo"] != null) 2071 if (config.Configs[GridInfoServiceConfigSectionName] != null)
2063 name = config.Configs["GridInfo"].GetString("gridname", name); 2072 name = config.Configs[GridInfoServiceConfigSectionName].GetString("gridname", name);
2064 2073
2065 if (String.IsNullOrEmpty(name)) 2074 if (String.IsNullOrEmpty(name))
2066 name = GridUserInfo(InfoType.Name); 2075 name = GridUserInfo(InfoType.Name);
@@ -2076,8 +2085,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2076 string loginURI = String.Empty; 2085 string loginURI = String.Empty;
2077 IConfigSource config = m_ScriptEngine.ConfigSource; 2086 IConfigSource config = m_ScriptEngine.ConfigSource;
2078 2087
2079 if (config.Configs["GridInfo"] != null) 2088 if (config.Configs[GridInfoServiceConfigSectionName] != null)
2080 loginURI = config.Configs["GridInfo"].GetString("login", loginURI); 2089 loginURI = config.Configs[GridInfoServiceConfigSectionName].GetString("login", loginURI);
2081 2090
2082 if (String.IsNullOrEmpty(loginURI)) 2091 if (String.IsNullOrEmpty(loginURI))
2083 loginURI = GridUserInfo(InfoType.Login); 2092 loginURI = GridUserInfo(InfoType.Login);
@@ -2124,8 +2133,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2124 string retval = String.Empty; 2133 string retval = String.Empty;
2125 IConfigSource config = m_ScriptEngine.ConfigSource; 2134 IConfigSource config = m_ScriptEngine.ConfigSource;
2126 2135
2127 if (config.Configs["GridInfo"] != null) 2136 if (config.Configs[GridInfoServiceConfigSectionName] != null)
2128 retval = config.Configs["GridInfo"].GetString(key, retval); 2137 retval = config.Configs[GridInfoServiceConfigSectionName].GetString(key, retval);
2129 2138
2130 if (String.IsNullOrEmpty(retval)) 2139 if (String.IsNullOrEmpty(retval))
2131 retval = GridUserInfo(InfoType.Custom, key); 2140 retval = GridUserInfo(InfoType.Custom, key);
@@ -2135,7 +2144,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2135 2144
2136 public LSL_String osFormatString(string str, LSL_List strings) 2145 public LSL_String osFormatString(string str, LSL_List strings)
2137 { 2146 {
2138 CheckThreatLevel(ThreatLevel.Low, "osFormatString"); 2147 CheckThreatLevel(ThreatLevel.VeryLow, "osFormatString");
2139 m_host.AddScriptLPS(1); 2148 m_host.AddScriptLPS(1);
2140 2149
2141 return String.Format(str, strings.Data); 2150 return String.Format(str, strings.Data);
@@ -2143,7 +2152,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2143 2152
2144 public LSL_List osMatchString(string src, string pattern, int start) 2153 public LSL_List osMatchString(string src, string pattern, int start)
2145 { 2154 {
2146 CheckThreatLevel(ThreatLevel.High, "osMatchString"); 2155 CheckThreatLevel(ThreatLevel.VeryLow, "osMatchString");
2147 m_host.AddScriptLPS(1); 2156 m_host.AddScriptLPS(1);
2148 2157
2149 LSL_List result = new LSL_List(); 2158 LSL_List result = new LSL_List();
@@ -2185,7 +2194,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2185 2194
2186 public LSL_String osReplaceString(string src, string pattern, string replace, int count, int start) 2195 public LSL_String osReplaceString(string src, string pattern, string replace, int count, int start)
2187 { 2196 {
2188 CheckThreatLevel(ThreatLevel.High, "osReplaceString"); 2197 CheckThreatLevel(ThreatLevel.VeryLow, "osReplaceString");
2189 m_host.AddScriptLPS(1); 2198 m_host.AddScriptLPS(1);
2190 2199
2191 // Normalize indices (if negative). 2200 // Normalize indices (if negative).
@@ -2480,7 +2489,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2480 return; 2489 return;
2481 2490
2482 Vector3 pos = new Vector3((float) position.x, (float) position.y, (float) position.z); 2491 Vector3 pos = new Vector3((float) position.x, (float) position.y, (float) position.z);
2483 module.MoveToTarget(npcId, World, pos, false, true); 2492 module.MoveToTarget(npcId, World, pos, false, true, false);
2484 } 2493 }
2485 } 2494 }
2486 2495
@@ -2505,7 +2514,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2505 World, 2514 World,
2506 pos, 2515 pos,
2507 (options & ScriptBaseClass.OS_NPC_NO_FLY) != 0, 2516 (options & ScriptBaseClass.OS_NPC_NO_FLY) != 0,
2508 (options & ScriptBaseClass.OS_NPC_LAND_AT_TARGET) != 0); 2517 (options & ScriptBaseClass.OS_NPC_LAND_AT_TARGET) != 0,
2518 (options & ScriptBaseClass.OS_NPC_RUNNING) != 0);
2509 } 2519 }
2510 } 2520 }
2511 2521
@@ -2555,7 +2565,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2555 2565
2556 public void osNpcStopMoveToTarget(LSL_Key npc) 2566 public void osNpcStopMoveToTarget(LSL_Key npc)
2557 { 2567 {
2558 CheckThreatLevel(ThreatLevel.VeryLow, "osNpcStopMoveTo"); 2568 CheckThreatLevel(ThreatLevel.High, "osNpcStopMoveToTarget");
2559 m_host.AddScriptLPS(1); 2569 m_host.AddScriptLPS(1);
2560 2570
2561 INPCModule module = World.RequestModuleInterface<INPCModule>(); 2571 INPCModule module = World.RequestModuleInterface<INPCModule>();
@@ -2572,6 +2582,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2572 2582
2573 public void osNpcSay(LSL_Key npc, string message) 2583 public void osNpcSay(LSL_Key npc, string message)
2574 { 2584 {
2585 osNpcSay(npc, 0, message);
2586 }
2587
2588 public void osNpcSay(LSL_Key npc, int channel, string message)
2589 {
2575 CheckThreatLevel(ThreatLevel.High, "osNpcSay"); 2590 CheckThreatLevel(ThreatLevel.High, "osNpcSay");
2576 m_host.AddScriptLPS(1); 2591 m_host.AddScriptLPS(1);
2577 2592
@@ -2583,7 +2598,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2583 if (!module.CheckPermissions(npcId, m_host.OwnerID)) 2598 if (!module.CheckPermissions(npcId, m_host.OwnerID))
2584 return; 2599 return;
2585 2600
2586 module.Say(npcId, World, message); 2601 module.Say(npcId, World, message, channel);
2602 }
2603 }
2604
2605 public void osNpcShout(LSL_Key npc, int channel, string message)
2606 {
2607 CheckThreatLevel(ThreatLevel.High, "osNpcShout");
2608 m_host.AddScriptLPS(1);
2609
2610 INPCModule module = World.RequestModuleInterface<INPCModule>();
2611 if (module != null)
2612 {
2613 UUID npcId = new UUID(npc.m_string);
2614
2615 if (!module.CheckPermissions(npcId, m_host.OwnerID))
2616 return;
2617
2618 module.Shout(npcId, World, message, channel);
2587 } 2619 }
2588 } 2620 }
2589 2621
@@ -2684,6 +2716,58 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2684 } 2716 }
2685 } 2717 }
2686 2718
2719 public void osNpcWhisper(LSL_Key npc, int channel, string message)
2720 {
2721 CheckThreatLevel(ThreatLevel.High, "osNpcWhisper");
2722 m_host.AddScriptLPS(1);
2723
2724 INPCModule module = World.RequestModuleInterface<INPCModule>();
2725 if (module != null)
2726 {
2727 UUID npcId = new UUID(npc.m_string);
2728
2729 if (!module.CheckPermissions(npcId, m_host.OwnerID))
2730 return;
2731
2732 module.Whisper(npcId, World, message, channel);
2733 }
2734 }
2735
2736 public void osNpcTouch(LSL_Key npcLSL_Key, LSL_Key object_key, LSL_Integer link_num)
2737 {
2738 CheckThreatLevel(ThreatLevel.High, "osNpcTouch");
2739 m_host.AddScriptLPS(1);
2740 INPCModule module = World.RequestModuleInterface<INPCModule>();
2741 int linkNum = link_num.value;
2742 if (module != null || (linkNum < 0 && linkNum != ScriptBaseClass.LINK_THIS))
2743 {
2744 UUID npcId;
2745 if (!UUID.TryParse(npcLSL_Key, out npcId) || !module.CheckPermissions(npcId, m_host.OwnerID))
2746 return;
2747 SceneObjectPart part = null;
2748 UUID objectId;
2749 if (UUID.TryParse(LSL_String.ToString(object_key), out objectId))
2750 part = World.GetSceneObjectPart(objectId);
2751 if (part == null)
2752 return;
2753 if (linkNum != ScriptBaseClass.LINK_THIS)
2754 {
2755 if (linkNum == 0 || linkNum == ScriptBaseClass.LINK_ROOT)
2756 { // 0 and 1 are treated as root, find the root if the current part isnt it
2757 if (!part.IsRoot)
2758 part = part.ParentGroup.RootPart;
2759 }
2760 else
2761 { // Find the prim with the given link number if not found then fail silently
2762 part = part.ParentGroup.GetLinkNumPart(linkNum);
2763 if (part == null)
2764 return;
2765 }
2766 }
2767 module.Touch(npcId, part.UUID);
2768 }
2769 }
2770
2687 /// <summary> 2771 /// <summary>
2688 /// Save the current appearance of the script owner permanently to the named notecard. 2772 /// Save the current appearance of the script owner permanently to the named notecard.
2689 /// </summary> 2773 /// </summary>
@@ -2835,21 +2919,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2835 CheckThreatLevel(ThreatLevel.Severe, "osKickAvatar"); 2919 CheckThreatLevel(ThreatLevel.Severe, "osKickAvatar");
2836 m_host.AddScriptLPS(1); 2920 m_host.AddScriptLPS(1);
2837 2921
2838 if (World.Permissions.CanRunConsoleCommand(m_host.OwnerID)) 2922 World.ForEachRootScenePresence(delegate(ScenePresence sp)
2839 { 2923 {
2840 World.ForEachRootScenePresence(delegate(ScenePresence sp) 2924 if (sp.Firstname == FirstName && sp.Lastname == SurName)
2841 { 2925 {
2842 if (sp.Firstname == FirstName && sp.Lastname == SurName) 2926 // kick client...
2843 { 2927 if (alert != null)
2844 // kick client... 2928 sp.ControllingClient.Kick(alert);
2845 if (alert != null)
2846 sp.ControllingClient.Kick(alert);
2847 2929
2848 // ...and close on our side 2930 // ...and close on our side
2849 sp.Scene.IncomingCloseAgent(sp.UUID); 2931 sp.Scene.IncomingCloseAgent(sp.UUID);
2850 } 2932 }
2851 }); 2933 });
2852 }
2853 } 2934 }
2854 2935
2855 public void osCauseDamage(string avatar, double damage) 2936 public void osCauseDamage(string avatar, double damage)
@@ -3095,5 +3176,151 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3095 3176
3096 return ScriptBaseClass.TRUE; 3177 return ScriptBaseClass.TRUE;
3097 } 3178 }
3179
3180 /// <summary>
3181 /// Sets terrain estate texture
3182 /// </summary>
3183 /// <param name="level"></param>
3184 /// <param name="texture"></param>
3185 /// <returns></returns>
3186 public void osSetTerrainTexture(int level, LSL_Key texture)
3187 {
3188 CheckThreatLevel(ThreatLevel.High, "osSetTerrainTexture");
3189
3190 m_host.AddScriptLPS(1);
3191 //Check to make sure that the script's owner is the estate manager/master
3192 //World.Permissions.GenericEstatePermission(
3193 if (World.Permissions.IsGod(m_host.OwnerID))
3194 {
3195 if (level < 0 || level > 3)
3196 return;
3197
3198 UUID textureID = new UUID();
3199 if (!UUID.TryParse(texture, out textureID))
3200 return;
3201
3202 // estate module is required
3203 IEstateModule estate = World.RequestModuleInterface<IEstateModule>();
3204 if (estate != null)
3205 estate.setEstateTerrainBaseTexture(level, textureID);
3206 }
3207 }
3208
3209 /// <summary>
3210 /// Sets terrain heights of estate
3211 /// </summary>
3212 /// <param name="corner"></param>
3213 /// <param name="low"></param>
3214 /// <param name="high"></param>
3215 /// <returns></returns>
3216 public void osSetTerrainTextureHeight(int corner, double low, double high)
3217 {
3218 CheckThreatLevel(ThreatLevel.High, "osSetTerrainTextureHeight");
3219
3220 m_host.AddScriptLPS(1);
3221 //Check to make sure that the script's owner is the estate manager/master
3222 //World.Permissions.GenericEstatePermission(
3223 if (World.Permissions.IsGod(m_host.OwnerID))
3224 {
3225 if (corner < 0 || corner > 3)
3226 return;
3227
3228 // estate module is required
3229 IEstateModule estate = World.RequestModuleInterface<IEstateModule>();
3230 if (estate != null)
3231 estate.setEstateTerrainTextureHeights(corner, (float)low, (float)high);
3232 }
3233 }
3234
3235 public void osForceAttachToAvatar(int attachmentPoint)
3236 {
3237 CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatar");
3238
3239 m_host.AddScriptLPS(1);
3240
3241 InitLSL();
3242 ((LSL_Api)m_LSL_Api).AttachToAvatar(attachmentPoint);
3243 }
3244
3245 public void osForceAttachToAvatarFromInventory(string itemName, int attachmentPoint)
3246 {
3247 CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatarFromInventory");
3248
3249 m_host.AddScriptLPS(1);
3250
3251 ForceAttachToAvatarFromInventory(m_host.OwnerID, itemName, attachmentPoint);
3252 }
3253
3254 public void osForceAttachToOtherAvatarFromInventory(string rawAvatarId, string itemName, int attachmentPoint)
3255 {
3256 CheckThreatLevel(ThreatLevel.Severe, "osForceAttachToOtherAvatarFromInventory");
3257
3258 m_host.AddScriptLPS(1);
3259
3260 UUID avatarId;
3261
3262 if (!UUID.TryParse(rawAvatarId, out avatarId))
3263 return;
3264
3265 ForceAttachToAvatarFromInventory(avatarId, itemName, attachmentPoint);
3266 }
3267
3268 public void ForceAttachToAvatarFromInventory(UUID avatarId, string itemName, int attachmentPoint)
3269 {
3270 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
3271
3272 if (attachmentsModule == null)
3273 return;
3274
3275 InitLSL();
3276
3277 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(itemName);
3278
3279 if (item == null)
3280 {
3281 ((LSL_Api)m_LSL_Api).llSay(0, string.Format("Could not find object '{0}'", itemName));
3282 throw new Exception(String.Format("The inventory item '{0}' could not be found", itemName));
3283 }
3284
3285 if (item.InvType != (int)InventoryType.Object)
3286 {
3287 // FIXME: Temporary null check for regression tests since they dont' have the infrastructure to set
3288 // up the api reference.
3289 if (m_LSL_Api != null)
3290 ((LSL_Api)m_LSL_Api).llSay(0, string.Format("Unable to attach, item '{0}' is not an object.", itemName));
3291
3292 throw new Exception(String.Format("The inventory item '{0}' is not an object", itemName));
3293
3294 return;
3295 }
3296
3297 ScenePresence sp = World.GetScenePresence(avatarId);
3298
3299 if (sp == null)
3300 return;
3301
3302 InventoryItemBase newItem = World.MoveTaskInventoryItem(sp.UUID, UUID.Zero, m_host, item.ItemID);
3303
3304 if (newItem == null)
3305 {
3306 m_log.ErrorFormat(
3307 "[OSSL API]: Could not create user inventory item {0} for {1}, attach point {2} in {3}",
3308 itemName, m_host.Name, attachmentPoint, World.Name);
3309
3310 return;
3311 }
3312
3313 attachmentsModule.RezSingleAttachmentFromInventory(sp, newItem.ID, (uint)attachmentPoint);
3314 }
3315
3316 public void osForceDetachFromAvatar()
3317 {
3318 CheckThreatLevel(ThreatLevel.High, "osForceDetachFromAvatar");
3319
3320 m_host.AddScriptLPS(1);
3321
3322 InitLSL();
3323 ((LSL_Api)m_LSL_Api).DetachFromAvatar();
3324 }
3098 } 3325 }
3099} 3326}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Listener.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Listener.cs
index 93e0261..efa86fc 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Listener.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Listener.cs
@@ -88,13 +88,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
88 88
89 public Object[] GetSerializationData(UUID itemID) 89 public Object[] GetSerializationData(UUID itemID)
90 { 90 {
91 return m_commsPlugin.GetSerializationData(itemID); 91 if (m_commsPlugin != null)
92 return m_commsPlugin.GetSerializationData(itemID);
93 else
94 return new Object[]{};
92 } 95 }
93 96
94 public void CreateFromData(uint localID, UUID itemID, UUID hostID, 97 public void CreateFromData(uint localID, UUID itemID, UUID hostID,
95 Object[] data) 98 Object[] data)
96 { 99 {
97 m_commsPlugin.CreateFromData(localID, itemID, hostID, data); 100 if (m_commsPlugin != null)
101 m_commsPlugin.CreateFromData(localID, itemID, hostID, data);
98 } 102 }
99 } 103 }
100} \ No newline at end of file 104} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
index 1373971..19f3ce1 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
@@ -308,7 +308,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
308 } 308 }
309 SceneObjectPart SensePoint = ts.host; 309 SceneObjectPart SensePoint = ts.host;
310 310
311 Vector3 fromRegionPos = SensePoint.AbsolutePosition; 311 Vector3 fromRegionPos = SensePoint.GetWorldPosition();
312 312
313 // pre define some things to avoid repeated definitions in the loop body 313 // pre define some things to avoid repeated definitions in the loop body
314 Vector3 toRegionPos; 314 Vector3 toRegionPos;
@@ -323,13 +323,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
323 Quaternion q = SensePoint.GetWorldRotation(); // non-attached prim Sensor *always* uses World rotation! 323 Quaternion q = SensePoint.GetWorldRotation(); // non-attached prim Sensor *always* uses World rotation!
324 if (SensePoint.ParentGroup.IsAttachment) 324 if (SensePoint.ParentGroup.IsAttachment)
325 { 325 {
326 // In attachments, the sensor cone always orients with the 326 // In attachments, rotate the sensor cone with the
327 // avatar rotation. This may include a nonzero elevation if 327 // avatar rotation. This may include a nonzero elevation if
328 // in mouselook. 328 // in mouselook.
329 // This will not include the rotation and position of the
330 // attachment point (e.g. your head when a sensor is in your
331 // hair attached to your scull. Your hair will turn with
332 // your head but the sensor will stay with your (global)
333 // avatar rotation and position.
334 // Position of a sensor in a child prim attached to an avatar
335 // will be still wrong.
329 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar); 336 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar);
330 fromRegionPos = avatar.AbsolutePosition; 337 fromRegionPos = avatar.AbsolutePosition;
331 q = avatar.Rotation; 338 q = avatar.Rotation;
332 } 339 }
340
333 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); 341 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W);
334 LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r); 342 LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r);
335 double mag_fwd = LSL_Types.Vector3.Mag(forward_dir); 343 double mag_fwd = LSL_Types.Vector3.Mag(forward_dir);
@@ -441,14 +449,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
441 return sensedEntities; 449 return sensedEntities;
442 450
443 SceneObjectPart SensePoint = ts.host; 451 SceneObjectPart SensePoint = ts.host;
444 Vector3 fromRegionPos = SensePoint.AbsolutePosition; 452 Vector3 fromRegionPos = SensePoint.GetWorldPosition();
445 453
446 Quaternion q = SensePoint.RotationOffset; 454 Quaternion q = SensePoint.GetWorldRotation();
447 if (SensePoint.ParentGroup.IsAttachment) 455 if (SensePoint.ParentGroup.IsAttachment)
448 { 456 {
449 // In attachments, the sensor cone always orients with the 457 // In attachments, rotate the sensor cone with the
450 // avatar rotation. This may include a nonzero elevation if 458 // avatar rotation. This may include a nonzero elevation if
451 // in mouselook. 459 // in mouselook.
460 // This will not include the rotation and position of the
461 // attachment point (e.g. your head when a sensor is in your
462 // hair attached to your scull. Your hair will turn with
463 // your head but the sensor will stay with your (global)
464 // avatar rotation and position.
465 // Position of a sensor in a child prim attached to an avatar
466 // will be still wrong.
452 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar); 467 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar);
453 if (avatar == null) 468 if (avatar == null)
454 return sensedEntities; 469 return sensedEntities;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
index 40ae495..af35258 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
@@ -105,6 +105,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
105 LSL_Integer llFloor(double f); 105 LSL_Integer llFloor(double f);
106 void llForceMouselook(int mouselook); 106 void llForceMouselook(int mouselook);
107 LSL_Float llFrand(double mag); 107 LSL_Float llFrand(double mag);
108 LSL_Key llGenerateKey();
108 LSL_Vector llGetAccel(); 109 LSL_Vector llGetAccel();
109 LSL_Integer llGetAgentInfo(string id); 110 LSL_Integer llGetAgentInfo(string id);
110 LSL_String llGetAgentLanguage(string id); 111 LSL_String llGetAgentLanguage(string id);
@@ -150,7 +151,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
150 LSL_Rotation llGetLocalRot(); 151 LSL_Rotation llGetLocalRot();
151 LSL_Float llGetMass(); 152 LSL_Float llGetMass();
152 LSL_Float llGetMassMKS(); 153 LSL_Float llGetMassMKS();
153 void llGetNextEmail(string address, string subject); 154 LSL_Integer llGetMemoryLimit();
155 void llGetNextEmail(string address, string subject);
154 LSL_String llGetNotecardLine(string name, int line); 156 LSL_String llGetNotecardLine(string name, int line);
155 LSL_Key llGetNumberOfNotecardLines(string name); 157 LSL_Key llGetNumberOfNotecardLines(string name);
156 LSL_Integer llGetNumberOfPrims(); 158 LSL_Integer llGetNumberOfPrims();
@@ -188,6 +190,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
188 LSL_String llGetScriptName(); 190 LSL_String llGetScriptName();
189 LSL_Integer llGetScriptState(string name); 191 LSL_Integer llGetScriptState(string name);
190 LSL_String llGetSimulatorHostname(); 192 LSL_String llGetSimulatorHostname();
193 LSL_Integer llGetSPMaxMemory();
191 LSL_Integer llGetStartParameter(); 194 LSL_Integer llGetStartParameter();
192 LSL_Integer llGetStatus(int status); 195 LSL_Integer llGetStatus(int status);
193 LSL_String llGetSubString(string src, int start, int end); 196 LSL_String llGetSubString(string src, int start, int end);
@@ -323,6 +326,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
323 void llSay(int channelID, string text); 326 void llSay(int channelID, string text);
324 void llScaleTexture(double u, double v, int face); 327 void llScaleTexture(double u, double v, int face);
325 LSL_Integer llScriptDanger(LSL_Vector pos); 328 LSL_Integer llScriptDanger(LSL_Vector pos);
329 void llScriptProfiler(LSL_Integer flag);
326 LSL_Key llSendRemoteData(string channel, string dest, int idata, string sdata); 330 LSL_Key llSendRemoteData(string channel, string dest, int idata, string sdata);
327 void llSensor(string name, string id, int type, double range, double arc); 331 void llSensor(string name, string id, int type, double range, double arc);
328 void llSensorRemove(); 332 void llSensorRemove();
@@ -347,6 +351,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
347 void llSetLinkTexture(int linknumber, string texture, int face); 351 void llSetLinkTexture(int linknumber, string texture, int face);
348 void llSetLinkTextureAnim(int linknum, int mode, int face, int sizex, int sizey, double start, double length, double rate); 352 void llSetLinkTextureAnim(int linknum, int mode, int face, int sizex, int sizey, double start, double length, double rate);
349 void llSetLocalRot(LSL_Rotation rot); 353 void llSetLocalRot(LSL_Rotation rot);
354 LSL_Integer llSetMemoryLimit(LSL_Integer limit);
350 void llSetObjectDesc(string desc); 355 void llSetObjectDesc(string desc);
351 void llSetObjectName(string name); 356 void llSetObjectName(string name);
352 void llSetObjectPermMask(int mask, int value); 357 void llSetObjectPermMask(int mask, int value);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index 444a681..1facc96 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -98,6 +98,41 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
98 void osAvatarPlayAnimation(string avatar, string animation); 98 void osAvatarPlayAnimation(string avatar, string animation);
99 void osAvatarStopAnimation(string avatar, string animation); 99 void osAvatarStopAnimation(string avatar, string animation);
100 100
101 // Attachment commands
102
103 /// <summary>
104 /// Attach the object containing this script to the avatar that owns it without asking for PERMISSION_ATTACH
105 /// </summary>
106 /// <param name='attachment'>The attachment point. For example, ATTACH_CHEST</param>
107 void osForceAttachToAvatar(int attachment);
108
109 /// <summary>
110 /// Attach an inventory item in the object containing this script to the avatar that owns it without asking for PERMISSION_ATTACH
111 /// </summary>
112 /// <remarks>
113 /// Nothing happens if the owner is not in the region.
114 /// </remarks>
115 /// <param name='itemName'>Tha name of the item. If this is not found then a warning is said to the owner</param>
116 /// <param name='attachment'>The attachment point. For example, ATTACH_CHEST</param>
117 void osForceAttachToAvatarFromInventory(string itemName, int attachment);
118
119 /// <summary>
120 /// Attach an inventory item in the object containing this script to any avatar in the region without asking for PERMISSION_ATTACH
121 /// </summary>
122 /// <remarks>
123 /// Nothing happens if the avatar is not in the region.
124 /// </remarks>
125 /// <param name='rawAvatarId'>The UUID of the avatar to which to attach. Nothing happens if this is not a UUID</para>
126 /// <param name='itemName'>The name of the item. If this is not found then a warning is said to the owner</param>
127 /// <param name='attachment'>The attachment point. For example, ATTACH_CHEST</param>
128 void osForceAttachToOtherAvatarFromInventory(string rawAvatarId, string itemName, int attachmentPoint);
129
130 /// <summary>
131 /// Detach the object containing this script from the avatar it is attached to without checking for PERMISSION_ATTACH
132 /// </summary>
133 /// <remarks>Nothing happens if the object is not attached.</remarks>
134 void osForceDetachFromAvatar();
135
101 //texture draw functions 136 //texture draw functions
102 string osMovePen(string drawList, int x, int y); 137 string osMovePen(string drawList, int x, int y);
103 string osDrawLine(string drawList, int startX, int startY, int endX, int endY); 138 string osDrawLine(string drawList, int startX, int startY, int endX, int endY);
@@ -203,11 +238,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
203 void osNpcSetRot(LSL_Key npc, rotation rot); 238 void osNpcSetRot(LSL_Key npc, rotation rot);
204 void osNpcStopMoveToTarget(LSL_Key npc); 239 void osNpcStopMoveToTarget(LSL_Key npc);
205 void osNpcSay(key npc, string message); 240 void osNpcSay(key npc, string message);
241 void osNpcSay(key npc, int channel, string message);
242 void osNpcShout(key npc, int channel, string message);
206 void osNpcSit(key npc, key target, int options); 243 void osNpcSit(key npc, key target, int options);
207 void osNpcStand(LSL_Key npc); 244 void osNpcStand(LSL_Key npc);
208 void osNpcRemove(key npc); 245 void osNpcRemove(key npc);
209 void osNpcPlayAnimation(LSL_Key npc, string animation); 246 void osNpcPlayAnimation(LSL_Key npc, string animation);
210 void osNpcStopAnimation(LSL_Key npc, string animation); 247 void osNpcStopAnimation(LSL_Key npc, string animation);
248 void osNpcTouch(LSL_Key npcLSL_Key, LSL_Key object_key, LSL_Integer link_num);
249 void osNpcWhisper(key npc, int channel, string message);
211 250
212 LSL_Key osOwnerSaveAppearance(string notecard); 251 LSL_Key osOwnerSaveAppearance(string notecard);
213 LSL_Key osAgentSaveAppearance(key agentId, string notecard); 252 LSL_Key osAgentSaveAppearance(key agentId, string notecard);
@@ -234,5 +273,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
234 273
235 LSL_Integer osInviteToGroup(LSL_Key agentId); 274 LSL_Integer osInviteToGroup(LSL_Key agentId);
236 LSL_Integer osEjectFromGroup(LSL_Key agentId); 275 LSL_Integer osEjectFromGroup(LSL_Key agentId);
276
277 void osSetTerrainTexture(int level, LSL_Key texture);
278 void osSetTerrainTextureHeight(int corner, double low, double high);
237 } 279 }
238} 280}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
index ad4f70c..a08cc42 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
@@ -383,6 +383,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
383 public const int PRIM_SCULPT_FLAG_INVERT = 64; 383 public const int PRIM_SCULPT_FLAG_INVERT = 64;
384 public const int PRIM_SCULPT_FLAG_MIRROR = 128; 384 public const int PRIM_SCULPT_FLAG_MIRROR = 128;
385 385
386 public const int PROFILE_NONE = 0;
387 public const int PROFILE_SCRIPT_MEMORY = 1;
388
386 public const int MASK_BASE = 0; 389 public const int MASK_BASE = 0;
387 public const int MASK_OWNER = 1; 390 public const int MASK_OWNER = 1;
388 public const int MASK_GROUP = 2; 391 public const int MASK_GROUP = 2;
@@ -641,6 +644,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
641 public const int OS_NPC_FLY = 0; 644 public const int OS_NPC_FLY = 0;
642 public const int OS_NPC_NO_FLY = 1; 645 public const int OS_NPC_NO_FLY = 1;
643 public const int OS_NPC_LAND_AT_TARGET = 2; 646 public const int OS_NPC_LAND_AT_TARGET = 2;
647 public const int OS_NPC_RUNNING = 4;
644 648
645 public const int OS_NPC_SIT_NOW = 0; 649 public const int OS_NPC_SIT_NOW = 0;
646 650
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
index 2f8e169..89b6eff 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
@@ -165,11 +165,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
165 m_LSL_Functions.llBreakLink(linknum); 165 m_LSL_Functions.llBreakLink(linknum);
166 } 166 }
167 167
168 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
169 {
170 return m_LSL_Functions.llCastRay(start, end, options);
171 }
172
173 public LSL_Integer llCeil(double f) 168 public LSL_Integer llCeil(double f)
174 { 169 {
175 return m_LSL_Functions.llCeil(f); 170 return m_LSL_Functions.llCeil(f);
@@ -376,6 +371,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
376 return m_LSL_Functions.llFrand(mag); 371 return m_LSL_Functions.llFrand(mag);
377 } 372 }
378 373
374 public LSL_Key llGenerateKey()
375 {
376 return m_LSL_Functions.llGenerateKey();
377 }
378
379 public LSL_Vector llGetAccel() 379 public LSL_Vector llGetAccel()
380 { 380 {
381 return m_LSL_Functions.llGetAccel(); 381 return m_LSL_Functions.llGetAccel();
@@ -591,6 +591,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
591 return m_LSL_Functions.llGetMassMKS(); 591 return m_LSL_Functions.llGetMassMKS();
592 } 592 }
593 593
594 public LSL_Integer llGetMemoryLimit()
595 {
596 return m_LSL_Functions.llGetMemoryLimit();
597 }
598
594 public void llGetNextEmail(string address, string subject) 599 public void llGetNextEmail(string address, string subject)
595 { 600 {
596 m_LSL_Functions.llGetNextEmail(address, subject); 601 m_LSL_Functions.llGetNextEmail(address, subject);
@@ -781,6 +786,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
781 return m_LSL_Functions.llGetSimulatorHostname(); 786 return m_LSL_Functions.llGetSimulatorHostname();
782 } 787 }
783 788
789 public LSL_Integer llGetSPMaxMemory()
790 {
791 return m_LSL_Functions.llGetSPMaxMemory();
792 }
793
784 public LSL_Integer llGetStartParameter() 794 public LSL_Integer llGetStartParameter()
785 { 795 {
786 return m_LSL_Functions.llGetStartParameter(); 796 return m_LSL_Functions.llGetStartParameter();
@@ -956,6 +966,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
956 return m_LSL_Functions.llRequestDisplayName(id); 966 return m_LSL_Functions.llRequestDisplayName(id);
957 } 967 }
958 968
969 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
970 {
971 return m_LSL_Functions.llCastRay(start, end, options);
972 }
973
959 public void llLinkParticleSystem(int linknum, LSL_List rules) 974 public void llLinkParticleSystem(int linknum, LSL_List rules)
960 { 975 {
961 m_LSL_Functions.llLinkParticleSystem(linknum, rules); 976 m_LSL_Functions.llLinkParticleSystem(linknum, rules);
@@ -1450,6 +1465,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1450 return m_LSL_Functions.llScriptDanger(pos); 1465 return m_LSL_Functions.llScriptDanger(pos);
1451 } 1466 }
1452 1467
1468 public void llScriptProfiler(LSL_Integer flags)
1469 {
1470 m_LSL_Functions.llScriptProfiler(flags);
1471 }
1472
1453 public LSL_Key llSendRemoteData(string channel, string dest, int idata, string sdata) 1473 public LSL_Key llSendRemoteData(string channel, string dest, int idata, string sdata)
1454 { 1474 {
1455 return m_LSL_Functions.llSendRemoteData(channel, dest, idata, sdata); 1475 return m_LSL_Functions.llSendRemoteData(channel, dest, idata, sdata);
@@ -1565,6 +1585,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1565 m_LSL_Functions.llSetLocalRot(rot); 1585 m_LSL_Functions.llSetLocalRot(rot);
1566 } 1586 }
1567 1587
1588 public LSL_Integer llSetMemoryLimit(LSL_Integer limit)
1589 {
1590 return m_LSL_Functions.llSetMemoryLimit(limit);
1591 }
1592
1568 public void llSetObjectDesc(string desc) 1593 public void llSetObjectDesc(string desc)
1569 { 1594 {
1570 m_LSL_Functions.llSetObjectDesc(desc); 1595 m_LSL_Functions.llSetObjectDesc(desc);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
index 680cefb4..b40bdf0 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
@@ -289,8 +289,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
289 m_OSSL_Functions.osAvatarStopAnimation(avatar, animation); 289 m_OSSL_Functions.osAvatarStopAnimation(avatar, animation);
290 } 290 }
291 291
292 // Avatar functions
292 293
293 //Texture Draw functions 294 public void osForceAttachToAvatar(int attachmentPoint)
295 {
296 m_OSSL_Functions.osForceAttachToAvatar(attachmentPoint);
297 }
298
299 public void osForceAttachToAvatarFromInventory(string itemName, int attachmentPoint)
300 {
301 m_OSSL_Functions.osForceAttachToAvatarFromInventory(itemName, attachmentPoint);
302 }
303
304 public void osForceAttachToOtherAvatarFromInventory(string rawAvatarId, string itemName, int attachmentPoint)
305 {
306 m_OSSL_Functions.osForceAttachToOtherAvatarFromInventory(rawAvatarId, itemName, attachmentPoint);
307 }
308
309 public void osForceDetachFromAvatar()
310 {
311 m_OSSL_Functions.osForceDetachFromAvatar();
312 }
313
314 // Texture Draw functions
294 315
295 public string osMovePen(string drawList, int x, int y) 316 public string osMovePen(string drawList, int x, int y)
296 { 317 {
@@ -569,6 +590,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
569 m_OSSL_Functions.osNpcSay(npc, message); 590 m_OSSL_Functions.osNpcSay(npc, message);
570 } 591 }
571 592
593 public void osNpcSay(key npc, int channel, string message)
594 {
595 m_OSSL_Functions.osNpcSay(npc, channel, message);
596 }
597
598
599 public void osNpcShout(key npc, int channel, string message)
600 {
601 m_OSSL_Functions.osNpcShout(npc, channel, message);
602 }
603
572 public void osNpcSit(LSL_Key npc, LSL_Key target, int options) 604 public void osNpcSit(LSL_Key npc, LSL_Key target, int options)
573 { 605 {
574 m_OSSL_Functions.osNpcSit(npc, target, options); 606 m_OSSL_Functions.osNpcSit(npc, target, options);
@@ -594,6 +626,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
594 m_OSSL_Functions.osNpcStopAnimation(npc, animation); 626 m_OSSL_Functions.osNpcStopAnimation(npc, animation);
595 } 627 }
596 628
629 public void osNpcWhisper(key npc, int channel, string message)
630 {
631 m_OSSL_Functions.osNpcWhisper(npc, channel, message);
632 }
633
634 public void osNpcTouch(LSL_Key npcLSL_Key, LSL_Key object_key, LSL_Integer link_num)
635 {
636 m_OSSL_Functions.osNpcTouch(npcLSL_Key, object_key, link_num);
637 }
638
597 public LSL_Key osOwnerSaveAppearance(string notecard) 639 public LSL_Key osOwnerSaveAppearance(string notecard)
598 { 640 {
599 return m_OSSL_Functions.osOwnerSaveAppearance(notecard); 641 return m_OSSL_Functions.osOwnerSaveAppearance(notecard);
@@ -878,5 +920,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
878 { 920 {
879 return m_OSSL_Functions.osEjectFromGroup(agentId); 921 return m_OSSL_Functions.osEjectFromGroup(agentId);
880 } 922 }
923
924 public void osSetTerrainTexture(int level, LSL_Key texture)
925 {
926 m_OSSL_Functions.osSetTerrainTexture(level, texture);
927 }
928
929 public void osSetTerrainTextureHeight(int corner, double low, double high)
930 {
931 m_OSSL_Functions.osSetTerrainTextureHeight(corner, low, high);
932 }
881 } 933 }
882} 934}
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
index 8f2ec49..17a0d69 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
@@ -31,6 +31,7 @@ using System.Collections.Generic;
31using System.Globalization; 31using System.Globalization;
32using System.Reflection; 32using System.Reflection;
33using System.IO; 33using System.IO;
34using System.Text;
34using Microsoft.CSharp; 35using Microsoft.CSharp;
35//using Microsoft.JScript; 36//using Microsoft.JScript;
36using Microsoft.VisualBasic; 37using Microsoft.VisualBasic;
@@ -711,9 +712,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
711 // 712 //
712 string filetext = System.Convert.ToBase64String(data); 713 string filetext = System.Convert.ToBase64String(data);
713 714
714 System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); 715 Byte[] buf = Encoding.ASCII.GetBytes(filetext);
715
716 Byte[] buf = enc.GetBytes(filetext);
717 716
718 FileStream sfs = File.Create(assembly + ".text"); 717 FileStream sfs = File.Create(assembly + ".text");
719 sfs.Write(buf, 0, buf.Length); 718 sfs.Write(buf, 0, buf.Length);
@@ -804,8 +803,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
804 mapstring += String.Format("{0},{1},{2},{3}\n", k.Key, k.Value, v.Key, v.Value); 803 mapstring += String.Format("{0},{1},{2},{3}\n", k.Key, k.Value, v.Key, v.Value);
805 } 804 }
806 805
807 System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); 806 Byte[] mapbytes = Encoding.ASCII.GetBytes(mapstring);
808 Byte[] mapbytes = enc.GetBytes(mapstring);
809 FileStream mfs = File.Create(filename); 807 FileStream mfs = File.Create(filename);
810 mfs.Write(mapbytes, 0, mapbytes.Length); 808 mfs.Write(mapbytes, 0, mapbytes.Length);
811 mfs.Close(); 809 mfs.Close();
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index 5e68d69..8d92ba5 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
@@ -26,16 +26,17 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Globalization;
29using System.IO; 32using System.IO;
30using System.Diagnostics; //for [DebuggerNonUserCode] 33using System.Diagnostics; //for [DebuggerNonUserCode]
34using System.Reflection;
31using System.Runtime.Remoting; 35using System.Runtime.Remoting;
32using System.Runtime.Remoting.Lifetime; 36using System.Runtime.Remoting.Lifetime;
33using System.Threading;
34using System.Collections;
35using System.Collections.Generic;
36using System.Security.Policy; 37using System.Security.Policy;
37using System.Reflection; 38using System.Text;
38using System.Globalization; 39using System.Threading;
39using System.Xml; 40using System.Xml;
40using OpenMetaverse; 41using OpenMetaverse;
41using log4net; 42using log4net;
@@ -121,6 +122,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
121 122
122 public bool Running { get; set; } 123 public bool Running { get; set; }
123 124
125 public bool Run { get; set; }
126
124 public bool Suspended 127 public bool Suspended
125 { 128 {
126 get { return m_Suspended; } 129 get { return m_Suspended; }
@@ -216,6 +219,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
216 m_postOnRez = postOnRez; 219 m_postOnRez = postOnRez;
217 m_AttachedAvatar = part.ParentGroup.AttachedAvatar; 220 m_AttachedAvatar = part.ParentGroup.AttachedAvatar;
218 m_RegionID = part.ParentGroup.Scene.RegionInfo.RegionID; 221 m_RegionID = part.ParentGroup.Scene.RegionInfo.RegionID;
222 Run = true;
219 223
220 if (part != null) 224 if (part != null)
221 { 225 {
@@ -232,7 +236,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
232 foreach (string api in am.GetApis()) 236 foreach (string api in am.GetApis())
233 { 237 {
234 m_Apis[api] = am.CreateApi(api); 238 m_Apis[api] = am.CreateApi(api);
235 m_Apis[api].Initialize(engine, part, LocalID, itemID); 239 m_Apis[api].Initialize(engine, part, ScriptTask);
236 } 240 }
237 241
238 try 242 try
@@ -295,13 +299,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
295 using (FileStream fs = File.Open(savedState, 299 using (FileStream fs = File.Open(savedState,
296 FileMode.Open, FileAccess.Read, FileShare.None)) 300 FileMode.Open, FileAccess.Read, FileShare.None))
297 { 301 {
298 System.Text.UTF8Encoding enc =
299 new System.Text.UTF8Encoding();
300
301 Byte[] data = new Byte[size]; 302 Byte[] data = new Byte[size];
302 fs.Read(data, 0, size); 303 fs.Read(data, 0, size);
303 304
304 xml = enc.GetString(data); 305 xml = Encoding.UTF8.GetString(data);
305 306
306 ScriptSerializer.Deserialize(xml, this); 307 ScriptSerializer.Deserialize(xml, this);
307 308
@@ -330,16 +331,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
330 } 331 }
331 else 332 else
332 { 333 {
333 m_log.ErrorFormat( 334 m_log.WarnFormat(
334 "[SCRIPT INSTANCE]: Unable to load script state from assembly {0}: Memory limit exceeded", 335 "[SCRIPT INSTANCE]: Unable to load script state file {0} for script {1} {2} in {3} {4} (assembly {5}). Memory limit exceeded",
335 assembly); 336 savedState, ScriptName, ItemID, PrimName, ObjectID, assembly);
336 } 337 }
337 } 338 }
338 catch (Exception e) 339 catch (Exception e)
339 { 340 {
340 m_log.ErrorFormat( 341 m_log.ErrorFormat(
341 "[SCRIPT INSTANCE]: Unable to load script state from assembly {0}. XML is {1}. Exception {2}{3}", 342 "[SCRIPT INSTANCE]: Unable to load script state file {0} for script {1} {2} in {3} {4} (assembly {5}). XML is {6}. Exception {7}{8}",
342 assembly, xml, e.Message, e.StackTrace); 343 savedState, ScriptName, ItemID, PrimName, ObjectID, assembly, xml, e.Message, e.StackTrace);
343 } 344 }
344 } 345 }
345// else 346// else
@@ -354,10 +355,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
354 355
355 public void Init() 356 public void Init()
356 { 357 {
357 if (!m_startOnInit) return; 358 if (!m_startOnInit)
359 return;
358 360
359 if (m_startedFromSavedState) 361 if (m_startedFromSavedState)
360 { 362 {
363 if (!Run)
364 return;
365
361 Start(); 366 Start();
362 if (m_postOnRez) 367 if (m_postOnRez)
363 { 368 {
@@ -390,6 +395,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
390 } 395 }
391 else 396 else
392 { 397 {
398 if (!Run)
399 return;
400
393 Start(); 401 Start();
394 PostEvent(new EventParams("state_entry", 402 PostEvent(new EventParams("state_entry",
395 new Object[0], new DetectParams[0])); 403 new Object[0], new DetectParams[0]));
@@ -946,8 +954,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
946 try 954 try
947 { 955 {
948 FileStream fs = File.Create(Path.Combine(Path.GetDirectoryName(assembly), ItemID.ToString() + ".state")); 956 FileStream fs = File.Create(Path.Combine(Path.GetDirectoryName(assembly), ItemID.ToString() + ".state"));
949 System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding(); 957 Byte[] buf = Util.UTF8NoBomEncoding.GetBytes(xml);
950 Byte[] buf = enc.GetBytes(xml);
951 fs.Write(buf, 0, buf.Length); 958 fs.Write(buf, 0, buf.Length);
952 fs.Close(); 959 fs.Close();
953 } 960 }
@@ -966,7 +973,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
966 public IScriptApi GetApi(string name) 973 public IScriptApi GetApi(string name)
967 { 974 {
968 if (m_Apis.ContainsKey(name)) 975 if (m_Apis.ContainsKey(name))
976 {
977// m_log.DebugFormat("[SCRIPT INSTANCE]: Found api {0} in {1}@{2}", name, ScriptName, PrimName);
978
969 return m_Apis[name]; 979 return m_Apis[name];
980 }
981
982// m_log.DebugFormat("[SCRIPT INSTANCE]: Did not find api {0} in {1}@{2}", name, ScriptName, PrimName);
983
970 return null; 984 return null;
971 } 985 }
972 986
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptSerializer.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptSerializer.cs
index bcdc7bf..797bce3 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptSerializer.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptSerializer.cs
@@ -55,6 +55,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
55 public static string Serialize(ScriptInstance instance) 55 public static string Serialize(ScriptInstance instance)
56 { 56 {
57 bool running = instance.Running; 57 bool running = instance.Running;
58 bool enabled = instance.Run;
58 59
59 XmlDocument xmldoc = new XmlDocument(); 60 XmlDocument xmldoc = new XmlDocument();
60 61
@@ -77,6 +78,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
77 78
78 rootElement.AppendChild(run); 79 rootElement.AppendChild(run);
79 80
81 XmlElement run_enable = xmldoc.CreateElement("", "Run", "");
82 run_enable.AppendChild(xmldoc.CreateTextNode(
83 enabled.ToString()));
84
85 rootElement.AppendChild(run_enable);
86
80 Dictionary<string, Object> vars = instance.GetVars(); 87 Dictionary<string, Object> vars = instance.GetVars();
81 88
82 XmlElement variables = xmldoc.CreateElement("", "Variables", ""); 89 XmlElement variables = xmldoc.CreateElement("", "Variables", "");
@@ -225,6 +232,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
225 { 232 {
226 object varValue; 233 object varValue;
227 XmlNodeList partL = rootNode.ChildNodes; 234 XmlNodeList partL = rootNode.ChildNodes;
235 instance.Run = true;
228 236
229 foreach (XmlNode part in partL) 237 foreach (XmlNode part in partL)
230 { 238 {
@@ -236,6 +244,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
236 case "Running": 244 case "Running":
237 instance.Running=bool.Parse(part.InnerText); 245 instance.Running=bool.Parse(part.InnerText);
238 break; 246 break;
247 case "Run":
248 instance.Run = bool.Parse(part.InnerText);
249 break;
239 case "Variables": 250 case "Variables":
240 XmlNodeList varL = part.ChildNodes; 251 XmlNodeList varL = part.ChildNodes;
241 foreach (XmlNode var in varL) 252 foreach (XmlNode var in varL)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs
index e2d0db2..c73e22f 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs
@@ -63,7 +63,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
63 IConfig config = initConfigSource.AddConfig("XEngine"); 63 IConfig config = initConfigSource.AddConfig("XEngine");
64 config.Set("Enabled", "true"); 64 config.Set("Enabled", "true");
65 65
66 m_scene = SceneHelpers.SetupScene(); 66 m_scene = new SceneHelpers().SetupScene();
67 SceneHelpers.SetupSceneModules(m_scene, initConfigSource); 67 SceneHelpers.SetupSceneModules(m_scene, initConfigSource);
68 68
69 m_engine = new XEngine.XEngine(); 69 m_engine = new XEngine.XEngine();
@@ -91,7 +91,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
91 TaskInventoryHelpers.AddSceneObject(m_scene, so1.RootPart, inventoryItemName, itemId, userId); 91 TaskInventoryHelpers.AddSceneObject(m_scene, so1.RootPart, inventoryItemName, itemId, userId);
92 92
93 LSL_Api api = new LSL_Api(); 93 LSL_Api api = new LSL_Api();
94 api.Initialize(m_engine, so1.RootPart, so1.RootPart.LocalId, so1.RootPart.UUID); 94 api.Initialize(m_engine, so1.RootPart, null);
95 95
96 // Create a second object 96 // Create a second object
97 SceneObjectGroup so2 = SceneHelpers.CreateSceneObject(1, userId, "so2", 0x100); 97 SceneObjectGroup so2 = SceneHelpers.CreateSceneObject(1, userId, "so2", 0x100);
@@ -124,7 +124,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
124 SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(1, user1Id, "so1", 0x10); 124 SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(1, user1Id, "so1", 0x10);
125 m_scene.AddSceneObject(so1); 125 m_scene.AddSceneObject(so1);
126 LSL_Api api = new LSL_Api(); 126 LSL_Api api = new LSL_Api();
127 api.Initialize(m_engine, so1.RootPart, so1.RootPart.LocalId, so1.RootPart.UUID); 127 api.Initialize(m_engine, so1.RootPart, null);
128 128
129 // Create an object embedded inside the first 129 // Create an object embedded inside the first
130 UUID itemId = TestHelpers.ParseTail(0x20); 130 UUID itemId = TestHelpers.ParseTail(0x20);
@@ -134,7 +134,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
134 SceneObjectGroup so2 = SceneHelpers.CreateSceneObject(1, user2Id, "so2", 0x100); 134 SceneObjectGroup so2 = SceneHelpers.CreateSceneObject(1, user2Id, "so2", 0x100);
135 m_scene.AddSceneObject(so2); 135 m_scene.AddSceneObject(so2);
136 LSL_Api api2 = new LSL_Api(); 136 LSL_Api api2 = new LSL_Api();
137 api2.Initialize(m_engine, so2.RootPart, so2.RootPart.LocalId, so2.RootPart.UUID); 137 api2.Initialize(m_engine, so2.RootPart, null);
138 138
139 // *** Firstly, we test where llAllowInventoryDrop() has not been called. *** 139 // *** Firstly, we test where llAllowInventoryDrop() has not been called. ***
140 api.llGiveInventory(so2.UUID.ToString(), inventoryItemName); 140 api.llGiveInventory(so2.UUID.ToString(), inventoryItemName);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs
new file mode 100644
index 0000000..2565ae7
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs
@@ -0,0 +1,142 @@
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.Text;
32using log4net;
33using Nini.Config;
34using NUnit.Framework;
35using OpenMetaverse;
36using OpenMetaverse.Assets;
37using OpenMetaverse.StructuredData;
38using OpenSim.Framework;
39using OpenSim.Region.CoreModules.Avatar.AvatarFactory;
40using OpenSim.Region.OptionalModules.World.NPC;
41using OpenSim.Region.Framework.Scenes;
42using OpenSim.Region.ScriptEngine.Shared;
43using OpenSim.Region.ScriptEngine.Shared.Api;
44using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
45using OpenSim.Services.Interfaces;
46using OpenSim.Tests.Common;
47using OpenSim.Tests.Common.Mock;
48
49namespace OpenSim.Region.ScriptEngine.Shared.Tests
50{
51 /// <summary>
52 /// Tests for linking functions in LSL
53 /// </summary>
54 /// <remarks>
55 /// This relates to LSL. Actual linking functionality should be tested in the main
56 /// OpenSim.Region.Framework.Scenes.Tests.SceneObjectLinkingTests.
57 /// </remarks>
58 [TestFixture]
59 public class LSL_ApiLinkingTests
60 {
61 protected Scene m_scene;
62 protected XEngine.XEngine m_engine;
63
64 [SetUp]
65 public void SetUp()
66 {
67 IConfigSource initConfigSource = new IniConfigSource();
68 IConfig config = initConfigSource.AddConfig("XEngine");
69 config.Set("Enabled", "true");
70
71 m_scene = new SceneHelpers().SetupScene();
72 SceneHelpers.SetupSceneModules(m_scene, initConfigSource);
73
74 m_engine = new XEngine.XEngine();
75 m_engine.Initialise(initConfigSource);
76 m_engine.AddRegion(m_scene);
77 }
78
79 [Test]
80 public void TestllCreateLink()
81 {
82 TestHelpers.InMethod();
83
84 UUID ownerId = TestHelpers.ParseTail(0x1);
85
86 SceneObjectGroup grp1 = SceneHelpers.CreateSceneObject(2, ownerId, "grp1-", 0x10);
87 grp1.AbsolutePosition = new Vector3(10, 10, 10);
88 m_scene.AddSceneObject(grp1);
89
90 // FIXME: This should really be a script item (with accompanying script)
91 TaskInventoryItem grp1Item
92 = TaskInventoryHelpers.AddNotecard(
93 m_scene, grp1.RootPart, "ncItem", TestHelpers.ParseTail(0x800), TestHelpers.ParseTail(0x900));
94 grp1Item.PermsMask |= ScriptBaseClass.PERMISSION_CHANGE_LINKS;
95
96 SceneObjectGroup grp2 = SceneHelpers.CreateSceneObject(2, ownerId, "grp2-", 0x20);
97 grp2.AbsolutePosition = new Vector3(20, 20, 20);
98
99 // <180,0,0>
100 grp2.UpdateGroupRotationR(Quaternion.CreateFromEulers(180 * Utils.DEG_TO_RAD, 0, 0));
101
102 m_scene.AddSceneObject(grp2);
103
104 LSL_Api apiGrp1 = new LSL_Api();
105 apiGrp1.Initialize(m_engine, grp1.RootPart, grp1Item);
106
107 apiGrp1.llCreateLink(grp2.UUID.ToString(), ScriptBaseClass.TRUE);
108
109 Assert.That(grp1.Parts.Length, Is.EqualTo(4));
110 Assert.That(grp2.IsDeleted, Is.True);
111 }
112
113 [Test]
114 public void TestllBreakLink()
115 {
116 TestHelpers.InMethod();
117
118 UUID ownerId = TestHelpers.ParseTail(0x1);
119
120 SceneObjectGroup grp1 = SceneHelpers.CreateSceneObject(2, ownerId, "grp1-", 0x10);
121 grp1.AbsolutePosition = new Vector3(10, 10, 10);
122 m_scene.AddSceneObject(grp1);
123
124 // FIXME: This should really be a script item (with accompanying script)
125 TaskInventoryItem grp1Item
126 = TaskInventoryHelpers.AddNotecard(
127 m_scene, grp1.RootPart, "ncItem", TestHelpers.ParseTail(0x800), TestHelpers.ParseTail(0x900));
128
129 grp1Item.PermsMask |= ScriptBaseClass.PERMISSION_CHANGE_LINKS;
130
131 LSL_Api apiGrp1 = new LSL_Api();
132 apiGrp1.Initialize(m_engine, grp1.RootPart, grp1Item);
133
134 apiGrp1.llBreakLink(2);
135
136 Assert.That(grp1.Parts.Length, Is.EqualTo(1));
137
138 SceneObjectGroup grp2 = m_scene.GetSceneObjectGroup("grp1-Part1");
139 Assert.That(grp2, Is.Not.Null);
140 }
141 }
142} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs
index 9cf9258..c41d1e7 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs
@@ -58,16 +58,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
58 IConfig config = initConfigSource.AddConfig("XEngine"); 58 IConfig config = initConfigSource.AddConfig("XEngine");
59 config.Set("Enabled", "true"); 59 config.Set("Enabled", "true");
60 60
61 Scene scene = SceneHelpers.SetupScene(); 61 Scene scene = new SceneHelpers().SetupScene();
62 SceneObjectPart part = SceneHelpers.AddSceneObject(scene); 62 SceneObjectPart part = SceneHelpers.AddSceneObject(scene).RootPart;
63 63
64 XEngine.XEngine engine = new XEngine.XEngine(); 64 XEngine.XEngine engine = new XEngine.XEngine();
65 engine.Initialise(initConfigSource); 65 engine.Initialise(initConfigSource);
66 engine.AddRegion(scene); 66 engine.AddRegion(scene);
67 67
68 m_lslApi = new LSL_Api(); 68 m_lslApi = new LSL_Api();
69 m_lslApi.Initialize(engine, part, part.LocalId, part.UUID); 69 m_lslApi.Initialize(engine, part, null);
70
71 } 70 }
72 71
73 [Test] 72 [Test]
@@ -261,7 +260,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
261 TestHelpers.InMethod(); 260 TestHelpers.InMethod();
262 261
263 // Create Prim1. 262 // Create Prim1.
264 Scene scene = SceneHelpers.SetupScene(); 263 Scene scene = new SceneHelpers().SetupScene();
265 string obj1Name = "Prim1"; 264 string obj1Name = "Prim1";
266 UUID objUuid = new UUID("00000000-0000-0000-0000-000000000001"); 265 UUID objUuid = new UUID("00000000-0000-0000-0000-000000000001");
267 SceneObjectPart part1 = 266 SceneObjectPart part1 =
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs
index 7573dff..c8718d9 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs
@@ -67,7 +67,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
67 config = initConfigSource.AddConfig("NPC"); 67 config = initConfigSource.AddConfig("NPC");
68 config.Set("Enabled", "true"); 68 config.Set("Enabled", "true");
69 69
70 m_scene = SceneHelpers.SetupScene(); 70 m_scene = new SceneHelpers().SetupScene();
71 SceneHelpers.SetupSceneModules(m_scene, initConfigSource, new AvatarFactoryModule(), new NPCModule()); 71 SceneHelpers.SetupSceneModules(m_scene, initConfigSource, new AvatarFactoryModule(), new NPCModule());
72 72
73 m_engine = new XEngine.XEngine(); 73 m_engine = new XEngine.XEngine();
@@ -79,7 +79,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
79 /// Test creation of an NPC where the appearance data comes from a notecard 79 /// Test creation of an NPC where the appearance data comes from a notecard
80 /// </summary> 80 /// </summary>
81 [Test] 81 [Test]
82 public void TestOsNpcCreateFromNotecard() 82 public void TestOsNpcCreateUsingAppearanceFromNotecard()
83 { 83 {
84 TestHelpers.InMethod(); 84 TestHelpers.InMethod();
85// log4net.Config.XmlConfigurator.Configure(); 85// log4net.Config.XmlConfigurator.Configure();
@@ -90,12 +90,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
90 90
91 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); 91 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
92 sp.Appearance.AvatarHeight = newHeight; 92 sp.Appearance.AvatarHeight = newHeight;
93 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId); 93 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10);
94 SceneObjectPart part = so.RootPart; 94 SceneObjectPart part = so.RootPart;
95 m_scene.AddSceneObject(so); 95 m_scene.AddSceneObject(so);
96 96
97 OSSL_Api osslApi = new OSSL_Api(); 97 OSSL_Api osslApi = new OSSL_Api();
98 osslApi.Initialize(m_engine, part, part.LocalId, part.UUID); 98 osslApi.Initialize(m_engine, part, null);
99 99
100 string notecardName = "appearanceNc"; 100 string notecardName = "appearanceNc";
101 osslApi.osOwnerSaveAppearance(notecardName); 101 osslApi.osOwnerSaveAppearance(notecardName);
@@ -114,10 +114,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
114 /// Test creation of an NPC where the appearance data comes from an avatar already in the region. 114 /// Test creation of an NPC where the appearance data comes from an avatar already in the region.
115 /// </summary> 115 /// </summary>
116 [Test] 116 [Test]
117 public void TestOsNpcCreateFromAvatar() 117 public void TestOsNpcCreateUsingAppearanceFromAvatar()
118 { 118 {
119 TestHelpers.InMethod(); 119 TestHelpers.InMethod();
120// log4net.Config.XmlConfigurator.Configure(); 120// TestHelpers.EnableLogging();
121 121
122 // Store an avatar with a different height from default in a notecard. 122 // Store an avatar with a different height from default in a notecard.
123 UUID userId = TestHelpers.ParseTail(0x1); 123 UUID userId = TestHelpers.ParseTail(0x1);
@@ -125,12 +125,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
125 125
126 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); 126 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
127 sp.Appearance.AvatarHeight = newHeight; 127 sp.Appearance.AvatarHeight = newHeight;
128 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId); 128 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10);
129 SceneObjectPart part = so.RootPart; 129 SceneObjectPart part = so.RootPart;
130 m_scene.AddSceneObject(so); 130 m_scene.AddSceneObject(so);
131 131
132 OSSL_Api osslApi = new OSSL_Api(); 132 OSSL_Api osslApi = new OSSL_Api();
133 osslApi.Initialize(m_engine, part, part.LocalId, part.UUID); 133 osslApi.Initialize(m_engine, part, null);
134 134
135 string notecardName = "appearanceNc"; 135 string notecardName = "appearanceNc";
136 osslApi.osOwnerSaveAppearance(notecardName); 136 osslApi.osOwnerSaveAppearance(notecardName);
@@ -156,12 +156,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
156 156
157 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); 157 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
158 sp.Appearance.AvatarHeight = newHeight; 158 sp.Appearance.AvatarHeight = newHeight;
159 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId); 159 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10);
160 SceneObjectPart part = so.RootPart; 160 SceneObjectPart part = so.RootPart;
161 m_scene.AddSceneObject(so); 161 m_scene.AddSceneObject(so);
162 162
163 OSSL_Api osslApi = new OSSL_Api(); 163 OSSL_Api osslApi = new OSSL_Api();
164 osslApi.Initialize(m_engine, part, part.LocalId, part.UUID); 164 osslApi.Initialize(m_engine, part, null);
165 165
166 string notecardName = "appearanceNc"; 166 string notecardName = "appearanceNc";
167 167
@@ -197,12 +197,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
197 197
198 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, nonOwnerId); 198 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, nonOwnerId);
199 sp.Appearance.AvatarHeight = newHeight; 199 sp.Appearance.AvatarHeight = newHeight;
200 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, ownerId); 200 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, ownerId, 0x10);
201 SceneObjectPart part = so.RootPart; 201 SceneObjectPart part = so.RootPart;
202 m_scene.AddSceneObject(so); 202 m_scene.AddSceneObject(so);
203 203
204 OSSL_Api osslApi = new OSSL_Api(); 204 OSSL_Api osslApi = new OSSL_Api();
205 osslApi.Initialize(m_engine, part, part.LocalId, part.UUID); 205 osslApi.Initialize(m_engine, part, null);
206 206
207 string notecardName = "appearanceNc"; 207 string notecardName = "appearanceNc";
208 208
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs
new file mode 100644
index 0000000..5ed1f3d
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs
@@ -0,0 +1,231 @@
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.Text;
32using log4net;
33using Nini.Config;
34using NUnit.Framework;
35using OpenMetaverse;
36using OpenMetaverse.Assets;
37using OpenMetaverse.StructuredData;
38using OpenSim.Framework;
39using OpenSim.Region.CoreModules.Avatar.Attachments;
40using OpenSim.Region.CoreModules.Framework.InventoryAccess;
41using OpenSim.Region.Framework.Scenes;
42using OpenSim.Region.ScriptEngine.Shared;
43using OpenSim.Region.ScriptEngine.Shared.Api;
44using OpenSim.Services.Interfaces;
45using OpenSim.Tests.Common;
46using OpenSim.Tests.Common.Mock;
47
48namespace OpenSim.Region.ScriptEngine.Shared.Tests
49{
50 /// <summary>
51 /// Tests for OSSL attachment functions
52 /// </summary>
53 /// <remarks>
54 /// TODO: Add tests for all functions
55 /// </remarks>
56 [TestFixture]
57 public class OSSL_ApiAttachmentTests : OpenSimTestCase
58 {
59 protected Scene m_scene;
60 protected XEngine.XEngine m_engine;
61
62 [SetUp]
63 public override void SetUp()
64 {
65 base.SetUp();
66
67 IConfigSource initConfigSource = new IniConfigSource();
68
69 IConfig xengineConfig = initConfigSource.AddConfig("XEngine");
70 xengineConfig.Set("Enabled", "true");
71 xengineConfig.Set("AllowOSFunctions", "true");
72 xengineConfig.Set("OSFunctionThreatLevel", "Severe");
73
74 IConfig modulesConfig = initConfigSource.AddConfig("Modules");
75 modulesConfig.Set("InventoryAccessModule", "BasicInventoryAccessModule");
76
77 m_scene = new SceneHelpers().SetupScene();
78 SceneHelpers.SetupSceneModules(
79 m_scene, initConfigSource, new AttachmentsModule(), new BasicInventoryAccessModule());
80
81 m_engine = new XEngine.XEngine();
82 m_engine.Initialise(initConfigSource);
83 m_engine.AddRegion(m_scene);
84 }
85
86 [Test]
87 public void TestOsForceAttachToAvatarFromInventory()
88 {
89 TestHelpers.InMethod();
90// TestHelpers.EnableLogging();
91
92 string taskInvObjItemName = "sphere";
93 UUID taskInvObjItemId = UUID.Parse("00000000-0000-0000-0000-100000000000");
94 AttachmentPoint attachPoint = AttachmentPoint.Chin;
95
96 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(m_scene, 0x1);
97 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, ua1.PrincipalID);
98 SceneObjectGroup inWorldObj = SceneHelpers.AddSceneObject(m_scene, "inWorldObj", ua1.PrincipalID);
99 TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene, inWorldObj.RootPart);
100
101 new LSL_Api().Initialize(m_engine, inWorldObj.RootPart, scriptItem);
102 OSSL_Api osslApi = new OSSL_Api();
103 osslApi.Initialize(m_engine, inWorldObj.RootPart, scriptItem);
104
105// SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ua1.PrincipalID);
106
107 // Create an object embedded inside the first
108 TaskInventoryHelpers.AddSceneObject(m_scene, inWorldObj.RootPart, taskInvObjItemName, taskInvObjItemId, ua1.PrincipalID);
109
110 osslApi.osForceAttachToAvatarFromInventory(taskInvObjItemName, (int)attachPoint);
111
112 // Check scene presence status
113 Assert.That(sp.HasAttachments(), Is.True);
114 List<SceneObjectGroup> attachments = sp.GetAttachments();
115 Assert.That(attachments.Count, Is.EqualTo(1));
116 SceneObjectGroup attSo = attachments[0];
117 Assert.That(attSo.Name, Is.EqualTo(taskInvObjItemName));
118 Assert.That(attSo.AttachmentPoint, Is.EqualTo((uint)attachPoint));
119 Assert.That(attSo.IsAttachment);
120 Assert.That(attSo.UsesPhysics, Is.False);
121 Assert.That(attSo.IsTemporary, Is.False);
122
123 // Check appearance status
124 List<AvatarAttachment> attachmentsInAppearance = sp.Appearance.GetAttachments();
125 Assert.That(attachmentsInAppearance.Count, Is.EqualTo(1));
126 Assert.That(sp.Appearance.GetAttachpoint(attachmentsInAppearance[0].ItemID), Is.EqualTo((uint)attachPoint));
127 }
128
129 /// <summary>
130 /// Make sure we can't force attach anything other than objects.
131 /// </summary>
132 [Test]
133 public void TestOsForceAttachToAvatarFromInventoryNotObject()
134 {
135 TestHelpers.InMethod();
136// TestHelpers.EnableLogging();
137
138 string taskInvObjItemName = "sphere";
139 UUID taskInvObjItemId = UUID.Parse("00000000-0000-0000-0000-100000000000");
140 AttachmentPoint attachPoint = AttachmentPoint.Chin;
141
142 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(m_scene, 0x1);
143 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, ua1.PrincipalID);
144 SceneObjectGroup inWorldObj = SceneHelpers.AddSceneObject(m_scene, "inWorldObj", ua1.PrincipalID);
145 TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene, inWorldObj.RootPart);
146
147 new LSL_Api().Initialize(m_engine, inWorldObj.RootPart, scriptItem);
148 OSSL_Api osslApi = new OSSL_Api();
149 osslApi.Initialize(m_engine, inWorldObj.RootPart, scriptItem);
150
151 // Create an object embedded inside the first
152 TaskInventoryHelpers.AddNotecard(
153 m_scene, inWorldObj.RootPart, taskInvObjItemName, taskInvObjItemId, TestHelpers.ParseTail(0x900));
154
155 bool exceptionCaught = false;
156
157 try
158 {
159 osslApi.osForceAttachToAvatarFromInventory(taskInvObjItemName, (int)attachPoint);
160 }
161 catch (Exception)
162 {
163 exceptionCaught = true;
164 }
165
166 Assert.That(exceptionCaught, Is.True);
167
168 // Check scene presence status
169 Assert.That(sp.HasAttachments(), Is.False);
170 List<SceneObjectGroup> attachments = sp.GetAttachments();
171 Assert.That(attachments.Count, Is.EqualTo(0));
172
173 // Check appearance status
174 List<AvatarAttachment> attachmentsInAppearance = sp.Appearance.GetAttachments();
175 Assert.That(attachmentsInAppearance.Count, Is.EqualTo(0));
176 }
177
178 [Test]
179 public void TestOsForceAttachToOtherAvatarFromInventory()
180 {
181 TestHelpers.InMethod();
182// TestHelpers.EnableLogging();
183
184 string taskInvObjItemName = "sphere";
185 UUID taskInvObjItemId = UUID.Parse("00000000-0000-0000-0000-100000000000");
186 AttachmentPoint attachPoint = AttachmentPoint.Chin;
187
188 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(m_scene, "user", "one", 0x1, "pass");
189 UserAccount ua2 = UserAccountHelpers.CreateUserWithInventory(m_scene, "user", "two", 0x2, "pass");
190
191 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, ua1);
192 SceneObjectGroup inWorldObj = SceneHelpers.AddSceneObject(m_scene, "inWorldObj", ua1.PrincipalID);
193 TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene, inWorldObj.RootPart);
194
195 new LSL_Api().Initialize(m_engine, inWorldObj.RootPart, scriptItem);
196 OSSL_Api osslApi = new OSSL_Api();
197 osslApi.Initialize(m_engine, inWorldObj.RootPart, scriptItem);
198
199 // Create an object embedded inside the first
200 TaskInventoryHelpers.AddSceneObject(m_scene, inWorldObj.RootPart, taskInvObjItemName, taskInvObjItemId, ua1.PrincipalID);
201
202 ScenePresence sp2 = SceneHelpers.AddScenePresence(m_scene, ua2);
203
204 osslApi.osForceAttachToOtherAvatarFromInventory(sp2.UUID.ToString(), taskInvObjItemName, (int)attachPoint);
205
206 // Check scene presence status
207 Assert.That(sp.HasAttachments(), Is.False);
208 List<SceneObjectGroup> attachments = sp.GetAttachments();
209 Assert.That(attachments.Count, Is.EqualTo(0));
210
211 Assert.That(sp2.HasAttachments(), Is.True);
212 List<SceneObjectGroup> attachments2 = sp2.GetAttachments();
213 Assert.That(attachments2.Count, Is.EqualTo(1));
214 SceneObjectGroup attSo = attachments2[0];
215 Assert.That(attSo.Name, Is.EqualTo(taskInvObjItemName));
216 Assert.That(attSo.OwnerID, Is.EqualTo(ua2.PrincipalID));
217 Assert.That(attSo.AttachmentPoint, Is.EqualTo((uint)attachPoint));
218 Assert.That(attSo.IsAttachment);
219 Assert.That(attSo.UsesPhysics, Is.False);
220 Assert.That(attSo.IsTemporary, Is.False);
221
222 // Check appearance status
223 List<AvatarAttachment> attachmentsInAppearance = sp.Appearance.GetAttachments();
224 Assert.That(attachmentsInAppearance.Count, Is.EqualTo(0));
225
226 List<AvatarAttachment> attachmentsInAppearance2 = sp2.Appearance.GetAttachments();
227 Assert.That(attachmentsInAppearance2.Count, Is.EqualTo(1));
228 Assert.That(sp2.Appearance.GetAttachpoint(attachmentsInAppearance2[0].ItemID), Is.EqualTo((uint)attachPoint));
229 }
230 }
231} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs
index 9d9fc51..25679a6 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs
@@ -52,14 +52,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
52 /// Tests for OSSL NPC API 52 /// Tests for OSSL NPC API
53 /// </summary> 53 /// </summary>
54 [TestFixture] 54 [TestFixture]
55 public class OSSL_NpcApiAppearanceTest 55 public class OSSL_NpcApiAppearanceTest : OpenSimTestCase
56 { 56 {
57 protected Scene m_scene; 57 protected Scene m_scene;
58 protected XEngine.XEngine m_engine; 58 protected XEngine.XEngine m_engine;
59 59
60 [SetUp] 60 [SetUp]
61 public void SetUp() 61 public override void SetUp()
62 { 62 {
63 base.SetUp();
64
63 IConfigSource initConfigSource = new IniConfigSource(); 65 IConfigSource initConfigSource = new IniConfigSource();
64 IConfig config = initConfigSource.AddConfig("XEngine"); 66 IConfig config = initConfigSource.AddConfig("XEngine");
65 config.Set("Enabled", "true"); 67 config.Set("Enabled", "true");
@@ -68,7 +70,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
68 config = initConfigSource.AddConfig("NPC"); 70 config = initConfigSource.AddConfig("NPC");
69 config.Set("Enabled", "true"); 71 config.Set("Enabled", "true");
70 72
71 m_scene = SceneHelpers.SetupScene(); 73 m_scene = new SceneHelpers().SetupScene();
72 SceneHelpers.SetupSceneModules(m_scene, initConfigSource, new AvatarFactoryModule(), new NPCModule()); 74 SceneHelpers.SetupSceneModules(m_scene, initConfigSource, new AvatarFactoryModule(), new NPCModule());
73 75
74 m_engine = new XEngine.XEngine(); 76 m_engine = new XEngine.XEngine();
@@ -95,19 +97,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
95 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); 97 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
96 sp.Appearance.AvatarHeight = newHeight; 98 sp.Appearance.AvatarHeight = newHeight;
97 99
98 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId); 100 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10);
99 SceneObjectPart part = so.RootPart; 101 SceneObjectPart part = so.RootPart;
100 m_scene.AddSceneObject(so); 102 m_scene.AddSceneObject(so);
101 103
102 SceneObjectGroup otherSo = SceneHelpers.CreateSceneObject(1, otherUserId); 104 SceneObjectGroup otherSo = SceneHelpers.CreateSceneObject(1, otherUserId, 0x20);
103 SceneObjectPart otherPart = otherSo.RootPart; 105 SceneObjectPart otherPart = otherSo.RootPart;
104 m_scene.AddSceneObject(otherSo); 106 m_scene.AddSceneObject(otherSo);
105 107
106 OSSL_Api osslApi = new OSSL_Api(); 108 OSSL_Api osslApi = new OSSL_Api();
107 osslApi.Initialize(m_engine, part, part.LocalId, part.UUID); 109 osslApi.Initialize(m_engine, part, null);
108 110
109 OSSL_Api otherOsslApi = new OSSL_Api(); 111 OSSL_Api otherOsslApi = new OSSL_Api();
110 otherOsslApi.Initialize(m_engine, otherPart, otherPart.LocalId, otherPart.UUID); 112 otherOsslApi.Initialize(m_engine, otherPart, null);
111 113
112 string notecardName = "appearanceNc"; 114 string notecardName = "appearanceNc";
113 osslApi.osOwnerSaveAppearance(notecardName); 115 osslApi.osOwnerSaveAppearance(notecardName);
@@ -146,12 +148,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
146 148
147 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); 149 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
148 sp.Appearance.AvatarHeight = newHeight; 150 sp.Appearance.AvatarHeight = newHeight;
149 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId); 151 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10);
150 SceneObjectPart part = so.RootPart; 152 SceneObjectPart part = so.RootPart;
151 m_scene.AddSceneObject(so); 153 m_scene.AddSceneObject(so);
152 154
153 OSSL_Api osslApi = new OSSL_Api(); 155 OSSL_Api osslApi = new OSSL_Api();
154 osslApi.Initialize(m_engine, part, part.LocalId, part.UUID); 156 osslApi.Initialize(m_engine, part, null);
155 157
156 string notecardName = "appearanceNc"; 158 string notecardName = "appearanceNc";
157 osslApi.osOwnerSaveAppearance(notecardName); 159 osslApi.osOwnerSaveAppearance(notecardName);
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs
index 7d7bd82..f247a0b 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs
@@ -58,9 +58,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine.Tests
58// Console.WriteLine(AppDomain.CurrentDomain.BaseDirectory); 58// Console.WriteLine(AppDomain.CurrentDomain.BaseDirectory);
59 m_xEngine = new XEngine(); 59 m_xEngine = new XEngine();
60 60
61 // Necessary to stop serialization complaining
62 WorldCommModule wcModule = new WorldCommModule();
63
64 IniConfigSource configSource = new IniConfigSource(); 61 IniConfigSource configSource = new IniConfigSource();
65 62
66 IConfig startupConfig = configSource.AddConfig("Startup"); 63 IConfig startupConfig = configSource.AddConfig("Startup");
@@ -68,13 +65,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine.Tests
68 65
69 IConfig xEngineConfig = configSource.AddConfig("XEngine"); 66 IConfig xEngineConfig = configSource.AddConfig("XEngine");
70 xEngineConfig.Set("Enabled", "true"); 67 xEngineConfig.Set("Enabled", "true");
68 xEngineConfig.Set("StartDelay", "0");
71 69
72 // These tests will not run with AppDomainLoading = true, at least on mono. For unknown reasons, the call 70 // These tests will not run with AppDomainLoading = true, at least on mono. For unknown reasons, the call
73 // to AssemblyResolver.OnAssemblyResolve fails. 71 // to AssemblyResolver.OnAssemblyResolve fails.
74 xEngineConfig.Set("AppDomainLoading", "false"); 72 xEngineConfig.Set("AppDomainLoading", "false");
75 73
76 m_scene = SceneHelpers.SetupScene("My Test", UUID.Random(), 1000, 1000, null, configSource); 74 m_scene = new SceneHelpers().SetupScene("My Test", UUID.Random(), 1000, 1000, configSource);
77 SceneHelpers.SetupSceneModules(m_scene, configSource, m_xEngine, wcModule); 75 SceneHelpers.SetupSceneModules(m_scene, configSource, m_xEngine);
78 m_scene.StartScripts(); 76 m_scene.StartScripts();
79 } 77 }
80 78
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 2a01fc4..d763063 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -63,6 +63,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
63 { 63 {
64 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 64 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
65 65
66 /// <summary>
67 /// Control the printing of certain debug messages.
68 /// </summary>
69 /// <remarks>
70 /// If DebugLevel >= 1, then we log every time that a script is started.
71 /// </remarks>
72// public int DebugLevel { get; set; }
73
66 private SmartThreadPool m_ThreadPool; 74 private SmartThreadPool m_ThreadPool;
67 private int m_MaxScriptQueue; 75 private int m_MaxScriptQueue;
68 private Scene m_Scene; 76 private Scene m_Scene;
@@ -70,7 +78,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
70 private IConfigSource m_ConfigSource = null; 78 private IConfigSource m_ConfigSource = null;
71 private ICompiler m_Compiler; 79 private ICompiler m_Compiler;
72 private int m_MinThreads; 80 private int m_MinThreads;
73 private int m_MaxThreads ; 81 private int m_MaxThreads;
82
83 /// <summary>
84 /// Amount of time to delay before starting.
85 /// </summary>
86 private int m_StartDelay;
87
74 private int m_IdleTimeout; 88 private int m_IdleTimeout;
75 private int m_StackSize; 89 private int m_StackSize;
76 private int m_SleepTime; 90 private int m_SleepTime;
@@ -284,14 +298,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
284 AppDomain.CurrentDomain.AssemblyResolve += 298 AppDomain.CurrentDomain.AssemblyResolve +=
285 OnAssemblyResolve; 299 OnAssemblyResolve;
286 300
287 m_log.InfoFormat("[XEngine] Initializing scripts in region {0}",
288 scene.RegionInfo.RegionName);
289 m_Scene = scene; 301 m_Scene = scene;
302 m_log.InfoFormat("[XEngine]: Initializing scripts in region {0}", m_Scene.RegionInfo.RegionName);
290 303
291 m_MinThreads = m_ScriptConfig.GetInt("MinThreads", 2); 304 m_MinThreads = m_ScriptConfig.GetInt("MinThreads", 2);
292 m_MaxThreads = m_ScriptConfig.GetInt("MaxThreads", 100); 305 m_MaxThreads = m_ScriptConfig.GetInt("MaxThreads", 100);
293 m_IdleTimeout = m_ScriptConfig.GetInt("IdleTimeout", 60); 306 m_IdleTimeout = m_ScriptConfig.GetInt("IdleTimeout", 60);
294 string priority = m_ScriptConfig.GetString("Priority", "BelowNormal"); 307 string priority = m_ScriptConfig.GetString("Priority", "BelowNormal");
308 m_StartDelay = m_ScriptConfig.GetInt("StartDelay", 15000);
295 m_MaxScriptQueue = m_ScriptConfig.GetInt("MaxScriptEventQueue",300); 309 m_MaxScriptQueue = m_ScriptConfig.GetInt("MaxScriptEventQueue",300);
296 m_StackSize = m_ScriptConfig.GetInt("ThreadStackSize", 262144); 310 m_StackSize = m_ScriptConfig.GetInt("ThreadStackSize", 262144);
297 m_SleepTime = m_ScriptConfig.GetInt("MaintenanceInterval", 10) * 1000; 311 m_SleepTime = m_ScriptConfig.GetInt("MaintenanceInterval", 10) * 1000;
@@ -389,9 +403,42 @@ namespace OpenSim.Region.ScriptEngine.XEngine
389 "Starts all stopped scripts." 403 "Starts all stopped scripts."
390 + "If a <script-item-uuid> is given then only that script will be started. Otherwise, all suitable scripts are started.", 404 + "If a <script-item-uuid> is given then only that script will be started. Otherwise, all suitable scripts are started.",
391 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStartScript)); 405 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStartScript));
406
407// MainConsole.Instance.Commands.AddCommand(
408// "Debug", false, "debug xengine", "debug xengine [<level>]",
409// "Turn on detailed xengine debugging.",
410// "If level <= 0, then no extra logging is done.\n"
411// + "If level >= 1, then we log every time that a script is started.",
412// HandleDebugLevelCommand);
392 } 413 }
393 414
394 /// <summary> 415 /// <summary>
416 /// Change debug level
417 /// </summary>
418 /// <param name="module"></param>
419 /// <param name="args"></param>
420// private void HandleDebugLevelCommand(string module, string[] args)
421// {
422// if (args.Length == 3)
423// {
424// int newDebug;
425// if (int.TryParse(args[2], out newDebug))
426// {
427// DebugLevel = newDebug;
428// MainConsole.Instance.OutputFormat("Debug level set to {0}", newDebug);
429// }
430// }
431// else if (args.Length == 2)
432// {
433// MainConsole.Instance.OutputFormat("Current debug level is {0}", DebugLevel);
434// }
435// else
436// {
437// MainConsole.Instance.Output("Usage: debug xengine 0..1");
438// }
439// }
440
441 /// <summary>
395 /// Parse the raw item id into a script instance from the command params if it's present. 442 /// Parse the raw item id into a script instance from the command params if it's present.
396 /// </summary> 443 /// </summary>
397 /// <param name="cmdparams"></param> 444 /// <param name="cmdparams"></param>
@@ -799,35 +846,66 @@ namespace OpenSim.Region.ScriptEngine.XEngine
799 int colon = firstline.IndexOf(':'); 846 int colon = firstline.IndexOf(':');
800 if (firstline.Length > 2 && firstline.Substring(0, 2) == "//" && colon != -1) 847 if (firstline.Length > 2 && firstline.Substring(0, 2) == "//" && colon != -1)
801 { 848 {
802 string engineName = firstline.Substring(2, colon-2); 849 string engineName = firstline.Substring(2, colon - 2);
803 850
804 if (names.Contains(engineName)) 851 if (names.Contains(engineName))
805 { 852 {
806 engine = engineName; 853 engine = engineName;
807 script = "//" + script.Substring(script.IndexOf(':')+1); 854 script = "//" + script.Substring(colon + 1);
808 } 855 }
809 else 856 else
810 { 857 {
811 if (engine == ScriptEngineName) 858 if (engine == ScriptEngineName)
812 { 859 {
813 SceneObjectPart part = 860 // If we are falling back on XEngine as the default engine, then only complain to the user
814 m_Scene.GetSceneObjectPart( 861 // if a script language has been explicitly set and it's one that we recognize or there are
815 localID); 862 // no non-whitespace characters after the colon.
816 863 //
817 TaskInventoryItem item = 864 // If the script is
818 part.Inventory.GetInventoryItem(itemID); 865 // explicitly not allowed or the script is not in LSL then the user will be informed by a later compiler message.
819 866 //
820 ScenePresence presence = 867 // If the colon ends the line then we'll risk the false positive as this is more likely
821 m_Scene.GetScenePresence( 868 // to signal a real scriptengine line where the user wants to use the default compile language.
822 item.OwnerID); 869 //
823 870 // This avoids the overwhelming number of false positives where we're in this code because
824 if (presence != null) 871 // there's a colon in a comment in the first line of a script for entirely
872 // unrelated reasons (e.g. vim settings).
873 //
874 // TODO: A better fix would be to deprecate simple : detection and look for some less likely
875 // string to begin the comment (like #! in unix shell scripts).
876 bool warnRunningInXEngine = false;
877 string restOfFirstLine = firstline.Substring(colon + 1);
878
879 // FIXME: These are hardcoded because they are currently hardcoded in Compiler.cs
880 if (restOfFirstLine.StartsWith("c#")
881 || restOfFirstLine.StartsWith("vb")
882 || restOfFirstLine.StartsWith("lsl")
883 || restOfFirstLine.StartsWith("js")
884 || restOfFirstLine.StartsWith("yp")
885 || restOfFirstLine.Length == 0)
886 warnRunningInXEngine = true;
887
888 if (warnRunningInXEngine)
825 { 889 {
826 presence.ControllingClient.SendAgentAlertMessage( 890 SceneObjectPart part =
827 "Selected engine unavailable. "+ 891 m_Scene.GetSceneObjectPart(
828 "Running script on "+ 892 localID);
829 ScriptEngineName, 893
830 false); 894 TaskInventoryItem item =
895 part.Inventory.GetInventoryItem(itemID);
896
897 ScenePresence presence =
898 m_Scene.GetScenePresence(
899 item.OwnerID);
900
901 if (presence != null)
902 {
903 presence.ControllingClient.SendAgentAlertMessage(
904 "Selected engine unavailable. "+
905 "Running script on "+
906 ScriptEngineName,
907 false);
908 }
831 } 909 }
832 } 910 }
833 } 911 }
@@ -884,20 +962,31 @@ namespace OpenSim.Region.ScriptEngine.XEngine
884 { 962 {
885 if (m_InitialStartup) 963 if (m_InitialStartup)
886 { 964 {
887 m_InitialStartup = false; 965 // This delay exists to stop mono problems where script compilation and startup would stop the sim
888 System.Threading.Thread.Sleep(15000); 966 // working properly for the session.
967 System.Threading.Thread.Sleep(m_StartDelay);
968 }
889 969
890 if (m_CompileQueue.Count == 0) 970 object[] o;
971
972 int scriptsStarted = 0;
973
974 while (m_CompileQueue.Dequeue(out o))
975 {
976 if (DoOnRezScript(o))
891 { 977 {
892 // No scripts on region, so won't get triggered later 978 scriptsStarted++;
893 // by the queue becoming empty so we trigger it here 979
894 m_Scene.EventManager.TriggerEmptyScriptCompileQueue(0, String.Empty); 980 if (m_InitialStartup)
981 if (scriptsStarted % 50 == 0)
982 m_log.InfoFormat(
983 "[XEngine]: Started {0} scripts in {1}", scriptsStarted, m_Scene.RegionInfo.RegionName);
895 } 984 }
896 } 985 }
897 986
898 object[] o; 987 if (m_InitialStartup)
899 while (m_CompileQueue.Dequeue(out o)) 988 m_log.InfoFormat(
900 DoOnRezScript(o); 989 "[XEngine]: Completed starting {0} scripts on {1}", scriptsStarted, m_Scene.RegionInfo.RegionName);
901 990
902 // NOTE: Despite having a lockless queue, this lock is required 991 // NOTE: Despite having a lockless queue, this lock is required
903 // to make sure there is never no compile thread while there 992 // to make sure there is never no compile thread while there
@@ -905,12 +994,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
905 // due to a race condition 994 // due to a race condition
906 // 995 //
907 lock (m_CompileQueue) 996 lock (m_CompileQueue)
908 {
909 m_CurrentCompile = null; 997 m_CurrentCompile = null;
910 } 998
911 m_Scene.EventManager.TriggerEmptyScriptCompileQueue(m_ScriptFailCount, 999 m_Scene.EventManager.TriggerEmptyScriptCompileQueue(m_ScriptFailCount,
912 m_ScriptErrorMessage); 1000 m_ScriptErrorMessage);
1001
913 m_ScriptFailCount = 0; 1002 m_ScriptFailCount = 0;
1003 m_InitialStartup = false;
914 1004
915 return null; 1005 return null;
916 } 1006 }
@@ -1093,11 +1183,18 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1093 1183
1094 AppDomain sandbox; 1184 AppDomain sandbox;
1095 if (m_AppDomainLoading) 1185 if (m_AppDomainLoading)
1186 {
1096 sandbox = AppDomain.CreateDomain( 1187 sandbox = AppDomain.CreateDomain(
1097 m_Scene.RegionInfo.RegionID.ToString(), 1188 m_Scene.RegionInfo.RegionID.ToString(),
1098 evidence, appSetup); 1189 evidence, appSetup);
1190 m_AppDomains[appDomain].AssemblyResolve +=
1191 new ResolveEventHandler(
1192 AssemblyResolver.OnAssemblyResolve);
1193 }
1099 else 1194 else
1195 {
1100 sandbox = AppDomain.CurrentDomain; 1196 sandbox = AppDomain.CurrentDomain;
1197 }
1101 1198
1102 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); 1199 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1103 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); 1200 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
@@ -1109,9 +1206,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1109 1206
1110 m_AppDomains[appDomain] = sandbox; 1207 m_AppDomains[appDomain] = sandbox;
1111 1208
1112 m_AppDomains[appDomain].AssemblyResolve +=
1113 new ResolveEventHandler(
1114 AssemblyResolver.OnAssemblyResolve);
1115 m_DomainScripts[appDomain] = new List<UUID>(); 1209 m_DomainScripts[appDomain] = new List<UUID>();
1116 } 1210 }
1117 catch (Exception e) 1211 catch (Exception e)
@@ -1396,25 +1490,24 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1396 return false; 1490 return false;
1397 1491
1398 uuids = m_PrimObjects[localID]; 1492 uuids = m_PrimObjects[localID];
1399
1400 1493
1401 foreach (UUID itemID in uuids) 1494 foreach (UUID itemID in uuids)
1402 {
1403 IScriptInstance instance = null;
1404 try
1405 { 1495 {
1406 if (m_Scripts.ContainsKey(itemID)) 1496 IScriptInstance instance = null;
1407 instance = m_Scripts[itemID]; 1497 try
1408 } 1498 {
1409 catch { /* ignore race conditions */ } 1499 if (m_Scripts.ContainsKey(itemID))
1410 1500 instance = m_Scripts[itemID];
1411 if (instance != null) 1501 }
1412 { 1502 catch { /* ignore race conditions */ }
1413 instance.PostEvent(p); 1503
1414 result = true; 1504 if (instance != null)
1505 {
1506 instance.PostEvent(p);
1507 result = true;
1508 }
1415 } 1509 }
1416 } 1510 }
1417 }
1418 1511
1419 return result; 1512 return result;
1420 } 1513 }
@@ -1539,6 +1632,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1539 } 1632 }
1540 } 1633 }
1541 1634
1635 public void SetRunEnable(UUID instanceID, bool enable)
1636 {
1637 IScriptInstance instance = GetInstance(instanceID);
1638 if (instance != null)
1639 instance.Run = enable;
1640 }
1641
1542 public bool GetScriptState(UUID itemID) 1642 public bool GetScriptState(UUID itemID)
1543 { 1643 {
1544 IScriptInstance instance = GetInstance(itemID); 1644 IScriptInstance instance = GetInstance(itemID);
@@ -1573,7 +1673,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1573 { 1673 {
1574 IScriptInstance instance = GetInstance(itemID); 1674 IScriptInstance instance = GetInstance(itemID);
1575 if (instance != null) 1675 if (instance != null)
1576 instance.Stop(0); 1676 {
1677 // Give the script some time to finish processing its last event. Simply aborting the script thread can
1678 // cause issues on mono 2.6, 2.10 and possibly later where locks are not released properly on abort.
1679 instance.Stop(1000);
1680 }
1577 } 1681 }
1578 1682
1579 public DetectParams GetDetectParams(UUID itemID, int idx) 1683 public DetectParams GetDetectParams(UUID itemID, int idx)
@@ -1671,12 +1775,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1671 1775
1672 public string GetXMLState(UUID itemID) 1776 public string GetXMLState(UUID itemID)
1673 { 1777 {
1674// m_log.DebugFormat("[XEngine]: Getting XML state for {0}", itemID); 1778// m_log.DebugFormat("[XEngine]: Getting XML state for script instance {0}", itemID);
1675 1779
1676 IScriptInstance instance = GetInstance(itemID); 1780 IScriptInstance instance = GetInstance(itemID);
1677 if (instance == null) 1781 if (instance == null)
1678 { 1782 {
1679// m_log.DebugFormat("[XEngine]: Found no script for {0}, returning empty string", itemID); 1783// m_log.DebugFormat("[XEngine]: Found no script instance for {0}, returning empty string", itemID);
1680 return ""; 1784 return "";
1681 } 1785 }
1682 1786
@@ -1749,14 +1853,15 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1749 FileMode.Open, FileAccess.Read)) 1853 FileMode.Open, FileAccess.Read))
1750 { 1854 {
1751 tfs.Read(tdata, 0, tdata.Length); 1855 tfs.Read(tdata, 0, tdata.Length);
1752 tfs.Close();
1753 } 1856 }
1754 1857
1755 assem = new System.Text.ASCIIEncoding().GetString(tdata); 1858 assem = Encoding.ASCII.GetString(tdata);
1756 } 1859 }
1757 catch (Exception e) 1860 catch (Exception e)
1758 { 1861 {
1759 m_log.DebugFormat("[XEngine]: Unable to open script textfile {0}, reason: {1}", assemName+".text", e.Message); 1862 m_log.ErrorFormat(
1863 "[XEngine]: Unable to open script textfile {0}{1}, reason: {2}",
1864 assemName, ".text", e.Message);
1760 } 1865 }
1761 } 1866 }
1762 } 1867 }
@@ -1773,16 +1878,15 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1773 using (FileStream fs = File.Open(assemName, FileMode.Open, FileAccess.Read)) 1878 using (FileStream fs = File.Open(assemName, FileMode.Open, FileAccess.Read))
1774 { 1879 {
1775 fs.Read(data, 0, data.Length); 1880 fs.Read(data, 0, data.Length);
1776 fs.Close();
1777 } 1881 }
1778 1882
1779 assem = System.Convert.ToBase64String(data); 1883 assem = System.Convert.ToBase64String(data);
1780 } 1884 }
1781 catch (Exception e) 1885 catch (Exception e)
1782 { 1886 {
1783 m_log.DebugFormat("[XEngine]: Unable to open script assembly {0}, reason: {1}", assemName, e.Message); 1887 m_log.ErrorFormat(
1888 "[XEngine]: Unable to open script assembly {0}, reason: {1}", assemName, e.Message);
1784 } 1889 }
1785
1786 } 1890 }
1787 } 1891 }
1788 1892
@@ -1795,9 +1899,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1795 using (StreamReader msr = new StreamReader(mfs)) 1899 using (StreamReader msr = new StreamReader(mfs))
1796 { 1900 {
1797 map = msr.ReadToEnd(); 1901 map = msr.ReadToEnd();
1798 msr.Close();
1799 } 1902 }
1800 mfs.Close();
1801 } 1903 }
1802 } 1904 }
1803 1905
@@ -1833,6 +1935,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1833 1935
1834 public bool SetXMLState(UUID itemID, string xml) 1936 public bool SetXMLState(UUID itemID, string xml)
1835 { 1937 {
1938// m_log.DebugFormat("[XEngine]: Writing state for script item with ID {0}", itemID);
1939
1836 if (xml == String.Empty) 1940 if (xml == String.Empty)
1837 return false; 1941 return false;
1838 1942
@@ -1893,31 +1997,61 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1893 { 1997 {
1894 using (FileStream fs = File.Create(path)) 1998 using (FileStream fs = File.Create(path))
1895 { 1999 {
2000// m_log.DebugFormat("[XEngine]: Writing assembly file {0}", path);
2001
1896 fs.Write(filedata, 0, filedata.Length); 2002 fs.Write(filedata, 0, filedata.Length);
1897 fs.Close();
1898 } 2003 }
1899 } 2004 }
1900 catch (IOException ex) 2005 catch (IOException ex)
1901 { 2006 {
1902 // if there already exists a file at that location, it may be locked. 2007 // if there already exists a file at that location, it may be locked.
1903 m_log.ErrorFormat("[XEngine]: File {0} already exists! {1}", path, ex.Message); 2008 m_log.ErrorFormat("[XEngine]: Error whilst writing assembly file {0}, {1}", path, ex.Message);
1904 } 2009 }
2010
2011 string textpath = path + ".text";
1905 try 2012 try
1906 { 2013 {
1907 using (FileStream fs = File.Create(path + ".text")) 2014 using (FileStream fs = File.Create(textpath))
1908 { 2015 {
1909 using (StreamWriter sw = new StreamWriter(fs)) 2016 using (StreamWriter sw = new StreamWriter(fs))
1910 { 2017 {
2018// m_log.DebugFormat("[XEngine]: Writing .text file {0}", textpath);
2019
1911 sw.Write(base64); 2020 sw.Write(base64);
1912 sw.Close();
1913 } 2021 }
1914 fs.Close();
1915 } 2022 }
1916 } 2023 }
1917 catch (IOException ex) 2024 catch (IOException ex)
1918 { 2025 {
1919 // if there already exists a file at that location, it may be locked. 2026 // if there already exists a file at that location, it may be locked.
1920 m_log.ErrorFormat("[XEngine]: File {0} already exists! {1}", path, ex.Message); 2027 m_log.ErrorFormat("[XEngine]: Error whilst writing .text file {0}, {1}", textpath, ex.Message);
2028 }
2029 }
2030
2031 XmlNodeList mapL = rootE.GetElementsByTagName("LineMap");
2032 if (mapL.Count > 0)
2033 {
2034 XmlElement mapE = (XmlElement)mapL[0];
2035
2036 string mappath = Path.Combine(m_ScriptEnginesPath, World.RegionInfo.RegionID.ToString());
2037 mappath = Path.Combine(mappath, mapE.GetAttribute("Filename"));
2038
2039 try
2040 {
2041 using (FileStream mfs = File.Create(mappath))
2042 {
2043 using (StreamWriter msw = new StreamWriter(mfs))
2044 {
2045 // m_log.DebugFormat("[XEngine]: Writing linemap file {0}", mappath);
2046
2047 msw.Write(mapE.InnerText);
2048 }
2049 }
2050 }
2051 catch (IOException ex)
2052 {
2053 // if there already exists a file at that location, it may be locked.
2054 m_log.ErrorFormat("[XEngine]: Linemap file {0} already exists! {1}", mappath, ex.Message);
1921 } 2055 }
1922 } 2056 }
1923 } 2057 }
@@ -1931,43 +2065,16 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1931 { 2065 {
1932 using (StreamWriter ssw = new StreamWriter(sfs)) 2066 using (StreamWriter ssw = new StreamWriter(sfs))
1933 { 2067 {
2068// m_log.DebugFormat("[XEngine]: Writing state file {0}", statepath);
2069
1934 ssw.Write(stateE.OuterXml); 2070 ssw.Write(stateE.OuterXml);
1935 ssw.Close();
1936 } 2071 }
1937 sfs.Close();
1938 } 2072 }
1939 } 2073 }
1940 catch (IOException ex) 2074 catch (IOException ex)
1941 { 2075 {
1942 // if there already exists a file at that location, it may be locked. 2076 // if there already exists a file at that location, it may be locked.
1943 m_log.ErrorFormat("[XEngine]: File {0} already exists! {1}", statepath, ex.Message); 2077 m_log.ErrorFormat("[XEngine]: Error whilst writing state file {0}, {1}", statepath, ex.Message);
1944 }
1945
1946 XmlNodeList mapL = rootE.GetElementsByTagName("LineMap");
1947 if (mapL.Count > 0)
1948 {
1949 XmlElement mapE = (XmlElement)mapL[0];
1950
1951 string mappath = Path.Combine(m_ScriptEnginesPath, World.RegionInfo.RegionID.ToString());
1952 mappath = Path.Combine(mappath, mapE.GetAttribute("Filename"));
1953
1954 try
1955 {
1956 using (FileStream mfs = File.Create(mappath))
1957 {
1958 using (StreamWriter msw = new StreamWriter(mfs))
1959 {
1960 msw.Write(mapE.InnerText);
1961 msw.Close();
1962 }
1963 mfs.Close();
1964 }
1965 }
1966 catch (IOException ex)
1967 {
1968 // if there already exists a file at that location, it may be locked.
1969 m_log.ErrorFormat("[XEngine]: File {0} already exists! {1}", statepath, ex.Message);
1970 }
1971 } 2078 }
1972 2079
1973 return true; 2080 return true;
@@ -2001,45 +2108,59 @@ namespace OpenSim.Region.ScriptEngine.XEngine
2001 if (!topScripts.ContainsKey(si.LocalID)) 2108 if (!topScripts.ContainsKey(si.LocalID))
2002 topScripts[si.RootLocalID] = 0; 2109 topScripts[si.RootLocalID] = 0;
2003 2110
2004// long ticksElapsed = tickNow - si.MeasurementPeriodTickStart; 2111 topScripts[si.RootLocalID] += CalculateAdjustedExectionTime(si, tickNow);
2005// float framesElapsed = ticksElapsed / (18.1818 * TimeSpan.TicksPerMillisecond); 2112 }
2006 2113 }
2007 // Execution time of the script adjusted by it's measurement period to make scripts started at
2008 // different times comparable.
2009// float adjustedExecutionTime
2010// = (float)si.MeasurementPeriodExecutionTime
2011// / ((float)(tickNow - si.MeasurementPeriodTickStart) / ScriptInstance.MaxMeasurementPeriod)
2012// / TimeSpan.TicksPerMillisecond;
2013
2014 long ticksElapsed = tickNow - si.MeasurementPeriodTickStart;
2015
2016 // Avoid divide by zerp
2017 if (ticksElapsed == 0)
2018 ticksElapsed = 1;
2019 2114
2020 // Scale execution time to the ideal 55 fps frame time for these reasons. 2115 return topScripts;
2021 // 2116 }
2022 // 1) XEngine does not execute scripts per frame, unlike other script engines. Hence, there is no
2023 // 'script execution time per frame', which is the original purpose of this value.
2024 //
2025 // 2) Giving the raw execution times is misleading since scripts start at different times, making
2026 // it impossible to compare scripts.
2027 //
2028 // 3) Scaling the raw execution time to the time that the script has been running is better but
2029 // is still misleading since a script that has just been rezzed may appear to have been running
2030 // for much longer.
2031 //
2032 // 4) Hence, we scale execution time to an idealised frame time (55 fps). This is also not perfect
2033 // since the figure does not represent actual execution time and very hard running scripts will
2034 // never exceed 18ms (though this is a very high number for script execution so is a warning sign).
2035 float adjustedExecutionTime
2036 = ((float)si.MeasurementPeriodExecutionTime / ticksElapsed) * 18.1818f;
2037 2117
2038 topScripts[si.RootLocalID] += adjustedExecutionTime; 2118 public float GetScriptExecutionTime(List<UUID> itemIDs)
2119 {
2120 if (itemIDs == null|| itemIDs.Count == 0)
2121 {
2122 return 0.0f;
2123 }
2124 float time = 0.0f;
2125 long tickNow = Util.EnvironmentTickCount();
2126 IScriptInstance si;
2127 // Calculate the time for all scripts that this engine is executing
2128 // Ignore any others
2129 foreach (UUID id in itemIDs)
2130 {
2131 si = GetInstance(id);
2132 if (si != null && si.Running)
2133 {
2134 time += CalculateAdjustedExectionTime(si, tickNow);
2039 } 2135 }
2040 } 2136 }
2137 return time;
2138 }
2041 2139
2042 return topScripts; 2140 private float CalculateAdjustedExectionTime(IScriptInstance si, long tickNow)
2141 {
2142 long ticksElapsed = tickNow - si.MeasurementPeriodTickStart;
2143
2144 // Avoid divide by zero
2145 if (ticksElapsed == 0)
2146 ticksElapsed = 1;
2147
2148 // Scale execution time to the ideal 55 fps frame time for these reasons.
2149 //
2150 // 1) XEngine does not execute scripts per frame, unlike other script engines. Hence, there is no
2151 // 'script execution time per frame', which is the original purpose of this value.
2152 //
2153 // 2) Giving the raw execution times is misleading since scripts start at different times, making
2154 // it impossible to compare scripts.
2155 //
2156 // 3) Scaling the raw execution time to the time that the script has been running is better but
2157 // is still misleading since a script that has just been rezzed may appear to have been running
2158 // for much longer.
2159 //
2160 // 4) Hence, we scale execution time to an idealised frame time (55 fps). This is also not perfect
2161 // since the figure does not represent actual execution time and very hard running scripts will
2162 // never exceed 18ms (though this is a very high number for script execution so is a warning sign).
2163 return ((float)si.MeasurementPeriodExecutionTime / ticksElapsed) * 18.1818f;
2043 } 2164 }
2044 2165
2045 public void SuspendScript(UUID itemID) 2166 public void SuspendScript(UUID itemID)
diff --git a/OpenSim/Region/UserStatistics/WebStatsModule.cs b/OpenSim/Region/UserStatistics/WebStatsModule.cs
index b9ba4bc..faf746f 100644
--- a/OpenSim/Region/UserStatistics/WebStatsModule.cs
+++ b/OpenSim/Region/UserStatistics/WebStatsModule.cs
@@ -90,7 +90,7 @@ namespace OpenSim.Region.UserStatistics
90 90
91 dbConn = new SqliteConnection("URI=file:LocalUserStatistics.db,version=3"); 91 dbConn = new SqliteConnection("URI=file:LocalUserStatistics.db,version=3");
92 dbConn.Open(); 92 dbConn.Open();
93 CheckAndUpdateDatabase(dbConn); 93 CreateTables(dbConn);
94 94
95 Prototype_distributor protodep = new Prototype_distributor(); 95 Prototype_distributor protodep = new Prototype_distributor();
96 Updater_distributor updatedep = new Updater_distributor(); 96 Updater_distributor updatedep = new Updater_distributor();
@@ -131,7 +131,7 @@ namespace OpenSim.Region.UserStatistics
131 } 131 }
132 } 132 }
133 133
134 public void ReceiveClassicSimStatsPacket(SimStats stats) 134 private void ReceiveClassicSimStatsPacket(SimStats stats)
135 { 135 {
136 if (!enabled) 136 if (!enabled)
137 { 137 {
@@ -163,7 +163,7 @@ namespace OpenSim.Region.UserStatistics
163 } 163 }
164 } 164 }
165 165
166 public Hashtable HandleUnknownCAPSRequest(Hashtable request) 166 private Hashtable HandleUnknownCAPSRequest(Hashtable request)
167 { 167 {
168 //string regpath = request["uri"].ToString(); 168 //string regpath = request["uri"].ToString();
169 int response_code = 200; 169 int response_code = 200;
@@ -178,7 +178,7 @@ namespace OpenSim.Region.UserStatistics
178 return responsedata; 178 return responsedata;
179 } 179 }
180 180
181 public Hashtable HandleStatsRequest(Hashtable request) 181 private Hashtable HandleStatsRequest(Hashtable request)
182 { 182 {
183 lastHit = System.Environment.TickCount; 183 lastHit = System.Environment.TickCount;
184 Hashtable responsedata = new Hashtable(); 184 Hashtable responsedata = new Hashtable();
@@ -237,36 +237,12 @@ namespace OpenSim.Region.UserStatistics
237 237
238 return responsedata; 238 return responsedata;
239 } 239 }
240
241 public void CheckAndUpdateDatabase(SqliteConnection db)
242 {
243 lock (db)
244 {
245 // TODO: FIXME: implement stats migrations
246 const string SQL = @"SELECT * FROM migrations LIMIT 1";
247
248 using (SqliteCommand cmd = new SqliteCommand(SQL, db))
249 {
250 try
251 {
252 cmd.ExecuteNonQuery();
253 }
254 catch (SqliteSyntaxException)
255 {
256 CreateTables(db);
257 }
258 }
259 }
260 }
261 240
262 public void CreateTables(SqliteConnection db) 241 private void CreateTables(SqliteConnection db)
263 { 242 {
264 using (SqliteCommand createcmd = new SqliteCommand(SQL_STATS_TABLE_CREATE, db)) 243 using (SqliteCommand createcmd = new SqliteCommand(SQL_STATS_TABLE_CREATE, db))
265 { 244 {
266 createcmd.ExecuteNonQuery(); 245 createcmd.ExecuteNonQuery();
267
268 createcmd.CommandText = SQL_MIGRA_TABLE_CREATE;
269 createcmd.ExecuteNonQuery();
270 } 246 }
271 } 247 }
272 248
@@ -301,22 +277,23 @@ namespace OpenSim.Region.UserStatistics
301 get { return true; } 277 get { return true; }
302 } 278 }
303 279
304 public void OnRegisterCaps(UUID agentID, Caps caps) 280 private void OnRegisterCaps(UUID agentID, Caps caps)
305 { 281 {
306// m_log.DebugFormat("[WEB STATS MODULE]: OnRegisterCaps: agentID {0} caps {1}", agentID, caps); 282// m_log.DebugFormat("[WEB STATS MODULE]: OnRegisterCaps: agentID {0} caps {1}", agentID, caps);
307 283
308 string capsPath = "/CAPS/VS/" + UUID.Random(); 284 string capsPath = "/CAPS/VS/" + UUID.Random();
309 caps.RegisterHandler("ViewerStats", 285 caps.RegisterHandler(
310 new RestStreamHandler("POST", capsPath, 286 "ViewerStats",
311 delegate(string request, string path, string param, 287 new RestStreamHandler(
312 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 288 "POST",
313 { 289 capsPath,
314 return ViewerStatsReport(request, path, param, 290 (request, path, param, httpRequest, httpResponse)
315 agentID, caps); 291 => ViewerStatsReport(request, path, param, agentID, caps),
316 })); 292 "ViewerStats",
293 agentID.ToString()));
317 } 294 }
318 295
319 public void OnDeRegisterCaps(UUID agentID, Caps caps) 296 private void OnDeRegisterCaps(UUID agentID, Caps caps)
320 { 297 {
321 } 298 }
322 299
@@ -336,7 +313,7 @@ namespace OpenSim.Region.UserStatistics
336 } 313 }
337 } 314 }
338 315
339 public void OnMakeRootAgent(ScenePresence agent) 316 private void OnMakeRootAgent(ScenePresence agent)
340 { 317 {
341 UUID regionUUID = GetRegionUUIDFromHandle(agent.RegionHandle); 318 UUID regionUUID = GetRegionUUIDFromHandle(agent.RegionHandle);
342 319
@@ -365,11 +342,11 @@ namespace OpenSim.Region.UserStatistics
365 } 342 }
366 } 343 }
367 344
368 public void OnMakeChildAgent(ScenePresence agent) 345 private void OnMakeChildAgent(ScenePresence agent)
369 { 346 {
370 } 347 }
371 348
372 public void OnClientClosed(UUID agentID, Scene scene) 349 private void OnClientClosed(UUID agentID, Scene scene)
373 { 350 {
374 lock (m_sessions) 351 lock (m_sessions)
375 { 352 {
@@ -380,7 +357,7 @@ namespace OpenSim.Region.UserStatistics
380 } 357 }
381 } 358 }
382 359
383 public string readLogLines(int amount) 360 private string readLogLines(int amount)
384 { 361 {
385 Encoding encoding = Encoding.ASCII; 362 Encoding encoding = Encoding.ASCII;
386 int sizeOfChar = encoding.GetByteCount("\n"); 363 int sizeOfChar = encoding.GetByteCount("\n");
@@ -418,7 +395,7 @@ namespace OpenSim.Region.UserStatistics
418 return encoding.GetString(buffer); 395 return encoding.GetString(buffer);
419 } 396 }
420 397
421 public UUID GetRegionUUIDFromHandle(ulong regionhandle) 398 private UUID GetRegionUUIDFromHandle(ulong regionhandle)
422 { 399 {
423 lock (m_scenes) 400 lock (m_scenes)
424 { 401 {
@@ -441,17 +418,17 @@ namespace OpenSim.Region.UserStatistics
441 /// <param name="agentID"></param> 418 /// <param name="agentID"></param>
442 /// <param name="caps"></param> 419 /// <param name="caps"></param>
443 /// <returns></returns> 420 /// <returns></returns>
444 public string ViewerStatsReport(string request, string path, string param, 421 private string ViewerStatsReport(string request, string path, string param,
445 UUID agentID, Caps caps) 422 UUID agentID, Caps caps)
446 { 423 {
447// m_log.DebugFormat("[WEB STATS MODULE]: Received viewer starts report from {0}", agentID); 424// m_log.DebugFormat("[WEB STATS MODULE]: Received viewer starts report from {0}", agentID);
448 425
449 UpdateUserStats(ParseViewerStats(request,agentID), dbConn); 426 UpdateUserStats(ParseViewerStats(request, agentID), dbConn);
450 427
451 return String.Empty; 428 return String.Empty;
452 } 429 }
453 430
454 public UserSessionID ParseViewerStats(string request, UUID agentID) 431 private UserSessionID ParseViewerStats(string request, UUID agentID)
455 { 432 {
456 UserSessionID uid = new UserSessionID(); 433 UserSessionID uid = new UserSessionID();
457 UserSessionData usd; 434 UserSessionData usd;
@@ -592,14 +569,14 @@ namespace OpenSim.Region.UserStatistics
592 return uid; 569 return uid;
593 } 570 }
594 571
595 public void UpdateUserStats(UserSessionID uid, SqliteConnection db) 572 private void UpdateUserStats(UserSessionID uid, SqliteConnection db)
596 { 573 {
597 if (uid.session_id == UUID.Zero) 574 if (uid.session_id == UUID.Zero)
598 return; 575 return;
599 576
600 lock (db) 577 lock (db)
601 { 578 {
602 using (SqliteCommand updatecmd = new SqliteCommand(SQL_STATS_TABLE_UPDATE, db)) 579 using (SqliteCommand updatecmd = new SqliteCommand(SQL_STATS_TABLE_INSERT, db))
603 { 580 {
604 updatecmd.Parameters.Add(new SqliteParameter(":session_id", uid.session_data.session_id.ToString())); 581 updatecmd.Parameters.Add(new SqliteParameter(":session_id", uid.session_data.session_id.ToString()));
605 updatecmd.Parameters.Add(new SqliteParameter(":agent_id", uid.session_data.agent_id.ToString())); 582 updatecmd.Parameters.Add(new SqliteParameter(":agent_id", uid.session_data.agent_id.ToString()));
@@ -648,44 +625,26 @@ namespace OpenSim.Region.UserStatistics
648 updatecmd.Parameters.Add(new SqliteParameter(":f_dropped", uid.session_data.f_dropped)); 625 updatecmd.Parameters.Add(new SqliteParameter(":f_dropped", uid.session_data.f_dropped));
649 updatecmd.Parameters.Add(new SqliteParameter(":f_failed_resends", uid.session_data.f_failed_resends)); 626 updatecmd.Parameters.Add(new SqliteParameter(":f_failed_resends", uid.session_data.f_failed_resends));
650 updatecmd.Parameters.Add(new SqliteParameter(":f_invalid", uid.session_data.f_invalid)); 627 updatecmd.Parameters.Add(new SqliteParameter(":f_invalid", uid.session_data.f_invalid));
651
652 updatecmd.Parameters.Add(new SqliteParameter(":f_off_circuit", uid.session_data.f_off_circuit)); 628 updatecmd.Parameters.Add(new SqliteParameter(":f_off_circuit", uid.session_data.f_off_circuit));
653 updatecmd.Parameters.Add(new SqliteParameter(":f_resent", uid.session_data.f_resent)); 629 updatecmd.Parameters.Add(new SqliteParameter(":f_resent", uid.session_data.f_resent));
654 updatecmd.Parameters.Add(new SqliteParameter(":f_send_packet", uid.session_data.f_send_packet)); 630 updatecmd.Parameters.Add(new SqliteParameter(":f_send_packet", uid.session_data.f_send_packet));
655
656 updatecmd.Parameters.Add(new SqliteParameter(":session_key", uid.session_data.session_id.ToString()));
657 updatecmd.Parameters.Add(new SqliteParameter(":agent_key", uid.session_data.agent_id.ToString()));
658 updatecmd.Parameters.Add(new SqliteParameter(":region_key", uid.session_data.region_id.ToString()));
659 631
660// m_log.DebugFormat("[WEB STATS MODULE]: Database stats update for {0}", uid.session_data.agent_id); 632// StringBuilder parameters = new StringBuilder();
661 633// SqliteParameterCollection spc = updatecmd.Parameters;
662 int result = updatecmd.ExecuteNonQuery(); 634// foreach (SqliteParameter sp in spc)
663 635// parameters.AppendFormat("{0}={1},", sp.ParameterName, sp.Value);
664 if (result == 0) 636//
665 { 637// m_log.DebugFormat("[WEB STATS MODULE]: Parameters {0}", parameters);
666// m_log.DebugFormat("[WEB STATS MODULE]: Database stats insert for {0}", uid.session_data.agent_id);
667 638
668 updatecmd.CommandText = SQL_STATS_TABLE_INSERT; 639// m_log.DebugFormat("[WEB STATS MODULE]: Database stats update for {0}", uid.session_data.agent_id);
669 640
670 try 641 updatecmd.ExecuteNonQuery();
671 {
672 updatecmd.ExecuteNonQuery();
673 }
674 catch (Exception e)
675 {
676 m_log.WarnFormat(
677 "[WEB STATS MODULE]: failed to write stats for {0}, storage Execution Exception {1}{2}",
678 uid.session_data.agent_id, e.Message, e.StackTrace);
679 }
680 }
681 } 642 }
682 } 643 }
683 } 644 }
684 645
685 #region SQL 646 #region SQL
686 private const string SQL_MIGRA_TABLE_CREATE = @"create table migrations(name varchar(100), version int)"; 647 private const string SQL_STATS_TABLE_CREATE = @"CREATE TABLE IF NOT EXISTS stats_session_data (
687
688 private const string SQL_STATS_TABLE_CREATE = @"CREATE TABLE stats_session_data (
689 session_id VARCHAR(36) NOT NULL PRIMARY KEY, 648 session_id VARCHAR(36) NOT NULL PRIMARY KEY,
690 agent_id VARCHAR(36) NOT NULL DEFAULT '', 649 agent_id VARCHAR(36) NOT NULL DEFAULT '',
691 region_id VARCHAR(36) NOT NULL DEFAULT '', 650 region_id VARCHAR(36) NOT NULL DEFAULT '',
@@ -735,11 +694,11 @@ namespace OpenSim.Region.UserStatistics
735 f_send_packet INT NOT NULL DEFAULT '0' 694 f_send_packet INT NOT NULL DEFAULT '0'
736 );"; 695 );";
737 696
738 private const string SQL_STATS_TABLE_INSERT = @"INSERT INTO stats_session_data ( 697 private const string SQL_STATS_TABLE_INSERT = @"INSERT OR REPLACE INTO stats_session_data (
739session_id, agent_id, region_id, last_updated, remote_ip, name_f, name_l, avg_agents_in_view, min_agents_in_view, max_agents_in_view, 698session_id, agent_id, region_id, last_updated, remote_ip, name_f, name_l, avg_agents_in_view, min_agents_in_view, max_agents_in_view,
740mode_agents_in_view, avg_fps, min_fps, max_fps, mode_fps, a_language, mem_use, meters_traveled, avg_ping, min_ping, max_ping, mode_ping, 699mode_agents_in_view, avg_fps, min_fps, max_fps, mode_fps, a_language, mem_use, meters_traveled, avg_ping, min_ping, max_ping, mode_ping,
741regions_visited, run_time, avg_sim_fps, min_sim_fps, max_sim_fps, mode_sim_fps, start_time, client_version, s_cpu, s_gpu, s_os, s_ram, 700regions_visited, run_time, avg_sim_fps, min_sim_fps, max_sim_fps, mode_sim_fps, start_time, client_version, s_cpu, s_gpu, s_os, s_ram,
742d_object_kb, d_texture_kb, n_in_kb, n_in_pk, n_out_kb, n_out_pk, f_dropped, f_failed_resends, f_invalid, f_invalid, f_off_circuit, 701d_object_kb, d_texture_kb, d_world_kb, n_in_kb, n_in_pk, n_out_kb, n_out_pk, f_dropped, f_failed_resends, f_invalid, f_off_circuit,
743f_resent, f_send_packet 702f_resent, f_send_packet
744) 703)
745VALUES 704VALUES
@@ -747,62 +706,13 @@ VALUES
747:session_id, :agent_id, :region_id, :last_updated, :remote_ip, :name_f, :name_l, :avg_agents_in_view, :min_agents_in_view, :max_agents_in_view, 706:session_id, :agent_id, :region_id, :last_updated, :remote_ip, :name_f, :name_l, :avg_agents_in_view, :min_agents_in_view, :max_agents_in_view,
748:mode_agents_in_view, :avg_fps, :min_fps, :max_fps, :mode_fps, :a_language, :mem_use, :meters_traveled, :avg_ping, :min_ping, :max_ping, :mode_ping, 707:mode_agents_in_view, :avg_fps, :min_fps, :max_fps, :mode_fps, :a_language, :mem_use, :meters_traveled, :avg_ping, :min_ping, :max_ping, :mode_ping,
749:regions_visited, :run_time, :avg_sim_fps, :min_sim_fps, :max_sim_fps, :mode_sim_fps, :start_time, :client_version, :s_cpu, :s_gpu, :s_os, :s_ram, 708:regions_visited, :run_time, :avg_sim_fps, :min_sim_fps, :max_sim_fps, :mode_sim_fps, :start_time, :client_version, :s_cpu, :s_gpu, :s_os, :s_ram,
750:d_object_kb, :d_texture_kb, :n_in_kb, :n_in_pk, :n_out_kb, :n_out_pk, :f_dropped, :f_failed_resends, :f_invalid, :f_invalid, :f_off_circuit, 709:d_object_kb, :d_texture_kb, :d_world_kb, :n_in_kb, :n_in_pk, :n_out_kb, :n_out_pk, :f_dropped, :f_failed_resends, :f_invalid, :f_off_circuit,
751:f_resent, :f_send_packet 710:f_resent, :f_send_packet
752) 711)
753"; 712";
754 713
755 private const string SQL_STATS_TABLE_UPDATE = @" 714 #endregion
756UPDATE stats_session_data 715
757set session_id=:session_id,
758 agent_id=:agent_id,
759 region_id=:region_id,
760 last_updated=:last_updated,
761 remote_ip=:remote_ip,
762 name_f=:name_f,
763 name_l=:name_l,
764 avg_agents_in_view=:avg_agents_in_view,
765 min_agents_in_view=:min_agents_in_view,
766 max_agents_in_view=:max_agents_in_view,
767 mode_agents_in_view=:mode_agents_in_view,
768 avg_fps=:avg_fps,
769 min_fps=:min_fps,
770 max_fps=:max_fps,
771 mode_fps=:mode_fps,
772 a_language=:a_language,
773 mem_use=:mem_use,
774 meters_traveled=:meters_traveled,
775 avg_ping=:avg_ping,
776 min_ping=:min_ping,
777 max_ping=:max_ping,
778 mode_ping=:mode_ping,
779 regions_visited=:regions_visited,
780 run_time=:run_time,
781 avg_sim_fps=:avg_sim_fps,
782 min_sim_fps=:min_sim_fps,
783 max_sim_fps=:max_sim_fps,
784 mode_sim_fps=:mode_sim_fps,
785 start_time=:start_time,
786 client_version=:client_version,
787 s_cpu=:s_cpu,
788 s_gpu=:s_gpu,
789 s_os=:s_os,
790 s_ram=:s_ram,
791 d_object_kb=:d_object_kb,
792 d_texture_kb=:d_texture_kb,
793 d_world_kb=:d_world_kb,
794 n_in_kb=:n_in_kb,
795 n_in_pk=:n_in_pk,
796 n_out_kb=:n_out_kb,
797 n_out_pk=:n_out_pk,
798 f_dropped=:f_dropped,
799 f_failed_resends=:f_failed_resends,
800 f_invalid=:f_invalid,
801 f_off_circuit=:f_off_circuit,
802 f_resent=:f_resent,
803 f_send_packet=:f_send_packet
804WHERE session_id=:session_key AND agent_id=:agent_key AND region_id=:region_key";
805 #endregion
806 } 716 }
807 717
808 public static class UserSessionUtil 718 public static class UserSessionUtil