aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs123
-rw-r--r--OpenSim/Data/AssetDataBase.cs2
-rw-r--r--OpenSim/Data/IAssetData.cs2
-rw-r--r--OpenSim/Data/IUserAccountData.cs1
-rw-r--r--OpenSim/Data/MSSQL/MSSQLAssetData.cs4
-rw-r--r--OpenSim/Data/MSSQL/MSSQLAvatarData.cs2
-rw-r--r--OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs4
-rw-r--r--OpenSim/Data/MSSQL/MSSQLGridUserData.cs2
-rw-r--r--OpenSim/Data/MSSQL/MSSQLManager.cs4
-rw-r--r--OpenSim/Data/MSSQL/MSSQLPresenceData.cs2
-rw-r--r--OpenSim/Data/MSSQL/MSSQLUserAccountData.cs5
-rw-r--r--OpenSim/Data/MSSQL/MSSQLXInventoryData.cs4
-rw-r--r--OpenSim/Data/MySQL/MySQLAssetData.cs4
-rw-r--r--OpenSim/Data/MySQL/MySQLGenericTableHandler.cs7
-rw-r--r--OpenSim/Data/MySQL/MySQLSimulationData.cs98
-rw-r--r--OpenSim/Data/MySQL/MySQLUserAccountData.cs43
-rw-r--r--OpenSim/Data/MySQL/Resources/RegionStore.migrations2
-rw-r--r--OpenSim/Data/Null/NullUserAccountData.cs5
-rw-r--r--OpenSim/Data/SQLite/SQLiteAssetData.cs4
-rw-r--r--OpenSim/Data/SQLite/SQLiteUserAccountData.cs5
-rw-r--r--OpenSim/Framework/AssetBase.cs8
-rw-r--r--OpenSim/Framework/AvatarAppearance.cs39
-rw-r--r--OpenSim/Framework/Communications/RestClient.cs2
-rw-r--r--OpenSim/Framework/EstateSettings.cs56
-rw-r--r--OpenSim/Framework/ICallingCardModule.cs13
-rw-r--r--OpenSim/Framework/IClientAPI.cs14
-rw-r--r--OpenSim/Framework/IMoneyModule.cs1
-rw-r--r--OpenSim/Framework/LandData.cs2
-rw-r--r--OpenSim/Framework/ParcelMediaCommandEnum.cs2
-rw-r--r--OpenSim/Framework/PluginLoader.cs17
-rw-r--r--OpenSim/Framework/PrimitiveBaseShape.cs30
-rw-r--r--OpenSim/Framework/RegionInfo.cs15
-rw-r--r--OpenSim/Framework/RegionLoader/Web/RegionLoaderWebServer.cs118
-rw-r--r--OpenSim/Framework/RegionSettings.cs22
-rw-r--r--OpenSim/Framework/Servers/BaseOpenSimServer.cs2
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs31
-rw-r--r--OpenSim/Framework/Servers/VersionInfo.cs6
-rw-r--r--OpenSim/Framework/TaskInventoryDictionary.cs164
-rw-r--r--OpenSim/Framework/TaskInventoryItem.cs12
-rw-r--r--OpenSim/Framework/Tests/MundaneFrameworkTests.cs6
-rw-r--r--OpenSim/Framework/Util.cs46
-rw-r--r--OpenSim/Framework/Watchdog.cs4
-rw-r--r--OpenSim/Framework/WebUtil.cs10
-rw-r--r--OpenSim/Region/Application/OpenSim.cs4
-rw-r--r--OpenSim/Region/Application/OpenSimBase.cs93
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs3
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs703
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs65
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs4
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs4
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs127
-rw-r--r--OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs85
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs93
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs105
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs19
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs202
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs67
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs97
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs52
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs5
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs138
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs32
-rw-r--r--OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs3
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs38
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs19
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs124
-rw-r--r--OpenSim/Region/CoreModules/LightShare/LightShareModule.cs3
-rw-r--r--OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs31
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs153
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs23
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs15
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs8
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs12
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs15
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs18
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs79
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs456
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs85
-rw-r--r--OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs7
-rw-r--r--OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Region/RestartModule.cs38
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs12
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs50
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs6
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityInventory.cs3
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs4
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEstateModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IInterregionComms.cs8
-rw-r--r--OpenSim/Region/Framework/Interfaces/IScriptModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISnmpModule.cs27
-rw-r--r--OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs13
-rw-r--r--OpenSim/Region/Framework/ModuleLoader.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs24
-rw-r--r--OpenSim/Region/Framework/Scenes/Prioritizer.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs344
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs489
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs37
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs230
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneManager.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs17
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs569
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs199
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs808
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs188
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs28
-rw-r--r--OpenSim/Region/Framework/Scenes/UndoState.cs87
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs4
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs9
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs4
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs22
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs16
-rw-r--r--OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs4
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs12
-rw-r--r--OpenSim/Region/Physics/ChOdePlugin/AssemblyInfo.cs58
-rw-r--r--OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs1438
-rw-r--r--OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs3875
-rw-r--r--OpenSim/Region/Physics/ChOdePlugin/ODERayCastRequestManager.cs384
-rw-r--r--OpenSim/Region/Physics/ChOdePlugin/OdePhysicsJoint.cs (renamed from OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs)46
-rw-r--r--OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs3841
-rw-r--r--OpenSim/Region/Physics/ChOdePlugin/Tests/ODETestClass.cs122
-rw-r--r--OpenSim/Region/Physics/ChOdePlugin/drawstuff.cs98
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsScene.cs3
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODEPrim.cs6
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs11
-rw-r--r--OpenSim/Region/Physics/POSPlugin/POSPrim.cs2
-rw-r--r--OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs82
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs20
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs118
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs2810
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs85
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs9
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs32
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs46
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs71
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs3
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs21
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs21
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Helpers.cs8
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs85
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs32
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs362
-rw-r--r--OpenSim/Server/Handlers/Simulation/AgentHandlers.cs23
-rw-r--r--OpenSim/Services/AssetService/AssetService.cs5
-rw-r--r--OpenSim/Services/AuthenticationService/AuthenticationServiceBase.cs9
-rw-r--r--OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs64
-rw-r--r--OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs5
-rw-r--r--OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs196
-rw-r--r--OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs16
-rw-r--r--OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs2
-rw-r--r--OpenSim/Services/Connectors/Land/LandServiceConnector.cs2
-rw-r--r--OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs11
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs90
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs5
-rw-r--r--OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs18
-rw-r--r--OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs5
-rw-r--r--OpenSim/Services/GridService/HypergridLinker.cs62
-rw-r--r--OpenSim/Services/HypergridService/UserAccountCache.cs5
-rw-r--r--OpenSim/Services/HypergridService/UserAgentService.cs10
-rw-r--r--OpenSim/Services/Interfaces/IAttachmentsService.cs17
-rw-r--r--OpenSim/Services/Interfaces/IGridService.cs14
-rw-r--r--OpenSim/Services/Interfaces/ISimulationService.cs8
-rw-r--r--OpenSim/Services/Interfaces/IUserAccountService.cs5
-rw-r--r--OpenSim/Services/LLLoginService/LLLoginResponse.cs6
-rw-r--r--OpenSim/Services/LLLoginService/LLLoginService.cs9
-rw-r--r--OpenSim/Services/UserAccountService/UserAccountService.cs21
-rw-r--r--OpenSim/Tests/Common/Mock/MockAssetDataPlugin.cs3
-rw-r--r--OpenSim/Tests/Common/Mock/TestClient.cs9
179 files changed, 18380 insertions, 3161 deletions
diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
index 7f1a0ed..914e4d6 100644
--- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
+++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
@@ -131,6 +131,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
131 availableMethods["admin_region_query"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcRegionQueryMethod); 131 availableMethods["admin_region_query"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcRegionQueryMethod);
132 availableMethods["admin_shutdown"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcShutdownMethod); 132 availableMethods["admin_shutdown"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcShutdownMethod);
133 availableMethods["admin_broadcast"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAlertMethod); 133 availableMethods["admin_broadcast"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAlertMethod);
134 availableMethods["admin_dialog"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcDialogMethod);
134 availableMethods["admin_restart"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcRestartMethod); 135 availableMethods["admin_restart"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcRestartMethod);
135 availableMethods["admin_load_heightmap"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcLoadHeightmapMethod); 136 availableMethods["admin_load_heightmap"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcLoadHeightmapMethod);
136 availableMethods["admin_save_heightmap"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcSaveHeightmapMethod); 137 availableMethods["admin_save_heightmap"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcSaveHeightmapMethod);
@@ -262,16 +263,70 @@ namespace OpenSim.ApplicationPlugins.RemoteController
262 Scene rebootedScene = null; 263 Scene rebootedScene = null;
263 GetSceneFromRegionParams(requestData, responseData, out rebootedScene); 264 GetSceneFromRegionParams(requestData, responseData, out rebootedScene);
264 265
266 IRestartModule restartModule = rebootedScene.RequestModuleInterface<IRestartModule>();
267
265 responseData["success"] = false; 268 responseData["success"] = false;
266 responseData["accepted"] = true; 269 responseData["accepted"] = true;
267 responseData["rebooting"] = true; 270 responseData["rebooting"] = true;
268 271
269 IRestartModule restartModule = rebootedScene.RequestModuleInterface<IRestartModule>(); 272 string message;
270 if (restartModule != null) 273 List<int> times = new List<int>();
274
275 if (requestData.ContainsKey("alerts"))
276 {
277 string[] alertTimes = requestData["alerts"].ToString().Split( new char[] {','});
278 if (alertTimes.Length == 1 && Convert.ToInt32(alertTimes[0]) == -1)
279 {
280 if (restartModule != null)
281 {
282 message = "Restart has been cancelled";
283
284 if (requestData.ContainsKey("message"))
285 message = requestData["message"].ToString();
286
287 restartModule.AbortRestart(message);
288
289 responseData["success"] = true;
290 responseData["rebooting"] = false;
291
292 return;
293 }
294 }
295 foreach (string a in alertTimes)
296 times.Add(Convert.ToInt32(a));
297 }
298 else
271 { 299 {
272 List<int> times = new List<int> { 30, 15 }; 300 int timeout = 30;
301 if (requestData.ContainsKey("milliseconds"))
302 timeout = Int32.Parse(requestData["milliseconds"].ToString()) / 1000;
303 while (timeout > 0)
304 {
305 times.Add(timeout);
306 if (timeout > 300)
307 timeout -= 120;
308 else if (timeout > 30)
309 timeout -= 30;
310 else
311 timeout -= 15;
312 }
313 }
314
315 message = "Region is restarting in {0}. Please save what you are doing and log out.";
273 316
274 restartModule.ScheduleRestart(UUID.Zero, "Region will restart in {0}", times.ToArray(), true); 317 if (requestData.ContainsKey("message"))
318 message = requestData["message"].ToString();
319
320 bool notice = true;
321 if (requestData.ContainsKey("noticetype")
322 && ((string)requestData["noticetype"] == "dialog"))
323 {
324 notice = false;
325 }
326
327 if (restartModule != null)
328 {
329 restartModule.ScheduleRestart(UUID.Zero, message, times.ToArray(), notice);
275 responseData["success"] = true; 330 responseData["success"] = true;
276 } 331 }
277 } 332 }
@@ -310,6 +365,32 @@ namespace OpenSim.ApplicationPlugins.RemoteController
310 m_log.Info("[RADMIN]: Alert request complete"); 365 m_log.Info("[RADMIN]: Alert request complete");
311 } 366 }
312 367
368 public void XmlRpcDialogMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
369 {
370 Hashtable responseData = (Hashtable)response.Value;
371
372 m_log.Info("[RADMIN]: Dialog request started");
373
374 Hashtable requestData = (Hashtable)request.Params[0];
375
376 string message = (string)requestData["message"];
377 string fromuuid = (string)requestData["from"];
378 m_log.InfoFormat("[RADMIN]: Broadcasting: {0}", message);
379
380 responseData["accepted"] = true;
381 responseData["success"] = true;
382
383 m_application.SceneManager.ForEachScene(
384 delegate(Scene scene)
385 {
386 IDialogModule dialogModule = scene.RequestModuleInterface<IDialogModule>();
387 if (dialogModule != null)
388 dialogModule.SendNotificationToUsersInRegion(UUID.Zero, fromuuid, message);
389 });
390
391 m_log.Info("[RADMIN]: Dialog request complete");
392 }
393
313 private void XmlRpcLoadHeightmapMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) 394 private void XmlRpcLoadHeightmapMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
314 { 395 {
315 m_log.Info("[RADMIN]: Load height maps request started"); 396 m_log.Info("[RADMIN]: Load height maps request started");
@@ -398,13 +479,32 @@ namespace OpenSim.ApplicationPlugins.RemoteController
398 message = "Region is going down now."; 479 message = "Region is going down now.";
399 } 480 }
400 481
401 m_application.SceneManager.ForEachScene( 482 if (requestData.ContainsKey("noticetype")
483 && ((string) requestData["noticetype"] == "dialog"))
484 {
485 m_application.SceneManager.ForEachScene(
486
402 delegate(Scene scene) 487 delegate(Scene scene)
488 {
489 IDialogModule dialogModule = scene.RequestModuleInterface<IDialogModule>();
490 if (dialogModule != null)
491 dialogModule.SendNotificationToUsersInRegion(UUID.Zero, "System", message);
492 });
493 }
494 else
495 {
496 if (!requestData.ContainsKey("noticetype")
497 || ((string)requestData["noticetype"] != "none"))
498 {
499 m_application.SceneManager.ForEachScene(
500 delegate(Scene scene)
403 { 501 {
404 IDialogModule dialogModule = scene.RequestModuleInterface<IDialogModule>(); 502 IDialogModule dialogModule = scene.RequestModuleInterface<IDialogModule>();
405 if (dialogModule != null) 503 if (dialogModule != null)
406 dialogModule.SendGeneralAlert(message); 504 dialogModule.SendGeneralAlert(message);
407 }); 505 });
506 }
507 }
408 508
409 // Perform shutdown 509 // Perform shutdown
410 System.Timers.Timer shutdownTimer = new System.Timers.Timer(timeout); // Wait before firing 510 System.Timers.Timer shutdownTimer = new System.Timers.Timer(timeout); // Wait before firing
@@ -1570,21 +1670,22 @@ namespace OpenSim.ApplicationPlugins.RemoteController
1570 1670
1571 private void XmlRpcRegionQueryMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) 1671 private void XmlRpcRegionQueryMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
1572 { 1672 {
1573 m_log.Info("[RADMIN]: Received Query XML Administrator Request");
1574
1575 Hashtable responseData = (Hashtable)response.Value; 1673 Hashtable responseData = (Hashtable)response.Value;
1576 Hashtable requestData = (Hashtable)request.Params[0]; 1674 Hashtable requestData = (Hashtable)request.Params[0];
1577 1675
1676 responseData["success"] = true;
1677
1578 CheckRegionParams(requestData, responseData); 1678 CheckRegionParams(requestData, responseData);
1579 1679
1580 Scene scene = null; 1680 Scene scene = null;
1581 GetSceneFromRegionParams(requestData, responseData, out scene); 1681 GetSceneFromRegionParams(requestData, responseData, out scene);
1582 1682
1583 int health = scene.GetHealth(); 1683 int flags;
1684 string text;
1685 int health = scene.GetHealth(out flags, out text);
1584 responseData["health"] = health; 1686 responseData["health"] = health;
1585 1687 responseData["flags"] = flags;
1586 responseData["success"] = true; 1688 responseData["message"] = text;
1587 m_log.Info("[RADMIN]: Query XML Administrator Request complete");
1588 } 1689 }
1589 1690
1590 private void XmlRpcConsoleCommandMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) 1691 private void XmlRpcConsoleCommandMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
diff --git a/OpenSim/Data/AssetDataBase.cs b/OpenSim/Data/AssetDataBase.cs
index e1a810c..b4ae913 100644
--- a/OpenSim/Data/AssetDataBase.cs
+++ b/OpenSim/Data/AssetDataBase.cs
@@ -38,7 +38,7 @@ namespace OpenSim.Data
38 { 38 {
39 public abstract AssetBase GetAsset(UUID uuid); 39 public abstract AssetBase GetAsset(UUID uuid);
40 40
41 public abstract void StoreAsset(AssetBase asset); 41 public abstract bool StoreAsset(AssetBase asset);
42 public abstract bool ExistsAsset(UUID uuid); 42 public abstract bool ExistsAsset(UUID uuid);
43 43
44 public abstract List<AssetMetadata> FetchAssetMetadataSet(int start, int count); 44 public abstract List<AssetMetadata> FetchAssetMetadataSet(int start, int count);
diff --git a/OpenSim/Data/IAssetData.cs b/OpenSim/Data/IAssetData.cs
index f31b215c..0c8eadd 100644
--- a/OpenSim/Data/IAssetData.cs
+++ b/OpenSim/Data/IAssetData.cs
@@ -34,7 +34,7 @@ namespace OpenSim.Data
34 public interface IAssetDataPlugin : IPlugin 34 public interface IAssetDataPlugin : IPlugin
35 { 35 {
36 AssetBase GetAsset(UUID uuid); 36 AssetBase GetAsset(UUID uuid);
37 void StoreAsset(AssetBase asset); 37 bool StoreAsset(AssetBase asset);
38 bool ExistsAsset(UUID uuid); 38 bool ExistsAsset(UUID uuid);
39 List<AssetMetadata> FetchAssetMetadataSet(int start, int count); 39 List<AssetMetadata> FetchAssetMetadataSet(int start, int count);
40 void Initialise(string connect); 40 void Initialise(string connect);
diff --git a/OpenSim/Data/IUserAccountData.cs b/OpenSim/Data/IUserAccountData.cs
index 906ba6c..bc7eda7 100644
--- a/OpenSim/Data/IUserAccountData.cs
+++ b/OpenSim/Data/IUserAccountData.cs
@@ -50,5 +50,6 @@ namespace OpenSim.Data
50 bool Store(UserAccountData data); 50 bool Store(UserAccountData data);
51 bool Delete(string field, string val); 51 bool Delete(string field, string val);
52 UserAccountData[] GetUsers(UUID scopeID, string query); 52 UserAccountData[] GetUsers(UUID scopeID, string query);
53 UserAccountData[] GetUsersWhere(UUID scopeID, string where);
53 } 54 }
54} 55}
diff --git a/OpenSim/Data/MSSQL/MSSQLAssetData.cs b/OpenSim/Data/MSSQL/MSSQLAssetData.cs
index c7488d8..c882555 100644
--- a/OpenSim/Data/MSSQL/MSSQLAssetData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLAssetData.cs
@@ -143,7 +143,7 @@ namespace OpenSim.Data.MSSQL
143 /// Create asset in m_database 143 /// Create asset in m_database
144 /// </summary> 144 /// </summary>
145 /// <param name="asset">the asset</param> 145 /// <param name="asset">the asset</param>
146 override public void StoreAsset(AssetBase asset) 146 override public bool StoreAsset(AssetBase asset)
147 { 147 {
148 148
149 string sql = 149 string sql =
@@ -192,10 +192,12 @@ namespace OpenSim.Data.MSSQL
192 try 192 try
193 { 193 {
194 command.ExecuteNonQuery(); 194 command.ExecuteNonQuery();
195 return true;
195 } 196 }
196 catch(Exception e) 197 catch(Exception e)
197 { 198 {
198 m_log.Error("[ASSET DB]: Error storing item :" + e.Message); 199 m_log.Error("[ASSET DB]: Error storing item :" + e.Message);
200 return false;
199 } 201 }
200 } 202 }
201 } 203 }
diff --git a/OpenSim/Data/MSSQL/MSSQLAvatarData.cs b/OpenSim/Data/MSSQL/MSSQLAvatarData.cs
index 301b424..49a6b09 100644
--- a/OpenSim/Data/MSSQL/MSSQLAvatarData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLAvatarData.cs
@@ -43,7 +43,7 @@ namespace OpenSim.Data.MSSQL
43 public class MSSQLAvatarData : MSSQLGenericTableHandler<AvatarBaseData>, 43 public class MSSQLAvatarData : MSSQLGenericTableHandler<AvatarBaseData>,
44 IAvatarData 44 IAvatarData
45 { 45 {
46// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 47
48 public MSSQLAvatarData(string connectionString, string realm) : 48 public MSSQLAvatarData(string connectionString, string realm) :
49 base(connectionString, realm, "Avatar") 49 base(connectionString, realm, "Avatar")
diff --git a/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs b/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs
index 4145d95..8f471c4 100644
--- a/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs
+++ b/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs
@@ -40,8 +40,8 @@ namespace OpenSim.Data.MSSQL
40{ 40{
41 public class MSSQLGenericTableHandler<T> where T : class, new() 41 public class MSSQLGenericTableHandler<T> where T : class, new()
42 { 42 {
43// private static readonly ILog m_log = 43 private static readonly ILog m_log =
44// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45 45
46 protected string m_ConnectionString; 46 protected string m_ConnectionString;
47 protected MSSQLManager m_database; //used for parameter type translation 47 protected MSSQLManager m_database; //used for parameter type translation
diff --git a/OpenSim/Data/MSSQL/MSSQLGridUserData.cs b/OpenSim/Data/MSSQL/MSSQLGridUserData.cs
index 9e215f9..1870273 100644
--- a/OpenSim/Data/MSSQL/MSSQLGridUserData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLGridUserData.cs
@@ -43,7 +43,7 @@ namespace OpenSim.Data.MSSQL
43 public class MSSQLGridUserData : MSSQLGenericTableHandler<GridUserData>, 43 public class MSSQLGridUserData : MSSQLGenericTableHandler<GridUserData>,
44 IGridUserData 44 IGridUserData
45 { 45 {
46// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 47
48 public MSSQLGridUserData(string connectionString, string realm) : 48 public MSSQLGridUserData(string connectionString, string realm) :
49 base(connectionString, realm, "GridUserStore") 49 base(connectionString, realm, "GridUserStore")
diff --git a/OpenSim/Data/MSSQL/MSSQLManager.cs b/OpenSim/Data/MSSQL/MSSQLManager.cs
index cf963e3..575fd21 100644
--- a/OpenSim/Data/MSSQL/MSSQLManager.cs
+++ b/OpenSim/Data/MSSQL/MSSQLManager.cs
@@ -41,7 +41,7 @@ namespace OpenSim.Data.MSSQL
41 /// </summary> 41 /// </summary>
42 public class MSSQLManager 42 public class MSSQLManager
43 { 43 {
44// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45 45
46 /// <summary> 46 /// <summary>
47 /// Connection string for ADO.net 47 /// Connection string for ADO.net
@@ -180,6 +180,8 @@ namespace OpenSim.Data.MSSQL
180 return parameter; 180 return parameter;
181 } 181 }
182 182
183 private static readonly Dictionary<string, string> emptyDictionary = new Dictionary<string, string>();
184
183 /// <summary> 185 /// <summary>
184 /// Checks if we need to do some migrations to the database 186 /// Checks if we need to do some migrations to the database
185 /// </summary> 187 /// </summary>
diff --git a/OpenSim/Data/MSSQL/MSSQLPresenceData.cs b/OpenSim/Data/MSSQL/MSSQLPresenceData.cs
index 8068d23..e7b3d9c 100644
--- a/OpenSim/Data/MSSQL/MSSQLPresenceData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLPresenceData.cs
@@ -43,7 +43,7 @@ namespace OpenSim.Data.MSSQL
43 public class MSSQLPresenceData : MSSQLGenericTableHandler<PresenceData>, 43 public class MSSQLPresenceData : MSSQLGenericTableHandler<PresenceData>,
44 IPresenceData 44 IPresenceData
45 { 45 {
46// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 47
48 public MSSQLPresenceData(string connectionString, string realm) : 48 public MSSQLPresenceData(string connectionString, string realm) :
49 base(connectionString, realm, "Presence") 49 base(connectionString, realm, "Presence")
diff --git a/OpenSim/Data/MSSQL/MSSQLUserAccountData.cs b/OpenSim/Data/MSSQL/MSSQLUserAccountData.cs
index 7feec91..dd0689c 100644
--- a/OpenSim/Data/MSSQL/MSSQLUserAccountData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLUserAccountData.cs
@@ -242,5 +242,10 @@ namespace OpenSim.Data.MSSQL
242 return DoQuery(cmd); 242 return DoQuery(cmd);
243 } 243 }
244 } 244 }
245
246 public UserAccountData[] GetUsersWhere(UUID scopeID, string where)
247 {
248 return null;
249 }
245 } 250 }
246} 251}
diff --git a/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs b/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs
index b19a0da..a1069c6 100644
--- a/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs
@@ -40,8 +40,8 @@ namespace OpenSim.Data.MSSQL
40{ 40{
41 public class MSSQLXInventoryData : IXInventoryData 41 public class MSSQLXInventoryData : IXInventoryData
42 { 42 {
43// private static readonly ILog m_log = LogManager.GetLogger( 43 private static readonly ILog m_log = LogManager.GetLogger(
44// MethodBase.GetCurrentMethod().DeclaringType); 44 MethodBase.GetCurrentMethod().DeclaringType);
45 45
46 private MSSQLGenericTableHandler<XInventoryFolder> m_Folders; 46 private MSSQLGenericTableHandler<XInventoryFolder> m_Folders;
47 private MSSQLItemHandler m_Items; 47 private MSSQLItemHandler m_Items;
diff --git a/OpenSim/Data/MySQL/MySQLAssetData.cs b/OpenSim/Data/MySQL/MySQLAssetData.cs
index a743479..a22dc0a 100644
--- a/OpenSim/Data/MySQL/MySQLAssetData.cs
+++ b/OpenSim/Data/MySQL/MySQLAssetData.cs
@@ -155,7 +155,7 @@ namespace OpenSim.Data.MySQL
155 /// </summary> 155 /// </summary>
156 /// <param name="asset">Asset UUID to create</param> 156 /// <param name="asset">Asset UUID to create</param>
157 /// <remarks>On failure : Throw an exception and attempt to reconnect to database</remarks> 157 /// <remarks>On failure : Throw an exception and attempt to reconnect to database</remarks>
158 override public void StoreAsset(AssetBase asset) 158 override public bool StoreAsset(AssetBase asset)
159 { 159 {
160 lock (m_dbLock) 160 lock (m_dbLock)
161 { 161 {
@@ -203,12 +203,14 @@ namespace OpenSim.Data.MySQL
203 cmd.Parameters.AddWithValue("?data", asset.Data); 203 cmd.Parameters.AddWithValue("?data", asset.Data);
204 cmd.ExecuteNonQuery(); 204 cmd.ExecuteNonQuery();
205 cmd.Dispose(); 205 cmd.Dispose();
206 return true;
206 } 207 }
207 } 208 }
208 catch (Exception e) 209 catch (Exception e)
209 { 210 {
210 m_log.ErrorFormat("[ASSET DB]: MySQL failure creating asset {0} with name \"{1}\". Error: {2}", 211 m_log.ErrorFormat("[ASSET DB]: MySQL failure creating asset {0} with name \"{1}\". Error: {2}",
211 asset.FullID, asset.Name, e.Message); 212 asset.FullID, asset.Name, e.Message);
213 return false;
212 } 214 }
213 } 215 }
214 } 216 }
diff --git a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs
index 754cf72..786b955 100644
--- a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs
+++ b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs
@@ -173,6 +173,11 @@ namespace OpenSim.Data.MySQL
173 int v = Convert.ToInt32(reader[name]); 173 int v = Convert.ToInt32(reader[name]);
174 m_Fields[name].SetValue(row, v); 174 m_Fields[name].SetValue(row, v);
175 } 175 }
176 else if (m_Fields[name].FieldType == typeof(uint))
177 {
178 uint v = Convert.ToUInt32(reader[name]);
179 m_Fields[name].SetValue(row, v);
180 }
176 else 181 else
177 { 182 {
178 m_Fields[name].SetValue(row, reader[name]); 183 m_Fields[name].SetValue(row, reader[name]);
@@ -294,4 +299,4 @@ namespace OpenSim.Data.MySQL
294 } 299 }
295 } 300 }
296 } 301 }
297} \ No newline at end of file 302}
diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs
index 3123edf..d459e08 100644
--- a/OpenSim/Data/MySQL/MySQLSimulationData.cs
+++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs
@@ -66,7 +66,7 @@ namespace OpenSim.Data.MySQL
66 Initialise(connectionString); 66 Initialise(connectionString);
67 } 67 }
68 68
69 public void Initialise(string connectionString) 69 public virtual void Initialise(string connectionString)
70 { 70 {
71 m_connectionString = connectionString; 71 m_connectionString = connectionString;
72 72
@@ -113,7 +113,7 @@ namespace OpenSim.Data.MySQL
113 113
114 public void Dispose() {} 114 public void Dispose() {}
115 115
116 public void StoreObject(SceneObjectGroup obj, UUID regionUUID) 116 public virtual void StoreObject(SceneObjectGroup obj, UUID regionUUID)
117 { 117 {
118 uint flags = obj.RootPart.GetEffectiveObjectFlags(); 118 uint flags = obj.RootPart.GetEffectiveObjectFlags();
119 119
@@ -241,7 +241,7 @@ namespace OpenSim.Data.MySQL
241 } 241 }
242 } 242 }
243 243
244 public void RemoveObject(UUID obj, UUID regionUUID) 244 public virtual void RemoveObject(UUID obj, UUID regionUUID)
245 { 245 {
246// m_log.DebugFormat("[REGION DB]: Deleting scene object {0} from {1} in database", obj, regionUUID); 246// m_log.DebugFormat("[REGION DB]: Deleting scene object {0} from {1} in database", obj, regionUUID);
247 247
@@ -390,7 +390,7 @@ namespace OpenSim.Data.MySQL
390 } 390 }
391 } 391 }
392 392
393 public List<SceneObjectGroup> LoadObjects(UUID regionID) 393 public virtual List<SceneObjectGroup> LoadObjects(UUID regionID)
394 { 394 {
395 const int ROWS_PER_QUERY = 5000; 395 const int ROWS_PER_QUERY = 5000;
396 396
@@ -559,36 +559,51 @@ namespace OpenSim.Data.MySQL
559 } 559 }
560 } 560 }
561 561
562 public void StoreTerrain(double[,] ter, UUID regionID) 562 public virtual void StoreTerrain(double[,] ter, UUID regionID)
563 { 563 {
564 m_log.Info("[REGION DB]: Storing terrain"); 564 Util.FireAndForget(delegate(object x)
565
566 lock (m_dbLock)
567 { 565 {
568 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 566 double[,] oldTerrain = LoadTerrain(regionID);
569 {
570 dbcon.Open();
571 567
572 using (MySqlCommand cmd = dbcon.CreateCommand()) 568 m_log.Info("[REGION DB]: Storing terrain");
569
570 lock (m_dbLock)
571 {
572 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
573 { 573 {
574 cmd.CommandText = "delete from terrain where RegionUUID = ?RegionUUID"; 574 dbcon.Open();
575 cmd.Parameters.AddWithValue("RegionUUID", regionID.ToString());
576 575
577 ExecuteNonQuery(cmd); 576 using (MySqlCommand cmd = dbcon.CreateCommand())
577 {
578 cmd.CommandText = "delete from terrain where RegionUUID = ?RegionUUID";
579 cmd.Parameters.AddWithValue("RegionUUID", regionID.ToString());
578 580
579 cmd.CommandText = "insert into terrain (RegionUUID, " + 581 using (MySqlCommand cmd2 = dbcon.CreateCommand())
580 "Revision, Heightfield) values (?RegionUUID, " + 582 {
581 "1, ?Heightfield)"; 583 try
584 {
585 cmd2.CommandText = "insert into terrain (RegionUUID, " +
586 "Revision, Heightfield) values (?RegionUUID, " +
587 "1, ?Heightfield)";
582 588
583 cmd.Parameters.AddWithValue("Heightfield", SerializeTerrain(ter)); 589 cmd2.Parameters.AddWithValue("RegionUUID", regionID.ToString());
590 cmd2.Parameters.AddWithValue("Heightfield", SerializeTerrain(ter, oldTerrain));
584 591
585 ExecuteNonQuery(cmd); 592 ExecuteNonQuery(cmd);
593 ExecuteNonQuery(cmd2);
594 }
595 catch (Exception e)
596 {
597 m_log.ErrorFormat(e.ToString());
598 }
599 }
600 }
586 } 601 }
587 } 602 }
588 } 603 });
589 } 604 }
590 605
591 public double[,] LoadTerrain(UUID regionID) 606 public virtual double[,] LoadTerrain(UUID regionID)
592 { 607 {
593 double[,] terrain = null; 608 double[,] terrain = null;
594 609
@@ -638,7 +653,7 @@ namespace OpenSim.Data.MySQL
638 return terrain; 653 return terrain;
639 } 654 }
640 655
641 public void RemoveLandObject(UUID globalID) 656 public virtual void RemoveLandObject(UUID globalID)
642 { 657 {
643 lock (m_dbLock) 658 lock (m_dbLock)
644 { 659 {
@@ -657,7 +672,7 @@ namespace OpenSim.Data.MySQL
657 } 672 }
658 } 673 }
659 674
660 public void StoreLandObject(ILandObject parcel) 675 public virtual void StoreLandObject(ILandObject parcel)
661 { 676 {
662 lock (m_dbLock) 677 lock (m_dbLock)
663 { 678 {
@@ -714,7 +729,7 @@ namespace OpenSim.Data.MySQL
714 } 729 }
715 } 730 }
716 731
717 public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID) 732 public virtual RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID)
718 { 733 {
719 RegionLightShareData nWP = new RegionLightShareData(); 734 RegionLightShareData nWP = new RegionLightShareData();
720 nWP.OnSave += StoreRegionWindlightSettings; 735 nWP.OnSave += StoreRegionWindlightSettings;
@@ -736,7 +751,7 @@ namespace OpenSim.Data.MySQL
736 { 751 {
737 //No result, so store our default windlight profile and return it 752 //No result, so store our default windlight profile and return it
738 nWP.regionID = regionUUID; 753 nWP.regionID = regionUUID;
739 StoreRegionWindlightSettings(nWP); 754 // StoreRegionWindlightSettings(nWP);
740 return nWP; 755 return nWP;
741 } 756 }
742 else 757 else
@@ -811,7 +826,7 @@ namespace OpenSim.Data.MySQL
811 return nWP; 826 return nWP;
812 } 827 }
813 828
814 public RegionSettings LoadRegionSettings(UUID regionUUID) 829 public virtual RegionSettings LoadRegionSettings(UUID regionUUID)
815 { 830 {
816 RegionSettings rs = null; 831 RegionSettings rs = null;
817 832
@@ -851,7 +866,7 @@ namespace OpenSim.Data.MySQL
851 return rs; 866 return rs;
852 } 867 }
853 868
854 public void StoreRegionWindlightSettings(RegionLightShareData wl) 869 public virtual void StoreRegionWindlightSettings(RegionLightShareData wl)
855 { 870 {
856 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 871 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
857 { 872 {
@@ -954,7 +969,7 @@ namespace OpenSim.Data.MySQL
954 } 969 }
955 } 970 }
956 971
957 public void RemoveRegionWindlightSettings(UUID regionID) 972 public virtual void RemoveRegionWindlightSettings(UUID regionID)
958 { 973 {
959 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 974 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
960 { 975 {
@@ -969,7 +984,7 @@ namespace OpenSim.Data.MySQL
969 } 984 }
970 } 985 }
971 986
972 public void StoreRegionSettings(RegionSettings rs) 987 public virtual void StoreRegionSettings(RegionSettings rs)
973 { 988 {
974 lock (m_dbLock) 989 lock (m_dbLock)
975 { 990 {
@@ -996,7 +1011,7 @@ namespace OpenSim.Data.MySQL
996 "use_estate_sun, fixed_sun, sun_position, " + 1011 "use_estate_sun, fixed_sun, sun_position, " +
997 "covenant, Sandbox, sunvectorx, sunvectory, " + 1012 "covenant, Sandbox, sunvectorx, sunvectory, " +
998 "sunvectorz, loaded_creation_datetime, " + 1013 "sunvectorz, loaded_creation_datetime, " +
999 "loaded_creation_id, map_tile_ID, " + 1014 "loaded_creation_id, map_tile_ID, block_search, casino, " +
1000 "TelehubObject, parcel_tile_ID) " + 1015 "TelehubObject, parcel_tile_ID) " +
1001 "values (?RegionUUID, ?BlockTerraform, " + 1016 "values (?RegionUUID, ?BlockTerraform, " +
1002 "?BlockFly, ?AllowDamage, ?RestrictPushing, " + 1017 "?BlockFly, ?AllowDamage, ?RestrictPushing, " +
@@ -1013,7 +1028,8 @@ namespace OpenSim.Data.MySQL
1013 "?SunPosition, ?Covenant, ?Sandbox, " + 1028 "?SunPosition, ?Covenant, ?Sandbox, " +
1014 "?SunVectorX, ?SunVectorY, ?SunVectorZ, " + 1029 "?SunVectorX, ?SunVectorY, ?SunVectorZ, " +
1015 "?LoadedCreationDateTime, ?LoadedCreationID, " + 1030 "?LoadedCreationDateTime, ?LoadedCreationID, " +
1016 "?TerrainImageID, ?TelehubObject, ?ParcelImageID) "; 1031 "?TerrainImageID, ?block_search, ?casino, " +
1032 "?TelehubObject, ?ParcelImageID)";
1017 1033
1018 FillRegionSettingsCommand(cmd, rs); 1034 FillRegionSettingsCommand(cmd, rs);
1019 1035
@@ -1024,7 +1040,7 @@ namespace OpenSim.Data.MySQL
1024 SaveSpawnPoints(rs); 1040 SaveSpawnPoints(rs);
1025 } 1041 }
1026 1042
1027 public List<LandData> LoadLandObjects(UUID regionUUID) 1043 public virtual List<LandData> LoadLandObjects(UUID regionUUID)
1028 { 1044 {
1029 List<LandData> landData = new List<LandData>(); 1045 List<LandData> landData = new List<LandData>();
1030 1046
@@ -1304,6 +1320,9 @@ namespace OpenSim.Data.MySQL
1304 newSettings.ParcelImageID = DBGuid.FromDB(row["parcel_tile_ID"]); 1320 newSettings.ParcelImageID = DBGuid.FromDB(row["parcel_tile_ID"]);
1305 newSettings.TelehubObject = DBGuid.FromDB(row["TelehubObject"]); 1321 newSettings.TelehubObject = DBGuid.FromDB(row["TelehubObject"]);
1306 1322
1323 newSettings.GodBlockSearch = Convert.ToBoolean(row["block_search"]);
1324 newSettings.Casino = Convert.ToBoolean(row["casino"]);
1325
1307 return newSettings; 1326 return newSettings;
1308 } 1327 }
1309 1328
@@ -1401,7 +1420,7 @@ namespace OpenSim.Data.MySQL
1401 /// </summary> 1420 /// </summary>
1402 /// <param name="val"></param> 1421 /// <param name="val"></param>
1403 /// <returns></returns> 1422 /// <returns></returns>
1404 private static Array SerializeTerrain(double[,] val) 1423 private static Array SerializeTerrain(double[,] val, double[,] oldTerrain)
1405 { 1424 {
1406 MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize) *sizeof (double)); 1425 MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize) *sizeof (double));
1407 BinaryWriter bw = new BinaryWriter(str); 1426 BinaryWriter bw = new BinaryWriter(str);
@@ -1410,7 +1429,11 @@ namespace OpenSim.Data.MySQL
1410 for (int x = 0; x < (int)Constants.RegionSize; x++) 1429 for (int x = 0; x < (int)Constants.RegionSize; x++)
1411 for (int y = 0; y < (int)Constants.RegionSize; y++) 1430 for (int y = 0; y < (int)Constants.RegionSize; y++)
1412 { 1431 {
1413 double height = val[x, y]; 1432 double height = 20.0;
1433 if (oldTerrain != null)
1434 height = oldTerrain[x, y];
1435 if (!double.IsNaN(val[x, y]))
1436 height = val[x, y];
1414 if (height == 0.0) 1437 if (height == 0.0)
1415 height = double.Epsilon; 1438 height = double.Epsilon;
1416 1439
@@ -1633,6 +1656,9 @@ namespace OpenSim.Data.MySQL
1633 cmd.Parameters.AddWithValue("LoadedCreationDateTime", settings.LoadedCreationDateTime); 1656 cmd.Parameters.AddWithValue("LoadedCreationDateTime", settings.LoadedCreationDateTime);
1634 cmd.Parameters.AddWithValue("LoadedCreationID", settings.LoadedCreationID); 1657 cmd.Parameters.AddWithValue("LoadedCreationID", settings.LoadedCreationID);
1635 cmd.Parameters.AddWithValue("TerrainImageID", settings.TerrainImageID); 1658 cmd.Parameters.AddWithValue("TerrainImageID", settings.TerrainImageID);
1659 cmd.Parameters.AddWithValue("block_search", settings.GodBlockSearch);
1660 cmd.Parameters.AddWithValue("casino", settings.Casino);
1661
1636 cmd.Parameters.AddWithValue("ParcelImageID", settings.ParcelImageID); 1662 cmd.Parameters.AddWithValue("ParcelImageID", settings.ParcelImageID);
1637 cmd.Parameters.AddWithValue("TelehubObject", settings.TelehubObject); 1663 cmd.Parameters.AddWithValue("TelehubObject", settings.TelehubObject);
1638 } 1664 }
@@ -1792,7 +1818,7 @@ namespace OpenSim.Data.MySQL
1792 cmd.Parameters.AddWithValue("Media", null == s.Media ? null : s.Media.ToXml()); 1818 cmd.Parameters.AddWithValue("Media", null == s.Media ? null : s.Media.ToXml());
1793 } 1819 }
1794 1820
1795 public void StorePrimInventory(UUID primID, ICollection<TaskInventoryItem> items) 1821 public virtual void StorePrimInventory(UUID primID, ICollection<TaskInventoryItem> items)
1796 { 1822 {
1797 lock (m_dbLock) 1823 lock (m_dbLock)
1798 { 1824 {
diff --git a/OpenSim/Data/MySQL/MySQLUserAccountData.cs b/OpenSim/Data/MySQL/MySQLUserAccountData.cs
index aa69d68..a18ac66 100644
--- a/OpenSim/Data/MySQL/MySQLUserAccountData.cs
+++ b/OpenSim/Data/MySQL/MySQLUserAccountData.cs
@@ -46,17 +46,21 @@ namespace OpenSim.Data.MySQL
46 { 46 {
47 string[] words = query.Split(new char[] {' '}); 47 string[] words = query.Split(new char[] {' '});
48 48
49 bool valid = false;
50
49 for (int i = 0 ; i < words.Length ; i++) 51 for (int i = 0 ; i < words.Length ; i++)
50 { 52 {
51 if (words[i].Length < 3) 53 if (words[i].Length > 2)
52 { 54 valid = true;
53 if (i != words.Length - 1) 55// if (words[i].Length < 3)
54 Array.Copy(words, i + 1, words, i, words.Length - i - 1); 56// {
55 Array.Resize(ref words, words.Length - 1); 57// if (i != words.Length - 1)
56 } 58// Array.Copy(words, i + 1, words, i, words.Length - i - 1);
59// Array.Resize(ref words, words.Length - 1);
60// }
57 } 61 }
58 62
59 if (words.Length == 0) 63 if ((!valid) || words.Length == 0)
60 return new UserAccountData[0]; 64 return new UserAccountData[0];
61 65
62 if (words.Length > 2) 66 if (words.Length > 2)
@@ -66,18 +70,33 @@ namespace OpenSim.Data.MySQL
66 70
67 if (words.Length == 1) 71 if (words.Length == 1)
68 { 72 {
69 cmd.CommandText = String.Format("select * from {0} where (ScopeID=?ScopeID or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like ?search or LastName like ?search)", m_Realm); 73 cmd.CommandText = String.Format("select * from {0} where (ScopeID=?ScopeID or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like ?search or LastName like ?search) and active=1", m_Realm);
70 cmd.Parameters.AddWithValue("?search", "%" + words[0] + "%"); 74 cmd.Parameters.AddWithValue("?search", words[0] + "%");
71 cmd.Parameters.AddWithValue("?ScopeID", scopeID.ToString()); 75 cmd.Parameters.AddWithValue("?ScopeID", scopeID.ToString());
72 } 76 }
73 else 77 else
74 { 78 {
75 cmd.CommandText = String.Format("select * from {0} where (ScopeID=?ScopeID or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like ?searchFirst or LastName like ?searchLast)", m_Realm); 79 cmd.CommandText = String.Format("select * from {0} where (ScopeID=?ScopeID or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like ?searchFirst and LastName like ?searchLast) and active=1", m_Realm);
76 cmd.Parameters.AddWithValue("?searchFirst", "%" + words[0] + "%"); 80 cmd.Parameters.AddWithValue("?searchFirst", words[0] + "%");
77 cmd.Parameters.AddWithValue("?searchLast", "%" + words[1] + "%"); 81 cmd.Parameters.AddWithValue("?searchLast", words[1] + "%");
82 cmd.Parameters.AddWithValue("?ScopeID", scopeID.ToString());
83 }
84
85 return DoQuery(cmd);
86 }
87
88 public UserAccountData[] GetUsersWhere(UUID scopeID, string where)
89 {
90 MySqlCommand cmd = new MySqlCommand();
91
92 if (scopeID != UUID.Zero)
93 {
94 where = "(ScopeID=?ScopeID or ScopeID='00000000-0000-0000-0000-000000000000') and (" + where + ")";
78 cmd.Parameters.AddWithValue("?ScopeID", scopeID.ToString()); 95 cmd.Parameters.AddWithValue("?ScopeID", scopeID.ToString());
79 } 96 }
80 97
98 cmd.CommandText = String.Format("select * from {0} where " + where, m_Realm);
99
81 return DoQuery(cmd); 100 return DoQuery(cmd);
82 } 101 }
83 } 102 }
diff --git a/OpenSim/Data/MySQL/Resources/RegionStore.migrations b/OpenSim/Data/MySQL/Resources/RegionStore.migrations
index f9b5737..dae704c 100644
--- a/OpenSim/Data/MySQL/Resources/RegionStore.migrations
+++ b/OpenSim/Data/MySQL/Resources/RegionStore.migrations
@@ -717,7 +717,7 @@ ALTER TABLE regionsettings ADD COLUMN loaded_creation_datetime int unsigned NOT
717 717
718COMMIT; 718COMMIT;
719 719
720:VERSION 32 720:VERSION 32 #---------------------
721 721
722BEGIN; 722BEGIN;
723CREATE TABLE `regionwindlight` ( 723CREATE TABLE `regionwindlight` (
diff --git a/OpenSim/Data/Null/NullUserAccountData.cs b/OpenSim/Data/Null/NullUserAccountData.cs
index ec54dba..241616b 100644
--- a/OpenSim/Data/Null/NullUserAccountData.cs
+++ b/OpenSim/Data/Null/NullUserAccountData.cs
@@ -193,5 +193,10 @@ namespace OpenSim.Data.Null
193 193
194 return false; 194 return false;
195 } 195 }
196
197 public UserAccountData[] GetUsersWhere(UUID scopeID, string where)
198 {
199 return null;
200 }
196 } 201 }
197} 202}
diff --git a/OpenSim/Data/SQLite/SQLiteAssetData.cs b/OpenSim/Data/SQLite/SQLiteAssetData.cs
index bb23fc1..723544a 100644
--- a/OpenSim/Data/SQLite/SQLiteAssetData.cs
+++ b/OpenSim/Data/SQLite/SQLiteAssetData.cs
@@ -128,7 +128,7 @@ namespace OpenSim.Data.SQLite
128 /// Create an asset 128 /// Create an asset
129 /// </summary> 129 /// </summary>
130 /// <param name="asset">Asset Base</param> 130 /// <param name="asset">Asset Base</param>
131 override public void StoreAsset(AssetBase asset) 131 override public bool StoreAsset(AssetBase asset)
132 { 132 {
133 //m_log.Info("[ASSET DB]: Creating Asset " + asset.FullID.ToString()); 133 //m_log.Info("[ASSET DB]: Creating Asset " + asset.FullID.ToString());
134 if (ExistsAsset(asset.FullID)) 134 if (ExistsAsset(asset.FullID))
@@ -150,6 +150,7 @@ namespace OpenSim.Data.SQLite
150 cmd.Parameters.Add(new SqliteParameter(":Data", asset.Data)); 150 cmd.Parameters.Add(new SqliteParameter(":Data", asset.Data));
151 151
152 cmd.ExecuteNonQuery(); 152 cmd.ExecuteNonQuery();
153 return true;
153 } 154 }
154 } 155 }
155 } 156 }
@@ -170,6 +171,7 @@ namespace OpenSim.Data.SQLite
170 cmd.Parameters.Add(new SqliteParameter(":Data", asset.Data)); 171 cmd.Parameters.Add(new SqliteParameter(":Data", asset.Data));
171 172
172 cmd.ExecuteNonQuery(); 173 cmd.ExecuteNonQuery();
174 return true;
173 } 175 }
174 } 176 }
175 } 177 }
diff --git a/OpenSim/Data/SQLite/SQLiteUserAccountData.cs b/OpenSim/Data/SQLite/SQLiteUserAccountData.cs
index 7a5de50..4d580c0 100644
--- a/OpenSim/Data/SQLite/SQLiteUserAccountData.cs
+++ b/OpenSim/Data/SQLite/SQLiteUserAccountData.cs
@@ -81,5 +81,10 @@ namespace OpenSim.Data.SQLite
81 81
82 return DoQuery(cmd); 82 return DoQuery(cmd);
83 } 83 }
84
85 public UserAccountData[] GetUsersWhere(UUID scopeID, string where)
86 {
87 return null;
88 }
84 } 89 }
85} 90}
diff --git a/OpenSim/Framework/AssetBase.cs b/OpenSim/Framework/AssetBase.cs
index d2c6c57..ff240be 100644
--- a/OpenSim/Framework/AssetBase.cs
+++ b/OpenSim/Framework/AssetBase.cs
@@ -60,6 +60,8 @@ namespace OpenSim.Framework
60 /// </summary> 60 /// </summary>
61 private AssetMetadata m_metadata; 61 private AssetMetadata m_metadata;
62 62
63 private int m_uploadAttempts;
64
63 // This is needed for .NET serialization!!! 65 // This is needed for .NET serialization!!!
64 // Do NOT "Optimize" away! 66 // Do NOT "Optimize" away!
65 public AssetBase() 67 public AssetBase()
@@ -198,6 +200,12 @@ namespace OpenSim.Framework
198 set { m_metadata.Type = value; } 200 set { m_metadata.Type = value; }
199 } 201 }
200 202
203 public int UploadAttempts
204 {
205 get { return m_uploadAttempts; }
206 set { m_uploadAttempts = value; }
207 }
208
201 /// <summary> 209 /// <summary>
202 /// Is this a region only asset, or does this exist on the asset server also 210 /// Is this a region only asset, or does this exist on the asset server also
203 /// </summary> 211 /// </summary>
diff --git a/OpenSim/Framework/AvatarAppearance.cs b/OpenSim/Framework/AvatarAppearance.cs
index 4f598b0..3a0b861 100644
--- a/OpenSim/Framework/AvatarAppearance.cs
+++ b/OpenSim/Framework/AvatarAppearance.cs
@@ -240,6 +240,21 @@ namespace OpenSim.Framework
240// } 240// }
241 } 241 }
242 242
243 /// <summary>
244 /// Invalidate all of the baked textures in the appearance, useful
245 /// if you know that none are valid
246 /// </summary>
247 public virtual void ResetBakedTextures()
248 {
249 SetDefaultTexture();
250
251 //for (int i = 0; i < BAKE_INDICES.Length; i++)
252 // {
253 // int idx = BAKE_INDICES[i];
254 // m_texture.FaceTextures[idx].TextureID = UUID.Zero;
255 // }
256 }
257
243 protected virtual void SetDefaultTexture() 258 protected virtual void SetDefaultTexture()
244 { 259 {
245 m_texture = new Primitive.TextureEntry(new UUID(AppearanceManager.DEFAULT_AVATAR_TEXTURE)); 260 m_texture = new Primitive.TextureEntry(new UUID(AppearanceManager.DEFAULT_AVATAR_TEXTURE));
@@ -390,19 +405,18 @@ namespace OpenSim.Framework
390 /// </remarks> 405 /// </remarks>
391 public List<AvatarAttachment> GetAttachments() 406 public List<AvatarAttachment> GetAttachments()
392 { 407 {
393 List<AvatarAttachment> alist = new List<AvatarAttachment>(); 408
394 409
395 lock (m_attachments) 410 lock (m_attachments)
396 { 411 {
412 List<AvatarAttachment> alist = new List<AvatarAttachment>();
397 foreach (KeyValuePair<int, List<AvatarAttachment>> kvp in m_attachments) 413 foreach (KeyValuePair<int, List<AvatarAttachment>> kvp in m_attachments)
398 { 414 {
399 foreach (AvatarAttachment attach in kvp.Value) 415 foreach (AvatarAttachment attach in kvp.Value)
400 alist.Add(new AvatarAttachment(attach)); 416 alist.Add(new AvatarAttachment(attach));
401 } 417 }
402 } 418 return alist;
403 419 } }
404 return alist;
405 }
406 420
407 internal void AppendAttachment(AvatarAttachment attach) 421 internal void AppendAttachment(AvatarAttachment attach)
408 { 422 {
@@ -531,7 +545,6 @@ namespace OpenSim.Framework
531 return kvp.Key; 545 return kvp.Key;
532 } 546 }
533 } 547 }
534
535 return 0; 548 return 0;
536 } 549 }
537 550
@@ -598,12 +611,14 @@ namespace OpenSim.Framework
598 OSDBinary visualparams = new OSDBinary(m_visualparams); 611 OSDBinary visualparams = new OSDBinary(m_visualparams);
599 data["visualparams"] = visualparams; 612 data["visualparams"] = visualparams;
600 613
601 // Attachments 614 lock (m_attachments)
602 List<AvatarAttachment> attachments = GetAttachments(); 615 {
603 OSDArray attachs = new OSDArray(attachments.Count); 616 // Attachments
604 foreach (AvatarAttachment attach in GetAttachments()) 617 OSDArray attachs = new OSDArray(m_attachments.Count);
605 attachs.Add(attach.Pack()); 618 foreach (AvatarAttachment attach in GetAttachments())
606 data["attachments"] = attachs; 619 attachs.Add(attach.Pack());
620 data["attachments"] = attachs;
621 }
607 622
608 return data; 623 return data;
609 } 624 }
diff --git a/OpenSim/Framework/Communications/RestClient.cs b/OpenSim/Framework/Communications/RestClient.cs
index 97b3b60..42c0b18 100644
--- a/OpenSim/Framework/Communications/RestClient.cs
+++ b/OpenSim/Framework/Communications/RestClient.cs
@@ -363,7 +363,7 @@ namespace OpenSim.Framework.Communications
363 _request = (HttpWebRequest) WebRequest.Create(buildUri()); 363 _request = (HttpWebRequest) WebRequest.Create(buildUri());
364 _request.KeepAlive = false; 364 _request.KeepAlive = false;
365 _request.ContentType = "application/xml"; 365 _request.ContentType = "application/xml";
366 _request.Timeout = 900000; 366 _request.Timeout = 30000;
367 _request.Method = RequestMethod; 367 _request.Method = RequestMethod;
368 _asyncException = null; 368 _asyncException = null;
369 _request.ContentLength = src.Length; 369 _request.ContentLength = src.Length;
diff --git a/OpenSim/Framework/EstateSettings.cs b/OpenSim/Framework/EstateSettings.cs
index 98604f2..142b783 100644
--- a/OpenSim/Framework/EstateSettings.cs
+++ b/OpenSim/Framework/EstateSettings.cs
@@ -58,6 +58,30 @@ namespace OpenSim.Framework
58 set { m_EstateName = value; } 58 set { m_EstateName = value; }
59 } 59 }
60 60
61 private bool m_AllowLandmark = true;
62
63 public bool AllowLandmark
64 {
65 get { return m_AllowLandmark; }
66 set { m_AllowLandmark = value; }
67 }
68
69 private bool m_AllowParcelChanges = true;
70
71 public bool AllowParcelChanges
72 {
73 get { return m_AllowParcelChanges; }
74 set { m_AllowParcelChanges = value; }
75 }
76
77 private bool m_AllowSetHome = true;
78
79 public bool AllowSetHome
80 {
81 get { return m_AllowSetHome; }
82 set { m_AllowSetHome = value; }
83 }
84
61 private uint m_ParentEstateID = 1; 85 private uint m_ParentEstateID = 1;
62 86
63 public uint ParentEstateID 87 public uint ParentEstateID
@@ -338,11 +362,30 @@ namespace OpenSim.Framework
338 return false; 362 return false;
339 } 363 }
340 364
341 public bool IsBanned(UUID avatarID) 365 public bool IsBanned(UUID avatarID, int userFlags)
342 { 366 {
343 foreach (EstateBan ban in l_EstateBans) 367 foreach (EstateBan ban in l_EstateBans)
344 if (ban.BannedUserID == avatarID) 368 if (ban.BannedUserID == avatarID)
345 return true; 369 return true;
370
371 if (!IsEstateManager(avatarID) && !HasAccess(avatarID))
372 {
373 if (DenyMinors)
374 {
375 if ((userFlags & 32) == 0)
376 {
377 return true;
378 }
379 }
380 if (DenyAnonymous)
381 {
382 if ((userFlags & 4) == 0)
383 {
384 return true;
385 }
386 }
387 }
388
346 return false; 389 return false;
347 } 390 }
348 391
@@ -350,7 +393,7 @@ namespace OpenSim.Framework
350 { 393 {
351 if (ban == null) 394 if (ban == null)
352 return; 395 return;
353 if (!IsBanned(ban.BannedUserID)) 396 if (!IsBanned(ban.BannedUserID, 32)) //Ignore age-based bans
354 l_EstateBans.Add(ban); 397 l_EstateBans.Add(ban);
355 } 398 }
356 399
@@ -374,6 +417,15 @@ namespace OpenSim.Framework
374 return l_EstateAccess.Contains(user); 417 return l_EstateAccess.Contains(user);
375 } 418 }
376 419
420 public void SetFromFlags(ulong regionFlags)
421 {
422 ResetHomeOnTeleport = ((regionFlags & (ulong)RegionFlags.ResetHomeOnTeleport) == (ulong)RegionFlags.ResetHomeOnTeleport);
423 BlockDwell = ((regionFlags & (ulong)RegionFlags.BlockDwell) == (ulong)RegionFlags.BlockDwell);
424 AllowLandmark = ((regionFlags & (ulong)RegionFlags.AllowLandmark) == (ulong)RegionFlags.AllowLandmark);
425 AllowParcelChanges = ((regionFlags & (ulong)RegionFlags.AllowParcelChanges) == (ulong)RegionFlags.AllowParcelChanges);
426 AllowSetHome = ((regionFlags & (ulong)RegionFlags.AllowSetHome) == (ulong)RegionFlags.AllowSetHome);
427 }
428
377 public bool GroupAccess(UUID groupID) 429 public bool GroupAccess(UUID groupID)
378 { 430 {
379 return l_EstateGroups.Contains(groupID); 431 return l_EstateGroups.Contains(groupID);
diff --git a/OpenSim/Framework/ICallingCardModule.cs b/OpenSim/Framework/ICallingCardModule.cs
new file mode 100644
index 0000000..17e6de35
--- /dev/null
+++ b/OpenSim/Framework/ICallingCardModule.cs
@@ -0,0 +1,13 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using OpenMetaverse;
5using OpenSim.Framework;
6
7namespace OpenSim.Framework
8{
9 public interface ICallingCardModule
10 {
11 UUID CreateCallingCard(UUID userID, UUID creatorID, UUID folderID);
12 }
13}
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index 1326fe9..0e0c218 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -266,6 +266,9 @@ namespace OpenSim.Framework
266 public delegate void MoveInventoryItem( 266 public delegate void MoveInventoryItem(
267 IClientAPI remoteClient, List<InventoryItemBase> items); 267 IClientAPI remoteClient, List<InventoryItemBase> items);
268 268
269 public delegate void MoveItemsAndLeaveCopy(
270 IClientAPI remoteClient, List<InventoryItemBase> items, UUID destFolder);
271
269 public delegate void RemoveInventoryItem( 272 public delegate void RemoveInventoryItem(
270 IClientAPI remoteClient, List<UUID> itemIDs); 273 IClientAPI remoteClient, List<UUID> itemIDs);
271 274
@@ -441,6 +444,7 @@ namespace OpenSim.Framework
441 public delegate void ClassifiedInfoRequest(UUID classifiedID, IClientAPI client); 444 public delegate void ClassifiedInfoRequest(UUID classifiedID, IClientAPI client);
442 public delegate void ClassifiedInfoUpdate(UUID classifiedID, uint category, string name, string description, UUID parcelID, uint parentEstate, UUID snapshotID, Vector3 globalPos, byte classifiedFlags, int price, IClientAPI client); 445 public delegate void ClassifiedInfoUpdate(UUID classifiedID, uint category, string name, string description, UUID parcelID, uint parentEstate, UUID snapshotID, Vector3 globalPos, byte classifiedFlags, int price, IClientAPI client);
443 public delegate void ClassifiedDelete(UUID classifiedID, IClientAPI client); 446 public delegate void ClassifiedDelete(UUID classifiedID, IClientAPI client);
447 public delegate void ClassifiedGodDelete(UUID classifiedID, UUID queryID, IClientAPI client);
444 448
445 public delegate void EventNotificationAddRequest(uint EventID, IClientAPI client); 449 public delegate void EventNotificationAddRequest(uint EventID, IClientAPI client);
446 public delegate void EventNotificationRemoveRequest(uint EventID, IClientAPI client); 450 public delegate void EventNotificationRemoveRequest(uint EventID, IClientAPI client);
@@ -463,9 +467,9 @@ namespace OpenSim.Framework
463 467
464 public delegate void AgentFOV(IClientAPI client, float verticalAngle); 468 public delegate void AgentFOV(IClientAPI client, float verticalAngle);
465 469
466 public delegate void MuteListEntryUpdate(IClientAPI client, UUID MuteID, string Name, int Flags,UUID AgentID); 470 public delegate void MuteListEntryUpdate(IClientAPI client, UUID MuteID, string Name, int type, uint flags);
467 471
468 public delegate void MuteListEntryRemove(IClientAPI client, UUID MuteID, string Name, UUID AgentID); 472 public delegate void MuteListEntryRemove(IClientAPI client, UUID MuteID, string Name);
469 473
470 public delegate void AvatarInterestReply(IClientAPI client,UUID target, uint wantmask, string wanttext, uint skillsmask, string skillstext, string languages); 474 public delegate void AvatarInterestReply(IClientAPI client,UUID target, uint wantmask, string wanttext, uint skillsmask, string skillstext, string languages);
471 475
@@ -503,6 +507,7 @@ namespace OpenSim.Framework
503 public delegate void SimWideDeletesDelegate(IClientAPI client,UUID agentID, int flags, UUID targetID); 507 public delegate void SimWideDeletesDelegate(IClientAPI client,UUID agentID, int flags, UUID targetID);
504 508
505 public delegate void SendPostcard(IClientAPI client); 509 public delegate void SendPostcard(IClientAPI client);
510 public delegate void ChangeInventoryItemFlags(IClientAPI client, UUID itemID, uint flags);
506 511
507 #endregion 512 #endregion
508 513
@@ -857,6 +862,7 @@ namespace OpenSim.Framework
857 event RequestTaskInventory OnRequestTaskInventory; 862 event RequestTaskInventory OnRequestTaskInventory;
858 event UpdateInventoryItem OnUpdateInventoryItem; 863 event UpdateInventoryItem OnUpdateInventoryItem;
859 event CopyInventoryItem OnCopyInventoryItem; 864 event CopyInventoryItem OnCopyInventoryItem;
865 event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy;
860 event MoveInventoryItem OnMoveInventoryItem; 866 event MoveInventoryItem OnMoveInventoryItem;
861 event RemoveInventoryFolder OnRemoveInventoryFolder; 867 event RemoveInventoryFolder OnRemoveInventoryFolder;
862 event RemoveInventoryItem OnRemoveInventoryItem; 868 event RemoveInventoryItem OnRemoveInventoryItem;
@@ -975,7 +981,7 @@ namespace OpenSim.Framework
975 event ClassifiedInfoRequest OnClassifiedInfoRequest; 981 event ClassifiedInfoRequest OnClassifiedInfoRequest;
976 event ClassifiedInfoUpdate OnClassifiedInfoUpdate; 982 event ClassifiedInfoUpdate OnClassifiedInfoUpdate;
977 event ClassifiedDelete OnClassifiedDelete; 983 event ClassifiedDelete OnClassifiedDelete;
978 event ClassifiedDelete OnClassifiedGodDelete; 984 event ClassifiedGodDelete OnClassifiedGodDelete;
979 985
980 event EventNotificationAddRequest OnEventNotificationAddRequest; 986 event EventNotificationAddRequest OnEventNotificationAddRequest;
981 event EventNotificationRemoveRequest OnEventNotificationRemoveRequest; 987 event EventNotificationRemoveRequest OnEventNotificationRemoveRequest;
@@ -1014,6 +1020,7 @@ namespace OpenSim.Framework
1014 event GroupVoteHistoryRequest OnGroupVoteHistoryRequest; 1020 event GroupVoteHistoryRequest OnGroupVoteHistoryRequest;
1015 event SimWideDeletesDelegate OnSimWideDeletes; 1021 event SimWideDeletesDelegate OnSimWideDeletes;
1016 event SendPostcard OnSendPostcard; 1022 event SendPostcard OnSendPostcard;
1023 event ChangeInventoryItemFlags OnChangeInventoryItemFlags;
1017 event MuteListEntryUpdate OnUpdateMuteListEntry; 1024 event MuteListEntryUpdate OnUpdateMuteListEntry;
1018 event MuteListEntryRemove OnRemoveMuteListEntry; 1025 event MuteListEntryRemove OnRemoveMuteListEntry;
1019 event GodlikeMessage onGodlikeMessage; 1026 event GodlikeMessage onGodlikeMessage;
@@ -1027,6 +1034,7 @@ namespace OpenSim.Framework
1027 void InPacket(object NewPack); 1034 void InPacket(object NewPack);
1028 void ProcessInPacket(Packet NewPack); 1035 void ProcessInPacket(Packet NewPack);
1029 void Close(); 1036 void Close();
1037 void Close(bool sendStop);
1030 void Kick(string message); 1038 void Kick(string message);
1031 1039
1032 /// <summary> 1040 /// <summary>
diff --git a/OpenSim/Framework/IMoneyModule.cs b/OpenSim/Framework/IMoneyModule.cs
index 1e09728..71de93a 100644
--- a/OpenSim/Framework/IMoneyModule.cs
+++ b/OpenSim/Framework/IMoneyModule.cs
@@ -40,6 +40,7 @@ namespace OpenSim.Framework
40 bool AmountCovered(UUID agentID, int amount); 40 bool AmountCovered(UUID agentID, int amount);
41 void ApplyCharge(UUID agentID, int amount, string text); 41 void ApplyCharge(UUID agentID, int amount, string text);
42 void ApplyUploadCharge(UUID agentID, int amount, string text); 42 void ApplyUploadCharge(UUID agentID, int amount, string text);
43 void MoveMoney(UUID fromUser, UUID toUser, int amount, string text);
43 44
44 int UploadCharge { get; } 45 int UploadCharge { get; }
45 int GroupCreationCharge { get; } 46 int GroupCreationCharge { get; }
diff --git a/OpenSim/Framework/LandData.cs b/OpenSim/Framework/LandData.cs
index c107143..282a128 100644
--- a/OpenSim/Framework/LandData.cs
+++ b/OpenSim/Framework/LandData.cs
@@ -60,7 +60,7 @@ namespace OpenSim.Framework
60 60
61 private uint _flags = (uint) ParcelFlags.AllowFly | (uint) ParcelFlags.AllowLandmark | 61 private uint _flags = (uint) ParcelFlags.AllowFly | (uint) ParcelFlags.AllowLandmark |
62 (uint) ParcelFlags.AllowAPrimitiveEntry | 62 (uint) ParcelFlags.AllowAPrimitiveEntry |
63 (uint) ParcelFlags.AllowDeedToGroup | (uint) ParcelFlags.AllowTerraform | 63 (uint) ParcelFlags.AllowDeedToGroup |
64 (uint) ParcelFlags.CreateObjects | (uint) ParcelFlags.AllowOtherScripts | 64 (uint) ParcelFlags.CreateObjects | (uint) ParcelFlags.AllowOtherScripts |
65 (uint) ParcelFlags.SoundLocal; 65 (uint) ParcelFlags.SoundLocal;
66 66
diff --git a/OpenSim/Framework/ParcelMediaCommandEnum.cs b/OpenSim/Framework/ParcelMediaCommandEnum.cs
index 93c41ec..e714382 100644
--- a/OpenSim/Framework/ParcelMediaCommandEnum.cs
+++ b/OpenSim/Framework/ParcelMediaCommandEnum.cs
@@ -27,7 +27,7 @@
27 27
28namespace OpenSim.Framework 28namespace OpenSim.Framework
29{ 29{
30 public enum ParcelMediaCommandEnum 30 public enum ParcelMediaCommandEnum : int
31 { 31 {
32 Stop = 0, 32 Stop = 0,
33 Pause = 1, 33 Pause = 1,
diff --git a/OpenSim/Framework/PluginLoader.cs b/OpenSim/Framework/PluginLoader.cs
index 819cb7b..cc80943 100644
--- a/OpenSim/Framework/PluginLoader.cs
+++ b/OpenSim/Framework/PluginLoader.cs
@@ -244,13 +244,22 @@ namespace OpenSim.Framework
244 // The Mono addin manager (in Mono.Addins.dll version 0.2.0.0) 244 // The Mono addin manager (in Mono.Addins.dll version 0.2.0.0)
245 // occasionally seems to corrupt its addin cache 245 // occasionally seems to corrupt its addin cache
246 // Hence, as a temporary solution we'll remove it before each startup 246 // Hence, as a temporary solution we'll remove it before each startup
247
248 string customDir = Environment.GetEnvironmentVariable ("MONO_ADDINS_REGISTRY");
249 string v0 = "addin-db-000";
250 string v1 = "addin-db-001";
251 if (customDir != null && customDir != String.Empty)
252 {
253 v0 = Path.Combine(customDir, v0);
254 v1 = Path.Combine(customDir, v1);
255 }
247 try 256 try
248 { 257 {
249 if (Directory.Exists("addin-db-000")) 258 if (Directory.Exists(v0))
250 Directory.Delete("addin-db-000", true); 259 Directory.Delete(v0, true);
251 260
252 if (Directory.Exists("addin-db-001")) 261 if (Directory.Exists(v1))
253 Directory.Delete("addin-db-001", true); 262 Directory.Delete(v1, true);
254 } 263 }
255 catch (IOException) 264 catch (IOException)
256 { 265 {
diff --git a/OpenSim/Framework/PrimitiveBaseShape.cs b/OpenSim/Framework/PrimitiveBaseShape.cs
index 1b6a1d2..9cfc7ed 100644
--- a/OpenSim/Framework/PrimitiveBaseShape.cs
+++ b/OpenSim/Framework/PrimitiveBaseShape.cs
@@ -720,7 +720,12 @@ namespace OpenSim.Framework
720 return _lightColorR; 720 return _lightColorR;
721 } 721 }
722 set { 722 set {
723 _lightColorR = value; 723 if (value < 0)
724 _lightColorR = 0;
725 else if (value > 1.0f)
726 _lightColorR = 1.0f;
727 else
728 _lightColorR = value;
724 } 729 }
725 } 730 }
726 731
@@ -729,7 +734,12 @@ namespace OpenSim.Framework
729 return _lightColorG; 734 return _lightColorG;
730 } 735 }
731 set { 736 set {
732 _lightColorG = value; 737 if (value < 0)
738 _lightColorG = 0;
739 else if (value > 1.0f)
740 _lightColorG = 1.0f;
741 else
742 _lightColorG = value;
733 } 743 }
734 } 744 }
735 745
@@ -738,7 +748,12 @@ namespace OpenSim.Framework
738 return _lightColorB; 748 return _lightColorB;
739 } 749 }
740 set { 750 set {
741 _lightColorB = value; 751 if (value < 0)
752 _lightColorB = 0;
753 else if (value > 1.0f)
754 _lightColorB = 1.0f;
755 else
756 _lightColorB = value;
742 } 757 }
743 } 758 }
744 759
@@ -747,7 +762,12 @@ namespace OpenSim.Framework
747 return _lightColorA; 762 return _lightColorA;
748 } 763 }
749 set { 764 set {
750 _lightColorA = value; 765 if (value < 0)
766 _lightColorA = 0;
767 else if (value > 1.0f)
768 _lightColorA = 1.0f;
769 else
770 _lightColorA = value;
751 } 771 }
752 } 772 }
753 773
@@ -1410,7 +1430,7 @@ namespace OpenSim.Framework
1410 prim.Textures = this.Textures; 1430 prim.Textures = this.Textures;
1411 1431
1412 prim.Properties = new Primitive.ObjectProperties(); 1432 prim.Properties = new Primitive.ObjectProperties();
1413 prim.Properties.Name = "Primitive"; 1433 prim.Properties.Name = "Object";
1414 prim.Properties.Description = ""; 1434 prim.Properties.Description = "";
1415 prim.Properties.CreatorID = UUID.Zero; 1435 prim.Properties.CreatorID = UUID.Zero;
1416 prim.Properties.GroupID = UUID.Zero; 1436 prim.Properties.GroupID = UUID.Zero;
diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs
index 169b951..96f3049 100644
--- a/OpenSim/Framework/RegionInfo.cs
+++ b/OpenSim/Framework/RegionInfo.cs
@@ -40,6 +40,7 @@ using OpenMetaverse.StructuredData;
40 40
41namespace OpenSim.Framework 41namespace OpenSim.Framework
42{ 42{
43 [Serializable]
43 public class RegionLightShareData : ICloneable 44 public class RegionLightShareData : ICloneable
44 { 45 {
45 public bool valid = false; 46 public bool valid = false;
@@ -102,6 +103,7 @@ namespace OpenSim.Framework
102 103
103 public bool commFailTF = false; 104 public bool commFailTF = false;
104 public ConfigurationMember configMember; 105 public ConfigurationMember configMember;
106 public string DataStore = String.Empty;
105 public string RegionFile = String.Empty; 107 public string RegionFile = String.Empty;
106 public bool isSandbox = false; 108 public bool isSandbox = false;
107 public bool Persistent = true; 109 public bool Persistent = true;
@@ -639,6 +641,9 @@ namespace OpenSim.Framework
639 string location = String.Format("{0},{1}", m_regionLocX, m_regionLocY); 641 string location = String.Format("{0},{1}", m_regionLocX, m_regionLocY);
640 config.Set("Location", location); 642 config.Set("Location", location);
641 643
644 if (DataStore != String.Empty)
645 config.Set("Datastore", DataStore);
646
642 config.Set("InternalAddress", m_internalEndPoint.Address.ToString()); 647 config.Set("InternalAddress", m_internalEndPoint.Address.ToString());
643 config.Set("InternalPort", m_internalEndPoint.Port); 648 config.Set("InternalPort", m_internalEndPoint.Port);
644 649
@@ -824,6 +829,9 @@ namespace OpenSim.Framework
824 case "sim_location_y": 829 case "sim_location_y":
825 m_regionLocY = (uint) configuration_result; 830 m_regionLocY = (uint) configuration_result;
826 break; 831 break;
832 case "datastore":
833 DataStore = (string) configuration_result;
834 break;
827 case "internal_ip_address": 835 case "internal_ip_address":
828 IPAddress address = (IPAddress) configuration_result; 836 IPAddress address = (IPAddress) configuration_result;
829 m_internalEndPoint = new IPEndPoint(address, 0); 837 m_internalEndPoint = new IPEndPoint(address, 0);
@@ -974,6 +982,11 @@ namespace OpenSim.Framework
974 return regionInfo; 982 return regionInfo;
975 } 983 }
976 984
985 public int getInternalEndPointPort()
986 {
987 return m_internalEndPoint.Port;
988 }
989
977 public Dictionary<string, object> ToKeyValuePairs() 990 public Dictionary<string, object> ToKeyValuePairs()
978 { 991 {
979 Dictionary<string, object> kvp = new Dictionary<string, object>(); 992 Dictionary<string, object> kvp = new Dictionary<string, object>();
@@ -992,4 +1005,4 @@ namespace OpenSim.Framework
992 return kvp; 1005 return kvp;
993 } 1006 }
994 } 1007 }
995} \ No newline at end of file 1008}
diff --git a/OpenSim/Framework/RegionLoader/Web/RegionLoaderWebServer.cs b/OpenSim/Framework/RegionLoader/Web/RegionLoaderWebServer.cs
index a2f5d9c..c7caf6f 100644
--- a/OpenSim/Framework/RegionLoader/Web/RegionLoaderWebServer.cs
+++ b/OpenSim/Framework/RegionLoader/Web/RegionLoaderWebServer.cs
@@ -48,6 +48,9 @@ namespace OpenSim.Framework.RegionLoader.Web
48 48
49 public RegionInfo[] LoadRegions() 49 public RegionInfo[] LoadRegions()
50 { 50 {
51 int tries = 3;
52 int wait = 2000;
53
51 if (m_configSource == null) 54 if (m_configSource == null)
52 { 55 {
53 m_log.Error("[WEBLOADER]: Unable to load configuration source!"); 56 m_log.Error("[WEBLOADER]: Unable to load configuration source!");
@@ -66,63 +69,72 @@ namespace OpenSim.Framework.RegionLoader.Web
66 } 69 }
67 else 70 else
68 { 71 {
69 RegionInfo[] regionInfos = new RegionInfo[] {}; 72 while(tries > 0)
70 int regionCount = 0; 73 {
71 HttpWebRequest webRequest = (HttpWebRequest) WebRequest.Create(url); 74 RegionInfo[] regionInfos = new RegionInfo[] {};
72 webRequest.Timeout = 30000; //30 Second Timeout 75 int regionCount = 0;
73 m_log.DebugFormat("[WEBLOADER]: Sending download request to {0}", url); 76 HttpWebRequest webRequest = (HttpWebRequest) WebRequest.Create(url);
77 webRequest.Timeout = 30000; //30 Second Timeout
78 m_log.DebugFormat("[WEBLOADER]: Sending download request to {0}", url);
74 79
75 try 80 try
76 { 81 {
77 HttpWebResponse webResponse = (HttpWebResponse) webRequest.GetResponse(); 82 HttpWebResponse webResponse = (HttpWebResponse) webRequest.GetResponse();
78 m_log.Debug("[WEBLOADER]: Downloading region information..."); 83 m_log.Debug("[WEBLOADER]: Downloading region information...");
79 StreamReader reader = new StreamReader(webResponse.GetResponseStream()); 84 StreamReader reader = new StreamReader(webResponse.GetResponseStream());
80 string xmlSource = String.Empty; 85 string xmlSource = String.Empty;
81 string tempStr = reader.ReadLine(); 86 string tempStr = reader.ReadLine();
82 while (tempStr != null) 87 while (tempStr != null)
83 { 88 {
84 xmlSource = xmlSource + tempStr; 89 xmlSource = xmlSource + tempStr;
85 tempStr = reader.ReadLine(); 90 tempStr = reader.ReadLine();
86 } 91 }
87 m_log.Debug("[WEBLOADER]: Done downloading region information from server. Total Bytes: " + 92 m_log.Debug("[WEBLOADER]: Done downloading region information from server. Total Bytes: " +
88 xmlSource.Length); 93 xmlSource.Length);
89 XmlDocument xmlDoc = new XmlDocument(); 94 XmlDocument xmlDoc = new XmlDocument();
90 xmlDoc.LoadXml(xmlSource); 95 xmlDoc.LoadXml(xmlSource);
91 if (xmlDoc.FirstChild.Name == "Regions") 96 if (xmlDoc.FirstChild.Name == "Regions")
92 { 97 {
93 regionCount = xmlDoc.FirstChild.ChildNodes.Count; 98 regionCount = xmlDoc.FirstChild.ChildNodes.Count;
94 99
95 if (regionCount > 0) 100 if (regionCount > 0)
96 { 101 {
97 regionInfos = new RegionInfo[regionCount]; 102 regionInfos = new RegionInfo[regionCount];
98 int i; 103 int i;
99 for (i = 0; i < xmlDoc.FirstChild.ChildNodes.Count; i++) 104 for (i = 0; i < xmlDoc.FirstChild.ChildNodes.Count; i++)
100 { 105 {
101 m_log.Debug(xmlDoc.FirstChild.ChildNodes[i].OuterXml); 106 m_log.Debug(xmlDoc.FirstChild.ChildNodes[i].OuterXml);
102 regionInfos[i] = 107 regionInfos[i] =
103 new RegionInfo("REGION CONFIG #" + (i + 1), xmlDoc.FirstChild.ChildNodes[i],false,m_configSource); 108 new RegionInfo("REGION CONFIG #" + (i + 1), xmlDoc.FirstChild.ChildNodes[i],false,m_configSource);
104 } 109 }
105 } 110 }
106 } 111 }
107 } 112 }
108 catch (WebException ex) 113 catch (WebException ex)
109 { 114 {
110 if (((HttpWebResponse)ex.Response).StatusCode == HttpStatusCode.NotFound) 115 if (((HttpWebResponse)ex.Response).StatusCode == HttpStatusCode.NotFound)
116 {
117 if (!allowRegionless)
118 throw ex;
119 }
120 else
121 throw ex;
122 }
123
124 if (regionCount > 0 | allowRegionless)
125 return regionInfos;
126
127 m_log.Debug("[WEBLOADER]: Request yielded no regions.");
128 tries--;
129 if (tries > 0)
111 { 130 {
112 if (!allowRegionless) 131 m_log.Debug("[WEBLOADER]: Retrying");
113 throw ex; 132 System.Threading.Thread.Sleep(wait);
114 } 133 }
115 else 134 }
116 throw ex;
117 }
118 135
119 if (regionCount > 0 | allowRegionless) 136 m_log.Error("[WEBLOADER]: No region configs were available.");
120 return regionInfos; 137 return null;
121 else
122 {
123 m_log.Error("[WEBLOADER]: No region configs were available.");
124 return null;
125 }
126 } 138 }
127 } 139 }
128 } 140 }
diff --git a/OpenSim/Framework/RegionSettings.cs b/OpenSim/Framework/RegionSettings.cs
index 91e07df..e668ad5 100644
--- a/OpenSim/Framework/RegionSettings.cs
+++ b/OpenSim/Framework/RegionSettings.cs
@@ -447,6 +447,28 @@ namespace OpenSim.Framework
447 set { m_LoadedCreationID = value; } 447 set { m_LoadedCreationID = value; }
448 } 448 }
449 449
450 private bool m_GodBlockSearch = false;
451 public bool GodBlockSearch
452 {
453 get { return m_GodBlockSearch; }
454 set { m_GodBlockSearch = value; }
455 }
456
457 private bool m_Casino = false;
458 public bool Casino
459 {
460 get { return m_Casino; }
461 set { m_Casino = value; }
462 }
463
464 // Telehub support
465 private bool m_TelehubEnabled = false;
466 public bool HasTelehub
467 {
468 get { return m_TelehubEnabled; }
469 set { m_TelehubEnabled = value; }
470 }
471
450 // Connected Telehub object 472 // Connected Telehub object
451 private UUID m_TelehubObject; 473 private UUID m_TelehubObject;
452 public UUID TelehubObject 474 public UUID TelehubObject
diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
index 545e76c..3868a31 100644
--- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs
+++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
@@ -304,7 +304,7 @@ namespace OpenSim.Framework.Servers
304 304
305 EnhanceVersionInformation(); 305 EnhanceVersionInformation();
306 306
307 m_log.Info("[STARTUP]: OpenSimulator version: " + m_version + Environment.NewLine); 307 m_log.Info("[STARTUP]: Careminster version: " + m_version + Environment.NewLine);
308 // clr version potentially is more confusing than helpful, since it doesn't tell us if we're running under Mono/MS .NET and 308 // clr version potentially is more confusing than helpful, since it doesn't tell us if we're running under Mono/MS .NET and
309 // the clr version number doesn't match the project version number under Mono. 309 // the clr version number doesn't match the project version number under Mono.
310 //m_log.Info("[STARTUP]: Virtual machine runtime version: " + Environment.Version + Environment.NewLine); 310 //m_log.Info("[STARTUP]: Virtual machine runtime version: " + Environment.Version + Environment.NewLine);
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index a8ece79..2c0d8f0 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -1539,11 +1539,34 @@ namespace OpenSim.Framework.Servers.HttpServer
1539 1539
1540 internal void DoHTTPGruntWork(Hashtable responsedata, OSHttpResponse response) 1540 internal void DoHTTPGruntWork(Hashtable responsedata, OSHttpResponse response)
1541 { 1541 {
1542 //m_log.Info("[BASE HTTP SERVER]: Doing HTTP Grunt work with response"); 1542 int responsecode;
1543 int responsecode = (int)responsedata["int_response_code"]; 1543 string responseString;
1544 string responseString = (string)responsedata["str_response_string"]; 1544 string contentType;
1545 string contentType = (string)responsedata["content_type"];
1546 1545
1546 if (responsedata == null)
1547 {
1548 responsecode = 500;
1549 responseString = "No response could be obtained";
1550 contentType = "text/plain";
1551 responsedata = new Hashtable();
1552 }
1553 else
1554 {
1555 try
1556 {
1557 //m_log.Info("[BASE HTTP SERVER]: Doing HTTP Grunt work with response");
1558 responsecode = (int)responsedata["int_response_code"];
1559 responseString = (string)responsedata["str_response_string"];
1560 contentType = (string)responsedata["content_type"];
1561 }
1562 catch
1563 {
1564 responsecode = 500;
1565 responseString = "No response could be obtained";
1566 contentType = "text/plain";
1567 responsedata = new Hashtable();
1568 }
1569 }
1547 1570
1548 if (responsedata.ContainsKey("error_status_text")) 1571 if (responsedata.ContainsKey("error_status_text"))
1549 { 1572 {
diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs
index f30cb7a..b2bb962 100644
--- a/OpenSim/Framework/Servers/VersionInfo.cs
+++ b/OpenSim/Framework/Servers/VersionInfo.cs
@@ -29,11 +29,11 @@ namespace OpenSim
29{ 29{
30 public class VersionInfo 30 public class VersionInfo
31 { 31 {
32 private const string VERSION_NUMBER = "0.7.3"; 32 private const string VERSION_NUMBER = "0.7.3CM";
33 private const Flavour VERSION_FLAVOUR = Flavour.Dev; 33 private const Flavour VERSION_FLAVOUR = Flavour.Dev;
34 34
35 public enum Flavour 35 public enum Flavour
36 { 36 {
37 Unknown, 37 Unknown,
38 Dev, 38 Dev,
39 RC1, 39 RC1,
@@ -49,7 +49,7 @@ namespace OpenSim
49 49
50 public static string GetVersionString(string versionNumber, Flavour flavour) 50 public static string GetVersionString(string versionNumber, Flavour flavour)
51 { 51 {
52 string versionString = "OpenSim " + versionNumber + " " + flavour; 52 string versionString = "Careminster " + versionNumber + " " + flavour;
53 return versionString.PadRight(VERSIONINFO_VERSION_LENGTH); 53 return versionString.PadRight(VERSIONINFO_VERSION_LENGTH);
54 } 54 }
55 55
diff --git a/OpenSim/Framework/TaskInventoryDictionary.cs b/OpenSim/Framework/TaskInventoryDictionary.cs
index 421bd5d..814758a 100644
--- a/OpenSim/Framework/TaskInventoryDictionary.cs
+++ b/OpenSim/Framework/TaskInventoryDictionary.cs
@@ -27,9 +27,13 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Threading;
31using System.Reflection;
30using System.Xml; 32using System.Xml;
33using System.Diagnostics;
31using System.Xml.Schema; 34using System.Xml.Schema;
32using System.Xml.Serialization; 35using System.Xml.Serialization;
36using log4net;
33using OpenMetaverse; 37using OpenMetaverse;
34 38
35namespace OpenSim.Framework 39namespace OpenSim.Framework
@@ -45,6 +49,155 @@ namespace OpenSim.Framework
45 // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 50
47 private static XmlSerializer tiiSerializer = new XmlSerializer(typeof (TaskInventoryItem)); 51 private static XmlSerializer tiiSerializer = new XmlSerializer(typeof (TaskInventoryItem));
52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
54 private Thread LockedByThread;
55 private string WriterStack;
56
57 private Dictionary<Thread, string> ReadLockers =
58 new Dictionary<Thread, string>();
59
60 /// <value>
61 /// An advanced lock for inventory data
62 /// </value>
63 private System.Threading.ReaderWriterLockSlim m_itemLock = new System.Threading.ReaderWriterLockSlim();
64
65 /// <summary>
66 /// Are we readlocked by the calling thread?
67 /// </summary>
68 public bool IsReadLockedByMe()
69 {
70 if (m_itemLock.RecursiveReadCount > 0)
71 {
72 return true;
73 }
74 else
75 {
76 return false;
77 }
78 }
79
80 /// <summary>
81 /// Lock our inventory list for reading (many can read, one can write)
82 /// </summary>
83 public void LockItemsForRead(bool locked)
84 {
85 if (locked)
86 {
87 if (m_itemLock.IsWriteLockHeld && LockedByThread != null)
88 {
89 if (!LockedByThread.IsAlive)
90 {
91 //Locked by dead thread, reset.
92 m_itemLock = new System.Threading.ReaderWriterLockSlim();
93 }
94 }
95
96 if (m_itemLock.RecursiveReadCount > 0)
97 {
98 m_log.Error("[TaskInventoryDictionary] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
99 try
100 {
101 StackTrace stackTrace = new StackTrace(); // get call stack
102 StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames)
103
104 // write call stack method names
105 foreach (StackFrame stackFrame in stackFrames)
106 {
107 m_log.Error("[SceneObjectGroup.m_parts] "+(stackFrame.GetMethod().Name)); // write method name
108 }
109 }
110 catch
111 {}
112 m_itemLock.ExitReadLock();
113 }
114 if (m_itemLock.RecursiveWriteCount > 0)
115 {
116 m_log.Error("[TaskInventoryDictionary] Recursive write lock requested. This should not happen and means something needs to be fixed.");
117 m_itemLock.ExitWriteLock();
118 }
119
120 while (!m_itemLock.TryEnterReadLock(60000))
121 {
122 m_log.Error("Thread lock detected while trying to aquire READ lock in TaskInventoryDictionary. Locked by thread " + LockedByThread.Name + ". I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
123 if (m_itemLock.IsWriteLockHeld)
124 {
125 m_itemLock = new System.Threading.ReaderWriterLockSlim();
126 System.Console.WriteLine("------------------------------------------");
127 System.Console.WriteLine("My call stack:\n" + Environment.StackTrace);
128 System.Console.WriteLine("------------------------------------------");
129 System.Console.WriteLine("Locker's call stack:\n" + WriterStack);
130 System.Console.WriteLine("------------------------------------------");
131 LockedByThread = null;
132 ReadLockers.Clear();
133 }
134 }
135 }
136 else
137 {
138 if (m_itemLock.RecursiveReadCount>0)
139 {
140 m_itemLock.ExitReadLock();
141 }
142 }
143 }
144
145 /// <summary>
146 /// Lock our inventory list for writing (many can read, one can write)
147 /// </summary>
148 public void LockItemsForWrite(bool locked)
149 {
150 if (locked)
151 {
152 //Enter a write lock, wait indefinately for one to open.
153 if (m_itemLock.RecursiveReadCount > 0)
154 {
155 m_log.Error("[TaskInventoryDictionary] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
156 m_itemLock.ExitReadLock();
157 }
158 if (m_itemLock.RecursiveWriteCount > 0)
159 {
160 m_log.Error("[TaskInventoryDictionary] Recursive write lock requested. This should not happen and means something needs to be fixed.");
161 m_itemLock.ExitWriteLock();
162 }
163 while (!m_itemLock.TryEnterWriteLock(60000))
164 {
165 if (m_itemLock.IsWriteLockHeld)
166 {
167 m_log.Error("Thread lock detected while trying to aquire WRITE lock in TaskInventoryDictionary. Locked by thread " + LockedByThread.Name + ". I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
168 System.Console.WriteLine("------------------------------------------");
169 System.Console.WriteLine("My call stack:\n" + Environment.StackTrace);
170 System.Console.WriteLine("------------------------------------------");
171 System.Console.WriteLine("Locker's call stack:\n" + WriterStack);
172 System.Console.WriteLine("------------------------------------------");
173 }
174 else
175 {
176 m_log.Error("Thread lock detected while trying to aquire WRITE lock in TaskInventoryDictionary. Locked by a reader. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
177 System.Console.WriteLine("------------------------------------------");
178 System.Console.WriteLine("My call stack:\n" + Environment.StackTrace);
179 System.Console.WriteLine("------------------------------------------");
180 foreach (KeyValuePair<Thread, string> kvp in ReadLockers)
181 {
182 System.Console.WriteLine("Locker name {0} call stack:\n" + kvp.Value, kvp.Key.Name);
183 System.Console.WriteLine("------------------------------------------");
184 }
185 }
186 m_itemLock = new System.Threading.ReaderWriterLockSlim();
187 ReadLockers.Clear();
188 }
189
190 LockedByThread = Thread.CurrentThread;
191 WriterStack = Environment.StackTrace;
192 }
193 else
194 {
195 if (m_itemLock.RecursiveWriteCount > 0)
196 {
197 m_itemLock.ExitWriteLock();
198 }
199 }
200 }
48 201
49 #region ICloneable Members 202 #region ICloneable Members
50 203
@@ -52,14 +205,13 @@ namespace OpenSim.Framework
52 { 205 {
53 TaskInventoryDictionary clone = new TaskInventoryDictionary(); 206 TaskInventoryDictionary clone = new TaskInventoryDictionary();
54 207
55 lock (this) 208 m_itemLock.EnterReadLock();
209 foreach (UUID uuid in Keys)
56 { 210 {
57 foreach (UUID uuid in Keys) 211 clone.Add(uuid, (TaskInventoryItem) this[uuid].Clone());
58 {
59 clone.Add(uuid, (TaskInventoryItem) this[uuid].Clone());
60 }
61 } 212 }
62 213 m_itemLock.ExitReadLock();
214
63 return clone; 215 return clone;
64 } 216 }
65 217
diff --git a/OpenSim/Framework/TaskInventoryItem.cs b/OpenSim/Framework/TaskInventoryItem.cs
index d4bbbfb..7ef8bf7 100644
--- a/OpenSim/Framework/TaskInventoryItem.cs
+++ b/OpenSim/Framework/TaskInventoryItem.cs
@@ -68,6 +68,9 @@ namespace OpenSim.Framework
68 private UUID _loadedID = UUID.Zero; 68 private UUID _loadedID = UUID.Zero;
69 69
70 private bool _ownerChanged = false; 70 private bool _ownerChanged = false;
71
72 // This used ONLY during copy. It can't be relied on at other times!
73 private bool _scriptRunning = true;
71 74
72 public UUID AssetID { 75 public UUID AssetID {
73 get { 76 get {
@@ -340,6 +343,15 @@ namespace OpenSim.Framework
340 } 343 }
341 } 344 }
342 345
346 public bool ScriptRunning {
347 get {
348 return _scriptRunning;
349 }
350 set {
351 _scriptRunning = value;
352 }
353 }
354
343 // See ICloneable 355 // See ICloneable
344 356
345 #region ICloneable Members 357 #region ICloneable Members
diff --git a/OpenSim/Framework/Tests/MundaneFrameworkTests.cs b/OpenSim/Framework/Tests/MundaneFrameworkTests.cs
index 76de6be..34a3f15 100644
--- a/OpenSim/Framework/Tests/MundaneFrameworkTests.cs
+++ b/OpenSim/Framework/Tests/MundaneFrameworkTests.cs
@@ -217,12 +217,12 @@ namespace OpenSim.Framework.Tests
217 BannedHostNameMask = string.Empty, 217 BannedHostNameMask = string.Empty,
218 BannedUserID = bannedUserId} 218 BannedUserID = bannedUserId}
219 ); 219 );
220 Assert.IsTrue(es.IsBanned(bannedUserId), "User Should be banned but is not."); 220 Assert.IsTrue(es.IsBanned(bannedUserId, 32), "User Should be banned but is not.");
221 Assert.IsFalse(es.IsBanned(UUID.Zero), "User Should not be banned but is."); 221 Assert.IsFalse(es.IsBanned(UUID.Zero, 32), "User Should not be banned but is.");
222 222
223 es.RemoveBan(bannedUserId); 223 es.RemoveBan(bannedUserId);
224 224
225 Assert.IsFalse(es.IsBanned(bannedUserId), "User Should not be banned but is."); 225 Assert.IsFalse(es.IsBanned(bannedUserId, 32), "User Should not be banned but is.");
226 226
227 es.AddEstateManager(UUID.Zero); 227 es.AddEstateManager(UUID.Zero);
228 228
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index ed92b2d..fae6802 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -433,19 +433,25 @@ namespace OpenSim.Framework
433 /// </summary> 433 /// </summary>
434 /// <param name="data"></param> 434 /// <param name="data"></param>
435 /// <returns></returns> 435 /// <returns></returns>
436
436 public static string Md5Hash(string data) 437 public static string Md5Hash(string data)
437 { 438 {
438 byte[] dataMd5 = ComputeMD5Hash(data); 439 return Md5Hash(data, Encoding.Default);
440 }
441
442 public static string Md5Hash(string data, Encoding encoding)
443 {
444 byte[] dataMd5 = ComputeMD5Hash(data, encoding);
439 StringBuilder sb = new StringBuilder(); 445 StringBuilder sb = new StringBuilder();
440 for (int i = 0; i < dataMd5.Length; i++) 446 for (int i = 0; i < dataMd5.Length; i++)
441 sb.AppendFormat("{0:x2}", dataMd5[i]); 447 sb.AppendFormat("{0:x2}", dataMd5[i]);
442 return sb.ToString(); 448 return sb.ToString();
443 } 449 }
444 450
445 private static byte[] ComputeMD5Hash(string data) 451 private static byte[] ComputeMD5Hash(string data, Encoding encoding)
446 { 452 {
447 MD5 md5 = MD5.Create(); 453 MD5 md5 = MD5.Create();
448 return md5.ComputeHash(Encoding.Default.GetBytes(data)); 454 return md5.ComputeHash(encoding.GetBytes(data));
449 } 455 }
450 456
451 /// <summary> 457 /// <summary>
@@ -453,6 +459,12 @@ namespace OpenSim.Framework
453 /// </summary> 459 /// </summary>
454 /// <param name="data"></param> 460 /// <param name="data"></param>
455 /// <returns></returns> 461 /// <returns></returns>
462
463 public static string SHA1Hash(string data, Encoding enc)
464 {
465 return SHA1Hash(enc.GetBytes(data));
466 }
467
456 public static string SHA1Hash(string data) 468 public static string SHA1Hash(string data)
457 { 469 {
458 return SHA1Hash(Encoding.Default.GetBytes(data)); 470 return SHA1Hash(Encoding.Default.GetBytes(data));
@@ -1057,19 +1069,19 @@ namespace OpenSim.Framework
1057 { 1069 {
1058 string os = String.Empty; 1070 string os = String.Empty;
1059 1071
1060 if (Environment.OSVersion.Platform != PlatformID.Unix) 1072// if (Environment.OSVersion.Platform != PlatformID.Unix)
1061 { 1073// {
1062 os = Environment.OSVersion.ToString(); 1074// os = Environment.OSVersion.ToString();
1063 } 1075// }
1064 else 1076// else
1065 { 1077// {
1066 os = ReadEtcIssue(); 1078// os = ReadEtcIssue();
1067 } 1079// }
1068 1080//
1069 if (os.Length > 45) 1081// if (os.Length > 45)
1070 { 1082// {
1071 os = os.Substring(0, 45); 1083// os = os.Substring(0, 45);
1072 } 1084// }
1073 1085
1074 return os; 1086 return os;
1075 } 1087 }
@@ -1202,7 +1214,7 @@ namespace OpenSim.Framework
1202 1214
1203 public static Guid GetHashGuid(string data, string salt) 1215 public static Guid GetHashGuid(string data, string salt)
1204 { 1216 {
1205 byte[] hash = ComputeMD5Hash(data + salt); 1217 byte[] hash = ComputeMD5Hash(data + salt, Encoding.Default);
1206 1218
1207 //string s = BitConverter.ToString(hash); 1219 //string s = BitConverter.ToString(hash);
1208 1220
diff --git a/OpenSim/Framework/Watchdog.cs b/OpenSim/Framework/Watchdog.cs
index 2dd6ebe..fa94109 100644
--- a/OpenSim/Framework/Watchdog.cs
+++ b/OpenSim/Framework/Watchdog.cs
@@ -240,7 +240,7 @@ namespace OpenSim.Framework
240 240
241 lock (m_threads) 241 lock (m_threads)
242 { 242 {
243 int now = Environment.TickCount & Int32.MaxValue; 243 int now = Environment.TickCount;
244 244
245 foreach (ThreadWatchdogInfo threadInfo in m_threads.Values) 245 foreach (ThreadWatchdogInfo threadInfo in m_threads.Values)
246 { 246 {
@@ -266,4 +266,4 @@ namespace OpenSim.Framework
266 m_watchdogTimer.Start(); 266 m_watchdogTimer.Start();
267 } 267 }
268 } 268 }
269} \ No newline at end of file 269}
diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs
index b761dfe..854f310 100644
--- a/OpenSim/Framework/WebUtil.cs
+++ b/OpenSim/Framework/WebUtil.cs
@@ -243,6 +243,7 @@ namespace OpenSim.Framework
243 catch (Exception ex) 243 catch (Exception ex)
244 { 244 {
245 errorMessage = ex.Message; 245 errorMessage = ex.Message;
246 m_log.Debug("[WEB UTIL]: Exception making request: " + ex.ToString());
246 } 247 }
247 finally 248 finally
248 { 249 {
@@ -309,7 +310,7 @@ namespace OpenSim.Framework
309 /// </summary> 310 /// </summary>
310 public static OSDMap PostToService(string url, NameValueCollection data) 311 public static OSDMap PostToService(string url, NameValueCollection data)
311 { 312 {
312 return ServiceFormRequest(url,data,10000); 313 return ServiceFormRequest(url,data, 20000);
313 } 314 }
314 315
315 public static OSDMap ServiceFormRequest(string url, NameValueCollection data, int timeout) 316 public static OSDMap ServiceFormRequest(string url, NameValueCollection data, int timeout)
@@ -923,11 +924,18 @@ namespace OpenSim.Framework
923 /// the request. You'll want to make sure you deal with this as they're not uncommon</exception> 924 /// the request. You'll want to make sure you deal with this as they're not uncommon</exception>
924 public static TResponse MakeRequest<TRequest, TResponse>(string verb, string requestUrl, TRequest obj) 925 public static TResponse MakeRequest<TRequest, TResponse>(string verb, string requestUrl, TRequest obj)
925 { 926 {
927 return MakeRequest<TRequest, TResponse>(verb, requestUrl, obj, 0);
928 }
929
930 public static TResponse MakeRequest<TRequest, TResponse>(string verb, string requestUrl, TRequest obj, int pTimeout)
931 {
926 Type type = typeof(TRequest); 932 Type type = typeof(TRequest);
927 TResponse deserial = default(TResponse); 933 TResponse deserial = default(TResponse);
928 934
929 WebRequest request = WebRequest.Create(requestUrl); 935 WebRequest request = WebRequest.Create(requestUrl);
930 request.Method = verb; 936 request.Method = verb;
937 if (pTimeout != 0)
938 request.Timeout = pTimeout * 1000;
931 939
932 if ((verb == "POST") || (verb == "PUT")) 940 if ((verb == "POST") || (verb == "PUT"))
933 { 941 {
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index 145875b..7a40751 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -484,7 +484,7 @@ namespace OpenSim
484 if (alert != null) 484 if (alert != null)
485 presence.ControllingClient.Kick(alert); 485 presence.ControllingClient.Kick(alert);
486 else 486 else
487 presence.ControllingClient.Kick("\nThe OpenSim manager kicked you out.\n"); 487 presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n");
488 488
489 // ...and close on our side 489 // ...and close on our side
490 presence.Scene.IncomingCloseAgent(presence.UUID); 490 presence.Scene.IncomingCloseAgent(presence.UUID);
@@ -1228,7 +1228,7 @@ namespace OpenSim
1228 MainConsole.Instance.Output(String.Format("loadOffsets <X,Y,Z> = <{0},{1},{2}>",loadOffset.X,loadOffset.Y,loadOffset.Z)); 1228 MainConsole.Instance.Output(String.Format("loadOffsets <X,Y,Z> = <{0},{1},{2}>",loadOffset.X,loadOffset.Y,loadOffset.Z));
1229 } 1229 }
1230 } 1230 }
1231 m_sceneManager.LoadCurrentSceneFromXml(cmdparams[2], generateNewIDS, loadOffset); 1231 m_sceneManager.LoadCurrentSceneFromXml(cmdparams[0], generateNewIDS, loadOffset);
1232 } 1232 }
1233 else 1233 else
1234 { 1234 {
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index f482d8f..80bff17 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -93,6 +93,10 @@ namespace OpenSim
93 93
94 protected List<IApplicationPlugin> m_plugins = new List<IApplicationPlugin>(); 94 protected List<IApplicationPlugin> m_plugins = new List<IApplicationPlugin>();
95 95
96 private List<string> m_permsModules;
97
98 private bool m_securePermissionsLoading = true;
99
96 /// <value> 100 /// <value>
97 /// The config information passed into the OpenSimulator region server. 101 /// The config information passed into the OpenSimulator region server.
98 /// </value> 102 /// </value>
@@ -197,6 +201,11 @@ namespace OpenSim
197 CreatePIDFile(pidFile); 201 CreatePIDFile(pidFile);
198 202
199 userStatsURI = startupConfig.GetString("Stats_URI", String.Empty); 203 userStatsURI = startupConfig.GetString("Stats_URI", String.Empty);
204
205 m_securePermissionsLoading = startupConfig.GetBoolean("SecurePermissionsLoading", true);
206
207 string permissionModules = startupConfig.GetString("permissionmodules", "DefaultPermissionsModule");
208 m_permsModules = new List<string>(permissionModules.Split(','));
200 } 209 }
201 210
202 // Load the simulation data service 211 // Load the simulation data service
@@ -225,6 +234,12 @@ namespace OpenSim
225 m_moduleLoader = new ModuleLoader(m_config.Source); 234 m_moduleLoader = new ModuleLoader(m_config.Source);
226 235
227 LoadPlugins(); 236 LoadPlugins();
237
238 if (m_plugins.Count == 0) // We failed to load any modules. Mono Addins glitch!
239 {
240 Environment.Exit(1);
241 }
242
228 foreach (IApplicationPlugin plugin in m_plugins) 243 foreach (IApplicationPlugin plugin in m_plugins)
229 { 244 {
230 plugin.PostInitialise(); 245 plugin.PostInitialise();
@@ -372,7 +387,41 @@ namespace OpenSim
372 } 387 }
373 else m_log.Error("[REGIONMODULES]: The new RegionModulesController is missing..."); 388 else m_log.Error("[REGIONMODULES]: The new RegionModulesController is missing...");
374 389
390 if (m_securePermissionsLoading)
391 {
392 foreach (string s in m_permsModules)
393 {
394 if (!scene.RegionModules.ContainsKey(s))
395 {
396 bool found = false;
397 foreach (IRegionModule m in modules)
398 {
399 if (m.Name == s)
400 {
401 found = true;
402 }
403 }
404 if (!found)
405 {
406 m_log.Fatal("[MODULES]: Required module " + s + " not found.");
407 Environment.Exit(0);
408 }
409 }
410 }
411 }
412
375 scene.SetModuleInterfaces(); 413 scene.SetModuleInterfaces();
414// First Step of bootreport sequence
415 if (scene.SnmpService != null)
416 {
417 scene.SnmpService.ColdStart(1,scene);
418 scene.SnmpService.LinkDown(scene);
419 }
420
421 if (scene.SnmpService != null)
422 {
423 scene.SnmpService.BootInfo("Loading prins", scene);
424 }
376 425
377 while (regionInfo.EstateSettings.EstateOwner == UUID.Zero && MainConsole.Instance != null) 426 while (regionInfo.EstateSettings.EstateOwner == UUID.Zero && MainConsole.Instance != null)
378 SetUpEstateOwner(scene); 427 SetUpEstateOwner(scene);
@@ -386,6 +435,11 @@ namespace OpenSim
386 scene.loadAllLandObjectsFromStorage(regionInfo.originRegionID); 435 scene.loadAllLandObjectsFromStorage(regionInfo.originRegionID);
387 scene.EventManager.TriggerParcelPrimCountUpdate(); 436 scene.EventManager.TriggerParcelPrimCountUpdate();
388 437
438 if (scene.SnmpService != null)
439 {
440 scene.SnmpService.BootInfo("Grid Registration in progress", scene);
441 }
442
389 try 443 try
390 { 444 {
391 scene.RegisterRegionWithGrid(); 445 scene.RegisterRegionWithGrid();
@@ -396,15 +450,29 @@ namespace OpenSim
396 "[STARTUP]: Registration of region with grid failed, aborting startup due to {0} {1}", 450 "[STARTUP]: Registration of region with grid failed, aborting startup due to {0} {1}",
397 e.Message, e.StackTrace); 451 e.Message, e.StackTrace);
398 452
453 if (scene.SnmpService != null)
454 {
455 scene.SnmpService.Critical("Grid registration failed. Startup aborted.", scene);
456 }
399 // Carrying on now causes a lot of confusion down the 457 // Carrying on now causes a lot of confusion down the
400 // line - we need to get the user's attention 458 // line - we need to get the user's attention
401 Environment.Exit(1); 459 Environment.Exit(1);
402 } 460 }
403 461
462 if (scene.SnmpService != null)
463 {
464 scene.SnmpService.BootInfo("Grid Registration done", scene);
465 }
466
404 // We need to do this after we've initialized the 467 // We need to do this after we've initialized the
405 // scripting engines. 468 // scripting engines.
406 scene.CreateScriptInstances(); 469 scene.CreateScriptInstances();
407 470
471 if (scene.SnmpService != null)
472 {
473 scene.SnmpService.BootInfo("ScriptEngine started", scene);
474 }
475
408 m_sceneManager.Add(scene); 476 m_sceneManager.Add(scene);
409 477
410 if (m_autoCreateClientStack) 478 if (m_autoCreateClientStack)
@@ -413,6 +481,10 @@ namespace OpenSim
413 clientServer.Start(); 481 clientServer.Start();
414 } 482 }
415 483
484 if (scene.SnmpService != null)
485 {
486 scene.SnmpService.BootInfo("Initializing region modules", scene);
487 }
416 if (do_post_init) 488 if (do_post_init)
417 { 489 {
418 foreach (IRegionModule module in modules) 490 foreach (IRegionModule module in modules)
@@ -424,7 +496,14 @@ namespace OpenSim
424 496
425 mscene = scene; 497 mscene = scene;
426 498
499 if (scene.SnmpService != null)
500 {
501 scene.SnmpService.BootInfo("The region is operational", scene);
502 scene.SnmpService.LinkUp(scene);
503 }
504
427 scene.StartTimer(); 505 scene.StartTimer();
506 scene.StartTimerWatchdog();
428 507
429 scene.StartScripts(); 508 scene.StartScripts();
430 509
@@ -501,6 +580,11 @@ namespace OpenSim
501 private void ShutdownRegion(Scene scene) 580 private void ShutdownRegion(Scene scene)
502 { 581 {
503 m_log.DebugFormat("[SHUTDOWN]: Shutting down region {0}", scene.RegionInfo.RegionName); 582 m_log.DebugFormat("[SHUTDOWN]: Shutting down region {0}", scene.RegionInfo.RegionName);
583 if (scene.SnmpService != null)
584 {
585 scene.SnmpService.BootInfo("The region is shutting down", scene);
586 scene.SnmpService.LinkDown(scene);
587 }
504 IRegionModulesController controller; 588 IRegionModulesController controller;
505 if (ApplicationRegistry.TryGet<IRegionModulesController>(out controller)) 589 if (ApplicationRegistry.TryGet<IRegionModulesController>(out controller))
506 { 590 {
@@ -944,7 +1028,7 @@ namespace OpenSim
944 = MainConsole.Instance.CmdPrompt( 1028 = MainConsole.Instance.CmdPrompt(
945 string.Format( 1029 string.Format(
946 "Do you wish to join region {0} to an existing estate (yes/no)?", regInfo.RegionName), 1030 "Do you wish to join region {0} to an existing estate (yes/no)?", regInfo.RegionName),
947 "yes", 1031 "no",
948 new List<string>() { "yes", "no" }); 1032 new List<string>() { "yes", "no" });
949 1033
950 if (response == "no") 1034 if (response == "no")
@@ -960,12 +1044,15 @@ namespace OpenSim
960 = MainConsole.Instance.CmdPrompt( 1044 = MainConsole.Instance.CmdPrompt(
961 string.Format( 1045 string.Format(
962 "Name of estate to join. Existing estate names are ({0})", string.Join(", ", estateNames.ToArray())), 1046 "Name of estate to join. Existing estate names are ({0})", string.Join(", ", estateNames.ToArray())),
963 estateNames[0]); 1047 "None");
1048
1049 if (response == "None")
1050 continue;
964 1051
965 List<int> estateIDs = EstateDataService.GetEstates(response); 1052 List<int> estateIDs = EstateDataService.GetEstates(response);
966 if (estateIDs.Count < 1) 1053 if (estateIDs.Count < 1)
967 { 1054 {
968 MainConsole.Instance.Output("The name you have entered matches no known estate. Please try again."); 1055 MainConsole.Instance.Output("The name you have entered matches no known estate. Please try again.");
969 continue; 1056 continue;
970 } 1057 }
971 1058
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
index afbe56b..3995620 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
@@ -234,6 +234,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
234 m_stopPacket = TexturePacketCount(); 234 m_stopPacket = TexturePacketCount();
235 } 235 }
236 236
237 //Give them at least two packets, to play nice with some broken viewers (SL also behaves this way)
238 if (m_stopPacket == 1 && m_layers[0].End > FIRST_PACKET_SIZE) m_stopPacket++;
239
237 m_currentPacket = StartPacket; 240 m_currentPacket = StartPacket;
238 } 241 }
239 } 242 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index a7bf06d..d126f5f 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -158,6 +158,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
158 public event RequestTaskInventory OnRequestTaskInventory; 158 public event RequestTaskInventory OnRequestTaskInventory;
159 public event UpdateInventoryItem OnUpdateInventoryItem; 159 public event UpdateInventoryItem OnUpdateInventoryItem;
160 public event CopyInventoryItem OnCopyInventoryItem; 160 public event CopyInventoryItem OnCopyInventoryItem;
161 public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy;
161 public event MoveInventoryItem OnMoveInventoryItem; 162 public event MoveInventoryItem OnMoveInventoryItem;
162 public event RemoveInventoryItem OnRemoveInventoryItem; 163 public event RemoveInventoryItem OnRemoveInventoryItem;
163 public event RemoveInventoryFolder OnRemoveInventoryFolder; 164 public event RemoveInventoryFolder OnRemoveInventoryFolder;
@@ -256,7 +257,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
256 public event ClassifiedInfoRequest OnClassifiedInfoRequest; 257 public event ClassifiedInfoRequest OnClassifiedInfoRequest;
257 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate; 258 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate;
258 public event ClassifiedDelete OnClassifiedDelete; 259 public event ClassifiedDelete OnClassifiedDelete;
259 public event ClassifiedDelete OnClassifiedGodDelete; 260 public event ClassifiedGodDelete OnClassifiedGodDelete;
260 public event EventNotificationAddRequest OnEventNotificationAddRequest; 261 public event EventNotificationAddRequest OnEventNotificationAddRequest;
261 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest; 262 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest;
262 public event EventGodDelete OnEventGodDelete; 263 public event EventGodDelete OnEventGodDelete;
@@ -287,6 +288,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
287 public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest; 288 public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest;
288 public event SimWideDeletesDelegate OnSimWideDeletes; 289 public event SimWideDeletesDelegate OnSimWideDeletes;
289 public event SendPostcard OnSendPostcard; 290 public event SendPostcard OnSendPostcard;
291 public event ChangeInventoryItemFlags OnChangeInventoryItemFlags;
290 public event MuteListEntryUpdate OnUpdateMuteListEntry; 292 public event MuteListEntryUpdate OnUpdateMuteListEntry;
291 public event MuteListEntryRemove OnRemoveMuteListEntry; 293 public event MuteListEntryRemove OnRemoveMuteListEntry;
292 public event GodlikeMessage onGodlikeMessage; 294 public event GodlikeMessage onGodlikeMessage;
@@ -337,7 +339,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
337 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an 339 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an
338 /// ownerless phantom. 340 /// ownerless phantom.
339 /// 341 ///
340 /// All manipulation of this set has to occur under a lock 342 /// All manipulation of this set has to occur under an m_entityUpdates.SyncRoot lock
341 /// 343 ///
342 /// </value> 344 /// </value>
343 protected HashSet<uint> m_killRecord; 345 protected HashSet<uint> m_killRecord;
@@ -345,6 +347,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
345// protected HashSet<uint> m_attachmentsSent; 347// protected HashSet<uint> m_attachmentsSent;
346 348
347 private int m_moneyBalance; 349 private int m_moneyBalance;
350 private bool m_deliverPackets = true;
348 private int m_animationSequenceNumber = 1; 351 private int m_animationSequenceNumber = 1;
349 private bool m_SendLogoutPacketWhenClosing = true; 352 private bool m_SendLogoutPacketWhenClosing = true;
350 private AgentUpdateArgs lastarg; 353 private AgentUpdateArgs lastarg;
@@ -384,6 +387,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
384 get { return m_startpos; } 387 get { return m_startpos; }
385 set { m_startpos = value; } 388 set { m_startpos = value; }
386 } 389 }
390 public bool DeliverPackets
391 {
392 get { return m_deliverPackets; }
393 set {
394 m_deliverPackets = value;
395 m_udpClient.m_deliverPackets = value;
396 }
397 }
387 public UUID AgentId { get { return m_agentId; } } 398 public UUID AgentId { get { return m_agentId; } }
388 public ISceneAgent SceneAgent { get; private set; } 399 public ISceneAgent SceneAgent { get; private set; }
389 public UUID ActiveGroupId { get { return m_activeGroupID; } } 400 public UUID ActiveGroupId { get { return m_activeGroupID; } }
@@ -488,18 +499,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
488 499
489 #region Client Methods 500 #region Client Methods
490 501
502
491 /// <summary> 503 /// <summary>
492 /// Shut down the client view 504 /// Shut down the client view
493 /// </summary> 505 /// </summary>
494 public void Close() 506 public void Close()
495 { 507 {
508 Close(true);
509 }
510
511 /// <summary>
512 /// Shut down the client view
513 /// </summary>
514 public void Close(bool sendStop)
515 {
496 m_log.DebugFormat( 516 m_log.DebugFormat(
497 "[CLIENT]: Close has been called for {0} attached to scene {1}", 517 "[CLIENT]: Close has been called for {0} attached to scene {1}",
498 Name, m_scene.RegionInfo.RegionName); 518 Name, m_scene.RegionInfo.RegionName);
499 519
500 // Send the STOP packet 520 if (sendStop)
501 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator); 521 {
502 OutPacket(disable, ThrottleOutPacketType.Unknown); 522 // Send the STOP packet
523 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
524 OutPacket(disable, ThrottleOutPacketType.Unknown);
525 }
503 526
504 IsActive = false; 527 IsActive = false;
505 528
@@ -799,7 +822,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
799 reply.ChatData.OwnerID = fromAgentID; 822 reply.ChatData.OwnerID = fromAgentID;
800 reply.ChatData.SourceID = fromAgentID; 823 reply.ChatData.SourceID = fromAgentID;
801 824
802 OutPacket(reply, ThrottleOutPacketType.Task); 825 OutPacket(reply, ThrottleOutPacketType.Unknown);
803 } 826 }
804 827
805 /// <summary> 828 /// <summary>
@@ -1085,6 +1108,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1085 public virtual void SendLayerData(float[] map) 1108 public virtual void SendLayerData(float[] map)
1086 { 1109 {
1087 Util.FireAndForget(DoSendLayerData, map); 1110 Util.FireAndForget(DoSendLayerData, map);
1111
1112 // Send it sync, and async. It's not that much data
1113 // and it improves user experience just so much!
1114 DoSendLayerData(map);
1088 } 1115 }
1089 1116
1090 /// <summary> 1117 /// <summary>
@@ -1097,16 +1124,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1097 1124
1098 try 1125 try
1099 { 1126 {
1100 //for (int y = 0; y < 16; y++) 1127 for (int y = 0; y < 16; y++)
1101 //{ 1128 {
1102 // for (int x = 0; x < 16; x++) 1129 for (int x = 0; x < 16; x+=4)
1103 // { 1130 {
1104 // SendLayerData(x, y, map); 1131 SendLayerPacket(x, y, map);
1105 // } 1132 }
1106 //} 1133 }
1107
1108 // Send LayerData in a spiral pattern. Fun!
1109 SendLayerTopRight(map, 0, 0, 15, 15);
1110 } 1134 }
1111 catch (Exception e) 1135 catch (Exception e)
1112 { 1136 {
@@ -1114,51 +1138,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1114 } 1138 }
1115 } 1139 }
1116 1140
1117 private void SendLayerTopRight(float[] map, int x1, int y1, int x2, int y2)
1118 {
1119 // Row
1120 for (int i = x1; i <= x2; i++)
1121 SendLayerData(i, y1, map);
1122
1123 // Column
1124 for (int j = y1 + 1; j <= y2; j++)
1125 SendLayerData(x2, j, map);
1126
1127 if (x2 - x1 > 0)
1128 SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2);
1129 }
1130
1131 void SendLayerBottomLeft(float[] map, int x1, int y1, int x2, int y2)
1132 {
1133 // Row in reverse
1134 for (int i = x2; i >= x1; i--)
1135 SendLayerData(i, y2, map);
1136
1137 // Column in reverse
1138 for (int j = y2 - 1; j >= y1; j--)
1139 SendLayerData(x1, j, map);
1140
1141 if (x2 - x1 > 0)
1142 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
1143 }
1144
1145 /// <summary> 1141 /// <summary>
1146 /// Sends a set of four patches (x, x+1, ..., x+3) to the client 1142 /// Sends a set of four patches (x, x+1, ..., x+3) to the client
1147 /// </summary> 1143 /// </summary>
1148 /// <param name="map">heightmap</param> 1144 /// <param name="map">heightmap</param>
1149 /// <param name="px">X coordinate for patches 0..12</param> 1145 /// <param name="px">X coordinate for patches 0..12</param>
1150 /// <param name="py">Y coordinate for patches 0..15</param> 1146 /// <param name="py">Y coordinate for patches 0..15</param>
1151 // private void SendLayerPacket(float[] map, int y, int x) 1147 private void SendLayerPacket(int x, int y, float[] map)
1152 // { 1148 {
1153 // int[] patches = new int[4]; 1149 int[] patches = new int[4];
1154 // patches[0] = x + 0 + y * 16; 1150 patches[0] = x + 0 + y * 16;
1155 // patches[1] = x + 1 + y * 16; 1151 patches[1] = x + 1 + y * 16;
1156 // patches[2] = x + 2 + y * 16; 1152 patches[2] = x + 2 + y * 16;
1157 // patches[3] = x + 3 + y * 16; 1153 patches[3] = x + 3 + y * 16;
1158 1154
1159 // Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); 1155 float[] heightmap = (map.Length == 65536) ?
1160 // OutPacket(layerpack, ThrottleOutPacketType.Land); 1156 map :
1161 // } 1157 LLHeightFieldMoronize(map);
1158
1159 try
1160 {
1161 Packet layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1162 OutPacket(layerpack, ThrottleOutPacketType.Land);
1163 }
1164 catch
1165 {
1166 for (int px = x ; px < x + 4 ; px++)
1167 SendLayerData(px, y, map);
1168 }
1169 }
1162 1170
1163 /// <summary> 1171 /// <summary>
1164 /// Sends a specified patch to a client 1172 /// Sends a specified patch to a client
@@ -1178,7 +1186,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1178 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); 1186 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1179 layerpack.Header.Reliable = true; 1187 layerpack.Header.Reliable = true;
1180 1188
1181 OutPacket(layerpack, ThrottleOutPacketType.Land); 1189 OutPacket(layerpack, ThrottleOutPacketType.Task);
1182 } 1190 }
1183 catch (Exception e) 1191 catch (Exception e)
1184 { 1192 {
@@ -2302,6 +2310,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2302 OutPacket(sound, ThrottleOutPacketType.Task); 2310 OutPacket(sound, ThrottleOutPacketType.Task);
2303 } 2311 }
2304 2312
2313 public void SendTransferAbort(TransferRequestPacket transferRequest)
2314 {
2315 TransferAbortPacket abort = (TransferAbortPacket)PacketPool.Instance.GetPacket(PacketType.TransferAbort);
2316 abort.TransferInfo.TransferID = transferRequest.TransferInfo.TransferID;
2317 abort.TransferInfo.ChannelType = transferRequest.TransferInfo.ChannelType;
2318 m_log.Debug("[Assets] Aborting transfer; asset request failed");
2319 OutPacket(abort, ThrottleOutPacketType.Task);
2320 }
2321
2305 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain) 2322 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain)
2306 { 2323 {
2307 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger); 2324 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger);
@@ -2749,7 +2766,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2749 reply.Data.ParcelID = parcelID; 2766 reply.Data.ParcelID = parcelID;
2750 reply.Data.OwnerID = land.OwnerID; 2767 reply.Data.OwnerID = land.OwnerID;
2751 reply.Data.Name = Utils.StringToBytes(land.Name); 2768 reply.Data.Name = Utils.StringToBytes(land.Name);
2752 reply.Data.Desc = Utils.StringToBytes(land.Description); 2769 if (land != null && land.Description != null && land.Description != String.Empty)
2770 reply.Data.Desc = Utils.StringToBytes(land.Description.Substring(0, land.Description.Length > 254 ? 254: land.Description.Length));
2771 else
2772 reply.Data.Desc = new Byte[0];
2753 reply.Data.ActualArea = land.Area; 2773 reply.Data.ActualArea = land.Area;
2754 reply.Data.BillableArea = land.Area; // TODO: what is this? 2774 reply.Data.BillableArea = land.Area; // TODO: what is this?
2755 2775
@@ -3612,7 +3632,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3612 /// </summary> 3632 /// </summary>
3613 public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) 3633 public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
3614 { 3634 {
3615 //double priority = m_prioritizer.GetUpdatePriority(this, entity); 3635 if (entity is SceneObjectPart)
3636 {
3637 SceneObjectPart e = (SceneObjectPart)entity;
3638 SceneObjectGroup g = e.ParentGroup;
3639 if (g.RootPart.Shape.State > 30) // HUD
3640 if (g.OwnerID != AgentId)
3641 return; // Don't send updates for other people's HUDs
3642 }
3643
3616 uint priority = m_prioritizer.GetUpdatePriority(this, entity); 3644 uint priority = m_prioritizer.GetUpdatePriority(this, entity);
3617 3645
3618 lock (m_entityUpdates.SyncRoot) 3646 lock (m_entityUpdates.SyncRoot)
@@ -3679,211 +3707,230 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3679 3707
3680 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race 3708 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race
3681 // condition where a kill can be processed before an out-of-date update for the same object. 3709 // condition where a kill can be processed before an out-of-date update for the same object.
3682 lock (m_killRecord) 3710 float avgTimeDilation = 1.0f;
3711 IEntityUpdate iupdate;
3712 Int32 timeinqueue; // this is just debugging code & can be dropped later
3713
3714 while (updatesThisCall < maxUpdates)
3683 { 3715 {
3684 float avgTimeDilation = 1.0f; 3716 lock (m_entityUpdates.SyncRoot)
3685 IEntityUpdate iupdate; 3717 if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue))
3686 Int32 timeinqueue; // this is just debugging code & can be dropped later 3718 break;
3687
3688 while (updatesThisCall < maxUpdates)
3689 {
3690 lock (m_entityUpdates.SyncRoot)
3691 if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue))
3692 break;
3693 3719
3694 EntityUpdate update = (EntityUpdate)iupdate; 3720 EntityUpdate update = (EntityUpdate)iupdate;
3695 3721
3696 avgTimeDilation += update.TimeDilation; 3722 avgTimeDilation += update.TimeDilation;
3697 avgTimeDilation *= 0.5f; 3723 avgTimeDilation *= 0.5f;
3698 3724
3699 if (update.Entity is SceneObjectPart) 3725 if (update.Entity is SceneObjectPart)
3726 {
3727 SceneObjectPart part = (SceneObjectPart)update.Entity;
3728
3729 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3730 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3731 // safety measure.
3732 //
3733 // If a Linden Lab 1.23.5 client (and possibly later and earlier) receives an object update
3734 // after a kill, it will keep displaying the deleted object until relog. OpenSim currently performs
3735 // updates and kills on different threads with different scheduling strategies, hence this protection.
3736 //
3737 // This doesn't appear to apply to child prims - a client will happily ignore these updates
3738 // after the root prim has been deleted.
3739 lock (m_killRecord)
3700 { 3740 {
3701 SceneObjectPart part = (SceneObjectPart)update.Entity;
3702
3703 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3704 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3705 // safety measure.
3706 //
3707 // If a Linden Lab 1.23.5 client (and possibly later and earlier) receives an object update
3708 // after a kill, it will keep displaying the deleted object until relog. OpenSim currently performs
3709 // updates and kills on different threads with different scheduling strategies, hence this protection.
3710 //
3711 // This doesn't appear to apply to child prims - a client will happily ignore these updates
3712 // after the root prim has been deleted.
3713 if (m_killRecord.Contains(part.LocalId)) 3741 if (m_killRecord.Contains(part.LocalId))
3714 {
3715 // m_log.WarnFormat(
3716 // "[CLIENT]: Preventing update for prim with local id {0} after client for user {1} told it was deleted",
3717 // part.LocalId, Name);
3718 continue; 3742 continue;
3719 } 3743 if (m_killRecord.Contains(part.ParentGroup.RootPart.LocalId))
3720 3744 continue;
3721 if (part.ParentGroup.IsAttachment && m_disableFacelights) 3745 }
3746
3747 if (part.ParentGroup.IsDeleted)
3748 continue;
3749
3750 if (part.ParentGroup.IsAttachment)
3751 { // Someone else's HUD, why are we getting these?
3752 if (part.ParentGroup.OwnerID != AgentId &&
3753 part.ParentGroup.RootPart.Shape.State >= 30)
3754 continue;
3755 ScenePresence sp;
3756 // Owner is not in the sim, don't update it to
3757 // anyone
3758 if (!m_scene.TryGetScenePresence(part.OwnerID, out sp))
3759 continue;
3760
3761 List<SceneObjectGroup> atts = sp.GetAttachments();
3762 bool found = false;
3763 foreach (SceneObjectGroup att in atts)
3722 { 3764 {
3723 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand && 3765 if (att == part.ParentGroup)
3724 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
3725 { 3766 {
3726 part.Shape.LightEntry = false; 3767 found = true;
3768 break;
3727 } 3769 }
3728 } 3770 }
3771
3772 // It's an attachment of a valid avatar, but
3773 // doesn't seem to be attached, skip
3774 if (!found)
3775 continue;
3729 } 3776 }
3730 3777 if (part.ParentGroup.IsAttachment && m_disableFacelights)
3731 ++updatesThisCall;
3732
3733 #region UpdateFlags to packet type conversion
3734
3735 PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags;
3736
3737 bool canUseCompressed = true;
3738 bool canUseImproved = true;
3739
3740 // Compressed object updates only make sense for LL primitives
3741 if (!(update.Entity is SceneObjectPart))
3742 {
3743 canUseCompressed = false;
3744 }
3745
3746 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
3747 {
3748 canUseCompressed = false;
3749 canUseImproved = false;
3750 }
3751 else
3752 { 3778 {
3753 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) || 3779 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand &&
3754 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) || 3780 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
3755 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3756 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3757 { 3781 {
3758 canUseCompressed = false; 3782 part.Shape.LightEntry = false;
3759 }
3760
3761 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
3762 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3763 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
3764 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
3765 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
3766 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
3767 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
3768 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
3769 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
3770 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
3771 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
3772 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
3773 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
3774 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3775 {
3776 canUseImproved = false;
3777 } 3783 }
3778 } 3784 }
3779 3785 }
3780 #endregion UpdateFlags to packet type conversion 3786
3781 3787 ++updatesThisCall;
3782 #region Block Construction 3788
3783 3789 #region UpdateFlags to packet type conversion
3784 // TODO: Remove this once we can build compressed updates 3790
3791 PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags;
3792
3793 bool canUseCompressed = true;
3794 bool canUseImproved = true;
3795
3796 // Compressed object updates only make sense for LL primitives
3797 if (!(update.Entity is SceneObjectPart))
3798 {
3785 canUseCompressed = false; 3799 canUseCompressed = false;
3786 3800 }
3787 if (!canUseImproved && !canUseCompressed) 3801
3788 { 3802 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
3789 if (update.Entity is ScenePresence) 3803 {
3790 { 3804 canUseCompressed = false;
3791 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity)); 3805 canUseImproved = false;
3792 objectUpdates.Value.Add(update); 3806 }
3793 } 3807 else
3794 else 3808 {
3795 { 3809 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
3796 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId)); 3810 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
3797 objectUpdates.Value.Add(update); 3811 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3798 } 3812 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3799 }
3800 else if (!canUseImproved)
3801 { 3813 {
3802 compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags)); 3814 canUseCompressed = false;
3803 compressedUpdates.Value.Add(update);
3804 } 3815 }
3805 else 3816
3817 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
3818 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3819 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
3820 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
3821 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
3822 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
3823 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
3824 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
3825 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
3826 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
3827 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
3828 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
3829 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
3830 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3806 { 3831 {
3807 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId) 3832 canUseImproved = false;
3808 {
3809 // Self updates go into a special list
3810 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3811 terseAgentUpdates.Value.Add(update);
3812 }
3813 else
3814 {
3815 // Everything else goes here
3816 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3817 terseUpdates.Value.Add(update);
3818 }
3819 } 3833 }
3820
3821 #endregion Block Construction
3822 } 3834 }
3823
3824
3825 #region Packet Sending
3826 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f);
3827 3835
3828 if (terseAgentUpdateBlocks.IsValueCreated) 3836 #endregion UpdateFlags to packet type conversion
3829 {
3830 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
3831 3837
3832 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); 3838 #region Block Construction
3833 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3834 packet.RegionData.TimeDilation = timeDilation;
3835 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3836 3839
3837 for (int i = 0; i < blocks.Count; i++) 3840 // TODO: Remove this once we can build compressed updates
3838 packet.ObjectData[i] = blocks[i]; 3841 canUseCompressed = false;
3839 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
3840 OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseAgentUpdates.Value, oPacket); });
3841 }
3842 3842
3843 if (objectUpdateBlocks.IsValueCreated) 3843 if (!canUseImproved && !canUseCompressed)
3844 { 3844 {
3845 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value; 3845 if (update.Entity is ScenePresence)
3846 3846 {
3847 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); 3847 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
3848 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 3848 }
3849 packet.RegionData.TimeDilation = timeDilation; 3849 else
3850 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 3850 {
3851 3851 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3852 for (int i = 0; i < blocks.Count; i++) 3852 }
3853 packet.ObjectData[i] = blocks[i];
3854 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
3855 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(objectUpdates.Value, oPacket); });
3856 } 3853 }
3857 3854 else if (!canUseImproved)
3858 if (compressedUpdateBlocks.IsValueCreated)
3859 { 3855 {
3860 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value; 3856 compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
3861
3862 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
3863 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3864 packet.RegionData.TimeDilation = timeDilation;
3865 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
3866
3867 for (int i = 0; i < blocks.Count; i++)
3868 packet.ObjectData[i] = blocks[i];
3869 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
3870 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates.Value, oPacket); });
3871 } 3857 }
3872 3858 else
3873 if (terseUpdateBlocks.IsValueCreated)
3874 { 3859 {
3875 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value; 3860 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId)
3876 3861 // Self updates go into a special list
3877 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); 3862 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3878 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 3863 else
3879 packet.RegionData.TimeDilation = timeDilation; 3864 // Everything else goes here
3880 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 3865 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3881
3882 for (int i = 0; i < blocks.Count; i++)
3883 packet.ObjectData[i] = blocks[i];
3884 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
3885 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); });
3886 } 3866 }
3867
3868 #endregion Block Construction
3869 }
3870
3871 #region Packet Sending
3872
3873 const float TIME_DILATION = 1.0f;
3874 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f);
3875
3876 if (terseAgentUpdateBlocks.IsValueCreated)
3877 {
3878 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
3879
3880 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3881 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3882 packet.RegionData.TimeDilation = timeDilation;
3883 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3884
3885 for (int i = 0; i < blocks.Count; i++)
3886 packet.ObjectData[i] = blocks[i];
3887
3888 OutPacket(packet, ThrottleOutPacketType.Unknown, true);
3889 }
3890
3891 if (objectUpdateBlocks.IsValueCreated)
3892 {
3893 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
3894
3895 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3896 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3897 packet.RegionData.TimeDilation = timeDilation;
3898 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3899
3900 for (int i = 0; i < blocks.Count; i++)
3901 packet.ObjectData[i] = blocks[i];
3902
3903 OutPacket(packet, ThrottleOutPacketType.Task, true);
3904 }
3905
3906 if (compressedUpdateBlocks.IsValueCreated)
3907 {
3908 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
3909
3910 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
3911 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3912 packet.RegionData.TimeDilation = timeDilation;
3913 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
3914
3915 for (int i = 0; i < blocks.Count; i++)
3916 packet.ObjectData[i] = blocks[i];
3917
3918 OutPacket(packet, ThrottleOutPacketType.Task, true);
3919 }
3920
3921 if (terseUpdateBlocks.IsValueCreated)
3922 {
3923 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
3924
3925 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3926 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3927 packet.RegionData.TimeDilation = timeDilation;
3928 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3929
3930 for (int i = 0; i < blocks.Count; i++)
3931 packet.ObjectData[i] = blocks[i];
3932
3933 OutPacket(packet, ThrottleOutPacketType.Task, true);
3887 } 3934 }
3888 3935
3889 #endregion Packet Sending 3936 #endregion Packet Sending
@@ -4176,11 +4223,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4176 4223
4177 // Pass in the delegate so that if this packet needs to be resent, we send the current properties 4224 // Pass in the delegate so that if this packet needs to be resent, we send the current properties
4178 // of the object rather than the properties when the packet was created 4225 // of the object rather than the properties when the packet was created
4179 OutPacket(packet, ThrottleOutPacketType.Task, true, 4226 // HACK : Remove intelligent resending until it's fixed in core
4180 delegate(OutgoingPacket oPacket) 4227 //OutPacket(packet, ThrottleOutPacketType.Task, true,
4181 { 4228 // delegate(OutgoingPacket oPacket)
4182 ResendPropertyUpdates(updates, oPacket); 4229 // {
4183 }); 4230 // ResendPropertyUpdates(updates, oPacket);
4231 // });
4232 OutPacket(packet, ThrottleOutPacketType.Task, true);
4184 4233
4185 // pbcnt += blocks.Count; 4234 // pbcnt += blocks.Count;
4186 // ppcnt++; 4235 // ppcnt++;
@@ -4206,11 +4255,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4206 // of the object rather than the properties when the packet was created 4255 // of the object rather than the properties when the packet was created
4207 List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>(); 4256 List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>();
4208 updates.Add(familyUpdates.Value[i]); 4257 updates.Add(familyUpdates.Value[i]);
4209 OutPacket(packet, ThrottleOutPacketType.Task, true, 4258 // HACK : Remove intelligent resending until it's fixed in core
4210 delegate(OutgoingPacket oPacket) 4259 //OutPacket(packet, ThrottleOutPacketType.Task, true,
4211 { 4260 // delegate(OutgoingPacket oPacket)
4212 ResendPropertyUpdates(updates, oPacket); 4261 // {
4213 }); 4262 // ResendPropertyUpdates(updates, oPacket);
4263 // });
4264 OutPacket(packet, ThrottleOutPacketType.Task, true);
4214 4265
4215 // fpcnt++; 4266 // fpcnt++;
4216 // fbcnt++; 4267 // fbcnt++;
@@ -4359,37 +4410,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4359 if (bl[i].BannedUserID == UUID.Zero) 4410 if (bl[i].BannedUserID == UUID.Zero)
4360 continue; 4411 continue;
4361 BannedUsers.Add(bl[i].BannedUserID); 4412 BannedUsers.Add(bl[i].BannedUserID);
4362 }
4363 4413
4364 EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); 4414 if (BannedUsers.Count >= 50 || (i == (bl.Length - 1) && BannedUsers.Count > 0))
4365 packet.AgentData.TransactionID = UUID.Random(); 4415 {
4366 packet.AgentData.AgentID = AgentId; 4416 EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket();
4367 packet.AgentData.SessionID = SessionId; 4417 packet.AgentData.TransactionID = UUID.Random();
4368 packet.MethodData.Invoice = invoice; 4418 packet.AgentData.AgentID = AgentId;
4369 packet.MethodData.Method = Utils.StringToBytes("setaccess"); 4419 packet.AgentData.SessionID = SessionId;
4420 packet.MethodData.Invoice = invoice;
4421 packet.MethodData.Method = Utils.StringToBytes("setaccess");
4370 4422
4371 EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + BannedUsers.Count]; 4423 EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + BannedUsers.Count];
4372 4424
4373 for (int i = 0; i < (6 + BannedUsers.Count); i++) 4425 int j;
4374 { 4426 for (j = 0; j < (6 + BannedUsers.Count); j++)
4375 returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); 4427 {
4376 } 4428 returnblock[j] = new EstateOwnerMessagePacket.ParamListBlock();
4377 int j = 0; 4429 }
4430 j = 0;
4378 4431
4379 returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; 4432 returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++;
4380 returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++; 4433 returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++;
4381 returnblock[j].Parameter = Utils.StringToBytes("0"); j++; 4434 returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
4382 returnblock[j].Parameter = Utils.StringToBytes("0"); j++; 4435 returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
4383 returnblock[j].Parameter = Utils.StringToBytes(BannedUsers.Count.ToString()); j++; 4436 returnblock[j].Parameter = Utils.StringToBytes(BannedUsers.Count.ToString()); j++;
4384 returnblock[j].Parameter = Utils.StringToBytes("0"); j++; 4437 returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
4385 4438
4386 foreach (UUID banned in BannedUsers) 4439 foreach (UUID banned in BannedUsers)
4387 { 4440 {
4388 returnblock[j].Parameter = banned.GetBytes(); j++; 4441 returnblock[j].Parameter = banned.GetBytes(); j++;
4442 }
4443 packet.ParamList = returnblock;
4444 packet.Header.Reliable = true;
4445 OutPacket(packet, ThrottleOutPacketType.Task);
4446
4447 BannedUsers.Clear();
4448 }
4389 } 4449 }
4390 packet.ParamList = returnblock; 4450
4391 packet.Header.Reliable = false;
4392 OutPacket(packet, ThrottleOutPacketType.Task);
4393 } 4451 }
4394 4452
4395 public void SendRegionInfoToEstateMenu(RegionInfoForEstateMenuArgs args) 4453 public void SendRegionInfoToEstateMenu(RegionInfoForEstateMenuArgs args)
@@ -4575,7 +4633,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4575 4633
4576 if (landData.SimwideArea > 0) 4634 if (landData.SimwideArea > 0)
4577 { 4635 {
4578 int simulatorCapacity = (int)(((float)landData.SimwideArea / 65536.0f) * (float)m_scene.RegionInfo.ObjectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); 4636 int simulatorCapacity = (int)((long)landData.SimwideArea * (long)m_scene.RegionInfo.ObjectCapacity * (long)m_scene.RegionInfo.RegionSettings.ObjectBonus / 65536L);
4637 // Never report more than sim total capacity
4638 if (simulatorCapacity > m_scene.RegionInfo.ObjectCapacity)
4639 simulatorCapacity = m_scene.RegionInfo.ObjectCapacity;
4579 updateMessage.SimWideMaxPrims = simulatorCapacity; 4640 updateMessage.SimWideMaxPrims = simulatorCapacity;
4580 } 4641 }
4581 else 4642 else
@@ -4704,14 +4765,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4704 4765
4705 if (notifyCount > 0) 4766 if (notifyCount > 0)
4706 { 4767 {
4707 if (notifyCount > 32) 4768// if (notifyCount > 32)
4708 { 4769// {
4709 m_log.InfoFormat( 4770// m_log.InfoFormat(
4710 "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}" 4771// "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}"
4711 + " - a developer might want to investigate whether this is a hard limit", 32); 4772// + " - a developer might want to investigate whether this is a hard limit", 32);
4712 4773//
4713 notifyCount = 32; 4774// notifyCount = 32;
4714 } 4775// }
4715 4776
4716 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock 4777 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock
4717 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount]; 4778 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount];
@@ -5244,6 +5305,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5244 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false); 5305 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false);
5245 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false); 5306 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false);
5246 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode); 5307 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode);
5308 AddLocalPacketHandler(PacketType.CreateNewOutfitAttachments, HandleCreateNewOutfitAttachments);
5247 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false); 5309 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false);
5248 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents); 5310 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents);
5249 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery); 5311 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery);
@@ -5310,6 +5372,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5310 AddLocalPacketHandler(PacketType.GroupVoteHistoryRequest, HandleGroupVoteHistoryRequest); 5372 AddLocalPacketHandler(PacketType.GroupVoteHistoryRequest, HandleGroupVoteHistoryRequest);
5311 AddLocalPacketHandler(PacketType.SimWideDeletes, HandleSimWideDeletes); 5373 AddLocalPacketHandler(PacketType.SimWideDeletes, HandleSimWideDeletes);
5312 AddLocalPacketHandler(PacketType.SendPostcard, HandleSendPostcard); 5374 AddLocalPacketHandler(PacketType.SendPostcard, HandleSendPostcard);
5375 AddLocalPacketHandler(PacketType.ChangeInventoryItemFlags, HandleChangeInventoryItemFlags);
5313 5376
5314 AddGenericPacketHandler("autopilot", HandleAutopilot); 5377 AddGenericPacketHandler("autopilot", HandleAutopilot);
5315 } 5378 }
@@ -5345,6 +5408,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5345 (x.CameraLeftAxis != lastarg.CameraLeftAxis) || 5408 (x.CameraLeftAxis != lastarg.CameraLeftAxis) ||
5346 (x.CameraUpAxis != lastarg.CameraUpAxis) || 5409 (x.CameraUpAxis != lastarg.CameraUpAxis) ||
5347 (x.ControlFlags != lastarg.ControlFlags) || 5410 (x.ControlFlags != lastarg.ControlFlags) ||
5411 (x.ControlFlags != 0) ||
5348 (x.Far != lastarg.Far) || 5412 (x.Far != lastarg.Far) ||
5349 (x.Flags != lastarg.Flags) || 5413 (x.Flags != lastarg.Flags) ||
5350 (x.State != lastarg.State) || 5414 (x.State != lastarg.State) ||
@@ -5722,7 +5786,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5722 args.Channel = ch; 5786 args.Channel = ch;
5723 args.From = String.Empty; 5787 args.From = String.Empty;
5724 args.Message = Utils.BytesToString(msg); 5788 args.Message = Utils.BytesToString(msg);
5725 args.Type = ChatTypeEnum.Shout; 5789 args.Type = ChatTypeEnum.Region; //Behaviour in SL is that the response can be heard from any distance
5726 args.Position = new Vector3(); 5790 args.Position = new Vector3();
5727 args.Scene = Scene; 5791 args.Scene = Scene;
5728 args.Sender = this; 5792 args.Sender = this;
@@ -9760,7 +9824,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9760 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID, 9824 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID,
9761 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName), 9825 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName),
9762 UpdateMuteListEntry.MuteData.MuteType, 9826 UpdateMuteListEntry.MuteData.MuteType,
9763 UpdateMuteListEntry.AgentData.AgentID); 9827 UpdateMuteListEntry.MuteData.MuteFlags);
9764 return true; 9828 return true;
9765 } 9829 }
9766 return false; 9830 return false;
@@ -9775,8 +9839,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9775 { 9839 {
9776 handlerRemoveMuteListEntry(this, 9840 handlerRemoveMuteListEntry(this,
9777 RemoveMuteListEntry.MuteData.MuteID, 9841 RemoveMuteListEntry.MuteData.MuteID,
9778 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName), 9842 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName));
9779 RemoveMuteListEntry.AgentData.AgentID);
9780 return true; 9843 return true;
9781 } 9844 }
9782 return false; 9845 return false;
@@ -9820,10 +9883,55 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9820 return false; 9883 return false;
9821 } 9884 }
9822 9885
9886 private bool HandleChangeInventoryItemFlags(IClientAPI client, Packet packet)
9887 {
9888 ChangeInventoryItemFlagsPacket ChangeInventoryItemFlags =
9889 (ChangeInventoryItemFlagsPacket)packet;
9890 ChangeInventoryItemFlags handlerChangeInventoryItemFlags = OnChangeInventoryItemFlags;
9891 if (handlerChangeInventoryItemFlags != null)
9892 {
9893 foreach(ChangeInventoryItemFlagsPacket.InventoryDataBlock b in ChangeInventoryItemFlags.InventoryData)
9894 handlerChangeInventoryItemFlags(this, b.ItemID, b.Flags);
9895 return true;
9896 }
9897 return false;
9898 }
9899
9823 private bool HandleUseCircuitCode(IClientAPI sender, Packet Pack) 9900 private bool HandleUseCircuitCode(IClientAPI sender, Packet Pack)
9824 { 9901 {
9825 return true; 9902 return true;
9826 } 9903 }
9904
9905 private bool HandleCreateNewOutfitAttachments(IClientAPI sender, Packet Pack)
9906 {
9907 CreateNewOutfitAttachmentsPacket packet = (CreateNewOutfitAttachmentsPacket)Pack;
9908
9909 #region Packet Session and User Check
9910 if (m_checkPackets)
9911 {
9912 if (packet.AgentData.SessionID != SessionId ||
9913 packet.AgentData.AgentID != AgentId)
9914 return true;
9915 }
9916 #endregion
9917 MoveItemsAndLeaveCopy handlerMoveItemsAndLeaveCopy = null;
9918 List<InventoryItemBase> items = new List<InventoryItemBase>();
9919 foreach (CreateNewOutfitAttachmentsPacket.ObjectDataBlock n in packet.ObjectData)
9920 {
9921 InventoryItemBase b = new InventoryItemBase();
9922 b.ID = n.OldItemID;
9923 b.Folder = n.OldFolderID;
9924 items.Add(b);
9925 }
9926
9927 handlerMoveItemsAndLeaveCopy = OnMoveItemsAndLeaveCopy;
9928 if (handlerMoveItemsAndLeaveCopy != null)
9929 {
9930 handlerMoveItemsAndLeaveCopy(this, items, packet.HeaderData.NewFolderID);
9931 }
9932
9933 return true;
9934 }
9827 9935
9828 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack) 9936 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack)
9829 { 9937 {
@@ -10250,6 +10358,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10250 groupProfileReply.GroupData.MaturePublish = d.MaturePublish; 10358 groupProfileReply.GroupData.MaturePublish = d.MaturePublish;
10251 groupProfileReply.GroupData.OwnerRole = d.OwnerRole; 10359 groupProfileReply.GroupData.OwnerRole = d.OwnerRole;
10252 10360
10361 Scene scene = (Scene)m_scene;
10362 if (scene.Permissions.IsGod(sender.AgentId) && (!sender.IsGroupMember(groupProfileRequest.GroupData.GroupID)))
10363 {
10364 ScenePresence p;
10365 if (scene.TryGetScenePresence(sender.AgentId, out p))
10366 {
10367 if (p.GodLevel >= 200)
10368 {
10369 groupProfileReply.GroupData.OpenEnrollment = true;
10370 groupProfileReply.GroupData.MembershipFee = 0;
10371 }
10372 }
10373 }
10374
10253 OutPacket(groupProfileReply, ThrottleOutPacketType.Task); 10375 OutPacket(groupProfileReply, ThrottleOutPacketType.Task);
10254 } 10376 }
10255 return true; 10377 return true;
@@ -10823,11 +10945,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10823 10945
10824 StartLure handlerStartLure = OnStartLure; 10946 StartLure handlerStartLure = OnStartLure;
10825 if (handlerStartLure != null) 10947 if (handlerStartLure != null)
10826 handlerStartLure(startLureRequest.Info.LureType, 10948 {
10827 Utils.BytesToString( 10949 for (int i = 0 ; i < startLureRequest.TargetData.Length ; i++)
10828 startLureRequest.Info.Message), 10950 {
10829 startLureRequest.TargetData[0].TargetID, 10951 handlerStartLure(startLureRequest.Info.LureType,
10830 this); 10952 Utils.BytesToString(
10953 startLureRequest.Info.Message),
10954 startLureRequest.TargetData[i].TargetID,
10955 this);
10956 }
10957 }
10831 return true; 10958 return true;
10832 } 10959 }
10833 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack) 10960 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack)
@@ -10941,10 +11068,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10941 } 11068 }
10942 #endregion 11069 #endregion
10943 11070
10944 ClassifiedDelete handlerClassifiedGodDelete = OnClassifiedGodDelete; 11071 ClassifiedGodDelete handlerClassifiedGodDelete = OnClassifiedGodDelete;
10945 if (handlerClassifiedGodDelete != null) 11072 if (handlerClassifiedGodDelete != null)
10946 handlerClassifiedGodDelete( 11073 handlerClassifiedGodDelete(
10947 classifiedGodDelete.Data.ClassifiedID, 11074 classifiedGodDelete.Data.ClassifiedID,
11075 classifiedGodDelete.Data.QueryID,
10948 this); 11076 this);
10949 return true; 11077 return true;
10950 } 11078 }
@@ -11988,7 +12116,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11988 12116
11989// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID); 12117// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID);
11990 12118
12119
12120 //Note, the bool returned from the below function is useless since it is always false.
11991 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived); 12121 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived);
12122
11992 } 12123 }
11993 12124
11994 /// <summary> 12125 /// <summary>
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
index ffa3be4..ae72175 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
@@ -158,6 +158,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
158 158
159 private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC 159 private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC
160 private int m_maxRTO = 60000; 160 private int m_maxRTO = 60000;
161 public bool m_deliverPackets = true;
161 162
162 /// <summary> 163 /// <summary>
163 /// Default constructor 164 /// Default constructor
@@ -439,6 +440,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
439 if (category >= 0 && category < m_packetOutboxes.Length) 440 if (category >= 0 && category < m_packetOutboxes.Length)
440 { 441 {
441 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category]; 442 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category];
443
444 if (m_deliverPackets == false)
445 {
446 queue.Enqueue(packet);
447 return true;
448 }
449
442 TokenBucket bucket = m_throttleCategories[category]; 450 TokenBucket bucket = m_throttleCategories[category];
443 451
444 // Don't send this packet if there is already a packet waiting in the queue 452 // Don't send this packet if there is already a packet waiting in the queue
@@ -488,7 +496,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
488 /// <returns>True if any packets were sent, otherwise false</returns> 496 /// <returns>True if any packets were sent, otherwise false</returns>
489 public bool DequeueOutgoing() 497 public bool DequeueOutgoing()
490 { 498 {
491 OutgoingPacket packet; 499 if (m_deliverPackets == false) return false;
500
501 OutgoingPacket packet = null;
492 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue; 502 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue;
493 TokenBucket bucket; 503 TokenBucket bucket;
494 bool packetSent = false; 504 bool packetSent = false;
@@ -520,32 +530,49 @@ namespace OpenSim.Region.ClientStack.LindenUDP
520 // No dequeued packet waiting to be sent, try to pull one off 530 // No dequeued packet waiting to be sent, try to pull one off
521 // this queue 531 // this queue
522 queue = m_packetOutboxes[i]; 532 queue = m_packetOutboxes[i];
523 if (queue.Dequeue(out packet)) 533 if (queue != null)
524 { 534 {
525 // A packet was pulled off the queue. See if we have 535 bool success = false;
526 // enough tokens in the bucket to send it out 536 try
527 if (bucket.RemoveTokens(packet.Buffer.DataLength))
528 { 537 {
529 // Send the packet 538 success = queue.Dequeue(out packet);
530 m_udpServer.SendPacketFinal(packet);
531 packetSent = true;
532 } 539 }
533 else 540 catch
534 { 541 {
535 // Save the dequeued packet for the next iteration 542 m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>();
536 m_nextPackets[i] = packet;
537 } 543 }
538 544 if (success)
539 // If the queue is empty after this dequeue, fire the queue 545 {
540 // empty callback now so it has a chance to fill before we 546 // A packet was pulled off the queue. See if we have
541 // get back here 547 // enough tokens in the bucket to send it out
542 if (queue.Count == 0) 548 if (bucket.RemoveTokens(packet.Buffer.DataLength))
549 {
550 // Send the packet
551 m_udpServer.SendPacketFinal(packet);
552 packetSent = true;
553 }
554 else
555 {
556 // Save the dequeued packet for the next iteration
557 m_nextPackets[i] = packet;
558 }
559
560 // If the queue is empty after this dequeue, fire the queue
561 // empty callback now so it has a chance to fill before we
562 // get back here
563 if (queue.Count == 0)
564 emptyCategories |= CategoryToFlag(i);
565 }
566 else
567 {
568 // No packets in this queue. Fire the queue empty callback
569 // if it has not been called recently
543 emptyCategories |= CategoryToFlag(i); 570 emptyCategories |= CategoryToFlag(i);
571 }
544 } 572 }
545 else 573 else
546 { 574 {
547 // No packets in this queue. Fire the queue empty callback 575 m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>();
548 // if it has not been called recently
549 emptyCategories |= CategoryToFlag(i); 576 emptyCategories |= CategoryToFlag(i);
550 } 577 }
551 } 578 }
@@ -703,4 +730,4 @@ namespace OpenSim.Region.ClientStack.LindenUDP
703 } 730 }
704 } 731 }
705 } 732 }
706} \ No newline at end of file 733}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index 7b1aa2c..3139112 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -1031,7 +1031,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1031 if (m_scene.TryGetClient(udpClient.AgentID, out client)) 1031 if (m_scene.TryGetClient(udpClient.AgentID, out client))
1032 { 1032 {
1033 client.IsLoggingOut = true; 1033 client.IsLoggingOut = true;
1034 client.Close(); 1034 client.Close(false);
1035 } 1035 }
1036 } 1036 }
1037 1037
@@ -1043,6 +1043,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1043 1043
1044 while (base.IsRunning) 1044 while (base.IsRunning)
1045 { 1045 {
1046 m_scene.ThreadAlive(1);
1046 try 1047 try
1047 { 1048 {
1048 IncomingPacket incomingPacket = null; 1049 IncomingPacket incomingPacket = null;
@@ -1085,6 +1086,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1085 1086
1086 while (base.IsRunning) 1087 while (base.IsRunning)
1087 { 1088 {
1089 m_scene.ThreadAlive(2);
1088 try 1090 try
1089 { 1091 {
1090 m_packetSent = false; 1092 m_packetSent = false;
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index 039379d..cfe7c9d 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -100,10 +100,6 @@ namespace OpenMetaverse
100 const int SIO_UDP_CONNRESET = -1744830452; 100 const int SIO_UDP_CONNRESET = -1744830452;
101 101
102 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort); 102 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort);
103
104 m_log.DebugFormat(
105 "[UDPBASE]: Binding UDP listener using internal IP address config {0}:{1}",
106 ipep.Address, ipep.Port);
107 103
108 m_udpSocket = new Socket( 104 m_udpSocket = new Socket(
109 AddressFamily.InterNetwork, 105 AddressFamily.InterNetwork,
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
index ec4dfd0..4cedfe6 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.IO; 29using System.IO;
30using System.Reflection; 30using System.Reflection;
31using System.Collections.Generic;
31using log4net; 32using log4net;
32using OpenMetaverse; 33using OpenMetaverse;
33using OpenSim.Framework; 34using OpenSim.Framework;
@@ -38,6 +39,13 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
38{ 39{
39 public class AssetXferUploader 40 public class AssetXferUploader
40 { 41 {
42 // Viewer's notion of the default texture
43 private List<UUID> defaultIDs = new List<UUID> {
44 new UUID("5748decc-f629-461c-9a36-a35a221fe21f"),
45 new UUID("7ca39b4c-bd19-4699-aff7-f93fd03d3e7b"),
46 new UUID("6522e74d-1660-4e7f-b601-6f48c1659a77"),
47 new UUID("c228d1cf-4b5d-4ba8-84f4-899a0796aa97")
48 };
41 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
42 50
43 /// <summary> 51 /// <summary>
@@ -65,6 +73,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
65 private UUID TransactionID = UUID.Zero; 73 private UUID TransactionID = UUID.Zero;
66 private sbyte type = 0; 74 private sbyte type = 0;
67 private byte wearableType = 0; 75 private byte wearableType = 0;
76 private byte[] m_oldData = null;
68 public ulong XferID; 77 public ulong XferID;
69 private Scene m_Scene; 78 private Scene m_Scene;
70 79
@@ -302,6 +311,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
302 311
303 private void DoCreateItem(uint callbackID) 312 private void DoCreateItem(uint callbackID)
304 { 313 {
314 ValidateAssets();
305 m_Scene.AssetService.Store(m_asset); 315 m_Scene.AssetService.Store(m_asset);
306 316
307 InventoryItemBase item = new InventoryItemBase(); 317 InventoryItemBase item = new InventoryItemBase();
@@ -322,12 +332,84 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
322 item.Flags = (uint) wearableType; 332 item.Flags = (uint) wearableType;
323 item.CreationDate = Util.UnixTimeSinceEpoch(); 333 item.CreationDate = Util.UnixTimeSinceEpoch();
324 334
335 m_log.DebugFormat("[XFER]: Created item {0} with asset {1}",
336 item.ID, item.AssetID);
337
325 if (m_Scene.AddInventoryItem(item)) 338 if (m_Scene.AddInventoryItem(item))
326 ourClient.SendInventoryItemCreateUpdate(item, callbackID); 339 ourClient.SendInventoryItemCreateUpdate(item, callbackID);
327 else 340 else
328 ourClient.SendAlertMessage("Unable to create inventory item"); 341 ourClient.SendAlertMessage("Unable to create inventory item");
329 } 342 }
330 343
344 private void ValidateAssets()
345 {
346 if (m_asset.Type == (sbyte)AssetType.Clothing ||
347 m_asset.Type == (sbyte)AssetType.Bodypart)
348 {
349 string content = System.Text.Encoding.ASCII.GetString(m_asset.Data);
350 string[] lines = content.Split(new char[] {'\n'});
351
352 List<string> validated = new List<string>();
353
354 Dictionary<int, UUID> allowed = ExtractTexturesFromOldData();
355
356 int textures = 0;
357
358 foreach (string line in lines)
359 {
360 try
361 {
362 if (line.StartsWith("textures "))
363 {
364 textures = Convert.ToInt32(line.Substring(9));
365 validated.Add(line);
366 }
367 else if (textures > 0)
368 {
369 string[] parts = line.Split(new char[] {' '});
370
371 UUID tx = new UUID(parts[1]);
372 int id = Convert.ToInt32(parts[0]);
373
374 if (defaultIDs.Contains(tx) || tx == UUID.Zero ||
375 (allowed.ContainsKey(id) && allowed[id] == tx))
376 {
377 validated.Add(parts[0] + " " + tx.ToString());
378 }
379 else
380 {
381 int perms = m_Scene.InventoryService.GetAssetPermissions(ourClient.AgentId, tx);
382 int full = (int)(PermissionMask.Modify | PermissionMask.Transfer | PermissionMask.Copy);
383
384 if ((perms & full) != full)
385 {
386 m_log.ErrorFormat("[ASSET UPLOADER]: REJECTED update with texture {0} from {1} because they do not own the texture", tx, ourClient.AgentId);
387 validated.Add(parts[0] + " " + UUID.Zero.ToString());
388 }
389 else
390 {
391 validated.Add(line);
392 }
393 }
394 textures--;
395 }
396 else
397 {
398 validated.Add(line);
399 }
400 }
401 catch
402 {
403 // If it's malformed, skip it
404 }
405 }
406
407 string final = String.Join("\n", validated.ToArray());
408
409 m_asset.Data = System.Text.Encoding.ASCII.GetBytes(final);
410 }
411 }
412
331 /// <summary> 413 /// <summary>
332 /// Get the asset data uploaded in this transfer. 414 /// Get the asset data uploaded in this transfer.
333 /// </summary> 415 /// </summary>
@@ -336,10 +418,55 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
336 { 418 {
337 if (m_finished) 419 if (m_finished)
338 { 420 {
421 ValidateAssets();
339 return m_asset; 422 return m_asset;
340 } 423 }
341 424
342 return null; 425 return null;
343 } 426 }
427
428 public void SetOldData(byte[] d)
429 {
430 m_oldData = d;
431 }
432
433 private Dictionary<int,UUID> ExtractTexturesFromOldData()
434 {
435 Dictionary<int,UUID> result = new Dictionary<int,UUID>();
436 if (m_oldData == null)
437 return result;
438
439 string content = System.Text.Encoding.ASCII.GetString(m_oldData);
440 string[] lines = content.Split(new char[] {'\n'});
441
442 int textures = 0;
443
444 foreach (string line in lines)
445 {
446 try
447 {
448 if (line.StartsWith("textures "))
449 {
450 textures = Convert.ToInt32(line.Substring(9));
451 }
452 else if (textures > 0)
453 {
454 string[] parts = line.Split(new char[] {' '});
455
456 UUID tx = new UUID(parts[1]);
457 int id = Convert.ToInt32(parts[0]);
458 result[id] = tx;
459 textures--;
460 }
461 }
462 catch
463 {
464 // If it's malformed, skip it
465 }
466 }
467
468 return result;
469 }
344 } 470 }
345} 471}
472
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index 22c301b..8e2dba4 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -257,53 +257,66 @@ namespace Flotsam.RegionModules.AssetCache
257 257
258 private void UpdateFileCache(string key, AssetBase asset) 258 private void UpdateFileCache(string key, AssetBase asset)
259 { 259 {
260 string filename = GetFileName(asset.ID); 260 // TODO: Spawn this off to some seperate thread to do the actual writing
261 261 if (asset != null)
262 try
263 { 262 {
264 // If the file is already cached, don't cache it, just touch it so access time is updated 263 string filename = GetFileName(key);
265 if (File.Exists(filename)) 264
266 { 265 try
267 File.SetLastAccessTime(filename, DateTime.Now);
268 }
269 else
270 { 266 {
271 // Once we start writing, make sure we flag that we're writing 267 // If the file is already cached, don't cache it, just touch it so access time is updated
272 // that object to the cache so that we don't try to write the 268 if (File.Exists(filename))
273 // same file multiple times.
274 lock (m_CurrentlyWriting)
275 { 269 {
276#if WAIT_ON_INPROGRESS_REQUESTS 270 // We don't really want to know about sharing
277 if (m_CurrentlyWriting.ContainsKey(filename)) 271 // violations here. If the file is locked, then
272 // the other thread has updated the time for us.
273 try
278 { 274 {
279 return; 275 File.SetLastAccessTime(filename, DateTime.Now);
280 } 276 }
281 else 277 catch
282 {
283 m_CurrentlyWriting.Add(filename, new ManualResetEvent(false));
284 }
285
286#else
287 if (m_CurrentlyWriting.Contains(filename))
288 { 278 {
289 return;
290 } 279 }
291 else 280 } else {
281
282 // Once we start writing, make sure we flag that we're writing
283 // that object to the cache so that we don't try to write the
284 // same file multiple times.
285 lock (m_CurrentlyWriting)
292 { 286 {
293 m_CurrentlyWriting.Add(filename); 287#if WAIT_ON_INPROGRESS_REQUESTS
294 } 288 if (m_CurrentlyWriting.ContainsKey(filename))
289 {
290 return;
291 }
292 else
293 {
294 m_CurrentlyWriting.Add(filename, new ManualResetEvent(false));
295 }
296
297#else
298 if (m_CurrentlyWriting.Contains(filename))
299 {
300 return;
301 }
302 else
303 {
304 m_CurrentlyWriting.Add(filename);
305 }
295#endif 306#endif
296 }
297 307
298 Util.FireAndForget( 308 }
299 delegate { WriteFileCache(filename, asset); }); 309
310 Util.FireAndForget(
311 delegate { WriteFileCache(filename, asset); });
312 }
313 }
314 catch (Exception e)
315 {
316 m_log.ErrorFormat(
317 "[FLOTSAM ASSET CACHE]: Failed to update cache for asset {0}. Exception {1} {2}",
318 asset.ID, e.Message, e.StackTrace);
300 } 319 }
301 }
302 catch (Exception e)
303 {
304 m_log.ErrorFormat(
305 "[FLOTSAM ASSET CACHE]: Failed to update cache for asset {0}. Exception {1} {2}",
306 asset.ID, e.Message, e.StackTrace);
307 } 320 }
308 } 321 }
309 322
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 7086e6c..5ca2ce4 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using System.Xml;
31using log4net; 32using log4net;
32using Mono.Addins; 33using Mono.Addins;
33using Nini.Config; 34using Nini.Config;
@@ -38,6 +39,7 @@ using OpenSim.Region.Framework;
38using OpenSim.Region.Framework.Interfaces; 39using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
40using OpenSim.Region.Framework.Scenes.Serialization; 41using OpenSim.Region.Framework.Scenes.Serialization;
42using OpenSim.Services.Interfaces;
41 43
42namespace OpenSim.Region.CoreModules.Avatar.Attachments 44namespace OpenSim.Region.CoreModules.Avatar.Attachments
43{ 45{
@@ -115,6 +117,40 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
115 117
116// m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing any attachments for {0}", sp.Name); 118// m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing any attachments for {0}", sp.Name);
117 119
120 XmlDocument doc = new XmlDocument();
121 string stateData = String.Empty;
122
123 IAttachmentsService attServ = m_scene.RequestModuleInterface<IAttachmentsService>();
124 if (attServ != null)
125 {
126 m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service");
127 stateData = attServ.Get(sp.UUID.ToString());
128 if (stateData != String.Empty)
129 {
130 try
131 {
132 doc.LoadXml(stateData);
133 }
134 catch { }
135 }
136 }
137
138 Dictionary<UUID, string> itemData = new Dictionary<UUID, string>();
139
140 XmlNodeList nodes = doc.GetElementsByTagName("Attachment");
141 if (nodes.Count > 0)
142 {
143 foreach (XmlNode n in nodes)
144 {
145 XmlElement elem = (XmlElement)n;
146 string itemID = elem.GetAttribute("ItemID");
147 string xml = elem.InnerXml;
148
149 itemData[new UUID(itemID)] = xml;
150 }
151 }
152
153
118 List<AvatarAttachment> attachments = sp.Appearance.GetAttachments(); 154 List<AvatarAttachment> attachments = sp.Appearance.GetAttachments();
119 foreach (AvatarAttachment attach in attachments) 155 foreach (AvatarAttachment attach in attachments)
120 { 156 {
@@ -134,12 +170,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
134 170
135 try 171 try
136 { 172 {
173 string xmlData;
174 XmlDocument d = null;
175 UUID asset;
176 if (itemData.TryGetValue(attach.ItemID, out xmlData))
177 {
178 d = new XmlDocument();
179 d.LoadXml(xmlData);
180 m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", attach.ItemID);
181 }
182
137 // If we're an NPC then skip all the item checks and manipulations since we don't have an 183 // If we're an NPC then skip all the item checks and manipulations since we don't have an
138 // inventory right now. 184 // inventory right now.
139 if (sp.PresenceType == PresenceType.Npc) 185 if (sp.PresenceType == PresenceType.Npc)
140 RezSingleAttachmentFromInventoryInternal(sp, UUID.Zero, attach.AssetID, p); 186 RezSingleAttachmentFromInventoryInternal(sp, UUID.Zero, attach.AssetID, p, null);
141 else 187 else
142 RezSingleAttachmentFromInventory(sp, attach.ItemID, p); 188 RezSingleAttachmentFromInventory(sp, attach.ItemID, p, true, d);
143 } 189 }
144 catch (Exception e) 190 catch (Exception e)
145 { 191 {
@@ -264,6 +310,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
264 } 310 }
265 311
266 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt) 312 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt)
313 {
314 return RezSingleAttachmentFromInventory(sp, itemID, AttachmentPt, true, null);
315 }
316
317 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt, bool updateInventoryStatus, XmlDocument doc)
267 { 318 {
268 if (!Enabled) 319 if (!Enabled)
269 return null; 320 return null;
@@ -302,7 +353,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
302 return null; 353 return null;
303 } 354 }
304 355
305 SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt); 356 SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, doc);
306 357
307 if (att == null) 358 if (att == null)
308 DetachSingleAttachmentToInv(sp, itemID); 359 DetachSingleAttachmentToInv(sp, itemID);
@@ -582,11 +633,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
582 633
583 Vector3 inventoryStoredPosition = new Vector3 634 Vector3 inventoryStoredPosition = new Vector3
584 (((grp.AbsolutePosition.X > (int)Constants.RegionSize) 635 (((grp.AbsolutePosition.X > (int)Constants.RegionSize)
585 ? Constants.RegionSize - 6 636 ? (float)Constants.RegionSize - 6
586 : grp.AbsolutePosition.X) 637 : grp.AbsolutePosition.X)
587 , 638 ,
588 (grp.AbsolutePosition.Y > (int)Constants.RegionSize) 639 (grp.AbsolutePosition.Y > (int)Constants.RegionSize)
589 ? Constants.RegionSize - 6 640 ? (float)Constants.RegionSize - 6
590 : grp.AbsolutePosition.Y, 641 : grp.AbsolutePosition.Y,
591 grp.AbsolutePosition.Z); 642 grp.AbsolutePosition.Z);
592 643
@@ -704,8 +755,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
704 } 755 }
705 } 756 }
706 757
707 private SceneObjectGroup RezSingleAttachmentFromInventoryInternal( 758 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal(
708 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt) 759 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, XmlDocument doc)
709 { 760 {
710 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>(); 761 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>();
711 if (invAccess != null) 762 if (invAccess != null)
@@ -713,7 +764,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
713 lock (sp.AttachmentsSyncLock) 764 lock (sp.AttachmentsSyncLock)
714 { 765 {
715 SceneObjectGroup objatt; 766 SceneObjectGroup objatt;
716 767
717 if (itemID != UUID.Zero) 768 if (itemID != UUID.Zero)
718 objatt = invAccess.RezObject(sp.ControllingClient, 769 objatt = invAccess.RezObject(sp.ControllingClient,
719 itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, 770 itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
@@ -722,11 +773,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
722 objatt = invAccess.RezObject(sp.ControllingClient, 773 objatt = invAccess.RezObject(sp.ControllingClient,
723 null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, 774 null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
724 false, false, sp.UUID, true); 775 false, false, sp.UUID, true);
725 776
726 // m_log.DebugFormat( 777 // m_log.DebugFormat(
727 // "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}", 778 // "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}",
728 // objatt.Name, remoteClient.Name, AttachmentPt); 779 // objatt.Name, remoteClient.Name, AttachmentPt);
729 780
730 if (objatt != null) 781 if (objatt != null)
731 { 782 {
732 // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. 783 // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller.
@@ -734,7 +785,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
734 bool tainted = false; 785 bool tainted = false;
735 if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint) 786 if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint)
736 tainted = true; 787 tainted = true;
737 788
738 // This will throw if the attachment fails 789 // This will throw if the attachment fails
739 try 790 try
740 { 791 {
@@ -745,21 +796,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
745 m_log.ErrorFormat( 796 m_log.ErrorFormat(
746 "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}", 797 "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}",
747 objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace); 798 objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace);
748 799
749 // Make sure the object doesn't stick around and bail 800 // Make sure the object doesn't stick around and bail
750 sp.RemoveAttachment(objatt); 801 sp.RemoveAttachment(objatt);
751 m_scene.DeleteSceneObject(objatt, false); 802 m_scene.DeleteSceneObject(objatt, false);
752 return null; 803 return null;
753 } 804 }
754 805
755 if (tainted) 806 if (tainted)
756 objatt.HasGroupChanged = true; 807 objatt.HasGroupChanged = true;
808
809 if (doc != null)
810 {
811 objatt.LoadScriptState(doc);
812 objatt.ResetOwnerChangeFlag();
813 }
757 814
758 // Fire after attach, so we don't get messy perms dialogs 815 // Fire after attach, so we don't get messy perms dialogs
759 // 4 == AttachedRez 816 // 4 == AttachedRez
760 objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4); 817 objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4);
761 objatt.ResumeScripts(); 818 objatt.ResumeScripts();
762 819
763 // Do this last so that event listeners have access to all the effects of the attachment 820 // Do this last so that event listeners have access to all the effects of the attachment
764 m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID); 821 m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID);
765 822
@@ -773,7 +830,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
773 } 830 }
774 } 831 }
775 } 832 }
776 833
777 return null; 834 return null;
778 } 835 }
779 836
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
index 10b4c37..4d8fb90 100644
--- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
@@ -49,7 +49,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
49 private int m_shoutdistance = 100; 49 private int m_shoutdistance = 100;
50 private int m_whisperdistance = 10; 50 private int m_whisperdistance = 10;
51 private List<Scene> m_scenes = new List<Scene>(); 51 private List<Scene> m_scenes = new List<Scene>();
52 52 private List<string> FreezeCache = new List<string>();
53 private string m_adminPrefix = "";
53 internal object m_syncy = new object(); 54 internal object m_syncy = new object();
54 55
55 internal IConfig m_config; 56 internal IConfig m_config;
@@ -76,6 +77,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
76 m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance); 77 m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance);
77 m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance); 78 m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance);
78 m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance); 79 m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance);
80 m_adminPrefix = config.Configs["Chat"].GetString("admin_prefix", "");
79 } 81 }
80 82
81 public virtual void AddRegion(Scene scene) 83 public virtual void AddRegion(Scene scene)
@@ -171,7 +173,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
171 return; 173 return;
172 } 174 }
173 175
174 DeliverChatToAvatars(ChatSourceType.Agent, c); 176 if (FreezeCache.Contains(c.Sender.AgentId.ToString()))
177 {
178 if (c.Type != ChatTypeEnum.StartTyping || c.Type != ChatTypeEnum.StopTyping)
179 c.Sender.SendAgentAlertMessage("You may not talk as you are frozen.", false);
180 }
181 else
182 {
183 DeliverChatToAvatars(ChatSourceType.Agent, c);
184 }
175 } 185 }
176 186
177 public virtual void OnChatFromWorld(Object sender, OSChatMessage c) 187 public virtual void OnChatFromWorld(Object sender, OSChatMessage c)
@@ -185,6 +195,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
185 protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c) 195 protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c)
186 { 196 {
187 string fromName = c.From; 197 string fromName = c.From;
198 string fromNamePrefix = "";
188 UUID fromID = UUID.Zero; 199 UUID fromID = UUID.Zero;
189 string message = c.Message; 200 string message = c.Message;
190 IScene scene = c.Scene; 201 IScene scene = c.Scene;
@@ -207,7 +218,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
207 fromPos = avatar.AbsolutePosition; 218 fromPos = avatar.AbsolutePosition;
208 fromName = avatar.Name; 219 fromName = avatar.Name;
209 fromID = c.Sender.AgentId; 220 fromID = c.Sender.AgentId;
210 221 if (avatar.GodLevel >= 200)
222 {
223 fromNamePrefix = m_adminPrefix;
224 }
211 break; 225 break;
212 226
213 case ChatSourceType.Object: 227 case ChatSourceType.Object:
@@ -233,8 +247,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
233 s.ForEachRootScenePresence( 247 s.ForEachRootScenePresence(
234 delegate(ScenePresence presence) 248 delegate(ScenePresence presence)
235 { 249 {
236 if (TrySendChatMessage(presence, fromPos, regionPos, fromID, fromName, c.Type, message, sourceType)) 250 ILandObject Presencecheck = s.LandChannel.GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y);
237 receiverIDs.Add(presence.UUID); 251 if (Presencecheck != null)
252 {
253 // This will pass all chat from objects. Not
254 // perfect, but it will do. For now. Better
255 // than the prior behavior of muting all
256 // objects on a parcel with access restrictions
257 if (c.Sender == null || Presencecheck.IsEitherBannedOrRestricted(c.Sender.AgentId) != true)
258 {
259 if (TrySendChatMessage(presence, fromPos, regionPos, fromID, fromNamePrefix + fromName, c.Type, message, sourceType))
260 receiverIDs.Add(presence.UUID);
261 }
262 }
263
238 } 264 }
239 ); 265 );
240 } 266 }
@@ -278,26 +304,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
278 } 304 }
279 305
280 // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType); 306 // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType);
281
282 HashSet<UUID> receiverIDs = new HashSet<UUID>(); 307 HashSet<UUID> receiverIDs = new HashSet<UUID>();
283 308
284 ((Scene)c.Scene).ForEachRootClient( 309 if (c.Scene != null)
285 delegate(IClientAPI client) 310 {
286 { 311 ((Scene)c.Scene).ForEachRootClient
287 // don't forward SayOwner chat from objects to 312 (
288 // non-owner agents 313 delegate(IClientAPI client)
289 if ((c.Type == ChatTypeEnum.Owner) && 314 {
290 (null != c.SenderObject) && 315 // don't forward SayOwner chat from objects to
291 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) 316 // non-owner agents
292 return; 317 if ((c.Type == ChatTypeEnum.Owner) &&
293 318 (null != c.SenderObject) &&
294 client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, 319 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId))
295 (byte)sourceType, (byte)ChatAudibleLevel.Fully); 320 return;
296 receiverIDs.Add(client.AgentId); 321
297 }); 322 client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID,
298 323 (byte)sourceType, (byte)ChatAudibleLevel.Fully);
299 (c.Scene as Scene).EventManager.TriggerOnChatToClients( 324 receiverIDs.Add(client.AgentId);
300 fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully); 325 }
326 );
327 (c.Scene as Scene).EventManager.TriggerOnChatToClients(
328 fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully);
329 }
301 } 330 }
302 331
303 /// <summary> 332 /// <summary>
@@ -340,5 +369,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
340 369
341 return true; 370 return true;
342 } 371 }
372
373 Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>();
374 public void ParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
375 {
376 System.Threading.Timer Timer;
377 if (flags == 0)
378 {
379 FreezeCache.Add(target.ToString());
380 System.Threading.TimerCallback timeCB = new System.Threading.TimerCallback(OnEndParcelFrozen);
381 Timer = new System.Threading.Timer(timeCB, target, 30000, 0);
382 Timers.Add(target, Timer);
383 }
384 else
385 {
386 FreezeCache.Remove(target.ToString());
387 Timers.TryGetValue(target, out Timer);
388 Timers.Remove(target);
389 Timer.Dispose();
390 }
391 }
392
393 private void OnEndParcelFrozen(object avatar)
394 {
395 UUID target = (UUID)avatar;
396 FreezeCache.Remove(target.ToString());
397 System.Threading.Timer Timer;
398 Timers.TryGetValue(target, out Timer);
399 Timers.Remove(target);
400 Timer.Dispose();
401 }
343 } 402 }
344} 403}
diff --git a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
index ffe7718..bb2cd1f 100644
--- a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
@@ -216,4 +216,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog
216 return result; 216 return result;
217 } 217 }
218 } 218 }
219} \ No newline at end of file 219}
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index c266fe5..5d94ff7 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -328,7 +328,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
328 //m_log.DebugFormat("[XXX]: OnClientLogin!"); 328 //m_log.DebugFormat("[XXX]: OnClientLogin!");
329 // Inform the friends that this user is online 329 // Inform the friends that this user is online
330 StatusChange(agentID, true); 330 StatusChange(agentID, true);
331 331
332 // Register that we need to send the list of online friends to this user 332 // Register that we need to send the list of online friends to this user
333 lock (m_NeedsListOfOnlineFriends) 333 lock (m_NeedsListOfOnlineFriends)
334 m_NeedsListOfOnlineFriends.Add(agentID); 334 m_NeedsListOfOnlineFriends.Add(agentID);
@@ -603,6 +603,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
603 { 603 {
604 StoreFriendships(client.AgentId, friendID); 604 StoreFriendships(client.AgentId, friendID);
605 605
606 ICallingCardModule ccm = client.Scene.RequestModuleInterface<ICallingCardModule>();
607 if (ccm != null)
608 {
609 ccm.CreateCallingCard(client.AgentId, friendID, UUID.Zero);
610 }
611
606 // Update the local cache 612 // Update the local cache
607 RecacheFriends(client); 613 RecacheFriends(client);
608 614
@@ -779,6 +785,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
779 (byte)OpenMetaverse.InstantMessageDialog.FriendshipAccepted, userID.ToString(), false, Vector3.Zero); 785 (byte)OpenMetaverse.InstantMessageDialog.FriendshipAccepted, userID.ToString(), false, Vector3.Zero);
780 friendClient.SendInstantMessage(im); 786 friendClient.SendInstantMessage(im);
781 787
788 ICallingCardModule ccm = friendClient.Scene.RequestModuleInterface<ICallingCardModule>();
789 if (ccm != null)
790 {
791 ccm.CreateCallingCard(friendID, userID, UUID.Zero);
792 }
793
794
782 // Update the local cache 795 // Update the local cache
783 RecacheFriends(friendClient); 796 RecacheFriends(friendClient);
784 797
@@ -801,7 +814,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
801 // we're done 814 // we're done
802 return true; 815 return true;
803 } 816 }
804 817
805 return false; 818 return false;
806 } 819 }
807 820
@@ -853,7 +866,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
853 866
854 public bool LocalStatusNotification(UUID userID, UUID friendID, bool online) 867 public bool LocalStatusNotification(UUID userID, UUID friendID, bool online)
855 { 868 {
856// m_log.DebugFormat("[FRIENDS]: Local Status Notify {0} that user {1} is {2}", friendID, userID, online); 869 //m_log.DebugFormat("[FRIENDS]: Local Status Notify {0} that user {1} is {2}", friendID, userID, online);
857 IClientAPI friendClient = LocateClientObject(friendID); 870 IClientAPI friendClient = LocateClientObject(friendID);
858 if (friendClient != null) 871 if (friendClient != null)
859 { 872 {
diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
index 2e3312f..1492302 100644
--- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
@@ -31,16 +31,40 @@ using OpenMetaverse;
31using OpenSim.Framework; 31using OpenSim.Framework;
32using OpenSim.Region.Framework.Scenes; 32using OpenSim.Region.Framework.Scenes;
33using OpenSim.Region.Framework.Interfaces; 33using OpenSim.Region.Framework.Interfaces;
34using System;
35using System.Reflection;
36using System.Collections;
37using System.Collections.Specialized;
38using System.Reflection;
39using System.IO;
40using System.Web;
41using System.Xml;
42using log4net;
43using Mono.Addins;
44using OpenMetaverse.Messages.Linden;
45using OpenMetaverse.StructuredData;
46using OpenSim.Framework.Capabilities;
47using OpenSim.Framework.Servers;
48using OpenSim.Framework.Servers.HttpServer;
49using Caps = OpenSim.Framework.Capabilities.Caps;
50using OSDArray = OpenMetaverse.StructuredData.OSDArray;
51using OSDMap = OpenMetaverse.StructuredData.OSDMap;
34 52
35namespace OpenSim.Region.CoreModules.Avatar.Gods 53namespace OpenSim.Region.CoreModules.Avatar.Gods
36{ 54{
37 public class GodsModule : IRegionModule, IGodsModule 55 public class GodsModule : IRegionModule, IGodsModule
38 { 56 {
57 private static readonly ILog m_log =
58 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
59
39 /// <summary>Special UUID for actions that apply to all agents</summary> 60 /// <summary>Special UUID for actions that apply to all agents</summary>
40 private static readonly UUID ALL_AGENTS = new UUID("44e87126-e794-4ded-05b3-7c42da3d5cdb"); 61 private static readonly UUID ALL_AGENTS = new UUID("44e87126-e794-4ded-05b3-7c42da3d5cdb");
41 62
42 protected Scene m_scene; 63 protected Scene m_scene;
43 protected IDialogModule m_dialogModule; 64 protected IDialogModule m_dialogModule;
65
66 protected Dictionary<UUID, string> m_capsDict =
67 new Dictionary<UUID, string>();
44 68
45 public void Initialise(Scene scene, IConfigSource source) 69 public void Initialise(Scene scene, IConfigSource source)
46 { 70 {
@@ -48,6 +72,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
48 m_dialogModule = m_scene.RequestModuleInterface<IDialogModule>(); 72 m_dialogModule = m_scene.RequestModuleInterface<IDialogModule>();
49 m_scene.RegisterModuleInterface<IGodsModule>(this); 73 m_scene.RegisterModuleInterface<IGodsModule>(this);
50 m_scene.EventManager.OnNewClient += SubscribeToClientEvents; 74 m_scene.EventManager.OnNewClient += SubscribeToClientEvents;
75 m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
76 m_scene.EventManager.OnClientClosed += OnClientClosed;
77 scene.EventManager.OnIncomingInstantMessage +=
78 OnIncomingInstantMessage;
51 } 79 }
52 80
53 public void PostInitialise() {} 81 public void PostInitialise() {}
@@ -67,6 +95,54 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
67 client.OnRequestGodlikePowers -= RequestGodlikePowers; 95 client.OnRequestGodlikePowers -= RequestGodlikePowers;
68 } 96 }
69 97
98 private void OnClientClosed(UUID agentID, Scene scene)
99 {
100 m_capsDict.Remove(agentID);
101 }
102
103 private void OnRegisterCaps(UUID agentID, Caps caps)
104 {
105 string uri = "/CAPS/" + UUID.Random();
106 m_capsDict[agentID] = uri;
107
108 caps.RegisterHandler("UntrustedSimulatorMessage",
109 new RestStreamHandler("POST", uri,
110 HandleUntrustedSimulatorMessage));
111 }
112
113 private string HandleUntrustedSimulatorMessage(string request,
114 string path, string param, IOSHttpRequest httpRequest,
115 IOSHttpResponse httpResponse)
116 {
117 OSDMap osd = (OSDMap)OSDParser.DeserializeLLSDXml(request);
118
119 string message = osd["message"].AsString();
120
121 if (message == "GodKickUser")
122 {
123 OSDMap body = (OSDMap)osd["body"];
124 OSDArray userInfo = (OSDArray)body["UserInfo"];
125 OSDMap userData = (OSDMap)userInfo[0];
126
127 UUID agentID = userData["AgentID"].AsUUID();
128 UUID godID = userData["GodID"].AsUUID();
129 UUID godSessionID = userData["GodSessionID"].AsUUID();
130 uint kickFlags = userData["KickFlags"].AsUInteger();
131 string reason = userData["Reason"].AsString();
132
133 ScenePresence god = m_scene.GetScenePresence(godID);
134 if (god == null || god.ControllingClient.SessionId != godSessionID)
135 return String.Empty;
136
137 KickUser(godID, godSessionID, agentID, kickFlags, Util.StringToBytes1024(reason));
138 }
139 else
140 {
141 m_log.ErrorFormat("[GOD]: Unhandled UntrustedSimulatorMessage: {0}", message);
142 }
143 return String.Empty;
144 }
145
70 public void RequestGodlikePowers( 146 public void RequestGodlikePowers(
71 UUID agentID, UUID sessionID, UUID token, bool godLike, IClientAPI controllingClient) 147 UUID agentID, UUID sessionID, UUID token, bool godLike, IClientAPI controllingClient)
72 { 148 {
@@ -115,69 +191,85 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
115 /// <param name="reason">The message to send to the user after it's been turned into a field</param> 191 /// <param name="reason">The message to send to the user after it's been turned into a field</param>
116 public void KickUser(UUID godID, UUID sessionID, UUID agentID, uint kickflags, byte[] reason) 192 public void KickUser(UUID godID, UUID sessionID, UUID agentID, uint kickflags, byte[] reason)
117 { 193 {
118 UUID kickUserID = ALL_AGENTS; 194 if (!m_scene.Permissions.IsGod(godID))
119 195 return;
196
120 ScenePresence sp = m_scene.GetScenePresence(agentID); 197 ScenePresence sp = m_scene.GetScenePresence(agentID);
121 198
122 if (sp != null || agentID == kickUserID) 199 if (sp == null && agentID != ALL_AGENTS)
123 { 200 {
124 if (m_scene.Permissions.IsGod(godID)) 201 IMessageTransferModule transferModule =
202 m_scene.RequestModuleInterface<IMessageTransferModule>();
203 if (transferModule != null)
125 { 204 {
126 if (kickflags == 0) 205 m_log.DebugFormat("[GODS]: Sending nonlocal kill for agent {0}", agentID);
127 { 206 transferModule.SendInstantMessage(new GridInstantMessage(
128 if (agentID == kickUserID) 207 m_scene, godID, "God", agentID, (byte)250, false,
129 { 208 Utils.BytesToString(reason), UUID.Zero, true,
130 string reasonStr = Utils.BytesToString(reason); 209 new Vector3(), new byte[] {(byte)kickflags}),
131 210 delegate(bool success) {} );
132 m_scene.ForEachClient( 211 }
133 delegate(IClientAPI controller) 212 return;
134 { 213 }
135 if (controller.AgentId != godID)
136 controller.Kick(reasonStr);
137 }
138 );
139
140 // This is a bit crude. It seems the client will be null before it actually stops the thread
141 // The thread will kill itself eventually :/
142 // Is there another way to make sure *all* clients get this 'inter region' message?
143 m_scene.ForEachRootClient(
144 delegate(IClientAPI client)
145 {
146 if (client.AgentId != godID)
147 {
148 client.Close();
149 }
150 }
151 );
152 }
153 else
154 {
155 m_scene.SceneGraph.removeUserCount(!sp.IsChildAgent);
156 214
157 sp.ControllingClient.Kick(Utils.BytesToString(reason)); 215 switch (kickflags)
158 sp.ControllingClient.Close(); 216 {
159 } 217 case 0:
160 } 218 if (sp != null)
161 219 {
162 if (kickflags == 1) 220 KickPresence(sp, Utils.BytesToString(reason));
163 {
164 sp.AllowMovement = false;
165 m_dialogModule.SendAlertToUser(agentID, Utils.BytesToString(reason));
166 m_dialogModule.SendAlertToUser(godID, "User Frozen");
167 }
168
169 if (kickflags == 2)
170 {
171 sp.AllowMovement = true;
172 m_dialogModule.SendAlertToUser(agentID, Utils.BytesToString(reason));
173 m_dialogModule.SendAlertToUser(godID, "User Unfrozen");
174 }
175 } 221 }
176 else 222 else if (agentID == ALL_AGENTS)
177 { 223 {
178 m_dialogModule.SendAlertToUser(godID, "Kick request denied"); 224 m_scene.ForEachRootScenePresence(
225 delegate(ScenePresence p)
226 {
227 if (p.UUID != godID && (!m_scene.Permissions.IsGod(p.UUID)))
228 KickPresence(p, Utils.BytesToString(reason));
229 }
230 );
179 } 231 }
232 break;
233 case 1:
234 if (sp != null)
235 {
236 sp.AllowMovement = false;
237 m_dialogModule.SendAlertToUser(agentID, Utils.BytesToString(reason));
238 m_dialogModule.SendAlertToUser(godID, "User Frozen");
239 }
240 break;
241 case 2:
242 if (sp != null)
243 {
244 sp.AllowMovement = true;
245 m_dialogModule.SendAlertToUser(agentID, Utils.BytesToString(reason));
246 m_dialogModule.SendAlertToUser(godID, "User Unfrozen");
247 }
248 break;
249 default:
250 break;
251 }
252 }
253
254 private void KickPresence(ScenePresence sp, string reason)
255 {
256 if (sp.IsChildAgent)
257 return;
258 sp.ControllingClient.Kick(reason);
259 sp.Scene.IncomingCloseAgent(sp.UUID);
260 }
261
262 private void OnIncomingInstantMessage(GridInstantMessage msg)
263 {
264 if (msg.dialog == (uint)250) // Nonlocal kick
265 {
266 UUID agentID = new UUID(msg.toAgentID);
267 string reason = msg.message;
268 UUID godID = new UUID(msg.fromAgentID);
269 uint kickMode = (uint)msg.binaryBucket[0];
270
271 KickUser(godID, UUID.Zero, agentID, kickMode, Util.StringToBytes1024(reason));
180 } 272 }
181 } 273 }
182 } 274 }
183} \ No newline at end of file 275}
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
index ca5d485..727f1c9 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
@@ -27,6 +27,7 @@
27using System; 27using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.Reflection; 29using System.Reflection;
30using System.Timers;
30using log4net; 31using log4net;
31using Nini.Config; 32using Nini.Config;
32using OpenMetaverse; 33using OpenMetaverse;
@@ -42,6 +43,10 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
42 private static readonly ILog m_log = LogManager.GetLogger( 43 private static readonly ILog m_log = LogManager.GetLogger(
43 MethodBase.GetCurrentMethod().DeclaringType); 44 MethodBase.GetCurrentMethod().DeclaringType);
44 45
46 private Timer m_logTimer = new Timer(10000);
47 private List<GridInstantMessage> m_logData = new List<GridInstantMessage>();
48 private string m_restUrl;
49
45 /// <value> 50 /// <value>
46 /// Is this module enabled? 51 /// Is this module enabled?
47 /// </value> 52 /// </value>
@@ -61,9 +66,12 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
61 "InstantMessageModule", "InstantMessageModule") != 66 "InstantMessageModule", "InstantMessageModule") !=
62 "InstantMessageModule") 67 "InstantMessageModule")
63 return; 68 return;
69 m_restUrl = config.Configs["Messaging"].GetString("LogURL", String.Empty);
64 } 70 }
65 71
66 m_enabled = true; 72 m_enabled = true;
73 m_logTimer.AutoReset = false;
74 m_logTimer.Elapsed += LogTimerElapsed;
67 } 75 }
68 76
69 public void AddRegion(Scene scene) 77 public void AddRegion(Scene scene)
@@ -148,6 +156,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
148 { 156 {
149 byte dialog = im.dialog; 157 byte dialog = im.dialog;
150 158
159 if (client != null && dialog == (byte)InstantMessageDialog.MessageFromAgent)
160 LogInstantMesssage(im);
161
151 if (dialog != (byte)InstantMessageDialog.MessageFromAgent 162 if (dialog != (byte)InstantMessageDialog.MessageFromAgent
152 && dialog != (byte)InstantMessageDialog.StartTyping 163 && dialog != (byte)InstantMessageDialog.StartTyping
153 && dialog != (byte)InstantMessageDialog.StopTyping 164 && dialog != (byte)InstantMessageDialog.StopTyping
@@ -157,6 +168,32 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
157 return; 168 return;
158 } 169 }
159 170
171 //DateTime dt = DateTime.UtcNow;
172
173 // Ticks from UtcNow, but make it look like local. Evil, huh?
174 //dt = DateTime.SpecifyKind(dt, DateTimeKind.Local);
175
176 //try
177 //{
178 // // Convert that to the PST timezone
179 // TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
180 // dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo);
181 //}
182 //catch
183 //{
184 // //m_log.Info("[OFFLINE MESSAGING]: No PST timezone found on this machine. Saving with local timestamp.");
185 //}
186
187 //// And make it look local again to fool the unix time util
188 //dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
189
190 // If client is null, this message comes from storage and IS offline
191 if (client != null)
192 im.offline = 0;
193
194 if (im.offline == 0)
195 im.timestamp = (uint)Util.UnixTimeSinceEpoch();
196
160 if (m_TransferModule != null) 197 if (m_TransferModule != null)
161 { 198 {
162 if (client != null) 199 if (client != null)
@@ -200,5 +237,35 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
200 // 237 //
201 OnInstantMessage(null, msg); 238 OnInstantMessage(null, msg);
202 } 239 }
240
241 private void LogInstantMesssage(GridInstantMessage im)
242 {
243 if (m_logData.Count < 20)
244 {
245 // Restart the log write timer
246 m_logTimer.Stop();
247 }
248 if (!m_logTimer.Enabled)
249 m_logTimer.Start();
250
251 lock (m_logData)
252 {
253 m_logData.Add(im);
254 }
255 }
256
257 private void LogTimerElapsed(object source, ElapsedEventArgs e)
258 {
259 lock (m_logData)
260 {
261 if (m_restUrl != String.Empty && m_logData.Count > 0)
262 {
263 bool success = SynchronousRestObjectRequester.MakeRequest<List<GridInstantMessage>, bool>("POST", m_restUrl + "/LogMessages/", m_logData);
264 if (!success)
265 m_log.ErrorFormat("[INSTANT MESSAGE]: Failed to save log data");
266 }
267 m_logData.Clear();
268 }
269 }
203 } 270 }
204} 271}
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
index 0dad3c4..6064ddc 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
@@ -48,6 +48,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49 49
50 private bool m_Enabled = false; 50 private bool m_Enabled = false;
51 protected string m_MessageKey = String.Empty;
51 protected List<Scene> m_Scenes = new List<Scene>(); 52 protected List<Scene> m_Scenes = new List<Scene>();
52 protected Dictionary<UUID, UUID> m_UserRegionMap = new Dictionary<UUID, UUID>(); 53 protected Dictionary<UUID, UUID> m_UserRegionMap = new Dictionary<UUID, UUID>();
53 54
@@ -67,14 +68,17 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
67 public virtual void Initialise(IConfigSource config) 68 public virtual void Initialise(IConfigSource config)
68 { 69 {
69 IConfig cnf = config.Configs["Messaging"]; 70 IConfig cnf = config.Configs["Messaging"];
70 if (cnf != null && cnf.GetString( 71 if (cnf != null)
71 "MessageTransferModule", "MessageTransferModule") !=
72 "MessageTransferModule")
73 { 72 {
74 m_log.Debug("[MESSAGE TRANSFER]: Disabled by configuration"); 73 if (cnf.GetString("MessageTransferModule",
75 return; 74 "MessageTransferModule") != "MessageTransferModule")
76 } 75 {
76 return;
77 }
77 78
79 m_MessageKey = cnf.GetString("MessageKey", String.Empty);
80 }
81 m_log.Debug("[MESSAGE TRANSFER]: Module enabled");
78 m_Enabled = true; 82 m_Enabled = true;
79 } 83 }
80 84
@@ -244,6 +248,19 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
244 && requestData.ContainsKey("position_z") && requestData.ContainsKey("region_id") 248 && requestData.ContainsKey("position_z") && requestData.ContainsKey("region_id")
245 && requestData.ContainsKey("binary_bucket")) 249 && requestData.ContainsKey("binary_bucket"))
246 { 250 {
251 if (m_MessageKey != String.Empty)
252 {
253 XmlRpcResponse error_resp = new XmlRpcResponse();
254 Hashtable error_respdata = new Hashtable();
255 error_respdata["success"] = "FALSE";
256 error_resp.Value = error_respdata;
257
258 if (!requestData.Contains("message_key"))
259 return error_resp;
260 if (m_MessageKey != (string)requestData["message_key"])
261 return error_resp;
262 }
263
247 // Do the easy way of validating the UUIDs 264 // Do the easy way of validating the UUIDs
248 UUID.TryParse((string)requestData["from_agent_id"], out fromAgentID); 265 UUID.TryParse((string)requestData["from_agent_id"], out fromAgentID);
249 UUID.TryParse((string)requestData["to_agent_id"], out toAgentID); 266 UUID.TryParse((string)requestData["to_agent_id"], out toAgentID);
@@ -420,24 +437,37 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
420 return resp; 437 return resp;
421 } 438 }
422 439
423 /// <summary> 440 private delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result);
424 /// delegate for sending a grid instant message asynchronously
425 /// </summary>
426 public delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID);
427 441
428 protected virtual void GridInstantMessageCompleted(IAsyncResult iar) 442 private class GIM {
429 { 443 public GridInstantMessage im;
430 GridInstantMessageDelegate icon = 444 public MessageResultNotification result;
431 (GridInstantMessageDelegate)iar.AsyncState; 445 };
432 icon.EndInvoke(iar);
433 }
434 446
447 private Queue<GIM> pendingInstantMessages = new Queue<GIM>();
448 private int numInstantMessageThreads = 0;
435 449
436 protected virtual void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result) 450 private void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result)
437 { 451 {
438 GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsync; 452 lock (pendingInstantMessages) {
453 if (numInstantMessageThreads >= 4) {
454 GIM gim = new GIM();
455 gim.im = im;
456 gim.result = result;
457 pendingInstantMessages.Enqueue(gim);
458 } else {
459 ++ numInstantMessageThreads;
460 //m_log.DebugFormat("[SendGridInstantMessageViaXMLRPC]: ++numInstantMessageThreads={0}", numInstantMessageThreads);
461 GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsyncMain;
462 d.BeginInvoke(im, result, GridInstantMessageCompleted, d);
463 }
464 }
465 }
439 466
440 d.BeginInvoke(im, result, UUID.Zero, GridInstantMessageCompleted, d); 467 private void GridInstantMessageCompleted(IAsyncResult iar)
468 {
469 GridInstantMessageDelegate d = (GridInstantMessageDelegate)iar.AsyncState;
470 d.EndInvoke(iar);
441 } 471 }
442 472
443 /// <summary> 473 /// <summary>
@@ -452,8 +482,31 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
452 /// Pass in 0 the first time this method is called. It will be called recursively with the last 482 /// Pass in 0 the first time this method is called. It will be called recursively with the last
453 /// regionhandle tried 483 /// regionhandle tried
454 /// </param> 484 /// </param>
455 protected virtual void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID) 485 private void SendGridInstantMessageViaXMLRPCAsyncMain(GridInstantMessage im, MessageResultNotification result)
456 { 486 {
487 GIM gim;
488 do {
489 try {
490 SendGridInstantMessageViaXMLRPCAsync(im, result, UUID.Zero);
491 } catch (Exception e) {
492 m_log.Error("[SendGridInstantMessageViaXMLRPC]: exception " + e.Message);
493 }
494 lock (pendingInstantMessages) {
495 if (pendingInstantMessages.Count > 0) {
496 gim = pendingInstantMessages.Dequeue();
497 im = gim.im;
498 result = gim.result;
499 } else {
500 gim = null;
501 -- numInstantMessageThreads;
502 //m_log.DebugFormat("[SendGridInstantMessageViaXMLRPC]: --numInstantMessageThreads={0}", numInstantMessageThreads);
503 }
504 }
505 } while (gim != null);
506 }
507 private void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID)
508 {
509
457 UUID toAgentID = new UUID(im.toAgentID); 510 UUID toAgentID = new UUID(im.toAgentID);
458 511
459 PresenceInfo upd = null; 512 PresenceInfo upd = null;
@@ -520,7 +573,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
520 573
521 if (upd != null) 574 if (upd != null)
522 { 575 {
523 GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, 576 GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(UUID.Zero,
524 upd.RegionID); 577 upd.RegionID);
525 if (reginfo != null) 578 if (reginfo != null)
526 { 579 {
@@ -669,6 +722,8 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
669 gim["position_z"] = msg.Position.Z.ToString(); 722 gim["position_z"] = msg.Position.Z.ToString();
670 gim["region_id"] = msg.RegionID.ToString(); 723 gim["region_id"] = msg.RegionID.ToString();
671 gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket,Base64FormattingOptions.None); 724 gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket,Base64FormattingOptions.None);
725 if (m_MessageKey != String.Empty)
726 gim["message_key"] = m_MessageKey;
672 return gim; 727 return gim;
673 } 728 }
674 729
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
index de25048..b27b07d 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
@@ -171,7 +171,11 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
171 171
172 private void RetrieveInstantMessages(IClientAPI client) 172 private void RetrieveInstantMessages(IClientAPI client)
173 { 173 {
174 if (m_RestURL != "") 174 if (m_RestURL == String.Empty)
175 {
176 return;
177 }
178 else
175 { 179 {
176 m_log.DebugFormat("[OFFLINE MESSAGING]: Retrieving stored messages for {0}", client.AgentId); 180 m_log.DebugFormat("[OFFLINE MESSAGING]: Retrieving stored messages for {0}", client.AgentId);
177 181
@@ -179,22 +183,25 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
179 = SynchronousRestObjectRequester.MakeRequest<UUID, List<GridInstantMessage>>( 183 = SynchronousRestObjectRequester.MakeRequest<UUID, List<GridInstantMessage>>(
180 "POST", m_RestURL + "/RetrieveMessages/", client.AgentId); 184 "POST", m_RestURL + "/RetrieveMessages/", client.AgentId);
181 185
182 if (msglist == null) 186 if (msglist != null)
183 m_log.WarnFormat("[OFFLINE MESSAGING]: WARNING null message list.");
184
185 foreach (GridInstantMessage im in msglist)
186 { 187 {
187 // client.SendInstantMessage(im); 188 foreach (GridInstantMessage im in msglist)
188 189 {
189 // Send through scene event manager so all modules get a chance 190 // client.SendInstantMessage(im);
190 // to look at this message before it gets delivered. 191
191 // 192 // Send through scene event manager so all modules get a chance
192 // Needed for proper state management for stored group 193 // to look at this message before it gets delivered.
193 // invitations 194 //
194 // 195 // Needed for proper state management for stored group
195 Scene s = FindScene(client.AgentId); 196 // invitations
196 if (s != null) 197 //
197 s.EventManager.TriggerIncomingInstantMessage(im); 198
199 im.offline = 1;
200
201 Scene s = FindScene(client.AgentId);
202 if (s != null)
203 s.EventManager.TriggerIncomingInstantMessage(im);
204 }
198 } 205 }
199 } 206 }
200 } 207 }
@@ -205,24 +212,19 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
205 im.dialog != (byte)InstantMessageDialog.MessageFromAgent && 212 im.dialog != (byte)InstantMessageDialog.MessageFromAgent &&
206 im.dialog != (byte)InstantMessageDialog.GroupNotice && 213 im.dialog != (byte)InstantMessageDialog.GroupNotice &&
207 im.dialog != (byte)InstantMessageDialog.GroupInvitation && 214 im.dialog != (byte)InstantMessageDialog.GroupInvitation &&
208 im.dialog != (byte)InstantMessageDialog.InventoryOffered) 215 im.dialog != (byte)InstantMessageDialog.InventoryOffered &&
216 im.dialog != (byte)InstantMessageDialog.TaskInventoryOffered)
209 { 217 {
210 return; 218 return;
211 } 219 }
212 220
213 if (!m_ForwardOfflineGroupMessages)
214 {
215 if (im.dialog == (byte)InstantMessageDialog.GroupNotice ||
216 im.dialog != (byte)InstantMessageDialog.GroupInvitation)
217 return;
218 }
219
220 Scene scene = FindScene(new UUID(im.fromAgentID)); 221 Scene scene = FindScene(new UUID(im.fromAgentID));
221 if (scene == null) 222 if (scene == null)
222 scene = m_SceneList[0]; 223 scene = m_SceneList[0];
223 224
224 bool success = SynchronousRestObjectRequester.MakeRequest<GridInstantMessage, bool>( 225 bool success = SynchronousRestObjectRequester.MakeRequest<GridInstantMessage, bool>(
225 "POST", m_RestURL+"/SaveMessage/", im); 226 "POST", m_RestURL+"/SaveMessage/?scope=" +
227 scene.RegionInfo.ScopeID.ToString(), im);
226 228
227 if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent) 229 if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent)
228 { 230 {
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
index ee10d04..0833154 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
@@ -635,4 +635,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
635 m_assetsLoaded = true; 635 m_assetsLoaded = true;
636 } 636 }
637 } 637 }
638} \ No newline at end of file 638}
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
index 36ecb3b..63fde07 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
@@ -178,9 +178,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
178 InventoryFolderBase inventoryFolder, string path, bool saveThisFolderItself, 178 InventoryFolderBase inventoryFolder, string path, bool saveThisFolderItself,
179 Dictionary<string, object> options, IUserAccountService userAccountService) 179 Dictionary<string, object> options, IUserAccountService userAccountService)
180 { 180 {
181 if (options.ContainsKey("verbose"))
182 m_log.InfoFormat("[INVENTORY ARCHIVER]: Saving folder {0}", inventoryFolder.Name);
183
184 if (saveThisFolderItself) 181 if (saveThisFolderItself)
185 { 182 {
186 path += CreateArchiveFolderName(inventoryFolder); 183 path += CreateArchiveFolderName(inventoryFolder);
@@ -449,4 +446,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
449 return s; 446 return s;
450 } 447 }
451 } 448 }
452} \ No newline at end of file 449}
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
index 19c774f..da708d2 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
@@ -175,8 +175,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
175 if (im.binaryBucket.Length < 17) // Invalid 175 if (im.binaryBucket.Length < 17) // Invalid
176 return; 176 return;
177 177
178 UUID receipientID = new UUID(im.toAgentID); 178 UUID recipientID = new UUID(im.toAgentID);
179 ScenePresence user = scene.GetScenePresence(receipientID); 179 ScenePresence user = scene.GetScenePresence(recipientID);
180 UUID copyID; 180 UUID copyID;
181 181
182 // First byte is the asset type 182 // First byte is the asset type
@@ -191,7 +191,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
191 folderID, new UUID(im.toAgentID)); 191 folderID, new UUID(im.toAgentID));
192 192
193 InventoryFolderBase folderCopy 193 InventoryFolderBase folderCopy
194 = scene.GiveInventoryFolder(receipientID, client.AgentId, folderID, UUID.Zero); 194 = scene.GiveInventoryFolder(recipientID, client.AgentId, folderID, UUID.Zero);
195 195
196 if (folderCopy == null) 196 if (folderCopy == null)
197 { 197 {
@@ -244,6 +244,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
244 im.imSessionID = itemID.Guid; 244 im.imSessionID = itemID.Guid;
245 } 245 }
246 246
247 im.offline = 0;
248
247 // Send the IM to the recipient. The item is already 249 // Send the IM to the recipient. The item is already
248 // in their inventory, so it will not be lost if 250 // in their inventory, so it will not be lost if
249 // they are offline. 251 // they are offline.
@@ -263,7 +265,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
263 }); 265 });
264 } 266 }
265 } 267 }
266 else if (im.dialog == (byte) InstantMessageDialog.InventoryAccepted) 268 else if (im.dialog == (byte) InstantMessageDialog.InventoryAccepted ||
269 im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted)
267 { 270 {
268 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID)); 271 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID));
269 272
@@ -274,30 +277,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
274 else 277 else
275 { 278 {
276 if (m_TransferModule != null) 279 if (m_TransferModule != null)
277 m_TransferModule.SendInstantMessage(im, delegate(bool success) { 280 m_TransferModule.SendInstantMessage(im, delegate(bool success) {});
278
279 // justincc - FIXME: Comment out for now. This code was added in commit db91044 Mon Aug 22 2011
280 // and is apparently supposed to fix bulk inventory updates after accepting items. But
281 // instead it appears to cause two copies of an accepted folder for the receiving user in
282 // at least some cases. Folder/item update is already done when the offer is made (see code above)
283
284// // Send BulkUpdateInventory
285// IInventoryService invService = scene.InventoryService;
286// UUID inventoryEntityID = new UUID(im.imSessionID); // The inventory item /folder, back from it's trip
287//
288// InventoryFolderBase folder = new InventoryFolderBase(inventoryEntityID, client.AgentId);
289// folder = invService.GetFolder(folder);
290//
291// ScenePresence fromUser = scene.GetScenePresence(new UUID(im.fromAgentID));
292//
293// // If the user has left the scene by the time the message comes back then we can't send
294// // them the update.
295// if (fromUser != null)
296// fromUser.ControllingClient.SendBulkUpdateInventory(folder);
297 });
298 } 281 }
299 } 282 }
300 else if (im.dialog == (byte) InstantMessageDialog.InventoryDeclined) 283 else if (im.dialog == (byte) InstantMessageDialog.InventoryDeclined ||
284 im.dialog == (byte) InstantMessageDialog.TaskInventoryDeclined)
301 { 285 {
302 // Here, the recipient is local and we can assume that the 286 // Here, the recipient is local and we can assume that the
303 // inventory is loaded. Courtesy of the above bulk update, 287 // inventory is loaded. Courtesy of the above bulk update,
@@ -333,6 +317,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
333 { 317 {
334 folder.ParentID = trashFolder.ID; 318 folder.ParentID = trashFolder.ID;
335 invService.MoveFolder(folder); 319 invService.MoveFolder(folder);
320 client.SendBulkUpdateInventory(folder);
336 } 321 }
337 } 322 }
338 323
@@ -433,22 +418,113 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
433 /// 418 ///
434 /// </summary> 419 /// </summary>
435 /// <param name="msg"></param> 420 /// <param name="msg"></param>
436 private void OnGridInstantMessage(GridInstantMessage msg) 421 private void OnGridInstantMessage(GridInstantMessage im)
437 { 422 {
438 // Check if this is ours to handle 423 // Check if this is ours to handle
439 // 424 //
440 Scene scene = FindClientScene(new UUID(msg.toAgentID)); 425 Scene scene = FindClientScene(new UUID(im.toAgentID));
441 426
442 if (scene == null) 427 if (scene == null)
443 return; 428 return;
444 429
445 // Find agent to deliver to 430 // Find agent to deliver to
446 // 431 //
447 ScenePresence user = scene.GetScenePresence(new UUID(msg.toAgentID)); 432 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID));
433 if (user == null)
434 return;
435
436 // This requires a little bit of processing because we have to make the
437 // new item visible in the recipient's inventory here
438 //
439 if (im.dialog == (byte) InstantMessageDialog.InventoryOffered)
440 {
441 if (im.binaryBucket.Length < 17) // Invalid
442 return;
443
444 UUID recipientID = new UUID(im.toAgentID);
445
446 // First byte is the asset type
447 AssetType assetType = (AssetType)im.binaryBucket[0];
448
449 if (AssetType.Folder == assetType)
450 {
451 UUID folderID = new UUID(im.binaryBucket, 1);
448 452
449 // Just forward to local handling 453 InventoryFolderBase given =
450 OnInstantMessage(user.ControllingClient, msg); 454 new InventoryFolderBase(folderID, recipientID);
455 InventoryFolderBase folder =
456 scene.InventoryService.GetFolder(given);
451 457
458 if (folder != null)
459 user.ControllingClient.SendBulkUpdateInventory(folder);
460 }
461 else
462 {
463 UUID itemID = new UUID(im.binaryBucket, 1);
464
465 InventoryItemBase given =
466 new InventoryItemBase(itemID, recipientID);
467 InventoryItemBase item =
468 scene.InventoryService.GetItem(given);
469
470 if (item != null)
471 {
472 user.ControllingClient.SendBulkUpdateInventory(item);
473 }
474 }
475 user.ControllingClient.SendInstantMessage(im);
476 }
477 if (im.dialog == (byte) InstantMessageDialog.TaskInventoryOffered)
478 {
479 if (im.binaryBucket.Length < 1) // Invalid
480 return;
481
482 UUID recipientID = new UUID(im.toAgentID);
483
484 // Bucket is the asset type
485 AssetType assetType = (AssetType)im.binaryBucket[0];
486
487 if (AssetType.Folder == assetType)
488 {
489 UUID folderID = new UUID(im.imSessionID);
490
491 InventoryFolderBase given =
492 new InventoryFolderBase(folderID, recipientID);
493 InventoryFolderBase folder =
494 scene.InventoryService.GetFolder(given);
495
496 if (folder != null)
497 user.ControllingClient.SendBulkUpdateInventory(folder);
498 }
499 else
500 {
501 UUID itemID = new UUID(im.imSessionID);
502
503 InventoryItemBase given =
504 new InventoryItemBase(itemID, recipientID);
505 InventoryItemBase item =
506 scene.InventoryService.GetItem(given);
507
508 if (item != null)
509 {
510 user.ControllingClient.SendBulkUpdateInventory(item);
511 }
512 }
513
514 // Fix up binary bucket since this may be 17 chars long here
515 Byte[] bucket = new Byte[1];
516 bucket[0] = im.binaryBucket[0];
517 im.binaryBucket = bucket;
518
519 user.ControllingClient.SendInstantMessage(im);
520 }
521 else if (im.dialog == (byte) InstantMessageDialog.InventoryAccepted ||
522 im.dialog == (byte) InstantMessageDialog.InventoryDeclined ||
523 im.dialog == (byte) InstantMessageDialog.TaskInventoryDeclined ||
524 im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted)
525 {
526 user.ControllingClient.SendInstantMessage(im);
527 }
452 } 528 }
453 } 529 }
454} 530}
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
index d295384..dcfdf8f 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
@@ -155,16 +155,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
155 scene.RegionInfo.RegionHandle, 155 scene.RegionInfo.RegionHandle,
156 (uint)presence.AbsolutePosition.X, 156 (uint)presence.AbsolutePosition.X,
157 (uint)presence.AbsolutePosition.Y, 157 (uint)presence.AbsolutePosition.Y,
158 (uint)presence.AbsolutePosition.Z); 158 (uint)presence.AbsolutePosition.Z + 2);
159 159
160 m_log.DebugFormat("TP invite with message {0}", message); 160 m_log.DebugFormat("[LURE]: TP invite with message {0}", message);
161
162 GridInstantMessage m;
163
164 if (scene.Permissions.IsAdministrator(client.AgentId) && presence.GodLevel >= 200 && (!scene.Permissions.IsAdministrator(targetid)))
165 {
166 m = new GridInstantMessage(scene, client.AgentId,
167 client.FirstName+" "+client.LastName, targetid,
168 (byte)InstantMessageDialog.GodLikeRequestTeleport, false,
169 message, dest, false, presence.AbsolutePosition,
170 new Byte[0]);
171 }
172 else
173 {
174 m = new GridInstantMessage(scene, client.AgentId,
175 client.FirstName+" "+client.LastName, targetid,
176 (byte)InstantMessageDialog.RequestTeleport, false,
177 message, dest, false, presence.AbsolutePosition,
178 new Byte[0]);
179 }
161 180
162 GridInstantMessage m = new GridInstantMessage(scene, client.AgentId,
163 client.FirstName+" "+client.LastName, targetid,
164 (byte)InstantMessageDialog.RequestTeleport, false,
165 message, dest, false, presence.AbsolutePosition,
166 new Byte[0]);
167
168 if (m_TransferModule != null) 181 if (m_TransferModule != null)
169 { 182 {
170 m_TransferModule.SendInstantMessage(m, 183 m_TransferModule.SendInstantMessage(m,
@@ -199,7 +212,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
199 { 212 {
200 // Forward remote teleport requests 213 // Forward remote teleport requests
201 // 214 //
202 if (msg.dialog != 22) 215 if (msg.dialog != (byte)InstantMessageDialog.RequestTeleport &&
216 msg.dialog != (byte)InstantMessageDialog.GodLikeRequestTeleport)
203 return; 217 return;
204 218
205 if (m_TransferModule != null) 219 if (m_TransferModule != null)
diff --git a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
index 9d1538f..97cd738 100644
--- a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
@@ -101,7 +101,8 @@ namespace OpenSim.Region.CoreModules.Framework
101 101
102 public void CreateCaps(UUID agentId) 102 public void CreateCaps(UUID agentId)
103 { 103 {
104 if (m_scene.RegionInfo.EstateSettings.IsBanned(agentId)) 104 int flags = m_scene.GetUserFlags(agentId);
105 if (m_scene.RegionInfo.EstateSettings.IsBanned(agentId, flags))
105 return; 106 return;
106 107
107 String capsObjectPath = GetCapsPath(agentId); 108 String capsObjectPath = GetCapsPath(agentId);
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index 928bcd0..f1399af 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -126,7 +126,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
126 126
127 protected virtual void OnNewClient(IClientAPI client) 127 protected virtual void OnNewClient(IClientAPI client)
128 { 128 {
129 client.OnTeleportHomeRequest += TeleportHome; 129 client.OnTeleportHomeRequest += TriggerTeleportHome;
130 client.OnTeleportLandmarkRequest += RequestTeleportLandmark; 130 client.OnTeleportLandmarkRequest += RequestTeleportLandmark;
131 } 131 }
132 132
@@ -204,6 +204,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
204 sp.ControllingClient.SendTeleportStart(teleportFlags); 204 sp.ControllingClient.SendTeleportStart(teleportFlags);
205 205
206 sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags); 206 sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags);
207 sp.TeleportFlags = (Constants.TeleportFlags)teleportFlags;
207 sp.Teleport(position); 208 sp.Teleport(position);
208 209
209 foreach (SceneObjectGroup grp in sp.GetAttachments()) 210 foreach (SceneObjectGroup grp in sp.GetAttachments())
@@ -319,7 +320,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
319 // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field, 320 // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field,
320 // it's actually doing a lot of work. 321 // it's actually doing a lot of work.
321 IPEndPoint endPoint = finalDestination.ExternalEndPoint; 322 IPEndPoint endPoint = finalDestination.ExternalEndPoint;
322 if (endPoint.Address != null) 323 if (endPoint != null && endPoint.Address != null)
323 { 324 {
324 // Fixing a bug where teleporting while sitting results in the avatar ending up removed from 325 // Fixing a bug where teleporting while sitting results in the avatar ending up removed from
325 // both regions 326 // both regions
@@ -630,7 +631,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
630 631
631 #region Teleport Home 632 #region Teleport Home
632 633
633 public virtual void TeleportHome(UUID id, IClientAPI client) 634 public virtual void TriggerTeleportHome(UUID id, IClientAPI client)
635 {
636 TeleportHome(id, client);
637 }
638
639 public virtual bool TeleportHome(UUID id, IClientAPI client)
634 { 640 {
635 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Request to teleport {0} {1} home", client.FirstName, client.LastName); 641 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Request to teleport {0} {1} home", client.FirstName, client.LastName);
636 642
@@ -639,12 +645,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
639 645
640 if (uinfo != null) 646 if (uinfo != null)
641 { 647 {
648 if (uinfo.HomeRegionID == UUID.Zero)
649 {
650 // can't find the Home region: Tell viewer and abort
651 client.SendTeleportFailed("You don't have a home position set.");
652 return false;
653 }
642 GridRegion regionInfo = m_aScene.GridService.GetRegionByUUID(UUID.Zero, uinfo.HomeRegionID); 654 GridRegion regionInfo = m_aScene.GridService.GetRegionByUUID(UUID.Zero, uinfo.HomeRegionID);
643 if (regionInfo == null) 655 if (regionInfo == null)
644 { 656 {
645 // can't find the Home region: Tell viewer and abort 657 // can't find the Home region: Tell viewer and abort
646 client.SendTeleportFailed("Your home region could not be found."); 658 client.SendTeleportFailed("Your home region could not be found.");
647 return; 659 return false;
648 } 660 }
649 661
650 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: User's home region is {0} {1} ({2}-{3})", 662 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: User's home region is {0} {1} ({2}-{3})",
@@ -655,6 +667,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
655 client, regionInfo.RegionHandle, uinfo.HomePosition, uinfo.HomeLookAt, 667 client, regionInfo.RegionHandle, uinfo.HomePosition, uinfo.HomeLookAt,
656 (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome)); 668 (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome));
657 } 669 }
670 else
671 {
672 // can't find the Home region: Tell viewer and abort
673 client.SendTeleportFailed("Your home region could not be found.");
674 return false;
675 }
676 return true;
658 } 677 }
659 678
660 #endregion 679 #endregion
@@ -1124,10 +1143,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1124 agent.Id0 = currentAgentCircuit.Id0; 1143 agent.Id0 = currentAgentCircuit.Id0;
1125 } 1144 }
1126 1145
1127 InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync; 1146 IPEndPoint external = region.ExternalEndPoint;
1128 d.BeginInvoke(sp, agent, region, region.ExternalEndPoint, true, 1147 if (external != null)
1148 {
1149 InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync;
1150 d.BeginInvoke(sp, agent, region, external, true,
1129 InformClientOfNeighbourCompleted, 1151 InformClientOfNeighbourCompleted,
1130 d); 1152 d);
1153 }
1131 } 1154 }
1132 #endregion 1155 #endregion
1133 1156
@@ -1261,6 +1284,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1261 InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync; 1284 InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync;
1262 try 1285 try
1263 { 1286 {
1287 //neighbour.ExternalEndPoint may return null, which will be caught
1264 d.BeginInvoke(sp, cagents[count], neighbour, neighbour.ExternalEndPoint, newAgent, 1288 d.BeginInvoke(sp, cagents[count], neighbour, neighbour.ExternalEndPoint, newAgent,
1265 InformClientOfNeighbourCompleted, 1289 InformClientOfNeighbourCompleted,
1266 d); 1290 d);
@@ -1374,8 +1398,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1374 1398
1375 m_log.Debug("[ENTITY TRANSFER MODULE]: Completed inform client about neighbour " + endPoint.ToString()); 1399 m_log.Debug("[ENTITY TRANSFER MODULE]: Completed inform client about neighbour " + endPoint.ToString());
1376 } 1400 }
1377 if (!regionAccepted)
1378 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Region {0} did not accept agent: {1}", reg.RegionName, reason);
1379 } 1401 }
1380 1402
1381 /// <summary> 1403 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
index 38a7805..5c7ca22 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
@@ -84,7 +84,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
84 84
85 protected override void OnNewClient(IClientAPI client) 85 protected override void OnNewClient(IClientAPI client)
86 { 86 {
87 client.OnTeleportHomeRequest += TeleportHome; 87 client.OnTeleportHomeRequest += TriggerTeleportHome;
88 client.OnTeleportLandmarkRequest += RequestTeleportLandmark; 88 client.OnTeleportLandmarkRequest += RequestTeleportLandmark;
89 client.OnConnectionClosed += new Action<IClientAPI>(OnConnectionClosed); 89 client.OnConnectionClosed += new Action<IClientAPI>(OnConnectionClosed);
90 } 90 }
@@ -182,7 +182,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
182 return m_aScene.SimulationService.CreateAgent(reg, agentCircuit, teleportFlags, out reason); 182 return m_aScene.SimulationService.CreateAgent(reg, agentCircuit, teleportFlags, out reason);
183 } 183 }
184 184
185 public override void TeleportHome(UUID id, IClientAPI client) 185 public void TriggerTeleportHome(UUID id, IClientAPI client)
186 {
187 TeleportHome(id, client);
188 }
189
190 public override bool TeleportHome(UUID id, IClientAPI client)
186 { 191 {
187 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Request to teleport {0} {1} home", client.FirstName, client.LastName); 192 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Request to teleport {0} {1} home", client.FirstName, client.LastName);
188 193
@@ -192,8 +197,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
192 { 197 {
193 // local grid user 198 // local grid user
194 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: User is local"); 199 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: User is local");
195 base.TeleportHome(id, client); 200 return base.TeleportHome(id, client);
196 return;
197 } 201 }
198 202
199 // Foreign user wants to go home 203 // Foreign user wants to go home
@@ -203,7 +207,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
203 { 207 {
204 client.SendTeleportFailed("Your information has been lost"); 208 client.SendTeleportFailed("Your information has been lost");
205 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Unable to locate agent's gateway information"); 209 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Unable to locate agent's gateway information");
206 return; 210 return false;
207 } 211 }
208 212
209 IUserAgentService userAgentService = new UserAgentServiceConnector(aCircuit.ServiceURLs["HomeURI"].ToString()); 213 IUserAgentService userAgentService = new UserAgentServiceConnector(aCircuit.ServiceURLs["HomeURI"].ToString());
@@ -213,7 +217,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
213 { 217 {
214 client.SendTeleportFailed("Your home region could not be found"); 218 client.SendTeleportFailed("Your home region could not be found");
215 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Agent's home region not found"); 219 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Agent's home region not found");
216 return; 220 return false;
217 } 221 }
218 222
219 ScenePresence sp = ((Scene)(client.Scene)).GetScenePresence(client.AgentId); 223 ScenePresence sp = ((Scene)(client.Scene)).GetScenePresence(client.AgentId);
@@ -221,7 +225,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
221 { 225 {
222 client.SendTeleportFailed("Internal error"); 226 client.SendTeleportFailed("Internal error");
223 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Agent not found in the scene where it is supposed to be"); 227 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Agent not found in the scene where it is supposed to be");
224 return; 228 return false;
225 } 229 }
226 230
227 IEventQueue eq = sp.Scene.RequestModuleInterface<IEventQueue>(); 231 IEventQueue eq = sp.Scene.RequestModuleInterface<IEventQueue>();
@@ -231,6 +235,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
231 aCircuit.firstname, aCircuit.lastname, finalDestination.RegionName, homeGatekeeper.ServerURI, homeGatekeeper.RegionName); 235 aCircuit.firstname, aCircuit.lastname, finalDestination.RegionName, homeGatekeeper.ServerURI, homeGatekeeper.RegionName);
232 236
233 DoTeleport(sp, homeGatekeeper, finalDestination, position, lookAt, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome), eq); 237 DoTeleport(sp, homeGatekeeper, finalDestination, position, lookAt, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome), eq);
238 return true;
234 } 239 }
235 240
236 /// <summary> 241 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index 54b422b..7ebf002 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -476,8 +476,17 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
476 IClientAPI remoteClient) 476 IClientAPI remoteClient)
477 { 477 {
478 uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move) | 7; 478 uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move) | 7;
479 // For the porposes of inventory, an object is modify if the prims
480 // are modify. This allows renaming an object that contains no
481 // mod items.
479 foreach (SceneObjectGroup grp in objsForEffectivePermissions) 482 foreach (SceneObjectGroup grp in objsForEffectivePermissions)
480 effectivePerms &= grp.GetEffectivePermissions(); 483 {
484 uint groupPerms = grp.GetEffectivePermissions(true);
485 if ((grp.RootPart.BaseMask & (uint)PermissionMask.Modify) != 0)
486 groupPerms |= (uint)PermissionMask.Modify;
487
488 effectivePerms &= groupPerms;
489 }
481 effectivePerms |= (uint)PermissionMask.Move; 490 effectivePerms |= (uint)PermissionMask.Move;
482 491
483 if (remoteClient != null && (remoteClient.AgentId != so.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions()) 492 if (remoteClient != null && (remoteClient.AgentId != so.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions())
@@ -644,7 +653,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
644 if (so.RootPart.FromFolderID != UUID.Zero) 653 if (so.RootPart.FromFolderID != UUID.Zero)
645 { 654 {
646 InventoryFolderBase f = new InventoryFolderBase(so.RootPart.FromFolderID, userID); 655 InventoryFolderBase f = new InventoryFolderBase(so.RootPart.FromFolderID, userID);
647 folder = m_Scene.InventoryService.GetFolder(f); 656 if (f != null)
657 folder = m_Scene.InventoryService.GetFolder(f);
648 } 658 }
649 } 659 }
650 660
@@ -674,15 +684,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
674 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) 684 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
675 { 685 {
676// m_log.DebugFormat("[INVENTORY ACCESS MODULE]: RezObject for {0}, item {1}", remoteClient.Name, itemID); 686// m_log.DebugFormat("[INVENTORY ACCESS MODULE]: RezObject for {0}, item {1}", remoteClient.Name, itemID);
677
678 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); 687 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId);
679 item = m_Scene.InventoryService.GetItem(item); 688 item = m_Scene.InventoryService.GetItem(item);
680 689
681 if (item == null) 690 if (item == null)
682 { 691 {
683 m_log.WarnFormat(
684 "[InventoryAccessModule]: Could not find item {0} for {1} in RezObject()",
685 itemID, remoteClient.Name);
686 692
687 return null; 693 return null;
688 } 694 }
@@ -782,12 +788,35 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
782 } 788 }
783 } 789 }
784 790
791 int primcount = 0;
792 foreach (SceneObjectGroup g in objlist)
793 primcount += g.PrimCount;
794
795 if (!m_Scene.Permissions.CanRezObject(
796 primcount, remoteClient.AgentId, pos)
797 && !attachment)
798 {
799 // The client operates in no fail mode. It will
800 // have already removed the item from the folder
801 // if it's no copy.
802 // Put it back if it's not an attachment
803 //
804 if (item != null)
805 {
806 if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!attachment))
807 remoteClient.SendBulkUpdateInventory(item);
808 }
809
810 return null;
811 }
812
785 if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, attachment)) 813 if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, attachment))
786 return null; 814 return null;
787 815
788 for (int i = 0; i < objlist.Count; i++) 816 for (int i = 0; i < objlist.Count; i++)
789 { 817 {
790 group = objlist[i]; 818 group = objlist[i];
819 SceneObjectPart rootPart = group.RootPart;
791 820
792// Vector3 storedPosition = group.AbsolutePosition; 821// Vector3 storedPosition = group.AbsolutePosition;
793 if (group.UUID == UUID.Zero) 822 if (group.UUID == UUID.Zero)
@@ -842,8 +871,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
842 871
843 if (!attachment) 872 if (!attachment)
844 { 873 {
845 SceneObjectPart rootPart = group.RootPart;
846
847 if (rootPart.Shape.PCode == (byte)PCode.Prim) 874 if (rootPart.Shape.PCode == (byte)PCode.Prim)
848 group.ClearPartAttachmentData(); 875 group.ClearPartAttachmentData();
849 876
@@ -853,12 +880,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
853 880
854 rootPart.ScheduleFullUpdate(); 881 rootPart.ScheduleFullUpdate();
855 } 882 }
856
857// m_log.DebugFormat(
858// "[InventoryAccessModule]: Rezzed {0} {1} {2} for {3}",
859// group.Name, group.LocalId, group.UUID, remoteClient.Name);
860 } 883 }
861 884
885 group.SetGroup(remoteClient.ActiveGroupId, remoteClient);
886
862 if (item != null) 887 if (item != null)
863 DoPostRezWhenFromItem(item, attachment); 888 DoPostRezWhenFromItem(item, attachment);
864 889
@@ -898,25 +923,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
898 } 923 }
899 } 924 }
900 925
901 int primcount = 0;
902 foreach (SceneObjectGroup g in objlist)
903 primcount += g.PrimCount;
904
905 if (!m_Scene.Permissions.CanRezObject(
906 primcount, remoteClient.AgentId, pos)
907 && !isAttachment)
908 {
909 // The client operates in no fail mode. It will
910 // have already removed the item from the folder
911 // if it's no copy.
912 // Put it back if it's not an attachment
913 //
914 if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!isAttachment))
915 remoteClient.SendBulkUpdateInventory(item);
916
917 return false;
918 }
919
920 for (int i = 0; i < objlist.Count; i++) 926 for (int i = 0; i < objlist.Count; i++)
921 { 927 {
922 SceneObjectGroup so = objlist[i]; 928 SceneObjectGroup so = objlist[i];
@@ -932,14 +938,18 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
932 { 938 {
933 rootPart.Name = item.Name; 939 rootPart.Name = item.Name;
934 rootPart.Description = item.Description; 940 rootPart.Description = item.Description;
935 rootPart.ObjectSaleType = item.SaleType; 941 if ((item.Flags & (uint)InventoryItemFlags.ObjectSlamSale) != 0)
936 rootPart.SalePrice = item.SalePrice; 942 {
943 rootPart.ObjectSaleType = item.SaleType;
944 rootPart.SalePrice = item.SalePrice;
945 }
937 } 946 }
938 947
939 rootPart.FromFolderID = item.Folder; 948 rootPart.FromFolderID = item.Folder;
940 949
941 if ((rootPart.OwnerID != item.Owner) || 950 if ((rootPart.OwnerID != item.Owner) ||
942 (item.CurrentPermissions & 16) != 0) 951 (item.CurrentPermissions & 16) != 0 ||
952 (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0)
943 { 953 {
944 //Need to kill the for sale here 954 //Need to kill the for sale here
945 rootPart.ObjectSaleType = 0; 955 rootPart.ObjectSaleType = 0;
@@ -949,31 +959,43 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
949 { 959 {
950 foreach (SceneObjectPart part in so.Parts) 960 foreach (SceneObjectPart part in so.Parts)
951 { 961 {
952 if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0)
953 {
954 part.EveryoneMask = item.EveryOnePermissions;
955 part.NextOwnerMask = item.NextPermissions;
956 }
957 part.GroupMask = 0; // DO NOT propagate here 962 part.GroupMask = 0; // DO NOT propagate here
963
964 part.LastOwnerID = part.OwnerID;
965 part.OwnerID = item.Owner;
966 part.Inventory.ChangeInventoryOwner(item.Owner);
958 } 967 }
959 968
960 so.ApplyNextOwnerPermissions(); 969 so.ApplyNextOwnerPermissions();
970
971 // In case the user has changed flags on a received item
972 // we have to apply those changes after the slam. Else we
973 // get a net loss of permissions
974 foreach (SceneObjectPart part in so.Parts)
975 {
976 if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0)
977 {
978 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
979 part.EveryoneMask = item.EveryOnePermissions & part.BaseMask;
980 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
981 part.NextOwnerMask = item.NextPermissions & part.BaseMask;
982 }
983 }
961 } 984 }
962 } 985 }
963 986 else
964 foreach (SceneObjectPart part in so.Parts)
965 { 987 {
966 part.FromUserInventoryItemID = fromUserInventoryItemId; 988 foreach (SceneObjectPart part in so.Parts)
967
968 if ((part.OwnerID != item.Owner) ||
969 (item.CurrentPermissions & 16) != 0)
970 { 989 {
971 part.Inventory.ChangeInventoryOwner(item.Owner); 990 part.FromUserInventoryItemID = fromUserInventoryItemId;
972 part.GroupMask = 0; // DO NOT propagate here 991
992 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
993 part.EveryoneMask = item.EveryOnePermissions;
994 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
995 part.NextOwnerMask = item.NextPermissions;
996 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
997 part.GroupMask = item.GroupPermissions;
973 } 998 }
974
975 part.EveryoneMask = item.EveryOnePermissions;
976 part.NextOwnerMask = item.NextPermissions;
977 } 999 }
978 1000
979 rootPart.TrimPermissions(); 1001 rootPart.TrimPermissions();
@@ -1111,4 +1133,4 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
1111 1133
1112 #endregion 1134 #endregion
1113 } 1135 }
1114} \ No newline at end of file 1136}
diff --git a/OpenSim/Region/CoreModules/LightShare/LightShareModule.cs b/OpenSim/Region/CoreModules/LightShare/LightShareModule.cs
index 16cbbf5..f49641f 100644
--- a/OpenSim/Region/CoreModules/LightShare/LightShareModule.cs
+++ b/OpenSim/Region/CoreModules/LightShare/LightShareModule.cs
@@ -170,7 +170,8 @@ namespace OpenSim.Region.CoreModules.World.LightShare
170 170
171 private void EventManager_OnMakeRootAgent(ScenePresence presence) 171 private void EventManager_OnMakeRootAgent(ScenePresence presence)
172 { 172 {
173 m_log.Debug("[WINDLIGHT]: Sending windlight scene to new client"); 173 if (m_enableWindlight && m_scene.RegionInfo.WindlightSettings.valid)
174 m_log.Debug("[WINDLIGHT]: Sending windlight scene to new client");
174 SendProfileToClient(presence.ControllingClient); 175 SendProfileToClient(presence.ControllingClient);
175 } 176 }
176 177
diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
index d328eb3..9dac6b9 100644
--- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
@@ -382,6 +382,10 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
382 try 382 try
383 { 383 {
384 Request = (HttpWebRequest) WebRequest.Create(Url); 384 Request = (HttpWebRequest) WebRequest.Create(Url);
385
386 //This works around some buggy HTTP Servers like Lighttpd
387 Request.ServicePoint.Expect100Continue = false;
388
385 Request.Method = HttpMethod; 389 Request.Method = HttpMethod;
386 Request.ContentType = HttpMIMEType; 390 Request.ContentType = HttpMIMEType;
387 391
@@ -458,15 +462,36 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
458 462
459 // continue building the string 463 // continue building the string
460 sb.Append(tempString); 464 sb.Append(tempString);
465 if (sb.Length > 2048)
466 break;
461 } 467 }
462 } while (count > 0); // any more data to read? 468 } while (count > 0); // any more data to read?
463 469
464 ResponseBody = sb.ToString(); 470 ResponseBody = sb.ToString().Replace("\r", "");
465 } 471 }
466 catch (Exception e) 472 catch (Exception e)
467 { 473 {
468 Status = (int)OSHttpStatusCode.ClientErrorJoker; 474 if (e is WebException && ((WebException)e).Status == WebExceptionStatus.ProtocolError)
469 ResponseBody = e.Message; 475 {
476 HttpWebResponse webRsp = (HttpWebResponse)((WebException)e).Response;
477 Status = (int)webRsp.StatusCode;
478 try
479 {
480 using (Stream responseStream = webRsp.GetResponseStream())
481 {
482 ResponseBody = responseStream.GetStreamString();
483 }
484 }
485 catch
486 {
487 ResponseBody = webRsp.StatusDescription;
488 }
489 }
490 else
491 {
492 Status = (int)OSHttpStatusCode.ClientErrorJoker;
493 ResponseBody = e.Message;
494 }
470 495
471 _finished = true; 496 _finished = true;
472 return; 497 return;
diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
index 93e75b3..f4cf6b4 100644
--- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
@@ -61,6 +61,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
61 //public ManualResetEvent ev; 61 //public ManualResetEvent ev;
62 public bool requestDone; 62 public bool requestDone;
63 public int startTime; 63 public int startTime;
64 public bool responseSent;
64 public string uri; 65 public string uri;
65 } 66 }
66 67
@@ -77,7 +78,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
77 new Dictionary<string, UrlData>(); 78 new Dictionary<string, UrlData>();
78 79
79 80
80 private int m_TotalUrls = 100; 81 private int m_TotalUrls = 5000;
81 82
82 private uint https_port = 0; 83 private uint https_port = 0;
83 private IHttpServer m_HttpServer = null; 84 private IHttpServer m_HttpServer = null;
@@ -157,7 +158,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
157 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); 158 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" });
158 return urlcode; 159 return urlcode;
159 } 160 }
160 string url = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + "/lslhttp/" + urlcode.ToString() + "/"; 161 string url = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + "/lslhttp/" + urlcode.ToString();
161 162
162 UrlData urlData = new UrlData(); 163 UrlData urlData = new UrlData();
163 urlData.hostID = host.UUID; 164 urlData.hostID = host.UUID;
@@ -166,10 +167,10 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
166 urlData.url = url; 167 urlData.url = url;
167 urlData.urlcode = urlcode; 168 urlData.urlcode = urlcode;
168 urlData.requests = new Dictionary<UUID, RequestData>(); 169 urlData.requests = new Dictionary<UUID, RequestData>();
169 170
170 m_UrlMap[url] = urlData; 171 m_UrlMap[url] = urlData;
171 172
172 string uri = "/lslhttp/" + urlcode.ToString() + "/"; 173 string uri = "/lslhttp/" + urlcode.ToString();
173 174
174 m_HttpServer.AddPollServiceHTTPHandler( 175 m_HttpServer.AddPollServiceHTTPHandler(
175 uri, 176 uri,
@@ -234,9 +235,12 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
234 return; 235 return;
235 } 236 }
236 237
237 foreach (UUID req in data.requests.Keys) 238 lock (m_RequestMap)
238 m_RequestMap.Remove(req); 239 {
239 240 foreach (UUID req in data.requests.Keys)
241 m_RequestMap.Remove(req);
242 }
243
240 RemoveUrl(data); 244 RemoveUrl(data);
241 m_UrlMap.Remove(url); 245 m_UrlMap.Remove(url);
242 } 246 }
@@ -244,32 +248,42 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
244 248
245 public void HttpResponse(UUID request, int status, string body) 249 public void HttpResponse(UUID request, int status, string body)
246 { 250 {
247 if (m_RequestMap.ContainsKey(request)) 251 lock (m_RequestMap)
248 {
249 UrlData urlData = m_RequestMap[request];
250 urlData.requests[request].responseCode = status;
251 urlData.requests[request].responseBody = body;
252 //urlData.requests[request].ev.Set();
253 urlData.requests[request].requestDone =true;
254 }
255 else
256 { 252 {
257 m_log.Info("[HttpRequestHandler] There is no http-in request with id " + request.ToString()); 253 if (m_RequestMap.ContainsKey(request))
254 {
255 UrlData urlData = m_RequestMap[request];
256 if (!urlData.requests[request].responseSent)
257 {
258 urlData.requests[request].responseCode = status;
259 urlData.requests[request].responseBody = body;
260 //urlData.requests[request].ev.Set();
261 urlData.requests[request].requestDone = true;
262 urlData.requests[request].responseSent = true;
263 }
264 }
265 else
266 {
267 m_log.Info("[HttpRequestHandler] There is no http-in request with id " + request.ToString());
268 }
258 } 269 }
259 } 270 }
260 271
261 public string GetHttpHeader(UUID requestId, string header) 272 public string GetHttpHeader(UUID requestId, string header)
262 { 273 {
263 if (m_RequestMap.ContainsKey(requestId)) 274 lock (m_RequestMap)
264 {
265 UrlData urlData=m_RequestMap[requestId];
266 string value;
267 if (urlData.requests[requestId].headers.TryGetValue(header,out value))
268 return value;
269 }
270 else
271 { 275 {
272 m_log.Warn("[HttpRequestHandler] There was no http-in request with id " + requestId); 276 if (m_RequestMap.ContainsKey(requestId))
277 {
278 UrlData urlData = m_RequestMap[requestId];
279 string value;
280 if (urlData.requests[requestId].headers.TryGetValue(header, out value))
281 return value;
282 }
283 else
284 {
285 m_log.Warn("[HttpRequestHandler] There was no http-in request with id " + requestId);
286 }
273 } 287 }
274 return String.Empty; 288 return String.Empty;
275 } 289 }
@@ -293,8 +307,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
293 { 307 {
294 RemoveUrl(url.Value); 308 RemoveUrl(url.Value);
295 removeURLs.Add(url.Key); 309 removeURLs.Add(url.Key);
296 foreach (UUID req in url.Value.requests.Keys) 310 lock (m_RequestMap)
297 m_RequestMap.Remove(req); 311 {
312 foreach (UUID req in url.Value.requests.Keys)
313 m_RequestMap.Remove(req);
314 }
298 } 315 }
299 } 316 }
300 317
@@ -315,8 +332,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
315 { 332 {
316 RemoveUrl(url.Value); 333 RemoveUrl(url.Value);
317 removeURLs.Add(url.Key); 334 removeURLs.Add(url.Key);
318 foreach (UUID req in url.Value.requests.Keys) 335 lock (m_RequestMap)
319 m_RequestMap.Remove(req); 336 {
337 foreach (UUID req in url.Value.requests.Keys)
338 m_RequestMap.Remove(req);
339 }
320 } 340 }
321 } 341 }
322 342
@@ -335,14 +355,16 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
335 { 355 {
336 Hashtable response = new Hashtable(); 356 Hashtable response = new Hashtable();
337 UrlData url; 357 UrlData url;
358 int startTime = 0;
338 lock (m_RequestMap) 359 lock (m_RequestMap)
339 { 360 {
340 if (!m_RequestMap.ContainsKey(requestID)) 361 if (!m_RequestMap.ContainsKey(requestID))
341 return response; 362 return response;
342 url = m_RequestMap[requestID]; 363 url = m_RequestMap[requestID];
364 startTime = url.requests[requestID].startTime;
343 } 365 }
344 366
345 if (System.Environment.TickCount - url.requests[requestID].startTime > 25000) 367 if (System.Environment.TickCount - startTime > 25000)
346 { 368 {
347 response["int_response_code"] = 500; 369 response["int_response_code"] = 500;
348 response["str_response_string"] = "Script timeout"; 370 response["str_response_string"] = "Script timeout";
@@ -351,9 +373,12 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
351 response["reusecontext"] = false; 373 response["reusecontext"] = false;
352 374
353 //remove from map 375 //remove from map
354 lock (url) 376 lock (url.requests)
355 { 377 {
356 url.requests.Remove(requestID); 378 url.requests.Remove(requestID);
379 }
380 lock (m_RequestMap)
381 {
357 m_RequestMap.Remove(requestID); 382 m_RequestMap.Remove(requestID);
358 } 383 }
359 384
@@ -375,22 +400,25 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
375 return false; 400 return false;
376 } 401 }
377 url = m_RequestMap[requestID]; 402 url = m_RequestMap[requestID];
403 }
404 lock (url.requests)
405 {
378 if (!url.requests.ContainsKey(requestID)) 406 if (!url.requests.ContainsKey(requestID))
379 { 407 {
380 return false; 408 return false;
381 } 409 }
410 else
411 {
412 if (System.Environment.TickCount - url.requests[requestID].startTime > 25000)
413 {
414 return true;
415 }
416 if (url.requests[requestID].requestDone)
417 return true;
418 else
419 return false;
420 }
382 } 421 }
383
384 if (System.Environment.TickCount-url.requests[requestID].startTime>25000)
385 {
386 return true;
387 }
388
389 if (url.requests[requestID].requestDone)
390 return true;
391 else
392 return false;
393
394 } 422 }
395 private Hashtable GetEvents(UUID requestID, UUID sessionID, string request) 423 private Hashtable GetEvents(UUID requestID, UUID sessionID, string request)
396 { 424 {
@@ -402,9 +430,12 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
402 if (!m_RequestMap.ContainsKey(requestID)) 430 if (!m_RequestMap.ContainsKey(requestID))
403 return NoEvents(requestID,sessionID); 431 return NoEvents(requestID,sessionID);
404 url = m_RequestMap[requestID]; 432 url = m_RequestMap[requestID];
433 }
434 lock (url.requests)
435 {
405 requestData = url.requests[requestID]; 436 requestData = url.requests[requestID];
406 } 437 }
407 438
408 if (!requestData.requestDone) 439 if (!requestData.requestDone)
409 return NoEvents(requestID,sessionID); 440 return NoEvents(requestID,sessionID);
410 441
@@ -427,14 +458,18 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
427 response["reusecontext"] = false; 458 response["reusecontext"] = false;
428 459
429 //remove from map 460 //remove from map
430 lock (url) 461 lock (url.requests)
431 { 462 {
432 url.requests.Remove(requestID); 463 url.requests.Remove(requestID);
464 }
465 lock (m_RequestMap)
466 {
433 m_RequestMap.Remove(requestID); 467 m_RequestMap.Remove(requestID);
434 } 468 }
435 469
436 return response; 470 return response;
437 } 471 }
472
438 public void HttpRequestHandler(UUID requestID, Hashtable request) 473 public void HttpRequestHandler(UUID requestID, Hashtable request)
439 { 474 {
440 lock (request) 475 lock (request)
@@ -450,8 +485,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
450 485
451 int pos1 = uri.IndexOf("/");// /lslhttp 486 int pos1 = uri.IndexOf("/");// /lslhttp
452 int pos2 = uri.IndexOf("/", pos1 + 1);// /lslhttp/ 487 int pos2 = uri.IndexOf("/", pos1 + 1);// /lslhttp/
453 int pos3 = uri.IndexOf("/", pos2 + 1);// /lslhttp/<UUID>/ 488 int pos3 = pos2 + 37; // /lslhttp/urlcode
454 string uri_tmp = uri.Substring(0, pos3 + 1); 489 string uri_tmp = uri.Substring(0, pos3);
455 //HTTP server code doesn't provide us with QueryStrings 490 //HTTP server code doesn't provide us with QueryStrings
456 string pathInfo; 491 string pathInfo;
457 string queryString; 492 string queryString;
@@ -460,10 +495,21 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
460 pathInfo = uri.Substring(pos3); 495 pathInfo = uri.Substring(pos3);
461 496
462 UrlData url = null; 497 UrlData url = null;
498 string urlkey;
463 if (!is_ssl) 499 if (!is_ssl)
464 url = m_UrlMap["http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri_tmp]; 500 urlkey = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri_tmp;
501 //m_UrlMap[];
465 else 502 else
466 url = m_UrlMap["https://" + m_ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + uri_tmp]; 503 urlkey = "https://" + m_ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + uri_tmp;
504
505 if (m_UrlMap.ContainsKey(urlkey))
506 {
507 url = m_UrlMap[urlkey];
508 }
509 else
510 {
511 m_log.Warn("[HttpRequestHandler]: http-in request failed; no such url: "+urlkey.ToString());
512 }
467 513
468 //for llGetHttpHeader support we need to store original URI here 514 //for llGetHttpHeader support we need to store original URI here
469 //to make x-path-info / x-query-string / x-script-url / x-remote-ip headers 515 //to make x-path-info / x-query-string / x-script-url / x-remote-ip headers
@@ -493,7 +539,14 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
493 if (request.ContainsKey(key)) 539 if (request.ContainsKey(key))
494 { 540 {
495 string val = (String)request[key]; 541 string val = (String)request[key];
496 queryString = queryString + key + "=" + val + "&"; 542 if (key != "")
543 {
544 queryString = queryString + key + "=" + val + "&";
545 }
546 else
547 {
548 queryString = queryString + val + "&";
549 }
497 } 550 }
498 } 551 }
499 if (queryString.Length > 1) 552 if (queryString.Length > 1)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
index a17c6ae..faa1def 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
@@ -271,7 +271,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
271 if (s.RegionInfo.RegionID == destination.RegionID) 271 if (s.RegionInfo.RegionID == destination.RegionID)
272 return s.QueryAccess(id, position, out reason); 272 return s.QueryAccess(id, position, out reason);
273 } 273 }
274 //m_log.Debug("[LOCAL COMMS]: region not found for QueryAccess");
275 return false; 274 return false;
276 } 275 }
277 276
@@ -301,10 +300,24 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
301 if (s.RegionInfo.RegionID == destination.RegionID) 300 if (s.RegionInfo.RegionID == destination.RegionID)
302 { 301 {
303 //m_log.Debug("[LOCAL COMMS]: Found region to SendCloseAgent"); 302 //m_log.Debug("[LOCAL COMMS]: Found region to SendCloseAgent");
304 // Let's spawn a threadlet right here, because this may take 303 return s.IncomingCloseAgent(id);
305 // a while 304 }
306 Util.FireAndForget(delegate { s.IncomingCloseAgent(id); }); 305 }
307 return true; 306 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent");
307 return false;
308 }
309
310 public bool CloseChildAgent(GridRegion destination, UUID id)
311 {
312 if (destination == null)
313 return false;
314
315 foreach (Scene s in m_sceneList)
316 {
317 if (s.RegionInfo.RegionID == destination.RegionID)
318 {
319 //m_log.Debug("[LOCAL COMMS]: Found region to SendCloseAgent");
320 return s.IncomingCloseChildAgent(id);
308 } 321 }
309 } 322 }
310 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent"); 323 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent");
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
index f8cea71..391b1a1 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
@@ -261,6 +261,21 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
261 return false; 261 return false;
262 } 262 }
263 263
264 public bool CloseChildAgent(GridRegion destination, UUID id)
265 {
266 if (destination == null)
267 return false;
268
269 // Try local first
270 if (m_localBackend.CloseChildAgent(destination, id))
271 return true;
272
273 // else do the remote thing
274 if (!m_localBackend.IsLocalRegion(destination.RegionHandle))
275 return m_remoteConnector.CloseChildAgent(destination, id);
276
277 return false;
278 }
264 279
265 public bool CloseAgent(GridRegion destination, UUID id) 280 public bool CloseAgent(GridRegion destination, UUID id)
266 { 281 {
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs
index 0a0ce3c..1ffd480 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs
@@ -127,6 +127,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
127 // FIXME: Why do we bother setting this module and caching up if we just end up registering the inner 127 // FIXME: Why do we bother setting this module and caching up if we just end up registering the inner
128 // user account service?! 128 // user account service?!
129 scene.RegisterModuleInterface<IUserAccountService>(UserAccountService); 129 scene.RegisterModuleInterface<IUserAccountService>(UserAccountService);
130 scene.RegisterModuleInterface<IUserAccountCacheModule>(m_Cache);
130 } 131 }
131 132
132 public void RemoveRegion(Scene scene) 133 public void RemoveRegion(Scene scene)
@@ -179,6 +180,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
179 return UserAccountService.GetUserAccount(scopeID, Email); 180 return UserAccountService.GetUserAccount(scopeID, Email);
180 } 181 }
181 182
183 public List<UserAccount> GetUserAccountsWhere(UUID scopeID, string query)
184 {
185 return null;
186 }
187
182 public List<UserAccount> GetUserAccounts(UUID scopeID, string query) 188 public List<UserAccount> GetUserAccounts(UUID scopeID, string query)
183 { 189 {
184 return UserAccountService.GetUserAccounts(scopeID, query); 190 return UserAccountService.GetUserAccounts(scopeID, query);
@@ -193,4 +199,4 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
193 199
194 #endregion 200 #endregion
195 } 201 }
196} \ No newline at end of file 202}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs
index 3321b38..f6b6aeb 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs
@@ -33,6 +33,7 @@ using OpenSim.Region.Framework.Interfaces;
33using OpenSim.Region.Framework.Scenes; 33using OpenSim.Region.Framework.Scenes;
34using OpenSim.Services.Interfaces; 34using OpenSim.Services.Interfaces;
35using OpenSim.Services.Connectors; 35using OpenSim.Services.Connectors;
36using OpenSim.Framework;
36 37
37using OpenMetaverse; 38using OpenMetaverse;
38 39
@@ -101,6 +102,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
101 return; 102 return;
102 103
103 scene.RegisterModuleInterface<IUserAccountService>(this); 104 scene.RegisterModuleInterface<IUserAccountService>(this);
105 scene.RegisterModuleInterface<IUserAccountCacheModule>(m_Cache);
106
107 scene.EventManager.OnNewClient += OnNewClient;
104 } 108 }
105 109
106 public void RemoveRegion(Scene scene) 110 public void RemoveRegion(Scene scene)
@@ -115,6 +119,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
115 return; 119 return;
116 } 120 }
117 121
122 // When a user actually enters the sim, clear them from
123 // cache so the sim will have the current values for
124 // flags, title, etc. And country, don't forget country!
125 private void OnNewClient(IClientAPI client)
126 {
127 m_Cache.Remove(client.Name);
128 }
129
118 #region Overwritten methods from IUserAccountService 130 #region Overwritten methods from IUserAccountService
119 131
120 public override UserAccount GetUserAccount(UUID scopeID, UUID userID) 132 public override UserAccount GetUserAccount(UUID scopeID, UUID userID)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs
index ddef75f..cbe2eaa 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs
@@ -34,7 +34,7 @@ using log4net;
34 34
35namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts 35namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
36{ 36{
37 public class UserAccountCache 37 public class UserAccountCache : IUserAccountCacheModule
38 { 38 {
39 private const double CACHE_EXPIRATION_SECONDS = 120000.0; // 33 hours! 39 private const double CACHE_EXPIRATION_SECONDS = 120000.0; // 33 hours!
40 40
@@ -92,5 +92,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
92 92
93 return null; 93 return null;
94 } 94 }
95
96 public void Remove(string name)
97 {
98 if (!m_NameCache.Contains(name))
99 return;
100
101 UUID uuid = UUID.Zero;
102 if (m_NameCache.TryGetValue(name, out uuid))
103 {
104 m_NameCache.Remove(name);
105 m_UUIDCache.Remove(uuid);
106 }
107 }
95 } 108 }
96} 109}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index a6dbaba..38db239 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -298,6 +298,23 @@ namespace OpenSim.Region.CoreModules.World.Archiver
298 // being no copy/no mod for everyone 298 // being no copy/no mod for everyone
299 lock (part.TaskInventory) 299 lock (part.TaskInventory)
300 { 300 {
301 if (!ResolveUserUuid(part.CreatorID))
302 part.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner;
303
304 if (!ResolveUserUuid(part.OwnerID))
305 part.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
306
307 if (!ResolveUserUuid(part.LastOwnerID))
308 part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
309
310 // And zap any troublesome sit target information
311 part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
312 part.SitTargetPosition = new Vector3(0, 0, 0);
313
314 // Fix ownership/creator of inventory items
315 // Not doing so results in inventory items
316 // being no copy/no mod for everyone
317 part.TaskInventory.LockItemsForRead(true);
301 TaskInventoryDictionary inv = part.TaskInventory; 318 TaskInventoryDictionary inv = part.TaskInventory;
302 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv) 319 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv)
303 { 320 {
@@ -313,6 +330,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
313 if (UserManager != null) 330 if (UserManager != null)
314 UserManager.AddUser(kvp.Value.CreatorID, kvp.Value.CreatorData); 331 UserManager.AddUser(kvp.Value.CreatorID, kvp.Value.CreatorData);
315 } 332 }
333 part.TaskInventory.LockItemsForRead(false);
316 } 334 }
317 } 335 }
318 336
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
index 948aac8..900260d 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
@@ -251,18 +251,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver
251 251
252 if (asset != null) 252 if (asset != null)
253 { 253 {
254 if (m_options.ContainsKey("verbose")) 254// m_log.DebugFormat("[ARCHIVER]: Writing asset {0}", id);
255 m_log.InfoFormat("[ARCHIVER]: Writing asset {0}", id);
256
257 m_foundAssetUuids.Add(asset.FullID); 255 m_foundAssetUuids.Add(asset.FullID);
258 256
259 m_assetsArchiver.WriteAsset(PostProcess(asset)); 257 m_assetsArchiver.WriteAsset(PostProcess(asset));
260 } 258 }
261 else 259 else
262 { 260 {
263 if (m_options.ContainsKey("verbose")) 261// m_log.DebugFormat("[ARCHIVER]: Recording asset {0} as not found", id);
264 m_log.InfoFormat("[ARCHIVER]: Recording asset {0} as not found", id);
265
266 m_notFoundAssetUuids.Add(new UUID(id)); 262 m_notFoundAssetUuids.Add(new UUID(id));
267 } 263 }
268 264
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index 2e1487f..d5e3314 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -30,6 +30,7 @@ using System.Collections.Generic;
30using System.IO; 30using System.IO;
31using System.Reflection; 31using System.Reflection;
32using System.Security; 32using System.Security;
33using System.Timers;
33using log4net; 34using log4net;
34using Mono.Addins; 35using Mono.Addins;
35using Nini.Config; 36using Nini.Config;
@@ -47,6 +48,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
47 48
48 private delegate void LookupUUIDS(List<UUID> uuidLst); 49 private delegate void LookupUUIDS(List<UUID> uuidLst);
49 50
51 private Timer m_regionChangeTimer = new Timer();
50 public Scene Scene { get; private set; } 52 public Scene Scene { get; private set; }
51 public IUserManagement UserManager { get; private set; } 53 public IUserManagement UserManager { get; private set; }
52 54
@@ -61,6 +63,12 @@ namespace OpenSim.Region.CoreModules.World.Estate
61 63
62 #region Packet Data Responders 64 #region Packet Data Responders
63 65
66 private void clientSendDetailedEstateData(IClientAPI remote_client, UUID invoice)
67 {
68 sendDetailedEstateData(remote_client, invoice);
69 sendEstateLists(remote_client, invoice);
70 }
71
64 private void sendDetailedEstateData(IClientAPI remote_client, UUID invoice) 72 private void sendDetailedEstateData(IClientAPI remote_client, UUID invoice)
65 { 73 {
66 uint sun = 0; 74 uint sun = 0;
@@ -82,7 +90,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
82 Scene.RegionInfo.RegionSettings.Covenant, 90 Scene.RegionInfo.RegionSettings.Covenant,
83 Scene.RegionInfo.EstateSettings.AbuseEmail, 91 Scene.RegionInfo.EstateSettings.AbuseEmail,
84 estateOwner); 92 estateOwner);
93 }
85 94
95 private void sendEstateLists(IClientAPI remote_client, UUID invoice)
96 {
86 remote_client.SendEstateList(invoice, 97 remote_client.SendEstateList(invoice,
87 (int)Constants.EstateAccessCodex.EstateManagers, 98 (int)Constants.EstateAccessCodex.EstateManagers,
88 Scene.RegionInfo.EstateSettings.EstateManagers, 99 Scene.RegionInfo.EstateSettings.EstateManagers,
@@ -245,6 +256,12 @@ namespace OpenSim.Region.CoreModules.World.Estate
245 IRestartModule restartModule = Scene.RequestModuleInterface<IRestartModule>(); 256 IRestartModule restartModule = Scene.RequestModuleInterface<IRestartModule>();
246 if (restartModule != null) 257 if (restartModule != null)
247 { 258 {
259 if (timeInSeconds == -1)
260 {
261 restartModule.AbortRestart("Restart aborted by region manager");
262 return;
263 }
264
248 List<int> times = new List<int>(); 265 List<int> times = new List<int>();
249 while (timeInSeconds > 0) 266 while (timeInSeconds > 0)
250 { 267 {
@@ -257,7 +274,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
257 timeInSeconds -= 15; 274 timeInSeconds -= 15;
258 } 275 }
259 276
260 restartModule.ScheduleRestart(UUID.Zero, "Region will restart in {0}", times.ToArray(), true); 277 restartModule.ScheduleRestart(UUID.Zero, "Region will restart in {0}", times.ToArray(), false);
261 } 278 }
262 } 279 }
263 280
@@ -464,7 +481,11 @@ namespace OpenSim.Region.CoreModules.World.Estate
464 { 481 {
465 if (!s.IsChildAgent) 482 if (!s.IsChildAgent)
466 { 483 {
467 Scene.TeleportClientHome(user, s.ControllingClient); 484 if (!Scene.TeleportClientHome(user, s.ControllingClient))
485 {
486 s.ControllingClient.Kick("Your access to the region was revoked and TP home failed - you have been logged out.");
487 s.ControllingClient.Close();
488 }
468 } 489 }
469 } 490 }
470 491
@@ -473,7 +494,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
473 { 494 {
474 remote_client.SendAlertMessage("User is already on the region ban list"); 495 remote_client.SendAlertMessage("User is already on the region ban list");
475 } 496 }
476 //m_scene.RegionInfo.regionBanlist.Add(Manager(user); 497 //Scene.RegionInfo.regionBanlist.Add(Manager(user);
477 remote_client.SendBannedUserList(invoice, Scene.RegionInfo.EstateSettings.EstateBans, Scene.RegionInfo.EstateSettings.EstateID); 498 remote_client.SendBannedUserList(invoice, Scene.RegionInfo.EstateSettings.EstateBans, Scene.RegionInfo.EstateSettings.EstateID);
478 } 499 }
479 else 500 else
@@ -528,7 +549,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
528 remote_client.SendAlertMessage("User is not on the region ban list"); 549 remote_client.SendAlertMessage("User is not on the region ban list");
529 } 550 }
530 551
531 //m_scene.RegionInfo.regionBanlist.Add(Manager(user); 552 //Scene.RegionInfo.regionBanlist.Add(Manager(user);
532 remote_client.SendBannedUserList(invoice, Scene.RegionInfo.EstateSettings.EstateBans, Scene.RegionInfo.EstateSettings.EstateID); 553 remote_client.SendBannedUserList(invoice, Scene.RegionInfo.EstateSettings.EstateBans, Scene.RegionInfo.EstateSettings.EstateID);
533 } 554 }
534 else 555 else
@@ -693,7 +714,11 @@ namespace OpenSim.Region.CoreModules.World.Estate
693 ScenePresence s = Scene.GetScenePresence(prey); 714 ScenePresence s = Scene.GetScenePresence(prey);
694 if (s != null) 715 if (s != null)
695 { 716 {
696 Scene.TeleportClientHome(prey, s.ControllingClient); 717 if (!Scene.TeleportClientHome(prey, s.ControllingClient))
718 {
719 s.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out.");
720 s.ControllingClient.Close();
721 }
697 } 722 }
698 } 723 }
699 } 724 }
@@ -711,7 +736,13 @@ namespace OpenSim.Region.CoreModules.World.Estate
711 // Also make sure they are actually in the region 736 // Also make sure they are actually in the region
712 ScenePresence p; 737 ScenePresence p;
713 if(Scene.TryGetScenePresence(client.AgentId, out p)) 738 if(Scene.TryGetScenePresence(client.AgentId, out p))
714 Scene.TeleportClientHome(p.UUID, p.ControllingClient); 739 {
740 if (!Scene.TeleportClientHome(p.UUID, p.ControllingClient))
741 {
742 p.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out.");
743 p.ControllingClient.Close();
744 }
745 }
715 } 746 }
716 }); 747 });
717 } 748 }
@@ -955,7 +986,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
955 986
956 for (int i = 0; i < uuidarr.Length; i++) 987 for (int i = 0; i < uuidarr.Length; i++)
957 { 988 {
958 // string lookupname = m_scene.CommsManager.UUIDNameRequestString(uuidarr[i]); 989 // string lookupname = Scene.CommsManager.UUIDNameRequestString(uuidarr[i]);
959 990
960 IUserManagement userManager = Scene.RequestModuleInterface<IUserManagement>(); 991 IUserManagement userManager = Scene.RequestModuleInterface<IUserManagement>();
961 if (userManager != null) 992 if (userManager != null)
@@ -1096,6 +1127,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
1096 1127
1097 public void AddRegion(Scene scene) 1128 public void AddRegion(Scene scene)
1098 { 1129 {
1130 m_regionChangeTimer.AutoReset = false;
1131 m_regionChangeTimer.Interval = 2000;
1132 m_regionChangeTimer.Elapsed += RaiseRegionInfoChange;
1133
1099 Scene = scene; 1134 Scene = scene;
1100 Scene.RegisterModuleInterface<IEstateModule>(this); 1135 Scene.RegisterModuleInterface<IEstateModule>(this);
1101 Scene.EventManager.OnNewClient += EventManager_OnNewClient; 1136 Scene.EventManager.OnNewClient += EventManager_OnNewClient;
@@ -1146,7 +1181,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
1146 1181
1147 private void EventManager_OnNewClient(IClientAPI client) 1182 private void EventManager_OnNewClient(IClientAPI client)
1148 { 1183 {
1149 client.OnDetailedEstateDataRequest += sendDetailedEstateData; 1184 client.OnDetailedEstateDataRequest += clientSendDetailedEstateData;
1150 client.OnSetEstateFlagsRequest += estateSetRegionInfoHandler; 1185 client.OnSetEstateFlagsRequest += estateSetRegionInfoHandler;
1151// client.OnSetEstateTerrainBaseTexture += setEstateTerrainBaseTexture; 1186// client.OnSetEstateTerrainBaseTexture += setEstateTerrainBaseTexture;
1152 client.OnSetEstateTerrainDetailTexture += setEstateTerrainBaseTexture; 1187 client.OnSetEstateTerrainDetailTexture += setEstateTerrainBaseTexture;
@@ -1198,6 +1233,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
1198 flags |= RegionFlags.AllowParcelChanges; 1233 flags |= RegionFlags.AllowParcelChanges;
1199 if (Scene.RegionInfo.RegionSettings.BlockShowInSearch) 1234 if (Scene.RegionInfo.RegionSettings.BlockShowInSearch)
1200 flags |= RegionFlags.BlockParcelSearch; 1235 flags |= RegionFlags.BlockParcelSearch;
1236 if (Scene.RegionInfo.RegionSettings.GodBlockSearch)
1237 flags |= (RegionFlags)(1 << 11);
1238 if (Scene.RegionInfo.RegionSettings.Casino)
1239 flags |= (RegionFlags)(1 << 10);
1201 1240
1202 if (Scene.RegionInfo.RegionSettings.FixedSun) 1241 if (Scene.RegionInfo.RegionSettings.FixedSun)
1203 flags |= RegionFlags.SunFixed; 1242 flags |= RegionFlags.SunFixed;
@@ -1205,11 +1244,15 @@ namespace OpenSim.Region.CoreModules.World.Estate
1205 flags |= RegionFlags.Sandbox; 1244 flags |= RegionFlags.Sandbox;
1206 if (Scene.RegionInfo.EstateSettings.AllowVoice) 1245 if (Scene.RegionInfo.EstateSettings.AllowVoice)
1207 flags |= RegionFlags.AllowVoice; 1246 flags |= RegionFlags.AllowVoice;
1247 if (Scene.RegionInfo.EstateSettings.AllowLandmark)
1248 flags |= RegionFlags.AllowLandmark;
1249 if (Scene.RegionInfo.EstateSettings.AllowSetHome)
1250 flags |= RegionFlags.AllowSetHome;
1251 if (Scene.RegionInfo.EstateSettings.BlockDwell)
1252 flags |= RegionFlags.BlockDwell;
1253 if (Scene.RegionInfo.EstateSettings.ResetHomeOnTeleport)
1254 flags |= RegionFlags.ResetHomeOnTeleport;
1208 1255
1209 // Fudge these to always on, so the menu options activate
1210 //
1211 flags |= RegionFlags.AllowLandmark;
1212 flags |= RegionFlags.AllowSetHome;
1213 1256
1214 // TODO: SkipUpdateInterestList 1257 // TODO: SkipUpdateInterestList
1215 1258
@@ -1250,6 +1293,12 @@ namespace OpenSim.Region.CoreModules.World.Estate
1250 flags |= RegionFlags.ResetHomeOnTeleport; 1293 flags |= RegionFlags.ResetHomeOnTeleport;
1251 if (Scene.RegionInfo.EstateSettings.TaxFree) 1294 if (Scene.RegionInfo.EstateSettings.TaxFree)
1252 flags |= RegionFlags.TaxFree; 1295 flags |= RegionFlags.TaxFree;
1296 if (Scene.RegionInfo.EstateSettings.AllowLandmark)
1297 flags |= RegionFlags.AllowLandmark;
1298 if (Scene.RegionInfo.EstateSettings.AllowParcelChanges)
1299 flags |= RegionFlags.AllowParcelChanges;
1300 if (Scene.RegionInfo.EstateSettings.AllowSetHome)
1301 flags |= RegionFlags.AllowSetHome;
1253 if (Scene.RegionInfo.EstateSettings.DenyMinors) 1302 if (Scene.RegionInfo.EstateSettings.DenyMinors)
1254 flags |= (RegionFlags)(1 << 30); 1303 flags |= (RegionFlags)(1 << 30);
1255 1304
@@ -1270,6 +1319,12 @@ namespace OpenSim.Region.CoreModules.World.Estate
1270 1319
1271 public void TriggerRegionInfoChange() 1320 public void TriggerRegionInfoChange()
1272 { 1321 {
1322 m_regionChangeTimer.Stop();
1323 m_regionChangeTimer.Start();
1324 }
1325
1326 protected void RaiseRegionInfoChange(object sender, ElapsedEventArgs e)
1327 {
1273 ChangeDelegate change = OnRegionInfoChange; 1328 ChangeDelegate change = OnRegionInfoChange;
1274 1329
1275 if (change != null) 1330 if (change != null)
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index 94bba83..7a236bc 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
@@ -91,6 +91,8 @@ namespace OpenSim.Region.CoreModules.World.Land
91 private int m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1; 91 private int m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1;
92 92
93 private bool m_allowedForcefulBans = true; 93 private bool m_allowedForcefulBans = true;
94 private UUID DefaultGodParcelGroup;
95 private string DefaultGodParcelName;
94 96
95 // caches ExtendedLandData 97 // caches ExtendedLandData
96 private Cache parcelInfoCache; 98 private Cache parcelInfoCache;
@@ -106,6 +108,12 @@ namespace OpenSim.Region.CoreModules.World.Land
106 108
107 public void Initialise(IConfigSource source) 109 public void Initialise(IConfigSource source)
108 { 110 {
111 IConfig cnf = source.Configs["LandManagement"];
112 if (cnf != null)
113 {
114 DefaultGodParcelGroup = new UUID(cnf.GetString("DefaultAdministratorGroupUUID", UUID.Zero.ToString()));
115 DefaultGodParcelName = cnf.GetString("DefaultAdministratorParcelName", "Default Parcel");
116 }
109 } 117 }
110 118
111 public void AddRegion(Scene scene) 119 public void AddRegion(Scene scene)
@@ -157,13 +165,6 @@ namespace OpenSim.Region.CoreModules.World.Land
157 m_scene.UnregisterModuleCommander(m_commander.Name); 165 m_scene.UnregisterModuleCommander(m_commander.Name);
158 } 166 }
159 167
160// private bool OnVerifyUserConnection(ScenePresence scenePresence, out string reason)
161// {
162// ILandObject nearestParcel = m_scene.GetNearestAllowedParcel(scenePresence.UUID, scenePresence.AbsolutePosition.X, scenePresence.AbsolutePosition.Y);
163// reason = "You are not allowed to enter this sim.";
164// return nearestParcel != null;
165// }
166
167 /// <summary> 168 /// <summary>
168 /// Processes commandline input. Do not call directly. 169 /// Processes commandline input. Do not call directly.
169 /// </summary> 170 /// </summary>
@@ -215,36 +216,6 @@ namespace OpenSim.Region.CoreModules.World.Land
215 216
216 void ClientOnPreAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) 217 void ClientOnPreAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
217 { 218 {
218 //If we are forcing a position for them to go
219 if (forcedPosition.ContainsKey(remoteClient.AgentId))
220 {
221 ScenePresence clientAvatar = m_scene.GetScenePresence(remoteClient.AgentId);
222
223 //Putting the user into flying, both keeps the avatar in fligth when it bumps into something and stopped from going another direction AND
224 //When the avatar walks into a ban line on the ground, it prevents getting stuck
225 agentData.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
226
227
228 //Make sure we stop if they get about to the right place to prevent yoyo and prevents getting stuck on banlines
229 if (Vector3.Distance(clientAvatar.AbsolutePosition, forcedPosition[remoteClient.AgentId]) < .2)
230 {
231 Debug.WriteLine(string.Format("Stopping force position because {0} is close enough to position {1}", forcedPosition[remoteClient.AgentId], clientAvatar.AbsolutePosition));
232 forcedPosition.Remove(remoteClient.AgentId);
233 }
234 //if we are far away, teleport
235 else if (Vector3.Distance(clientAvatar.AbsolutePosition, forcedPosition[remoteClient.AgentId]) > 3)
236 {
237 Debug.WriteLine(string.Format("Teleporting out because {0} is too far from avatar position {1}", forcedPosition[remoteClient.AgentId], clientAvatar.AbsolutePosition));
238 clientAvatar.Teleport(forcedPosition[remoteClient.AgentId]);
239 forcedPosition.Remove(remoteClient.AgentId);
240 }
241 else
242 {
243 //Forces them toward the forced position we want if they aren't there yet
244 agentData.UseClientAgentPosition = true;
245 agentData.ClientAgentPosition = forcedPosition[remoteClient.AgentId];
246 }
247 }
248 } 219 }
249 220
250 public void Close() 221 public void Close()
@@ -363,10 +334,16 @@ namespace OpenSim.Region.CoreModules.World.Land
363 private void ForceAvatarToPosition(ScenePresence avatar, Vector3? position) 334 private void ForceAvatarToPosition(ScenePresence avatar, Vector3? position)
364 { 335 {
365 if (m_scene.Permissions.IsGod(avatar.UUID)) return; 336 if (m_scene.Permissions.IsGod(avatar.UUID)) return;
366 if (position.HasValue) 337
367 { 338 if (!position.HasValue)
368 forcedPosition[avatar.ControllingClient.AgentId] = (Vector3)position; 339 return;
369 } 340
341 bool isFlying = avatar.PhysicsActor.Flying;
342 avatar.RemoveFromPhysicalScene();
343
344 avatar.AbsolutePosition = (Vector3)position;
345
346 avatar.AddToPhysicalScene(isFlying);
370 } 347 }
371 348
372 public void SendYouAreRestrictedNotice(ScenePresence avatar) 349 public void SendYouAreRestrictedNotice(ScenePresence avatar)
@@ -386,29 +363,7 @@ namespace OpenSim.Region.CoreModules.World.Land
386 } 363 }
387 364
388 if (parcelAvatarIsEntering != null) 365 if (parcelAvatarIsEntering != null)
389 { 366 EnforceBans(parcelAvatarIsEntering, avatar);
390 if (avatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT)
391 {
392 if (parcelAvatarIsEntering.IsBannedFromLand(avatar.UUID))
393 {
394 SendYouAreBannedNotice(avatar);
395 ForceAvatarToPosition(avatar, m_scene.GetNearestAllowedPosition(avatar));
396 }
397 else if (parcelAvatarIsEntering.IsRestrictedFromLand(avatar.UUID))
398 {
399 SendYouAreRestrictedNotice(avatar);
400 ForceAvatarToPosition(avatar, m_scene.GetNearestAllowedPosition(avatar));
401 }
402 else
403 {
404 avatar.sentMessageAboutRestrictedParcelFlyingDown = true;
405 }
406 }
407 else
408 {
409 avatar.sentMessageAboutRestrictedParcelFlyingDown = true;
410 }
411 }
412 } 367 }
413 } 368 }
414 369
@@ -512,6 +467,7 @@ namespace OpenSim.Region.CoreModules.World.Land
512 //when we are finally in a safe place, lets release the forced position lock 467 //when we are finally in a safe place, lets release the forced position lock
513 forcedPosition.Remove(clientAvatar.ControllingClient.AgentId); 468 forcedPosition.Remove(clientAvatar.ControllingClient.AgentId);
514 } 469 }
470 EnforceBans(parcel, clientAvatar);
515 } 471 }
516 } 472 }
517 473
@@ -720,7 +676,7 @@ namespace OpenSim.Region.CoreModules.World.Land
720 int x; 676 int x;
721 int y; 677 int y;
722 678
723 if (x_float >= Constants.RegionSize || x_float < 0 || y_float >= Constants.RegionSize || y_float < 0) 679 if (x_float > Constants.RegionSize || x_float < 0 || y_float > Constants.RegionSize || y_float < 0)
724 return null; 680 return null;
725 681
726 try 682 try
@@ -770,14 +726,13 @@ namespace OpenSim.Region.CoreModules.World.Land
770 { 726 {
771 try 727 try
772 { 728 {
773 return m_landList[m_landIDList[x / 4, y / 4]]; 729 //if (m_landList.ContainsKey(m_landIDList[x / 4, y / 4]))
730 return m_landList[m_landIDList[x / 4, y / 4]];
731 //else
732 // return null;
774 } 733 }
775 catch (IndexOutOfRangeException) 734 catch (IndexOutOfRangeException)
776 { 735 {
777// m_log.WarnFormat(
778// "[LAND MANAGEMENT MODULE]: Tried to retrieve land object from out of bounds co-ordinate ({0},{1}) in {2}",
779// x, y, m_scene.RegionInfo.RegionName);
780
781 return null; 736 return null;
782 } 737 }
783 } 738 }
@@ -1060,6 +1015,10 @@ namespace OpenSim.Region.CoreModules.World.Land
1060 //Owner Flag 1015 //Owner Flag
1061 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER); 1016 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER);
1062 } 1017 }
1018 else if (currentParcelBlock.LandData.IsGroupOwned && remote_client.IsGroupMember(currentParcelBlock.LandData.GroupID))
1019 {
1020 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_GROUP);
1021 }
1063 else if (currentParcelBlock.LandData.SalePrice > 0 && 1022 else if (currentParcelBlock.LandData.SalePrice > 0 &&
1064 (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero || 1023 (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero ||
1065 currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId)) 1024 currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId))
@@ -1360,18 +1319,31 @@ namespace OpenSim.Region.CoreModules.World.Land
1360 1319
1361 public void EventManagerOnIncomingLandDataFromStorage(List<LandData> data) 1320 public void EventManagerOnIncomingLandDataFromStorage(List<LandData> data)
1362 { 1321 {
1363 for (int i = 0; i < data.Count; i++) 1322 lock (m_landList)
1364 { 1323 {
1365 IncomingLandObjectFromStorage(data[i]); 1324 //Remove all the land objects in the sim and then process our new data
1325 foreach (int n in m_landList.Keys)
1326 {
1327 m_scene.EventManager.TriggerLandObjectRemoved(m_landList[n].LandData.GlobalID);
1328 }
1329 m_landIDList.Initialize();
1330 m_landList.Clear();
1331
1332 for (int i = 0; i < data.Count; i++)
1333 {
1334 IncomingLandObjectFromStorage(data[i]);
1335 }
1366 } 1336 }
1367 } 1337 }
1368 1338
1369 public void IncomingLandObjectFromStorage(LandData data) 1339 public void IncomingLandObjectFromStorage(LandData data)
1370 { 1340 {
1341
1371 ILandObject new_land = new LandObject(data.OwnerID, data.IsGroupOwned, m_scene); 1342 ILandObject new_land = new LandObject(data.OwnerID, data.IsGroupOwned, m_scene);
1372 new_land.LandData = data.Copy(); 1343 new_land.LandData = data.Copy();
1373 new_land.SetLandBitmapFromByteArray(); 1344 new_land.SetLandBitmapFromByteArray();
1374 AddLandObject(new_land); 1345 AddLandObject(new_land);
1346 new_land.SendLandUpdateToAvatarsOverMe();
1375 } 1347 }
1376 1348
1377 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient) 1349 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient)
@@ -1649,6 +1621,322 @@ namespace OpenSim.Region.CoreModules.World.Land
1649 1621
1650 UpdateLandObject(localID, land.LandData); 1622 UpdateLandObject(localID, land.LandData);
1651 } 1623 }
1624
1625 public void ClientOnParcelGodMark(IClientAPI client, UUID god, int landID)
1626 {
1627 ILandObject land = null;
1628 List<ILandObject> Land = ((Scene)client.Scene).LandChannel.AllParcels();
1629 foreach (ILandObject landObject in Land)
1630 {
1631 if (landObject.LandData.LocalID == landID)
1632 {
1633 land = landObject;
1634 }
1635 }
1636 land.DeedToGroup(DefaultGodParcelGroup);
1637 land.LandData.Name = DefaultGodParcelName;
1638 land.SendLandUpdateToAvatarsOverMe();
1639 }
1640
1641 private void ClientOnSimWideDeletes(IClientAPI client, UUID agentID, int flags, UUID targetID)
1642 {
1643 ScenePresence SP;
1644 ((Scene)client.Scene).TryGetScenePresence(client.AgentId, out SP);
1645 List<SceneObjectGroup> returns = new List<SceneObjectGroup>();
1646 if (SP.UserLevel != 0)
1647 {
1648 if (flags == 0) //All parcels, scripted or not
1649 {
1650 ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e)
1651 {
1652 if (e.OwnerID == targetID)
1653 {
1654 returns.Add(e);
1655 }
1656 }
1657 );
1658 }
1659 if (flags == 4) //All parcels, scripted object
1660 {
1661 ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e)
1662 {
1663 if (e.OwnerID == targetID)
1664 {
1665 if (e.scriptScore >= 0.01)
1666 {
1667 returns.Add(e);
1668 }
1669 }
1670 }
1671 );
1672 }
1673 if (flags == 4) //not target parcel, scripted object
1674 {
1675 ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e)
1676 {
1677 if (e.OwnerID == targetID)
1678 {
1679 ILandObject landobject = ((Scene)client.Scene).LandChannel.GetLandObject(e.AbsolutePosition.X, e.AbsolutePosition.Y);
1680 if (landobject.LandData.OwnerID != e.OwnerID)
1681 {
1682 if (e.scriptScore >= 0.01)
1683 {
1684 returns.Add(e);
1685 }
1686 }
1687 }
1688 }
1689 );
1690 }
1691 foreach (SceneObjectGroup ol in returns)
1692 {
1693 ReturnObject(ol, client);
1694 }
1695 }
1696 }
1697 public void ReturnObject(SceneObjectGroup obj, IClientAPI client)
1698 {
1699 SceneObjectGroup[] objs = new SceneObjectGroup[1];
1700 objs[0] = obj;
1701 ((Scene)client.Scene).returnObjects(objs, client.AgentId);
1702 }
1703
1704 Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>();
1705
1706 public void ClientOnParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
1707 {
1708 ScenePresence targetAvatar = null;
1709 ((Scene)client.Scene).TryGetScenePresence(target, out targetAvatar);
1710 ScenePresence parcelManager = null;
1711 ((Scene)client.Scene).TryGetScenePresence(client.AgentId, out parcelManager);
1712 System.Threading.Timer Timer;
1713
1714 if (targetAvatar.UserLevel == 0)
1715 {
1716 ILandObject land = ((Scene)client.Scene).LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y);
1717 if (!((Scene)client.Scene).Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze))
1718 return;
1719 if (flags == 0)
1720 {
1721 targetAvatar.AllowMovement = false;
1722 targetAvatar.ControllingClient.SendAlertMessage(parcelManager.Firstname + " " + parcelManager.Lastname + " has frozen you for 30 seconds. You cannot move or interact with the world.");
1723 parcelManager.ControllingClient.SendAlertMessage("Avatar Frozen.");
1724 System.Threading.TimerCallback timeCB = new System.Threading.TimerCallback(OnEndParcelFrozen);
1725 Timer = new System.Threading.Timer(timeCB, targetAvatar, 30000, 0);
1726 Timers.Add(targetAvatar.UUID, Timer);
1727 }
1728 else
1729 {
1730 targetAvatar.AllowMovement = true;
1731 targetAvatar.ControllingClient.SendAlertMessage(parcelManager.Firstname + " " + parcelManager.Lastname + " has unfrozen you.");
1732 parcelManager.ControllingClient.SendAlertMessage("Avatar Unfrozen.");
1733 Timers.TryGetValue(targetAvatar.UUID, out Timer);
1734 Timers.Remove(targetAvatar.UUID);
1735 Timer.Dispose();
1736 }
1737 }
1738 }
1739 private void OnEndParcelFrozen(object avatar)
1740 {
1741 ScenePresence targetAvatar = (ScenePresence)avatar;
1742 targetAvatar.AllowMovement = true;
1743 System.Threading.Timer Timer;
1744 Timers.TryGetValue(targetAvatar.UUID, out Timer);
1745 Timers.Remove(targetAvatar.UUID);
1746 targetAvatar.ControllingClient.SendAgentAlertMessage("The freeze has worn off; you may go about your business.", false);
1747 }
1748
1749
1750 public void ClientOnParcelEjectUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
1751 {
1752 ScenePresence targetAvatar = null;
1753 ((Scene)client.Scene).TryGetScenePresence(target, out targetAvatar);
1754 ScenePresence parcelManager = null;
1755 ((Scene)client.Scene).TryGetScenePresence(client.AgentId, out parcelManager);
1756 //Just eject
1757 if (flags == 0)
1758 {
1759 if (targetAvatar.UserLevel == 0)
1760 {
1761 ILandObject land = ((Scene)client.Scene).LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y);
1762 if (!((Scene)client.Scene).Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze))
1763 return;
1764
1765 Vector3 position = new Vector3(0, 0, 0);
1766 List<ILandObject> allParcels = new List<ILandObject>();
1767 allParcels = AllParcels();
1768 if (allParcels.Count != 1)
1769 {
1770 foreach (ILandObject parcel in allParcels)
1771 {
1772 if (parcel.LandData.GlobalID != land.LandData.GlobalID)
1773 {
1774 if (parcel.IsEitherBannedOrRestricted(targetAvatar.UUID) != true)
1775 {
1776 for (int x = 1; x <= Constants.RegionSize; x += 2)
1777 {
1778 for (int y = 1; y <= Constants.RegionSize; y += 2)
1779 {
1780 if (parcel.ContainsPoint(x, y))
1781 {
1782 position = new Vector3(x, y, targetAvatar.AbsolutePosition.Z);
1783 targetAvatar.TeleportWithMomentum(position);
1784 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1785 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected.");
1786 return;
1787 }
1788 }
1789 }
1790 }
1791 }
1792 }
1793 }
1794 Vector3 targetVector;
1795 if (targetAvatar.AbsolutePosition.X > targetAvatar.AbsolutePosition.Y)
1796 {
1797 if (targetAvatar.AbsolutePosition.X > .5 * Constants.RegionSize)
1798 {
1799 targetVector = new Vector3(Constants.RegionSize, targetAvatar.AbsolutePosition.Y, targetAvatar.AbsolutePosition.Z); ;
1800 targetAvatar.TeleportWithMomentum(targetVector);
1801 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1802 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected.");
1803 return;
1804 }
1805 else
1806 {
1807 targetVector = new Vector3(0, targetAvatar.AbsolutePosition.Y, targetAvatar.AbsolutePosition.Z); ;
1808 targetAvatar.TeleportWithMomentum(targetVector);
1809 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1810 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected.");
1811 return;
1812 }
1813 }
1814 else
1815 {
1816 if (targetAvatar.AbsolutePosition.Y > .5 * Constants.RegionSize)
1817 {
1818 targetVector = new Vector3(targetAvatar.AbsolutePosition.X, Constants.RegionSize, targetAvatar.AbsolutePosition.Z); ;
1819 targetAvatar.TeleportWithMomentum(targetVector);
1820 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1821 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected.");
1822 return;
1823 }
1824 else
1825 {
1826 targetVector = new Vector3(targetAvatar.AbsolutePosition.X, 0, targetAvatar.AbsolutePosition.Z); ;
1827 targetAvatar.TeleportWithMomentum(targetVector);
1828 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1829 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected.");
1830 return;
1831 }
1832 }
1833 }
1834 }
1835 //Eject and ban
1836 if (flags == 1)
1837 {
1838 if (targetAvatar.UserLevel == 0)
1839 {
1840 ILandObject land = ((Scene)client.Scene).LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y);
1841 if (!((Scene)client.Scene).Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze))
1842 return;
1843
1844 Vector3 position = new Vector3(0, 0, 0);
1845 List<ILandObject> allParcels = new List<ILandObject>();
1846 allParcels = AllParcels();
1847 if (allParcels.Count != 1)
1848 {
1849 foreach (ILandObject parcel in allParcels)
1850 {
1851 if (parcel.LandData.GlobalID != land.LandData.GlobalID)
1852 {
1853 if (parcel.IsEitherBannedOrRestricted(targetAvatar.UUID) != true)
1854 {
1855 for (int x = 1; x <= Constants.RegionSize; x += 2)
1856 {
1857 for (int y = 1; y <= Constants.RegionSize; y += 2)
1858 {
1859 if (parcel.ContainsPoint(x, y))
1860 {
1861 position = new Vector3(x, y, targetAvatar.AbsolutePosition.Z);
1862 targetAvatar.TeleportWithMomentum(position);
1863 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected and banned by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1864 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected and Banned.");
1865 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
1866 entry.AgentID = targetAvatar.UUID;
1867 entry.Flags = AccessList.Ban;
1868 entry.Time = new DateTime();
1869 land.LandData.ParcelAccessList.Add(entry);
1870 return;
1871 }
1872 }
1873 }
1874 }
1875 }
1876 }
1877 }
1878 Vector3 targetVector;
1879 if (targetAvatar.AbsolutePosition.X > targetAvatar.AbsolutePosition.Y)
1880 {
1881 if (targetAvatar.AbsolutePosition.X > .5 * Constants.RegionSize)
1882 {
1883 targetVector = new Vector3(Constants.RegionSize, targetAvatar.AbsolutePosition.Y, targetAvatar.AbsolutePosition.Z); ;
1884 targetAvatar.TeleportWithMomentum(targetVector);
1885 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected and banned by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1886 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected and Banned.");
1887 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
1888 entry.AgentID = targetAvatar.UUID;
1889 entry.Flags = AccessList.Ban;
1890 entry.Time = new DateTime();
1891 land.LandData.ParcelAccessList.Add(entry);
1892 return;
1893 }
1894 else
1895 {
1896 targetVector = new Vector3(0, targetAvatar.AbsolutePosition.Y, targetAvatar.AbsolutePosition.Z); ;
1897 targetAvatar.TeleportWithMomentum(targetVector);
1898 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected and banned by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1899 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected and Banned.");
1900 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
1901 entry.AgentID = targetAvatar.UUID;
1902 entry.Flags = AccessList.Ban;
1903 entry.Time = new DateTime();
1904 land.LandData.ParcelAccessList.Add(entry);
1905 return;
1906 }
1907 }
1908 else
1909 {
1910 if (targetAvatar.AbsolutePosition.Y > .5 * Constants.RegionSize)
1911 {
1912 targetVector = new Vector3(targetAvatar.AbsolutePosition.X, Constants.RegionSize, targetAvatar.AbsolutePosition.Z); ;
1913 targetAvatar.TeleportWithMomentum(targetVector);
1914 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected and banned by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1915 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected and Banned.");
1916 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
1917 entry.AgentID = targetAvatar.UUID;
1918 entry.Flags = AccessList.Ban;
1919 entry.Time = new DateTime();
1920 land.LandData.ParcelAccessList.Add(entry);
1921 return;
1922 }
1923 else
1924 {
1925 targetVector = new Vector3(targetAvatar.AbsolutePosition.X, 0, targetAvatar.AbsolutePosition.Z); ;
1926 targetAvatar.TeleportWithMomentum(targetVector);
1927 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected and banned by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1928 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected and Banned.");
1929 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
1930 entry.AgentID = targetAvatar.UUID;
1931 entry.Flags = AccessList.Ban;
1932 entry.Time = new DateTime();
1933 land.LandData.ParcelAccessList.Add(entry);
1934 return;
1935 }
1936 }
1937 }
1938 }
1939 }
1652 1940
1653 protected void InstallInterfaces() 1941 protected void InstallInterfaces()
1654 { 1942 {
@@ -1711,5 +1999,27 @@ namespace OpenSim.Region.CoreModules.World.Land
1711 1999
1712 MainConsole.Instance.Output(report.ToString()); 2000 MainConsole.Instance.Output(report.ToString());
1713 } 2001 }
2002
2003 public void EnforceBans(ILandObject land, ScenePresence avatar)
2004 {
2005 if (avatar.AbsolutePosition.Z > LandChannel.BAN_LINE_SAFETY_HIEGHT)
2006 return;
2007
2008 if (land.IsEitherBannedOrRestricted(avatar.UUID))
2009 {
2010 if (land.ContainsPoint(Convert.ToInt32(avatar.lastKnownAllowedPosition.X), Convert.ToInt32(avatar.lastKnownAllowedPosition.Y)))
2011 {
2012 Vector3? pos = m_scene.GetNearestAllowedPosition(avatar);
2013 if (pos == null)
2014 m_scene.TeleportClientHome(avatar.UUID, avatar.ControllingClient);
2015 else
2016 ForceAvatarToPosition(avatar, (Vector3)pos);
2017 }
2018 else
2019 {
2020 ForceAvatarToPosition(avatar, avatar.lastKnownAllowedPosition);
2021 }
2022 }
2023 }
1714 } 2024 }
1715} \ No newline at end of file 2025}
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index 79b13c3..07b28c7 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -190,10 +190,27 @@ namespace OpenSim.Region.CoreModules.World.Land
190 else 190 else
191 { 191 {
192 // Normal Calculations 192 // Normal Calculations
193 int parcelMax = (int)(((float)LandData.Area / 65536.0f) 193 int parcelMax = (int)((long)LandData.Area
194 * (float)m_scene.RegionInfo.ObjectCapacity 194 * (long)m_scene.RegionInfo.ObjectCapacity
195 * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); 195 * (long)m_scene.RegionInfo.RegionSettings.ObjectBonus
196 // TODO: The calculation of ObjectBonus should be refactored. It does still not work in the same manner as SL! 196 / 65536L);
197 m_log.DebugFormat("Area: {0}, Capacity {1}, Bonus {2}, Parcel {3}", LandData.Area, m_scene.RegionInfo.ObjectCapacity, m_scene.RegionInfo.RegionSettings.ObjectBonus, parcelMax);
198 return parcelMax;
199 }
200 }
201
202 private int GetParcelBasePrimCount()
203 {
204 if (overrideParcelMaxPrimCount != null)
205 {
206 return overrideParcelMaxPrimCount(this);
207 }
208 else
209 {
210 // Normal Calculations
211 int parcelMax = (int)((long)LandData.Area
212 * (long)m_scene.RegionInfo.ObjectCapacity
213 / 65536L);
197 return parcelMax; 214 return parcelMax;
198 } 215 }
199 } 216 }
@@ -207,8 +224,9 @@ namespace OpenSim.Region.CoreModules.World.Land
207 else 224 else
208 { 225 {
209 //Normal Calculations 226 //Normal Calculations
210 int simMax = (int)(((float)LandData.SimwideArea / 65536.0f) 227 int simMax = (int)((long)LandData.SimwideArea
211 * (float)m_scene.RegionInfo.ObjectCapacity); 228 * (long)m_scene.RegionInfo.ObjectCapacity / 65536L);
229 // m_log.DebugFormat("Simwide Area: {0}, Capacity {1}, SimMax {2}", LandData.SimwideArea, m_scene.RegionInfo.ObjectCapacity, simMax);
212 return simMax; 230 return simMax;
213 } 231 }
214 } 232 }
@@ -245,7 +263,7 @@ namespace OpenSim.Region.CoreModules.World.Land
245 remote_client.SendLandProperties(seq_id, 263 remote_client.SendLandProperties(seq_id,
246 snap_selection, request_result, this, 264 snap_selection, request_result, this,
247 (float)m_scene.RegionInfo.RegionSettings.ObjectBonus, 265 (float)m_scene.RegionInfo.RegionSettings.ObjectBonus,
248 GetParcelMaxPrimCount(), 266 GetParcelBasePrimCount(),
249 GetSimulatorMaxPrimCount(), regionFlags); 267 GetSimulatorMaxPrimCount(), regionFlags);
250 } 268 }
251 269
@@ -304,7 +322,7 @@ namespace OpenSim.Region.CoreModules.World.Land
304 322
305 allowedDelta |= (uint)(ParcelFlags.ShowDirectory | 323 allowedDelta |= (uint)(ParcelFlags.ShowDirectory |
306 ParcelFlags.AllowPublish | 324 ParcelFlags.AllowPublish |
307 ParcelFlags.MaturePublish); 325 ParcelFlags.MaturePublish) | (uint)(1 << 23);
308 } 326 }
309 327
310 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandChangeIdentity)) 328 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandChangeIdentity))
@@ -416,9 +434,43 @@ namespace OpenSim.Region.CoreModules.World.Land
416 return false; 434 return false;
417 } 435 }
418 436
437 public bool HasGroupAccess(UUID avatar)
438 {
439 if (LandData.GroupID != UUID.Zero && (LandData.Flags & (uint)ParcelFlags.UseAccessGroup) == (uint)ParcelFlags.UseAccessGroup)
440 {
441 ScenePresence sp;
442 if (!m_scene.TryGetScenePresence(avatar, out sp))
443 {
444 IGroupsModule groupsModule = m_scene.RequestModuleInterface<IGroupsModule>();
445 if (groupsModule == null)
446 return false;
447
448 GroupMembershipData[] membership = groupsModule.GetMembershipData(avatar);
449 if (membership == null || membership.Length == 0)
450 return false;
451
452 foreach (GroupMembershipData d in membership)
453 {
454 if (d.GroupID == LandData.GroupID)
455 return true;
456 }
457 return false;
458 }
459
460 if (!sp.ControllingClient.IsGroupMember(LandData.GroupID))
461 return false;
462
463 return true;
464 }
465 return false;
466 }
467
419 public bool IsBannedFromLand(UUID avatar) 468 public bool IsBannedFromLand(UUID avatar)
420 { 469 {
421 if (m_scene.Permissions.CanEditParcelProperties(avatar, this, 0)) 470 if (m_scene.Permissions.IsAdministrator(avatar))
471 return false;
472
473 if (m_scene.RegionInfo.EstateSettings.IsEstateManager(avatar))
422 return false; 474 return false;
423 475
424 if ((LandData.Flags & (uint) ParcelFlags.UseBanList) > 0) 476 if ((LandData.Flags & (uint) ParcelFlags.UseBanList) > 0)
@@ -429,7 +481,7 @@ namespace OpenSim.Region.CoreModules.World.Land
429 if (e.AgentID == avatar && e.Flags == AccessList.Ban) 481 if (e.AgentID == avatar && e.Flags == AccessList.Ban)
430 return true; 482 return true;
431 return false; 483 return false;
432 }) != -1) 484 }) != -1 && LandData.OwnerID != avatar)
433 { 485 {
434 return true; 486 return true;
435 } 487 }
@@ -439,7 +491,10 @@ namespace OpenSim.Region.CoreModules.World.Land
439 491
440 public bool IsRestrictedFromLand(UUID avatar) 492 public bool IsRestrictedFromLand(UUID avatar)
441 { 493 {
442 if (m_scene.Permissions.CanEditParcelProperties(avatar, this, 0)) 494 if (m_scene.Permissions.IsAdministrator(avatar))
495 return false;
496
497 if (m_scene.RegionInfo.EstateSettings.IsEstateManager(avatar))
443 return false; 498 return false;
444 499
445 if ((LandData.Flags & (uint) ParcelFlags.UseAccessList) > 0) 500 if ((LandData.Flags & (uint) ParcelFlags.UseAccessList) > 0)
@@ -450,11 +505,15 @@ namespace OpenSim.Region.CoreModules.World.Land
450 if (e.AgentID == avatar && e.Flags == AccessList.Access) 505 if (e.AgentID == avatar && e.Flags == AccessList.Access)
451 return true; 506 return true;
452 return false; 507 return false;
453 }) == -1) 508 }) == -1 && LandData.OwnerID != avatar)
454 { 509 {
455 return true; 510 if (!HasGroupAccess(avatar))
511 {
512 return true;
513 }
456 } 514 }
457 } 515 }
516
458 return false; 517 return false;
459 } 518 }
460 519
diff --git a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
index efede5c..5122734 100644
--- a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
@@ -206,7 +206,7 @@ namespace OpenSim.Region.CoreModules.World.Land
206 if (m_ParcelCounts.TryGetValue(landData.GlobalID, out parcelCounts)) 206 if (m_ParcelCounts.TryGetValue(landData.GlobalID, out parcelCounts))
207 { 207 {
208 UUID landOwner = landData.OwnerID; 208 UUID landOwner = landData.OwnerID;
209 int partCount = obj.Parts.Length; 209 int partCount = obj.GetPartCount();
210 210
211 m_SimwideCounts[landOwner] += partCount; 211 m_SimwideCounts[landOwner] += partCount;
212 if (parcelCounts.Users.ContainsKey(obj.OwnerID)) 212 if (parcelCounts.Users.ContainsKey(obj.OwnerID))
@@ -593,4 +593,4 @@ namespace OpenSim.Region.CoreModules.World.Land
593 } 593 }
594 } 594 }
595 } 595 }
596} \ No newline at end of file 596}
diff --git a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
index 1e4f0a4..eb4731c 100644
--- a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
@@ -176,6 +176,13 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
176 return false; 176 return false;
177 } 177 }
178 178
179 if ((perms & (uint)PermissionMask.Copy) == 0)
180 {
181 if (m_dialogModule != null)
182 m_dialogModule.SendAlertToUser(remoteClient, "This sale has been blocked by the permissions system");
183 return false;
184 }
185
179 AssetBase asset = m_scene.CreateAsset( 186 AssetBase asset = m_scene.CreateAsset(
180 group.GetPartName(localID), 187 group.GetPartName(localID),
181 group.GetPartDescription(localID), 188 group.GetPartDescription(localID),
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
index cdecd2f..5e7d37a 100644
--- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
@@ -363,7 +363,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
363 363
364 public string Name 364 public string Name
365 { 365 {
366 get { return "PermissionsModule"; } 366 get { return "DefaultPermissionsModule"; }
367 } 367 }
368 368
369 public bool IsSharedModule 369 public bool IsSharedModule
diff --git a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
index 0f37ddd..86821c6 100644
--- a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
+++ b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
@@ -28,6 +28,8 @@
28using System; 28using System;
29using System.Reflection; 29using System.Reflection;
30using System.Timers; 30using System.Timers;
31using System.IO;
32using System.Diagnostics;
31using System.Threading; 33using System.Threading;
32using System.Collections.Generic; 34using System.Collections.Generic;
33using log4net; 35using log4net;
@@ -56,13 +58,23 @@ namespace OpenSim.Region.CoreModules.World.Region
56 protected UUID m_Initiator; 58 protected UUID m_Initiator;
57 protected bool m_Notice = false; 59 protected bool m_Notice = false;
58 protected IDialogModule m_DialogModule = null; 60 protected IDialogModule m_DialogModule = null;
61 protected string m_MarkerPath = String.Empty;
59 62
60 public void Initialise(IConfigSource config) 63 public void Initialise(IConfigSource config)
61 { 64 {
65 IConfig restartConfig = config.Configs["RestartModule"];
66 if (restartConfig != null)
67 {
68 m_MarkerPath = restartConfig.GetString("MarkerPath", String.Empty);
69 }
62 } 70 }
63 71
64 public void AddRegion(Scene scene) 72 public void AddRegion(Scene scene)
65 { 73 {
74 if (m_MarkerPath != String.Empty)
75 File.Delete(Path.Combine(m_MarkerPath,
76 scene.RegionInfo.RegionID.ToString()));
77
66 m_Scene = scene; 78 m_Scene = scene;
67 79
68 scene.RegisterModuleInterface<IRestartModule>(this); 80 scene.RegisterModuleInterface<IRestartModule>(this);
@@ -121,6 +133,7 @@ namespace OpenSim.Region.CoreModules.World.Region
121 133
122 if (alerts == null) 134 if (alerts == null)
123 { 135 {
136 CreateMarkerFile();
124 m_Scene.RestartNow(); 137 m_Scene.RestartNow();
125 return; 138 return;
126 } 139 }
@@ -134,6 +147,7 @@ namespace OpenSim.Region.CoreModules.World.Region
134 147
135 if (m_Alerts[0] == 0) 148 if (m_Alerts[0] == 0)
136 { 149 {
150 CreateMarkerFile();
137 m_Scene.RestartNow(); 151 m_Scene.RestartNow();
138 return; 152 return;
139 } 153 }
@@ -147,6 +161,7 @@ namespace OpenSim.Region.CoreModules.World.Region
147 { 161 {
148 if (m_Alerts.Count == 0 || m_Alerts[0] == 0) 162 if (m_Alerts.Count == 0 || m_Alerts[0] == 0)
149 { 163 {
164 CreateMarkerFile();
150 m_Scene.RestartNow(); 165 m_Scene.RestartNow();
151 return 0; 166 return 0;
152 } 167 }
@@ -225,6 +240,9 @@ namespace OpenSim.Region.CoreModules.World.Region
225 if (m_DialogModule != null && message != String.Empty) 240 if (m_DialogModule != null && message != String.Empty)
226 m_DialogModule.SendGeneralAlert(message); 241 m_DialogModule.SendGeneralAlert(message);
227 } 242 }
243 if (m_MarkerPath != String.Empty)
244 File.Delete(Path.Combine(m_MarkerPath,
245 m_Scene.RegionInfo.RegionID.ToString()));
228 } 246 }
229 247
230 private void HandleRegionRestart(string module, string[] args) 248 private void HandleRegionRestart(string module, string[] args)
@@ -266,5 +284,25 @@ namespace OpenSim.Region.CoreModules.World.Region
266 284
267 ScheduleRestart(UUID.Zero, args[3], times.ToArray(), notice); 285 ScheduleRestart(UUID.Zero, args[3], times.ToArray(), notice);
268 } 286 }
287
288 protected void CreateMarkerFile()
289 {
290 if (m_MarkerPath == String.Empty)
291 return;
292
293 string path = Path.Combine(m_MarkerPath, m_Scene.RegionInfo.RegionID.ToString());
294 try
295 {
296 string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
297 FileStream fs = File.Create(path);
298 System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
299 Byte[] buf = enc.GetBytes(pidstring);
300 fs.Write(buf, 0, buf.Length);
301 fs.Close();
302 }
303 catch (Exception)
304 {
305 }
306 }
269 } 307 }
270} 308}
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
index cf000a4..4805ccb 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
@@ -606,6 +606,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
606 m_scene.PhysicsScene.SetTerrain(m_channel.GetFloatsSerialised()); 606 m_scene.PhysicsScene.SetTerrain(m_channel.GetFloatsSerialised());
607 m_scene.SaveTerrain(); 607 m_scene.SaveTerrain();
608 608
609 m_scene.EventManager.TriggerTerrainUpdate();
610
609 // Clients who look at the map will never see changes after they looked at the map, so i've commented this out. 611 // Clients who look at the map will never see changes after they looked at the map, so i've commented this out.
610 //m_scene.CreateTerrainTexture(true); 612 //m_scene.CreateTerrainTexture(true);
611 } 613 }
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
index 657975b..f9384e9 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
@@ -86,9 +86,9 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
86 86
87 private void OnMapNameRequest(IClientAPI remoteClient, string mapName, uint flags) 87 private void OnMapNameRequest(IClientAPI remoteClient, string mapName, uint flags)
88 { 88 {
89 if (mapName.Length < 3) 89 if (mapName.Length < 2)
90 { 90 {
91 remoteClient.SendAlertMessage("Use a search string with at least 3 characters"); 91 remoteClient.SendAlertMessage("Use a search string with at least 2 characters");
92 return; 92 return;
93 } 93 }
94 94
@@ -96,10 +96,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
96 96
97 // try to fetch from GridServer 97 // try to fetch from GridServer
98 List<GridRegion> regionInfos = m_scene.GridService.GetRegionsByName(m_scene.RegionInfo.ScopeID, mapName, 20); 98 List<GridRegion> regionInfos = m_scene.GridService.GetRegionsByName(m_scene.RegionInfo.ScopeID, mapName, 20);
99 if (regionInfos.Count == 0) 99// if (regionInfos.Count == 0)
100 remoteClient.SendAlertMessage("Hyperlink could not be established."); 100// remoteClient.SendAlertMessage("Hyperlink could not be established.");
101 101
102 m_log.DebugFormat("[MAPSEARCHMODULE]: search {0} returned {1} regions. Flags={2}", mapName, regionInfos.Count, flags); 102 //m_log.DebugFormat("[MAPSEARCHMODULE]: search {0} returned {1} regions", mapName, regionInfos.Count);
103 List<MapBlockData> blocks = new List<MapBlockData>(); 103 List<MapBlockData> blocks = new List<MapBlockData>();
104 104
105 MapBlockData data; 105 MapBlockData data;
@@ -128,7 +128,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
128 data.Agents = 0; 128 data.Agents = 0;
129 data.Access = 255; 129 data.Access = 255;
130 data.MapImageId = UUID.Zero; 130 data.MapImageId = UUID.Zero;
131 data.Name = ""; // mapName; 131 data.Name = mapName;
132 data.RegionFlags = 0; 132 data.RegionFlags = 0;
133 data.WaterHeight = 0; // not used 133 data.WaterHeight = 0; // not used
134 data.X = 0; 134 data.X = 0;
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
index 6c6aa37..a4210b2 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
@@ -1239,7 +1239,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1239 } 1239 }
1240 else 1240 else
1241 { 1241 {
1242 OSDArray responsearr = new OSDArray(m_scene.GetRootAgentCount()); 1242 OSDArray responsearr = new OSDArray(); // Don't preallocate. MT (m_scene.GetRootAgentCount());
1243 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 1243 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
1244 { 1244 {
1245 OSDMap responsemapdata = new OSDMap(); 1245 OSDMap responsemapdata = new OSDMap();
@@ -1458,9 +1458,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1458 Color background = Color.FromArgb(0, 0, 0, 0); 1458 Color background = Color.FromArgb(0, 0, 0, 0);
1459 SolidBrush transparent = new SolidBrush(background); 1459 SolidBrush transparent = new SolidBrush(background);
1460 Graphics g = Graphics.FromImage(overlay); 1460 Graphics g = Graphics.FromImage(overlay);
1461 g.FillRectangle(transparent, 0, 0, 256, 256); 1461 g.FillRectangle(transparent, 0, 0, 255, 255);
1462 1462
1463 SolidBrush yellow = new SolidBrush(Color.FromArgb(255, 249, 223, 9)); 1463 SolidBrush yellow = new SolidBrush(Color.FromArgb(255, 249, 223, 9));
1464 Pen grey = new Pen(Color.FromArgb(255, 92, 92, 92));
1464 1465
1465 foreach (ILandObject land in parcels) 1466 foreach (ILandObject land in parcels)
1466 { 1467 {
@@ -1469,7 +1470,41 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1469 { 1470 {
1470 landForSale = true; 1471 landForSale = true;
1471 1472
1472 saleBitmap = land.MergeLandBitmaps(saleBitmap, land.GetLandBitmap()); 1473 bool[,] landBitmap = land.GetLandBitmap();
1474
1475 for (int x = 0 ; x < 64 ; x++)
1476 {
1477 for (int y = 0 ; y < 64 ; y++)
1478 {
1479 if (landBitmap[x, y])
1480 {
1481 g.FillRectangle(yellow, x * 4, 252 - (y * 4), 4, 4);
1482
1483 if (x > 0)
1484 {
1485 if ((saleBitmap[x - 1, y] || landBitmap[x - 1, y]) == false)
1486 g.DrawLine(grey, x * 4, 252 - (y * 4), x * 4, 255 - (y * 4));
1487 }
1488 if (y > 0)
1489 {
1490 if ((saleBitmap[x, y-1] || landBitmap[x, y-1]) == false)
1491 g.DrawLine(grey, x * 4, 255 - (y * 4), x * 4 + 3, 255 - (y * 4));
1492 }
1493 if (x < 63)
1494 {
1495 if ((saleBitmap[x + 1, y] || landBitmap[x + 1, y]) == false)
1496 g.DrawLine(grey, x * 4 + 3, 252 - (y * 4), x * 4 + 3, 255 - (y * 4));
1497 }
1498 if (y < 63)
1499 {
1500 if ((saleBitmap[x, y + 1] || landBitmap[x, y + 1]) == false)
1501 g.DrawLine(grey, x * 4, 252 - (y * 4), x * 4 + 3, 252 - (y * 4));
1502 }
1503 }
1504 }
1505 }
1506
1507 saleBitmap = land.MergeLandBitmaps(saleBitmap, landBitmap);
1473 } 1508 }
1474 } 1509 }
1475 1510
@@ -1481,15 +1516,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1481 1516
1482 m_log.DebugFormat("[WORLD MAP]: Region {0} has parcels for sale, genrating overlay", m_scene.RegionInfo.RegionName); 1517 m_log.DebugFormat("[WORLD MAP]: Region {0} has parcels for sale, genrating overlay", m_scene.RegionInfo.RegionName);
1483 1518
1484 for (int x = 0 ; x < 64 ; x++)
1485 {
1486 for (int y = 0 ; y < 64 ; y++)
1487 {
1488 if (saleBitmap[x, y])
1489 g.FillRectangle(yellow, x * 4, 252 - (y * 4), 4, 4);
1490 }
1491 }
1492
1493 try 1519 try
1494 { 1520 {
1495 return OpenJPEG.EncodeFromImage(overlay, true); 1521 return OpenJPEG.EncodeFromImage(overlay, true);
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index eb07165..69ce967 100644
--- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Xml;
29using System.Collections.Generic; 30using System.Collections.Generic;
30using OpenMetaverse; 31using OpenMetaverse;
31using OpenSim.Framework; 32using OpenSim.Framework;
@@ -75,6 +76,10 @@ namespace OpenSim.Region.Framework.Interfaces
75 /// <returns>The scene object that was attached. Null if the scene object could not be found</returns> 76 /// <returns>The scene object that was attached. Null if the scene object could not be found</returns>
76 ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt); 77 ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt);
77 78
79 // Same as above, but also load script states from a separate doc
80 ISceneEntity RezSingleAttachmentFromInventory(
81 IScenePresence presence, UUID itemID, uint AttachmentPt, bool updateInventoryStatus, XmlDocument doc);
82
78 /// <summary> 83 /// <summary>
79 /// Rez multiple attachments from a user's inventory 84 /// Rez multiple attachments from a user's inventory
80 /// </summary> 85 /// </summary>
@@ -96,7 +101,6 @@ namespace OpenSim.Region.Framework.Interfaces
96 /// <param name="itemID"></param> 101 /// <param name="itemID"></param>
97 void DetachSingleAttachmentToInv(IScenePresence sp, UUID itemID); 102 void DetachSingleAttachmentToInv(IScenePresence sp, UUID itemID);
98 103
99 /// <summary>
100 /// Update the position of an attachment. 104 /// Update the position of an attachment.
101 /// </summary> 105 /// </summary>
102 /// <param name="sog"></param> 106 /// <param name="sog"></param>
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
index 15060fd..4b17b9a 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
@@ -115,6 +115,8 @@ namespace OpenSim.Region.Framework.Interfaces
115 /// <param name="stateSource"></param> 115 /// <param name="stateSource"></param>
116 void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource); 116 void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
117 117
118 ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
119
118 /// <summary> 120 /// <summary>
119 /// Stop a script which is in this prim's inventory. 121 /// Stop a script which is in this prim's inventory.
120 /// </summary> 122 /// </summary>
@@ -229,5 +231,6 @@ namespace OpenSim.Region.Framework.Interfaces
229 /// A <see cref="Dictionary`2"/> 231 /// A <see cref="Dictionary`2"/>
230 /// </returns> 232 /// </returns>
231 Dictionary<UUID, string> GetScriptStates(); 233 Dictionary<UUID, string> GetScriptStates();
234 Dictionary<UUID, string> GetScriptStates(bool oldIDs);
232 } 235 }
233} 236}
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
index 07e97d5..c38ecd9 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
@@ -40,11 +40,11 @@ namespace OpenSim.Region.Framework.Interfaces
40 void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, 40 void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position,
41 Vector3 lookAt, uint teleportFlags); 41 Vector3 lookAt, uint teleportFlags);
42 42
43 bool TeleportHome(UUID id, IClientAPI client);
44
43 void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, 45 void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination,
44 Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq); 46 Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq);
45 47
46 void TeleportHome(UUID id, IClientAPI client);
47
48 bool Cross(ScenePresence agent, bool isFlying); 48 bool Cross(ScenePresence agent, bool isFlying);
49 49
50 void AgentArrivedAtDestination(UUID agent); 50 void AgentArrivedAtDestination(UUID agent);
diff --git a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
index 721f0ee..72e79ed 100644
--- a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
@@ -45,5 +45,7 @@ namespace OpenSim.Region.Framework.Interfaces
45 /// Tell all clients about the current state of the region (terrain textures, water height, etc.). 45 /// Tell all clients about the current state of the region (terrain textures, water height, etc.).
46 /// </summary> 46 /// </summary>
47 void sendRegionHandshakeToAll(); 47 void sendRegionHandshakeToAll();
48 void TriggerEstateInfoChange();
49 void TriggerRegionInfoChange();
48 } 50 }
49} 51}
diff --git a/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs b/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
index 2d6287f..67a500f 100644
--- a/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
+++ b/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
@@ -68,6 +68,14 @@ namespace OpenSim.Region.Framework.Interfaces
68 bool SendReleaseAgent(ulong regionHandle, UUID id, string uri); 68 bool SendReleaseAgent(ulong regionHandle, UUID id, string uri);
69 69
70 /// <summary> 70 /// <summary>
71 /// Close chid agent.
72 /// </summary>
73 /// <param name="regionHandle"></param>
74 /// <param name="id"></param>
75 /// <returns></returns>
76 bool SendCloseChildAgent(ulong regionHandle, UUID id);
77
78 /// <summary>
71 /// Close agent. 79 /// Close agent.
72 /// </summary> 80 /// </summary>
73 /// <param name="regionHandle"></param> 81 /// <param name="regionHandle"></param>
diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
index 18c45dd..2d6758b 100644
--- a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
@@ -68,6 +68,8 @@ namespace OpenSim.Region.Framework.Interfaces
68 68
69 ArrayList GetScriptErrors(UUID itemID); 69 ArrayList GetScriptErrors(UUID itemID);
70 70
71 bool HasScript(UUID itemID, out bool running);
72
71 void SaveAllState(); 73 void SaveAllState();
72 74
73 /// <summary> 75 /// <summary>
diff --git a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs
new file mode 100644
index 0000000..e01f649
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs
@@ -0,0 +1,27 @@
1///////////////////////////////////////////////////////////////////
2//
3// (c) Careminster LImited, Melanie Thielker and the Meta7 Team
4//
5// This file is not open source. All rights reserved
6// Mod 2
7
8using OpenSim.Region.Framework.Scenes;
9
10public interface ISnmpModule
11{
12 void Trap(int code, string Message, Scene scene);
13 void Critical(string Message, Scene scene);
14 void Warning(string Message, Scene scene);
15 void Major(string Message, Scene scene);
16 void ColdStart(int step , Scene scene);
17 void Shutdown(int step , Scene scene);
18 //
19 // Node Start/stop events
20 //
21 void LinkUp(Scene scene);
22 void LinkDown(Scene scene);
23 void BootInfo(string data, Scene scene);
24 void trapDebug(string Module,string data, Scene scene);
25 void trapXMRE(int data, string Message, Scene scene);
26
27}
diff --git a/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs b/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs
new file mode 100644
index 0000000..d1a4d8e
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs
@@ -0,0 +1,13 @@
1///////////////////////////////////////////////////////////////////
2//
3// (c) Careminster Limited, Melanie Thielker and the Meta7 Team
4//
5// This file is not open source. All rights reserved
6//
7
8using OpenSim.Region.Framework.Scenes;
9
10public interface IUserAccountCacheModule
11{
12 void Remove(string name);
13}
diff --git a/OpenSim/Region/Framework/ModuleLoader.cs b/OpenSim/Region/Framework/ModuleLoader.cs
index 14ecd44..32ee674 100644
--- a/OpenSim/Region/Framework/ModuleLoader.cs
+++ b/OpenSim/Region/Framework/ModuleLoader.cs
@@ -227,7 +227,8 @@ namespace OpenSim.Region.Framework
227 pluginAssembly.FullName, e.Message, e.StackTrace); 227 pluginAssembly.FullName, e.Message, e.StackTrace);
228 228
229 // justincc: Right now this is fatal to really get the user's attention 229 // justincc: Right now this is fatal to really get the user's attention
230 throw e; 230 // TomMeta: WTF? No, how about we /don't/ throw a fatal exception when there's no need to?
231 //throw e;
231 } 232 }
232 } 233 }
233 234
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index fd35c62..74d9e60 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -55,8 +55,12 @@ namespace OpenSim.Region.Framework.Scenes
55 55
56 public delegate void OnTerrainTickDelegate(); 56 public delegate void OnTerrainTickDelegate();
57 57
58 public delegate void OnTerrainUpdateDelegate();
59
58 public event OnTerrainTickDelegate OnTerrainTick; 60 public event OnTerrainTickDelegate OnTerrainTick;
59 61
62 public event OnTerrainUpdateDelegate OnTerrainUpdate;
63
60 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup); 64 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup);
61 65
62 public event OnBackupDelegate OnBackup; 66 public event OnBackupDelegate OnBackup;
@@ -791,6 +795,26 @@ namespace OpenSim.Region.Framework.Scenes
791 } 795 }
792 } 796 }
793 } 797 }
798 public void TriggerTerrainUpdate()
799 {
800 OnTerrainUpdateDelegate handlerTerrainUpdate = OnTerrainUpdate;
801 if (handlerTerrainUpdate != null)
802 {
803 foreach (OnTerrainUpdateDelegate d in handlerTerrainUpdate.GetInvocationList())
804 {
805 try
806 {
807 d();
808 }
809 catch (Exception e)
810 {
811 m_log.ErrorFormat(
812 "[EVENT MANAGER]: Delegate for TriggerTerrainUpdate failed - continuing. {0} {1}",
813 e.Message, e.StackTrace);
814 }
815 }
816 }
817 }
794 818
795 public void TriggerTerrainTick() 819 public void TriggerTerrainTick()
796 { 820 {
diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
index 1b10e3c..0a34a4c 100644
--- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs
+++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
@@ -157,7 +157,7 @@ namespace OpenSim.Region.Framework.Scenes
157 157
158 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity) 158 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity)
159 { 159 {
160 uint pqueue = ComputeDistancePriority(client,entity,true); 160 uint pqueue = ComputeDistancePriority(client,entity,false);
161 161
162 ScenePresence presence = m_scene.GetScenePresence(client.AgentId); 162 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
163 if (presence != null) 163 if (presence != null)
@@ -226,7 +226,7 @@ namespace OpenSim.Region.Framework.Scenes
226 226
227 for (int i = 0; i < queues - 1; i++) 227 for (int i = 0; i < queues - 1; i++)
228 { 228 {
229 if (distance < 10 * Math.Pow(2.0,i)) 229 if (distance < 30 * Math.Pow(2.0,i))
230 break; 230 break;
231 pqueue++; 231 pqueue++;
232 } 232 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index dd3208a..817736f 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -117,34 +117,22 @@ namespace OpenSim.Region.Framework.Scenes
117 /// <param name="item"></param> 117 /// <param name="item"></param>
118 public bool AddInventoryItem(InventoryItemBase item) 118 public bool AddInventoryItem(InventoryItemBase item)
119 { 119 {
120 if (UUID.Zero == item.Folder) 120 InventoryFolderBase folder;
121
122 if (item.Folder == UUID.Zero)
121 { 123 {
122 InventoryFolderBase f = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType); 124 folder = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType);
123 if (f != null) 125 if (folder == null)
124 {
125// m_log.DebugFormat(
126// "[LOCAL INVENTORY SERVICES CONNECTOR]: Found folder {0} type {1} for item {2}",
127// f.Name, (AssetType)f.Type, item.Name);
128
129 item.Folder = f.ID;
130 }
131 else
132 { 126 {
133 f = InventoryService.GetRootFolder(item.Owner); 127 folder = InventoryService.GetRootFolder(item.Owner);
134 if (f != null) 128
135 { 129 if (folder == null)
136 item.Folder = f.ID;
137 }
138 else
139 {
140 m_log.WarnFormat(
141 "[AGENT INVENTORY]: Could not find root folder for {0} when trying to add item {1} with no parent folder specified",
142 item.Owner, item.Name);
143 return false; 130 return false;
144 }
145 } 131 }
132
133 item.Folder = folder.ID;
146 } 134 }
147 135
148 if (InventoryService.AddItem(item)) 136 if (InventoryService.AddItem(item))
149 { 137 {
150 int userlevel = 0; 138 int userlevel = 0;
@@ -264,8 +252,7 @@ namespace OpenSim.Region.Framework.Scenes
264 252
265 // Update item with new asset 253 // Update item with new asset
266 item.AssetID = asset.FullID; 254 item.AssetID = asset.FullID;
267 if (group.UpdateInventoryItem(item)) 255 group.UpdateInventoryItem(item);
268 remoteClient.SendAgentAlertMessage("Script saved", false);
269 256
270 part.SendPropertiesToClient(remoteClient); 257 part.SendPropertiesToClient(remoteClient);
271 258
@@ -276,12 +263,7 @@ namespace OpenSim.Region.Framework.Scenes
276 { 263 {
277 // Needs to determine which engine was running it and use that 264 // Needs to determine which engine was running it and use that
278 // 265 //
279 part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0); 266 errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 0);
280 errors = part.Inventory.GetScriptErrors(item.ItemID);
281 }
282 else
283 {
284 remoteClient.SendAgentAlertMessage("Script saved", false);
285 } 267 }
286 part.ParentGroup.ResumeScripts(); 268 part.ParentGroup.ResumeScripts();
287 return errors; 269 return errors;
@@ -345,6 +327,7 @@ namespace OpenSim.Region.Framework.Scenes
345 327
346 if (UUID.Zero == transactionID) 328 if (UUID.Zero == transactionID)
347 { 329 {
330 item.Flags = (item.Flags & ~(uint)255) | (itemUpd.Flags & (uint)255);
348 item.Name = itemUpd.Name; 331 item.Name = itemUpd.Name;
349 item.Description = itemUpd.Description; 332 item.Description = itemUpd.Description;
350 if (item.NextPermissions != (itemUpd.NextPermissions & item.BasePermissions)) 333 if (item.NextPermissions != (itemUpd.NextPermissions & item.BasePermissions))
@@ -723,6 +706,8 @@ namespace OpenSim.Region.Framework.Scenes
723 return; 706 return;
724 } 707 }
725 708
709 if (newName == null) newName = item.Name;
710
726 AssetBase asset = AssetService.Get(item.AssetID.ToString()); 711 AssetBase asset = AssetService.Get(item.AssetID.ToString());
727 712
728 if (asset != null) 713 if (asset != null)
@@ -779,6 +764,24 @@ namespace OpenSim.Region.Framework.Scenes
779 } 764 }
780 765
781 /// <summary> 766 /// <summary>
767 /// Move an item within the agent's inventory, and leave a copy (used in making a new outfit)
768 /// </summary>
769 public void MoveInventoryItemsLeaveCopy(IClientAPI remoteClient, List<InventoryItemBase> items, UUID destfolder)
770 {
771 List<InventoryItemBase> moveitems = new List<InventoryItemBase>();
772 foreach (InventoryItemBase b in items)
773 {
774 CopyInventoryItem(remoteClient, 0, remoteClient.AgentId, b.ID, b.Folder, null);
775 InventoryItemBase n = InventoryService.GetItem(b);
776 n.Folder = destfolder;
777 moveitems.Add(n);
778 remoteClient.SendInventoryItemCreateUpdate(n, 0);
779 }
780
781 MoveInventoryItem(remoteClient, moveitems);
782 }
783
784 /// <summary>
782 /// Move an item within the agent's inventory. 785 /// Move an item within the agent's inventory.
783 /// </summary> 786 /// </summary>
784 /// <param name="remoteClient"></param> 787 /// <param name="remoteClient"></param>
@@ -1121,6 +1124,10 @@ namespace OpenSim.Region.Framework.Scenes
1121 { 1124 {
1122 SceneObjectPart part = GetSceneObjectPart(primLocalId); 1125 SceneObjectPart part = GetSceneObjectPart(primLocalId);
1123 1126
1127 // Can't move a null item
1128 if (itemId == UUID.Zero)
1129 return;
1130
1124 if (null == part) 1131 if (null == part)
1125 { 1132 {
1126 m_log.WarnFormat( 1133 m_log.WarnFormat(
@@ -1231,6 +1238,10 @@ namespace OpenSim.Region.Framework.Scenes
1231 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)) 1238 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0))
1232 return; 1239 return;
1233 1240
1241 bool overrideNoMod = false;
1242 if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) != 0)
1243 overrideNoMod = true;
1244
1234 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0) 1245 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1235 { 1246 {
1236 // object cannot copy items to an object owned by a different owner 1247 // object cannot copy items to an object owned by a different owner
@@ -1240,7 +1251,7 @@ namespace OpenSim.Region.Framework.Scenes
1240 } 1251 }
1241 1252
1242 // must have both move and modify permission to put an item in an object 1253 // must have both move and modify permission to put an item in an object
1243 if ((part.OwnerMask & ((uint)PermissionMask.Move | (uint)PermissionMask.Modify)) == 0) 1254 if (((part.OwnerMask & (uint)PermissionMask.Modify) == 0) && (!overrideNoMod))
1244 { 1255 {
1245 return; 1256 return;
1246 } 1257 }
@@ -1299,6 +1310,14 @@ namespace OpenSim.Region.Framework.Scenes
1299 1310
1300 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items) 1311 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items)
1301 { 1312 {
1313 SceneObjectPart destPart = GetSceneObjectPart(destID);
1314 if (destPart != null) // Move into a prim
1315 {
1316 foreach(UUID itemID in items)
1317 MoveTaskInventoryItem(destID, host, itemID);
1318 return destID; // Prim folder ID == prim ID
1319 }
1320
1302 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID); 1321 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID);
1303 1322
1304 UUID newFolderID = UUID.Random(); 1323 UUID newFolderID = UUID.Random();
@@ -1472,28 +1491,12 @@ namespace OpenSim.Region.Framework.Scenes
1472// m_log.DebugFormat( 1491// m_log.DebugFormat(
1473// "[PRIM INVENTORY]: Updating item {0} in {1} for UpdateTaskInventory()", 1492// "[PRIM INVENTORY]: Updating item {0} in {1} for UpdateTaskInventory()",
1474// currentItem.Name, part.Name); 1493// currentItem.Name, part.Name);
1475 1494 IAgentAssetTransactions agentTransactions = this.RequestModuleInterface<IAgentAssetTransactions>();
1476 // Viewers from at least Linden Lab 1.23 onwards use a capability to update script contents rather 1495 if (agentTransactions != null)
1477 // than UDP. With viewers from at least 1.23 onwards, changing properties on scripts (e.g. renaming) causes 1496 {
1478 // this to spew spurious errors and "thing saved" messages. 1497 agentTransactions.HandleTaskItemUpdateFromTransaction(
1479 // Rather than retaining complexity in the code and removing useful error messages, I'm going to 1498 remoteClient, part, transactionID, currentItem);
1480 // comment this section out. If this was still working for very old viewers and there is 1499 }
1481 // a large population using them which cannot upgrade to 1.23 or derivatives then we can revisit
1482 // this - justincc
1483// IAgentAssetTransactions agentTransactions = this.RequestModuleInterface<IAgentAssetTransactions>();
1484// if (agentTransactions != null)
1485// {
1486// agentTransactions.HandleTaskItemUpdateFromTransaction(
1487// remoteClient, part, transactionID, currentItem);
1488//
1489// if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1490// remoteClient.SendAgentAlertMessage("Notecard saved", false);
1491// else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1492// remoteClient.SendAgentAlertMessage("Script saved", false);
1493// else
1494// remoteClient.SendAgentAlertMessage("Item saved", false);
1495// }
1496
1497 // Base ALWAYS has move 1500 // Base ALWAYS has move
1498 currentItem.BasePermissions |= (uint)PermissionMask.Move; 1501 currentItem.BasePermissions |= (uint)PermissionMask.Move;
1499 1502
@@ -1670,7 +1673,7 @@ namespace OpenSim.Region.Framework.Scenes
1670 } 1673 }
1671 1674
1672 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, 1675 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType,
1673 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), 1676 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n\n touch_start(integer num)\n {\n }\n}"),
1674 agentID); 1677 agentID);
1675 AssetService.Store(asset); 1678 AssetService.Store(asset);
1676 1679
@@ -1822,23 +1825,32 @@ namespace OpenSim.Region.Framework.Scenes
1822 // build a list of eligible objects 1825 // build a list of eligible objects
1823 List<uint> deleteIDs = new List<uint>(); 1826 List<uint> deleteIDs = new List<uint>();
1824 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); 1827 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
1825 1828 List<SceneObjectGroup> takeGroups = new List<SceneObjectGroup>();
1826 // Start with true for both, then remove the flags if objects
1827 // that we can't derez are part of the selection
1828 bool permissionToTake = true;
1829 bool permissionToTakeCopy = true;
1830 bool permissionToDelete = true;
1831 1829
1832 foreach (uint localID in localIDs) 1830 foreach (uint localID in localIDs)
1833 { 1831 {
1832 // Start with true for both, then remove the flags if objects
1833 // that we can't derez are part of the selection
1834 bool permissionToTake = true;
1835 bool permissionToTakeCopy = true;
1836 bool permissionToDelete = true;
1837
1834 // Invalid id 1838 // Invalid id
1835 SceneObjectPart part = GetSceneObjectPart(localID); 1839 SceneObjectPart part = GetSceneObjectPart(localID);
1836 if (part == null) 1840 if (part == null)
1841 {
1842 //Client still thinks the object exists, kill it
1843 deleteIDs.Add(localID);
1837 continue; 1844 continue;
1845 }
1838 1846
1839 // Already deleted by someone else 1847 // Already deleted by someone else
1840 if (part.ParentGroup.IsDeleted) 1848 if (part.ParentGroup.IsDeleted)
1849 {
1850 //Client still thinks the object exists, kill it
1851 deleteIDs.Add(localID);
1841 continue; 1852 continue;
1853 }
1842 1854
1843 // Can't delete child prims 1855 // Can't delete child prims
1844 if (part != part.ParentGroup.RootPart) 1856 if (part != part.ParentGroup.RootPart)
@@ -1846,9 +1858,6 @@ namespace OpenSim.Region.Framework.Scenes
1846 1858
1847 SceneObjectGroup grp = part.ParentGroup; 1859 SceneObjectGroup grp = part.ParentGroup;
1848 1860
1849 deleteIDs.Add(localID);
1850 deleteGroups.Add(grp);
1851
1852 if (remoteClient == null) 1861 if (remoteClient == null)
1853 { 1862 {
1854 // Autoreturn has a null client. Nothing else does. So 1863 // Autoreturn has a null client. Nothing else does. So
@@ -1865,81 +1874,193 @@ namespace OpenSim.Region.Framework.Scenes
1865 } 1874 }
1866 else 1875 else
1867 { 1876 {
1868 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) 1877 if (action == DeRezAction.TakeCopy)
1878 {
1879 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId))
1880 permissionToTakeCopy = false;
1881 }
1882 else
1883 {
1869 permissionToTakeCopy = false; 1884 permissionToTakeCopy = false;
1870 1885 }
1871 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) 1886 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
1872 permissionToTake = false; 1887 permissionToTake = false;
1873 1888
1874 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) 1889 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
1875 permissionToDelete = false; 1890 permissionToDelete = false;
1876 } 1891 }
1877 }
1878 1892
1879 // Handle god perms 1893 // Handle god perms
1880 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) 1894 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
1881 { 1895 {
1882 permissionToTake = true; 1896 permissionToTake = true;
1883 permissionToTakeCopy = true; 1897 permissionToTakeCopy = true;
1884 permissionToDelete = true; 1898 permissionToDelete = true;
1885 } 1899 }
1886 1900
1887 // If we're re-saving, we don't even want to delete 1901 // If we're re-saving, we don't even want to delete
1888 if (action == DeRezAction.SaveToExistingUserInventoryItem) 1902 if (action == DeRezAction.SaveToExistingUserInventoryItem)
1889 permissionToDelete = false; 1903 permissionToDelete = false;
1890 1904
1891 // if we want to take a copy, we also don't want to delete 1905 // if we want to take a copy, we also don't want to delete
1892 // Note: after this point, the permissionToTakeCopy flag 1906 // Note: after this point, the permissionToTakeCopy flag
1893 // becomes irrelevant. It already includes the permissionToTake 1907 // becomes irrelevant. It already includes the permissionToTake
1894 // permission and after excluding no copy items here, we can 1908 // permission and after excluding no copy items here, we can
1895 // just use that. 1909 // just use that.
1896 if (action == DeRezAction.TakeCopy) 1910 if (action == DeRezAction.TakeCopy)
1897 { 1911 {
1898 // If we don't have permission, stop right here 1912 // If we don't have permission, stop right here
1899 if (!permissionToTakeCopy) 1913 if (!permissionToTakeCopy)
1900 return; 1914 return;
1901 1915
1902 permissionToTake = true; 1916 permissionToTake = true;
1903 // Don't delete 1917 // Don't delete
1904 permissionToDelete = false; 1918 permissionToDelete = false;
1905 } 1919 }
1906 1920
1907 if (action == DeRezAction.Return) 1921 if (action == DeRezAction.Return)
1908 {
1909 if (remoteClient != null)
1910 { 1922 {
1911 if (Permissions.CanReturnObjects( 1923 if (remoteClient != null)
1912 null,
1913 remoteClient.AgentId,
1914 deleteGroups))
1915 { 1924 {
1916 permissionToTake = true; 1925 if (Permissions.CanReturnObjects(
1917 permissionToDelete = true; 1926 null,
1918 1927 remoteClient.AgentId,
1919 foreach (SceneObjectGroup g in deleteGroups) 1928 deleteGroups))
1920 { 1929 {
1921 AddReturn(g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); 1930 permissionToTake = true;
1931 permissionToDelete = true;
1932
1933 AddReturn(grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return");
1922 } 1934 }
1923 } 1935 }
1936 else // Auto return passes through here with null agent
1937 {
1938 permissionToTake = true;
1939 permissionToDelete = true;
1940 }
1924 } 1941 }
1925 else // Auto return passes through here with null agent 1942
1943 if (permissionToTake && (!permissionToDelete))
1944 takeGroups.Add(grp);
1945
1946 if (permissionToDelete)
1926 { 1947 {
1927 permissionToTake = true; 1948 if (permissionToTake)
1928 permissionToDelete = true; 1949 deleteGroups.Add(grp);
1950 deleteIDs.Add(grp.LocalId);
1929 } 1951 }
1930 } 1952 }
1931 1953
1932 if (permissionToTake) 1954 SendKillObject(deleteIDs);
1955
1956 if (deleteGroups.Count > 0)
1933 { 1957 {
1958 foreach (SceneObjectGroup g in deleteGroups)
1959 deleteIDs.Remove(g.LocalId);
1960
1934 m_asyncSceneObjectDeleter.DeleteToInventory( 1961 m_asyncSceneObjectDeleter.DeleteToInventory(
1935 action, destinationID, deleteGroups, remoteClient, 1962 action, destinationID, deleteGroups, remoteClient,
1936 permissionToDelete); 1963 true);
1937 } 1964 }
1938 else if (permissionToDelete) 1965 if (takeGroups.Count > 0)
1966 {
1967 m_asyncSceneObjectDeleter.DeleteToInventory(
1968 action, destinationID, takeGroups, remoteClient,
1969 false);
1970 }
1971 if (deleteIDs.Count > 0)
1939 { 1972 {
1940 foreach (SceneObjectGroup g in deleteGroups) 1973 foreach (SceneObjectGroup g in deleteGroups)
1941 DeleteSceneObject(g, false); 1974 DeleteSceneObject(g, true);
1975 }
1976 }
1977
1978 public UUID attachObjectAssetStore(IClientAPI remoteClient, SceneObjectGroup grp, UUID AgentId, out UUID itemID)
1979 {
1980 itemID = UUID.Zero;
1981 if (grp != null)
1982 {
1983 Vector3 inventoryStoredPosition = new Vector3
1984 (((grp.AbsolutePosition.X > (int)Constants.RegionSize)
1985 ? 250
1986 : grp.AbsolutePosition.X)
1987 ,
1988 (grp.AbsolutePosition.X > (int)Constants.RegionSize)
1989 ? 250
1990 : grp.AbsolutePosition.X,
1991 grp.AbsolutePosition.Z);
1992
1993 Vector3 originalPosition = grp.AbsolutePosition;
1994
1995 grp.AbsolutePosition = inventoryStoredPosition;
1996
1997 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
1998
1999 grp.AbsolutePosition = originalPosition;
2000
2001 AssetBase asset = CreateAsset(
2002 grp.GetPartName(grp.LocalId),
2003 grp.GetPartDescription(grp.LocalId),
2004 (sbyte)AssetType.Object,
2005 Utils.StringToBytes(sceneObjectXml),
2006 remoteClient.AgentId);
2007 AssetService.Store(asset);
2008
2009 InventoryItemBase item = new InventoryItemBase();
2010 item.CreatorId = grp.RootPart.CreatorID.ToString();
2011 item.CreatorData = grp.RootPart.CreatorData;
2012 item.Owner = remoteClient.AgentId;
2013 item.ID = UUID.Random();
2014 item.AssetID = asset.FullID;
2015 item.Description = asset.Description;
2016 item.Name = asset.Name;
2017 item.AssetType = asset.Type;
2018 item.InvType = (int)InventoryType.Object;
2019
2020 InventoryFolderBase folder = InventoryService.GetFolderForType(remoteClient.AgentId, AssetType.Object);
2021 if (folder != null)
2022 item.Folder = folder.ID;
2023 else // oopsies
2024 item.Folder = UUID.Zero;
2025
2026 // Set up base perms properly
2027 uint permsBase = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify);
2028 permsBase &= grp.RootPart.BaseMask;
2029 permsBase |= (uint)PermissionMask.Move;
2030
2031 // Make sure we don't lock it
2032 grp.RootPart.NextOwnerMask |= (uint)PermissionMask.Move;
2033
2034 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions())
2035 {
2036 item.BasePermissions = permsBase & grp.RootPart.NextOwnerMask;
2037 item.CurrentPermissions = permsBase & grp.RootPart.NextOwnerMask;
2038 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
2039 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask;
2040 item.GroupPermissions = permsBase & grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask;
2041 }
2042 else
2043 {
2044 item.BasePermissions = permsBase;
2045 item.CurrentPermissions = permsBase & grp.RootPart.OwnerMask;
2046 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
2047 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask;
2048 item.GroupPermissions = permsBase & grp.RootPart.GroupMask;
2049 }
2050 item.CreationDate = Util.UnixTimeSinceEpoch();
2051
2052 // sets itemID so client can show item as 'attached' in inventory
2053 grp.SetFromItemID(item.ID);
2054
2055 if (AddInventoryItem(item))
2056 remoteClient.SendInventoryItemCreateUpdate(item, 0);
2057 else
2058 m_dialogModule.SendAlertToUser(remoteClient, "Operation failed");
2059
2060 itemID = item.ID;
2061 return item.AssetID;
1942 } 2062 }
2063 return UUID.Zero;
1943 } 2064 }
1944 2065
1945 /// <summary> 2066 /// <summary>
@@ -2068,6 +2189,9 @@ namespace OpenSim.Region.Framework.Scenes
2068 2189
2069 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running) 2190 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running)
2070 { 2191 {
2192 if (!Permissions.CanEditScript(itemID, objectID, controllingClient.AgentId))
2193 return;
2194
2071 SceneObjectPart part = GetSceneObjectPart(objectID); 2195 SceneObjectPart part = GetSceneObjectPart(objectID);
2072 if (part == null) 2196 if (part == null)
2073 return; 2197 return;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index 3355ebe..bf2e775 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -346,7 +346,10 @@ namespace OpenSim.Region.Framework.Scenes
346 List<UserAccount> accounts = UserAccountService.GetUserAccounts(RegionInfo.ScopeID, query); 346 List<UserAccount> accounts = UserAccountService.GetUserAccounts(RegionInfo.ScopeID, query);
347 347
348 if (accounts == null) 348 if (accounts == null)
349 {
350 m_log.DebugFormat("[LLCIENT]: ProcessAvatarPickerRequest: returned null result");
349 return; 351 return;
352 }
350 353
351 AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket) PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply); 354 AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket) PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply);
352 // TODO: don't create new blocks if recycling an old packet 355 // TODO: don't create new blocks if recycling an old packet
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 23fee4e..b37df82 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -104,6 +104,7 @@ namespace OpenSim.Region.Framework.Scenes
104 // TODO: need to figure out how allow client agents but deny 104 // TODO: need to figure out how allow client agents but deny
105 // root agents when ACL denies access to root agent 105 // root agents when ACL denies access to root agent
106 public bool m_strictAccessControl = true; 106 public bool m_strictAccessControl = true;
107 public bool m_seeIntoBannedRegion = false;
107 public int MaxUndoCount = 5; 108 public int MaxUndoCount = 5;
108 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; 109 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet;
109 public bool LoginLock = false; 110 public bool LoginLock = false;
@@ -119,12 +120,14 @@ namespace OpenSim.Region.Framework.Scenes
119 120
120 protected int m_splitRegionID; 121 protected int m_splitRegionID;
121 protected Timer m_restartWaitTimer = new Timer(); 122 protected Timer m_restartWaitTimer = new Timer();
123 protected Timer m_timerWatchdog = new Timer();
122 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>(); 124 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>();
123 protected List<RegionInfo> m_neighbours = new List<RegionInfo>(); 125 protected List<RegionInfo> m_neighbours = new List<RegionInfo>();
124 protected string m_simulatorVersion = "OpenSimulator Server"; 126 protected string m_simulatorVersion = "OpenSimulator Server";
125 protected ModuleLoader m_moduleLoader; 127 protected ModuleLoader m_moduleLoader;
126 protected AgentCircuitManager m_authenticateHandler; 128 protected AgentCircuitManager m_authenticateHandler;
127 protected SceneCommunicationService m_sceneGridService; 129 protected SceneCommunicationService m_sceneGridService;
130 protected ISnmpModule m_snmpService = null;
128 131
129 protected ISimulationDataService m_SimulationDataService; 132 protected ISimulationDataService m_SimulationDataService;
130 protected IEstateDataService m_EstateDataService; 133 protected IEstateDataService m_EstateDataService;
@@ -177,7 +180,7 @@ namespace OpenSim.Region.Framework.Scenes
177 private int m_update_events = 1; 180 private int m_update_events = 1;
178 private int m_update_backup = 200; 181 private int m_update_backup = 200;
179 private int m_update_terrain = 50; 182 private int m_update_terrain = 50;
180// private int m_update_land = 1; 183 private int m_update_land = 10;
181 private int m_update_coarse_locations = 50; 184 private int m_update_coarse_locations = 50;
182 185
183 private int agentMS; 186 private int agentMS;
@@ -192,6 +195,7 @@ namespace OpenSim.Region.Framework.Scenes
192 private int landMS; 195 private int landMS;
193 private int lastCompletedFrame; 196 private int lastCompletedFrame;
194 197
198 public bool CombineRegions = false;
195 /// <summary> 199 /// <summary>
196 /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched 200 /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched
197 /// asynchronously from the update loop. 201 /// asynchronously from the update loop.
@@ -214,11 +218,14 @@ namespace OpenSim.Region.Framework.Scenes
214 private bool m_scripts_enabled = true; 218 private bool m_scripts_enabled = true;
215 private string m_defaultScriptEngine; 219 private string m_defaultScriptEngine;
216 private int m_LastLogin; 220 private int m_LastLogin;
217 private Thread HeartbeatThread; 221 private Thread HeartbeatThread = null;
218 private volatile bool shuttingdown; 222 private volatile bool shuttingdown;
219 223
220 private int m_lastUpdate; 224 private int m_lastUpdate;
225 private int m_lastIncoming;
226 private int m_lastOutgoing;
221 private bool m_firstHeartbeat = true; 227 private bool m_firstHeartbeat = true;
228 private int m_hbRestarts = 0;
222 229
223 private object m_deleting_scene_object = new object(); 230 private object m_deleting_scene_object = new object();
224 231
@@ -265,6 +272,19 @@ namespace OpenSim.Region.Framework.Scenes
265 get { return m_sceneGridService; } 272 get { return m_sceneGridService; }
266 } 273 }
267 274
275 public ISnmpModule SnmpService
276 {
277 get
278 {
279 if (m_snmpService == null)
280 {
281 m_snmpService = RequestModuleInterface<ISnmpModule>();
282 }
283
284 return m_snmpService;
285 }
286 }
287
268 public ISimulationDataService SimulationDataService 288 public ISimulationDataService SimulationDataService
269 { 289 {
270 get 290 get
@@ -546,6 +566,9 @@ namespace OpenSim.Region.Framework.Scenes
546 m_EstateDataService = estateDataService; 566 m_EstateDataService = estateDataService;
547 m_regionHandle = m_regInfo.RegionHandle; 567 m_regionHandle = m_regInfo.RegionHandle;
548 m_regionName = m_regInfo.RegionName; 568 m_regionName = m_regInfo.RegionName;
569 m_lastUpdate = Util.EnvironmentTickCount();
570 m_lastIncoming = 0;
571 m_lastOutgoing = 0;
549 572
550 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this); 573 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
551 m_asyncSceneObjectDeleter.Enabled = true; 574 m_asyncSceneObjectDeleter.Enabled = true;
@@ -646,6 +669,7 @@ namespace OpenSim.Region.Framework.Scenes
646 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true); 669 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
647 670
648 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); 671 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys);
672
649 if (RegionInfo.NonphysPrimMax > 0) 673 if (RegionInfo.NonphysPrimMax > 0)
650 { 674 {
651 m_maxNonphys = RegionInfo.NonphysPrimMax; 675 m_maxNonphys = RegionInfo.NonphysPrimMax;
@@ -677,6 +701,7 @@ namespace OpenSim.Region.Framework.Scenes
677 m_persistAfter *= 10000000; 701 m_persistAfter *= 10000000;
678 702
679 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 703 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
704 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
680 705
681 IConfig packetConfig = m_config.Configs["PacketPool"]; 706 IConfig packetConfig = m_config.Configs["PacketPool"];
682 if (packetConfig != null) 707 if (packetConfig != null)
@@ -686,6 +711,8 @@ namespace OpenSim.Region.Framework.Scenes
686 } 711 }
687 712
688 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 713 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
714 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
715 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
689 716
690 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true); 717 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true);
691 if (m_generateMaptiles) 718 if (m_generateMaptiles)
@@ -721,9 +748,9 @@ namespace OpenSim.Region.Framework.Scenes
721 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain); 748 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain);
722 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning); 749 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning);
723 } 750 }
724 catch 751 catch (Exception e)
725 { 752 {
726 m_log.Warn("[SCENE]: Failed to load StartupConfig"); 753 m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString());
727 } 754 }
728 755
729 #endregion Region Config 756 #endregion Region Config
@@ -1134,7 +1161,22 @@ namespace OpenSim.Region.Framework.Scenes
1134 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); 1161 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
1135 if (HeartbeatThread != null) 1162 if (HeartbeatThread != null)
1136 { 1163 {
1164 m_hbRestarts++;
1165 if(m_hbRestarts > 10)
1166 Environment.Exit(1);
1167 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1168
1169//int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
1170//System.Diagnostics.Process proc = new System.Diagnostics.Process();
1171//proc.EnableRaisingEvents=false;
1172//proc.StartInfo.FileName = "/bin/kill";
1173//proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
1174//proc.Start();
1175//proc.WaitForExit();
1176//Thread.Sleep(1000);
1177//Environment.Exit(1);
1137 HeartbeatThread.Abort(); 1178 HeartbeatThread.Abort();
1179 Watchdog.AbortThread(HeartbeatThread.ManagedThreadId);
1138 HeartbeatThread = null; 1180 HeartbeatThread = null;
1139 } 1181 }
1140 m_lastUpdate = Util.EnvironmentTickCount(); 1182 m_lastUpdate = Util.EnvironmentTickCount();
@@ -1181,9 +1223,6 @@ namespace OpenSim.Region.Framework.Scenes
1181 m_eventManager.TriggerOnRegionStarted(this); 1223 m_eventManager.TriggerOnRegionStarted(this);
1182 while (!shuttingdown) 1224 while (!shuttingdown)
1183 Update(); 1225 Update();
1184
1185 m_lastUpdate = Util.EnvironmentTickCount();
1186 m_firstHeartbeat = false;
1187 } 1226 }
1188 catch (ThreadAbortException) 1227 catch (ThreadAbortException)
1189 { 1228 {
@@ -1281,6 +1320,13 @@ namespace OpenSim.Region.Framework.Scenes
1281 eventMS = Util.EnvironmentTickCountSubtract(evMS); ; 1320 eventMS = Util.EnvironmentTickCountSubtract(evMS); ;
1282 } 1321 }
1283 1322
1323 // if (Frame % m_update_land == 0)
1324 // {
1325 // int ldMS = Util.EnvironmentTickCount();
1326 // UpdateLand();
1327 // landMS = Util.EnvironmentTickCountSubtract(ldMS);
1328 // }
1329
1284 if (Frame % m_update_backup == 0) 1330 if (Frame % m_update_backup == 0)
1285 { 1331 {
1286 int backMS = Util.EnvironmentTickCount(); 1332 int backMS = Util.EnvironmentTickCount();
@@ -1388,12 +1434,16 @@ namespace OpenSim.Region.Framework.Scenes
1388 maintc = Util.EnvironmentTickCountSubtract(maintc); 1434 maintc = Util.EnvironmentTickCountSubtract(maintc);
1389 maintc = (int)(MinFrameTime * 1000) - maintc; 1435 maintc = (int)(MinFrameTime * 1000) - maintc;
1390 1436
1437
1438 m_lastUpdate = Util.EnvironmentTickCount();
1439 m_firstHeartbeat = false;
1440
1391 if (maintc > 0) 1441 if (maintc > 0)
1392 Thread.Sleep(maintc); 1442 Thread.Sleep(maintc);
1393 1443
1394 // Tell the watchdog that this thread is still alive 1444 // Tell the watchdog that this thread is still alive
1395 Watchdog.UpdateThread(); 1445 Watchdog.UpdateThread();
1396 } 1446 }
1397 1447
1398 public void AddGroupTarget(SceneObjectGroup grp) 1448 public void AddGroupTarget(SceneObjectGroup grp)
1399 { 1449 {
@@ -1409,9 +1459,9 @@ namespace OpenSim.Region.Framework.Scenes
1409 1459
1410 private void CheckAtTargets() 1460 private void CheckAtTargets()
1411 { 1461 {
1412 Dictionary<UUID, SceneObjectGroup>.ValueCollection objs; 1462 List<SceneObjectGroup> objs = new List<SceneObjectGroup>();
1413 lock (m_groupsWithTargets) 1463 lock (m_groupsWithTargets)
1414 objs = m_groupsWithTargets.Values; 1464 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values);
1415 1465
1416 foreach (SceneObjectGroup entry in objs) 1466 foreach (SceneObjectGroup entry in objs)
1417 entry.checkAtTargets(); 1467 entry.checkAtTargets();
@@ -1493,7 +1543,7 @@ namespace OpenSim.Region.Framework.Scenes
1493 msg.fromAgentName = "Server"; 1543 msg.fromAgentName = "Server";
1494 msg.dialog = (byte)19; // Object msg 1544 msg.dialog = (byte)19; // Object msg
1495 msg.fromGroup = false; 1545 msg.fromGroup = false;
1496 msg.offline = (byte)0; 1546 msg.offline = (byte)1;
1497 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID; 1547 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID;
1498 msg.Position = Vector3.Zero; 1548 msg.Position = Vector3.Zero;
1499 msg.RegionID = RegionInfo.RegionID.Guid; 1549 msg.RegionID = RegionInfo.RegionID.Guid;
@@ -1724,14 +1774,24 @@ namespace OpenSim.Region.Framework.Scenes
1724 /// <returns></returns> 1774 /// <returns></returns>
1725 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 1775 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
1726 { 1776 {
1777
1778 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
1779 Vector3 wpos = Vector3.Zero;
1780 // Check for water surface intersection from above
1781 if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) )
1782 {
1783 float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
1784 wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
1785 wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y));
1786 wpos.Z = wheight;
1787 }
1788
1727 Vector3 pos = Vector3.Zero; 1789 Vector3 pos = Vector3.Zero;
1728 if (RayEndIsIntersection == (byte)1) 1790 if (RayEndIsIntersection == (byte)1)
1729 { 1791 {
1730 pos = RayEnd; 1792 pos = RayEnd;
1731 return pos;
1732 } 1793 }
1733 1794 else if (RayTargetID != UUID.Zero)
1734 if (RayTargetID != UUID.Zero)
1735 { 1795 {
1736 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 1796 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
1737 1797
@@ -1753,7 +1813,7 @@ namespace OpenSim.Region.Framework.Scenes
1753 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 1813 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
1754 1814
1755 // Un-comment out the following line to Get Raytrace results printed to the console. 1815 // Un-comment out the following line to Get Raytrace results printed to the console.
1756 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 1816 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1757 float ScaleOffset = 0.5f; 1817 float ScaleOffset = 0.5f;
1758 1818
1759 // If we hit something 1819 // If we hit something
@@ -1776,13 +1836,10 @@ namespace OpenSim.Region.Framework.Scenes
1776 //pos.Z -= 0.25F; 1836 //pos.Z -= 0.25F;
1777 1837
1778 } 1838 }
1779
1780 return pos;
1781 } 1839 }
1782 else 1840 else
1783 { 1841 {
1784 // We don't have a target here, so we're going to raytrace all the objects in the scene. 1842 // We don't have a target here, so we're going to raytrace all the objects in the scene.
1785
1786 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 1843 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
1787 1844
1788 // Un-comment the following line to print the raytrace results to the console. 1845 // Un-comment the following line to print the raytrace results to the console.
@@ -1791,13 +1848,12 @@ namespace OpenSim.Region.Framework.Scenes
1791 if (ei.HitTF) 1848 if (ei.HitTF)
1792 { 1849 {
1793 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 1850 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1794 } else 1851 }
1852 else
1795 { 1853 {
1796 // fall back to our stupid functionality 1854 // fall back to our stupid functionality
1797 pos = RayEnd; 1855 pos = RayEnd;
1798 } 1856 }
1799
1800 return pos;
1801 } 1857 }
1802 } 1858 }
1803 else 1859 else
@@ -1808,8 +1864,12 @@ namespace OpenSim.Region.Framework.Scenes
1808 //increase height so its above the ground. 1864 //increase height so its above the ground.
1809 //should be getting the normal of the ground at the rez point and using that? 1865 //should be getting the normal of the ground at the rez point and using that?
1810 pos.Z += scale.Z / 2f; 1866 pos.Z += scale.Z / 2f;
1811 return pos; 1867// return pos;
1812 } 1868 }
1869
1870 // check against posible water intercept
1871 if (wpos.Z > pos.Z) pos = wpos;
1872 return pos;
1813 } 1873 }
1814 1874
1815 1875
@@ -1893,7 +1953,10 @@ namespace OpenSim.Region.Framework.Scenes
1893 public bool AddRestoredSceneObject( 1953 public bool AddRestoredSceneObject(
1894 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 1954 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
1895 { 1955 {
1896 return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 1956 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates);
1957 if (result)
1958 sceneObject.IsDeleted = false;
1959 return result;
1897 } 1960 }
1898 1961
1899 /// <summary> 1962 /// <summary>
@@ -1985,6 +2048,15 @@ namespace OpenSim.Region.Framework.Scenes
1985 /// </summary> 2048 /// </summary>
1986 public void DeleteAllSceneObjects() 2049 public void DeleteAllSceneObjects()
1987 { 2050 {
2051 DeleteAllSceneObjects(false);
2052 }
2053
2054 /// <summary>
2055 /// Delete every object from the scene. This does not include attachments worn by avatars.
2056 /// </summary>
2057 public void DeleteAllSceneObjects(bool exceptNoCopy)
2058 {
2059 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
1988 lock (Entities) 2060 lock (Entities)
1989 { 2061 {
1990 EntityBase[] entities = Entities.GetEntities(); 2062 EntityBase[] entities = Entities.GetEntities();
@@ -1993,11 +2065,24 @@ namespace OpenSim.Region.Framework.Scenes
1993 if (e is SceneObjectGroup) 2065 if (e is SceneObjectGroup)
1994 { 2066 {
1995 SceneObjectGroup sog = (SceneObjectGroup)e; 2067 SceneObjectGroup sog = (SceneObjectGroup)e;
1996 if (!sog.IsAttachment) 2068 if (sog != null && !sog.IsAttachment)
1997 DeleteSceneObject((SceneObjectGroup)e, false); 2069 {
2070 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2071 {
2072 DeleteSceneObject((SceneObjectGroup)e, false);
2073 }
2074 else
2075 {
2076 toReturn.Add((SceneObjectGroup)e);
2077 }
2078 }
1998 } 2079 }
1999 } 2080 }
2000 } 2081 }
2082 if (toReturn.Count > 0)
2083 {
2084 returnObjects(toReturn.ToArray(), UUID.Zero);
2085 }
2001 } 2086 }
2002 2087
2003 /// <summary> 2088 /// <summary>
@@ -2045,6 +2130,8 @@ namespace OpenSim.Region.Framework.Scenes
2045 } 2130 }
2046 2131
2047 group.DeleteGroupFromScene(silent); 2132 group.DeleteGroupFromScene(silent);
2133 if (!silent)
2134 SendKillObject(new List<uint>() { group.LocalId });
2048 2135
2049// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2136// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2050 } 2137 }
@@ -2399,10 +2486,17 @@ namespace OpenSim.Region.Framework.Scenes
2399 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2486 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2400 public bool AddSceneObject(SceneObjectGroup sceneObject) 2487 public bool AddSceneObject(SceneObjectGroup sceneObject)
2401 { 2488 {
2489 if (sceneObject.OwnerID == UUID.Zero)
2490 {
2491 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2492 return false;
2493 }
2494
2402 // If the user is banned, we won't let any of their objects 2495 // If the user is banned, we won't let any of their objects
2403 // enter. Period. 2496 // enter. Period.
2404 // 2497 //
2405 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID)) 2498 int flags = GetUserFlags(sceneObject.OwnerID);
2499 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2406 { 2500 {
2407 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID); 2501 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID);
2408 2502
@@ -2448,12 +2542,23 @@ namespace OpenSim.Region.Framework.Scenes
2448 } 2542 }
2449 else 2543 else
2450 { 2544 {
2545 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2451 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2546 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2452 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 2547 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2453 } 2548 }
2549 if (sceneObject.OwnerID == UUID.Zero)
2550 {
2551 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
2552 return false;
2553 }
2454 } 2554 }
2455 else 2555 else
2456 { 2556 {
2557 if (sceneObject.OwnerID == UUID.Zero)
2558 {
2559 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
2560 return false;
2561 }
2457 AddRestoredSceneObject(sceneObject, true, false); 2562 AddRestoredSceneObject(sceneObject, true, false);
2458 2563
2459 if (!Permissions.CanObjectEntry(sceneObject.UUID, 2564 if (!Permissions.CanObjectEntry(sceneObject.UUID,
@@ -2482,6 +2587,24 @@ namespace OpenSim.Region.Framework.Scenes
2482 return 2; // StateSource.PrimCrossing 2587 return 2; // StateSource.PrimCrossing
2483 } 2588 }
2484 2589
2590 public int GetUserFlags(UUID user)
2591 {
2592 //Unfortunately the SP approach means that the value is cached until region is restarted
2593 /*
2594 ScenePresence sp;
2595 if (TryGetScenePresence(user, out sp))
2596 {
2597 return sp.UserFlags;
2598 }
2599 else
2600 {
2601 */
2602 UserAccount uac = UserAccountService.GetUserAccount(RegionInfo.ScopeID, user);
2603 if (uac == null)
2604 return 0;
2605 return uac.UserFlags;
2606 //}
2607 }
2485 #endregion 2608 #endregion
2486 2609
2487 #region Add/Remove Avatar Methods 2610 #region Add/Remove Avatar Methods
@@ -2496,6 +2619,7 @@ namespace OpenSim.Region.Framework.Scenes
2496 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 2619 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2497 2620
2498 CheckHeartbeat(); 2621 CheckHeartbeat();
2622 ScenePresence presence;
2499 2623
2500 ScenePresence sp = GetScenePresence(client.AgentId); 2624 ScenePresence sp = GetScenePresence(client.AgentId);
2501 2625
@@ -2544,7 +2668,13 @@ namespace OpenSim.Region.Framework.Scenes
2544 2668
2545 EventManager.TriggerOnNewClient(client); 2669 EventManager.TriggerOnNewClient(client);
2546 if (vialogin) 2670 if (vialogin)
2671 {
2547 EventManager.TriggerOnClientLogin(client); 2672 EventManager.TriggerOnClientLogin(client);
2673 // Send initial parcel data
2674 Vector3 pos = sp.AbsolutePosition;
2675 ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y);
2676 land.SendLandUpdateToClient(client);
2677 }
2548 2678
2549 return sp; 2679 return sp;
2550 } 2680 }
@@ -2634,19 +2764,12 @@ namespace OpenSim.Region.Framework.Scenes
2634 // and the scene presence and the client, if they exist 2764 // and the scene presence and the client, if they exist
2635 try 2765 try
2636 { 2766 {
2637 // We need to wait for the client to make UDP contact first. 2767 ScenePresence sp = GetScenePresence(agentID);
2638 // It's the UDP contact that creates the scene presence 2768 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2639 ScenePresence sp = WaitGetScenePresence(agentID); 2769
2640 if (sp != null) 2770 if (sp != null)
2641 {
2642 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2643
2644 sp.ControllingClient.Close(); 2771 sp.ControllingClient.Close();
2645 } 2772
2646 else
2647 {
2648 m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID);
2649 }
2650 // BANG! SLASH! 2773 // BANG! SLASH!
2651 m_authenticateHandler.RemoveCircuit(agentID); 2774 m_authenticateHandler.RemoveCircuit(agentID);
2652 2775
@@ -2747,6 +2870,7 @@ namespace OpenSim.Region.Framework.Scenes
2747 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory; 2870 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory;
2748 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 2871 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
2749 client.OnCopyInventoryItem += CopyInventoryItem; 2872 client.OnCopyInventoryItem += CopyInventoryItem;
2873 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
2750 client.OnMoveInventoryItem += MoveInventoryItem; 2874 client.OnMoveInventoryItem += MoveInventoryItem;
2751 client.OnRemoveInventoryItem += RemoveInventoryItem; 2875 client.OnRemoveInventoryItem += RemoveInventoryItem;
2752 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 2876 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -2922,15 +3046,16 @@ namespace OpenSim.Region.Framework.Scenes
2922 /// </summary> 3046 /// </summary>
2923 /// <param name="agentId">The avatar's Unique ID</param> 3047 /// <param name="agentId">The avatar's Unique ID</param>
2924 /// <param name="client">The IClientAPI for the client</param> 3048 /// <param name="client">The IClientAPI for the client</param>
2925 public virtual void TeleportClientHome(UUID agentId, IClientAPI client) 3049 public virtual bool TeleportClientHome(UUID agentId, IClientAPI client)
2926 { 3050 {
2927 if (m_teleportModule != null) 3051 if (m_teleportModule != null)
2928 m_teleportModule.TeleportHome(agentId, client); 3052 return m_teleportModule.TeleportHome(agentId, client);
2929 else 3053 else
2930 { 3054 {
2931 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); 3055 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active");
2932 client.SendTeleportFailed("Unable to perform teleports on this simulator."); 3056 client.SendTeleportFailed("Unable to perform teleports on this simulator.");
2933 } 3057 }
3058 return false;
2934 } 3059 }
2935 3060
2936 /// <summary> 3061 /// <summary>
@@ -3022,6 +3147,16 @@ namespace OpenSim.Region.Framework.Scenes
3022 /// <param name="flags"></param> 3147 /// <param name="flags"></param>
3023 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) 3148 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
3024 { 3149 {
3150 //Add half the avatar's height so that the user doesn't fall through prims
3151 ScenePresence presence;
3152 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3153 {
3154 if (presence.Appearance != null)
3155 {
3156 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3157 }
3158 }
3159
3025 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) 3160 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
3026 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. 3161 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
3027 m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); 3162 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
@@ -3090,8 +3225,9 @@ namespace OpenSim.Region.Framework.Scenes
3090 regions.Remove(RegionInfo.RegionHandle); 3225 regions.Remove(RegionInfo.RegionHandle);
3091 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3226 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3092 } 3227 }
3093 3228 m_log.Debug("[Scene] Beginning ClientClosed");
3094 m_eventManager.TriggerClientClosed(agentID, this); 3229 m_eventManager.TriggerClientClosed(agentID, this);
3230 m_log.Debug("[Scene] Finished ClientClosed");
3095 } 3231 }
3096 catch (NullReferenceException) 3232 catch (NullReferenceException)
3097 { 3233 {
@@ -3153,9 +3289,10 @@ namespace OpenSim.Region.Framework.Scenes
3153 { 3289 {
3154 m_log.ErrorFormat("[SCENE] Scene.cs:RemoveClient exception {0}{1}", e.Message, e.StackTrace); 3290 m_log.ErrorFormat("[SCENE] Scene.cs:RemoveClient exception {0}{1}", e.Message, e.StackTrace);
3155 } 3291 }
3156 3292 m_log.Debug("[Scene] Done. Firing RemoveCircuit");
3157 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3293 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3158// CleanDroppedAttachments(); 3294// CleanDroppedAttachments();
3295 m_log.Debug("[Scene] The avatar has left the building");
3159 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 3296 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
3160 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); 3297 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
3161 } 3298 }
@@ -3274,13 +3411,16 @@ namespace OpenSim.Region.Framework.Scenes
3274 sp = null; 3411 sp = null;
3275 } 3412 }
3276 3413
3277 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3278 3414
3279 //On login test land permisions 3415 //On login test land permisions
3280 if (vialogin) 3416 if (vialogin)
3281 { 3417 {
3282 if (land != null && !TestLandRestrictions(agent, land, out reason)) 3418 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3419 if (cache != null)
3420 cache.Remove(agent.firstname + " " + agent.lastname);
3421 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3283 { 3422 {
3423 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3284 return false; 3424 return false;
3285 } 3425 }
3286 } 3426 }
@@ -3304,8 +3444,13 @@ namespace OpenSim.Region.Framework.Scenes
3304 3444
3305 try 3445 try
3306 { 3446 {
3307 if (!AuthorizeUser(agent, out reason)) 3447 // Always check estate if this is a login. Always
3308 return false; 3448 // check if banned regions are to be blacked out.
3449 if (vialogin || (!m_seeIntoBannedRegion))
3450 {
3451 if (!AuthorizeUser(agent, out reason))
3452 return false;
3453 }
3309 } 3454 }
3310 catch (Exception e) 3455 catch (Exception e)
3311 { 3456 {
@@ -3408,6 +3553,8 @@ namespace OpenSim.Region.Framework.Scenes
3408 } 3553 }
3409 } 3554 }
3410 // Honor parcel landing type and position. 3555 // Honor parcel landing type and position.
3556 /*
3557 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3411 if (land != null) 3558 if (land != null)
3412 { 3559 {
3413 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3560 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3415,26 +3562,34 @@ namespace OpenSim.Region.Framework.Scenes
3415 agent.startpos = land.LandData.UserLocation; 3562 agent.startpos = land.LandData.UserLocation;
3416 } 3563 }
3417 } 3564 }
3565 */// This is now handled properly in ScenePresence.MakeRootAgent
3418 } 3566 }
3419 3567
3420 return true; 3568 return true;
3421 } 3569 }
3422 3570
3423 private bool TestLandRestrictions(AgentCircuitData agent, ILandObject land, out string reason) 3571 public bool TestLandRestrictions(UUID agentID, out string reason, ref float posX, ref float posY)
3424 { 3572 {
3425 3573 reason = String.Empty;
3426 bool banned = land.IsBannedFromLand(agent.AgentID); 3574 if (Permissions.IsGod(agentID))
3427 bool restricted = land.IsRestrictedFromLand(agent.AgentID); 3575 return true;
3576
3577 ILandObject land = LandChannel.GetLandObject(posX, posY);
3578 if (land == null)
3579 return false;
3580
3581 bool banned = land.IsBannedFromLand(agentID);
3582 bool restricted = land.IsRestrictedFromLand(agentID);
3428 3583
3429 if (banned || restricted) 3584 if (banned || restricted)
3430 { 3585 {
3431 ILandObject nearestParcel = GetNearestAllowedParcel(agent.AgentID, agent.startpos.X, agent.startpos.Y); 3586 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY);
3432 if (nearestParcel != null) 3587 if (nearestParcel != null)
3433 { 3588 {
3434 //Move agent to nearest allowed 3589 //Move agent to nearest allowed
3435 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); 3590 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel);
3436 agent.startpos.X = newPosition.X; 3591 posX = newPosition.X;
3437 agent.startpos.Y = newPosition.Y; 3592 posY = newPosition.Y;
3438 } 3593 }
3439 else 3594 else
3440 { 3595 {
@@ -3496,7 +3651,7 @@ namespace OpenSim.Region.Framework.Scenes
3496 3651
3497 if (!m_strictAccessControl) return true; 3652 if (!m_strictAccessControl) return true;
3498 if (Permissions.IsGod(agent.AgentID)) return true; 3653 if (Permissions.IsGod(agent.AgentID)) return true;
3499 3654
3500 if (AuthorizationService != null) 3655 if (AuthorizationService != null)
3501 { 3656 {
3502 if (!AuthorizationService.IsAuthorizedForRegion( 3657 if (!AuthorizationService.IsAuthorizedForRegion(
@@ -3504,14 +3659,14 @@ namespace OpenSim.Region.Framework.Scenes
3504 { 3659 {
3505 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region", 3660 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region",
3506 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3661 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
3507 3662
3508 return false; 3663 return false;
3509 } 3664 }
3510 } 3665 }
3511 3666
3512 if (m_regInfo.EstateSettings != null) 3667 if (m_regInfo.EstateSettings != null)
3513 { 3668 {
3514 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID)) 3669 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID,0))
3515 { 3670 {
3516 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 3671 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
3517 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3672 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
@@ -3703,6 +3858,13 @@ namespace OpenSim.Region.Framework.Scenes
3703 3858
3704 // We have to wait until the viewer contacts this region after receiving EAC. 3859 // We have to wait until the viewer contacts this region after receiving EAC.
3705 // That calls AddNewClient, which finally creates the ScenePresence 3860 // That calls AddNewClient, which finally creates the ScenePresence
3861 int flags = GetUserFlags(cAgentData.AgentID);
3862 if (m_regInfo.EstateSettings.IsBanned(cAgentData.AgentID, flags))
3863 {
3864 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
3865 return false;
3866 }
3867
3706 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 3868 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
3707 if (nearestParcel == null) 3869 if (nearestParcel == null)
3708 { 3870 {
@@ -3784,12 +3946,22 @@ namespace OpenSim.Region.Framework.Scenes
3784 return false; 3946 return false;
3785 } 3947 }
3786 3948
3949 public bool IncomingCloseAgent(UUID agentID)
3950 {
3951 return IncomingCloseAgent(agentID, false);
3952 }
3953
3954 public bool IncomingCloseChildAgent(UUID agentID)
3955 {
3956 return IncomingCloseAgent(agentID, true);
3957 }
3958
3787 /// <summary> 3959 /// <summary>
3788 /// Tell a single agent to disconnect from the region. 3960 /// Tell a single agent to disconnect from the region.
3789 /// </summary> 3961 /// </summary>
3790 /// <param name="regionHandle"></param>
3791 /// <param name="agentID"></param> 3962 /// <param name="agentID"></param>
3792 public bool IncomingCloseAgent(UUID agentID) 3963 /// <param name="childOnly"></param>
3964 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
3793 { 3965 {
3794 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 3966 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
3795 3967
@@ -3801,7 +3973,7 @@ namespace OpenSim.Region.Framework.Scenes
3801 { 3973 {
3802 m_sceneGraph.removeUserCount(false); 3974 m_sceneGraph.removeUserCount(false);
3803 } 3975 }
3804 else 3976 else if (!childOnly)
3805 { 3977 {
3806 m_sceneGraph.removeUserCount(true); 3978 m_sceneGraph.removeUserCount(true);
3807 } 3979 }
@@ -3817,9 +3989,12 @@ namespace OpenSim.Region.Framework.Scenes
3817 } 3989 }
3818 else 3990 else
3819 presence.ControllingClient.SendShutdownConnectionNotice(); 3991 presence.ControllingClient.SendShutdownConnectionNotice();
3992 presence.ControllingClient.Close(false);
3993 }
3994 else if (!childOnly)
3995 {
3996 presence.ControllingClient.Close(true);
3820 } 3997 }
3821
3822 presence.ControllingClient.Close();
3823 return true; 3998 return true;
3824 } 3999 }
3825 4000
@@ -4402,34 +4577,78 @@ namespace OpenSim.Region.Framework.Scenes
4402 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID); 4577 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID);
4403 } 4578 }
4404 4579
4405 public int GetHealth() 4580 public int GetHealth(out int flags, out string message)
4406 { 4581 {
4407 // Returns: 4582 // Returns:
4408 // 1 = sim is up and accepting http requests. The heartbeat has 4583 // 1 = sim is up and accepting http requests. The heartbeat has
4409 // stopped and the sim is probably locked up, but a remote 4584 // stopped and the sim is probably locked up, but a remote
4410 // admin restart may succeed 4585 // admin restart may succeed
4411 // 4586 //
4412 // 2 = Sim is up and the heartbeat is running. The sim is likely 4587 // 2 = Sim is up and the heartbeat is running. The sim is likely
4413 // usable for people within and logins _may_ work 4588 // usable for people within
4589 //
4590 // 3 = Sim is up and one packet thread is running. Sim is
4591 // unstable and will not accept new logins
4414 // 4592 //
4415 // 3 = We have seen a new user enter within the past 4 minutes 4593 // 4 = Sim is up and both packet threads are running. Sim is
4594 // likely usable
4595 //
4596 // 5 = We have seen a new user enter within the past 4 minutes
4416 // which can be seen as positive confirmation of sim health 4597 // which can be seen as positive confirmation of sim health
4417 // 4598 //
4599
4600 flags = 0;
4601 message = String.Empty;
4602
4603 CheckHeartbeat();
4604
4605 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
4606 {
4607 // We're still starting
4608 // 0 means "in startup", it can't happen another way, since
4609 // to get here, we must be able to accept http connections
4610 return 0;
4611 }
4612
4418 int health=1; // Start at 1, means we're up 4613 int health=1; // Start at 1, means we're up
4419 4614
4420 if ((Util.EnvironmentTickCountSubtract(m_lastUpdate)) < 1000) 4615 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) < 1000)
4616 {
4421 health+=1; 4617 health+=1;
4618 flags |= 1;
4619 }
4620
4621 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 1000)
4622 {
4623 health+=1;
4624 flags |= 2;
4625 }
4626
4627 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 1000)
4628 {
4629 health+=1;
4630 flags |= 4;
4631 }
4422 else 4632 else
4633 {
4634int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
4635System.Diagnostics.Process proc = new System.Diagnostics.Process();
4636proc.EnableRaisingEvents=false;
4637proc.StartInfo.FileName = "/bin/kill";
4638proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
4639proc.Start();
4640proc.WaitForExit();
4641Thread.Sleep(1000);
4642Environment.Exit(1);
4643 }
4644
4645 if (flags != 7)
4423 return health; 4646 return health;
4424 4647
4425 // A login in the last 4 mins? We can't be doing too badly 4648 // A login in the last 4 mins? We can't be doing too badly
4426 // 4649 //
4427 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 4650 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
4428 health++; 4651 health++;
4429 else
4430 return health;
4431
4432 CheckHeartbeat();
4433 4652
4434 return health; 4653 return health;
4435 } 4654 }
@@ -4622,7 +4841,7 @@ namespace OpenSim.Region.Framework.Scenes
4622 if (m_firstHeartbeat) 4841 if (m_firstHeartbeat)
4623 return; 4842 return;
4624 4843
4625 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 2000) 4844 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 5000)
4626 StartTimer(); 4845 StartTimer();
4627 } 4846 }
4628 4847
@@ -4945,7 +5164,55 @@ namespace OpenSim.Region.Framework.Scenes
4945 mapModule.GenerateMaptile(); 5164 mapModule.GenerateMaptile();
4946 } 5165 }
4947 5166
4948 private void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e) 5167// public void CleanDroppedAttachments()
5168// {
5169// List<SceneObjectGroup> objectsToDelete =
5170// new List<SceneObjectGroup>();
5171//
5172// lock (m_cleaningAttachments)
5173// {
5174// ForEachSOG(delegate (SceneObjectGroup grp)
5175// {
5176// if (grp.RootPart.Shape.PCode == 0 && grp.RootPart.Shape.State != 0 && (!objectsToDelete.Contains(grp)))
5177// {
5178// UUID agentID = grp.OwnerID;
5179// if (agentID == UUID.Zero)
5180// {
5181// objectsToDelete.Add(grp);
5182// return;
5183// }
5184//
5185// ScenePresence sp = GetScenePresence(agentID);
5186// if (sp == null)
5187// {
5188// objectsToDelete.Add(grp);
5189// return;
5190// }
5191// }
5192// });
5193// }
5194//
5195// foreach (SceneObjectGroup grp in objectsToDelete)
5196// {
5197// m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
5198// DeleteSceneObject(grp, true);
5199// }
5200// }
5201
5202 public void ThreadAlive(int threadCode)
5203 {
5204 switch(threadCode)
5205 {
5206 case 1: // Incoming
5207 m_lastIncoming = Util.EnvironmentTickCount();
5208 break;
5209 case 2: // Incoming
5210 m_lastOutgoing = Util.EnvironmentTickCount();
5211 break;
5212 }
5213 }
5214
5215 public void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e)
4949 { 5216 {
4950 RegenerateMaptile(); 5217 RegenerateMaptile();
4951 5218
@@ -4964,6 +5231,14 @@ namespace OpenSim.Region.Framework.Scenes
4964 // child agent creation, thereby emulating the SL behavior. 5231 // child agent creation, thereby emulating the SL behavior.
4965 public bool QueryAccess(UUID agentID, Vector3 position, out string reason) 5232 public bool QueryAccess(UUID agentID, Vector3 position, out string reason)
4966 { 5233 {
5234 reason = "You are banned from the region";
5235
5236 if (Permissions.IsGod(agentID))
5237 {
5238 reason = String.Empty;
5239 return true;
5240 }
5241
4967 int num = m_sceneGraph.GetNumberOfScenePresences(); 5242 int num = m_sceneGraph.GetNumberOfScenePresences();
4968 5243
4969 if (num >= RegionInfo.RegionSettings.AgentLimit) 5244 if (num >= RegionInfo.RegionSettings.AgentLimit)
@@ -4975,6 +5250,41 @@ namespace OpenSim.Region.Framework.Scenes
4975 } 5250 }
4976 } 5251 }
4977 5252
5253 ScenePresence presence = GetScenePresence(agentID);
5254 IClientAPI client = null;
5255 AgentCircuitData aCircuit = null;
5256
5257 if (presence != null)
5258 {
5259 client = presence.ControllingClient;
5260 if (client != null)
5261 aCircuit = client.RequestClientInfo();
5262 }
5263
5264 // We may be called before there is a presence or a client.
5265 // Fake AgentCircuitData to keep IAuthorizationModule smiling
5266 if (client == null)
5267 {
5268 aCircuit = new AgentCircuitData();
5269 aCircuit.AgentID = agentID;
5270 aCircuit.firstname = String.Empty;
5271 aCircuit.lastname = String.Empty;
5272 }
5273
5274 try
5275 {
5276 if (!AuthorizeUser(aCircuit, out reason))
5277 {
5278 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5279 return false;
5280 }
5281 }
5282 catch (Exception e)
5283 {
5284 m_log.DebugFormat("[SCENE]: Exception authorizing agent: {0} "+ e.StackTrace, e.Message);
5285 return false;
5286 }
5287
4978 if (position == Vector3.Zero) // Teleport 5288 if (position == Vector3.Zero) // Teleport
4979 { 5289 {
4980 if (!RegionInfo.EstateSettings.AllowDirectTeleport) 5290 if (!RegionInfo.EstateSettings.AllowDirectTeleport)
@@ -5003,13 +5313,46 @@ namespace OpenSim.Region.Framework.Scenes
5003 } 5313 }
5004 } 5314 }
5005 } 5315 }
5316
5317 float posX = 128.0f;
5318 float posY = 128.0f;
5319
5320 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY))
5321 {
5322 // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID);
5323 return false;
5324 }
5325 }
5326 else // Walking
5327 {
5328 ILandObject land = LandChannel.GetLandObject(position.X, position.Y);
5329 if (land == null)
5330 return false;
5331
5332 bool banned = land.IsBannedFromLand(agentID);
5333 bool restricted = land.IsRestrictedFromLand(agentID);
5334
5335 if (banned || restricted)
5336 return false;
5006 } 5337 }
5007 5338
5008 reason = String.Empty; 5339 reason = String.Empty;
5009 return true; 5340 return true;
5010 } 5341 }
5011 5342
5012 /// <summary> 5343 public void StartTimerWatchdog()
5344 {
5345 m_timerWatchdog.Interval = 1000;
5346 m_timerWatchdog.Elapsed += TimerWatchdog;
5347 m_timerWatchdog.AutoReset = true;
5348 m_timerWatchdog.Start();
5349 }
5350
5351 public void TimerWatchdog(object sender, ElapsedEventArgs e)
5352 {
5353 CheckHeartbeat();
5354 }
5355
5013 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the 5356 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the
5014 /// autopilot that moves an avatar to a sit target!. 5357 /// autopilot that moves an avatar to a sit target!.
5015 /// </summary> 5358 /// </summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index 712e094..da3b4dd 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -136,6 +136,8 @@ namespace OpenSim.Region.Framework.Scenes
136 get { return m_permissions; } 136 get { return m_permissions; }
137 } 137 }
138 138
139 protected string m_datastore;
140
139 /* Used by the loadbalancer plugin on GForge */ 141 /* Used by the loadbalancer plugin on GForge */
140 protected RegionStatus m_regStatus; 142 protected RegionStatus m_regStatus;
141 public RegionStatus RegionStatus 143 public RegionStatus RegionStatus
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index 58a7b20..27833e8 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -88,7 +88,7 @@ namespace OpenSim.Region.Framework.Scenes
88 88
89 if (neighbour != null) 89 if (neighbour != null)
90 { 90 {
91 m_log.DebugFormat("[INTERGRID]: Successfully informed neighbour {0}-{1} that I'm here", x / Constants.RegionSize, y / Constants.RegionSize); 91 // m_log.DebugFormat("[INTERGRID]: Successfully informed neighbour {0}-{1} that I'm here", x / Constants.RegionSize, y / Constants.RegionSize);
92 m_scene.EventManager.TriggerOnRegionUp(neighbour); 92 m_scene.EventManager.TriggerOnRegionUp(neighbour);
93 } 93 }
94 else 94 else
@@ -102,7 +102,7 @@ namespace OpenSim.Region.Framework.Scenes
102 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName); 102 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName);
103 103
104 List<GridRegion> neighbours = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID); 104 List<GridRegion> neighbours = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID);
105 m_log.DebugFormat("[INTERGRID]: Informing {0} neighbours that this region is up", neighbours.Count); 105 //m_log.DebugFormat("[INTERGRID]: Informing {0} neighbours that this region is up", neighbours.Count);
106 foreach (GridRegion n in neighbours) 106 foreach (GridRegion n in neighbours)
107 { 107 {
108 InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync; 108 InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync;
@@ -176,10 +176,13 @@ namespace OpenSim.Region.Framework.Scenes
176 } 176 }
177 } 177 }
178 178
179 public delegate void SendCloseChildAgentDelegate(UUID agentID, ulong regionHandle);
180
179 /// <summary> 181 /// <summary>
180 /// Closes a child agent on a given region 182 /// This Closes child agents on neighboring regions
183 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
181 /// </summary> 184 /// </summary>
182 protected void SendCloseChildAgent(UUID agentID, ulong regionHandle) 185 protected void SendCloseChildAgentAsync(UUID agentID, ulong regionHandle)
183 { 186 {
184 // let's do our best, but there's not much we can do if the neighbour doesn't accept. 187 // let's do our best, but there's not much we can do if the neighbour doesn't accept.
185 188
@@ -188,31 +191,29 @@ namespace OpenSim.Region.Framework.Scenes
188 Utils.LongToUInts(regionHandle, out x, out y); 191 Utils.LongToUInts(regionHandle, out x, out y);
189 192
190 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y); 193 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);
194 m_scene.SimulationService.CloseChildAgent(destination, agentID);
195 }
191 196
192 m_log.DebugFormat( 197 private void SendCloseChildAgentCompleted(IAsyncResult iar)
193 "[INTERGRID]: Sending close agent {0} to region at {1}-{2}", 198 {
194 agentID, destination.RegionCoordX, destination.RegionCoordY); 199 SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState;
195 200 icon.EndInvoke(iar);
196 m_scene.SimulationService.CloseAgent(destination, agentID);
197 } 201 }
198 202
199 /// <summary>
200 /// Closes a child agents in a collection of regions. Does so asynchronously
201 /// so that the caller doesn't wait.
202 /// </summary>
203 /// <param name="agentID"></param>
204 /// <param name="regionslst"></param>
205 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst) 203 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst)
206 { 204 {
207 foreach (ulong handle in regionslst) 205 foreach (ulong handle in regionslst)
208 { 206 {
209 SendCloseChildAgent(agentID, handle); 207 SendCloseChildAgentDelegate d = SendCloseChildAgentAsync;
208 d.BeginInvoke(agentID, handle,
209 SendCloseChildAgentCompleted,
210 d);
210 } 211 }
211 } 212 }
212 213
213 public List<GridRegion> RequestNamedRegions(string name, int maxNumber) 214 public List<GridRegion> RequestNamedRegions(string name, int maxNumber)
214 { 215 {
215 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber); 216 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber);
216 } 217 }
217 } 218 }
218} \ No newline at end of file 219}
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 06de72f..aecca27 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -41,6 +41,12 @@ namespace OpenSim.Region.Framework.Scenes
41{ 41{
42 public delegate void PhysicsCrash(); 42 public delegate void PhysicsCrash();
43 43
44 public delegate void AttachToBackupDelegate(SceneObjectGroup sog);
45
46 public delegate void DetachFromBackupDelegate(SceneObjectGroup sog);
47
48 public delegate void ChangedBackupDelegate(SceneObjectGroup sog);
49
44 /// <summary> 50 /// <summary>
45 /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components 51 /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components
46 /// should be migrated out over time. 52 /// should be migrated out over time.
@@ -54,11 +60,15 @@ namespace OpenSim.Region.Framework.Scenes
54 protected internal event PhysicsCrash UnRecoverableError; 60 protected internal event PhysicsCrash UnRecoverableError;
55 private PhysicsCrash handlerPhysicsCrash = null; 61 private PhysicsCrash handlerPhysicsCrash = null;
56 62
63 public event AttachToBackupDelegate OnAttachToBackup;
64 public event DetachFromBackupDelegate OnDetachFromBackup;
65 public event ChangedBackupDelegate OnChangeBackup;
66
57 #endregion 67 #endregion
58 68
59 #region Fields 69 #region Fields
60 70
61 protected object m_presenceLock = new object(); 71 protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim();
62 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>(); 72 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>();
63 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>(); 73 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>();
64 74
@@ -120,13 +130,18 @@ namespace OpenSim.Region.Framework.Scenes
120 130
121 protected internal void Close() 131 protected internal void Close()
122 { 132 {
123 lock (m_presenceLock) 133 m_scenePresencesLock.EnterWriteLock();
134 try
124 { 135 {
125 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 136 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
126 List<ScenePresence> newlist = new List<ScenePresence>(); 137 List<ScenePresence> newlist = new List<ScenePresence>();
127 m_scenePresenceMap = newmap; 138 m_scenePresenceMap = newmap;
128 m_scenePresenceArray = newlist; 139 m_scenePresenceArray = newlist;
129 } 140 }
141 finally
142 {
143 m_scenePresencesLock.ExitWriteLock();
144 }
130 145
131 lock (SceneObjectGroupsByFullID) 146 lock (SceneObjectGroupsByFullID)
132 SceneObjectGroupsByFullID.Clear(); 147 SceneObjectGroupsByFullID.Clear();
@@ -265,6 +280,33 @@ namespace OpenSim.Region.Framework.Scenes
265 protected internal bool AddRestoredSceneObject( 280 protected internal bool AddRestoredSceneObject(
266 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 281 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
267 { 282 {
283 if (!m_parentScene.CombineRegions)
284 {
285 // KF: Check for out-of-region, move inside and make static.
286 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
287 sceneObject.RootPart.GroupPosition.Y,
288 sceneObject.RootPart.GroupPosition.Z);
289 if (!(((sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) && (sceneObject.RootPart.Shape.State != 0))) && (npos.X < 0.0 || npos.Y < 0.0 || npos.Z < 0.0 ||
290 npos.X > Constants.RegionSize ||
291 npos.Y > Constants.RegionSize))
292 {
293 if (npos.X < 0.0) npos.X = 1.0f;
294 if (npos.Y < 0.0) npos.Y = 1.0f;
295 if (npos.Z < 0.0) npos.Z = 0.0f;
296 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
297 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
298
299 foreach (SceneObjectPart part in sceneObject.Parts)
300 {
301 part.GroupPosition = npos;
302 }
303 sceneObject.RootPart.Velocity = Vector3.Zero;
304 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
305 sceneObject.RootPart.Acceleration = Vector3.Zero;
306 sceneObject.RootPart.Velocity = Vector3.Zero;
307 }
308 }
309
268 if (attachToBackup && (!alreadyPersisted)) 310 if (attachToBackup && (!alreadyPersisted))
269 { 311 {
270 sceneObject.ForceInventoryPersistence(); 312 sceneObject.ForceInventoryPersistence();
@@ -353,6 +395,11 @@ namespace OpenSim.Region.Framework.Scenes
353 /// </returns> 395 /// </returns>
354 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 396 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
355 { 397 {
398 if (sceneObject == null)
399 {
400 m_log.ErrorFormat("[SCENEGRAPH]: Tried to add null scene object");
401 return false;
402 }
356 if (sceneObject.UUID == UUID.Zero) 403 if (sceneObject.UUID == UUID.Zero)
357 { 404 {
358 m_log.ErrorFormat( 405 m_log.ErrorFormat(
@@ -487,6 +534,30 @@ namespace OpenSim.Region.Framework.Scenes
487 m_updateList[obj.UUID] = obj; 534 m_updateList[obj.UUID] = obj;
488 } 535 }
489 536
537 public void FireAttachToBackup(SceneObjectGroup obj)
538 {
539 if (OnAttachToBackup != null)
540 {
541 OnAttachToBackup(obj);
542 }
543 }
544
545 public void FireDetachFromBackup(SceneObjectGroup obj)
546 {
547 if (OnDetachFromBackup != null)
548 {
549 OnDetachFromBackup(obj);
550 }
551 }
552
553 public void FireChangeBackup(SceneObjectGroup obj)
554 {
555 if (OnChangeBackup != null)
556 {
557 OnChangeBackup(obj);
558 }
559 }
560
490 /// <summary> 561 /// <summary>
491 /// Process all pending updates 562 /// Process all pending updates
492 /// </summary> 563 /// </summary>
@@ -604,7 +675,8 @@ namespace OpenSim.Region.Framework.Scenes
604 675
605 Entities[presence.UUID] = presence; 676 Entities[presence.UUID] = presence;
606 677
607 lock (m_presenceLock) 678 m_scenePresencesLock.EnterWriteLock();
679 try
608 { 680 {
609 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 681 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
610 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 682 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -628,6 +700,10 @@ namespace OpenSim.Region.Framework.Scenes
628 m_scenePresenceMap = newmap; 700 m_scenePresenceMap = newmap;
629 m_scenePresenceArray = newlist; 701 m_scenePresenceArray = newlist;
630 } 702 }
703 finally
704 {
705 m_scenePresencesLock.ExitWriteLock();
706 }
631 } 707 }
632 708
633 /// <summary> 709 /// <summary>
@@ -642,7 +718,8 @@ namespace OpenSim.Region.Framework.Scenes
642 agentID); 718 agentID);
643 } 719 }
644 720
645 lock (m_presenceLock) 721 m_scenePresencesLock.EnterWriteLock();
722 try
646 { 723 {
647 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 724 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
648 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 725 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -664,6 +741,10 @@ namespace OpenSim.Region.Framework.Scenes
664 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 741 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
665 } 742 }
666 } 743 }
744 finally
745 {
746 m_scenePresencesLock.ExitWriteLock();
747 }
667 } 748 }
668 749
669 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 750 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1379,8 +1460,13 @@ namespace OpenSim.Region.Framework.Scenes
1379 { 1460 {
1380 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1461 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1381 { 1462 {
1382 if (m_parentScene.AttachmentsModule != null) 1463 // Set the new attachment point data in the object
1383 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1464 byte attachmentPoint = group.GetAttachmentPoint();
1465 group.UpdateGroupPosition(pos);
1466 group.IsAttachment = false;
1467 group.AbsolutePosition = group.RootPart.AttachedPos;
1468 group.AttachmentPoint = attachmentPoint;
1469 group.HasGroupChanged = true;
1384 } 1470 }
1385 else 1471 else
1386 { 1472 {
@@ -1652,8 +1738,11 @@ namespace OpenSim.Region.Framework.Scenes
1652 return; 1738 return;
1653 1739
1654 Monitor.Enter(m_updateLock); 1740 Monitor.Enter(m_updateLock);
1741
1655 try 1742 try
1656 { 1743 {
1744 parentGroup.areUpdatesSuspended = true;
1745
1657 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1746 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1658 1747
1659 // We do this in reverse to get the link order of the prims correct 1748 // We do this in reverse to get the link order of the prims correct
@@ -1664,9 +1753,13 @@ namespace OpenSim.Region.Framework.Scenes
1664 // Make sure no child prim is set for sale 1753 // Make sure no child prim is set for sale
1665 // So that, on delink, no prims are unwittingly 1754 // So that, on delink, no prims are unwittingly
1666 // left for sale and sold off 1755 // left for sale and sold off
1667 child.RootPart.ObjectSaleType = 0; 1756
1668 child.RootPart.SalePrice = 10; 1757 if (child != null)
1669 childGroups.Add(child); 1758 {
1759 child.RootPart.ObjectSaleType = 0;
1760 child.RootPart.SalePrice = 10;
1761 childGroups.Add(child);
1762 }
1670 } 1763 }
1671 1764
1672 foreach (SceneObjectGroup child in childGroups) 1765 foreach (SceneObjectGroup child in childGroups)
@@ -1685,12 +1778,19 @@ namespace OpenSim.Region.Framework.Scenes
1685 // occur on link to invoke this elsewhere (such as object selection) 1778 // occur on link to invoke this elsewhere (such as object selection)
1686 parentGroup.RootPart.CreateSelected = true; 1779 parentGroup.RootPart.CreateSelected = true;
1687 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1780 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1688 parentGroup.HasGroupChanged = true;
1689 parentGroup.ScheduleGroupForFullUpdate();
1690
1691 } 1781 }
1692 finally 1782 finally
1693 { 1783 {
1784 lock (SceneObjectGroupsByLocalPartID)
1785 {
1786 foreach (SceneObjectPart part in parentGroup.Parts)
1787 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1788 }
1789
1790 parentGroup.areUpdatesSuspended = false;
1791 parentGroup.HasGroupChanged = true;
1792 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1793 parentGroup.ScheduleGroupForFullUpdate();
1694 Monitor.Exit(m_updateLock); 1794 Monitor.Exit(m_updateLock);
1695 } 1795 }
1696 } 1796 }
@@ -1727,21 +1827,24 @@ namespace OpenSim.Region.Framework.Scenes
1727 1827
1728 SceneObjectGroup group = part.ParentGroup; 1828 SceneObjectGroup group = part.ParentGroup;
1729 if (!affectedGroups.Contains(group)) 1829 if (!affectedGroups.Contains(group))
1830 {
1831 group.areUpdatesSuspended = true;
1730 affectedGroups.Add(group); 1832 affectedGroups.Add(group);
1833 }
1731 } 1834 }
1732 } 1835 }
1733 } 1836 }
1734 1837
1735 foreach (SceneObjectPart child in childParts) 1838 if (childParts.Count > 0)
1736 { 1839 {
1737 // Unlink all child parts from their groups 1840 foreach (SceneObjectPart child in childParts)
1738 // 1841 {
1739 child.ParentGroup.DelinkFromGroup(child, true); 1842 // Unlink all child parts from their groups
1740 1843 //
1741 // These are not in affected groups and will not be 1844 child.ParentGroup.DelinkFromGroup(child, true);
1742 // handled further. Do the honors here. 1845 child.ParentGroup.HasGroupChanged = true;
1743 child.ParentGroup.HasGroupChanged = true; 1846 child.ParentGroup.ScheduleGroupForFullUpdate();
1744 child.ParentGroup.ScheduleGroupForFullUpdate(); 1847 }
1745 } 1848 }
1746 1849
1747 foreach (SceneObjectPart root in rootParts) 1850 foreach (SceneObjectPart root in rootParts)
@@ -1751,56 +1854,68 @@ namespace OpenSim.Region.Framework.Scenes
1751 // However, editing linked parts and unlinking may be different 1854 // However, editing linked parts and unlinking may be different
1752 // 1855 //
1753 SceneObjectGroup group = root.ParentGroup; 1856 SceneObjectGroup group = root.ParentGroup;
1857 group.areUpdatesSuspended = true;
1754 1858
1755 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1859 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1756 int numChildren = newSet.Count; 1860 int numChildren = newSet.Count;
1757 1861
1862 if (numChildren == 1)
1863 break;
1864
1758 // If there are prims left in a link set, but the root is 1865 // If there are prims left in a link set, but the root is
1759 // slated for unlink, we need to do this 1866 // slated for unlink, we need to do this
1867 // Unlink the remaining set
1760 // 1868 //
1761 if (numChildren != 1) 1869 bool sendEventsToRemainder = true;
1762 { 1870 if (numChildren > 1)
1763 // Unlink the remaining set 1871 sendEventsToRemainder = false;
1764 //
1765 bool sendEventsToRemainder = true;
1766 if (numChildren > 1)
1767 sendEventsToRemainder = false;
1768 1872
1769 foreach (SceneObjectPart p in newSet) 1873 foreach (SceneObjectPart p in newSet)
1874 {
1875 if (p != group.RootPart)
1770 { 1876 {
1771 if (p != group.RootPart) 1877 group.DelinkFromGroup(p, sendEventsToRemainder);
1772 group.DelinkFromGroup(p, sendEventsToRemainder); 1878 if (numChildren > 2)
1879 {
1880 p.ParentGroup.areUpdatesSuspended = true;
1881 }
1882 else
1883 {
1884 p.ParentGroup.HasGroupChanged = true;
1885 p.ParentGroup.ScheduleGroupForFullUpdate();
1886 }
1773 } 1887 }
1888 }
1889
1890 // If there is more than one prim remaining, we
1891 // need to re-link
1892 //
1893 if (numChildren > 2)
1894 {
1895 // Remove old root
1896 //
1897 if (newSet.Contains(root))
1898 newSet.Remove(root);
1774 1899
1775 // If there is more than one prim remaining, we 1900 // Preserve link ordering
1776 // need to re-link
1777 // 1901 //
1778 if (numChildren > 2) 1902 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1779 { 1903 {
1780 // Remove old root 1904 return a.LinkNum.CompareTo(b.LinkNum);
1781 // 1905 });
1782 if (newSet.Contains(root))
1783 newSet.Remove(root);
1784
1785 // Preserve link ordering
1786 //
1787 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1788 {
1789 return a.LinkNum.CompareTo(b.LinkNum);
1790 });
1791 1906
1792 // Determine new root 1907 // Determine new root
1793 // 1908 //
1794 SceneObjectPart newRoot = newSet[0]; 1909 SceneObjectPart newRoot = newSet[0];
1795 newSet.RemoveAt(0); 1910 newSet.RemoveAt(0);
1796 1911
1797 foreach (SceneObjectPart newChild in newSet) 1912 foreach (SceneObjectPart newChild in newSet)
1798 newChild.ClearUpdateSchedule(); 1913 newChild.ClearUpdateSchedule();
1799 1914
1800 LinkObjects(newRoot, newSet); 1915 newRoot.ParentGroup.areUpdatesSuspended = true;
1801 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1916 LinkObjects(newRoot, newSet);
1802 affectedGroups.Add(newRoot.ParentGroup); 1917 if (!affectedGroups.Contains(newRoot.ParentGroup))
1803 } 1918 affectedGroups.Add(newRoot.ParentGroup);
1804 } 1919 }
1805 } 1920 }
1806 1921
@@ -1808,8 +1923,14 @@ namespace OpenSim.Region.Framework.Scenes
1808 // 1923 //
1809 foreach (SceneObjectGroup g in affectedGroups) 1924 foreach (SceneObjectGroup g in affectedGroups)
1810 { 1925 {
1926 // Child prims that have been unlinked and deleted will
1927 // return unless the root is deleted. This will remove them
1928 // from the database. They will be rewritten immediately,
1929 // minus the rows for the unlinked child prims.
1930 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1811 g.TriggerScriptChangedEvent(Changed.LINK); 1931 g.TriggerScriptChangedEvent(Changed.LINK);
1812 g.HasGroupChanged = true; // Persist 1932 g.HasGroupChanged = true; // Persist
1933 g.areUpdatesSuspended = false;
1813 g.ScheduleGroupForFullUpdate(); 1934 g.ScheduleGroupForFullUpdate();
1814 } 1935 }
1815 } 1936 }
@@ -1927,9 +2048,6 @@ namespace OpenSim.Region.Framework.Scenes
1927 child.ApplyNextOwnerPermissions(); 2048 child.ApplyNextOwnerPermissions();
1928 } 2049 }
1929 } 2050 }
1930
1931 copy.RootPart.ObjectSaleType = 0;
1932 copy.RootPart.SalePrice = 10;
1933 } 2051 }
1934 2052
1935 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2053 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs
index d73a959..e4eaf3a 100644
--- a/OpenSim/Region/Framework/Scenes/SceneManager.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs
@@ -356,7 +356,7 @@ namespace OpenSim.Region.Framework.Scenes
356 356
357 public bool TrySetCurrentScene(UUID regionID) 357 public bool TrySetCurrentScene(UUID regionID)
358 { 358 {
359 m_log.Debug("Searching for Region: '" + regionID + "'"); 359// m_log.Debug("Searching for Region: '" + regionID + "'");
360 360
361 lock (m_localScenes) 361 lock (m_localScenes)
362 { 362 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index f173c95..b56d3fc 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -69,10 +69,6 @@ namespace OpenSim.Region.Framework.Scenes
69 /// <summary> 69 /// <summary>
70 /// Stop the scripts contained in all the prims in this group 70 /// Stop the scripts contained in all the prims in this group
71 /// </summary> 71 /// </summary>
72 /// <param name="sceneObjectBeingDeleted">
73 /// Should be true if these scripts are being removed because the scene
74 /// object is being deleted. This will prevent spurious updates to the client.
75 /// </param>
76 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 72 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
77 { 73 {
78 SceneObjectPart[] parts = m_parts.GetArray(); 74 SceneObjectPart[] parts = m_parts.GetArray();
@@ -227,6 +223,11 @@ namespace OpenSim.Region.Framework.Scenes
227 223
228 public uint GetEffectivePermissions() 224 public uint GetEffectivePermissions()
229 { 225 {
226 return GetEffectivePermissions(false);
227 }
228
229 public uint GetEffectivePermissions(bool useBase)
230 {
230 uint perms=(uint)(PermissionMask.Modify | 231 uint perms=(uint)(PermissionMask.Modify |
231 PermissionMask.Copy | 232 PermissionMask.Copy |
232 PermissionMask.Move | 233 PermissionMask.Move |
@@ -238,7 +239,10 @@ namespace OpenSim.Region.Framework.Scenes
238 for (int i = 0; i < parts.Length; i++) 239 for (int i = 0; i < parts.Length; i++)
239 { 240 {
240 SceneObjectPart part = parts[i]; 241 SceneObjectPart part = parts[i];
241 ownerMask &= part.OwnerMask; 242 if (useBase)
243 ownerMask &= part.BaseMask;
244 else
245 ownerMask &= part.OwnerMask;
242 perms &= part.Inventory.MaskEffectivePermissions(); 246 perms &= part.Inventory.MaskEffectivePermissions();
243 } 247 }
244 248
@@ -378,6 +382,9 @@ namespace OpenSim.Region.Framework.Scenes
378 382
379 public void ResumeScripts() 383 public void ResumeScripts()
380 { 384 {
385 if (m_scene.RegionInfo.RegionSettings.DisableScripts)
386 return;
387
381 SceneObjectPart[] parts = m_parts.GetArray(); 388 SceneObjectPart[] parts = m_parts.GetArray();
382 for (int i = 0; i < parts.Length; i++) 389 for (int i = 0; i < parts.Length; i++)
383 parts[i].Inventory.ResumeScripts(); 390 parts[i].Inventory.ResumeScripts();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index e7f2fdb..c31cbab 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -24,11 +24,12 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Drawing; 30using System.Drawing;
31using System.IO; 31using System.IO;
32using System.Diagnostics;
32using System.Linq; 33using System.Linq;
33using System.Threading; 34using System.Threading;
34using System.Xml; 35using System.Xml;
@@ -105,8 +106,29 @@ namespace OpenSim.Region.Framework.Scenes
105 /// since the group's last persistent backup 106 /// since the group's last persistent backup
106 /// </summary> 107 /// </summary>
107 private bool m_hasGroupChanged = false; 108 private bool m_hasGroupChanged = false;
108 private long timeFirstChanged; 109 private long timeFirstChanged = 0;
109 private long timeLastChanged; 110 private long timeLastChanged = 0;
111 private long m_maxPersistTime = 0;
112 private long m_minPersistTime = 0;
113 private Random m_rand;
114 private bool m_suspendUpdates;
115 private List<ScenePresence> m_linkedAvatars = new List<ScenePresence>();
116
117 public bool areUpdatesSuspended
118 {
119 get
120 {
121 return m_suspendUpdates;
122 }
123 set
124 {
125 m_suspendUpdates = value;
126 if (!value)
127 {
128 QueueForUpdateCheck();
129 }
130 }
131 }
110 132
111 public bool HasGroupChanged 133 public bool HasGroupChanged
112 { 134 {
@@ -114,9 +136,39 @@ namespace OpenSim.Region.Framework.Scenes
114 { 136 {
115 if (value) 137 if (value)
116 { 138 {
139 if (m_isBackedUp)
140 {
141 m_scene.SceneGraph.FireChangeBackup(this);
142 }
117 timeLastChanged = DateTime.Now.Ticks; 143 timeLastChanged = DateTime.Now.Ticks;
118 if (!m_hasGroupChanged) 144 if (!m_hasGroupChanged)
119 timeFirstChanged = DateTime.Now.Ticks; 145 timeFirstChanged = DateTime.Now.Ticks;
146 if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null)
147 {
148 if (m_rand == null)
149 {
150 byte[] val = new byte[16];
151 m_rootPart.UUID.ToBytes(val, 0);
152 m_rand = new Random(BitConverter.ToInt32(val, 0));
153 }
154
155 if (m_scene.GetRootAgentCount() == 0)
156 {
157 //If the region is empty, this change has been made by an automated process
158 //and thus we delay the persist time by a random amount between 1.5 and 2.5.
159
160 float factor = 1.5f + (float)(m_rand.NextDouble());
161 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor);
162 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor);
163 }
164 else
165 {
166 //If the region is not empty, we want to obey the minimum and maximum persist times
167 //but add a random factor so we stagger the object persistance a little
168 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5
169 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0
170 }
171 }
120 } 172 }
121 m_hasGroupChanged = value; 173 m_hasGroupChanged = value;
122 174
@@ -131,7 +183,7 @@ namespace OpenSim.Region.Framework.Scenes
131 /// Has the group changed due to an unlink operation? We record this in order to optimize deletion, since 183 /// Has the group changed due to an unlink operation? We record this in order to optimize deletion, since
132 /// an unlinked group currently has to be persisted to the database before we can perform an unlink operation. 184 /// an unlinked group currently has to be persisted to the database before we can perform an unlink operation.
133 /// </summary> 185 /// </summary>
134 public bool HasGroupChangedDueToDelink { get; private set; } 186 public bool HasGroupChangedDueToDelink { get; set; }
135 187
136 private bool isTimeToPersist() 188 private bool isTimeToPersist()
137 { 189 {
@@ -141,8 +193,19 @@ namespace OpenSim.Region.Framework.Scenes
141 return false; 193 return false;
142 if (m_scene.ShuttingDown) 194 if (m_scene.ShuttingDown)
143 return true; 195 return true;
196
197 if (m_minPersistTime == 0 || m_maxPersistTime == 0)
198 {
199 m_maxPersistTime = m_scene.m_persistAfter;
200 m_minPersistTime = m_scene.m_dontPersistBefore;
201 }
202
144 long currentTime = DateTime.Now.Ticks; 203 long currentTime = DateTime.Now.Ticks;
145 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) 204
205 if (timeLastChanged == 0) timeLastChanged = currentTime;
206 if (timeFirstChanged == 0) timeFirstChanged = currentTime;
207
208 if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime)
146 return true; 209 return true;
147 return false; 210 return false;
148 } 211 }
@@ -247,10 +310,10 @@ namespace OpenSim.Region.Framework.Scenes
247 310
248 private bool m_scriptListens_atTarget; 311 private bool m_scriptListens_atTarget;
249 private bool m_scriptListens_notAtTarget; 312 private bool m_scriptListens_notAtTarget;
250
251 private bool m_scriptListens_atRotTarget; 313 private bool m_scriptListens_atRotTarget;
252 private bool m_scriptListens_notAtRotTarget; 314 private bool m_scriptListens_notAtRotTarget;
253 315
316 public bool m_dupeInProgress = false;
254 internal Dictionary<UUID, string> m_savedScriptState; 317 internal Dictionary<UUID, string> m_savedScriptState;
255 318
256 #region Properties 319 #region Properties
@@ -287,6 +350,16 @@ namespace OpenSim.Region.Framework.Scenes
287 get { return m_parts.Count; } 350 get { return m_parts.Count; }
288 } 351 }
289 352
353// protected Quaternion m_rotation = Quaternion.Identity;
354//
355// public virtual Quaternion Rotation
356// {
357// get { return m_rotation; }
358// set {
359// m_rotation = value;
360// }
361// }
362
290 public Quaternion GroupRotation 363 public Quaternion GroupRotation
291 { 364 {
292 get { return m_rootPart.RotationOffset; } 365 get { return m_rootPart.RotationOffset; }
@@ -395,7 +468,11 @@ namespace OpenSim.Region.Framework.Scenes
395 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 468 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
396 } 469 }
397 } 470 }
398 471
472 foreach (SceneObjectPart part in m_parts.GetArray())
473 {
474 part.IgnoreUndoUpdate = true;
475 }
399 if (RootPart.GetStatusSandbox()) 476 if (RootPart.GetStatusSandbox())
400 { 477 {
401 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 478 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -409,10 +486,30 @@ namespace OpenSim.Region.Framework.Scenes
409 return; 486 return;
410 } 487 }
411 } 488 }
412
413 SceneObjectPart[] parts = m_parts.GetArray(); 489 SceneObjectPart[] parts = m_parts.GetArray();
414 for (int i = 0; i < parts.Length; i++) 490 bool triggerScriptEvent = m_rootPart.GroupPosition != val;
415 parts[i].GroupPosition = val; 491 if (m_dupeInProgress)
492 triggerScriptEvent = false;
493 foreach (SceneObjectPart part in parts)
494 {
495 part.GroupPosition = val;
496 if (triggerScriptEvent)
497 part.TriggerScriptChangedEvent(Changed.POSITION);
498 }
499 if (!m_dupeInProgress)
500 {
501 foreach (ScenePresence av in m_linkedAvatars)
502 {
503 SceneObjectPart p = m_scene.GetSceneObjectPart(av.ParentID);
504 if (m_parts.TryGetValue(p.UUID, out p))
505 {
506 Vector3 offset = p.GetWorldPosition() - av.ParentPosition;
507 av.AbsolutePosition += offset;
508 av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
509 av.SendAvatarDataToAllAgents();
510 }
511 }
512 }
416 513
417 //if (m_rootPart.PhysActor != null) 514 //if (m_rootPart.PhysActor != null)
418 //{ 515 //{
@@ -577,6 +674,7 @@ namespace OpenSim.Region.Framework.Scenes
577 /// </summary> 674 /// </summary>
578 public SceneObjectGroup() 675 public SceneObjectGroup()
579 { 676 {
677
580 } 678 }
581 679
582 /// <summary> 680 /// <summary>
@@ -593,7 +691,7 @@ namespace OpenSim.Region.Framework.Scenes
593 /// Constructor. This object is added to the scene later via AttachToScene() 691 /// Constructor. This object is added to the scene later via AttachToScene()
594 /// </summary> 692 /// </summary>
595 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 693 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
596 { 694 {
597 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 695 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
598 } 696 }
599 697
@@ -641,6 +739,9 @@ namespace OpenSim.Region.Framework.Scenes
641 /// </summary> 739 /// </summary>
642 public virtual void AttachToBackup() 740 public virtual void AttachToBackup()
643 { 741 {
742 if (IsAttachment) return;
743 m_scene.SceneGraph.FireAttachToBackup(this);
744
644 if (InSceneBackup) 745 if (InSceneBackup)
645 { 746 {
646 //m_log.DebugFormat( 747 //m_log.DebugFormat(
@@ -683,6 +784,9 @@ namespace OpenSim.Region.Framework.Scenes
683 784
684 ApplyPhysics(); 785 ApplyPhysics();
685 786
787 if (RootPart.PhysActor != null)
788 RootPart.Buoyancy = RootPart.Buoyancy;
789
686 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 790 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
687 // for the same object with very different properties. The caller must schedule the update. 791 // for the same object with very different properties. The caller must schedule the update.
688 //ScheduleGroupForFullUpdate(); 792 //ScheduleGroupForFullUpdate();
@@ -698,6 +802,10 @@ namespace OpenSim.Region.Framework.Scenes
698 EntityIntersection result = new EntityIntersection(); 802 EntityIntersection result = new EntityIntersection();
699 803
700 SceneObjectPart[] parts = m_parts.GetArray(); 804 SceneObjectPart[] parts = m_parts.GetArray();
805
806 // Find closest hit here
807 float idist = float.MaxValue;
808
701 for (int i = 0; i < parts.Length; i++) 809 for (int i = 0; i < parts.Length; i++)
702 { 810 {
703 SceneObjectPart part = parts[i]; 811 SceneObjectPart part = parts[i];
@@ -712,11 +820,6 @@ namespace OpenSim.Region.Framework.Scenes
712 820
713 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters); 821 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters);
714 822
715 // This may need to be updated to the maximum draw distance possible..
716 // We might (and probably will) be checking for prim creation from other sims
717 // when the camera crosses the border.
718 float idist = Constants.RegionSize;
719
720 if (inter.HitTF) 823 if (inter.HitTF)
721 { 824 {
722 // We need to find the closest prim to return to the testcaller along the ray 825 // We need to find the closest prim to return to the testcaller along the ray
@@ -727,10 +830,11 @@ namespace OpenSim.Region.Framework.Scenes
727 result.obj = part; 830 result.obj = part;
728 result.normal = inter.normal; 831 result.normal = inter.normal;
729 result.distance = inter.distance; 832 result.distance = inter.distance;
833
834 idist = inter.distance;
730 } 835 }
731 } 836 }
732 } 837 }
733
734 return result; 838 return result;
735 } 839 }
736 840
@@ -750,17 +854,19 @@ namespace OpenSim.Region.Framework.Scenes
750 minZ = 8192f; 854 minZ = 8192f;
751 855
752 SceneObjectPart[] parts = m_parts.GetArray(); 856 SceneObjectPart[] parts = m_parts.GetArray();
753 for (int i = 0; i < parts.Length; i++) 857 foreach (SceneObjectPart part in parts)
754 { 858 {
755 SceneObjectPart part = parts[i];
756
757 Vector3 worldPos = part.GetWorldPosition(); 859 Vector3 worldPos = part.GetWorldPosition();
758 Vector3 offset = worldPos - AbsolutePosition; 860 Vector3 offset = worldPos - AbsolutePosition;
759 Quaternion worldRot; 861 Quaternion worldRot;
760 if (part.ParentID == 0) 862 if (part.ParentID == 0)
863 {
761 worldRot = part.RotationOffset; 864 worldRot = part.RotationOffset;
865 }
762 else 866 else
867 {
763 worldRot = part.GetWorldRotation(); 868 worldRot = part.GetWorldRotation();
869 }
764 870
765 Vector3 frontTopLeft; 871 Vector3 frontTopLeft;
766 Vector3 frontTopRight; 872 Vector3 frontTopRight;
@@ -772,6 +878,8 @@ namespace OpenSim.Region.Framework.Scenes
772 Vector3 backBottomLeft; 878 Vector3 backBottomLeft;
773 Vector3 backBottomRight; 879 Vector3 backBottomRight;
774 880
881 // Vector3[] corners = new Vector3[8];
882
775 Vector3 orig = Vector3.Zero; 883 Vector3 orig = Vector3.Zero;
776 884
777 frontTopLeft.X = orig.X - (part.Scale.X / 2); 885 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -806,6 +914,38 @@ namespace OpenSim.Region.Framework.Scenes
806 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 914 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
807 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 915 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
808 916
917
918
919 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
920 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
921 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
922 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
923 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
924 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
925 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
926 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
927
928 //for (int i = 0; i < 8; i++)
929 //{
930 // corners[i] = corners[i] * worldRot;
931 // corners[i] += offset;
932
933 // if (corners[i].X > maxX)
934 // maxX = corners[i].X;
935 // if (corners[i].X < minX)
936 // minX = corners[i].X;
937
938 // if (corners[i].Y > maxY)
939 // maxY = corners[i].Y;
940 // if (corners[i].Y < minY)
941 // minY = corners[i].Y;
942
943 // if (corners[i].Z > maxZ)
944 // maxZ = corners[i].Y;
945 // if (corners[i].Z < minZ)
946 // minZ = corners[i].Z;
947 //}
948
809 frontTopLeft = frontTopLeft * worldRot; 949 frontTopLeft = frontTopLeft * worldRot;
810 frontTopRight = frontTopRight * worldRot; 950 frontTopRight = frontTopRight * worldRot;
811 frontBottomLeft = frontBottomLeft * worldRot; 951 frontBottomLeft = frontBottomLeft * worldRot;
@@ -827,6 +967,15 @@ namespace OpenSim.Region.Framework.Scenes
827 backTopLeft += offset; 967 backTopLeft += offset;
828 backTopRight += offset; 968 backTopRight += offset;
829 969
970 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
971 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
972 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
973 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
974 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
975 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
976 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
977 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
978
830 if (frontTopRight.X > maxX) 979 if (frontTopRight.X > maxX)
831 maxX = frontTopRight.X; 980 maxX = frontTopRight.X;
832 if (frontTopLeft.X > maxX) 981 if (frontTopLeft.X > maxX)
@@ -972,15 +1121,20 @@ namespace OpenSim.Region.Framework.Scenes
972 1121
973 public void SaveScriptedState(XmlTextWriter writer) 1122 public void SaveScriptedState(XmlTextWriter writer)
974 { 1123 {
1124 SaveScriptedState(writer, false);
1125 }
1126
1127 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1128 {
975 XmlDocument doc = new XmlDocument(); 1129 XmlDocument doc = new XmlDocument();
976 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1130 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
977 1131
978 SceneObjectPart[] parts = m_parts.GetArray(); 1132 SceneObjectPart[] parts = m_parts.GetArray();
979 for (int i = 0; i < parts.Length; i++) 1133 for (int i = 0; i < parts.Length; i++)
980 { 1134 {
981 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 1135 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
982 foreach (KeyValuePair<UUID, string> kvp in pstates) 1136 foreach (KeyValuePair<UUID, string> kvp in pstates)
983 states.Add(kvp.Key, kvp.Value); 1137 states[kvp.Key] = kvp.Value;
984 } 1138 }
985 1139
986 if (states.Count > 0) 1140 if (states.Count > 0)
@@ -1000,6 +1154,168 @@ namespace OpenSim.Region.Framework.Scenes
1000 } 1154 }
1001 1155
1002 /// <summary> 1156 /// <summary>
1157 /// Add the avatar to this linkset (avatar is sat).
1158 /// </summary>
1159 /// <param name="agentID"></param>
1160 public void AddAvatar(UUID agentID)
1161 {
1162 ScenePresence presence;
1163 if (m_scene.TryGetScenePresence(agentID, out presence))
1164 {
1165 if (!m_linkedAvatars.Contains(presence))
1166 {
1167 m_linkedAvatars.Add(presence);
1168 }
1169 }
1170 }
1171
1172 /// <summary>
1173 /// Delete the avatar from this linkset (avatar is unsat).
1174 /// </summary>
1175 /// <param name="agentID"></param>
1176 public void DeleteAvatar(UUID agentID)
1177 {
1178 ScenePresence presence;
1179 if (m_scene.TryGetScenePresence(agentID, out presence))
1180 {
1181 if (m_linkedAvatars.Contains(presence))
1182 {
1183 m_linkedAvatars.Remove(presence);
1184 }
1185 }
1186 }
1187
1188 /// <summary>
1189 /// Returns the list of linked presences (avatars sat on this group)
1190 /// </summary>
1191 /// <param name="agentID"></param>
1192 public List<ScenePresence> GetLinkedAvatars()
1193 {
1194 return m_linkedAvatars;
1195 }
1196
1197 /// <summary>
1198 /// Attach this scene object to the given avatar.
1199 /// </summary>
1200 /// <param name="agentID"></param>
1201 /// <param name="attachmentpoint"></param>
1202 /// <param name="AttachOffset"></param>
1203 private void AttachToAgent(
1204 ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
1205 {
1206 if (avatar != null)
1207 {
1208 // don't attach attachments to child agents
1209 if (avatar.IsChildAgent) return;
1210
1211 // Remove from database and parcel prim count
1212 m_scene.DeleteFromStorage(so.UUID);
1213 m_scene.EventManager.TriggerParcelPrimCountTainted();
1214
1215 so.AttachedAvatar = avatar.UUID;
1216
1217 if (so.RootPart.PhysActor != null)
1218 {
1219 m_scene.PhysicsScene.RemovePrim(so.RootPart.PhysActor);
1220 so.RootPart.PhysActor = null;
1221 }
1222
1223 so.AbsolutePosition = attachOffset;
1224 so.RootPart.AttachedPos = attachOffset;
1225 so.IsAttachment = true;
1226 so.RootPart.SetParentLocalId(avatar.LocalId);
1227 so.AttachmentPoint = attachmentpoint;
1228
1229 avatar.AddAttachment(this);
1230
1231 if (!silent)
1232 {
1233 // Killing it here will cause the client to deselect it
1234 // It then reappears on the avatar, deselected
1235 // through the full update below
1236 //
1237 if (IsSelected)
1238 {
1239 m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
1240 }
1241
1242 IsSelected = false; // fudge....
1243 ScheduleGroupForFullUpdate();
1244 }
1245 }
1246 else
1247 {
1248 m_log.WarnFormat(
1249 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1250 UUID, avatar.ControllingClient.AgentId, Scene.RegionInfo.RegionName);
1251 }
1252 }
1253
1254 public byte GetAttachmentPoint()
1255 {
1256 return m_rootPart.Shape.State;
1257 }
1258
1259 public void DetachToGround()
1260 {
1261 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1262 if (avatar == null)
1263 return;
1264
1265 avatar.RemoveAttachment(this);
1266
1267 Vector3 detachedpos = new Vector3(127f,127f,127f);
1268 if (avatar == null)
1269 return;
1270
1271 detachedpos = avatar.AbsolutePosition;
1272 RootPart.FromItemID = UUID.Zero;
1273
1274 AbsolutePosition = detachedpos;
1275 AttachedAvatar = UUID.Zero;
1276
1277 //SceneObjectPart[] parts = m_parts.GetArray();
1278 //for (int i = 0; i < parts.Length; i++)
1279 // parts[i].AttachedAvatar = UUID.Zero;
1280
1281 m_rootPart.SetParentLocalId(0);
1282 AttachmentPoint = (byte)0;
1283 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive);
1284 HasGroupChanged = true;
1285 RootPart.Rezzed = DateTime.Now;
1286 RootPart.RemFlag(PrimFlags.TemporaryOnRez);
1287 AttachToBackup();
1288 m_scene.EventManager.TriggerParcelPrimCountTainted();
1289 m_rootPart.ScheduleFullUpdate();
1290 m_rootPart.ClearUndoState();
1291 }
1292
1293 public void DetachToInventoryPrep()
1294 {
1295 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1296 //Vector3 detachedpos = new Vector3(127f, 127f, 127f);
1297 if (avatar != null)
1298 {
1299 //detachedpos = avatar.AbsolutePosition;
1300 avatar.RemoveAttachment(this);
1301 }
1302
1303 AttachedAvatar = UUID.Zero;
1304
1305 /*SceneObjectPart[] parts = m_parts.GetArray();
1306 for (int i = 0; i < parts.Length; i++)
1307 parts[i].AttachedAvatar = UUID.Zero;*/
1308
1309 m_rootPart.SetParentLocalId(0);
1310 //m_rootPart.SetAttachmentPoint((byte)0);
1311 IsAttachment = false;
1312 AbsolutePosition = m_rootPart.AttachedPos;
1313 //m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim);
1314 //AttachToBackup();
1315 //m_rootPart.ScheduleFullUpdate();
1316 }
1317
1318 /// <summary>
1003 /// 1319 ///
1004 /// </summary> 1320 /// </summary>
1005 /// <param name="part"></param> 1321 /// <param name="part"></param>
@@ -1049,7 +1365,10 @@ namespace OpenSim.Region.Framework.Scenes
1049 public void AddPart(SceneObjectPart part) 1365 public void AddPart(SceneObjectPart part)
1050 { 1366 {
1051 part.SetParent(this); 1367 part.SetParent(this);
1052 part.LinkNum = m_parts.Add(part.UUID, part); 1368 m_parts.Add(part.UUID, part);
1369
1370 part.LinkNum = m_parts.Count;
1371
1053 if (part.LinkNum == 2) 1372 if (part.LinkNum == 2)
1054 RootPart.LinkNum = 1; 1373 RootPart.LinkNum = 1;
1055 } 1374 }
@@ -1157,6 +1476,11 @@ namespace OpenSim.Region.Framework.Scenes
1157 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1476 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1158 public void DeleteGroupFromScene(bool silent) 1477 public void DeleteGroupFromScene(bool silent)
1159 { 1478 {
1479 // We need to keep track of this state in case this group is still queued for backup.
1480 IsDeleted = true;
1481
1482 DetachFromBackup();
1483
1160 SceneObjectPart[] parts = m_parts.GetArray(); 1484 SceneObjectPart[] parts = m_parts.GetArray();
1161 for (int i = 0; i < parts.Length; i++) 1485 for (int i = 0; i < parts.Length; i++)
1162 { 1486 {
@@ -1179,6 +1503,8 @@ namespace OpenSim.Region.Framework.Scenes
1179 } 1503 }
1180 }); 1504 });
1181 } 1505 }
1506
1507
1182 } 1508 }
1183 1509
1184 public void AddScriptLPS(int count) 1510 public void AddScriptLPS(int count)
@@ -1274,7 +1600,12 @@ namespace OpenSim.Region.Framework.Scenes
1274 1600
1275 public void SetOwnerId(UUID userId) 1601 public void SetOwnerId(UUID userId)
1276 { 1602 {
1277 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1603 ForEachPart(delegate(SceneObjectPart part)
1604 {
1605
1606 part.OwnerID = userId;
1607
1608 });
1278 } 1609 }
1279 1610
1280 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1611 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1306,11 +1637,17 @@ namespace OpenSim.Region.Framework.Scenes
1306 return; 1637 return;
1307 } 1638 }
1308 1639
1640 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1641 return;
1642
1309 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 1643 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1310 // any exception propogate upwards. 1644 // any exception propogate upwards.
1311 try 1645 try
1312 { 1646 {
1313 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 1647 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1648 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
1649 m_scene.LoadingPrims) // Land may not be valid yet
1650
1314 { 1651 {
1315 ILandObject parcel = m_scene.LandChannel.GetLandObject( 1652 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1316 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 1653 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1337,6 +1674,7 @@ namespace OpenSim.Region.Framework.Scenes
1337 } 1674 }
1338 } 1675 }
1339 } 1676 }
1677
1340 } 1678 }
1341 1679
1342 if (m_scene.UseBackup && HasGroupChanged) 1680 if (m_scene.UseBackup && HasGroupChanged)
@@ -1344,6 +1682,20 @@ namespace OpenSim.Region.Framework.Scenes
1344 // don't backup while it's selected or you're asking for changes mid stream. 1682 // don't backup while it's selected or you're asking for changes mid stream.
1345 if (isTimeToPersist() || forcedBackup) 1683 if (isTimeToPersist() || forcedBackup)
1346 { 1684 {
1685 if (m_rootPart.PhysActor != null &&
1686 (!m_rootPart.PhysActor.IsPhysical))
1687 {
1688 // Possible ghost prim
1689 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
1690 {
1691 foreach (SceneObjectPart part in m_parts.GetArray())
1692 {
1693 // Re-set physics actor positions and
1694 // orientations
1695 part.GroupPosition = m_rootPart.GroupPosition;
1696 }
1697 }
1698 }
1347// m_log.DebugFormat( 1699// m_log.DebugFormat(
1348// "[SCENE]: Storing {0}, {1} in {2}", 1700// "[SCENE]: Storing {0}, {1} in {2}",
1349// Name, UUID, m_scene.RegionInfo.RegionName); 1701// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1427,7 +1779,7 @@ namespace OpenSim.Region.Framework.Scenes
1427 // This is only necessary when userExposed is false! 1779 // This is only necessary when userExposed is false!
1428 1780
1429 bool previousAttachmentStatus = dupe.IsAttachment; 1781 bool previousAttachmentStatus = dupe.IsAttachment;
1430 1782
1431 if (!userExposed) 1783 if (!userExposed)
1432 dupe.IsAttachment = true; 1784 dupe.IsAttachment = true;
1433 1785
@@ -1445,11 +1797,11 @@ namespace OpenSim.Region.Framework.Scenes
1445 dupe.m_rootPart.TrimPermissions(); 1797 dupe.m_rootPart.TrimPermissions();
1446 1798
1447 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 1799 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1448 1800
1449 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1801 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1450 { 1802 {
1451 return p1.LinkNum.CompareTo(p2.LinkNum); 1803 return p1.LinkNum.CompareTo(p2.LinkNum);
1452 } 1804 }
1453 ); 1805 );
1454 1806
1455 foreach (SceneObjectPart part in partList) 1807 foreach (SceneObjectPart part in partList)
@@ -1469,7 +1821,7 @@ namespace OpenSim.Region.Framework.Scenes
1469 if (part.PhysActor != null && userExposed) 1821 if (part.PhysActor != null && userExposed)
1470 { 1822 {
1471 PrimitiveBaseShape pbs = newPart.Shape; 1823 PrimitiveBaseShape pbs = newPart.Shape;
1472 1824
1473 newPart.PhysActor 1825 newPart.PhysActor
1474 = m_scene.PhysicsScene.AddPrimShape( 1826 = m_scene.PhysicsScene.AddPrimShape(
1475 string.Format("{0}/{1}", newPart.Name, newPart.UUID), 1827 string.Format("{0}/{1}", newPart.Name, newPart.UUID),
@@ -1479,11 +1831,11 @@ namespace OpenSim.Region.Framework.Scenes
1479 newPart.RotationOffset, 1831 newPart.RotationOffset,
1480 part.PhysActor.IsPhysical, 1832 part.PhysActor.IsPhysical,
1481 newPart.LocalId); 1833 newPart.LocalId);
1482 1834
1483 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true); 1835 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1484 } 1836 }
1485 } 1837 }
1486 1838
1487 if (userExposed) 1839 if (userExposed)
1488 { 1840 {
1489 dupe.UpdateParentIDs(); 1841 dupe.UpdateParentIDs();
@@ -1598,6 +1950,7 @@ namespace OpenSim.Region.Framework.Scenes
1598 return Vector3.Zero; 1950 return Vector3.Zero;
1599 } 1951 }
1600 1952
1953 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object
1601 public void moveToTarget(Vector3 target, float tau) 1954 public void moveToTarget(Vector3 target, float tau)
1602 { 1955 {
1603 if (IsAttachment) 1956 if (IsAttachment)
@@ -1625,6 +1978,46 @@ namespace OpenSim.Region.Framework.Scenes
1625 RootPart.PhysActor.PIDActive = false; 1978 RootPart.PhysActor.PIDActive = false;
1626 } 1979 }
1627 1980
1981 public void rotLookAt(Quaternion target, float strength, float damping)
1982 {
1983 SceneObjectPart rootpart = m_rootPart;
1984 if (rootpart != null)
1985 {
1986 if (IsAttachment)
1987 {
1988 /*
1989 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1990 if (avatar != null)
1991 {
1992 Rotate the Av?
1993 } */
1994 }
1995 else
1996 {
1997 if (rootpart.PhysActor != null)
1998 { // APID must be implemented in your physics system for this to function.
1999 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2000 rootpart.PhysActor.APIDStrength = strength;
2001 rootpart.PhysActor.APIDDamping = damping;
2002 rootpart.PhysActor.APIDActive = true;
2003 }
2004 }
2005 }
2006 }
2007
2008 public void stopLookAt()
2009 {
2010 SceneObjectPart rootpart = m_rootPart;
2011 if (rootpart != null)
2012 {
2013 if (rootpart.PhysActor != null)
2014 { // APID must be implemented in your physics system for this to function.
2015 rootpart.PhysActor.APIDActive = false;
2016 }
2017 }
2018
2019 }
2020
1628 /// <summary> 2021 /// <summary>
1629 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds. 2022 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds.
1630 /// </summary> 2023 /// </summary>
@@ -1680,6 +2073,8 @@ namespace OpenSim.Region.Framework.Scenes
1680 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2073 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1681 { 2074 {
1682 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2075 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2076 newPart.SetParent(this);
2077
1683 AddPart(newPart); 2078 AddPart(newPart);
1684 2079
1685 SetPartAsNonRoot(newPart); 2080 SetPartAsNonRoot(newPart);
@@ -1808,11 +2203,11 @@ namespace OpenSim.Region.Framework.Scenes
1808 /// Immediately send a full update for this scene object. 2203 /// Immediately send a full update for this scene object.
1809 /// </summary> 2204 /// </summary>
1810 public void SendGroupFullUpdate() 2205 public void SendGroupFullUpdate()
1811 { 2206 {
1812 if (IsDeleted) 2207 if (IsDeleted)
1813 return; 2208 return;
1814 2209
1815// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2210// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
1816 2211
1817 RootPart.SendFullUpdateToAllClients(); 2212 RootPart.SendFullUpdateToAllClients();
1818 2213
@@ -2013,7 +2408,7 @@ namespace OpenSim.Region.Framework.Scenes
2013 objectGroup.IsDeleted = true; 2408 objectGroup.IsDeleted = true;
2014 2409
2015 objectGroup.m_parts.Clear(); 2410 objectGroup.m_parts.Clear();
2016 2411
2017 // Can't do this yet since backup still makes use of the root part without any synchronization 2412 // Can't do this yet since backup still makes use of the root part without any synchronization
2018// objectGroup.m_rootPart = null; 2413// objectGroup.m_rootPart = null;
2019 2414
@@ -2147,6 +2542,7 @@ namespace OpenSim.Region.Framework.Scenes
2147 /// <param name="objectGroup"></param> 2542 /// <param name="objectGroup"></param>
2148 public virtual void DetachFromBackup() 2543 public virtual void DetachFromBackup()
2149 { 2544 {
2545 m_scene.SceneGraph.FireDetachFromBackup(this);
2150 if (m_isBackedUp && Scene != null) 2546 if (m_isBackedUp && Scene != null)
2151 m_scene.EventManager.OnBackup -= ProcessBackup; 2547 m_scene.EventManager.OnBackup -= ProcessBackup;
2152 2548
@@ -2165,7 +2561,8 @@ namespace OpenSim.Region.Framework.Scenes
2165 2561
2166 axPos *= parentRot; 2562 axPos *= parentRot;
2167 part.OffsetPosition = axPos; 2563 part.OffsetPosition = axPos;
2168 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 2564 Vector3 newPos = oldGroupPosition + part.OffsetPosition;
2565 part.GroupPosition = newPos;
2169 part.OffsetPosition = Vector3.Zero; 2566 part.OffsetPosition = Vector3.Zero;
2170 part.RotationOffset = worldRot; 2567 part.RotationOffset = worldRot;
2171 2568
@@ -2176,7 +2573,7 @@ namespace OpenSim.Region.Framework.Scenes
2176 2573
2177 part.LinkNum = linkNum; 2574 part.LinkNum = linkNum;
2178 2575
2179 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 2576 part.OffsetPosition = newPos - AbsolutePosition;
2180 2577
2181 Quaternion rootRotation = m_rootPart.RotationOffset; 2578 Quaternion rootRotation = m_rootPart.RotationOffset;
2182 2579
@@ -2186,7 +2583,7 @@ namespace OpenSim.Region.Framework.Scenes
2186 2583
2187 parentRot = m_rootPart.RotationOffset; 2584 parentRot = m_rootPart.RotationOffset;
2188 oldRot = part.RotationOffset; 2585 oldRot = part.RotationOffset;
2189 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 2586 Quaternion newRot = Quaternion.Inverse(parentRot) * worldRot;
2190 part.RotationOffset = newRot; 2587 part.RotationOffset = newRot;
2191 } 2588 }
2192 2589
@@ -2433,8 +2830,12 @@ namespace OpenSim.Region.Framework.Scenes
2433 } 2830 }
2434 } 2831 }
2435 2832
2833 RootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
2436 for (int i = 0; i < parts.Length; i++) 2834 for (int i = 0; i < parts.Length; i++)
2437 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect); 2835 {
2836 if (parts[i] != RootPart)
2837 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
2838 }
2438 } 2839 }
2439 } 2840 }
2440 2841
@@ -2447,6 +2848,17 @@ namespace OpenSim.Region.Framework.Scenes
2447 } 2848 }
2448 } 2849 }
2449 2850
2851
2852
2853 /// <summary>
2854 /// Gets the number of parts
2855 /// </summary>
2856 /// <returns></returns>
2857 public int GetPartCount()
2858 {
2859 return Parts.Count();
2860 }
2861
2450 /// <summary> 2862 /// <summary>
2451 /// Update the texture entry for this part 2863 /// Update the texture entry for this part
2452 /// </summary> 2864 /// </summary>
@@ -2508,7 +2920,6 @@ namespace OpenSim.Region.Framework.Scenes
2508 { 2920 {
2509// m_log.DebugFormat( 2921// m_log.DebugFormat(
2510// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale); 2922// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale);
2511
2512 RootPart.StoreUndoState(true); 2923 RootPart.StoreUndoState(true);
2513 2924
2514 scale.X = Math.Min(scale.X, Scene.m_maxNonphys); 2925 scale.X = Math.Min(scale.X, Scene.m_maxNonphys);
@@ -2609,7 +3020,6 @@ namespace OpenSim.Region.Framework.Scenes
2609 prevScale.X *= x; 3020 prevScale.X *= x;
2610 prevScale.Y *= y; 3021 prevScale.Y *= y;
2611 prevScale.Z *= z; 3022 prevScale.Z *= z;
2612
2613// RootPart.IgnoreUndoUpdate = true; 3023// RootPart.IgnoreUndoUpdate = true;
2614 RootPart.Resize(prevScale); 3024 RootPart.Resize(prevScale);
2615// RootPart.IgnoreUndoUpdate = false; 3025// RootPart.IgnoreUndoUpdate = false;
@@ -2640,7 +3050,9 @@ namespace OpenSim.Region.Framework.Scenes
2640 } 3050 }
2641 3051
2642// obPart.IgnoreUndoUpdate = false; 3052// obPart.IgnoreUndoUpdate = false;
2643// obPart.StoreUndoState(); 3053 HasGroupChanged = true;
3054 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
3055 ScheduleGroupForTerseUpdate();
2644 } 3056 }
2645 3057
2646// m_log.DebugFormat( 3058// m_log.DebugFormat(
@@ -2700,9 +3112,9 @@ namespace OpenSim.Region.Framework.Scenes
2700 { 3112 {
2701 SceneObjectPart part = GetChildPart(localID); 3113 SceneObjectPart part = GetChildPart(localID);
2702 3114
2703// SceneObjectPart[] parts = m_parts.GetArray(); 3115 SceneObjectPart[] parts = m_parts.GetArray();
2704// for (int i = 0; i < parts.Length; i++) 3116 for (int i = 0; i < parts.Length; i++)
2705// parts[i].StoreUndoState(); 3117 parts[i].StoreUndoState();
2706 3118
2707 if (part != null) 3119 if (part != null)
2708 { 3120 {
@@ -2758,10 +3170,27 @@ namespace OpenSim.Region.Framework.Scenes
2758 obPart.OffsetPosition = obPart.OffsetPosition + diff; 3170 obPart.OffsetPosition = obPart.OffsetPosition + diff;
2759 } 3171 }
2760 3172
2761 AbsolutePosition = newPos; 3173 //We have to set undoing here because otherwise an undo state will be saved
3174 if (!m_rootPart.Undoing)
3175 {
3176 m_rootPart.Undoing = true;
3177 AbsolutePosition = newPos;
3178 m_rootPart.Undoing = false;
3179 }
3180 else
3181 {
3182 AbsolutePosition = newPos;
3183 }
2762 3184
2763 HasGroupChanged = true; 3185 HasGroupChanged = true;
2764 ScheduleGroupForTerseUpdate(); 3186 if (m_rootPart.Undoing)
3187 {
3188 ScheduleGroupForFullUpdate();
3189 }
3190 else
3191 {
3192 ScheduleGroupForTerseUpdate();
3193 }
2765 } 3194 }
2766 3195
2767 #endregion 3196 #endregion
@@ -2838,10 +3267,7 @@ namespace OpenSim.Region.Framework.Scenes
2838 public void UpdateSingleRotation(Quaternion rot, uint localID) 3267 public void UpdateSingleRotation(Quaternion rot, uint localID)
2839 { 3268 {
2840 SceneObjectPart part = GetChildPart(localID); 3269 SceneObjectPart part = GetChildPart(localID);
2841
2842 SceneObjectPart[] parts = m_parts.GetArray(); 3270 SceneObjectPart[] parts = m_parts.GetArray();
2843 for (int i = 0; i < parts.Length; i++)
2844 parts[i].StoreUndoState();
2845 3271
2846 if (part != null) 3272 if (part != null)
2847 { 3273 {
@@ -2879,7 +3305,16 @@ namespace OpenSim.Region.Framework.Scenes
2879 if (part.UUID == m_rootPart.UUID) 3305 if (part.UUID == m_rootPart.UUID)
2880 { 3306 {
2881 UpdateRootRotation(rot); 3307 UpdateRootRotation(rot);
2882 AbsolutePosition = pos; 3308 if (!m_rootPart.Undoing)
3309 {
3310 m_rootPart.Undoing = true;
3311 AbsolutePosition = pos;
3312 m_rootPart.Undoing = false;
3313 }
3314 else
3315 {
3316 AbsolutePosition = pos;
3317 }
2883 } 3318 }
2884 else 3319 else
2885 { 3320 {
@@ -2903,9 +3338,10 @@ namespace OpenSim.Region.Framework.Scenes
2903 3338
2904 Quaternion axRot = rot; 3339 Quaternion axRot = rot;
2905 Quaternion oldParentRot = m_rootPart.RotationOffset; 3340 Quaternion oldParentRot = m_rootPart.RotationOffset;
2906
2907 m_rootPart.StoreUndoState(); 3341 m_rootPart.StoreUndoState();
2908 m_rootPart.UpdateRotation(rot); 3342
3343 //Don't use UpdateRotation because it schedules an update prematurely
3344 m_rootPart.RotationOffset = rot;
2909 if (m_rootPart.PhysActor != null) 3345 if (m_rootPart.PhysActor != null)
2910 { 3346 {
2911 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset; 3347 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset;
@@ -2919,15 +3355,17 @@ namespace OpenSim.Region.Framework.Scenes
2919 if (prim.UUID != m_rootPart.UUID) 3355 if (prim.UUID != m_rootPart.UUID)
2920 { 3356 {
2921 prim.IgnoreUndoUpdate = true; 3357 prim.IgnoreUndoUpdate = true;
3358
3359 Quaternion NewRot = oldParentRot * prim.RotationOffset;
3360 NewRot = Quaternion.Inverse(axRot) * NewRot;
3361 prim.RotationOffset = NewRot;
3362
2922 Vector3 axPos = prim.OffsetPosition; 3363 Vector3 axPos = prim.OffsetPosition;
3364
2923 axPos *= oldParentRot; 3365 axPos *= oldParentRot;
2924 axPos *= Quaternion.Inverse(axRot); 3366 axPos *= Quaternion.Inverse(axRot);
2925 prim.OffsetPosition = axPos; 3367 prim.OffsetPosition = axPos;
2926 Quaternion primsRot = prim.RotationOffset; 3368
2927 Quaternion newRot = oldParentRot * primsRot;
2928 newRot = Quaternion.Inverse(axRot) * newRot;
2929 prim.RotationOffset = newRot;
2930 prim.ScheduleTerseUpdate();
2931 prim.IgnoreUndoUpdate = false; 3369 prim.IgnoreUndoUpdate = false;
2932 } 3370 }
2933 } 3371 }
@@ -2941,8 +3379,8 @@ namespace OpenSim.Region.Framework.Scenes
2941//// childpart.StoreUndoState(); 3379//// childpart.StoreUndoState();
2942// } 3380// }
2943// } 3381// }
2944 3382 HasGroupChanged = true;
2945 m_rootPart.ScheduleTerseUpdate(); 3383 ScheduleGroupForFullUpdate();
2946 3384
2947// m_log.DebugFormat( 3385// m_log.DebugFormat(
2948// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}", 3386// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}",
@@ -3170,7 +3608,6 @@ namespace OpenSim.Region.Framework.Scenes
3170 public float GetMass() 3608 public float GetMass()
3171 { 3609 {
3172 float retmass = 0f; 3610 float retmass = 0f;
3173
3174 SceneObjectPart[] parts = m_parts.GetArray(); 3611 SceneObjectPart[] parts = m_parts.GetArray();
3175 for (int i = 0; i < parts.Length; i++) 3612 for (int i = 0; i < parts.Length; i++)
3176 retmass += parts[i].GetMass(); 3613 retmass += parts[i].GetMass();
@@ -3266,6 +3703,14 @@ namespace OpenSim.Region.Framework.Scenes
3266 SetFromItemID(uuid); 3703 SetFromItemID(uuid);
3267 } 3704 }
3268 3705
3706 public void ResetOwnerChangeFlag()
3707 {
3708 ForEachPart(delegate(SceneObjectPart part)
3709 {
3710 part.ResetOwnerChangeFlag();
3711 });
3712 }
3713
3269 #endregion 3714 #endregion
3270 } 3715 }
3271} 3716}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 36d3588..5576ec9 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -62,7 +62,8 @@ namespace OpenSim.Region.Framework.Scenes
62 TELEPORT = 512, 62 TELEPORT = 512,
63 REGION_RESTART = 1024, 63 REGION_RESTART = 1024,
64 MEDIA = 2048, 64 MEDIA = 2048,
65 ANIMATION = 16384 65 ANIMATION = 16384,
66 POSITION = 32768
66 } 67 }
67 68
68 // I don't really know where to put this except here. 69 // I don't really know where to put this except here.
@@ -184,6 +185,15 @@ namespace OpenSim.Region.Framework.Scenes
184 185
185 public UUID FromFolderID; 186 public UUID FromFolderID;
186 187
188 // The following two are to hold the attachment data
189 // while an object is inworld
190 [XmlIgnore]
191 public byte AttachPoint = 0;
192
193 [XmlIgnore]
194 public Vector3 AttachOffset = Vector3.Zero;
195
196 [XmlIgnore]
187 public int STATUS_ROTATE_X; 197 public int STATUS_ROTATE_X;
188 198
189 public int STATUS_ROTATE_Y; 199 public int STATUS_ROTATE_Y;
@@ -210,8 +220,7 @@ namespace OpenSim.Region.Framework.Scenes
210 220
211 public Vector3 RotationAxis = Vector3.One; 221 public Vector3 RotationAxis = Vector3.One;
212 222
213 public bool VolumeDetectActive; // XmlIgnore set to avoid problems with persistance until I come to care for this 223 public bool VolumeDetectActive;
214 // Certainly this must be a persistant setting finally
215 224
216 public bool IsWaitingForFirstSpinUpdatePacket; 225 public bool IsWaitingForFirstSpinUpdatePacket;
217 226
@@ -251,6 +260,7 @@ namespace OpenSim.Region.Framework.Scenes
251 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 260 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
252 private Vector3 m_sitTargetPosition; 261 private Vector3 m_sitTargetPosition;
253 private string m_sitAnimation = "SIT"; 262 private string m_sitAnimation = "SIT";
263 private bool m_occupied; // KF if any av is sitting on this prim
254 private string m_text = String.Empty; 264 private string m_text = String.Empty;
255 private string m_touchName = String.Empty; 265 private string m_touchName = String.Empty;
256 private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5); 266 private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5);
@@ -283,6 +293,7 @@ namespace OpenSim.Region.Framework.Scenes
283 protected Vector3 m_lastAcceleration; 293 protected Vector3 m_lastAcceleration;
284 protected Vector3 m_lastAngularVelocity; 294 protected Vector3 m_lastAngularVelocity;
285 protected int m_lastTerseSent; 295 protected int m_lastTerseSent;
296 protected float m_buoyancy = 0.0f;
286 297
287 /// <summary> 298 /// <summary>
288 /// Stores media texture data 299 /// Stores media texture data
@@ -338,7 +349,7 @@ namespace OpenSim.Region.Framework.Scenes
338 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 349 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
339 Quaternion rotationOffset, Vector3 offsetPosition) : this() 350 Quaternion rotationOffset, Vector3 offsetPosition) : this()
340 { 351 {
341 m_name = "Primitive"; 352 m_name = "Object";
342 353
343 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 354 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
344 LastOwnerID = CreatorID = OwnerID = ownerID; 355 LastOwnerID = CreatorID = OwnerID = ownerID;
@@ -378,7 +389,7 @@ namespace OpenSim.Region.Framework.Scenes
378 private uint _ownerMask = (uint)PermissionMask.All; 389 private uint _ownerMask = (uint)PermissionMask.All;
379 private uint _groupMask = (uint)PermissionMask.None; 390 private uint _groupMask = (uint)PermissionMask.None;
380 private uint _everyoneMask = (uint)PermissionMask.None; 391 private uint _everyoneMask = (uint)PermissionMask.None;
381 private uint _nextOwnerMask = (uint)PermissionMask.All; 392 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
382 private PrimFlags _flags = PrimFlags.None; 393 private PrimFlags _flags = PrimFlags.None;
383 private DateTime m_expires; 394 private DateTime m_expires;
384 private DateTime m_rezzed; 395 private DateTime m_rezzed;
@@ -472,12 +483,16 @@ namespace OpenSim.Region.Framework.Scenes
472 } 483 }
473 484
474 /// <value> 485 /// <value>
475 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 486 /// Get the inventory list
476 /// </value> 487 /// </value>
477 public TaskInventoryDictionary TaskInventory 488 public TaskInventoryDictionary TaskInventory
478 { 489 {
479 get { return m_inventory.Items; } 490 get {
480 set { m_inventory.Items = value; } 491 return m_inventory.Items;
492 }
493 set {
494 m_inventory.Items = value;
495 }
481 } 496 }
482 497
483 /// <summary> 498 /// <summary>
@@ -621,14 +636,12 @@ namespace OpenSim.Region.Framework.Scenes
621 set { m_LoopSoundSlavePrims = value; } 636 set { m_LoopSoundSlavePrims = value; }
622 } 637 }
623 638
624
625 public Byte[] TextureAnimation 639 public Byte[] TextureAnimation
626 { 640 {
627 get { return m_TextureAnimation; } 641 get { return m_TextureAnimation; }
628 set { m_TextureAnimation = value; } 642 set { m_TextureAnimation = value; }
629 } 643 }
630 644
631
632 public Byte[] ParticleSystem 645 public Byte[] ParticleSystem
633 { 646 {
634 get { return m_particleSystem; } 647 get { return m_particleSystem; }
@@ -665,9 +678,11 @@ namespace OpenSim.Region.Framework.Scenes
665 { 678 {
666 // If this is a linkset, we don't want the physics engine mucking up our group position here. 679 // If this is a linkset, we don't want the physics engine mucking up our group position here.
667 PhysicsActor actor = PhysActor; 680 PhysicsActor actor = PhysActor;
668 if (actor != null && ParentID == 0) 681 if (ParentID == 0)
669 { 682 {
670 m_groupPosition = actor.Position; 683 if (actor != null)
684 m_groupPosition = actor.Position;
685 return m_groupPosition;
671 } 686 }
672 687
673 if (ParentGroup.IsAttachment) 688 if (ParentGroup.IsAttachment)
@@ -677,12 +692,14 @@ namespace OpenSim.Region.Framework.Scenes
677 return sp.AbsolutePosition; 692 return sp.AbsolutePosition;
678 } 693 }
679 694
695 // use root prim's group position. Physics may have updated it
696 if (ParentGroup.RootPart != this)
697 m_groupPosition = ParentGroup.RootPart.GroupPosition;
680 return m_groupPosition; 698 return m_groupPosition;
681 } 699 }
682 set 700 set
683 { 701 {
684 m_groupPosition = value; 702 m_groupPosition = value;
685
686 PhysicsActor actor = PhysActor; 703 PhysicsActor actor = PhysActor;
687 if (actor != null) 704 if (actor != null)
688 { 705 {
@@ -708,16 +725,6 @@ namespace OpenSim.Region.Framework.Scenes
708 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); 725 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message);
709 } 726 }
710 } 727 }
711
712 // TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too
713 if (SitTargetAvatar != UUID.Zero)
714 {
715 ScenePresence avatar;
716 if (ParentGroup.Scene.TryGetScenePresence(SitTargetAvatar, out avatar))
717 {
718 avatar.ParentPosition = GetWorldPosition();
719 }
720 }
721 } 728 }
722 } 729 }
723 730
@@ -726,7 +733,7 @@ namespace OpenSim.Region.Framework.Scenes
726 get { return m_offsetPosition; } 733 get { return m_offsetPosition; }
727 set 734 set
728 { 735 {
729// StoreUndoState(); 736 Vector3 oldpos = m_offsetPosition;
730 m_offsetPosition = value; 737 m_offsetPosition = value;
731 738
732 if (ParentGroup != null && !ParentGroup.IsDeleted) 739 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -741,7 +748,22 @@ namespace OpenSim.Region.Framework.Scenes
741 if (ParentGroup.Scene != null) 748 if (ParentGroup.Scene != null)
742 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 749 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
743 } 750 }
751
752 if (!m_parentGroup.m_dupeInProgress)
753 {
754 List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
755 foreach (ScenePresence av in avs)
756 {
757 if (av.ParentID == m_localId)
758 {
759 Vector3 offset = (m_offsetPosition - oldpos);
760 av.AbsolutePosition += offset;
761 av.SendAvatarDataToAllAgents();
762 }
763 }
764 }
744 } 765 }
766 TriggerScriptChangedEvent(Changed.POSITION);
745 } 767 }
746 } 768 }
747 769
@@ -890,7 +912,16 @@ namespace OpenSim.Region.Framework.Scenes
890 /// <summary></summary> 912 /// <summary></summary>
891 public Vector3 Acceleration 913 public Vector3 Acceleration
892 { 914 {
893 get { return m_acceleration; } 915 get
916 {
917 PhysicsActor actor = PhysActor;
918 if (actor != null)
919 {
920 m_acceleration = actor.Acceleration;
921 }
922 return m_acceleration;
923 }
924
894 set { m_acceleration = value; } 925 set { m_acceleration = value; }
895 } 926 }
896 927
@@ -1041,10 +1072,7 @@ namespace OpenSim.Region.Framework.Scenes
1041 { 1072 {
1042 get 1073 get
1043 { 1074 {
1044 if (ParentGroup.IsAttachment) 1075 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1045 return GroupPosition;
1046
1047 return m_offsetPosition + m_groupPosition;
1048 } 1076 }
1049 } 1077 }
1050 1078
@@ -1214,6 +1242,13 @@ namespace OpenSim.Region.Framework.Scenes
1214 _flags = value; 1242 _flags = value;
1215 } 1243 }
1216 } 1244 }
1245
1246 [XmlIgnore]
1247 public bool IsOccupied // KF If an av is sittingon this prim
1248 {
1249 get { return m_occupied; }
1250 set { m_occupied = value; }
1251 }
1217 1252
1218 /// <summary> 1253 /// <summary>
1219 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero 1254 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero
@@ -1273,6 +1308,19 @@ namespace OpenSim.Region.Framework.Scenes
1273 set { m_collisionSoundVolume = value; } 1308 set { m_collisionSoundVolume = value; }
1274 } 1309 }
1275 1310
1311 public float Buoyancy
1312 {
1313 get { return m_buoyancy; }
1314 set
1315 {
1316 m_buoyancy = value;
1317 if (PhysActor != null)
1318 {
1319 PhysActor.Buoyancy = value;
1320 }
1321 }
1322 }
1323
1276 #endregion Public Properties with only Get 1324 #endregion Public Properties with only Get
1277 1325
1278 private uint ApplyMask(uint val, bool set, uint mask) 1326 private uint ApplyMask(uint val, bool set, uint mask)
@@ -1597,6 +1645,9 @@ namespace OpenSim.Region.Framework.Scenes
1597 1645
1598 // Move afterwards ResetIDs as it clears the localID 1646 // Move afterwards ResetIDs as it clears the localID
1599 dupe.LocalId = localID; 1647 dupe.LocalId = localID;
1648 if(dupe.PhysActor != null)
1649 dupe.PhysActor.LocalID = localID;
1650
1600 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 1651 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1601 dupe.LastOwnerID = OwnerID; 1652 dupe.LastOwnerID = OwnerID;
1602 1653
@@ -2602,17 +2653,18 @@ namespace OpenSim.Region.Framework.Scenes
2602 //Trys to fetch sound id from prim's inventory. 2653 //Trys to fetch sound id from prim's inventory.
2603 //Prim's inventory doesn't support non script items yet 2654 //Prim's inventory doesn't support non script items yet
2604 2655
2605 lock (TaskInventory) 2656 TaskInventory.LockItemsForRead(true);
2657
2658 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2606 { 2659 {
2607 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2660 if (item.Value.Name == sound)
2608 { 2661 {
2609 if (item.Value.Name == sound) 2662 soundID = item.Value.ItemID;
2610 { 2663 break;
2611 soundID = item.Value.ItemID;
2612 break;
2613 }
2614 } 2664 }
2615 } 2665 }
2666
2667 TaskInventory.LockItemsForRead(false);
2616 } 2668 }
2617 2669
2618 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp) 2670 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp)
@@ -2925,8 +2977,8 @@ namespace OpenSim.Region.Framework.Scenes
2925 { 2977 {
2926 const float ROTATION_TOLERANCE = 0.01f; 2978 const float ROTATION_TOLERANCE = 0.01f;
2927 const float VELOCITY_TOLERANCE = 0.001f; 2979 const float VELOCITY_TOLERANCE = 0.001f;
2928 const float POSITION_TOLERANCE = 0.05f; 2980 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2929 const int TIME_MS_TOLERANCE = 3000; 2981 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2930 2982
2931 switch (UpdateFlag) 2983 switch (UpdateFlag)
2932 { 2984 {
@@ -2988,17 +3040,16 @@ namespace OpenSim.Region.Framework.Scenes
2988 if (!UUID.TryParse(sound, out soundID)) 3040 if (!UUID.TryParse(sound, out soundID))
2989 { 3041 {
2990 // search sound file from inventory 3042 // search sound file from inventory
2991 lock (TaskInventory) 3043 TaskInventory.LockItemsForRead(true);
3044 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2992 { 3045 {
2993 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3046 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
2994 { 3047 {
2995 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3048 soundID = item.Value.ItemID;
2996 { 3049 break;
2997 soundID = item.Value.ItemID;
2998 break;
2999 }
3000 } 3050 }
3001 } 3051 }
3052 TaskInventory.LockItemsForRead(false);
3002 } 3053 }
3003 3054
3004 if (soundID == UUID.Zero) 3055 if (soundID == UUID.Zero)
@@ -3465,10 +3516,10 @@ namespace OpenSim.Region.Framework.Scenes
3465 // TODO: May need to fix for group comparison 3516 // TODO: May need to fix for group comparison
3466 if (last.Compare(this)) 3517 if (last.Compare(this))
3467 { 3518 {
3468 // m_log.DebugFormat( 3519 // m_log.DebugFormat(
3469 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}", 3520 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3470 // Name, LocalId, m_undo.Count); 3521 // Name, LocalId, m_undo.Count);
3471 3522
3472 return; 3523 return;
3473 } 3524 }
3474 } 3525 }
@@ -3481,29 +3532,29 @@ namespace OpenSim.Region.Framework.Scenes
3481 if (ParentGroup.GetSceneMaxUndo() > 0) 3532 if (ParentGroup.GetSceneMaxUndo() > 0)
3482 { 3533 {
3483 UndoState nUndo = new UndoState(this, forGroup); 3534 UndoState nUndo = new UndoState(this, forGroup);
3484 3535
3485 m_undo.Push(nUndo); 3536 m_undo.Push(nUndo);
3486 3537
3487 if (m_redo.Count > 0) 3538 if (m_redo.Count > 0)
3488 m_redo.Clear(); 3539 m_redo.Clear();
3489 3540
3490 // m_log.DebugFormat( 3541 // m_log.DebugFormat(
3491 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}", 3542 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3492 // Name, LocalId, forGroup, m_undo.Count); 3543 // Name, LocalId, forGroup, m_undo.Count);
3493 } 3544 }
3494 } 3545 }
3495 } 3546 }
3496 } 3547 }
3497// else 3548 // else
3498// { 3549 // {
3499// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId); 3550 // m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3500// } 3551 // }
3501 } 3552 }
3502// else 3553 // else
3503// { 3554 // {
3504// m_log.DebugFormat( 3555 // m_log.DebugFormat(
3505// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId); 3556 // "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3506// } 3557 // }
3507 } 3558 }
3508 3559
3509 /// <summary> 3560 /// <summary>
@@ -4234,6 +4285,9 @@ namespace OpenSim.Region.Framework.Scenes
4234 bool wasPhantom = ((Flags & PrimFlags.Phantom) != 0); 4285 bool wasPhantom = ((Flags & PrimFlags.Phantom) != 0);
4235 bool wasVD = VolumeDetectActive; 4286 bool wasVD = VolumeDetectActive;
4236 4287
4288// m_log.DebugFormat("[SOP]: Old states: phys: {0} temp: {1} phan: {2} vd: {3}", wasUsingPhysics, wasTemporary, wasPhantom, wasVD);
4289// m_log.DebugFormat("[SOP]: New states: phys: {0} temp: {1} phan: {2} vd: {3}", UsePhysics, SetTemporary, SetPhantom, SetVD);
4290
4237 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) 4291 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
4238 return; 4292 return;
4239 4293
@@ -4263,6 +4317,11 @@ namespace OpenSim.Region.Framework.Scenes
4263 SetPhantom = false; 4317 SetPhantom = false;
4264 } 4318 }
4265 } 4319 }
4320 else if (wasVD)
4321 {
4322 // Correspondingly, if VD is turned off, also turn off phantom
4323 SetPhantom = false;
4324 }
4266 4325
4267 if (UsePhysics && IsJoint()) 4326 if (UsePhysics && IsJoint())
4268 { 4327 {
@@ -4761,5 +4820,17 @@ namespace OpenSim.Region.Framework.Scenes
4761 Color color = Color; 4820 Color color = Color;
4762 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 4821 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4763 } 4822 }
4823
4824 public void ResetOwnerChangeFlag()
4825 {
4826 List<UUID> inv = Inventory.GetInventoryList();
4827
4828 foreach (UUID itemID in inv)
4829 {
4830 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
4831 item.OwnerChanged = false;
4832 Inventory.UpdateInventoryItem(item, false, false);
4833 }
4834 }
4764 } 4835 }
4765} 4836}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 0c36dcd..dc64281 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -48,6 +48,9 @@ namespace OpenSim.Region.Framework.Scenes
48 private string m_inventoryFileName = String.Empty; 48 private string m_inventoryFileName = String.Empty;
49 private byte[] m_inventoryFileData = new byte[0]; 49 private byte[] m_inventoryFileData = new byte[0];
50 private uint m_inventoryFileNameSerial = 0; 50 private uint m_inventoryFileNameSerial = 0;
51 private bool m_inventoryPrivileged = false;
52
53 private Dictionary<UUID, ArrayList> m_scriptErrors = new Dictionary<UUID, ArrayList>();
51 54
52 /// <value> 55 /// <value>
53 /// The part to which the inventory belongs. 56 /// The part to which the inventory belongs.
@@ -84,11 +87,14 @@ namespace OpenSim.Region.Framework.Scenes
84 /// </value> 87 /// </value>
85 protected internal TaskInventoryDictionary Items 88 protected internal TaskInventoryDictionary Items
86 { 89 {
87 get { return m_items; } 90 get {
91 return m_items;
92 }
88 set 93 set
89 { 94 {
90 m_items = value; 95 m_items = value;
91 m_inventorySerial++; 96 m_inventorySerial++;
97 QueryScriptStates();
92 } 98 }
93 } 99 }
94 100
@@ -123,38 +129,45 @@ namespace OpenSim.Region.Framework.Scenes
123 public void ResetInventoryIDs() 129 public void ResetInventoryIDs()
124 { 130 {
125 if (null == m_part) 131 if (null == m_part)
126 return; 132 m_items.LockItemsForWrite(true);
127 133
128 lock (m_items) 134 if (Items.Count == 0)
129 { 135 {
130 if (0 == m_items.Count) 136 m_items.LockItemsForWrite(false);
131 return; 137 return;
138 }
132 139
133 IList<TaskInventoryItem> items = GetInventoryItems(); 140 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
134 m_items.Clear(); 141 Items.Clear();
135 142
136 foreach (TaskInventoryItem item in items) 143 foreach (TaskInventoryItem item in items)
137 { 144 {
138 item.ResetIDs(m_part.UUID); 145 item.ResetIDs(m_part.UUID);
139 m_items.Add(item.ItemID, item); 146 Items.Add(item.ItemID, item);
140 }
141 } 147 }
148 m_items.LockItemsForWrite(false);
142 } 149 }
143 150
144 public void ResetObjectID() 151 public void ResetObjectID()
145 { 152 {
146 lock (Items) 153 m_items.LockItemsForWrite(true);
154
155 if (Items.Count == 0)
147 { 156 {
148 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 157 m_items.LockItemsForWrite(false);
149 Items.Clear(); 158 return;
150
151 foreach (TaskInventoryItem item in items)
152 {
153 item.ParentPartID = m_part.UUID;
154 item.ParentID = m_part.UUID;
155 Items.Add(item.ItemID, item);
156 }
157 } 159 }
160
161 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
162 Items.Clear();
163
164 foreach (TaskInventoryItem item in items)
165 {
166 item.ParentPartID = m_part.UUID;
167 item.ParentID = m_part.UUID;
168 Items.Add(item.ItemID, item);
169 }
170 m_items.LockItemsForWrite(false);
158 } 171 }
159 172
160 /// <summary> 173 /// <summary>
@@ -163,12 +176,11 @@ namespace OpenSim.Region.Framework.Scenes
163 /// <param name="ownerId"></param> 176 /// <param name="ownerId"></param>
164 public void ChangeInventoryOwner(UUID ownerId) 177 public void ChangeInventoryOwner(UUID ownerId)
165 { 178 {
166 lock (Items) 179 m_items.LockItemsForWrite(true);
180 if (0 == Items.Count)
167 { 181 {
168 if (0 == Items.Count) 182 m_items.LockItemsForWrite(false);
169 { 183 return;
170 return;
171 }
172 } 184 }
173 185
174 HasInventoryChanged = true; 186 HasInventoryChanged = true;
@@ -184,6 +196,7 @@ namespace OpenSim.Region.Framework.Scenes
184 item.PermsGranter = UUID.Zero; 196 item.PermsGranter = UUID.Zero;
185 item.OwnerChanged = true; 197 item.OwnerChanged = true;
186 } 198 }
199 m_items.LockItemsForWrite(false);
187 } 200 }
188 201
189 /// <summary> 202 /// <summary>
@@ -192,12 +205,11 @@ namespace OpenSim.Region.Framework.Scenes
192 /// <param name="groupID"></param> 205 /// <param name="groupID"></param>
193 public void ChangeInventoryGroup(UUID groupID) 206 public void ChangeInventoryGroup(UUID groupID)
194 { 207 {
195 lock (Items) 208 m_items.LockItemsForWrite(true);
209 if (0 == Items.Count)
196 { 210 {
197 if (0 == Items.Count) 211 m_items.LockItemsForWrite(false);
198 { 212 return;
199 return;
200 }
201 } 213 }
202 214
203 // Don't let this set the HasGroupChanged flag for attachments 215 // Don't let this set the HasGroupChanged flag for attachments
@@ -209,12 +221,45 @@ namespace OpenSim.Region.Framework.Scenes
209 m_part.ParentGroup.HasGroupChanged = true; 221 m_part.ParentGroup.HasGroupChanged = true;
210 } 222 }
211 223
212 List<TaskInventoryItem> items = GetInventoryItems(); 224 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
213 foreach (TaskInventoryItem item in items) 225 foreach (TaskInventoryItem item in items)
214 { 226 {
215 if (groupID != item.GroupID) 227 if (groupID != item.GroupID)
228 {
216 item.GroupID = groupID; 229 item.GroupID = groupID;
230 }
231 }
232 m_items.LockItemsForWrite(false);
233 }
234
235 private void QueryScriptStates()
236 {
237 if (m_part == null || m_part.ParentGroup == null)
238 return;
239
240 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
241 if (engines == null) // No engine at all
242 return;
243
244 Items.LockItemsForRead(true);
245 foreach (TaskInventoryItem item in Items.Values)
246 {
247 if (item.InvType == (int)InventoryType.LSL)
248 {
249 foreach (IScriptModule e in engines)
250 {
251 bool running;
252
253 if (e.HasScript(item.ItemID, out running))
254 {
255 item.ScriptRunning = running;
256 break;
257 }
258 }
259 }
217 } 260 }
261
262 Items.LockItemsForRead(false);
218 } 263 }
219 264
220 /// <summary> 265 /// <summary>
@@ -222,9 +267,14 @@ namespace OpenSim.Region.Framework.Scenes
222 /// </summary> 267 /// </summary>
223 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) 268 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
224 { 269 {
225 List<TaskInventoryItem> scripts = GetInventoryScripts(); 270 Items.LockItemsForRead(true);
226 foreach (TaskInventoryItem item in scripts) 271 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
227 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 272 Items.LockItemsForRead(false);
273 foreach (TaskInventoryItem item in items)
274 {
275 if ((int)InventoryType.LSL == item.InvType)
276 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
277 }
228 } 278 }
229 279
230 public ArrayList GetScriptErrors(UUID itemID) 280 public ArrayList GetScriptErrors(UUID itemID)
@@ -255,9 +305,18 @@ namespace OpenSim.Region.Framework.Scenes
255 /// </param> 305 /// </param>
256 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 306 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
257 { 307 {
258 List<TaskInventoryItem> scripts = GetInventoryScripts(); 308 Items.LockItemsForRead(true);
259 foreach (TaskInventoryItem item in scripts) 309 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
260 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted); 310 Items.LockItemsForRead(false);
311
312 foreach (TaskInventoryItem item in items)
313 {
314 if ((int)InventoryType.LSL == item.InvType)
315 {
316 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
317 m_part.RemoveScriptEvents(item.ItemID);
318 }
319 }
261 } 320 }
262 321
263 /// <summary> 322 /// <summary>
@@ -273,7 +332,10 @@ namespace OpenSim.Region.Framework.Scenes
273 // item.Name, item.ItemID, Name, UUID); 332 // item.Name, item.ItemID, Name, UUID);
274 333
275 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) 334 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID))
335 {
336 StoreScriptError(item.ItemID, "no permission");
276 return; 337 return;
338 }
277 339
278 m_part.AddFlag(PrimFlags.Scripted); 340 m_part.AddFlag(PrimFlags.Scripted);
279 341
@@ -282,14 +344,13 @@ namespace OpenSim.Region.Framework.Scenes
282 if (stateSource == 2 && // Prim crossing 344 if (stateSource == 2 && // Prim crossing
283 m_part.ParentGroup.Scene.m_trustBinaries) 345 m_part.ParentGroup.Scene.m_trustBinaries)
284 { 346 {
285 lock (m_items) 347 m_items.LockItemsForWrite(true);
286 { 348 m_items[item.ItemID].PermsMask = 0;
287 m_items[item.ItemID].PermsMask = 0; 349 m_items[item.ItemID].PermsGranter = UUID.Zero;
288 m_items[item.ItemID].PermsGranter = UUID.Zero; 350 m_items.LockItemsForWrite(false);
289 }
290
291 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 351 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
292 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 352 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
353 StoreScriptErrors(item.ItemID, null);
293 m_part.ParentGroup.AddActiveScriptCount(1); 354 m_part.ParentGroup.AddActiveScriptCount(1);
294 m_part.ScheduleFullUpdate(); 355 m_part.ScheduleFullUpdate();
295 return; 356 return;
@@ -298,6 +359,8 @@ namespace OpenSim.Region.Framework.Scenes
298 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 359 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
299 if (null == asset) 360 if (null == asset)
300 { 361 {
362 string msg = String.Format("asset ID {0} could not be found", item.AssetID);
363 StoreScriptError(item.ItemID, msg);
301 m_log.ErrorFormat( 364 m_log.ErrorFormat(
302 "[PRIM INVENTORY]: " + 365 "[PRIM INVENTORY]: " +
303 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", 366 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
@@ -309,16 +372,21 @@ namespace OpenSim.Region.Framework.Scenes
309 if (m_part.ParentGroup.m_savedScriptState != null) 372 if (m_part.ParentGroup.m_savedScriptState != null)
310 item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID); 373 item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID);
311 374
312 lock (m_items) 375 m_items.LockItemsForWrite(true);
313 { 376
314 m_items[item.ItemID].OldItemID = item.OldItemID; 377 m_items[item.ItemID].OldItemID = item.OldItemID;
315 m_items[item.ItemID].PermsMask = 0; 378 m_items[item.ItemID].PermsMask = 0;
316 m_items[item.ItemID].PermsGranter = UUID.Zero; 379 m_items[item.ItemID].PermsGranter = UUID.Zero;
317 }
318 380
381 m_items.LockItemsForWrite(false);
382
319 string script = Utils.BytesToString(asset.Data); 383 string script = Utils.BytesToString(asset.Data);
320 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 384 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
321 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 385 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
386 StoreScriptErrors(item.ItemID, null);
387 if (!item.ScriptRunning)
388 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(
389 m_part.LocalId, item.ItemID);
322 m_part.ParentGroup.AddActiveScriptCount(1); 390 m_part.ParentGroup.AddActiveScriptCount(1);
323 m_part.ScheduleFullUpdate(); 391 m_part.ScheduleFullUpdate();
324 } 392 }
@@ -389,21 +457,145 @@ namespace OpenSim.Region.Framework.Scenes
389 457
390 /// <summary> 458 /// <summary>
391 /// Start a script which is in this prim's inventory. 459 /// Start a script which is in this prim's inventory.
460 /// Some processing may occur in the background, but this routine returns asap.
392 /// </summary> 461 /// </summary>
393 /// <param name="itemId"> 462 /// <param name="itemId">
394 /// A <see cref="UUID"/> 463 /// A <see cref="UUID"/>
395 /// </param> 464 /// </param>
396 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 465 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
397 { 466 {
398 TaskInventoryItem item = GetInventoryItem(itemId); 467 lock (m_scriptErrors)
399 if (item != null) 468 {
400 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 469 // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion
470 m_scriptErrors.Remove(itemId);
471 }
472 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
473 }
474
475 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
476 {
477 m_items.LockItemsForRead(true);
478 if (m_items.ContainsKey(itemId))
479 {
480 if (m_items.ContainsKey(itemId))
481 {
482 m_items.LockItemsForRead(false);
483 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource);
484 }
485 else
486 {
487 m_items.LockItemsForRead(false);
488 string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID,
489 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
490 StoreScriptError(itemId, msg);
491 m_log.ErrorFormat(
492 "[PRIM INVENTORY]: " +
493 "Couldn't start script with ID {0} since it {1}", itemId, msg);
494 }
495 }
401 else 496 else
497 {
498 m_items.LockItemsForRead(false);
499 string msg = String.Format("couldn't be found for prim {0}, {1}", m_part.Name, m_part.UUID);
500 StoreScriptError(itemId, msg);
402 m_log.ErrorFormat( 501 m_log.ErrorFormat(
403 "[PRIM INVENTORY]: " + 502 "[PRIM INVENTORY]: " +
404 "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 503 "Couldn't start script with ID {0} since it {1}", itemId, msg);
405 itemId, m_part.Name, m_part.UUID, 504 }
406 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 505
506 }
507
508 /// <summary>
509 /// Start a script which is in this prim's inventory and return any compilation error messages.
510 /// </summary>
511 /// <param name="itemId">
512 /// A <see cref="UUID"/>
513 /// </param>
514 public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
515 {
516 ArrayList errors;
517
518 // Indicate to CreateScriptInstanceInternal() we want it to
519 // post any compilation/loading error messages
520 lock (m_scriptErrors)
521 {
522 m_scriptErrors[itemId] = null;
523 }
524
525 // Perform compilation/loading
526 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
527
528 // Wait for and retrieve any errors
529 lock (m_scriptErrors)
530 {
531 while ((errors = m_scriptErrors[itemId]) == null)
532 {
533 if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000))
534 {
535 m_log.ErrorFormat(
536 "[PRIM INVENTORY]: " +
537 "timedout waiting for script {0} errors", itemId);
538 errors = m_scriptErrors[itemId];
539 if (errors == null)
540 {
541 errors = new ArrayList(1);
542 errors.Add("timedout waiting for errors");
543 }
544 break;
545 }
546 }
547 m_scriptErrors.Remove(itemId);
548 }
549 return errors;
550 }
551
552 // Signal to CreateScriptInstanceEr() that compilation/loading is complete
553 private void StoreScriptErrors(UUID itemId, ArrayList errors)
554 {
555 lock (m_scriptErrors)
556 {
557 // If compilation/loading initiated via CreateScriptInstance(),
558 // it does not want the errors, so just get out
559 if (!m_scriptErrors.ContainsKey(itemId))
560 {
561 return;
562 }
563
564 // Initiated via CreateScriptInstanceEr(), if we know what the
565 // errors are, save them and wake CreateScriptInstanceEr().
566 if (errors != null)
567 {
568 m_scriptErrors[itemId] = errors;
569 System.Threading.Monitor.PulseAll(m_scriptErrors);
570 return;
571 }
572 }
573
574 // Initiated via CreateScriptInstanceEr() but we don't know what
575 // the errors are yet, so retrieve them from the script engine.
576 // This may involve some waiting internal to GetScriptErrors().
577 errors = GetScriptErrors(itemId);
578
579 // Get a default non-null value to indicate success.
580 if (errors == null)
581 {
582 errors = new ArrayList();
583 }
584
585 // Post to CreateScriptInstanceEr() and wake it up
586 lock (m_scriptErrors)
587 {
588 m_scriptErrors[itemId] = errors;
589 System.Threading.Monitor.PulseAll(m_scriptErrors);
590 }
591 }
592
593 // Like StoreScriptErrors(), but just posts a single string message
594 private void StoreScriptError(UUID itemId, string message)
595 {
596 ArrayList errors = new ArrayList(1);
597 errors.Add(message);
598 StoreScriptErrors(itemId, errors);
407 } 599 }
408 600
409 /// <summary> 601 /// <summary>
@@ -416,15 +608,7 @@ namespace OpenSim.Region.Framework.Scenes
416 /// </param> 608 /// </param>
417 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted) 609 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
418 { 610 {
419 bool scriptPresent = false; 611 if (m_items.ContainsKey(itemId))
420
421 lock (m_items)
422 {
423 if (m_items.ContainsKey(itemId))
424 scriptPresent = true;
425 }
426
427 if (scriptPresent)
428 { 612 {
429 if (!sceneObjectBeingDeleted) 613 if (!sceneObjectBeingDeleted)
430 m_part.RemoveScriptEvents(itemId); 614 m_part.RemoveScriptEvents(itemId);
@@ -449,14 +633,16 @@ namespace OpenSim.Region.Framework.Scenes
449 /// <returns></returns> 633 /// <returns></returns>
450 private bool InventoryContainsName(string name) 634 private bool InventoryContainsName(string name)
451 { 635 {
452 lock (m_items) 636 m_items.LockItemsForRead(true);
637 foreach (TaskInventoryItem item in m_items.Values)
453 { 638 {
454 foreach (TaskInventoryItem item in m_items.Values) 639 if (item.Name == name)
455 { 640 {
456 if (item.Name == name) 641 m_items.LockItemsForRead(false);
457 return true; 642 return true;
458 } 643 }
459 } 644 }
645 m_items.LockItemsForRead(false);
460 return false; 646 return false;
461 } 647 }
462 648
@@ -498,8 +684,9 @@ namespace OpenSim.Region.Framework.Scenes
498 /// <param name="item"></param> 684 /// <param name="item"></param>
499 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 685 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
500 { 686 {
501 List<TaskInventoryItem> il = GetInventoryItems(); 687 m_items.LockItemsForRead(true);
502 688 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
689 m_items.LockItemsForRead(false);
503 foreach (TaskInventoryItem i in il) 690 foreach (TaskInventoryItem i in il)
504 { 691 {
505 if (i.Name == item.Name) 692 if (i.Name == item.Name)
@@ -537,14 +724,14 @@ namespace OpenSim.Region.Framework.Scenes
537 item.Name = name; 724 item.Name = name;
538 item.GroupID = m_part.GroupID; 725 item.GroupID = m_part.GroupID;
539 726
540 lock (m_items) 727 m_items.LockItemsForWrite(true);
541 m_items.Add(item.ItemID, item); 728 m_items.Add(item.ItemID, item);
542 729 m_items.LockItemsForWrite(false);
543 if (allowedDrop) 730 if (allowedDrop)
544 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 731 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
545 else 732 else
546 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 733 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
547 734
548 m_inventorySerial++; 735 m_inventorySerial++;
549 //m_inventorySerial += 2; 736 //m_inventorySerial += 2;
550 HasInventoryChanged = true; 737 HasInventoryChanged = true;
@@ -560,15 +747,15 @@ namespace OpenSim.Region.Framework.Scenes
560 /// <param name="items"></param> 747 /// <param name="items"></param>
561 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 748 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
562 { 749 {
563 lock (m_items) 750 m_items.LockItemsForWrite(true);
751 foreach (TaskInventoryItem item in items)
564 { 752 {
565 foreach (TaskInventoryItem item in items) 753 m_items.Add(item.ItemID, item);
566 { 754// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
567 m_items.Add(item.ItemID, item);
568// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
569 }
570 m_inventorySerial++;
571 } 755 }
756 m_items.LockItemsForWrite(false);
757
758 m_inventorySerial++;
572 } 759 }
573 760
574 /// <summary> 761 /// <summary>
@@ -579,10 +766,9 @@ namespace OpenSim.Region.Framework.Scenes
579 public TaskInventoryItem GetInventoryItem(UUID itemId) 766 public TaskInventoryItem GetInventoryItem(UUID itemId)
580 { 767 {
581 TaskInventoryItem item; 768 TaskInventoryItem item;
582 769 m_items.LockItemsForRead(true);
583 lock (m_items) 770 m_items.TryGetValue(itemId, out item);
584 m_items.TryGetValue(itemId, out item); 771 m_items.LockItemsForRead(false);
585
586 return item; 772 return item;
587 } 773 }
588 774
@@ -598,15 +784,16 @@ namespace OpenSim.Region.Framework.Scenes
598 { 784 {
599 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(); 785 IList<TaskInventoryItem> items = new List<TaskInventoryItem>();
600 786
601 lock (m_items) 787 m_items.LockItemsForRead(true);
788
789 foreach (TaskInventoryItem item in m_items.Values)
602 { 790 {
603 foreach (TaskInventoryItem item in m_items.Values) 791 if (item.Name == name)
604 { 792 items.Add(item);
605 if (item.Name == name)
606 items.Add(item);
607 }
608 } 793 }
609 794
795 m_items.LockItemsForRead(false);
796
610 return items; 797 return items;
611 } 798 }
612 799
@@ -625,6 +812,9 @@ namespace OpenSim.Region.Framework.Scenes
625 string xmlData = Utils.BytesToString(rezAsset.Data); 812 string xmlData = Utils.BytesToString(rezAsset.Data);
626 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 813 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
627 814
815 group.RootPart.AttachPoint = group.RootPart.Shape.State;
816 group.RootPart.AttachOffset = group.AbsolutePosition;
817
628 group.ResetIDs(); 818 group.ResetIDs();
629 819
630 SceneObjectPart rootPart = group.GetChildPart(group.UUID); 820 SceneObjectPart rootPart = group.GetChildPart(group.UUID);
@@ -699,8 +889,9 @@ namespace OpenSim.Region.Framework.Scenes
699 889
700 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged) 890 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
701 { 891 {
702 TaskInventoryItem it = GetInventoryItem(item.ItemID); 892 m_items.LockItemsForWrite(true);
703 if (it != null) 893
894 if (m_items.ContainsKey(item.ItemID))
704 { 895 {
705// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name); 896// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name);
706 897
@@ -713,14 +904,10 @@ namespace OpenSim.Region.Framework.Scenes
713 item.GroupID = m_part.GroupID; 904 item.GroupID = m_part.GroupID;
714 905
715 if (item.AssetID == UUID.Zero) 906 if (item.AssetID == UUID.Zero)
716 item.AssetID = it.AssetID; 907 item.AssetID = m_items[item.ItemID].AssetID;
717 908
718 lock (m_items) 909 m_items[item.ItemID] = item;
719 { 910 m_inventorySerial++;
720 m_items[item.ItemID] = item;
721 m_inventorySerial++;
722 }
723
724 if (fireScriptEvents) 911 if (fireScriptEvents)
725 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 912 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
726 913
@@ -729,7 +916,7 @@ namespace OpenSim.Region.Framework.Scenes
729 HasInventoryChanged = true; 916 HasInventoryChanged = true;
730 m_part.ParentGroup.HasGroupChanged = true; 917 m_part.ParentGroup.HasGroupChanged = true;
731 } 918 }
732 919 m_items.LockItemsForWrite(false);
733 return true; 920 return true;
734 } 921 }
735 else 922 else
@@ -740,8 +927,9 @@ namespace OpenSim.Region.Framework.Scenes
740 item.ItemID, m_part.Name, m_part.UUID, 927 item.ItemID, m_part.Name, m_part.UUID,
741 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 928 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
742 } 929 }
743 return false; 930 m_items.LockItemsForWrite(false);
744 931
932 return false;
745 } 933 }
746 934
747 /// <summary> 935 /// <summary>
@@ -752,43 +940,59 @@ namespace OpenSim.Region.Framework.Scenes
752 /// in this prim's inventory.</returns> 940 /// in this prim's inventory.</returns>
753 public int RemoveInventoryItem(UUID itemID) 941 public int RemoveInventoryItem(UUID itemID)
754 { 942 {
755 TaskInventoryItem item = GetInventoryItem(itemID); 943 m_items.LockItemsForRead(true);
756 if (item != null) 944
945 if (m_items.ContainsKey(itemID))
757 { 946 {
758 int type = m_items[itemID].InvType; 947 int type = m_items[itemID].InvType;
948 m_items.LockItemsForRead(false);
759 if (type == 10) // Script 949 if (type == 10) // Script
760 { 950 {
761 m_part.RemoveScriptEvents(itemID);
762 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 951 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
763 } 952 }
953 m_items.LockItemsForWrite(true);
764 m_items.Remove(itemID); 954 m_items.Remove(itemID);
955 m_items.LockItemsForWrite(false);
765 m_inventorySerial++; 956 m_inventorySerial++;
766 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 957 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
767 958
768 HasInventoryChanged = true; 959 HasInventoryChanged = true;
769 m_part.ParentGroup.HasGroupChanged = true; 960 m_part.ParentGroup.HasGroupChanged = true;
770 961
771 if (!ContainsScripts()) 962 int scriptcount = 0;
963 m_items.LockItemsForRead(true);
964 foreach (TaskInventoryItem item in m_items.Values)
965 {
966 if (item.Type == 10)
967 {
968 scriptcount++;
969 }
970 }
971 m_items.LockItemsForRead(false);
972
973
974 if (scriptcount <= 0)
975 {
772 m_part.RemFlag(PrimFlags.Scripted); 976 m_part.RemFlag(PrimFlags.Scripted);
977 }
773 978
774 m_part.ScheduleFullUpdate(); 979 m_part.ScheduleFullUpdate();
775 980
776 return type; 981 return type;
777
778 } 982 }
779 else 983 else
780 { 984 {
985 m_items.LockItemsForRead(false);
781 m_log.ErrorFormat( 986 m_log.ErrorFormat(
782 "[PRIM INVENTORY]: " + 987 "[PRIM INVENTORY]: " +
783 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", 988 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
784 itemID, m_part.Name, m_part.UUID, 989 itemID, m_part.Name, m_part.UUID);
785 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
786 } 990 }
787 991
788 return -1; 992 return -1;
789 } 993 }
790 994
791 private bool CreateInventoryFile() 995 private bool CreateInventoryFileName()
792 { 996 {
793// m_log.DebugFormat( 997// m_log.DebugFormat(
794// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}", 998// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}",
@@ -797,116 +1001,125 @@ namespace OpenSim.Region.Framework.Scenes
797 if (m_inventoryFileName == String.Empty || 1001 if (m_inventoryFileName == String.Empty ||
798 m_inventoryFileNameSerial < m_inventorySerial) 1002 m_inventoryFileNameSerial < m_inventorySerial)
799 { 1003 {
800 // Something changed, we need to create a new file
801 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp"; 1004 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp";
802 m_inventoryFileNameSerial = m_inventorySerial; 1005 m_inventoryFileNameSerial = m_inventorySerial;
803 1006
804 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); 1007 return true;
1008 }
1009
1010 return false;
1011 }
1012
1013 /// <summary>
1014 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
1015 /// </summary>
1016 /// <param name="xferManager"></param>
1017 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
1018 {
1019 bool changed = CreateInventoryFileName();
1020
1021 bool includeAssets = false;
1022 if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId))
1023 includeAssets = true;
1024
1025 if (m_inventoryPrivileged != includeAssets)
1026 changed = true;
1027
1028 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
1029
1030 Items.LockItemsForRead(true);
1031
1032 if (m_inventorySerial == 0) // No inventory
1033 {
1034 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1035 Items.LockItemsForRead(false);
1036 return;
1037 }
805 1038
806 lock (m_items) 1039 if (m_items.Count == 0) // No inventory
1040 {
1041 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1042 Items.LockItemsForRead(false);
1043 return;
1044 }
1045
1046 if (!changed)
1047 {
1048 if (m_inventoryFileData.Length > 2)
807 { 1049 {
808 foreach (TaskInventoryItem item in m_items.Values) 1050 xferManager.AddNewFile(m_inventoryFileName,
809 { 1051 m_inventoryFileData);
810// m_log.DebugFormat( 1052 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
811// "[PRIM INVENTORY]: Adding item {0} {1} for serial {2} on prim {3} {4} {5}", 1053 Util.StringToBytes256(m_inventoryFileName));
812// item.Name, item.ItemID, m_inventorySerial, m_part.Name, m_part.UUID, m_part.LocalId);
813 1054
814 UUID ownerID = item.OwnerID; 1055 Items.LockItemsForRead(false);
815 uint everyoneMask = 0; 1056 return;
816 uint baseMask = item.BasePermissions; 1057 }
817 uint ownerMask = item.CurrentPermissions; 1058 }
818 uint groupMask = item.GroupPermissions;
819 1059
820 invString.AddItemStart(); 1060 m_inventoryPrivileged = includeAssets;
821 invString.AddNameValueLine("item_id", item.ItemID.ToString());
822 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
823 1061
824 invString.AddPermissionsStart(); 1062 foreach (TaskInventoryItem item in m_items.Values)
1063 {
1064 UUID ownerID = item.OwnerID;
1065 uint everyoneMask = 0;
1066 uint baseMask = item.BasePermissions;
1067 uint ownerMask = item.CurrentPermissions;
1068 uint groupMask = item.GroupPermissions;
825 1069
826 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); 1070 invString.AddItemStart();
827 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); 1071 invString.AddNameValueLine("item_id", item.ItemID.ToString());
828 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask)); 1072 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
829 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
830 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
831 1073
832 invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); 1074 invString.AddPermissionsStart();
833 invString.AddNameValueLine("owner_id", ownerID.ToString());
834 1075
835 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); 1076 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
1077 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
1078 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
1079 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
1080 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
836 1081
837 invString.AddNameValueLine("group_id", item.GroupID.ToString()); 1082 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
838 invString.AddSectionEnd(); 1083 invString.AddNameValueLine("owner_id", ownerID.ToString());
839 1084
840 invString.AddNameValueLine("asset_id", item.AssetID.ToString()); 1085 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
841 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type));
842 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
843 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
844 1086
845 invString.AddSaleStart(); 1087 invString.AddNameValueLine("group_id", item.GroupID.ToString());
846 invString.AddNameValueLine("sale_type", "not"); 1088 invString.AddSectionEnd();
847 invString.AddNameValueLine("sale_price", "0");
848 invString.AddSectionEnd();
849 1089
850 invString.AddNameValueLine("name", item.Name + "|"); 1090 if (includeAssets)
851 invString.AddNameValueLine("desc", item.Description + "|"); 1091 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
1092 else
1093 invString.AddNameValueLine("asset_id", UUID.Zero.ToString());
1094 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type));
1095 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
1096 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
852 1097
853 invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); 1098 invString.AddSaleStart();
854 invString.AddSectionEnd(); 1099 invString.AddNameValueLine("sale_type", "not");
855 } 1100 invString.AddNameValueLine("sale_price", "0");
856 } 1101 invString.AddSectionEnd();
857 1102
858 m_inventoryFileData = Utils.StringToBytes(invString.BuildString); 1103 invString.AddNameValueLine("name", item.Name + "|");
1104 invString.AddNameValueLine("desc", item.Description + "|");
859 1105
860 return true; 1106 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
1107 invString.AddSectionEnd();
861 } 1108 }
862 1109
863 // No need to recreate, the existing file is fine 1110 Items.LockItemsForRead(false);
864 return false;
865 }
866 1111
867 /// <summary> 1112 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
868 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
869 /// </summary>
870 /// <param name="xferManager"></param>
871 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
872 {
873 lock (m_items)
874 {
875 // Don't send a inventory xfer name if there are no items. Doing so causes viewer 3 to crash when rezzing
876 // a new script if any previous deletion has left the prim inventory empty.
877 if (m_items.Count == 0) // No inventory
878 {
879// m_log.DebugFormat(
880// "[PRIM INVENTORY]: Not sending inventory data for part {0} {1} {2} for {3} since no items",
881// m_part.Name, m_part.LocalId, m_part.UUID, client.Name);
882 1113
883 client.SendTaskInventory(m_part.UUID, 0, new byte[0]); 1114 if (m_inventoryFileData.Length > 2)
884 return; 1115 {
885 } 1116 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
886 1117 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
887 CreateInventoryFile(); 1118 Util.StringToBytes256(m_inventoryFileName));
888 1119 return;
889 // In principle, we should only do the rest if the inventory changed;
890 // by sending m_inventorySerial to the client, it ought to know
891 // that nothing changed and that it doesn't need to request the file.
892 // Unfortunately, it doesn't look like the client optimizes this;
893 // the client seems to always come back and request the Xfer,
894 // no matter what value m_inventorySerial has.
895 // FIXME: Could probably be > 0 here rather than > 2
896 if (m_inventoryFileData.Length > 2)
897 {
898 // Add the file for Xfer
899 // m_log.DebugFormat(
900 // "[PRIM INVENTORY]: Adding inventory file {0} (length {1}) for transfer on {2} {3} {4}",
901 // m_inventoryFileName, m_inventoryFileData.Length, m_part.Name, m_part.UUID, m_part.LocalId);
902
903 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
904 }
905
906 // Tell the client we're ready to Xfer the file
907 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
908 Util.StringToBytes256(m_inventoryFileName));
909 } 1120 }
1121
1122 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
910 } 1123 }
911 1124
912 /// <summary> 1125 /// <summary>
@@ -915,13 +1128,19 @@ namespace OpenSim.Region.Framework.Scenes
915 /// <param name="datastore"></param> 1128 /// <param name="datastore"></param>
916 public void ProcessInventoryBackup(ISimulationDataService datastore) 1129 public void ProcessInventoryBackup(ISimulationDataService datastore)
917 { 1130 {
918 if (HasInventoryChanged) 1131// Removed this because linking will cause an immediate delete of the new
919 { 1132// child prim from the database and the subsequent storing of the prim sees
920 HasInventoryChanged = false; 1133// the inventory of it as unchanged and doesn't store it at all. The overhead
921 List<TaskInventoryItem> items = GetInventoryItems(); 1134// of storing prim inventory needlessly is much less than the aggravation
922 datastore.StorePrimInventory(m_part.UUID, items); 1135// of prim inventory loss.
1136// if (HasInventoryChanged)
1137// {
1138 Items.LockItemsForRead(true);
1139 datastore.StorePrimInventory(m_part.UUID, Items.Values);
1140 Items.LockItemsForRead(false);
923 1141
924 } 1142 HasInventoryChanged = false;
1143// }
925 } 1144 }
926 1145
927 public class InventoryStringBuilder 1146 public class InventoryStringBuilder
@@ -987,82 +1206,63 @@ namespace OpenSim.Region.Framework.Scenes
987 { 1206 {
988 uint mask=0x7fffffff; 1207 uint mask=0x7fffffff;
989 1208
990 lock (m_items) 1209 foreach (TaskInventoryItem item in m_items.Values)
991 { 1210 {
992 foreach (TaskInventoryItem item in m_items.Values) 1211 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1212 mask &= ~((uint)PermissionMask.Copy >> 13);
1213 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1214 mask &= ~((uint)PermissionMask.Transfer >> 13);
1215 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1216 mask &= ~((uint)PermissionMask.Modify >> 13);
1217
1218 if (item.InvType == (int)InventoryType.Object)
993 { 1219 {
994 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1220 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
995 mask &= ~((uint)PermissionMask.Copy >> 13); 1221 mask &= ~((uint)PermissionMask.Copy >> 13);
996 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1222 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
997 mask &= ~((uint)PermissionMask.Transfer >> 13); 1223 mask &= ~((uint)PermissionMask.Transfer >> 13);
998 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) 1224 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
999 mask &= ~((uint)PermissionMask.Modify >> 13); 1225 mask &= ~((uint)PermissionMask.Modify >> 13);
1000
1001 if (item.InvType != (int)InventoryType.Object)
1002 {
1003 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1004 mask &= ~((uint)PermissionMask.Copy >> 13);
1005 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1006 mask &= ~((uint)PermissionMask.Transfer >> 13);
1007 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1008 mask &= ~((uint)PermissionMask.Modify >> 13);
1009 }
1010 else
1011 {
1012 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1013 mask &= ~((uint)PermissionMask.Copy >> 13);
1014 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1015 mask &= ~((uint)PermissionMask.Transfer >> 13);
1016 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1017 mask &= ~((uint)PermissionMask.Modify >> 13);
1018 }
1019
1020 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1021 mask &= ~(uint)PermissionMask.Copy;
1022 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1023 mask &= ~(uint)PermissionMask.Transfer;
1024 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1025 mask &= ~(uint)PermissionMask.Modify;
1026 } 1226 }
1227
1228 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1229 mask &= ~(uint)PermissionMask.Copy;
1230 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1231 mask &= ~(uint)PermissionMask.Transfer;
1232 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1233 mask &= ~(uint)PermissionMask.Modify;
1027 } 1234 }
1028
1029 return mask; 1235 return mask;
1030 } 1236 }
1031 1237
1032 public void ApplyNextOwnerPermissions() 1238 public void ApplyNextOwnerPermissions()
1033 { 1239 {
1034 lock (m_items) 1240 foreach (TaskInventoryItem item in m_items.Values)
1035 { 1241 {
1036 foreach (TaskInventoryItem item in m_items.Values) 1242 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
1037 { 1243 {
1038 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) 1244 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1039 { 1245 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
1040 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) 1246 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1041 item.CurrentPermissions &= ~(uint)PermissionMask.Copy; 1247 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
1042 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) 1248 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1043 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; 1249 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1044 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1045 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1046 }
1047 item.CurrentPermissions &= item.NextPermissions;
1048 item.BasePermissions &= item.NextPermissions;
1049 item.EveryonePermissions &= item.NextPermissions;
1050 item.OwnerChanged = true;
1051 item.PermsMask = 0;
1052 item.PermsGranter = UUID.Zero;
1053 } 1250 }
1251 item.OwnerChanged = true;
1252 item.CurrentPermissions &= item.NextPermissions;
1253 item.BasePermissions &= item.NextPermissions;
1254 item.EveryonePermissions &= item.NextPermissions;
1255 item.PermsMask = 0;
1256 item.PermsGranter = UUID.Zero;
1054 } 1257 }
1055 } 1258 }
1056 1259
1057 public void ApplyGodPermissions(uint perms) 1260 public void ApplyGodPermissions(uint perms)
1058 { 1261 {
1059 lock (m_items) 1262 foreach (TaskInventoryItem item in m_items.Values)
1060 { 1263 {
1061 foreach (TaskInventoryItem item in m_items.Values) 1264 item.CurrentPermissions = perms;
1062 { 1265 item.BasePermissions = perms;
1063 item.CurrentPermissions = perms;
1064 item.BasePermissions = perms;
1065 }
1066 } 1266 }
1067 1267
1068 m_inventorySerial++; 1268 m_inventorySerial++;
@@ -1075,17 +1275,13 @@ namespace OpenSim.Region.Framework.Scenes
1075 /// <returns></returns> 1275 /// <returns></returns>
1076 public bool ContainsScripts() 1276 public bool ContainsScripts()
1077 { 1277 {
1078 lock (m_items) 1278 foreach (TaskInventoryItem item in m_items.Values)
1079 { 1279 {
1080 foreach (TaskInventoryItem item in m_items.Values) 1280 if (item.InvType == (int)InventoryType.LSL)
1081 { 1281 {
1082 if (item.InvType == (int)InventoryType.LSL) 1282 return true;
1083 {
1084 return true;
1085 }
1086 } 1283 }
1087 } 1284 }
1088
1089 return false; 1285 return false;
1090 } 1286 }
1091 1287
@@ -1093,11 +1289,8 @@ namespace OpenSim.Region.Framework.Scenes
1093 { 1289 {
1094 List<UUID> ret = new List<UUID>(); 1290 List<UUID> ret = new List<UUID>();
1095 1291
1096 lock (m_items) 1292 foreach (TaskInventoryItem item in m_items.Values)
1097 { 1293 ret.Add(item.ItemID);
1098 foreach (TaskInventoryItem item in m_items.Values)
1099 ret.Add(item.ItemID);
1100 }
1101 1294
1102 return ret; 1295 return ret;
1103 } 1296 }
@@ -1128,6 +1321,11 @@ namespace OpenSim.Region.Framework.Scenes
1128 1321
1129 public Dictionary<UUID, string> GetScriptStates() 1322 public Dictionary<UUID, string> GetScriptStates()
1130 { 1323 {
1324 return GetScriptStates(false);
1325 }
1326
1327 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1328 {
1131 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1329 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1132 1330
1133 if (m_part.ParentGroup.Scene == null) // Group not in a scene 1331 if (m_part.ParentGroup.Scene == null) // Group not in a scene
@@ -1138,25 +1336,35 @@ namespace OpenSim.Region.Framework.Scenes
1138 if (engines.Length == 0) // No engine at all 1336 if (engines.Length == 0) // No engine at all
1139 return ret; 1337 return ret;
1140 1338
1141 List<TaskInventoryItem> scripts = GetInventoryScripts(); 1339 Items.LockItemsForRead(true);
1142 1340 foreach (TaskInventoryItem item in m_items.Values)
1143 foreach (TaskInventoryItem item in scripts)
1144 { 1341 {
1145 foreach (IScriptModule e in engines) 1342 if (item.InvType == (int)InventoryType.LSL)
1146 { 1343 {
1147 if (e != null) 1344 foreach (IScriptModule e in engines)
1148 { 1345 {
1149 string n = e.GetXMLState(item.ItemID); 1346 if (e != null)
1150 if (n != String.Empty)
1151 { 1347 {
1152 if (!ret.ContainsKey(item.ItemID)) 1348 string n = e.GetXMLState(item.ItemID);
1153 ret[item.ItemID] = n; 1349 if (n != String.Empty)
1154 break; 1350 {
1351 if (oldIDs)
1352 {
1353 if (!ret.ContainsKey(item.OldItemID))
1354 ret[item.OldItemID] = n;
1355 }
1356 else
1357 {
1358 if (!ret.ContainsKey(item.ItemID))
1359 ret[item.ItemID] = n;
1360 }
1361 break;
1362 }
1155 } 1363 }
1156 } 1364 }
1157 } 1365 }
1158 } 1366 }
1159 1367 Items.LockItemsForRead(false);
1160 return ret; 1368 return ret;
1161 } 1369 }
1162 1370
@@ -1166,21 +1374,27 @@ namespace OpenSim.Region.Framework.Scenes
1166 if (engines.Length == 0) 1374 if (engines.Length == 0)
1167 return; 1375 return;
1168 1376
1169 List<TaskInventoryItem> scripts = GetInventoryScripts();
1170 1377
1171 foreach (TaskInventoryItem item in scripts) 1378 Items.LockItemsForRead(true);
1379
1380 foreach (TaskInventoryItem item in m_items.Values)
1172 { 1381 {
1173 foreach (IScriptModule engine in engines) 1382 if (item.InvType == (int)InventoryType.LSL)
1174 { 1383 {
1175 if (engine != null) 1384 foreach (IScriptModule engine in engines)
1176 { 1385 {
1177 if (item.OwnerChanged) 1386 if (engine != null)
1178 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER }); 1387 {
1179 item.OwnerChanged = false; 1388 if (item.OwnerChanged)
1180 engine.ResumeScript(item.ItemID); 1389 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER });
1390 item.OwnerChanged = false;
1391 engine.ResumeScript(item.ItemID);
1392 }
1181 } 1393 }
1182 } 1394 }
1183 } 1395 }
1396
1397 Items.LockItemsForRead(false);
1184 } 1398 }
1185 } 1399 }
1186} 1400}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 5c56150..c7c90da 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -168,6 +168,7 @@ namespace OpenSim.Region.Framework.Scenes
168// private int m_lastColCount = -1; //KF: Look for Collision chnages 168// private int m_lastColCount = -1; //KF: Look for Collision chnages
169// private int m_updateCount = 0; //KF: Update Anims for a while 169// private int m_updateCount = 0; //KF: Update Anims for a while
170// private static readonly int UPDATE_COUNT = 10; // how many frames to update for 170// private static readonly int UPDATE_COUNT = 10; // how many frames to update for
171 private List<uint> m_lastColliders = new List<uint>();
171 172
172 private TeleportFlags m_teleportFlags; 173 private TeleportFlags m_teleportFlags;
173 public TeleportFlags TeleportFlags 174 public TeleportFlags TeleportFlags
@@ -229,6 +230,9 @@ namespace OpenSim.Region.Framework.Scenes
229 //private int m_moveToPositionStateStatus; 230 //private int m_moveToPositionStateStatus;
230 //***************************************************** 231 //*****************************************************
231 232
233 private bool m_collisionEventFlag = false;
234 private object m_collisionEventLock = new Object();
235
232 protected AvatarAppearance m_appearance; 236 protected AvatarAppearance m_appearance;
233 237
234 public AvatarAppearance Appearance 238 public AvatarAppearance Appearance
@@ -1751,9 +1755,9 @@ namespace OpenSim.Region.Framework.Scenes
1751 if (pos.Z - terrainHeight < 0.2) 1755 if (pos.Z - terrainHeight < 0.2)
1752 pos.Z = terrainHeight; 1756 pos.Z = terrainHeight;
1753 1757
1754 m_log.DebugFormat( 1758// m_log.DebugFormat(
1755 "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}", 1759// "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}",
1756 Name, pos, terrainHeight, m_scene.RegionInfo.RegionName); 1760// Name, pos, terrainHeight, m_scene.RegionInfo.RegionName);
1757 1761
1758 if (noFly) 1762 if (noFly)
1759 Flying = false; 1763 Flying = false;
@@ -1837,6 +1841,7 @@ namespace OpenSim.Region.Framework.Scenes
1837 if (part.SitTargetAvatar == UUID) 1841 if (part.SitTargetAvatar == UUID)
1838 part.SitTargetAvatar = UUID.Zero; 1842 part.SitTargetAvatar = UUID.Zero;
1839 1843
1844 part.ParentGroup.DeleteAvatar(UUID);
1840 ParentPosition = part.GetWorldPosition(); 1845 ParentPosition = part.GetWorldPosition();
1841 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1846 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1842 } 1847 }
@@ -1975,7 +1980,7 @@ namespace OpenSim.Region.Framework.Scenes
1975 forceMouselook = part.GetForceMouselook(); 1980 forceMouselook = part.GetForceMouselook();
1976 1981
1977 ControllingClient.SendSitResponse( 1982 ControllingClient.SendSitResponse(
1978 targetID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); 1983 part.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
1979 1984
1980 m_requestedSitTargetUUID = targetID; 1985 m_requestedSitTargetUUID = targetID;
1981 1986
@@ -2260,11 +2265,13 @@ namespace OpenSim.Region.Framework.Scenes
2260 m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT; 2265 m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT;
2261 Rotation = sitTargetOrient; 2266 Rotation = sitTargetOrient;
2262 ParentPosition = part.AbsolutePosition; 2267 ParentPosition = part.AbsolutePosition;
2268 part.ParentGroup.AddAvatar(UUID);
2263 } 2269 }
2264 else 2270 else
2265 { 2271 {
2266 m_pos -= part.AbsolutePosition; 2272 m_pos -= part.AbsolutePosition;
2267 ParentPosition = part.AbsolutePosition; 2273 ParentPosition = part.AbsolutePosition;
2274 part.ParentGroup.AddAvatar(UUID);
2268 2275
2269// m_log.DebugFormat( 2276// m_log.DebugFormat(
2270// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", 2277// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target",
@@ -3370,6 +3377,8 @@ namespace OpenSim.Region.Framework.Scenes
3370 } 3377 }
3371 } 3378 }
3372 3379
3380 RaiseCollisionScriptEvents(coldata);
3381
3373 if (Invulnerable) 3382 if (Invulnerable)
3374 return; 3383 return;
3375 3384
@@ -3881,6 +3890,12 @@ namespace OpenSim.Region.Framework.Scenes
3881 3890
3882 private void CheckAndAdjustLandingPoint(ref Vector3 pos) 3891 private void CheckAndAdjustLandingPoint(ref Vector3 pos)
3883 { 3892 {
3893 string reason;
3894
3895 // Honor bans
3896 if (!m_scene.TestLandRestrictions(UUID, out reason, ref pos.X, ref pos.Y))
3897 return;
3898
3884 SceneObjectGroup telehub = null; 3899 SceneObjectGroup telehub = null;
3885 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null) 3900 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null)
3886 { 3901 {
@@ -3920,11 +3935,173 @@ namespace OpenSim.Region.Framework.Scenes
3920 pos = land.LandData.UserLocation; 3935 pos = land.LandData.UserLocation;
3921 } 3936 }
3922 } 3937 }
3923 3938
3924 land.SendLandUpdateToClient(ControllingClient); 3939 land.SendLandUpdateToClient(ControllingClient);
3925 } 3940 }
3926 } 3941 }
3927 3942
3943 private void RaiseCollisionScriptEvents(Dictionary<uint, ContactPoint> coldata)
3944 {
3945 lock(m_collisionEventLock)
3946 {
3947 if (m_collisionEventFlag)
3948 return;
3949 m_collisionEventFlag = true;
3950 }
3951
3952 Util.FireAndForget(delegate(object x)
3953 {
3954 try
3955 {
3956 List<uint> thisHitColliders = new List<uint>();
3957 List<uint> endedColliders = new List<uint>();
3958 List<uint> startedColliders = new List<uint>();
3959
3960 foreach (uint localid in coldata.Keys)
3961 {
3962 thisHitColliders.Add(localid);
3963 if (!m_lastColliders.Contains(localid))
3964 {
3965 startedColliders.Add(localid);
3966 }
3967 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
3968 }
3969
3970 // calculate things that ended colliding
3971 foreach (uint localID in m_lastColliders)
3972 {
3973 if (!thisHitColliders.Contains(localID))
3974 {
3975 endedColliders.Add(localID);
3976 }
3977 }
3978 //add the items that started colliding this time to the last colliders list.
3979 foreach (uint localID in startedColliders)
3980 {
3981 m_lastColliders.Add(localID);
3982 }
3983 // remove things that ended colliding from the last colliders list
3984 foreach (uint localID in endedColliders)
3985 {
3986 m_lastColliders.Remove(localID);
3987 }
3988
3989 // do event notification
3990 if (startedColliders.Count > 0)
3991 {
3992 ColliderArgs StartCollidingMessage = new ColliderArgs();
3993 List<DetectedObject> colliding = new List<DetectedObject>();
3994 foreach (uint localId in startedColliders)
3995 {
3996 if (localId == 0)
3997 continue;
3998
3999 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
4000 string data = "";
4001 if (obj != null)
4002 {
4003 DetectedObject detobj = new DetectedObject();
4004 detobj.keyUUID = obj.UUID;
4005 detobj.nameStr = obj.Name;
4006 detobj.ownerUUID = obj.OwnerID;
4007 detobj.posVector = obj.AbsolutePosition;
4008 detobj.rotQuat = obj.GetWorldRotation();
4009 detobj.velVector = obj.Velocity;
4010 detobj.colliderType = 0;
4011 detobj.groupUUID = obj.GroupID;
4012 colliding.Add(detobj);
4013 }
4014 }
4015
4016 if (colliding.Count > 0)
4017 {
4018 StartCollidingMessage.Colliders = colliding;
4019
4020 foreach (SceneObjectGroup att in GetAttachments())
4021 Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage);
4022 }
4023 }
4024
4025 if (endedColliders.Count > 0)
4026 {
4027 ColliderArgs EndCollidingMessage = new ColliderArgs();
4028 List<DetectedObject> colliding = new List<DetectedObject>();
4029 foreach (uint localId in endedColliders)
4030 {
4031 if (localId == 0)
4032 continue;
4033
4034 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
4035 string data = "";
4036 if (obj != null)
4037 {
4038 DetectedObject detobj = new DetectedObject();
4039 detobj.keyUUID = obj.UUID;
4040 detobj.nameStr = obj.Name;
4041 detobj.ownerUUID = obj.OwnerID;
4042 detobj.posVector = obj.AbsolutePosition;
4043 detobj.rotQuat = obj.GetWorldRotation();
4044 detobj.velVector = obj.Velocity;
4045 detobj.colliderType = 0;
4046 detobj.groupUUID = obj.GroupID;
4047 colliding.Add(detobj);
4048 }
4049 }
4050
4051 if (colliding.Count > 0)
4052 {
4053 EndCollidingMessage.Colliders = colliding;
4054
4055 foreach (SceneObjectGroup att in GetAttachments())
4056 Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage);
4057 }
4058 }
4059
4060 if (thisHitColliders.Count > 0)
4061 {
4062 ColliderArgs CollidingMessage = new ColliderArgs();
4063 List<DetectedObject> colliding = new List<DetectedObject>();
4064 foreach (uint localId in thisHitColliders)
4065 {
4066 if (localId == 0)
4067 continue;
4068
4069 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
4070 string data = "";
4071 if (obj != null)
4072 {
4073 DetectedObject detobj = new DetectedObject();
4074 detobj.keyUUID = obj.UUID;
4075 detobj.nameStr = obj.Name;
4076 detobj.ownerUUID = obj.OwnerID;
4077 detobj.posVector = obj.AbsolutePosition;
4078 detobj.rotQuat = obj.GetWorldRotation();
4079 detobj.velVector = obj.Velocity;
4080 detobj.colliderType = 0;
4081 detobj.groupUUID = obj.GroupID;
4082 colliding.Add(detobj);
4083 }
4084 }
4085
4086 if (colliding.Count > 0)
4087 {
4088 CollidingMessage.Colliders = colliding;
4089
4090 lock (m_attachments)
4091 {
4092 foreach (SceneObjectGroup att in m_attachments)
4093 Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
4094 }
4095 }
4096 }
4097 }
4098 finally
4099 {
4100 m_collisionEventFlag = false;
4101 }
4102 });
4103 }
4104
3928 private void TeleportFlagsDebug() { 4105 private void TeleportFlagsDebug() {
3929 4106
3930 // Some temporary debugging help to show all the TeleportFlags we have... 4107 // Some temporary debugging help to show all the TeleportFlags we have...
@@ -3949,6 +4126,5 @@ namespace OpenSim.Region.Framework.Scenes
3949 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); 4126 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************");
3950 4127
3951 } 4128 }
3952
3953 } 4129 }
3954} 4130}
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index b54fcb7..6303cb1 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -345,6 +345,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
345 m_SOPXmlProcessors.Add("PayPrice2", ProcessPayPrice2); 345 m_SOPXmlProcessors.Add("PayPrice2", ProcessPayPrice2);
346 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3); 346 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3);
347 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4); 347 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4);
348
349 m_SOPXmlProcessors.Add("Buoyancy", ProcessBuoyancy);
350 m_SOPXmlProcessors.Add("VolumeDetectActive", ProcessVolumeDetectActive);
348 #endregion 351 #endregion
349 352
350 #region TaskInventoryXmlProcessors initialization 353 #region TaskInventoryXmlProcessors initialization
@@ -729,6 +732,16 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
729 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty); 732 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty);
730 } 733 }
731 734
735 private static void ProcessBuoyancy(SceneObjectPart obj, XmlTextReader reader)
736 {
737 obj.Buoyancy = (int)reader.ReadElementContentAsFloat("Buoyancy", String.Empty);
738 }
739
740 private static void ProcessVolumeDetectActive(SceneObjectPart obj, XmlTextReader reader)
741 {
742 obj.VolumeDetectActive = Util.ReadBoolean(reader);
743 }
744
732 #endregion 745 #endregion
733 746
734 #region TaskInventoryXmlProcessors 747 #region TaskInventoryXmlProcessors
@@ -1214,6 +1227,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1214 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString()); 1227 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString());
1215 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString()); 1228 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString());
1216 1229
1230 writer.WriteElementString("Buoyancy", sop.Buoyancy.ToString());
1231 writer.WriteElementString("VolumeDetectActive", sop.VolumeDetectActive.ToString().ToLower());
1232
1217 writer.WriteEndElement(); 1233 writer.WriteEndElement();
1218 } 1234 }
1219 1235
@@ -1503,12 +1519,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1503 { 1519 {
1504 TaskInventoryDictionary tinv = new TaskInventoryDictionary(); 1520 TaskInventoryDictionary tinv = new TaskInventoryDictionary();
1505 1521
1506 if (reader.IsEmptyElement)
1507 {
1508 reader.Read();
1509 return tinv;
1510 }
1511
1512 reader.ReadStartElement(name, String.Empty); 1522 reader.ReadStartElement(name, String.Empty);
1513 1523
1514 while (reader.Name == "TaskInventoryItem") 1524 while (reader.Name == "TaskInventoryItem")
@@ -1551,12 +1561,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1551 1561
1552 PrimitiveBaseShape shape = new PrimitiveBaseShape(); 1562 PrimitiveBaseShape shape = new PrimitiveBaseShape();
1553 1563
1554 if (reader.IsEmptyElement)
1555 {
1556 reader.Read();
1557 return shape;
1558 }
1559
1560 reader.ReadStartElement(name, String.Empty); // Shape 1564 reader.ReadStartElement(name, String.Empty); // Shape
1561 1565
1562 string nodeName = string.Empty; 1566 string nodeName = string.Empty;
diff --git a/OpenSim/Region/Framework/Scenes/UndoState.cs b/OpenSim/Region/Framework/Scenes/UndoState.cs
index 860172c..5ed3c79 100644
--- a/OpenSim/Region/Framework/Scenes/UndoState.cs
+++ b/OpenSim/Region/Framework/Scenes/UndoState.cs
@@ -30,12 +30,27 @@ using System.Reflection;
30using log4net; 30using log4net;
31using OpenMetaverse; 31using OpenMetaverse;
32using OpenSim.Region.Framework.Interfaces; 32using OpenSim.Region.Framework.Interfaces;
33using System;
33 34
34namespace OpenSim.Region.Framework.Scenes 35namespace OpenSim.Region.Framework.Scenes
35{ 36{
37 [Flags]
38 public enum UndoType
39 {
40 STATE_PRIM_POSITION = 1,
41 STATE_PRIM_ROTATION = 2,
42 STATE_PRIM_SCALE = 4,
43 STATE_PRIM_ALL = 7,
44 STATE_GROUP_POSITION = 8,
45 STATE_GROUP_ROTATION = 16,
46 STATE_GROUP_SCALE = 32,
47 STATE_GROUP_ALL = 56,
48 STATE_ALL = 63
49 }
50
36 public class UndoState 51 public class UndoState
37 { 52 {
38// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 53 // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
39 54
40 public Vector3 Position = Vector3.Zero; 55 public Vector3 Position = Vector3.Zero;
41 public Vector3 Scale = Vector3.Zero; 56 public Vector3 Scale = Vector3.Zero;
@@ -57,37 +72,37 @@ namespace OpenSim.Region.Framework.Scenes
57 { 72 {
58 ForGroup = forGroup; 73 ForGroup = forGroup;
59 74
60// if (ForGroup) 75 // if (ForGroup)
61 Position = part.ParentGroup.AbsolutePosition; 76 Position = part.ParentGroup.AbsolutePosition;
62// else 77 // else
63// Position = part.OffsetPosition; 78 // Position = part.OffsetPosition;
64 79
65// m_log.DebugFormat( 80 // m_log.DebugFormat(
66// "[UNDO STATE]: Storing undo position {0} for root part", Position); 81 // "[UNDO STATE]: Storing undo position {0} for root part", Position);
67 82
68 Rotation = part.RotationOffset; 83 Rotation = part.RotationOffset;
69 84
70// m_log.DebugFormat( 85 // m_log.DebugFormat(
71// "[UNDO STATE]: Storing undo rotation {0} for root part", Rotation); 86 // "[UNDO STATE]: Storing undo rotation {0} for root part", Rotation);
72 87
73 Scale = part.Shape.Scale; 88 Scale = part.Shape.Scale;
74 89
75// m_log.DebugFormat( 90 // m_log.DebugFormat(
76// "[UNDO STATE]: Storing undo scale {0} for root part", Scale); 91 // "[UNDO STATE]: Storing undo scale {0} for root part", Scale);
77 } 92 }
78 else 93 else
79 { 94 {
80 Position = part.OffsetPosition; 95 Position = part.OffsetPosition;
81// m_log.DebugFormat( 96 // m_log.DebugFormat(
82// "[UNDO STATE]: Storing undo position {0} for child part", Position); 97 // "[UNDO STATE]: Storing undo position {0} for child part", Position);
83 98
84 Rotation = part.RotationOffset; 99 Rotation = part.RotationOffset;
85// m_log.DebugFormat( 100 // m_log.DebugFormat(
86// "[UNDO STATE]: Storing undo rotation {0} for child part", Rotation); 101 // "[UNDO STATE]: Storing undo rotation {0} for child part", Rotation);
87 102
88 Scale = part.Shape.Scale; 103 Scale = part.Shape.Scale;
89// m_log.DebugFormat( 104 // m_log.DebugFormat(
90// "[UNDO STATE]: Storing undo scale {0} for child part", Scale); 105 // "[UNDO STATE]: Storing undo scale {0} for child part", Scale);
91 } 106 }
92 } 107 }
93 108
@@ -121,9 +136,9 @@ namespace OpenSim.Region.Framework.Scenes
121 136
122 if (part.ParentID == 0) 137 if (part.ParentID == 0)
123 { 138 {
124// m_log.DebugFormat( 139 // m_log.DebugFormat(
125// "[UNDO STATE]: Undoing position to {0} for root part {1} {2}", 140 // "[UNDO STATE]: Undoing position to {0} for root part {1} {2}",
126// Position, part.Name, part.LocalId); 141 // Position, part.Name, part.LocalId);
127 142
128 if (Position != Vector3.Zero) 143 if (Position != Vector3.Zero)
129 { 144 {
@@ -133,9 +148,9 @@ namespace OpenSim.Region.Framework.Scenes
133 part.ParentGroup.UpdateRootPosition(Position); 148 part.ParentGroup.UpdateRootPosition(Position);
134 } 149 }
135 150
136// m_log.DebugFormat( 151 // m_log.DebugFormat(
137// "[UNDO STATE]: Undoing rotation {0} to {1} for root part {2} {3}", 152 // "[UNDO STATE]: Undoing rotation {0} to {1} for root part {2} {3}",
138// part.RotationOffset, Rotation, part.Name, part.LocalId); 153 // part.RotationOffset, Rotation, part.Name, part.LocalId);
139 154
140 if (ForGroup) 155 if (ForGroup)
141 part.UpdateRotation(Rotation); 156 part.UpdateRotation(Rotation);
@@ -144,9 +159,9 @@ namespace OpenSim.Region.Framework.Scenes
144 159
145 if (Scale != Vector3.Zero) 160 if (Scale != Vector3.Zero)
146 { 161 {
147// m_log.DebugFormat( 162 // m_log.DebugFormat(
148// "[UNDO STATE]: Undoing scale {0} to {1} for root part {2} {3}", 163 // "[UNDO STATE]: Undoing scale {0} to {1} for root part {2} {3}",
149// part.Shape.Scale, Scale, part.Name, part.LocalId); 164 // part.Shape.Scale, Scale, part.Name, part.LocalId);
150 165
151 if (ForGroup) 166 if (ForGroup)
152 part.ParentGroup.GroupResize(Scale); 167 part.ParentGroup.GroupResize(Scale);
@@ -161,24 +176,24 @@ namespace OpenSim.Region.Framework.Scenes
161 // Note: Updating these properties on sop automatically schedules an update if needed 176 // Note: Updating these properties on sop automatically schedules an update if needed
162 if (Position != Vector3.Zero) 177 if (Position != Vector3.Zero)
163 { 178 {
164// m_log.DebugFormat( 179 // m_log.DebugFormat(
165// "[UNDO STATE]: Undoing position {0} to {1} for child part {2} {3}", 180 // "[UNDO STATE]: Undoing position {0} to {1} for child part {2} {3}",
166// part.OffsetPosition, Position, part.Name, part.LocalId); 181 // part.OffsetPosition, Position, part.Name, part.LocalId);
167 182
168 part.OffsetPosition = Position; 183 part.OffsetPosition = Position;
169 } 184 }
170 185
171// m_log.DebugFormat( 186 // m_log.DebugFormat(
172// "[UNDO STATE]: Undoing rotation {0} to {1} for child part {2} {3}", 187 // "[UNDO STATE]: Undoing rotation {0} to {1} for child part {2} {3}",
173// part.RotationOffset, Rotation, part.Name, part.LocalId); 188 // part.RotationOffset, Rotation, part.Name, part.LocalId);
174 189
175 part.UpdateRotation(Rotation); 190 part.UpdateRotation(Rotation);
176 191
177 if (Scale != Vector3.Zero) 192 if (Scale != Vector3.Zero)
178 { 193 {
179// m_log.DebugFormat( 194 // m_log.DebugFormat(
180// "[UNDO STATE]: Undoing scale {0} to {1} for child part {2} {3}", 195 // "[UNDO STATE]: Undoing scale {0} to {1} for child part {2} {3}",
181// part.Shape.Scale, Scale, part.Name, part.LocalId); 196 // part.Shape.Scale, Scale, part.Name, part.LocalId);
182 197
183 part.Resize(Scale); 198 part.Resize(Scale);
184 } 199 }
@@ -247,4 +262,4 @@ namespace OpenSim.Region.Framework.Scenes
247 m_terrainModule.UndoTerrain(m_terrainChannel); 262 m_terrainModule.UndoTerrain(m_terrainChannel);
248 } 263 }
249 } 264 }
250} \ No newline at end of file 265}
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index efb68a2..411e421 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -87,10 +87,6 @@ namespace OpenSim.Region.Framework.Scenes
87 /// <param name="assetUuids">The assets gathered</param> 87 /// <param name="assetUuids">The assets gathered</param>
88 public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids) 88 public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids)
89 { 89 {
90 // avoid infinite loops
91 if (assetUuids.ContainsKey(assetUuid))
92 return;
93
94 try 90 try
95 { 91 {
96 assetUuids[assetUuid] = assetType; 92 assetUuids[assetUuid] = assetType;
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index bbf3729..d4d0ad7 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -818,6 +818,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
818 public event ObjectOwner OnObjectOwner; 818 public event ObjectOwner OnObjectOwner;
819 public event DirPlacesQuery OnDirPlacesQuery; 819 public event DirPlacesQuery OnDirPlacesQuery;
820 public event DirFindQuery OnDirFindQuery; 820 public event DirFindQuery OnDirFindQuery;
821 public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy;
821 public event DirLandQuery OnDirLandQuery; 822 public event DirLandQuery OnDirLandQuery;
822 public event DirPopularQuery OnDirPopularQuery; 823 public event DirPopularQuery OnDirPopularQuery;
823 public event DirClassifiedQuery OnDirClassifiedQuery; 824 public event DirClassifiedQuery OnDirClassifiedQuery;
@@ -834,7 +835,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
834 public event ClassifiedInfoRequest OnClassifiedInfoRequest; 835 public event ClassifiedInfoRequest OnClassifiedInfoRequest;
835 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate; 836 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate;
836 public event ClassifiedDelete OnClassifiedDelete; 837 public event ClassifiedDelete OnClassifiedDelete;
837 public event ClassifiedDelete OnClassifiedGodDelete; 838 public event ClassifiedGodDelete OnClassifiedGodDelete;
838 public event EventNotificationAddRequest OnEventNotificationAddRequest; 839 public event EventNotificationAddRequest OnEventNotificationAddRequest;
839 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest; 840 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest;
840 public event EventGodDelete OnEventGodDelete; 841 public event EventGodDelete OnEventGodDelete;
@@ -864,6 +865,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
864 public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest; 865 public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest;
865 public event SimWideDeletesDelegate OnSimWideDeletes; 866 public event SimWideDeletesDelegate OnSimWideDeletes;
866 public event SendPostcard OnSendPostcard; 867 public event SendPostcard OnSendPostcard;
868 public event ChangeInventoryItemFlags OnChangeInventoryItemFlags;
867 public event MuteListEntryUpdate OnUpdateMuteListEntry; 869 public event MuteListEntryUpdate OnUpdateMuteListEntry;
868 public event MuteListEntryRemove OnRemoveMuteListEntry; 870 public event MuteListEntryRemove OnRemoveMuteListEntry;
869 public event GodlikeMessage onGodlikeMessage; 871 public event GodlikeMessage onGodlikeMessage;
@@ -885,6 +887,11 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
885 887
886 public void Close() 888 public void Close()
887 { 889 {
890 Close(true);
891 }
892
893 public void Close(bool sendStop)
894 {
888 Disconnect(); 895 Disconnect();
889 } 896 }
890 897
diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
index 5323a95..1b675a6 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
@@ -563,7 +563,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
563 563
564 public Hashtable FreeSwitchSLVoiceGetPreloginHTTPHandler(Hashtable request) 564 public Hashtable FreeSwitchSLVoiceGetPreloginHTTPHandler(Hashtable request)
565 { 565 {
566 m_log.Debug("[FreeSwitchVoice]: FreeSwitchSLVoiceGetPreloginHTTPHandler called"); 566// m_log.Debug("[FreeSwitchVoice] FreeSwitchSLVoiceGetPreloginHTTPHandler called");
567 567
568 Hashtable response = new Hashtable(); 568 Hashtable response = new Hashtable();
569 response["content_type"] = "text/xml"; 569 response["content_type"] = "text/xml";
@@ -714,7 +714,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
714 714
715 public Hashtable FreeSwitchSLVoiceSigninHTTPHandler(Hashtable request) 715 public Hashtable FreeSwitchSLVoiceSigninHTTPHandler(Hashtable request)
716 { 716 {
717 m_log.Debug("[FreeSwitchVoice]: FreeSwitchSLVoiceSigninHTTPHandler called"); 717 //m_log.Debug("[FreeSwitchVoice] FreeSwitchSLVoiceSigninHTTPHandler called");
718// string requestbody = (string)request["body"]; 718// string requestbody = (string)request["body"];
719// string uri = (string)request["uri"]; 719// string uri = (string)request["uri"];
720// string contenttype = (string)request["content-type"]; 720// string contenttype = (string)request["content-type"];
diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
index 70e2f7e..0be0a19 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
@@ -190,7 +190,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
190 break; 190 break;
191 } 191 }
192 192
193 m_vivoxVoiceAccountApi = String.Format("http://{0}/api2", m_vivoxServer); 193 m_vivoxVoiceAccountApi = String.Format("https://{0}/api2", m_vivoxServer);
194 194
195 // Admin interface required values 195 // Admin interface required values
196 if (String.IsNullOrEmpty(m_vivoxServer) || 196 if (String.IsNullOrEmpty(m_vivoxServer) ||
@@ -749,7 +749,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
749 } 749 }
750 750
751 751
752 private static readonly string m_vivoxLoginPath = "http://{0}/api2/viv_signin.php?userid={1}&pwd={2}"; 752 private static readonly string m_vivoxLoginPath = "https://{0}/api2/viv_signin.php?userid={1}&pwd={2}";
753 753
754 /// <summary> 754 /// <summary>
755 /// Perform administrative login for Vivox. 755 /// Perform administrative login for Vivox.
@@ -762,7 +762,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
762 } 762 }
763 763
764 764
765 private static readonly string m_vivoxLogoutPath = "http://{0}/api2/viv_signout.php?auth_token={1}"; 765 private static readonly string m_vivoxLogoutPath = "https://{0}/api2/viv_signout.php?auth_token={1}";
766 766
767 /// <summary> 767 /// <summary>
768 /// Perform administrative logout for Vivox. 768 /// Perform administrative logout for Vivox.
@@ -774,7 +774,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
774 } 774 }
775 775
776 776
777 private static readonly string m_vivoxGetAccountPath = "http://{0}/api2/viv_get_acct.php?auth_token={1}&user_name={2}"; 777 private static readonly string m_vivoxGetAccountPath = "https://{0}/api2/viv_get_acct.php?auth_token={1}&user_name={2}";
778 778
779 /// <summary> 779 /// <summary>
780 /// Retrieve account information for the specified user. 780 /// Retrieve account information for the specified user.
@@ -787,7 +787,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
787 } 787 }
788 788
789 789
790 private static readonly string m_vivoxNewAccountPath = "http://{0}/api2/viv_adm_acct_new.php?username={1}&pwd={2}&auth_token={3}"; 790 private static readonly string m_vivoxNewAccountPath = "https://{0}/api2/viv_adm_acct_new.php?username={1}&pwd={2}&auth_token={3}";
791 791
792 /// <summary> 792 /// <summary>
793 /// Creates a new account. 793 /// Creates a new account.
@@ -802,7 +802,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
802 } 802 }
803 803
804 804
805 private static readonly string m_vivoxPasswordPath = "http://{0}/api2/viv_adm_password.php?user_name={1}&new_pwd={2}&auth_token={3}"; 805 private static readonly string m_vivoxPasswordPath = "https://{0}/api2/viv_adm_password.php?user_name={1}&new_pwd={2}&auth_token={3}";
806 806
807 /// <summary> 807 /// <summary>
808 /// Change the user's password. 808 /// Change the user's password.
@@ -814,7 +814,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
814 } 814 }
815 815
816 816
817 private static readonly string m_vivoxChannelPath = "http://{0}/api2/viv_chan_mod.php?mode={1}&chan_name={2}&auth_token={3}"; 817 private static readonly string m_vivoxChannelPath = "https://{0}/api2/viv_chan_mod.php?mode={1}&chan_name={2}&auth_token={3}";
818 818
819 /// <summary> 819 /// <summary>
820 /// Create a channel. 820 /// Create a channel.
@@ -888,7 +888,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
888 return false; 888 return false;
889 } 889 }
890 890
891 private static readonly string m_vivoxChannelSearchPath = "http://{0}/api2/viv_chan_search.php?cond_channame={1}&auth_token={2}"; 891 private static readonly string m_vivoxChannelSearchPath = "https://{0}/api2/viv_chan_search.php?cond_channame={1}&auth_token={2}";
892 892
893 /// <summary> 893 /// <summary>
894 /// Retrieve a channel. 894 /// Retrieve a channel.
@@ -1032,7 +1032,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
1032 return false; 1032 return false;
1033 } 1033 }
1034 1034
1035 // private static readonly string m_vivoxChannelById = "http://{0}/api2/viv_chan_mod.php?mode={1}&chan_id={2}&auth_token={3}"; 1035 // private static readonly string m_vivoxChannelById = "https://{0}/api2/viv_chan_mod.php?mode={1}&chan_id={2}&auth_token={3}";
1036 1036
1037 // private XmlElement VivoxGetChannelById(string parent, string channelid) 1037 // private XmlElement VivoxGetChannelById(string parent, string channelid)
1038 // { 1038 // {
@@ -1056,7 +1056,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
1056 /// In this case the call handles parent and description as optional values. 1056 /// In this case the call handles parent and description as optional values.
1057 /// </summary> 1057 /// </summary>
1058 1058
1059 private static readonly string m_vivoxChannelDel = "http://{0}/api2/viv_chan_mod.php?mode={1}&chan_id={2}&auth_token={3}"; 1059 private static readonly string m_vivoxChannelDel = "https://{0}/api2/viv_chan_mod.php?mode={1}&chan_id={2}&auth_token={3}";
1060 1060
1061 private XmlElement VivoxDeleteChannel(string parent, string channelid) 1061 private XmlElement VivoxDeleteChannel(string parent, string channelid)
1062 { 1062 {
@@ -1072,7 +1072,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
1072 /// Return information on channels in the given directory 1072 /// Return information on channels in the given directory
1073 /// </summary> 1073 /// </summary>
1074 1074
1075 private static readonly string m_vivoxChannelSearch = "http://{0}/api2/viv_chan_search.php?&cond_chanparent={1}&auth_token={2}"; 1075 private static readonly string m_vivoxChannelSearch = "https://{0}/api2/viv_chan_search.php?&cond_chanparent={1}&auth_token={2}";
1076 1076
1077 private XmlElement VivoxListChildren(string channelid) 1077 private XmlElement VivoxListChildren(string channelid)
1078 { 1078 {
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
index b60cd42..d39b847 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
@@ -874,7 +874,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
874 msg.dialog = dialog; 874 msg.dialog = dialog;
875 // msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupNotice; 875 // msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupNotice;
876 msg.fromGroup = true; 876 msg.fromGroup = true;
877 msg.offline = (byte)0; 877 msg.offline = (byte)1; // Allow this message to be stored for offline use
878 msg.ParentEstateID = 0; 878 msg.ParentEstateID = 0;
879 msg.Position = Vector3.Zero; 879 msg.Position = Vector3.Zero;
880 msg.RegionID = UUID.Zero.Guid; 880 msg.RegionID = UUID.Zero.Guid;
diff --git a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs
index 32659c8..11c87f8 100644
--- a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs
@@ -42,17 +42,22 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcRouterModule
42 public class XmlRpcRouter : IRegionModule, IXmlRpcRouter 42 public class XmlRpcRouter : IRegionModule, IXmlRpcRouter
43 { 43 {
44 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45 45 private bool m_enabled = false;
46 public void Initialise(Scene scene, IConfigSource config) 46 public void Initialise(Scene scene, IConfigSource config)
47 { 47 {
48 IConfig startupConfig = config.Configs["Startup"]; 48 IConfig startupConfig = config.Configs["XMLRPC"];
49 if (startupConfig == null) 49 if (startupConfig == null)
50 return; 50 return;
51 51
52 if (startupConfig.GetString("XmlRpcRouterModule", 52 if (startupConfig.GetString("XmlRpcRouterModule",
53 "XmlRpcRouterModule") == "XmlRpcRouterModule") 53 "") == "XmlRpcRouterModule")
54 { 54 {
55 scene.RegisterModuleInterface<IXmlRpcRouter>(this); 55 scene.RegisterModuleInterface<IXmlRpcRouter>(this);
56 m_enabled = true;
57 }
58 else
59 {
60 m_enabled = false;
56 } 61 }
57 } 62 }
58 63
@@ -76,7 +81,10 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcRouterModule
76 81
77 public void RegisterNewReceiver(IScriptModule scriptEngine, UUID channel, UUID objectID, UUID itemID, string uri) 82 public void RegisterNewReceiver(IScriptModule scriptEngine, UUID channel, UUID objectID, UUID itemID, string uri)
78 { 83 {
79 scriptEngine.PostScriptEvent(itemID, "xmlrpc_uri", new Object[] {uri}); 84 if (m_enabled)
85 {
86 scriptEngine.PostScriptEvent(itemID, "xmlrpc_uri", new Object[] { uri });
87 }
80 } 88 }
81 89
82 public void ScriptRemoved(UUID itemID) 90 public void ScriptRemoved(UUID itemID)
diff --git a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs
index 9c838d0..d206f69 100644
--- a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs
+++ b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs
@@ -838,6 +838,10 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
838 if (module != null) 838 if (module != null)
839 module.BuyObject(remoteClient, categoryID, localID, saleType, salePrice); 839 module.BuyObject(remoteClient, categoryID, localID, saleType, salePrice);
840 } 840 }
841
842 public void MoveMoney(UUID fromAgentID, UUID toAgentID, int amount, string text)
843 {
844 }
841 } 845 }
842 846
843 public enum TransactionType : int 847 public enum TransactionType : int
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index 6d40a92..17fd6b1 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
@@ -171,7 +171,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
171#pragma warning disable 67 171#pragma warning disable 67
172 public event Action<IClientAPI> OnLogout; 172 public event Action<IClientAPI> OnLogout;
173 public event ObjectPermissions OnObjectPermissions; 173 public event ObjectPermissions OnObjectPermissions;
174 174 public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy;
175 public event MoneyTransferRequest OnMoneyTransferRequest; 175 public event MoneyTransferRequest OnMoneyTransferRequest;
176 public event ParcelBuy OnParcelBuy; 176 public event ParcelBuy OnParcelBuy;
177 public event Action<IClientAPI> OnConnectionClosed; 177 public event Action<IClientAPI> OnConnectionClosed;
@@ -377,7 +377,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
377 public event ClassifiedInfoRequest OnClassifiedInfoRequest; 377 public event ClassifiedInfoRequest OnClassifiedInfoRequest;
378 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate; 378 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate;
379 public event ClassifiedDelete OnClassifiedDelete; 379 public event ClassifiedDelete OnClassifiedDelete;
380 public event ClassifiedDelete OnClassifiedGodDelete; 380 public event ClassifiedGodDelete OnClassifiedGodDelete;
381 381
382 public event EventNotificationAddRequest OnEventNotificationAddRequest; 382 public event EventNotificationAddRequest OnEventNotificationAddRequest;
383 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest; 383 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest;
@@ -416,6 +416,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
416 public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest; 416 public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest;
417 public event SimWideDeletesDelegate OnSimWideDeletes; 417 public event SimWideDeletesDelegate OnSimWideDeletes;
418 public event SendPostcard OnSendPostcard; 418 public event SendPostcard OnSendPostcard;
419 public event ChangeInventoryItemFlags OnChangeInventoryItemFlags;
419 public event MuteListEntryUpdate OnUpdateMuteListEntry; 420 public event MuteListEntryUpdate OnUpdateMuteListEntry;
420 public event MuteListEntryRemove OnRemoveMuteListEntry; 421 public event MuteListEntryRemove OnRemoveMuteListEntry;
421 public event GodlikeMessage onGodlikeMessage; 422 public event GodlikeMessage onGodlikeMessage;
@@ -851,8 +852,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC
851 852
852 public void Close() 853 public void Close()
853 { 854 {
854 // Remove ourselves from the scene 855 Close(true);
855 m_scene.RemoveClient(AgentId, false); 856 }
857
858 public void Close(bool sendStop)
859 {
856 } 860 }
857 861
858 public void Start() 862 public void Start()
diff --git a/OpenSim/Region/Physics/ChOdePlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/ChOdePlugin/AssemblyInfo.cs
new file mode 100644
index 0000000..d65929a
--- /dev/null
+++ b/OpenSim/Region/Physics/ChOdePlugin/AssemblyInfo.cs
@@ -0,0 +1,58 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System.Reflection;
29using System.Runtime.InteropServices;
30
31// Information about this assembly is defined by the following
32// attributes.
33//
34// change them to the information which is associated with the assembly
35// you compile.
36
37[assembly : AssemblyTitle("OdePlugin")]
38[assembly : AssemblyDescription("")]
39[assembly : AssemblyConfiguration("")]
40[assembly : AssemblyCompany("http://opensimulator.org")]
41[assembly : AssemblyProduct("OdePlugin")]
42[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers 2007-2009")]
43[assembly : AssemblyTrademark("")]
44[assembly : AssemblyCulture("")]
45
46// This sets the default COM visibility of types in the assembly to invisible.
47// If you need to expose a type to COM, use [ComVisible(true)] on that type.
48
49[assembly : ComVisible(false)]
50
51// The assembly version has following format :
52//
53// Major.Minor.Build.Revision
54//
55// You can specify all values by your own or you can build default build and revision
56// numbers with the '*' character (the default):
57
58[assembly : AssemblyVersion("0.6.5.*")]
diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs
new file mode 100644
index 0000000..2945199
--- /dev/null
+++ b/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs
@@ -0,0 +1,1438 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using OpenMetaverse;
32using Ode.NET;
33using OpenSim.Framework;
34using OpenSim.Region.Physics.Manager;
35using log4net;
36
37namespace OpenSim.Region.Physics.OdePlugin
38{
39 /// <summary>
40 /// Various properties that ODE uses for AMotors but isn't exposed in ODE.NET so we must define them ourselves.
41 /// </summary>
42
43 public enum dParam : int
44 {
45 LowStop = 0,
46 HiStop = 1,
47 Vel = 2,
48 FMax = 3,
49 FudgeFactor = 4,
50 Bounce = 5,
51 CFM = 6,
52 StopERP = 7,
53 StopCFM = 8,
54 LoStop2 = 256,
55 HiStop2 = 257,
56 Vel2 = 258,
57 FMax2 = 259,
58 StopERP2 = 7 + 256,
59 StopCFM2 = 8 + 256,
60 LoStop3 = 512,
61 HiStop3 = 513,
62 Vel3 = 514,
63 FMax3 = 515,
64 StopERP3 = 7 + 512,
65 StopCFM3 = 8 + 512
66 }
67 public class OdeCharacter : PhysicsActor
68 {
69 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
70
71 private Vector3 _position;
72 private d.Vector3 _zeroPosition;
73 // private d.Matrix3 m_StandUpRotation;
74 private bool _zeroFlag = false;
75 private bool m_lastUpdateSent = false;
76 private Vector3 _velocity;
77 private Vector3 _target_velocity;
78 private Vector3 _acceleration;
79 private Vector3 m_rotationalVelocity;
80 private float m_mass = 80f;
81 public float m_density = 60f;
82 private bool m_pidControllerActive = true;
83 public float PID_D = 800.0f;
84 public float PID_P = 900.0f;
85 //private static float POSTURE_SERVO = 10000.0f;
86 public float CAPSULE_RADIUS = 0.37f;
87 public float CAPSULE_LENGTH = 2.140599f;
88 public float m_tensor = 3800000f;
89 public float heightFudgeFactor = 0.52f;
90 public float walkDivisor = 1.3f;
91 public float runDivisor = 0.8f;
92 private bool flying = false;
93 private bool jumping = false; // add for jumping
94 private bool m_iscolliding = false;
95 private bool m_iscollidingGround = false;
96 private bool m_wascolliding = false;
97 private bool m_wascollidingGround = false;
98 private bool m_iscollidingObj = false;
99 private bool m_alwaysRun = false;
100 private bool m_hackSentFall = false;
101 private bool m_hackSentFly = false;
102 private int m_requestedUpdateFrequency = 0;
103 private Vector3 m_taintPosition = Vector3.Zero;
104 public uint m_localID = 0;
105 public bool m_returnCollisions = false;
106 // taints and their non-tainted counterparts
107 public bool m_isPhysical = false; // the current physical status
108 public bool m_tainted_isPhysical = false; // set when the physical status is tainted (false=not existing in physics engine, true=existing)
109 public float MinimumGroundFlightOffset = 3f;
110
111 private float m_tainted_CAPSULE_LENGTH; // set when the capsule length changes.
112 private float m_tiltMagnitudeWhenProjectedOnXYPlane = 0.1131371f; // used to introduce a fixed tilt because a straight-up capsule falls through terrain, probably a bug in terrain collider
113
114
115 private float m_buoyancy = 0f;
116
117 // private CollisionLocker ode;
118
119 private string m_name = String.Empty;
120
121 private bool[] m_colliderarr = new bool[11];
122 private bool[] m_colliderGroundarr = new bool[11];
123
124 // Default we're a Character
125 private CollisionCategories m_collisionCategories = (CollisionCategories.Character);
126
127 // Default, Collide with Other Geometries, spaces, bodies and characters.
128 private CollisionCategories m_collisionFlags = (CollisionCategories.Geom
129 | CollisionCategories.Space
130 | CollisionCategories.Body
131 | CollisionCategories.Character
132 | CollisionCategories.Land);
133 public IntPtr Body = IntPtr.Zero;
134 private OdeScene _parent_scene;
135 public IntPtr Shell = IntPtr.Zero;
136 public IntPtr Amotor = IntPtr.Zero;
137 public d.Mass ShellMass;
138 public bool collidelock = false;
139
140 public int m_eventsubscription = 0;
141 private CollisionEventUpdate CollisionEventsThisFrame = new CollisionEventUpdate();
142
143 // unique UUID of this character object
144 public UUID m_uuid;
145 public bool bad = false;
146 private Object m_syncRoot = new Object();
147
148 public OdeCharacter(String avName, OdeScene parent_scene, Vector3 pos, CollisionLocker dode, Vector3 size, float pid_d, float pid_p, float capsule_radius, float tensor, float density, float height_fudge_factor, float walk_divisor, float rundivisor)
149 {
150 m_uuid = UUID.Random();
151
152 if (pos.IsFinite())
153 {
154 if (pos.Z > 9999999f)
155 {
156 pos.Z = parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
157 }
158 if (pos.Z < -90000f)
159 {
160 pos.Z = parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
161 }
162 _position = pos;
163 m_taintPosition.X = pos.X;
164 m_taintPosition.Y = pos.Y;
165 m_taintPosition.Z = pos.Z;
166 }
167 else
168 {
169 _position = new Vector3(((float)_parent_scene.WorldExtents.X * 0.5f), ((float)_parent_scene.WorldExtents.Y * 0.5f), parent_scene.GetTerrainHeightAtXY(128f, 128f) + 10f);
170 m_taintPosition.X = _position.X;
171 m_taintPosition.Y = _position.Y;
172 m_taintPosition.Z = _position.Z;
173 m_log.Warn("[PHYSICS]: Got NaN Position on Character Create");
174 }
175
176 _parent_scene = parent_scene;
177
178 PID_D = pid_d;
179 PID_P = pid_p;
180 CAPSULE_RADIUS = capsule_radius;
181 m_tensor = tensor;
182 m_density = density;
183 heightFudgeFactor = height_fudge_factor;
184 walkDivisor = walk_divisor;
185 runDivisor = rundivisor;
186
187 // m_StandUpRotation =
188 // new d.Matrix3(0.5f, 0.7071068f, 0.5f, -0.7071068f, 0f, 0.7071068f, 0.5f, -0.7071068f,
189 // 0.5f);
190
191 for (int i = 0; i < 11; i++)
192 {
193 m_colliderarr[i] = false;
194 }
195 CAPSULE_LENGTH = (size.Z * 1.15f) - CAPSULE_RADIUS * 2.0f;
196 //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
197 m_tainted_CAPSULE_LENGTH = CAPSULE_LENGTH;
198
199 m_isPhysical = false; // current status: no ODE information exists
200 m_tainted_isPhysical = true; // new tainted status: need to create ODE information
201
202 _parent_scene.AddPhysicsActorTaint(this);
203
204 m_name = avName;
205 }
206
207 public override int PhysicsActorType
208 {
209 get { return (int) ActorTypes.Agent; }
210 set { return; }
211 }
212
213 /// <summary>
214 /// If this is set, the avatar will move faster
215 /// </summary>
216 public override bool SetAlwaysRun
217 {
218 get { return m_alwaysRun; }
219 set { m_alwaysRun = value; }
220 }
221
222 public override uint LocalID
223 {
224 set { m_localID = value; }
225 }
226
227 public override bool Grabbed
228 {
229 set { return; }
230 }
231
232 public override bool Selected
233 {
234// set { return; }
235 set { jumping = value; } // add for jumping flag
236 }
237
238 public override float Buoyancy
239 {
240 get { return m_buoyancy; }
241 set { m_buoyancy = value; }
242 }
243
244 public override bool FloatOnWater
245 {
246 set { return; }
247 }
248
249 public override bool IsPhysical
250 {
251 get { return false; }
252 set { return; }
253 }
254
255 public override bool ThrottleUpdates
256 {
257 get { return false; }
258 set { return; }
259 }
260
261 public override bool Flying
262 {
263 get { return flying; }
264 set { flying = value; }
265 }
266
267 /// <summary>
268 /// Returns if the avatar is colliding in general.
269 /// This includes the ground and objects and avatar.
270 /// </summary>
271 public override bool IsColliding
272 {
273//#@ get { return m_iscolliding; }
274 get { //##
275//Console.WriteLine(">>>>>>>>>>>> IC get = {0}", m_iscolliding); //##
276 return m_iscolliding; } //##
277 set
278 {
279 int i;
280 int truecount = 0;
281 int falsecount = 0;
282
283 if (m_colliderarr.Length >= 10)
284 {
285 for (i = 0; i < 10; i++)
286 {
287 m_colliderarr[i] = m_colliderarr[i + 1];
288 }
289 }
290 m_colliderarr[10] = value;
291
292 for (i = 0; i < 11; i++)
293 {
294 if (m_colliderarr[i])
295 {
296 truecount++;
297 }
298 else
299 {
300 falsecount++;
301 }
302 }
303
304 // Equal truecounts and false counts means we're colliding with something.
305
306 if (falsecount > 1.2*truecount)
307 {
308 m_iscolliding = false;
309 }
310 else
311 {
312 m_iscolliding = true;
313 }
314// ## Console.WriteLine("IC SET = {0} t{1} f{2} i {3}", value, truecount, falsecount, m_iscolliding);
315 if (m_wascolliding != m_iscolliding)
316 {
317 //base.SendCollisionUpdate(new CollisionEventUpdate());
318 }
319 m_wascolliding = m_iscolliding;
320 }
321 }
322
323 /// <summary>
324 /// Returns if an avatar is colliding with the ground
325 /// </summary>
326 public override bool CollidingGround
327 {
328 get { return m_iscollidingGround; }
329 set
330 {
331 // Collisions against the ground are not really reliable
332 // So, to get a consistant value we have to average the current result over time
333 // Currently we use 1 second = 10 calls to this.
334 int i;
335 int truecount = 0;
336 int falsecount = 0;
337
338 if (m_colliderGroundarr.Length >= 10)
339 {
340 for (i = 0; i < 10; i++)
341 {
342 m_colliderGroundarr[i] = m_colliderGroundarr[i + 1];
343 }
344 }
345 m_colliderGroundarr[10] = value;
346
347 for (i = 0; i < 11; i++)
348 {
349 if (m_colliderGroundarr[i])
350 {
351 truecount++;
352 }
353 else
354 {
355 falsecount++;
356 }
357 }
358
359 // Equal truecounts and false counts means we're colliding with something.
360
361 if (falsecount > 1.2*truecount)
362 {
363 m_iscollidingGround = false;
364 }
365 else
366 {
367 m_iscollidingGround = true;
368 }
369 if (m_wascollidingGround != m_iscollidingGround)
370 {
371 //base.SendCollisionUpdate(new CollisionEventUpdate());
372 }
373 m_wascollidingGround = m_iscollidingGround;
374 }
375 }
376
377 /// <summary>
378 /// Returns if the avatar is colliding with an object
379 /// </summary>
380 public override bool CollidingObj
381 {
382 get { return m_iscollidingObj; }
383 set
384 {
385 m_iscollidingObj = value;
386 if (value)
387 m_pidControllerActive = false;
388 else
389 m_pidControllerActive = true;
390 }
391 }
392
393 /// <summary>
394 /// turn the PID controller on or off.
395 /// The PID Controller will turn on all by itself in many situations
396 /// </summary>
397 /// <param name="status"></param>
398 public void SetPidStatus(bool status)
399 {
400 m_pidControllerActive = status;
401 }
402
403 public override bool Stopped
404 {
405 get { return _zeroFlag; }
406 }
407
408 /// <summary>
409 /// This 'puts' an avatar somewhere in the physics space.
410 /// Not really a good choice unless you 'know' it's a good
411 /// spot otherwise you're likely to orbit the avatar.
412 /// </summary>
413 public override Vector3 Position
414 {
415 get { return _position; }
416 set
417 {
418 if (Body == IntPtr.Zero || Shell == IntPtr.Zero)
419 {
420 if (value.IsFinite())
421 {
422 if (value.Z > 9999999f)
423 {
424 value.Z = _parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
425 }
426 if (value.Z < -90000f)
427 {
428 value.Z = _parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
429 }
430
431 _position.X = value.X;
432 _position.Y = value.Y;
433 _position.Z = value.Z;
434
435 m_taintPosition.X = value.X;
436 m_taintPosition.Y = value.Y;
437 m_taintPosition.Z = value.Z;
438 _parent_scene.AddPhysicsActorTaint(this);
439 }
440 else
441 {
442 m_log.Warn("[PHYSICS]: Got a NaN Position from Scene on a Character");
443 }
444 }
445 }
446 }
447
448 public override Vector3 RotationalVelocity
449 {
450 get { return m_rotationalVelocity; }
451 set { m_rotationalVelocity = value; }
452 }
453
454 /// <summary>
455 /// This property sets the height of the avatar only. We use the height to make sure the avatar stands up straight
456 /// and use it to offset landings properly
457 /// </summary>
458 public override Vector3 Size
459 {
460 get { return new Vector3(CAPSULE_RADIUS * 2, CAPSULE_RADIUS * 2, CAPSULE_LENGTH); }
461 set
462 {
463 if (value.IsFinite())
464 {
465 m_pidControllerActive = true;
466
467 Vector3 SetSize = value;
468 m_tainted_CAPSULE_LENGTH = (SetSize.Z*1.15f) - CAPSULE_RADIUS*2.0f;
469 //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
470
471 Velocity = Vector3.Zero;
472 m_taintPosition = _position; // update the stale taint position
473 _parent_scene.AddPhysicsActorTaint(this);
474 }
475 else
476 {
477 m_log.Warn("[PHYSICS]: Got a NaN Size from Scene on a Character");
478 }
479 }
480 }
481
482 private void AlignAvatarTiltWithCurrentDirectionOfMovement(Vector3 movementVector)
483 {
484 movementVector.Z = 0f;
485 float magnitude = (float)Math.Sqrt((double)(movementVector.X * movementVector.X + movementVector.Y * movementVector.Y));
486 if (magnitude < 0.1f) return;
487
488 // normalize the velocity vector
489 float invMagnitude = 1.0f / magnitude;
490 movementVector.X *= invMagnitude;
491 movementVector.Y *= invMagnitude;
492
493 // if we change the capsule heading too often, the capsule can fall down
494 // therefore we snap movement vector to just 1 of 4 predefined directions (ne, nw, se, sw),
495 // meaning only 4 possible capsule tilt orientations
496 if (movementVector.X > 0)
497 {
498 // east
499 if (movementVector.Y > 0)
500 {
501 // northeast
502 movementVector.X = (float)Math.Sqrt(2.0);
503 movementVector.Y = (float)Math.Sqrt(2.0);
504 }
505 else
506 {
507 // southeast
508 movementVector.X = (float)Math.Sqrt(2.0);
509 movementVector.Y = -(float)Math.Sqrt(2.0);
510 }
511 }
512 else
513 {
514 // west
515 if (movementVector.Y > 0)
516 {
517 // northwest
518 movementVector.X = -(float)Math.Sqrt(2.0);
519 movementVector.Y = (float)Math.Sqrt(2.0);
520 }
521 else
522 {
523 // southwest
524 movementVector.X = -(float)Math.Sqrt(2.0);
525 movementVector.Y = -(float)Math.Sqrt(2.0);
526 }
527 }
528
529
530 // movementVector.Z is zero
531
532 // calculate tilt components based on desired amount of tilt and current (snapped) heading.
533 // the "-" sign is to force the tilt to be OPPOSITE the direction of movement.
534 float xTiltComponent = -movementVector.X * m_tiltMagnitudeWhenProjectedOnXYPlane;
535 float yTiltComponent = -movementVector.Y * m_tiltMagnitudeWhenProjectedOnXYPlane;
536
537 //m_log.Debug("[PHYSICS] changing avatar tilt");
538 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, xTiltComponent);
539 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, xTiltComponent); // must be same as lowstop, else a different, spurious tilt is introduced
540 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, yTiltComponent);
541 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, yTiltComponent); // same as lowstop
542 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, 0f);
543 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0f); // same as lowstop
544 }
545
546 /// <summary>
547 /// This creates the Avatar's physical Surrogate at the position supplied
548 /// </summary>
549 /// <param name="npositionX"></param>
550 /// <param name="npositionY"></param>
551 /// <param name="npositionZ"></param>
552
553 // WARNING: This MUST NOT be called outside of ProcessTaints, else we can have unsynchronized access
554 // to ODE internals. ProcessTaints is called from within thread-locked Simulate(), so it is the only
555 // place that is safe to call this routine AvatarGeomAndBodyCreation.
556 private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ, float tensor)
557 {
558 //CAPSULE_LENGTH = -5;
559 //CAPSULE_RADIUS = -5;
560 int dAMotorEuler = 1;
561 _parent_scene.waitForSpaceUnlock(_parent_scene.space);
562 if (CAPSULE_LENGTH <= 0)
563 {
564 m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
565 CAPSULE_LENGTH = 0.01f;
566
567 }
568
569 if (CAPSULE_RADIUS <= 0)
570 {
571 m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
572 CAPSULE_RADIUS = 0.01f;
573
574 }
575
576 if(Shell != IntPtr.Zero)
577 {
578 try
579 {
580 d.GeomDestroy(Shell);
581 }
582 catch (System.AccessViolationException)
583 {
584 m_log.Error("[PHYSICS]: PrimGeom dead");
585 }
586 // Remove any old entries
587//string tShell;
588//_parent_scene.geom_name_map.TryGetValue(Shell, out tShell);
589//Console.WriteLine("**** Remove {0}", tShell);
590 if(_parent_scene.geom_name_map.ContainsKey(Shell)) _parent_scene.geom_name_map.Remove(Shell);
591 if(_parent_scene.actor_name_map.ContainsKey(Shell)) _parent_scene.actor_name_map.Remove(Shell);
592 }
593
594 Shell = d.CreateCapsule(_parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH);
595 _parent_scene.geom_name_map[Shell] = m_name;
596 _parent_scene.actor_name_map[Shell] = (PhysicsActor)this;
597//Console.WriteLine("**** Create {2} Dicts: actor={0} name={1} height={3} rad={4}", _parent_scene.actor_name_map.Count, _parent_scene.geom_name_map.Count, m_name, CAPSULE_LENGTH, CAPSULE_RADIUS);
598
599 d.GeomSetCategoryBits(Shell, (int)m_collisionCategories);
600 d.GeomSetCollideBits(Shell, (int)m_collisionFlags);
601
602 d.MassSetCapsuleTotal(out ShellMass, m_mass, 2, CAPSULE_RADIUS, CAPSULE_LENGTH);
603 Body = d.BodyCreate(_parent_scene.world);
604 d.BodySetPosition(Body, npositionX, npositionY, npositionZ);
605
606 _position.X = npositionX;
607 _position.Y = npositionY;
608 _position.Z = npositionZ;
609
610
611 m_taintPosition.X = npositionX;
612 m_taintPosition.Y = npositionY;
613 m_taintPosition.Z = npositionZ;
614
615 d.BodySetMass(Body, ref ShellMass);
616 d.Matrix3 m_caprot;
617 // 90 Stand up on the cap of the capped cyllinder
618 if (_parent_scene.IsAvCapsuleTilted)
619 {
620 d.RFromAxisAndAngle(out m_caprot, 1, 0, 1, (float)(Math.PI / 2));
621 }
622 else
623 {
624 d.RFromAxisAndAngle(out m_caprot, 0, 0, 1, (float)(Math.PI / 2));
625 }
626
627
628 d.GeomSetRotation(Shell, ref m_caprot);
629 d.BodySetRotation(Body, ref m_caprot);
630
631 d.GeomSetBody(Shell, Body);
632
633
634 // The purpose of the AMotor here is to keep the avatar's physical
635 // surrogate from rotating while moving
636 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero);
637 d.JointAttach(Amotor, Body, IntPtr.Zero);
638 d.JointSetAMotorMode(Amotor, dAMotorEuler);
639 d.JointSetAMotorNumAxes(Amotor, 3);
640 d.JointSetAMotorAxis(Amotor, 0, 0, 1, 0, 0);
641 d.JointSetAMotorAxis(Amotor, 1, 0, 0, 1, 0);
642 d.JointSetAMotorAxis(Amotor, 2, 0, 0, 0, 1);
643 d.JointSetAMotorAngle(Amotor, 0, 0);
644 d.JointSetAMotorAngle(Amotor, 1, 0);
645 d.JointSetAMotorAngle(Amotor, 2, 0);
646
647 // These lowstops and high stops are effectively (no wiggle room)
648 if (_parent_scene.IsAvCapsuleTilted)
649 {
650 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, -0.000000000001f);
651 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0.000000000001f);
652 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, -0.000000000001f);
653 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0.000000000001f);
654 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0.000000000001f);
655 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0.000000000001f);
656 }
657 else
658 {
659 #region Documentation of capsule motor LowStop and HighStop parameters
660 // Intentionally introduce some tilt into the capsule by setting
661 // the motor stops to small epsilon values. This small tilt prevents
662 // the capsule from falling into the terrain; a straight-up capsule
663 // (with -0..0 motor stops) falls into the terrain for reasons yet
664 // to be comprehended in their entirety.
665 #endregion
666 AlignAvatarTiltWithCurrentDirectionOfMovement(Vector3.Zero);
667 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, 0.08f);
668 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0f);
669 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, 0.08f);
670 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0.08f); // must be same as lowstop, else a different, spurious tilt is introduced
671 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0f); // same as lowstop
672 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0.08f); // same as lowstop
673 }
674
675 // Fudge factor is 1f by default, we're setting it to 0. We don't want it to Fudge or the
676 // capped cyllinder will fall over
677 d.JointSetAMotorParam(Amotor, (int)dParam.FudgeFactor, 0f);
678 d.JointSetAMotorParam(Amotor, (int)dParam.FMax, tensor);
679
680 //d.Matrix3 bodyrotation = d.BodyGetRotation(Body);
681 //d.QfromR(
682 //d.Matrix3 checkrotation = new d.Matrix3(0.7071068,0.5, -0.7071068,
683 //
684 //m_log.Info("[PHYSICSAV]: Rotation: " + bodyrotation.M00 + " : " + bodyrotation.M01 + " : " + bodyrotation.M02 + " : " + bodyrotation.M10 + " : " + bodyrotation.M11 + " : " + bodyrotation.M12 + " : " + bodyrotation.M20 + " : " + bodyrotation.M21 + " : " + bodyrotation.M22);
685 //standupStraight();
686 }
687
688 //
689 /// <summary>
690 /// Uses the capped cyllinder volume formula to calculate the avatar's mass.
691 /// This may be used in calculations in the scene/scenepresence
692 /// </summary>
693 public override float Mass
694 {
695 get
696 {
697 float AVvolume = (float) (Math.PI*Math.Pow(CAPSULE_RADIUS, 2)*CAPSULE_LENGTH);
698 return m_density*AVvolume;
699 }
700 }
701 public override void link(PhysicsActor obj)
702 {
703
704 }
705
706 public override void delink()
707 {
708
709 }
710
711 public override void LockAngularMotion(Vector3 axis)
712 {
713
714 }
715
716// This code is very useful. Written by DanX0r. We're just not using it right now.
717// Commented out to prevent a warning.
718//
719// private void standupStraight()
720// {
721// // The purpose of this routine here is to quickly stabilize the Body while it's popped up in the air.
722// // The amotor needs a few seconds to stabilize so without it, the avatar shoots up sky high when you
723// // change appearance and when you enter the simulator
724// // After this routine is done, the amotor stabilizes much quicker
725// d.Vector3 feet;
726// d.Vector3 head;
727// d.BodyGetRelPointPos(Body, 0.0f, 0.0f, -1.0f, out feet);
728// d.BodyGetRelPointPos(Body, 0.0f, 0.0f, 1.0f, out head);
729// float posture = head.Z - feet.Z;
730
731// // restoring force proportional to lack of posture:
732// float servo = (2.5f - posture) * POSTURE_SERVO;
733// d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, servo, 0.0f, 0.0f, 1.0f);
734// d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, -servo, 0.0f, 0.0f, -1.0f);
735// //d.Matrix3 bodyrotation = d.BodyGetRotation(Body);
736// //m_log.Info("[PHYSICSAV]: Rotation: " + bodyrotation.M00 + " : " + bodyrotation.M01 + " : " + bodyrotation.M02 + " : " + bodyrotation.M10 + " : " + bodyrotation.M11 + " : " + bodyrotation.M12 + " : " + bodyrotation.M20 + " : " + bodyrotation.M21 + " : " + bodyrotation.M22);
737// }
738
739 public override Vector3 Force
740 {
741 get { return _target_velocity; }
742 set { return; }
743 }
744
745 public override int VehicleType
746 {
747 get { return 0; }
748 set { return; }
749 }
750
751 public override void VehicleFloatParam(int param, float value)
752 {
753
754 }
755
756 public override void VehicleVectorParam(int param, Vector3 value)
757 {
758
759 }
760
761 public override void VehicleRotationParam(int param, Quaternion rotation)
762 {
763
764 }
765
766 public override void VehicleFlags(int flags, bool remove)
767 {
768 }
769
770 public override void SetVolumeDetect(int param)
771 {
772
773 }
774
775 public override Vector3 CenterOfMass
776 {
777 get { return Vector3.Zero; }
778 }
779
780 public override Vector3 GeometricCenter
781 {
782 get { return Vector3.Zero; }
783 }
784
785 public override PrimitiveBaseShape Shape
786 {
787 set { return; }
788 }
789
790 public override Vector3 Velocity
791 {
792 get {
793 // There's a problem with Vector3.Zero! Don't Use it Here!
794 if (_zeroFlag)
795 return Vector3.Zero;
796 m_lastUpdateSent = false;
797 return _velocity;
798 }
799 set
800 {
801 if (value.IsFinite())
802 {
803 m_pidControllerActive = true;
804 _target_velocity = value;
805 }
806 else
807 {
808 m_log.Warn("[PHYSICS]: Got a NaN velocity from Scene in a Character");
809 }
810 }
811 }
812
813 public override Vector3 Torque
814 {
815 get { return Vector3.Zero; }
816 set { return; }
817 }
818
819 public override float CollisionScore
820 {
821 get { return 0f; }
822 set { }
823 }
824
825 public override bool Kinematic
826 {
827 get { return false; }
828 set { }
829 }
830
831 public override Quaternion Orientation
832 {
833 get { return Quaternion.Identity; }
834 set {
835 //Matrix3 or = Orientation.ToRotationMatrix();
836 //d.Matrix3 ord = new d.Matrix3(or.m00, or.m10, or.m20, or.m01, or.m11, or.m21, or.m02, or.m12, or.m22);
837 //d.BodySetRotation(Body, ref ord);
838 }
839 }
840
841 public override Vector3 Acceleration
842 {
843 get { return _acceleration; }
844 set { _acceleration = value; }
845 }
846
847 public void SetAcceleration(Vector3 accel)
848 {
849 m_pidControllerActive = true;
850 _acceleration = accel;
851 }
852
853 /// <summary>
854 /// Adds the force supplied to the Target Velocity
855 /// The PID controller takes this target velocity and tries to make it a reality
856 /// </summary>
857 /// <param name="force"></param>
858 public override void AddForce(Vector3 force, bool pushforce)
859 {
860 if (force.IsFinite())
861 {
862 if (pushforce)
863 {
864 m_pidControllerActive = false;
865 force *= 100f;
866//Console.WriteLine("DF 1"); // ##
867 if (!force.ApproxEquals(Vector3.Zero, 0.01f))
868 doForce(force);
869 // If uncommented, things get pushed off world
870 //
871 // m_log.Debug("Push!");
872 // _target_velocity.X += force.X;
873 // _target_velocity.Y += force.Y;
874 // _target_velocity.Z += force.Z;
875 }
876 else
877 {
878 m_pidControllerActive = true;
879 _target_velocity.X += force.X;
880 _target_velocity.Y += force.Y;
881 _target_velocity.Z += force.Z;
882 }
883 }
884 else
885 {
886 m_log.Warn("[PHYSICS]: Got a NaN force applied to a Character");
887 }
888 //m_lastUpdateSent = false;
889 }
890
891 public override void AddAngularForce(Vector3 force, bool pushforce)
892 {
893
894 }
895
896 /// <summary>
897 /// After all of the forces add up with 'add force' we apply them with doForce
898 /// </summary>
899 /// <param name="force"></param>
900 public void doForce(Vector3 force)
901 {
902 if (!collidelock)
903 {
904 d.BodyAddForce(Body, force.X, force.Y, force.Z);
905 //d.BodySetRotation(Body, ref m_StandUpRotation);
906 //standupStraight();
907 d.Vector3 vel = d.BodyGetLinearVel(Body); //##
908//Console.WriteLine("AvVel <{0},{1},{2}>", vel.X, vel.Y, vel.Z); //##
909 }
910 }
911
912 public override void SetMomentum(Vector3 momentum)
913 {
914 }
915
916
917 /// <summary>
918 /// Called from Simulate
919 /// This is the avatar's movement control + PID Controller
920 /// </summary>
921 /// <param name="timeStep"></param>
922 public void Move(float timeStep, List<OdeCharacter> defects)
923 {
924 // no lock; for now it's only called from within Simulate()
925
926 // If the PID Controller isn't active then we set our force
927 // calculating base velocity to the current position
928
929 if (Body == IntPtr.Zero)
930 return;
931
932 if (m_pidControllerActive == false)
933 {
934 _zeroPosition = d.BodyGetPosition(Body);
935 }
936 //PidStatus = true;
937
938 d.Vector3 localpos = d.BodyGetPosition(Body);
939 Vector3 localPos = new Vector3(localpos.X, localpos.Y, localpos.Z);
940
941 if (!localPos.IsFinite())
942 {
943
944 m_log.Warn("[PHYSICS]: Avatar Position is non-finite!");
945 defects.Add(this);
946 // _parent_scene.RemoveCharacter(this);
947
948 // destroy avatar capsule and related ODE data
949 if (Amotor != IntPtr.Zero)
950 {
951 // Kill the Amotor
952 d.JointDestroy(Amotor);
953 Amotor = IntPtr.Zero;
954 }
955
956 //kill the Geometry
957 _parent_scene.waitForSpaceUnlock(_parent_scene.space);
958
959 if (Body != IntPtr.Zero)
960 {
961 //kill the body
962 d.BodyDestroy(Body);
963
964 Body = IntPtr.Zero;
965 }
966
967 if(Shell != IntPtr.Zero)
968 {
969 try
970 {
971 d.GeomDestroy(Shell);
972 }
973 catch (System.AccessViolationException)
974 {
975 m_log.Error("[PHYSICS]: PrimGeom dead");
976 }
977 // Remove any old entries
978//string tShell;
979//_parent_scene.geom_name_map.TryGetValue(Shell, out tShell);
980//Console.WriteLine("**** Remove {0}", tShell);
981
982 if(_parent_scene.geom_name_map.ContainsKey(Shell)) _parent_scene.geom_name_map.Remove(Shell);
983 if(_parent_scene.actor_name_map.ContainsKey(Shell)) _parent_scene.actor_name_map.Remove(Shell);
984 Shell = IntPtr.Zero;
985 }
986
987 return;
988 }
989
990 Vector3 vec = Vector3.Zero;
991 d.Vector3 vel = d.BodyGetLinearVel(Body);
992
993 float movementdivisor = 1f;
994
995 if (!m_alwaysRun)
996 {
997 movementdivisor = walkDivisor;
998 }
999 else
1000 {
1001 movementdivisor = runDivisor;
1002 }
1003
1004 // if velocity is zero, use position control; otherwise, velocity control
1005 if (_target_velocity.X == 0.0f && _target_velocity.Y == 0.0f && _target_velocity.Z == 0.0f && m_iscolliding)
1006 {
1007 // keep track of where we stopped. No more slippin' & slidin'
1008 if (!_zeroFlag)
1009 {
1010 _zeroFlag = true;
1011 _zeroPosition = d.BodyGetPosition(Body);
1012 }
1013 if (m_pidControllerActive)
1014 {
1015 // We only want to deactivate the PID Controller if we think we want to have our surrogate
1016 // react to the physics scene by moving it's position.
1017 // Avatar to Avatar collisions
1018 // Prim to avatar collisions
1019
1020 d.Vector3 pos = d.BodyGetPosition(Body);
1021 float errX = _zeroPosition.X - pos.X;
1022 float errY = _zeroPosition.Y - pos.Y;
1023 if( (Math.Abs(errX) > 0.1f) || (Math.Abs(errY) > 0.1f) )
1024 {
1025 vec.X = (_target_velocity.X - vel.X) * (PID_D) + (errX) * (PID_P * 2);
1026 vec.Y = (_target_velocity.Y - vel.Y) * (PID_D) + (errY) * (PID_P * 2);
1027 }
1028 else
1029 { // close, jump to lateral destination
1030 d.BodySetPosition(Body, _zeroPosition.X, _zeroPosition.Y, pos.Z);
1031 }
1032// if (flying)
1033 if (flying || jumping) // add for jumping
1034 {
1035 vec.Z = (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P;
1036 }
1037 }
1038 //PidStatus = true;
1039 }
1040 else
1041 {
1042 m_pidControllerActive = true;
1043 _zeroFlag = false;
1044 if (m_iscolliding && !flying)
1045 {
1046 // We're standing on something
1047 vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D);
1048 vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D);
1049 }
1050 else if (m_iscolliding && flying)
1051 {
1052 // We're flying and colliding with something
1053 vec.X = ((_target_velocity.X/movementdivisor) - vel.X)*(PID_D / 16);
1054 vec.Y = ((_target_velocity.Y/movementdivisor) - vel.Y)*(PID_D / 16);
1055 }
1056 else if (!m_iscolliding && flying)
1057 {
1058 // we're in mid air suspended
1059 vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D/6);
1060 vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D/6);
1061 }
1062
1063 if (m_iscolliding && !flying && _target_velocity.Z > 0.0f)
1064 {
1065 // We're colliding with something and we're not flying but we're moving
1066 // This means we're walking or running.
1067 d.Vector3 pos = d.BodyGetPosition(Body);
1068 vec.Z = (_target_velocity.Z - vel.Z)*PID_D + (_zeroPosition.Z - pos.Z)*PID_P;
1069 if (_target_velocity.X > 0)
1070 {
1071 vec.X = ((_target_velocity.X - vel.X)/1.2f)*PID_D;
1072 }
1073 if (_target_velocity.Y > 0)
1074 {
1075 vec.Y = ((_target_velocity.Y - vel.Y)/1.2f)*PID_D;
1076 }
1077 }
1078 else if (!m_iscolliding && !flying)
1079 {
1080 // we're not colliding and we're not flying so that means we're falling!
1081 // m_iscolliding includes collisions with the ground.
1082
1083 // d.Vector3 pos = d.BodyGetPosition(Body);
1084 if (Math.Abs(_target_velocity.X) > 0)
1085 {
1086 vec.X = ((_target_velocity.X - vel.X)/1.2f)*PID_D;
1087 }
1088 if (Math.Abs(_target_velocity.Y) > 0)
1089 {
1090 vec.Y = ((_target_velocity.Y - vel.Y)/1.2f)*PID_D;
1091 }
1092 }
1093
1094 if (flying)
1095 {
1096 vec.Z = (_target_velocity.Z - vel.Z) * (PID_D);
1097 }
1098 }
1099 if (flying)
1100 {
1101 vec.Z += ((-1 * _parent_scene.gravityz)*m_mass);
1102
1103 //Added for auto fly height. Kitto Flora
1104 //d.Vector3 pos = d.BodyGetPosition(Body);
1105 float target_altitude = _parent_scene.GetTerrainHeightAtXY(_position.X, _position.Y) + MinimumGroundFlightOffset;
1106
1107 if (_position.Z < target_altitude)
1108 {
1109 vec.Z += (target_altitude - _position.Z) * PID_P * 5.0f;
1110 }
1111 // end add Kitto Flora
1112 }
1113 if (vec.IsFinite())
1114 {
1115 if (!vec.ApproxEquals(Vector3.Zero, 0.02f)) // 0.01 allows 0.002 !!
1116 {
1117//Console.WriteLine("DF 2"); // ##
1118
1119 doForce(vec);
1120 if (!_zeroFlag)
1121 {
1122// AlignAvatarTiltWithCurrentDirectionOfMovement(vec);
1123 }
1124 }
1125 }
1126 else
1127 {
1128 m_log.Warn("[PHYSICS]: Got a NaN force vector in Move()");
1129 m_log.Warn("[PHYSICS]: Avatar Position is non-finite!");
1130 defects.Add(this);
1131 // _parent_scene.RemoveCharacter(this);
1132 // destroy avatar capsule and related ODE data
1133 if (Amotor != IntPtr.Zero)
1134 {
1135 // Kill the Amotor
1136 d.JointDestroy(Amotor);
1137 Amotor = IntPtr.Zero;
1138 }
1139 //kill the Geometry
1140 _parent_scene.waitForSpaceUnlock(_parent_scene.space);
1141
1142 if (Body != IntPtr.Zero)
1143 {
1144 //kill the body
1145 d.BodyDestroy(Body);
1146
1147 Body = IntPtr.Zero;
1148 }
1149
1150 if(Shell != IntPtr.Zero)
1151 {
1152 try
1153 {
1154 d.GeomDestroy(Shell);
1155 }
1156 catch (System.AccessViolationException)
1157 {
1158 m_log.Error("[PHYSICS]: PrimGeom dead");
1159 }
1160 // Remove any old entries
1161//string tShell;
1162//_parent_scene.geom_name_map.TryGetValue(Shell, out tShell);
1163//Console.WriteLine("**** Remove {0}", tShell);
1164
1165 if(_parent_scene.geom_name_map.ContainsKey(Shell)) _parent_scene.geom_name_map.Remove(Shell);
1166 if(_parent_scene.actor_name_map.ContainsKey(Shell)) _parent_scene.actor_name_map.Remove(Shell);
1167 Shell = IntPtr.Zero;
1168 }
1169 }
1170 }
1171
1172 /// <summary>
1173 /// Updates the reported position and velocity. This essentially sends the data up to ScenePresence.
1174 /// </summary>
1175 public void UpdatePositionAndVelocity()
1176 {
1177 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
1178 d.Vector3 vec;
1179 try
1180 {
1181 vec = d.BodyGetPosition(Body);
1182 }
1183 catch (NullReferenceException)
1184 {
1185 bad = true;
1186 _parent_scene.BadCharacter(this);
1187 vec = new d.Vector3(_position.X, _position.Y, _position.Z);
1188 base.RaiseOutOfBounds(_position); // Tells ScenePresence that there's a problem!
1189 m_log.WarnFormat("[ODEPLUGIN]: Avatar Null reference for Avatar {0}, physical actor {1}", m_name, m_uuid);
1190 }
1191
1192
1193 // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!)
1194 if (vec.X < 0.0f) vec.X = 0.0f;
1195 if (vec.Y < 0.0f) vec.Y = 0.0f;
1196 if (vec.X > (int)_parent_scene.WorldExtents.X - 0.05f) vec.X = (int)_parent_scene.WorldExtents.X - 0.05f;
1197 if (vec.Y > (int)_parent_scene.WorldExtents.Y - 0.05f) vec.Y = (int)_parent_scene.WorldExtents.Y - 0.05f;
1198
1199 _position.X = vec.X;
1200 _position.Y = vec.Y;
1201 _position.Z = vec.Z;
1202
1203 // Did we move last? = zeroflag
1204 // This helps keep us from sliding all over
1205
1206 if (_zeroFlag)
1207 {
1208 _velocity.X = 0.0f;
1209 _velocity.Y = 0.0f;
1210 _velocity.Z = 0.0f;
1211
1212 // Did we send out the 'stopped' message?
1213 if (!m_lastUpdateSent)
1214 {
1215 m_lastUpdateSent = true;
1216 //base.RequestPhysicsterseUpdate();
1217
1218 }
1219 }
1220 else
1221 {
1222 m_lastUpdateSent = false;
1223 try
1224 {
1225 vec = d.BodyGetLinearVel(Body);
1226 }
1227 catch (NullReferenceException)
1228 {
1229 vec.X = _velocity.X;
1230 vec.Y = _velocity.Y;
1231 vec.Z = _velocity.Z;
1232 }
1233 _velocity.X = (vec.X);
1234 _velocity.Y = (vec.Y);
1235
1236 _velocity.Z = (vec.Z);
1237
1238 if (_velocity.Z < -6 && !m_hackSentFall)
1239 {
1240 m_hackSentFall = true;
1241 m_pidControllerActive = false;
1242 }
1243 else if (flying && !m_hackSentFly)
1244 {
1245 //m_hackSentFly = true;
1246 //base.SendCollisionUpdate(new CollisionEventUpdate());
1247 }
1248 else
1249 {
1250 m_hackSentFly = false;
1251 m_hackSentFall = false;
1252 }
1253 }
1254 }
1255
1256 /// <summary>
1257 /// Cleanup the things we use in the scene.
1258 /// </summary>
1259 public void Destroy()
1260 {
1261 m_tainted_isPhysical = false;
1262 _parent_scene.AddPhysicsActorTaint(this);
1263 }
1264
1265 public override void CrossingFailure()
1266 {
1267 }
1268
1269 public override Vector3 PIDTarget { set { return; } }
1270 public override bool PIDActive { set { return; } }
1271 public override float PIDTau { set { return; } }
1272
1273 public override float PIDHoverHeight { set { return; } }
1274 public override bool PIDHoverActive { set { return; } }
1275 public override PIDHoverType PIDHoverType { set { return; } }
1276 public override float PIDHoverTau { set { return; } }
1277
1278 public override Quaternion APIDTarget{ set { return; } }
1279
1280 public override bool APIDActive{ set { return; } }
1281
1282 public override float APIDStrength{ set { return; } }
1283
1284 public override float APIDDamping{ set { return; } }
1285
1286
1287 public override void SubscribeEvents(int ms)
1288 {
1289 m_requestedUpdateFrequency = ms;
1290 m_eventsubscription = ms;
1291 _parent_scene.addCollisionEventReporting(this);
1292 }
1293 public override void UnSubscribeEvents()
1294 {
1295 _parent_scene.remCollisionEventReporting(this);
1296 m_requestedUpdateFrequency = 0;
1297 m_eventsubscription = 0;
1298 }
1299 public void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
1300 {
1301 if (m_eventsubscription > 0)
1302 {
1303 CollisionEventsThisFrame.AddCollider(CollidedWith, contact);
1304 }
1305 }
1306
1307 public void SendCollisions()
1308 {
1309 if (m_eventsubscription > m_requestedUpdateFrequency)
1310 {
1311 if (CollisionEventsThisFrame != null)
1312 {
1313 base.SendCollisionUpdate(CollisionEventsThisFrame);
1314 }
1315 CollisionEventsThisFrame = new CollisionEventUpdate();
1316 m_eventsubscription = 0;
1317 }
1318 }
1319 public override bool SubscribedEvents()
1320 {
1321 if (m_eventsubscription > 0)
1322 return true;
1323 return false;
1324 }
1325
1326 public void ProcessTaints(float timestep)
1327 {
1328 lock (m_syncRoot)
1329 {
1330
1331 if (m_tainted_isPhysical != m_isPhysical)
1332 {
1333 if (m_tainted_isPhysical)
1334 {
1335 // Create avatar capsule and related ODE data
1336 if (!(Shell == IntPtr.Zero && Body == IntPtr.Zero && Amotor == IntPtr.Zero))
1337 {
1338 m_log.Warn("[PHYSICS]: re-creating the following avatar ODE data, even though it already exists - "
1339 + (Shell!=IntPtr.Zero ? "Shell ":"")
1340 + (Body!=IntPtr.Zero ? "Body ":"")
1341 + (Amotor!=IntPtr.Zero ? "Amotor ":""));
1342 }
1343 AvatarGeomAndBodyCreation(_position.X, _position.Y, _position.Z, m_tensor);
1344 _parent_scene.AddCharacter(this);
1345 }
1346 else
1347 {
1348 _parent_scene.RemoveCharacter(this);
1349 // destroy avatar capsule and related ODE data
1350 if (Amotor != IntPtr.Zero)
1351 {
1352 // Kill the Amotor
1353 d.JointDestroy(Amotor);
1354 Amotor = IntPtr.Zero;
1355 }
1356 //kill the Geometry
1357 _parent_scene.waitForSpaceUnlock(_parent_scene.space);
1358
1359 if (Body != IntPtr.Zero)
1360 {
1361 //kill the body
1362 d.BodyDestroy(Body);
1363 Body = IntPtr.Zero;
1364 }
1365
1366 if(Shell != IntPtr.Zero)
1367 {
1368 try
1369 {
1370 d.GeomDestroy(Shell);
1371 }
1372 catch (System.AccessViolationException)
1373 {
1374 m_log.Error("[PHYSICS]: PrimGeom dead");
1375 }
1376 // Remove any old entries
1377 //string tShell;
1378 //_parent_scene.geom_name_map.TryGetValue(Shell, out tShell);
1379 //Console.WriteLine("**** Remove {0}", tShell);
1380
1381 if(_parent_scene.geom_name_map.ContainsKey(Shell)) _parent_scene.geom_name_map.Remove(Shell);
1382 if(_parent_scene.actor_name_map.ContainsKey(Shell)) _parent_scene.actor_name_map.Remove(Shell);
1383 Shell = IntPtr.Zero;
1384 }
1385 }
1386
1387 m_isPhysical = m_tainted_isPhysical;
1388 }
1389
1390 if (m_tainted_CAPSULE_LENGTH != CAPSULE_LENGTH)
1391 {
1392 if (Shell != IntPtr.Zero && Body != IntPtr.Zero && Amotor != IntPtr.Zero)
1393 {
1394
1395 m_pidControllerActive = true;
1396 // no lock needed on _parent_scene.OdeLock because we are called from within the thread lock in OdePlugin's simulate()
1397 d.JointDestroy(Amotor);
1398 float prevCapsule = CAPSULE_LENGTH;
1399 CAPSULE_LENGTH = m_tainted_CAPSULE_LENGTH;
1400 //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
1401 d.BodyDestroy(Body);
1402 AvatarGeomAndBodyCreation(_position.X, _position.Y,
1403 _position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2), m_tensor);
1404 Velocity = Vector3.Zero;
1405 }
1406 else
1407 {
1408 m_log.Warn("[PHYSICS]: trying to change capsule size, but the following ODE data is missing - "
1409 + (Shell==IntPtr.Zero ? "Shell ":"")
1410 + (Body==IntPtr.Zero ? "Body ":"")
1411 + (Amotor==IntPtr.Zero ? "Amotor ":""));
1412 }
1413 }
1414
1415 if (!m_taintPosition.ApproxEquals(_position, 0.05f))
1416 {
1417 if (Body != IntPtr.Zero)
1418 {
1419 d.BodySetPosition(Body, m_taintPosition.X, m_taintPosition.Y, m_taintPosition.Z);
1420
1421 _position.X = m_taintPosition.X;
1422 _position.Y = m_taintPosition.Y;
1423 _position.Z = m_taintPosition.Z;
1424 }
1425 }
1426
1427 }
1428 }
1429
1430 internal void AddCollisionFrameTime(int p)
1431 {
1432 // protect it from overflow crashing
1433 if (m_eventsubscription + p >= int.MaxValue)
1434 m_eventsubscription = 0;
1435 m_eventsubscription += p;
1436 }
1437 }
1438}
diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs
new file mode 100644
index 0000000..42e22ff
--- /dev/null
+++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs
@@ -0,0 +1,3875 @@
1/* Copyright (c) Contributors, http://opensimulator.org/
2 * See CONTRIBUTORS.TXT for a full list of copyright holders.
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are met:
5 * * Redistributions of source code must retain the above copyright
6 * notice, this list of conditions and the following disclaimer.
7 * * Redistributions in binary form must reproduce the above copyright
8 * notice, this list of conditions and the following disclaimer in the
9 * documentation and/or other materials provided with the distribution.
10 * * Neither the name of the OpenSimulator Project nor the
11 * names of its contributors may be used to endorse or promote products
12 * derived from this software without specific prior written permission.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 * Revised March 5th 2010 by Kitto Flora. ODEDynamics.cs
26 * rolled into ODEPrim.cs
27 */
28
29using System;
30using System.Collections.Generic;
31using System.Reflection;
32using System.Runtime.InteropServices;
33using System.Threading;
34using log4net;
35using OpenMetaverse;
36using Ode.NET;
37using OpenSim.Framework;
38using OpenSim.Region.Physics.Manager;
39
40
41namespace OpenSim.Region.Physics.OdePlugin
42{
43 /// <summary>
44 /// Various properties that ODE uses for AMotors but isn't exposed in ODE.NET so we must define them ourselves.
45 /// </summary>
46
47 public class OdePrim : PhysicsActor
48 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50
51 private Vector3 _position;
52 private Vector3 _velocity;
53 private Vector3 _torque;
54 private Vector3 m_lastVelocity;
55 private Vector3 m_lastposition;
56 private Quaternion m_lastorientation = new Quaternion();
57 private Vector3 m_rotationalVelocity;
58 private Vector3 _size;
59 private Vector3 _acceleration;
60 // private d.Vector3 _zeroPosition = new d.Vector3(0.0f, 0.0f, 0.0f);
61 private Quaternion _orientation;
62 private Vector3 m_taintposition;
63 private Vector3 m_taintsize;
64 private Vector3 m_taintVelocity;
65 private Vector3 m_taintTorque;
66 private Quaternion m_taintrot;
67 private Vector3 m_rotateEnable = Vector3.One; // Current setting
68 private Vector3 m_rotateEnableRequest = Vector3.One; // Request from LSL
69 private bool m_rotateEnableUpdate = false;
70 private Vector3 m_lockX;
71 private Vector3 m_lockY;
72 private Vector3 m_lockZ;
73 private IntPtr Amotor = IntPtr.Zero;
74 private IntPtr AmotorX = IntPtr.Zero;
75 private IntPtr AmotorY = IntPtr.Zero;
76 private IntPtr AmotorZ = IntPtr.Zero;
77
78 private Vector3 m_PIDTarget;
79 private float m_PIDTau;
80 private float PID_D = 35f;
81 private float PID_G = 25f;
82 private bool m_usePID = false;
83
84 private Quaternion m_APIDTarget = new Quaternion();
85 private float m_APIDStrength = 0.5f;
86 private float m_APIDDamping = 0.5f;
87 private bool m_useAPID = false;
88 private float m_APIDdamper = 1.0f;
89
90 // These next 7 params apply to llSetHoverHeight(float height, integer water, float tau),
91 // do not confuse with VEHICLE HOVER
92
93 private float m_PIDHoverHeight;
94 private float m_PIDHoverTau;
95 private bool m_useHoverPID;
96 private PIDHoverType m_PIDHoverType = PIDHoverType.Ground;
97 private float m_targetHoverHeight;
98 private float m_groundHeight;
99 private float m_waterHeight;
100 private float m_buoyancy; //m_buoyancy set by llSetBuoyancy()
101
102 // private float m_tensor = 5f;
103 private int body_autodisable_frames = 20;
104
105
106 private const CollisionCategories m_default_collisionFlags = (CollisionCategories.Geom
107 | CollisionCategories.Space
108 | CollisionCategories.Body
109 | CollisionCategories.Character
110 );
111 private bool m_taintshape;
112 private bool m_taintPhysics;
113 private bool m_collidesLand = true;
114 private bool m_collidesWater;
115 public bool m_returnCollisions;
116
117 // Default we're a Geometry
118 private CollisionCategories m_collisionCategories = (CollisionCategories.Geom);
119
120 // Default, Collide with Other Geometries, spaces and Bodies
121 private CollisionCategories m_collisionFlags = m_default_collisionFlags;
122
123 public bool m_taintremove;
124 public bool m_taintdisable;
125 public bool m_disabled;
126 public bool m_taintadd;
127 public bool m_taintselected;
128 public bool m_taintCollidesWater;
129
130 public uint m_localID;
131
132 //public GCHandle gc;
133 private CollisionLocker ode;
134
135 private bool m_meshfailed = false;
136 private bool m_taintforce = false;
137 private bool m_taintaddangularforce = false;
138 private Vector3 m_force;
139 private List<Vector3> m_forcelist = new List<Vector3>();
140 private List<Vector3> m_angularforcelist = new List<Vector3>();
141
142 private IMesh _mesh;
143 private PrimitiveBaseShape _pbs;
144 private OdeScene _parent_scene;
145 public IntPtr m_targetSpace = IntPtr.Zero;
146 public IntPtr prim_geom;
147// public IntPtr prev_geom;
148 public IntPtr _triMeshData;
149
150 private IntPtr _linkJointGroup = IntPtr.Zero;
151 private PhysicsActor _parent;
152 private PhysicsActor m_taintparent;
153
154 private List<OdePrim> childrenPrim = new List<OdePrim>();
155
156 private bool iscolliding;
157 private bool m_isphysical;
158 private bool m_isSelected;
159
160 internal bool m_isVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively
161
162 private bool m_throttleUpdates;
163 private int throttleCounter;
164 public int m_interpenetrationcount;
165 public float m_collisionscore;
166 public int m_roundsUnderMotionThreshold;
167 private int m_crossingfailures;
168
169 public bool outofBounds;
170 private float m_density = 10.000006836f; // Aluminum g/cm3;
171
172 public bool _zeroFlag; // if body has been stopped
173 private bool m_lastUpdateSent;
174
175 public IntPtr Body = IntPtr.Zero;
176 public String m_primName;
177 private Vector3 _target_velocity;
178 public d.Mass pMass;
179
180 public int m_eventsubscription;
181 private CollisionEventUpdate CollisionEventsThisFrame;
182
183 private IntPtr m_linkJoint = IntPtr.Zero;
184
185 public volatile bool childPrim;
186
187 internal int m_material = (int)Material.Wood;
188
189 private int frcount = 0; // Used to limit dynamics debug output to
190 private int revcount = 0; // Reverse motion while > 0
191
192 private IntPtr m_body = IntPtr.Zero;
193
194 // Vehicle properties ============================================================================================
195 private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind
196 // private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier
197 private VehicleFlag m_flags = (VehicleFlag) 0; // Bit settings:
198 // HOVER_TERRAIN_ONLY
199 // HOVER_GLOBAL_HEIGHT
200 // NO_DEFLECTION_UP
201 // HOVER_WATER_ONLY
202 // HOVER_UP_ONLY
203 // LIMIT_MOTOR_UP
204 // LIMIT_ROLL_ONLY
205
206 // Linear properties
207 private Vector3 m_linearMotorDirection = Vector3.Zero; // (was m_linearMotorDirectionLASTSET) the (local) Velocity
208 //requested by LSL
209 private float m_linearMotorTimescale = 0; // Motor Attack rate set by LSL
210 private float m_linearMotorDecayTimescale = 0; // Motor Decay rate set by LSL
211 private Vector3 m_linearFrictionTimescale = Vector3.Zero; // General Friction set by LSL
212
213 private Vector3 m_lLinMotorDVel = Vector3.Zero; // decayed motor
214 private Vector3 m_lLinObjectVel = Vector3.Zero; // local frame object velocity
215 private Vector3 m_wLinObjectVel = Vector3.Zero; // world frame object velocity
216
217 //Angular properties
218 private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor
219
220 private float m_angularMotorTimescale = 0; // motor angular Attack rate set by LSL
221 private float m_angularMotorDecayTimescale = 0; // motor angular Decay rate set by LSL
222 private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular Friction set by LSL
223
224 private Vector3 m_angularMotorDVel = Vector3.Zero; // decayed angular motor
225// private Vector3 m_angObjectVel = Vector3.Zero; // current body angular velocity
226 private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body
227
228 //Deflection properties
229 // private float m_angularDeflectionEfficiency = 0;
230 // private float m_angularDeflectionTimescale = 0;
231 // private float m_linearDeflectionEfficiency = 0;
232 // private float m_linearDeflectionTimescale = 0;
233
234 //Banking properties
235 // private float m_bankingEfficiency = 0;
236 // private float m_bankingMix = 0;
237 // private float m_bankingTimescale = 0;
238
239 //Hover and Buoyancy properties
240 private float m_VhoverHeight = 0f;
241// private float m_VhoverEfficiency = 0f;
242 private float m_VhoverTimescale = 0f;
243 private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height
244 private float m_VehicleBuoyancy = 0f; // Set by VEHICLE_BUOYANCY, for a vehicle.
245 // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity)
246 // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity.
247 // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity.
248
249 //Attractor properties
250 private float m_verticalAttractionEfficiency = 1.0f; // damped
251 private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor.
252
253
254
255
256
257
258 public OdePrim(String primName, OdeScene parent_scene, Vector3 pos, Vector3 size,
259 Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical, CollisionLocker dode, uint localid)
260 {
261 m_localID = localid;
262 ode = dode;
263 if (!pos.IsFinite())
264 {
265 pos = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f),
266 parent_scene.GetTerrainHeightAtXY(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f)) + 0.5f);
267 m_log.Warn("[PHYSICS]: Got nonFinite Object create Position");
268 }
269
270 _position = pos;
271 m_taintposition = pos;
272 PID_D = parent_scene.bodyPIDD;
273 PID_G = parent_scene.bodyPIDG;
274 m_density = parent_scene.geomDefaultDensity;
275 // m_tensor = parent_scene.bodyMotorJointMaxforceTensor;
276 body_autodisable_frames = parent_scene.bodyFramesAutoDisable;
277
278
279 prim_geom = IntPtr.Zero;
280// prev_geom = IntPtr.Zero;
281
282 if (!pos.IsFinite())
283 {
284 size = new Vector3(0.5f, 0.5f, 0.5f);
285 m_log.Warn("[PHYSICS]: Got nonFinite Object create Size");
286 }
287
288 if (size.X <= 0) size.X = 0.01f;
289 if (size.Y <= 0) size.Y = 0.01f;
290 if (size.Z <= 0) size.Z = 0.01f;
291
292 _size = size;
293 m_taintsize = _size;
294
295 if (!QuaternionIsFinite(rotation))
296 {
297 rotation = Quaternion.Identity;
298 m_log.Warn("[PHYSICS]: Got nonFinite Object create Rotation");
299 }
300
301 _orientation = rotation;
302 m_taintrot = _orientation;
303 _mesh = mesh;
304 _pbs = pbs;
305
306 _parent_scene = parent_scene;
307 m_targetSpace = (IntPtr)0;
308
309// if (pos.Z < 0)
310 if (pos.Z < parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y))
311 m_isphysical = false;
312 else
313 {
314 m_isphysical = pisPhysical;
315 // If we're physical, we need to be in the master space for now.
316 // linksets *should* be in a space together.. but are not currently
317 if (m_isphysical)
318 m_targetSpace = _parent_scene.space;
319 }
320 m_primName = primName;
321 m_taintadd = true;
322 _parent_scene.AddPhysicsActorTaint(this);
323 // don't do .add() here; old geoms get recycled with the same hash
324 }
325
326 public override int PhysicsActorType
327 {
328 get { return (int) ActorTypes.Prim; }
329 set { return; }
330 }
331
332 public override bool SetAlwaysRun
333 {
334 get { return false; }
335 set { return; }
336 }
337
338 public override uint LocalID
339 {
340 set {
341 //m_log.Info("[PHYSICS]: Setting TrackerID: " + value);
342 m_localID = value; }
343 }
344
345 public override bool Grabbed
346 {
347 set { return; }
348 }
349
350 public override bool Selected
351 {
352 set {
353
354//Console.WriteLine("Sel {0} {1} {2}", m_primName, value, m_isphysical);
355 // This only makes the object not collidable if the object
356 // is physical or the object is modified somehow *IN THE FUTURE*
357 // without this, if an avatar selects prim, they can walk right
358 // through it while it's selected
359 m_collisionscore = 0;
360 if ((m_isphysical && !_zeroFlag) || !value)
361 {
362 m_taintselected = value;
363 _parent_scene.AddPhysicsActorTaint(this);
364 }
365 else
366 {
367 m_taintselected = value;
368 m_isSelected = value;
369 }
370 if(m_isSelected) disableBodySoft();
371 }
372 }
373
374 public override bool IsPhysical
375 {
376 get { return m_isphysical; }
377 set
378 {
379 m_isphysical = value;
380 if (!m_isphysical)
381 { // Zero the remembered last velocity
382 m_lastVelocity = Vector3.Zero;
383 if (m_type != Vehicle.TYPE_NONE) Halt();
384 }
385 }
386 }
387
388 public void setPrimForRemoval()
389 {
390 m_taintremove = true;
391 }
392
393 public override bool Flying
394 {
395 // no flying prims for you
396 get { return false; }
397 set { }
398 }
399
400 public override bool IsColliding
401 {
402 get { return iscolliding; }
403 set { iscolliding = value; }
404 }
405
406 public override bool CollidingGround
407 {
408 get { return false; }
409 set { return; }
410 }
411
412 public override bool CollidingObj
413 {
414 get { return false; }
415 set { return; }
416 }
417
418 public override bool ThrottleUpdates
419 {
420 get { return m_throttleUpdates; }
421 set { m_throttleUpdates = value; }
422 }
423
424 public override bool Stopped
425 {
426 get { return _zeroFlag; }
427 }
428
429 public override Vector3 Position
430 {
431 get { return _position; }
432
433 set { _position = value;
434 //m_log.Info("[PHYSICS]: " + _position.ToString());
435 }
436 }
437
438 public override Vector3 Size
439 {
440 get { return _size; }
441 set
442 {
443 if (value.IsFinite())
444 {
445 _size = value;
446 }
447 else
448 {
449 m_log.Warn("[PHYSICS]: Got NaN Size on object");
450 }
451 }
452 }
453
454 public override float Mass
455 {
456 get { return CalculateMass(); }
457 }
458
459 public override Vector3 Force
460 {
461 //get { return Vector3.Zero; }
462 get { return m_force; }
463 set
464 {
465 if (value.IsFinite())
466 {
467 m_force = value;
468 }
469 else
470 {
471 m_log.Warn("[PHYSICS]: NaN in Force Applied to an Object");
472 }
473 }
474 }
475
476 public override int VehicleType
477 {
478 get { return (int)m_type; }
479 set { ProcessTypeChange((Vehicle)value); }
480 }
481
482 public override void VehicleFloatParam(int param, float value)
483 {
484 ProcessFloatVehicleParam((Vehicle) param, value);
485 }
486
487 public override void VehicleVectorParam(int param, Vector3 value)
488 {
489 ProcessVectorVehicleParam((Vehicle) param, value);
490 }
491
492 public override void VehicleRotationParam(int param, Quaternion rotation)
493 {
494 ProcessRotationVehicleParam((Vehicle) param, rotation);
495 }
496
497 public override void VehicleFlags(int param, bool remove)
498 {
499 ProcessVehicleFlags(param, remove);
500 }
501
502 public override void SetVolumeDetect(int param)
503 {
504 lock (_parent_scene.OdeLock)
505 {
506 m_isVolumeDetect = (param!=0);
507 }
508 }
509
510 public override Vector3 CenterOfMass
511 {
512 get { return Vector3.Zero; }
513 }
514
515 public override Vector3 GeometricCenter
516 {
517 get { return Vector3.Zero; }
518 }
519
520 public override PrimitiveBaseShape Shape
521 {
522 set
523 {
524 _pbs = value;
525 m_taintshape = true;
526 }
527 }
528
529 public override Vector3 Velocity
530 {
531 get
532 {
533 // Averate previous velocity with the new one so
534 // client object interpolation works a 'little' better
535 if (_zeroFlag)
536 return Vector3.Zero;
537
538 Vector3 returnVelocity = Vector3.Zero;
539 returnVelocity.X = (m_lastVelocity.X + _velocity.X)/2;
540 returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y)/2;
541 returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z)/2;
542 return returnVelocity;
543 }
544 set
545 {
546 if (value.IsFinite())
547 {
548 _velocity = value;
549 if (_velocity.ApproxEquals(Vector3.Zero,0.001f))
550 _acceleration = Vector3.Zero;
551
552 m_taintVelocity = value;
553 _parent_scene.AddPhysicsActorTaint(this);
554 }
555 else
556 {
557 m_log.Warn("[PHYSICS]: Got NaN Velocity in Object");
558 }
559
560 }
561 }
562
563 public override Vector3 Torque
564 {
565 get
566 {
567 if (!m_isphysical || Body == IntPtr.Zero)
568 return Vector3.Zero;
569
570 return _torque;
571 }
572
573 set
574 {
575 if (value.IsFinite())
576 {
577 m_taintTorque = value;
578 _parent_scene.AddPhysicsActorTaint(this);
579 }
580 else
581 {
582 m_log.Warn("[PHYSICS]: Got NaN Torque in Object");
583 }
584 }
585 }
586
587 public override float CollisionScore
588 {
589 get { return m_collisionscore; }
590 set { m_collisionscore = value; }
591 }
592
593 public override bool Kinematic
594 {
595 get { return false; }
596 set { }
597 }
598
599 public override Quaternion Orientation
600 {
601 get { return _orientation; }
602 set
603 {
604 if (QuaternionIsFinite(value))
605 {
606 _orientation = value;
607 }
608 else
609 m_log.Warn("[PHYSICS]: Got NaN quaternion Orientation from Scene in Object");
610
611 }
612 }
613
614
615 public override bool FloatOnWater
616 {
617 set {
618 m_taintCollidesWater = value;
619 _parent_scene.AddPhysicsActorTaint(this);
620 }
621 }
622
623 public override void SetMomentum(Vector3 momentum)
624 {
625 }
626
627 public override Vector3 PIDTarget
628 {
629 set
630 {
631 if (value.IsFinite())
632 {
633 m_PIDTarget = value;
634 }
635 else
636 m_log.Warn("[PHYSICS]: Got NaN PIDTarget from Scene on Object");
637 }
638 }
639 public override bool PIDActive { set { m_usePID = value; } }
640 public override float PIDTau { set { m_PIDTau = value; } }
641
642 // For RotLookAt
643 public override Quaternion APIDTarget { set { m_APIDTarget = value; } }
644 public override bool APIDActive { set { m_useAPID = value; } }
645 public override float APIDStrength { set { m_APIDStrength = value; } }
646 public override float APIDDamping { set { m_APIDDamping = value; } }
647
648 public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } }
649 public override bool PIDHoverActive { set { m_useHoverPID = value; } }
650 public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } }
651 public override float PIDHoverTau { set { m_PIDHoverTau = value; } }
652
653 internal static bool QuaternionIsFinite(Quaternion q)
654 {
655 if (Single.IsNaN(q.X) || Single.IsInfinity(q.X))
656 return false;
657 if (Single.IsNaN(q.Y) || Single.IsInfinity(q.Y))
658 return false;
659 if (Single.IsNaN(q.Z) || Single.IsInfinity(q.Z))
660 return false;
661 if (Single.IsNaN(q.W) || Single.IsInfinity(q.W))
662 return false;
663 return true;
664 }
665
666 public override Vector3 Acceleration // client updates read data via here
667 {
668 get
669 {
670 if (_zeroFlag)
671 {
672 return Vector3.Zero;
673 }
674 return _acceleration;
675 }
676 set { _acceleration = value; }
677 }
678
679
680 public void SetAcceleration(Vector3 accel) // No one calls this, and it would not do anything.
681 {
682 _acceleration = accel;
683 }
684
685 public override void AddForce(Vector3 force, bool pushforce)
686 {
687 if (force.IsFinite())
688 {
689 lock (m_forcelist)
690 m_forcelist.Add(force);
691
692 m_taintforce = true;
693 }
694 else
695 {
696 m_log.Warn("[PHYSICS]: Got Invalid linear force vector from Scene in Object");
697 }
698 //m_log.Info("[PHYSICS]: Added Force:" + force.ToString() + " to prim at " + Position.ToString());
699 }
700
701 public override void AddAngularForce(Vector3 force, bool pushforce)
702 {
703 if (force.IsFinite())
704 {
705 m_angularforcelist.Add(force);
706 m_taintaddangularforce = true;
707 }
708 else
709 {
710 m_log.Warn("[PHYSICS]: Got Invalid Angular force vector from Scene in Object");
711 }
712 }
713
714 public override Vector3 RotationalVelocity
715 {
716 get
717 {
718 return m_rotationalVelocity;
719 }
720 set
721 {
722 if (value.IsFinite())
723 {
724 m_rotationalVelocity = value;
725 }
726 else
727 {
728 m_log.Warn("[PHYSICS]: Got NaN RotationalVelocity in Object");
729 }
730 }
731 }
732
733 public override void CrossingFailure()
734 {
735 m_crossingfailures++;
736 if (m_crossingfailures > _parent_scene.geomCrossingFailuresBeforeOutofbounds)
737 {
738 base.RaiseOutOfBounds(_position);
739 return;
740 }
741 else if (m_crossingfailures == _parent_scene.geomCrossingFailuresBeforeOutofbounds)
742 {
743 m_log.Warn("[PHYSICS]: Too many crossing failures for: " + m_primName);
744 }
745 }
746
747 public override float Buoyancy
748 {
749 get { return m_buoyancy; }
750 set { m_buoyancy = value; }
751 }
752
753 public override void link(PhysicsActor obj)
754 {
755 m_taintparent = obj;
756 }
757
758 public override void delink()
759 {
760 m_taintparent = null;
761 }
762
763 public override void LockAngularMotion(Vector3 axis)
764 {
765 // This is actually ROTATION ENABLE, not a lock.
766 // default is <1,1,1> which is all enabled.
767 // The lock value is updated inside Move(), no point in using the taint system.
768 // OS 'm_taintAngularLock' etc change to m_rotateEnable.
769 if (axis.IsFinite())
770 {
771 axis.X = (axis.X > 0) ? 1f : 0f;
772 axis.Y = (axis.Y > 0) ? 1f : 0f;
773 axis.Z = (axis.Z > 0) ? 1f : 0f;
774 m_log.DebugFormat("[axislock]: <{0},{1},{2}>", axis.X, axis.Y, axis.Z);
775 m_rotateEnableRequest = axis;
776 m_rotateEnableUpdate = true;
777 }
778 else
779 {
780 m_log.Warn("[PHYSICS]: Got NaN locking axis from Scene on Object");
781 }
782 }
783
784
785 public void SetGeom(IntPtr geom)
786 {
787 if(prim_geom != IntPtr.Zero)
788 {
789 // Remove any old entries
790//string tPA;
791//_parent_scene.geom_name_map.TryGetValue(prim_geom, out tPA);
792//Console.WriteLine("**** Remove {0}", tPA);
793 if(_parent_scene.geom_name_map.ContainsKey(prim_geom)) _parent_scene.geom_name_map.Remove(prim_geom);
794 if(_parent_scene.actor_name_map.ContainsKey(prim_geom)) _parent_scene.actor_name_map.Remove(prim_geom);
795 d.GeomDestroy(prim_geom);
796 }
797
798 prim_geom = geom;
799//Console.WriteLine("SetGeom to " + prim_geom + " for " + m_primName);
800 if (prim_geom != IntPtr.Zero)
801 {
802 _parent_scene.geom_name_map[prim_geom] = this.m_primName;
803 _parent_scene.actor_name_map[prim_geom] = (PhysicsActor)this;
804 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
805 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
806//Console.WriteLine("**** Create {2} Dicts: actor={0} name={1}", _parent_scene.actor_name_map.Count, _parent_scene.geom_name_map.Count, this.m_primName);
807 }
808
809 if (childPrim)
810 {
811 if (_parent != null && _parent is OdePrim)
812 {
813 OdePrim parent = (OdePrim)_parent;
814//Console.WriteLine("SetGeom calls ChildSetGeom");
815 parent.ChildSetGeom(this);
816 }
817 }
818 //m_log.Warn("Setting Geom to: " + prim_geom);
819 }
820
821 public void enableBodySoft()
822 {
823 if (!childPrim)
824 {
825 if (m_isphysical && Body != IntPtr.Zero)
826 {
827 d.BodyEnable(Body);
828 if (m_type != Vehicle.TYPE_NONE)
829 Enable(Body, _parent_scene);
830 }
831
832 m_disabled = false;
833 }
834 }
835
836 public void disableBodySoft()
837 {
838 m_disabled = true;
839
840 if (m_isphysical && Body != IntPtr.Zero)
841 {
842 d.BodyDisable(Body);
843 Halt();
844 }
845 }
846
847 public void enableBody()
848 {
849 // Don't enable this body if we're a child prim
850 // this should be taken care of in the parent function not here
851 if (!childPrim)
852 {
853 // Sets the geom to a body
854 Body = d.BodyCreate(_parent_scene.world);
855
856 setMass();
857 d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
858 d.Quaternion myrot = new d.Quaternion();
859 myrot.X = _orientation.X;
860 myrot.Y = _orientation.Y;
861 myrot.Z = _orientation.Z;
862 myrot.W = _orientation.W;
863 d.BodySetQuaternion(Body, ref myrot);
864 d.GeomSetBody(prim_geom, Body);
865 m_collisionCategories |= CollisionCategories.Body;
866 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
867
868 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
869 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
870
871 d.BodySetAutoDisableFlag(Body, true);
872 d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
873
874 // disconnect from world gravity so we can apply buoyancy
875 d.BodySetGravityMode (Body, false);
876
877 m_interpenetrationcount = 0;
878 m_collisionscore = 0;
879 m_disabled = false;
880
881 if (m_type != Vehicle.TYPE_NONE)
882 {
883 Enable(Body, _parent_scene);
884 }
885
886 _parent_scene.addActivePrim(this);
887 }
888 }
889
890 #region Mass Calculation
891
892 private float CalculateMass()
893 {
894 float volume = _size.X * _size.Y * _size.Z; // default
895 float tmp;
896
897 float returnMass = 0;
898 float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f;
899 float hollowVolume = hollowAmount * hollowAmount;
900
901 switch (_pbs.ProfileShape)
902 {
903 case ProfileShape.Square:
904 // default box
905
906 if (_pbs.PathCurve == (byte)Extrusion.Straight)
907 {
908 if (hollowAmount > 0.0)
909 {
910 switch (_pbs.HollowShape)
911 {
912 case HollowShape.Square:
913 case HollowShape.Same:
914 break;
915
916 case HollowShape.Circle:
917
918 hollowVolume *= 0.78539816339f;
919 break;
920
921 case HollowShape.Triangle:
922
923 hollowVolume *= (0.5f * .5f);
924 break;
925
926 default:
927 hollowVolume = 0;
928 break;
929 }
930 volume *= (1.0f - hollowVolume);
931 }
932 }
933
934 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
935 {
936 //a tube
937
938 volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX);
939 tmp= 1.0f -2.0e-2f * (float)(200 - _pbs.PathScaleY);
940 volume -= volume*tmp*tmp;
941
942 if (hollowAmount > 0.0)
943 {
944 hollowVolume *= hollowAmount;
945
946 switch (_pbs.HollowShape)
947 {
948 case HollowShape.Square:
949 case HollowShape.Same:
950 break;
951
952 case HollowShape.Circle:
953 hollowVolume *= 0.78539816339f;;
954 break;
955
956 case HollowShape.Triangle:
957 hollowVolume *= 0.5f * 0.5f;
958 break;
959 default:
960 hollowVolume = 0;
961 break;
962 }
963 volume *= (1.0f - hollowVolume);
964 }
965 }
966
967 break;
968
969 case ProfileShape.Circle:
970
971 if (_pbs.PathCurve == (byte)Extrusion.Straight)
972 {
973 volume *= 0.78539816339f; // elipse base
974
975 if (hollowAmount > 0.0)
976 {
977 switch (_pbs.HollowShape)
978 {
979 case HollowShape.Same:
980 case HollowShape.Circle:
981 break;
982
983 case HollowShape.Square:
984 hollowVolume *= 0.5f * 2.5984480504799f;
985 break;
986
987 case HollowShape.Triangle:
988 hollowVolume *= .5f * 1.27323954473516f;
989 break;
990
991 default:
992 hollowVolume = 0;
993 break;
994 }
995 volume *= (1.0f - hollowVolume);
996 }
997 }
998
999 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
1000 {
1001 volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX);
1002 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
1003 volume *= (1.0f - tmp * tmp);
1004
1005 if (hollowAmount > 0.0)
1006 {
1007
1008 // calculate the hollow volume by it's shape compared to the prim shape
1009 hollowVolume *= hollowAmount;
1010
1011 switch (_pbs.HollowShape)
1012 {
1013 case HollowShape.Same:
1014 case HollowShape.Circle:
1015 break;
1016
1017 case HollowShape.Square:
1018 hollowVolume *= 0.5f * 2.5984480504799f;
1019 break;
1020
1021 case HollowShape.Triangle:
1022 hollowVolume *= .5f * 1.27323954473516f;
1023 break;
1024
1025 default:
1026 hollowVolume = 0;
1027 break;
1028 }
1029 volume *= (1.0f - hollowVolume);
1030 }
1031 }
1032 break;
1033
1034 case ProfileShape.HalfCircle:
1035 if (_pbs.PathCurve == (byte)Extrusion.Curve1)
1036 {
1037 volume *= 0.52359877559829887307710723054658f;
1038 }
1039 break;
1040
1041 case ProfileShape.EquilateralTriangle:
1042
1043 if (_pbs.PathCurve == (byte)Extrusion.Straight)
1044 {
1045 volume *= 0.32475953f;
1046
1047 if (hollowAmount > 0.0)
1048 {
1049
1050 // calculate the hollow volume by it's shape compared to the prim shape
1051 switch (_pbs.HollowShape)
1052 {
1053 case HollowShape.Same:
1054 case HollowShape.Triangle:
1055 hollowVolume *= .25f;
1056 break;
1057
1058 case HollowShape.Square:
1059 hollowVolume *= 0.499849f * 3.07920140172638f;
1060 break;
1061
1062 case HollowShape.Circle:
1063 // Hollow shape is a perfect cyllinder in respect to the cube's scale
1064 // Cyllinder hollow volume calculation
1065
1066 hollowVolume *= 0.1963495f * 3.07920140172638f;
1067 break;
1068
1069 default:
1070 hollowVolume = 0;
1071 break;
1072 }
1073 volume *= (1.0f - hollowVolume);
1074 }
1075 }
1076 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
1077 {
1078 volume *= 0.32475953f;
1079 volume *= 0.01f * (float)(200 - _pbs.PathScaleX);
1080 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
1081 volume *= (1.0f - tmp * tmp);
1082
1083 if (hollowAmount > 0.0)
1084 {
1085
1086 hollowVolume *= hollowAmount;
1087
1088 switch (_pbs.HollowShape)
1089 {
1090 case HollowShape.Same:
1091 case HollowShape.Triangle:
1092 hollowVolume *= .25f;
1093 break;
1094
1095 case HollowShape.Square:
1096 hollowVolume *= 0.499849f * 3.07920140172638f;
1097 break;
1098
1099 case HollowShape.Circle:
1100
1101 hollowVolume *= 0.1963495f * 3.07920140172638f;
1102 break;
1103
1104 default:
1105 hollowVolume = 0;
1106 break;
1107 }
1108 volume *= (1.0f - hollowVolume);
1109 }
1110 }
1111 break;
1112
1113 default:
1114 break;
1115 }
1116
1117
1118
1119 float taperX1;
1120 float taperY1;
1121 float taperX;
1122 float taperY;
1123 float pathBegin;
1124 float pathEnd;
1125 float profileBegin;
1126 float profileEnd;
1127
1128 if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible)
1129 {
1130 taperX1 = _pbs.PathScaleX * 0.01f;
1131 if (taperX1 > 1.0f)
1132 taperX1 = 2.0f - taperX1;
1133 taperX = 1.0f - taperX1;
1134
1135 taperY1 = _pbs.PathScaleY * 0.01f;
1136 if (taperY1 > 1.0f)
1137 taperY1 = 2.0f - taperY1;
1138 taperY = 1.0f - taperY1;
1139 }
1140 else
1141 {
1142 taperX = _pbs.PathTaperX * 0.01f;
1143 if (taperX < 0.0f)
1144 taperX = -taperX;
1145 taperX1 = 1.0f - taperX;
1146
1147 taperY = _pbs.PathTaperY * 0.01f;
1148 if (taperY < 0.0f)
1149 taperY = -taperY;
1150 taperY1 = 1.0f - taperY;
1151
1152 }
1153
1154
1155 volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
1156
1157 pathBegin = (float)_pbs.PathBegin * 2.0e-5f;
1158 pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f;
1159 volume *= (pathEnd - pathBegin);
1160
1161// this is crude aproximation
1162 profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f;
1163 profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f;
1164 volume *= (profileEnd - profileBegin);
1165
1166 returnMass = m_density * volume;
1167
1168 if (returnMass <= 0)
1169 returnMass = 0.0001f;//ckrinke: Mass must be greater then zero.
1170// else if (returnMass > _parent_scene.maximumMassObject)
1171// returnMass = _parent_scene.maximumMassObject;
1172
1173
1174
1175
1176 // Recursively calculate mass
1177 bool HasChildPrim = false;
1178 lock (childrenPrim)
1179 {
1180 if (childrenPrim.Count > 0)
1181 {
1182 HasChildPrim = true;
1183 }
1184
1185 }
1186 if (HasChildPrim)
1187 {
1188 OdePrim[] childPrimArr = new OdePrim[0];
1189
1190 lock (childrenPrim)
1191 childPrimArr = childrenPrim.ToArray();
1192
1193 for (int i = 0; i < childPrimArr.Length; i++)
1194 {
1195 if (childPrimArr[i] != null && !childPrimArr[i].m_taintremove)
1196 returnMass += childPrimArr[i].CalculateMass();
1197 // failsafe, this shouldn't happen but with OpenSim, you never know :)
1198 if (i > 256)
1199 break;
1200 }
1201 }
1202 if (returnMass > _parent_scene.maximumMassObject)
1203 returnMass = _parent_scene.maximumMassObject;
1204 return returnMass;
1205 }// end CalculateMass
1206
1207 #endregion
1208
1209 public void setMass()
1210 {
1211 if (Body != (IntPtr) 0)
1212 {
1213 float newmass = CalculateMass();
1214
1215 //m_log.Info("[PHYSICS]: New Mass: " + newmass.ToString());
1216
1217 d.MassSetBoxTotal(out pMass, newmass, _size.X, _size.Y, _size.Z);
1218 d.BodySetMass(Body, ref pMass);
1219 }
1220 }
1221
1222 public void disableBody()
1223 {
1224 //this kills the body so things like 'mesh' can re-create it.
1225 lock (this)
1226 {
1227 if (!childPrim)
1228 {
1229 if (Body != IntPtr.Zero)
1230 {
1231 _parent_scene.remActivePrim(this);
1232 m_collisionCategories &= ~CollisionCategories.Body;
1233 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
1234
1235 if (prim_geom != IntPtr.Zero)
1236 {
1237 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1238 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1239 }
1240
1241
1242 d.BodyDestroy(Body);
1243 lock (childrenPrim)
1244 {
1245 if (childrenPrim.Count > 0)
1246 {
1247 foreach (OdePrim prm in childrenPrim)
1248 {
1249 _parent_scene.remActivePrim(prm);
1250 prm.Body = IntPtr.Zero;
1251 }
1252 }
1253 }
1254 Body = IntPtr.Zero;
1255 }
1256 }
1257 else
1258 {
1259 _parent_scene.remActivePrim(this);
1260
1261 m_collisionCategories &= ~CollisionCategories.Body;
1262 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
1263
1264 if (prim_geom != IntPtr.Zero)
1265 {
1266 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1267 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1268 }
1269
1270
1271 Body = IntPtr.Zero;
1272 }
1273 }
1274 m_disabled = true;
1275 m_collisionscore = 0;
1276 }
1277
1278 private static Dictionary<IMesh, IntPtr> m_MeshToTriMeshMap = new Dictionary<IMesh, IntPtr>();
1279
1280 public void setMesh(OdeScene parent_scene, IMesh mesh)
1281 {
1282 // This sleeper is there to moderate how long it takes between
1283 // setting up the mesh and pre-processing it when we get rapid fire mesh requests on a single object
1284
1285 //Thread.Sleep(10);
1286
1287 //Kill Body so that mesh can re-make the geom
1288 if (IsPhysical && Body != IntPtr.Zero)
1289 {
1290 if (childPrim)
1291 {
1292 if (_parent != null)
1293 {
1294 OdePrim parent = (OdePrim)_parent;
1295 parent.ChildDelink(this);
1296 }
1297 }
1298 else
1299 {
1300 disableBody();
1301 }
1302 }
1303 IntPtr vertices, indices;
1304 int vertexCount, indexCount;
1305 int vertexStride, triStride;
1306 mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap
1307 mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage
1308
1309 mesh.releaseSourceMeshData(); // free up the original mesh data to save memory
1310 if (m_MeshToTriMeshMap.ContainsKey(mesh))
1311 {
1312 _triMeshData = m_MeshToTriMeshMap[mesh];
1313 }
1314 else
1315 {
1316 _triMeshData = d.GeomTriMeshDataCreate();
1317
1318 d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride);
1319 d.GeomTriMeshDataPreprocess(_triMeshData);
1320 m_MeshToTriMeshMap[mesh] = _triMeshData;
1321 }
1322
1323 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1324 try
1325 {
1326 // if (prim_geom == IntPtr.Zero) // setGeom takes care of phys engine recreate and prim_geom pointer
1327 // {
1328 SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null));
1329 // }
1330 }
1331 catch (AccessViolationException)
1332 {
1333 m_log.Error("[PHYSICS]: MESH LOCKED");
1334 return;
1335 }
1336
1337
1338 // if (IsPhysical && Body == (IntPtr) 0)
1339 // {
1340 // Recreate the body
1341 // m_interpenetrationcount = 0;
1342 // m_collisionscore = 0;
1343
1344 // enableBody();
1345 // }
1346 }
1347
1348 public void ProcessTaints(float timestep) //=============================================================================
1349 {
1350 if (m_taintadd)
1351 {
1352 changeadd(timestep);
1353 }
1354
1355 if (prim_geom != IntPtr.Zero)
1356 {
1357 if (!_position.ApproxEquals(m_taintposition, 0f))
1358 {
1359 changemove(timestep);
1360 }
1361 if (m_taintrot != _orientation)
1362 {
1363 if(childPrim && IsPhysical) // For physical child prim...
1364 {
1365 rotate(timestep);
1366 // KF: ODE will also rotate the parent prim!
1367 // so rotate the root back to where it was
1368 OdePrim parent = (OdePrim)_parent;
1369 parent.rotate(timestep);
1370 }
1371 else
1372 {
1373 //Just rotate the prim
1374 rotate(timestep);
1375 }
1376 }
1377 //
1378
1379 if (m_taintPhysics != m_isphysical && !(m_taintparent != _parent))
1380 {
1381 changePhysicsStatus(timestep);
1382 }//
1383
1384 if (!_size.ApproxEquals(m_taintsize,0f))
1385 changesize(timestep);
1386 //
1387
1388 if (m_taintshape)
1389 changeshape(timestep);
1390 //
1391
1392 if (m_taintforce)
1393 changeAddForce(timestep);
1394
1395 if (m_taintaddangularforce)
1396 changeAddAngularForce(timestep);
1397
1398 if (!m_taintTorque.ApproxEquals(Vector3.Zero, 0.001f))
1399 changeSetTorque(timestep);
1400
1401 if (m_taintdisable)
1402 changedisable(timestep);
1403
1404 if (m_taintselected != m_isSelected)
1405 changeSelectedStatus(timestep);
1406
1407 if (!m_taintVelocity.ApproxEquals(Vector3.Zero, 0.001f))
1408 changevelocity(timestep);
1409
1410 if (m_taintparent != _parent)
1411 changelink(timestep);
1412
1413 if (m_taintCollidesWater != m_collidesWater)
1414 changefloatonwater(timestep);
1415/* obsolete
1416 if (!m_angularLock.ApproxEquals(m_taintAngularLock,0f))
1417 changeAngularLock(timestep);
1418 */
1419 }
1420 else
1421 {
1422 m_log.Error("[PHYSICS]: The scene reused a disposed PhysActor! *waves finger*, Don't be evil. A couple of things can cause this. An improper prim breakdown(be sure to set prim_geom to zero after d.GeomDestroy! An improper buildup (creating the geom failed). Or, the Scene Reused a physics actor after disposing it.)");
1423 }
1424 }
1425
1426/* obsolete
1427 private void changeAngularLock(float timestep)
1428 {
1429 if (_parent == null)
1430 {
1431 m_angularLock = m_taintAngularLock;
1432 m_angularLockSet = true;
1433 }
1434 }
1435 */
1436 private void changelink(float timestep)
1437 {
1438 // If the newly set parent is not null
1439 // create link
1440 if (_parent == null && m_taintparent != null)
1441 {
1442 if (m_taintparent.PhysicsActorType == (int)ActorTypes.Prim)
1443 {
1444 OdePrim obj = (OdePrim)m_taintparent;
1445 //obj.disableBody();
1446 obj.ParentPrim(this);
1447
1448 /*
1449 if (obj.Body != (IntPtr)0 && Body != (IntPtr)0 && obj.Body != Body)
1450 {
1451 _linkJointGroup = d.JointGroupCreate(0);
1452 m_linkJoint = d.JointCreateFixed(_parent_scene.world, _linkJointGroup);
1453 d.JointAttach(m_linkJoint, obj.Body, Body);
1454 d.JointSetFixed(m_linkJoint);
1455 }
1456 */
1457 }
1458 }
1459 // If the newly set parent is null
1460 // destroy link
1461 else if (_parent != null && m_taintparent == null)
1462 {
1463 if (_parent is OdePrim)
1464 {
1465 OdePrim obj = (OdePrim)_parent;
1466 obj.ChildDelink(this);
1467 childPrim = false;
1468 //_parent = null;
1469 }
1470
1471 /*
1472 if (Body != (IntPtr)0 && _linkJointGroup != (IntPtr)0)
1473 d.JointGroupDestroy(_linkJointGroup);
1474
1475 _linkJointGroup = (IntPtr)0;
1476 m_linkJoint = (IntPtr)0;
1477 */
1478 }
1479
1480 _parent = m_taintparent;
1481 m_taintPhysics = m_isphysical;
1482 }
1483
1484 // I'm the parent
1485 // prim is the child
1486 public void ParentPrim(OdePrim prim)
1487 {
1488 if (this.m_localID != prim.m_localID)
1489 {
1490 if (Body == IntPtr.Zero)
1491 {
1492 Body = d.BodyCreate(_parent_scene.world);
1493 // disconnect from world gravity so we can apply buoyancy
1494 d.BodySetGravityMode (Body, false);
1495
1496 setMass();
1497 }
1498 if (Body != IntPtr.Zero)
1499 {
1500 lock (childrenPrim)
1501 {
1502 if (!childrenPrim.Contains(prim))
1503 {
1504 childrenPrim.Add(prim);
1505
1506 foreach (OdePrim prm in childrenPrim)
1507 {
1508 d.Mass m2;
1509 d.MassSetZero(out m2);
1510 d.MassSetBoxTotal(out m2, prim.CalculateMass(), prm._size.X, prm._size.Y, prm._size.Z);
1511
1512
1513 d.Quaternion quat = new d.Quaternion();
1514 quat.W = prm._orientation.W;
1515 quat.X = prm._orientation.X;
1516 quat.Y = prm._orientation.Y;
1517 quat.Z = prm._orientation.Z;
1518
1519 d.Matrix3 mat = new d.Matrix3();
1520 d.RfromQ(out mat, ref quat);
1521 d.MassRotate(ref m2, ref mat);
1522 d.MassTranslate(ref m2, Position.X - prm.Position.X, Position.Y - prm.Position.Y, Position.Z - prm.Position.Z);
1523 d.MassAdd(ref pMass, ref m2);
1524 }
1525 foreach (OdePrim prm in childrenPrim)
1526 {
1527
1528 prm.m_collisionCategories |= CollisionCategories.Body;
1529 prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1530
1531 if (prm.prim_geom == IntPtr.Zero)
1532 {
1533 m_log.Warn("[PHYSICS]: Unable to link one of the linkset elements. No geom yet");
1534 continue;
1535 }
1536 d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories);
1537 d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags);
1538
1539
1540 d.Quaternion quat = new d.Quaternion();
1541 quat.W = prm._orientation.W;
1542 quat.X = prm._orientation.X;
1543 quat.Y = prm._orientation.Y;
1544 quat.Z = prm._orientation.Z;
1545
1546 d.Matrix3 mat = new d.Matrix3();
1547 d.RfromQ(out mat, ref quat);
1548 if (Body != IntPtr.Zero)
1549 {
1550 d.GeomSetBody(prm.prim_geom, Body);
1551 prm.childPrim = true;
1552 d.GeomSetOffsetWorldPosition(prm.prim_geom, prm.Position.X , prm.Position.Y, prm.Position.Z);
1553 //d.GeomSetOffsetPosition(prim.prim_geom,
1554 // (Position.X - prm.Position.X) - pMass.c.X,
1555 // (Position.Y - prm.Position.Y) - pMass.c.Y,
1556 // (Position.Z - prm.Position.Z) - pMass.c.Z);
1557 d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat);
1558 //d.GeomSetOffsetRotation(prm.prim_geom, ref mat);
1559 d.MassTranslate(ref pMass, -pMass.c.X, -pMass.c.Y, -pMass.c.Z);
1560 d.BodySetMass(Body, ref pMass);
1561 }
1562 else
1563 {
1564 m_log.Debug("[PHYSICS]:I ain't got no boooooooooddy, no body");
1565 }
1566
1567
1568 prm.m_interpenetrationcount = 0;
1569 prm.m_collisionscore = 0;
1570 prm.m_disabled = false;
1571
1572 prm.Body = Body;
1573 _parent_scene.addActivePrim(prm);
1574 }
1575 m_collisionCategories |= CollisionCategories.Body;
1576 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1577
1578 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1579 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1580
1581
1582 d.Quaternion quat2 = new d.Quaternion();
1583 quat2.W = _orientation.W;
1584 quat2.X = _orientation.X;
1585 quat2.Y = _orientation.Y;
1586 quat2.Z = _orientation.Z;
1587
1588 d.Matrix3 mat2 = new d.Matrix3();
1589 d.RfromQ(out mat2, ref quat2);
1590 d.GeomSetBody(prim_geom, Body);
1591 d.GeomSetOffsetWorldPosition(prim_geom, Position.X - pMass.c.X, Position.Y - pMass.c.Y, Position.Z - pMass.c.Z);
1592 //d.GeomSetOffsetPosition(prim.prim_geom,
1593 // (Position.X - prm.Position.X) - pMass.c.X,
1594 // (Position.Y - prm.Position.Y) - pMass.c.Y,
1595 // (Position.Z - prm.Position.Z) - pMass.c.Z);
1596 //d.GeomSetOffsetRotation(prim_geom, ref mat2);
1597 d.MassTranslate(ref pMass, -pMass.c.X, -pMass.c.Y, -pMass.c.Z);
1598 d.BodySetMass(Body, ref pMass);
1599
1600 d.BodySetAutoDisableFlag(Body, true);
1601 d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
1602
1603
1604 m_interpenetrationcount = 0;
1605 m_collisionscore = 0;
1606 m_disabled = false;
1607
1608 d.BodySetPosition(Body, Position.X, Position.Y, Position.Z);
1609 if (m_type != Vehicle.TYPE_NONE) Enable(Body, _parent_scene);
1610 _parent_scene.addActivePrim(this);
1611 }
1612 }
1613 }
1614 }
1615
1616 }
1617
1618 private void ChildSetGeom(OdePrim odePrim)
1619 {
1620 //if (m_isphysical && Body != IntPtr.Zero)
1621 lock (childrenPrim)
1622 {
1623 foreach (OdePrim prm in childrenPrim)
1624 {
1625 //prm.childPrim = true;
1626 prm.disableBody();
1627 //prm.m_taintparent = null;
1628 //prm._parent = null;
1629 //prm.m_taintPhysics = false;
1630 //prm.m_disabled = true;
1631 //prm.childPrim = false;
1632 }
1633 }
1634 disableBody();
1635
1636
1637 if (Body != IntPtr.Zero)
1638 {
1639 _parent_scene.remActivePrim(this);
1640 }
1641
1642 lock (childrenPrim)
1643 {
1644 foreach (OdePrim prm in childrenPrim)
1645 {
1646 ParentPrim(prm);
1647 }
1648 }
1649
1650 }
1651
1652 private void ChildDelink(OdePrim odePrim)
1653 {
1654 // Okay, we have a delinked child.. need to rebuild the body.
1655 lock (childrenPrim)
1656 {
1657 foreach (OdePrim prm in childrenPrim)
1658 {
1659 prm.childPrim = true;
1660 prm.disableBody();
1661 //prm.m_taintparent = null;
1662 //prm._parent = null;
1663 //prm.m_taintPhysics = false;
1664 //prm.m_disabled = true;
1665 //prm.childPrim = false;
1666 }
1667 }
1668 disableBody();
1669
1670 lock (childrenPrim)
1671 {
1672 childrenPrim.Remove(odePrim);
1673 }
1674
1675 if (Body != IntPtr.Zero)
1676 {
1677 _parent_scene.remActivePrim(this);
1678 }
1679
1680 lock (childrenPrim)
1681 {
1682 foreach (OdePrim prm in childrenPrim)
1683 {
1684 ParentPrim(prm);
1685 }
1686 }
1687 }
1688
1689 private void changeSelectedStatus(float timestep)
1690 {
1691 if (m_taintselected)
1692 {
1693 m_collisionCategories = CollisionCategories.Selected;
1694 m_collisionFlags = (CollisionCategories.Sensor | CollisionCategories.Space);
1695
1696 // We do the body disable soft twice because 'in theory' a collision could have happened
1697 // in between the disabling and the collision properties setting
1698 // which would wake the physical body up from a soft disabling and potentially cause it to fall
1699 // through the ground.
1700
1701 // NOTE FOR JOINTS: this doesn't always work for jointed assemblies because if you select
1702 // just one part of the assembly, the rest of the assembly is non-selected and still simulating,
1703 // so that causes the selected part to wake up and continue moving.
1704
1705 // even if you select all parts of a jointed assembly, it is not guaranteed that the entire
1706 // assembly will stop simulating during the selection, because of the lack of atomicity
1707 // of select operations (their processing could be interrupted by a thread switch, causing
1708 // simulation to continue before all of the selected object notifications trickle down to
1709 // the physics engine).
1710
1711 // e.g. we select 100 prims that are connected by joints. non-atomically, the first 50 are
1712 // selected and disabled. then, due to a thread switch, the selection processing is
1713 // interrupted and the physics engine continues to simulate, so the last 50 items, whose
1714 // selection was not yet processed, continues to simulate. this wakes up ALL of the
1715 // first 50 again. then the last 50 are disabled. then the first 50, which were just woken
1716 // up, start simulating again, which in turn wakes up the last 50.
1717
1718 if (m_isphysical)
1719 {
1720 disableBodySoft();
1721 }
1722
1723 if (prim_geom != IntPtr.Zero)
1724 {
1725 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1726 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1727 }
1728
1729 if (m_isphysical)
1730 {
1731 disableBodySoft();
1732 }
1733 if (Body != IntPtr.Zero)
1734 {
1735 d.BodySetLinearVel(Body, 0f, 0f, 0f);
1736 d.BodySetForce(Body, 0f, 0f, 0f);
1737 d.BodySetAngularVel (Body, 0.0f, 0.0f, 0.0f);
1738 d.BodySetTorque (Body, 0.0f, 0.0f, 0.0f);
1739 }
1740
1741 }
1742 else
1743 {
1744 m_collisionCategories = CollisionCategories.Geom;
1745
1746 if (m_isphysical)
1747 m_collisionCategories |= CollisionCategories.Body;
1748
1749 m_collisionFlags = m_default_collisionFlags;
1750
1751 if (m_collidesLand)
1752 m_collisionFlags |= CollisionCategories.Land;
1753 if (m_collidesWater)
1754 m_collisionFlags |= CollisionCategories.Water;
1755
1756 if (prim_geom != IntPtr.Zero)
1757 {
1758 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1759 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1760 }
1761 if (Body != IntPtr.Zero)
1762 {
1763 d.BodySetLinearVel(Body, 0f, 0f, 0f);
1764 d.BodySetForce(Body, 0f, 0f, 0f);
1765 d.BodySetAngularVel (Body, 0.0f, 0.0f, 0.0f);
1766 d.BodySetTorque (Body, 0.0f, 0.0f, 0.0f);
1767 }
1768
1769 if (m_isphysical)
1770 {
1771 if (Body != IntPtr.Zero)
1772 {
1773 enableBodySoft();
1774 }
1775 }
1776 }
1777
1778 resetCollisionAccounting();
1779 m_isSelected = m_taintselected;
1780 }//end changeSelectedStatus
1781
1782 public void ResetTaints()
1783 {
1784 m_taintposition = _position;
1785 m_taintrot = _orientation;
1786 m_taintPhysics = m_isphysical;
1787 m_taintselected = m_isSelected;
1788 m_taintsize = _size;
1789 m_taintshape = false;
1790 m_taintforce = false;
1791 m_taintdisable = false;
1792 m_taintVelocity = Vector3.Zero;
1793 }
1794
1795 public void CreateGeom(IntPtr m_targetSpace, IMesh _mesh)
1796 {
1797 if (_mesh != null) // Special - make mesh
1798 {
1799 setMesh(_parent_scene, _mesh);
1800 }
1801 else // not a mesh
1802 {
1803 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) // special profile??
1804 {
1805 if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) // Equi-size
1806 {
1807 if (((_size.X / 2f) > 0f)) // Has size
1808 {
1809 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1810 try
1811 {
1812 SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2));
1813 }
1814 catch (AccessViolationException)
1815 {
1816 m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
1817 ode.dunlock(_parent_scene.world);
1818 return;
1819 }
1820 }
1821 else
1822 {
1823 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1824 try
1825 {
1826 SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
1827 }
1828 catch (AccessViolationException)
1829 {
1830 m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
1831 ode.dunlock(_parent_scene.world);
1832 return;
1833 }
1834 }
1835 }
1836 else // not equi-size
1837 {
1838 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1839 try
1840 {
1841 SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
1842 }
1843 catch (AccessViolationException)
1844 {
1845 m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
1846 ode.dunlock(_parent_scene.world);
1847 return;
1848 }
1849 }
1850 }
1851
1852 else // not special profile
1853 {
1854 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1855 try
1856 {
1857 SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
1858 }
1859 catch (AccessViolationException)
1860 {
1861 m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
1862 ode.dunlock(_parent_scene.world);
1863 return;
1864 }
1865 }
1866 }
1867 }
1868
1869 public void changeadd(float timestep)
1870 {
1871 int[] iprimspaceArrItem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
1872 IntPtr targetspace = _parent_scene.calculateSpaceForGeom(_position);
1873
1874 if (targetspace == IntPtr.Zero)
1875 targetspace = _parent_scene.createprimspace(iprimspaceArrItem[0], iprimspaceArrItem[1]);
1876
1877 m_targetSpace = targetspace;
1878
1879 if (_mesh == null && m_meshfailed == false)
1880 {
1881 if (_parent_scene.needsMeshing(_pbs))
1882 {
1883 // Don't need to re-enable body.. it's done in SetMesh
1884 try
1885 {
1886 _mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size, _parent_scene.meshSculptLOD, IsPhysical);
1887 }
1888 catch
1889 {
1890 //Don't continuously try to mesh prims when meshing has failed
1891 m_meshfailed = true;
1892 }
1893 // createmesh returns null when it's a shape that isn't a cube.
1894 // m_log.Debug(m_localID);
1895 }
1896 }
1897
1898
1899 lock (_parent_scene.OdeLock)
1900 {
1901 CreateGeom(m_targetSpace, _mesh);
1902
1903 if (prim_geom != IntPtr.Zero)
1904 {
1905 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1906 d.Quaternion myrot = new d.Quaternion();
1907 myrot.X = _orientation.X;
1908 myrot.Y = _orientation.Y;
1909 myrot.Z = _orientation.Z;
1910 myrot.W = _orientation.W;
1911 d.GeomSetQuaternion(prim_geom, ref myrot);
1912 }
1913
1914 if (m_isphysical && Body == IntPtr.Zero)
1915 {
1916 enableBody();
1917 }
1918 }
1919
1920 changeSelectedStatus(timestep);
1921
1922 m_taintadd = false;
1923 }
1924
1925 public void changemove(float timestep)
1926 {
1927 if (m_isphysical)
1928 {
1929// if (!m_disabled && !m_taintremove && !childPrim) After one edit m_disabled is sometimes set, disabling further edits!
1930 if (!m_taintremove && !childPrim)
1931 {
1932 if (Body == IntPtr.Zero)
1933 enableBody();
1934 //Prim auto disable after 20 frames,
1935 //if you move it, re-enable the prim manually.
1936 if (_parent != null)
1937 {
1938 if (m_linkJoint != IntPtr.Zero)
1939 {
1940 d.JointDestroy(m_linkJoint);
1941 m_linkJoint = IntPtr.Zero;
1942 }
1943 }
1944 if (Body != IntPtr.Zero)
1945 {
1946 d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
1947
1948 if (_parent != null)
1949 {
1950 OdePrim odParent = (OdePrim)_parent;
1951 if (Body != (IntPtr)0 && odParent.Body != (IntPtr)0 && Body != odParent.Body)
1952 {
1953// KF: Fixed Joints were removed? Anyway - this Console.WriteLine does not show up, so routine is not used??
1954Console.WriteLine("ODEPrim JointCreateFixed !!!");
1955 m_linkJoint = d.JointCreateFixed(_parent_scene.world, _linkJointGroup);
1956 d.JointAttach(m_linkJoint, Body, odParent.Body);
1957 d.JointSetFixed(m_linkJoint);
1958 }
1959 }
1960 d.BodyEnable(Body);
1961 if (m_type != Vehicle.TYPE_NONE)
1962 {
1963 Enable(Body, _parent_scene);
1964 }
1965 }
1966 else
1967 {
1968 m_log.Warn("[PHYSICS]: Body Still null after enableBody(). This is a crash scenario.");
1969 }
1970 }
1971 //else
1972 // {
1973 //m_log.Debug("[BUG]: race!");
1974 //}
1975 }
1976 else
1977 {
1978 // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
1979 // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
1980 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1981
1982 IntPtr tempspace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position, m_targetSpace);
1983 m_targetSpace = tempspace;
1984
1985 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1986 if (prim_geom != IntPtr.Zero)
1987 {
1988 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1989
1990 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1991 d.SpaceAdd(m_targetSpace, prim_geom);
1992 }
1993 }
1994
1995 changeSelectedStatus(timestep);
1996
1997 resetCollisionAccounting();
1998 m_taintposition = _position;
1999 }
2000
2001
2002
2003 public void rotate(float timestep)
2004 {
2005 d.Quaternion myrot = new d.Quaternion();
2006 myrot.X = _orientation.X;
2007 myrot.Y = _orientation.Y;
2008 myrot.Z = _orientation.Z;
2009 myrot.W = _orientation.W;
2010 if (Body != IntPtr.Zero)
2011 {
2012 // KF: If this is a root prim do BodySet
2013 d.BodySetQuaternion(Body, ref myrot);
2014 }
2015 else
2016 {
2017 // daughter prim, do Geom set
2018 d.GeomSetQuaternion(prim_geom, ref myrot);
2019 }
2020
2021 resetCollisionAccounting();
2022 m_taintrot = _orientation;
2023 }
2024
2025 private void resetCollisionAccounting()
2026 {
2027 m_collisionscore = 0;
2028 m_interpenetrationcount = 0;
2029 m_disabled = false;
2030 }
2031
2032 public void changedisable(float timestep)
2033 {
2034 m_disabled = true;
2035 if (Body != IntPtr.Zero)
2036 {
2037 d.BodyDisable(Body);
2038 Body = IntPtr.Zero;
2039 }
2040
2041 m_taintdisable = false;
2042 }
2043
2044 public void changePhysicsStatus(float timestep)
2045 {
2046 if (m_isphysical == true)
2047 {
2048 if (Body == IntPtr.Zero)
2049 {
2050 if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim)
2051 {
2052 changeshape(2f);
2053 }
2054 else
2055 {
2056 enableBody();
2057 }
2058 }
2059 }
2060 else
2061 {
2062 if (Body != IntPtr.Zero)
2063 {
2064 if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim)
2065 {
2066 _mesh = null;
2067 changeadd(2f);
2068 }
2069 if (childPrim)
2070 {
2071 if (_parent != null)
2072 {
2073 OdePrim parent = (OdePrim)_parent;
2074 parent.ChildDelink(this);
2075 }
2076 }
2077 else
2078 {
2079 disableBody();
2080 }
2081 }
2082 }
2083
2084 changeSelectedStatus(timestep);
2085
2086 resetCollisionAccounting();
2087 m_taintPhysics = m_isphysical;
2088 }
2089
2090 public void changesize(float timestamp)
2091 {
2092
2093 string oldname = _parent_scene.geom_name_map[prim_geom];
2094
2095 if (_size.X <= 0) _size.X = 0.01f;
2096 if (_size.Y <= 0) _size.Y = 0.01f;
2097 if (_size.Z <= 0) _size.Z = 0.01f;
2098
2099 // Cleanup of old prim geometry
2100 if (_mesh != null)
2101 {
2102 // Cleanup meshing here
2103 }
2104 //kill body to rebuild
2105 if (IsPhysical && Body != IntPtr.Zero)
2106 {
2107 if (childPrim)
2108 {
2109 if (_parent != null)
2110 {
2111 OdePrim parent = (OdePrim)_parent;
2112 parent.ChildDelink(this);
2113 }
2114 }
2115 else
2116 {
2117 disableBody();
2118 }
2119 }
2120 if (d.SpaceQuery(m_targetSpace, prim_geom))
2121 {
2122 _parent_scene.waitForSpaceUnlock(m_targetSpace);
2123 d.SpaceRemove(m_targetSpace, prim_geom);
2124 }
2125 // we don't need to do space calculation because the client sends a position update also.
2126
2127 // Construction of new prim
2128 if (_parent_scene.needsMeshing(_pbs) && m_meshfailed == false)
2129 {
2130 float meshlod = _parent_scene.meshSculptLOD;
2131
2132 if (IsPhysical)
2133 meshlod = _parent_scene.MeshSculptphysicalLOD;
2134 // Don't need to re-enable body.. it's done in SetMesh
2135
2136 IMesh mesh = null;
2137
2138 try
2139 {
2140 if (_parent_scene.needsMeshing(_pbs))
2141 mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical);
2142 }
2143 catch
2144 {
2145 m_meshfailed = true;
2146 }
2147
2148 //IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical);
2149 CreateGeom(m_targetSpace, mesh);
2150
2151
2152 }
2153 else
2154 {
2155 _mesh = null;
2156 CreateGeom(m_targetSpace, _mesh);
2157 }
2158
2159 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2160 d.Quaternion myrot = new d.Quaternion();
2161 myrot.X = _orientation.X;
2162 myrot.Y = _orientation.Y;
2163 myrot.Z = _orientation.Z;
2164 myrot.W = _orientation.W;
2165 d.GeomSetQuaternion(prim_geom, ref myrot);
2166
2167 //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
2168 if (IsPhysical && Body == IntPtr.Zero && !childPrim)
2169 {
2170 // Re creates body on size.
2171 // EnableBody also does setMass()
2172 enableBody();
2173 d.BodyEnable(Body);
2174 }
2175
2176 _parent_scene.geom_name_map[prim_geom] = oldname;
2177
2178 changeSelectedStatus(timestamp);
2179 if (childPrim)
2180 {
2181 if (_parent is OdePrim)
2182 {
2183 OdePrim parent = (OdePrim)_parent;
2184 parent.ChildSetGeom(this);
2185 }
2186 }
2187 resetCollisionAccounting();
2188 m_taintsize = _size;
2189 }
2190
2191
2192
2193 public void changefloatonwater(float timestep)
2194 {
2195 m_collidesWater = m_taintCollidesWater;
2196
2197 if (prim_geom != IntPtr.Zero)
2198 {
2199 if (m_collidesWater)
2200 {
2201 m_collisionFlags |= CollisionCategories.Water;
2202 }
2203 else
2204 {
2205 m_collisionFlags &= ~CollisionCategories.Water;
2206 }
2207 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
2208 }
2209 }
2210
2211 public void changeshape(float timestamp)
2212 {
2213 string oldname = _parent_scene.geom_name_map[prim_geom];
2214
2215 // Cleanup of old prim geometry and Bodies
2216 if (IsPhysical && Body != IntPtr.Zero)
2217 {
2218 if (childPrim)
2219 {
2220 if (_parent != null)
2221 {
2222 OdePrim parent = (OdePrim)_parent;
2223 parent.ChildDelink(this);
2224 }
2225 }
2226 else
2227 {
2228 disableBody();
2229 }
2230 }
2231
2232
2233 // we don't need to do space calculation because the client sends a position update also.
2234 if (_size.X <= 0) _size.X = 0.01f;
2235 if (_size.Y <= 0) _size.Y = 0.01f;
2236 if (_size.Z <= 0) _size.Z = 0.01f;
2237 // Construction of new prim
2238
2239 if (_parent_scene.needsMeshing(_pbs) && m_meshfailed == false)
2240 {
2241 // Don't need to re-enable body.. it's done in SetMesh
2242 float meshlod = _parent_scene.meshSculptLOD;
2243
2244 if (IsPhysical)
2245 meshlod = _parent_scene.MeshSculptphysicalLOD;
2246 try
2247 {
2248 IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical);
2249 CreateGeom(m_targetSpace, mesh);
2250 }
2251 catch
2252 {
2253 m_meshfailed = true;
2254 }
2255 // createmesh returns null when it doesn't mesh.
2256 }
2257 else
2258 {
2259 _mesh = null;
2260 CreateGeom(m_targetSpace, null);
2261 }
2262
2263 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2264 d.Quaternion myrot = new d.Quaternion();
2265 //myrot.W = _orientation.w;
2266 myrot.W = _orientation.W;
2267 myrot.X = _orientation.X;
2268 myrot.Y = _orientation.Y;
2269 myrot.Z = _orientation.Z;
2270 d.GeomSetQuaternion(prim_geom, ref myrot);
2271
2272 //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
2273 if (IsPhysical && Body == IntPtr.Zero)
2274 {
2275 // Re creates body on size.
2276 // EnableBody also does setMass()
2277 enableBody();
2278 if (Body != IntPtr.Zero)
2279 {
2280 d.BodyEnable(Body);
2281 }
2282 }
2283 _parent_scene.geom_name_map[prim_geom] = oldname;
2284
2285 changeSelectedStatus(timestamp);
2286 if (childPrim)
2287 {
2288 if (_parent is OdePrim)
2289 {
2290 OdePrim parent = (OdePrim)_parent;
2291 parent.ChildSetGeom(this);
2292 }
2293 }
2294 resetCollisionAccounting();
2295 m_taintshape = false;
2296 }
2297
2298 public void changeAddForce(float timestamp)
2299 {
2300 if (!m_isSelected)
2301 {
2302 lock (m_forcelist)
2303 {
2304 //m_log.Info("[PHYSICS]: dequeing forcelist");
2305 if (IsPhysical)
2306 {
2307 Vector3 iforce = Vector3.Zero;
2308 int i = 0;
2309 try
2310 {
2311 for (i = 0; i < m_forcelist.Count; i++)
2312 {
2313
2314 iforce = iforce + (m_forcelist[i] * 100);
2315 }
2316 }
2317 catch (IndexOutOfRangeException)
2318 {
2319 m_forcelist = new List<Vector3>();
2320 m_collisionscore = 0;
2321 m_interpenetrationcount = 0;
2322 m_taintforce = false;
2323 return;
2324 }
2325 catch (ArgumentOutOfRangeException)
2326 {
2327 m_forcelist = new List<Vector3>();
2328 m_collisionscore = 0;
2329 m_interpenetrationcount = 0;
2330 m_taintforce = false;
2331 return;
2332 }
2333 d.BodyEnable(Body);
2334
2335 d.BodyAddForce(Body, iforce.X, iforce.Y, iforce.Z);
2336 }
2337 m_forcelist.Clear();
2338 }
2339
2340 m_collisionscore = 0;
2341 m_interpenetrationcount = 0;
2342 }
2343
2344 m_taintforce = false;
2345
2346 }
2347
2348
2349
2350 public void changeSetTorque(float timestamp)
2351 {
2352 if (!m_isSelected)
2353 {
2354 if (IsPhysical && Body != IntPtr.Zero)
2355 {
2356 d.BodySetTorque(Body, m_taintTorque.X, m_taintTorque.Y, m_taintTorque.Z);
2357 }
2358 }
2359
2360 m_taintTorque = Vector3.Zero;
2361 }
2362
2363 public void changeAddAngularForce(float timestamp)
2364 {
2365 if (!m_isSelected)
2366 {
2367 lock (m_angularforcelist)
2368 {
2369 //m_log.Info("[PHYSICS]: dequeing forcelist");
2370 if (IsPhysical)
2371 {
2372 Vector3 iforce = Vector3.Zero;
2373 for (int i = 0; i < m_angularforcelist.Count; i++)
2374 {
2375 iforce = iforce + (m_angularforcelist[i] * 100);
2376 }
2377 d.BodyEnable(Body);
2378 d.BodyAddTorque(Body, iforce.X, iforce.Y, iforce.Z);
2379
2380 }
2381 m_angularforcelist.Clear();
2382 }
2383
2384 m_collisionscore = 0;
2385 m_interpenetrationcount = 0;
2386 }
2387
2388 m_taintaddangularforce = false;
2389 }
2390
2391 private void changevelocity(float timestep)
2392 {
2393 if (!m_isSelected)
2394 {
2395 Thread.Sleep(20);
2396 if (IsPhysical)
2397 {
2398 if (Body != IntPtr.Zero)
2399 d.BodySetLinearVel(Body, m_taintVelocity.X, m_taintVelocity.Y, m_taintVelocity.Z);
2400 }
2401
2402 //resetCollisionAccounting();
2403 }
2404 m_taintVelocity = Vector3.Zero;
2405 }
2406
2407 public void UpdatePositionAndVelocity()
2408 {
2409 return; // moved to the Move () method
2410 }
2411
2412 public d.Mass FromMatrix4(Matrix4 pMat, ref d.Mass obj)
2413 {
2414 obj.I.M00 = pMat[0, 0];
2415 obj.I.M01 = pMat[0, 1];
2416 obj.I.M02 = pMat[0, 2];
2417 obj.I.M10 = pMat[1, 0];
2418 obj.I.M11 = pMat[1, 1];
2419 obj.I.M12 = pMat[1, 2];
2420 obj.I.M20 = pMat[2, 0];
2421 obj.I.M21 = pMat[2, 1];
2422 obj.I.M22 = pMat[2, 2];
2423 return obj;
2424 }
2425
2426 public override void SubscribeEvents(int ms)
2427 {
2428 m_eventsubscription = ms;
2429 _parent_scene.addCollisionEventReporting(this);
2430 }
2431
2432 public override void UnSubscribeEvents()
2433 {
2434 _parent_scene.remCollisionEventReporting(this);
2435 m_eventsubscription = 0;
2436 }
2437
2438 public void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
2439 {
2440 if (CollisionEventsThisFrame == null)
2441 CollisionEventsThisFrame = new CollisionEventUpdate();
2442 CollisionEventsThisFrame.AddCollider(CollidedWith, contact);
2443 }
2444
2445 public void SendCollisions()
2446 {
2447 if (CollisionEventsThisFrame == null)
2448 return;
2449
2450 base.SendCollisionUpdate(CollisionEventsThisFrame);
2451
2452 if (CollisionEventsThisFrame.m_objCollisionList.Count == 0)
2453 CollisionEventsThisFrame = null;
2454 else
2455 CollisionEventsThisFrame = new CollisionEventUpdate();
2456 }
2457
2458 public override bool SubscribedEvents()
2459 {
2460 if (m_eventsubscription > 0)
2461 return true;
2462 return false;
2463 }
2464
2465 public static Matrix4 Inverse(Matrix4 pMat)
2466 {
2467 if (determinant3x3(pMat) == 0)
2468 {
2469 return Matrix4.Identity; // should probably throw an error. singluar matrix inverse not possible
2470 }
2471
2472
2473
2474 return (Adjoint(pMat) / determinant3x3(pMat));
2475 }
2476
2477 public static Matrix4 Adjoint(Matrix4 pMat)
2478 {
2479 Matrix4 adjointMatrix = new Matrix4();
2480 for (int i=0; i<4; i++)
2481 {
2482 for (int j=0; j<4; j++)
2483 {
2484 Matrix4SetValue(ref adjointMatrix, i, j, (float)(Math.Pow(-1, i + j) * (determinant3x3(Minor(pMat, i, j)))));
2485 }
2486 }
2487
2488 adjointMatrix = Transpose(adjointMatrix);
2489 return adjointMatrix;
2490 }
2491
2492 public static Matrix4 Minor(Matrix4 matrix, int iRow, int iCol)
2493 {
2494 Matrix4 minor = new Matrix4();
2495 int m = 0, n = 0;
2496 for (int i = 0; i < 4; i++)
2497 {
2498 if (i == iRow)
2499 continue;
2500 n = 0;
2501 for (int j = 0; j < 4; j++)
2502 {
2503 if (j == iCol)
2504 continue;
2505 Matrix4SetValue(ref minor, m,n, matrix[i, j]);
2506 n++;
2507 }
2508 m++;
2509 }
2510 return minor;
2511 }
2512
2513 public static Matrix4 Transpose(Matrix4 pMat)
2514 {
2515 Matrix4 transposeMatrix = new Matrix4();
2516 for (int i = 0; i < 4; i++)
2517 for (int j = 0; j < 4; j++)
2518 Matrix4SetValue(ref transposeMatrix, i, j, pMat[j, i]);
2519 return transposeMatrix;
2520 }
2521
2522 public static void Matrix4SetValue(ref Matrix4 pMat, int r, int c, float val)
2523 {
2524 switch (r)
2525 {
2526 case 0:
2527 switch (c)
2528 {
2529 case 0:
2530 pMat.M11 = val;
2531 break;
2532 case 1:
2533 pMat.M12 = val;
2534 break;
2535 case 2:
2536 pMat.M13 = val;
2537 break;
2538 case 3:
2539 pMat.M14 = val;
2540 break;
2541 }
2542
2543 break;
2544 case 1:
2545 switch (c)
2546 {
2547 case 0:
2548 pMat.M21 = val;
2549 break;
2550 case 1:
2551 pMat.M22 = val;
2552 break;
2553 case 2:
2554 pMat.M23 = val;
2555 break;
2556 case 3:
2557 pMat.M24 = val;
2558 break;
2559 }
2560
2561 break;
2562 case 2:
2563 switch (c)
2564 {
2565 case 0:
2566 pMat.M31 = val;
2567 break;
2568 case 1:
2569 pMat.M32 = val;
2570 break;
2571 case 2:
2572 pMat.M33 = val;
2573 break;
2574 case 3:
2575 pMat.M34 = val;
2576 break;
2577 }
2578
2579 break;
2580 case 3:
2581 switch (c)
2582 {
2583 case 0:
2584 pMat.M41 = val;
2585 break;
2586 case 1:
2587 pMat.M42 = val;
2588 break;
2589 case 2:
2590 pMat.M43 = val;
2591 break;
2592 case 3:
2593 pMat.M44 = val;
2594 break;
2595 }
2596
2597 break;
2598 }
2599 }
2600 private static float determinant3x3(Matrix4 pMat)
2601 {
2602 float det = 0;
2603 float diag1 = pMat[0, 0]*pMat[1, 1]*pMat[2, 2];
2604 float diag2 = pMat[0, 1]*pMat[2, 1]*pMat[2, 0];
2605 float diag3 = pMat[0, 2]*pMat[1, 0]*pMat[2, 1];
2606 float diag4 = pMat[2, 0]*pMat[1, 1]*pMat[0, 2];
2607 float diag5 = pMat[2, 1]*pMat[1, 2]*pMat[0, 0];
2608 float diag6 = pMat[2, 2]*pMat[1, 0]*pMat[0, 1];
2609
2610 det = diag1 + diag2 + diag3 - (diag4 + diag5 + diag6);
2611 return det;
2612
2613 }
2614
2615 private static void DMassCopy(ref d.Mass src, ref d.Mass dst)
2616 {
2617 dst.c.W = src.c.W;
2618 dst.c.X = src.c.X;
2619 dst.c.Y = src.c.Y;
2620 dst.c.Z = src.c.Z;
2621 dst.mass = src.mass;
2622 dst.I.M00 = src.I.M00;
2623 dst.I.M01 = src.I.M01;
2624 dst.I.M02 = src.I.M02;
2625 dst.I.M10 = src.I.M10;
2626 dst.I.M11 = src.I.M11;
2627 dst.I.M12 = src.I.M12;
2628 dst.I.M20 = src.I.M20;
2629 dst.I.M21 = src.I.M21;
2630 dst.I.M22 = src.I.M22;
2631 }
2632
2633 public override void SetMaterial(int pMaterial)
2634 {
2635 m_material = pMaterial;
2636 }
2637
2638 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
2639 {
2640 switch (pParam)
2641 {
2642 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
2643 if (pValue < 0.01f) pValue = 0.01f;
2644 // m_angularDeflectionEfficiency = pValue;
2645 break;
2646 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
2647 if (pValue < 0.1f) pValue = 0.1f;
2648 // m_angularDeflectionTimescale = pValue;
2649 break;
2650 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
2651 if (pValue < 0.3f) pValue = 0.3f;
2652 m_angularMotorDecayTimescale = pValue;
2653 break;
2654 case Vehicle.ANGULAR_MOTOR_TIMESCALE:
2655 if (pValue < 0.3f) pValue = 0.3f;
2656 m_angularMotorTimescale = pValue;
2657 break;
2658 case Vehicle.BANKING_EFFICIENCY:
2659 if (pValue < 0.01f) pValue = 0.01f;
2660 // m_bankingEfficiency = pValue;
2661 break;
2662 case Vehicle.BANKING_MIX:
2663 if (pValue < 0.01f) pValue = 0.01f;
2664 // m_bankingMix = pValue;
2665 break;
2666 case Vehicle.BANKING_TIMESCALE:
2667 if (pValue < 0.01f) pValue = 0.01f;
2668 // m_bankingTimescale = pValue;
2669 break;
2670 case Vehicle.BUOYANCY:
2671 if (pValue < -1f) pValue = -1f;
2672 if (pValue > 1f) pValue = 1f;
2673 m_VehicleBuoyancy = pValue;
2674 break;
2675// case Vehicle.HOVER_EFFICIENCY:
2676// if (pValue < 0f) pValue = 0f;
2677// if (pValue > 1f) pValue = 1f;
2678// m_VhoverEfficiency = pValue;
2679// break;
2680 case Vehicle.HOVER_HEIGHT:
2681 m_VhoverHeight = pValue;
2682 break;
2683 case Vehicle.HOVER_TIMESCALE:
2684 if (pValue < 0.1f) pValue = 0.1f;
2685 m_VhoverTimescale = pValue;
2686 break;
2687 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
2688 if (pValue < 0.01f) pValue = 0.01f;
2689 // m_linearDeflectionEfficiency = pValue;
2690 break;
2691 case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
2692 if (pValue < 0.01f) pValue = 0.01f;
2693 // m_linearDeflectionTimescale = pValue;
2694 break;
2695 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
2696 if (pValue < 0.3f) pValue = 0.3f;
2697 m_linearMotorDecayTimescale = pValue;
2698 break;
2699 case Vehicle.LINEAR_MOTOR_TIMESCALE:
2700 if (pValue < 0.1f) pValue = 0.1f;
2701 m_linearMotorTimescale = pValue;
2702 break;
2703 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
2704 if (pValue < 0.1f) pValue = 0.1f; // Less goes unstable
2705 if (pValue > 1.0f) pValue = 1.0f;
2706 m_verticalAttractionEfficiency = pValue;
2707 break;
2708 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
2709 if (pValue < 0.1f) pValue = 0.1f;
2710 m_verticalAttractionTimescale = pValue;
2711 break;
2712
2713 // These are vector properties but the engine lets you use a single float value to
2714 // set all of the components to the same value
2715 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
2716 if (pValue > 30f) pValue = 30f;
2717 if (pValue < 0.1f) pValue = 0.1f;
2718 m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
2719 break;
2720 case Vehicle.ANGULAR_MOTOR_DIRECTION:
2721 m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
2722 UpdateAngDecay();
2723 break;
2724 case Vehicle.LINEAR_FRICTION_TIMESCALE:
2725 if (pValue < 0.1f) pValue = 0.1f;
2726 m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
2727 break;
2728 case Vehicle.LINEAR_MOTOR_DIRECTION:
2729 m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
2730 UpdateLinDecay();
2731 break;
2732 case Vehicle.LINEAR_MOTOR_OFFSET:
2733 // m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
2734 break;
2735
2736 }
2737
2738 }//end ProcessFloatVehicleParam
2739
2740 internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue)
2741 {
2742 switch (pParam)
2743 {
2744 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
2745 if (pValue.X > 30f) pValue.X = 30f;
2746 if (pValue.X < 0.1f) pValue.X = 0.1f;
2747 if (pValue.Y > 30f) pValue.Y = 30f;
2748 if (pValue.Y < 0.1f) pValue.Y = 0.1f;
2749 if (pValue.Z > 30f) pValue.Z = 30f;
2750 if (pValue.Z < 0.1f) pValue.Z = 0.1f;
2751 m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
2752 break;
2753 case Vehicle.ANGULAR_MOTOR_DIRECTION:
2754 m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
2755 // Limit requested angular speed to 2 rps= 4 pi rads/sec
2756 if(m_angularMotorDirection.X > 12.56f) m_angularMotorDirection.X = 12.56f;
2757 if(m_angularMotorDirection.X < - 12.56f) m_angularMotorDirection.X = - 12.56f;
2758 if(m_angularMotorDirection.Y > 12.56f) m_angularMotorDirection.Y = 12.56f;
2759 if(m_angularMotorDirection.Y < - 12.56f) m_angularMotorDirection.Y = - 12.56f;
2760 if(m_angularMotorDirection.Z > 12.56f) m_angularMotorDirection.Z = 12.56f;
2761 if(m_angularMotorDirection.Z < - 12.56f) m_angularMotorDirection.Z = - 12.56f;
2762 UpdateAngDecay();
2763 break;
2764 case Vehicle.LINEAR_FRICTION_TIMESCALE:
2765 if (pValue.X < 0.1f) pValue.X = 0.1f;
2766 if (pValue.Y < 0.1f) pValue.Y = 0.1f;
2767 if (pValue.Z < 0.1f) pValue.Z = 0.1f;
2768 m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
2769 break;
2770 case Vehicle.LINEAR_MOTOR_DIRECTION:
2771 m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); // velocity requested by LSL, for max limiting
2772 UpdateLinDecay();
2773 break;
2774 case Vehicle.LINEAR_MOTOR_OFFSET:
2775 // m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z);
2776 break;
2777 }
2778
2779 }//end ProcessVectorVehicleParam
2780
2781 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
2782 {
2783 switch (pParam)
2784 {
2785 case Vehicle.REFERENCE_FRAME:
2786 // m_referenceFrame = pValue;
2787 break;
2788 }
2789
2790 }//end ProcessRotationVehicleParam
2791
2792 internal void ProcessVehicleFlags(int pParam, bool remove)
2793 {
2794 if (remove)
2795 {
2796 m_flags &= ~((VehicleFlag)pParam);
2797 }
2798 else
2799 {
2800 m_flags |= (VehicleFlag)pParam;
2801 }
2802 }
2803
2804 internal void ProcessTypeChange(Vehicle pType)
2805 {
2806 // Set Defaults For Type
2807 m_type = pType;
2808 switch (pType)
2809 {
2810 case Vehicle.TYPE_SLED:
2811 m_linearFrictionTimescale = new Vector3(30, 1, 1000);
2812 m_angularFrictionTimescale = new Vector3(30, 30, 30);
2813// m_lLinMotorVel = Vector3.Zero;
2814 m_linearMotorTimescale = 1000;
2815 m_linearMotorDecayTimescale = 120;
2816 m_angularMotorDirection = Vector3.Zero;
2817 m_angularMotorDVel = Vector3.Zero;
2818 m_angularMotorTimescale = 1000;
2819 m_angularMotorDecayTimescale = 120;
2820 m_VhoverHeight = 0;
2821// m_VhoverEfficiency = 1;
2822 m_VhoverTimescale = 10;
2823 m_VehicleBuoyancy = 0;
2824 // m_linearDeflectionEfficiency = 1;
2825 // m_linearDeflectionTimescale = 1;
2826 // m_angularDeflectionEfficiency = 1;
2827 // m_angularDeflectionTimescale = 1000;
2828 // m_bankingEfficiency = 0;
2829 // m_bankingMix = 1;
2830 // m_bankingTimescale = 10;
2831 // m_referenceFrame = Quaternion.Identity;
2832 m_flags &=
2833 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
2834 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
2835 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
2836 break;
2837 case Vehicle.TYPE_CAR:
2838 m_linearFrictionTimescale = new Vector3(100, 2, 1000);
2839 m_angularFrictionTimescale = new Vector3(30, 30, 30); // was 1000, but sl max frict time is 30.
2840// m_lLinMotorVel = Vector3.Zero;
2841 m_linearMotorTimescale = 1;
2842 m_linearMotorDecayTimescale = 60;
2843 m_angularMotorDirection = Vector3.Zero;
2844 m_angularMotorDVel = Vector3.Zero;
2845 m_angularMotorTimescale = 1;
2846 m_angularMotorDecayTimescale = 0.8f;
2847 m_VhoverHeight = 0;
2848// m_VhoverEfficiency = 0;
2849 m_VhoverTimescale = 1000;
2850 m_VehicleBuoyancy = 0;
2851 // // m_linearDeflectionEfficiency = 1;
2852 // // m_linearDeflectionTimescale = 2;
2853 // // m_angularDeflectionEfficiency = 0;
2854 // m_angularDeflectionTimescale = 10;
2855 m_verticalAttractionEfficiency = 1f;
2856 m_verticalAttractionTimescale = 10f;
2857 // m_bankingEfficiency = -0.2f;
2858 // m_bankingMix = 1;
2859 // m_bankingTimescale = 1;
2860 // m_referenceFrame = Quaternion.Identity;
2861 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
2862 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.HOVER_UP_ONLY |
2863 VehicleFlag.LIMIT_MOTOR_UP);
2864 break;
2865 case Vehicle.TYPE_BOAT:
2866 m_linearFrictionTimescale = new Vector3(10, 3, 2);
2867 m_angularFrictionTimescale = new Vector3(10,10,10);
2868// m_lLinMotorVel = Vector3.Zero;
2869 m_linearMotorTimescale = 5;
2870 m_linearMotorDecayTimescale = 60;
2871 m_angularMotorDirection = Vector3.Zero;
2872 m_angularMotorDVel = Vector3.Zero;
2873 m_angularMotorTimescale = 4;
2874 m_angularMotorDecayTimescale = 4;
2875 m_VhoverHeight = 0;
2876// m_VhoverEfficiency = 0.5f;
2877 m_VhoverTimescale = 2;
2878 m_VehicleBuoyancy = 1;
2879 // m_linearDeflectionEfficiency = 0.5f;
2880 // m_linearDeflectionTimescale = 3;
2881 // m_angularDeflectionEfficiency = 0.5f;
2882 // m_angularDeflectionTimescale = 5;
2883 m_verticalAttractionEfficiency = 0.5f;
2884 m_verticalAttractionTimescale = 5f;
2885 // m_bankingEfficiency = -0.3f;
2886 // m_bankingMix = 0.8f;
2887 // m_bankingTimescale = 1;
2888 // m_referenceFrame = Quaternion.Identity;
2889 m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.LIMIT_ROLL_ONLY |
2890 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
2891 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY |
2892 VehicleFlag.LIMIT_MOTOR_UP);
2893 break;
2894 case Vehicle.TYPE_AIRPLANE:
2895 m_linearFrictionTimescale = new Vector3(200, 10, 5);
2896 m_angularFrictionTimescale = new Vector3(20, 20, 20);
2897// m_lLinMotorVel = Vector3.Zero;
2898 m_linearMotorTimescale = 2;
2899 m_linearMotorDecayTimescale = 60;
2900 m_angularMotorDirection = Vector3.Zero;
2901 m_angularMotorDVel = Vector3.Zero;
2902 m_angularMotorTimescale = 4;
2903 m_angularMotorDecayTimescale = 4;
2904 m_VhoverHeight = 0;
2905// m_VhoverEfficiency = 0.5f;
2906 m_VhoverTimescale = 1000;
2907 m_VehicleBuoyancy = 0;
2908 // m_linearDeflectionEfficiency = 0.5f;
2909 // m_linearDeflectionTimescale = 3;
2910 // m_angularDeflectionEfficiency = 1;
2911 // m_angularDeflectionTimescale = 2;
2912 m_verticalAttractionEfficiency = 0.9f;
2913 m_verticalAttractionTimescale = 2f;
2914 // m_bankingEfficiency = 1;
2915 // m_bankingMix = 0.7f;
2916 // m_bankingTimescale = 2;
2917 // m_referenceFrame = Quaternion.Identity;
2918 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
2919 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
2920 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
2921 break;
2922 case Vehicle.TYPE_BALLOON:
2923 m_linearFrictionTimescale = new Vector3(5, 5, 5);
2924 m_angularFrictionTimescale = new Vector3(10, 10, 10);
2925 m_linearMotorTimescale = 5;
2926 m_linearMotorDecayTimescale = 60;
2927 m_angularMotorDirection = Vector3.Zero;
2928 m_angularMotorDVel = Vector3.Zero;
2929 m_angularMotorTimescale = 6;
2930 m_angularMotorDecayTimescale = 10;
2931 m_VhoverHeight = 5;
2932// m_VhoverEfficiency = 0.8f;
2933 m_VhoverTimescale = 10;
2934 m_VehicleBuoyancy = 1;
2935 // m_linearDeflectionEfficiency = 0;
2936 // m_linearDeflectionTimescale = 5;
2937 // m_angularDeflectionEfficiency = 0;
2938 // m_angularDeflectionTimescale = 5;
2939 m_verticalAttractionEfficiency = 1f;
2940 m_verticalAttractionTimescale = 100f;
2941 // m_bankingEfficiency = 0;
2942 // m_bankingMix = 0.7f;
2943 // m_bankingTimescale = 5;
2944 // m_referenceFrame = Quaternion.Identity;
2945 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
2946 VehicleFlag.HOVER_UP_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
2947 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
2948 break;
2949
2950 }
2951 }//end SetDefaultsForType
2952
2953 internal void Enable(IntPtr pBody, OdeScene pParentScene)
2954 {
2955 if (m_type == Vehicle.TYPE_NONE)
2956 return;
2957
2958 m_body = pBody;
2959 }
2960
2961
2962 internal void Halt()
2963 { // Kill all motions, when non-physical
2964 // m_linearMotorDirection = Vector3.Zero;
2965 m_lLinMotorDVel = Vector3.Zero;
2966 m_lLinObjectVel = Vector3.Zero;
2967 m_wLinObjectVel = Vector3.Zero;
2968 m_angularMotorDirection = Vector3.Zero;
2969 m_lastAngularVelocity = Vector3.Zero;
2970 m_angularMotorDVel = Vector3.Zero;
2971 _acceleration = Vector3.Zero;
2972 }
2973
2974 private void UpdateLinDecay()
2975 {
2976// if (Math.Abs(m_linearMotorDirection.X) > Math.Abs(m_lLinMotorDVel.X)) m_lLinMotorDVel.X = m_linearMotorDirection.X;
2977// if (Math.Abs(m_linearMotorDirection.Y) > Math.Abs(m_lLinMotorDVel.Y)) m_lLinMotorDVel.Y = m_linearMotorDirection.Y;
2978// if (Math.Abs(m_linearMotorDirection.Z) > Math.Abs(m_lLinMotorDVel.Z)) m_lLinMotorDVel.Z = m_linearMotorDirection.Z;
2979 m_lLinMotorDVel.X = m_linearMotorDirection.X;
2980 m_lLinMotorDVel.Y = m_linearMotorDirection.Y;
2981 m_lLinMotorDVel.Z = m_linearMotorDirection.Z;
2982 } // else let the motor decay on its own
2983
2984 private void UpdateAngDecay()
2985 {
2986// if (Math.Abs(m_angularMotorDirection.X) > Math.Abs(m_angularMotorDVel.X)) m_angularMotorDVel.X = m_angularMotorDirection.X;
2987// if (Math.Abs(m_angularMotorDirection.Y) > Math.Abs(m_angularMotorDVel.Y)) m_angularMotorDVel.Y = m_angularMotorDirection.Y;
2988// if (Math.Abs(m_angularMotorDirection.Z) > Math.Abs(m_angularMotorDVel.Z)) m_angularMotorDVel.Z = m_angularMotorDirection.Z;
2989 m_angularMotorDVel.X = m_angularMotorDirection.X;
2990 m_angularMotorDVel.Y = m_angularMotorDirection.Y;
2991 m_angularMotorDVel.Z = m_angularMotorDirection.Z;
2992 } // else let the motor decay on its own
2993
2994 public void Move(float timestep)
2995 {
2996 float fx = 0;
2997 float fy = 0;
2998 float fz = 0;
2999 Vector3 linvel; // velocity applied, including any reversal
3000 int outside = 0;
3001
3002 // If geomCrossingFailuresBeforeOutofbounds is set to 0 in OpenSim.ini then phys objects bounce off region borders.
3003 // This is a temp patch until proper region crossing is developed.
3004
3005 int failureLimit = _parent_scene.geomCrossingFailuresBeforeOutofbounds;
3006 float fence = _parent_scene.geomRegionFence;
3007
3008 frcount++; // used to limit debug comment output
3009 if (frcount > 50)
3010 frcount = 0;
3011
3012 if(revcount > 0) revcount--;
3013
3014 if (IsPhysical && (Body != IntPtr.Zero) && !m_isSelected && !childPrim) // Only move root prims.
3015 {
3016 // Old public void UpdatePositionAndVelocity(), more accuratley calculated here
3017 bool lastZeroFlag = _zeroFlag; // was it stopped
3018
3019 d.Vector3 vec = d.BodyGetPosition(Body);
3020 Vector3 l_position = Vector3.Zero;
3021 l_position.X = vec.X;
3022 l_position.Y = vec.Y;
3023 l_position.Z = vec.Z;
3024 m_lastposition = _position;
3025 _position = l_position;
3026
3027 d.Quaternion ori = d.BodyGetQuaternion(Body);
3028 // Quaternion l_orientation = Quaternion.Identity;
3029 _orientation.X = ori.X;
3030 _orientation.Y = ori.Y;
3031 _orientation.Z = ori.Z;
3032 _orientation.W = ori.W;
3033 m_lastorientation = _orientation;
3034
3035 d.Vector3 vel = d.BodyGetLinearVel(Body);
3036 m_lastVelocity = _velocity;
3037 _velocity.X = vel.X;
3038 _velocity.Y = vel.Y;
3039 _velocity.Z = vel.Z;
3040 _acceleration = ((_velocity - m_lastVelocity) / timestep);
3041
3042 d.Vector3 torque = d.BodyGetTorque(Body);
3043 _torque = new Vector3(torque.X, torque.Y, torque.Z);
3044
3045 base.RequestPhysicsterseUpdate();
3046
3047//Console.WriteLine("Move {0} at {1}", m_primName, l_position);
3048
3049 // Check if outside region
3050 // In Scene.cs/CrossPrimGroupIntoNewRegion the object is checked for 0.1M from border!
3051 if (l_position.X > ((float)_parent_scene.WorldExtents.X - fence))
3052 {
3053 l_position.X = ((float)_parent_scene.WorldExtents.X - fence);
3054 outside = 1;
3055 }
3056
3057 if (l_position.X < fence)
3058 {
3059 l_position.X = fence;
3060 outside = 2;
3061 }
3062 if (l_position.Y > ((float)_parent_scene.WorldExtents.Y - fence))
3063 {
3064 l_position.Y = ((float)_parent_scene.WorldExtents.Y - fence);
3065 outside = 3;
3066 }
3067
3068 if (l_position.Y < fence)
3069 {
3070 l_position.Y = fence;
3071 outside = 4;
3072 }
3073
3074 if (outside > 0)
3075 {
3076
3077//Console.WriteLine("Border {0} fence={1}", l_position, fence);
3078 if (fence > 0.0f) // bounce object off boundary
3079 {
3080 if (revcount == 0)
3081 {
3082 if (outside < 3)
3083 {
3084 _velocity.X = -_velocity.X;
3085 }
3086 else
3087 {
3088 _velocity.Y = -_velocity.Y;
3089 }
3090 if (m_type != Vehicle.TYPE_NONE) Halt();
3091 _position = l_position;
3092 m_taintposition = _position;
3093 m_lastVelocity = _velocity;
3094 _acceleration = Vector3.Zero;
3095 d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
3096 d.BodySetLinearVel(Body, _velocity.X, _velocity.Y, _velocity.Z);
3097 base.RequestPhysicsterseUpdate();
3098
3099 revcount = 25; // wait for object to move away from border
3100 }
3101 } // else old crossing mode
3102 else if (m_crossingfailures < failureLimit)
3103 { // keep trying to cross?
3104 _position = l_position;
3105 //_parent_scene.remActivePrim(this);
3106 if (_parent == null) base.RequestPhysicsterseUpdate();
3107 return; // Dont process any other motion?
3108 }
3109 else
3110 { // Too many tries
3111 if (_parent == null) base.RaiseOutOfBounds(l_position);
3112 return; // Dont process any other motion?
3113 } // end various methods
3114 } // end outside region horizontally
3115
3116
3117 if (l_position.Z < 0)
3118 {
3119 // This is so prim that get lost underground don't fall forever and suck up
3120 //
3121 // Sim resources and memory.
3122 // Disables the prim's movement physics....
3123 // It's a hack and will generate a console message if it fails.
3124
3125 //IsPhysical = false;
3126 if (_parent == null) base.RaiseOutOfBounds(_position);
3127
3128
3129 _acceleration.X = 0; // This stuff may stop client display but it has no
3130 _acceleration.Y = 0; // effect on the object in phys engine!
3131 _acceleration.Z = 0;
3132
3133 _velocity.X = 0;
3134 _velocity.Y = 0;
3135 _velocity.Z = 0;
3136 m_lastVelocity = Vector3.Zero;
3137 m_rotationalVelocity.X = 0;
3138 m_rotationalVelocity.Y = 0;
3139 m_rotationalVelocity.Z = 0;
3140
3141 if (_parent == null) base.RequestPhysicsterseUpdate();
3142
3143 m_throttleUpdates = false;
3144 throttleCounter = 0;
3145 _zeroFlag = true;
3146 //outofBounds = true;
3147 } // end neg Z check
3148
3149 // Is it moving?
3150 /* if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02)
3151 && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02)
3152 && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02) */
3153 if ( (Vector3.Mag(_velocity) < 0.01) && // moving very slowly
3154 (Vector3.Mag(_velocity) < Vector3.Mag(m_lastVelocity)) && // decelerating
3155 (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, _orientation)) < 0.0001) ) // spinning very slowly
3156 {
3157 _zeroFlag = true;
3158 m_throttleUpdates = false;
3159 }
3160 else
3161 {
3162 //m_log.Debug(Math.Abs(m_lastposition.X - l_position.X).ToString());
3163 _zeroFlag = false;
3164 m_lastUpdateSent = false;
3165 //m_throttleUpdates = false;
3166 }
3167
3168 if (_zeroFlag)
3169 { // Its stopped
3170 _velocity.X = 0.0f;
3171 _velocity.Y = 0.0f;
3172 // _velocity.Z = 0.0f;
3173
3174 _acceleration.X = 0;
3175 _acceleration.Y = 0;
3176 // _acceleration.Z = 0;
3177
3178 m_rotationalVelocity.X = 0;
3179 m_rotationalVelocity.Y = 0;
3180 m_rotationalVelocity.Z = 0;
3181 // Stop it in the phys engine
3182 d.BodySetLinearVel(Body, 0.0f, 0.0f, _velocity.Z);
3183 d.BodySetAngularVel (Body, 0.0f, 0.0f, 0.0f);
3184 d.BodySetForce(Body, 0f, 0f, 0f);
3185
3186 if (!m_lastUpdateSent)
3187 {
3188 m_throttleUpdates = false;
3189 throttleCounter = 0;
3190 if (_parent == null)
3191 {
3192 base.RequestPhysicsterseUpdate();
3193 }
3194
3195 m_lastUpdateSent = true;
3196 }
3197 }
3198 else
3199 { // Its moving
3200 if (lastZeroFlag != _zeroFlag)
3201 {
3202 if (_parent == null)
3203 {
3204 base.RequestPhysicsterseUpdate();
3205 }
3206 }
3207 m_lastUpdateSent = false;
3208 if (!m_throttleUpdates || throttleCounter > _parent_scene.geomUpdatesPerThrottledUpdate)
3209 {
3210 if (_parent == null)
3211 {
3212 base.RequestPhysicsterseUpdate();
3213 }
3214 }
3215 else
3216 {
3217 throttleCounter++;
3218 }
3219 }
3220 m_lastposition = l_position;
3221
3222 /// End UpdatePositionAndVelocity insert
3223
3224
3225 // Rotation lock =====================================
3226 if(m_rotateEnableUpdate)
3227 {
3228 // Snapshot current angles, set up Amotor(s)
3229 m_rotateEnableUpdate = false;
3230 m_rotateEnable = m_rotateEnableRequest;
3231//Console.WriteLine("RotEnable {0} = {1}",m_primName, m_rotateEnable);
3232
3233 if (Amotor != IntPtr.Zero)
3234 {
3235 d.JointDestroy(Amotor);
3236 Amotor = IntPtr.Zero;
3237//Console.WriteLine("Old Amotor Destroyed");
3238 }
3239
3240 if (!m_rotateEnable.ApproxEquals(Vector3.One, 0.003f))
3241 { // not all are enabled
3242 d.Quaternion r = d.BodyGetQuaternion(Body);
3243 Quaternion locrot = new Quaternion(r.X, r.Y, r.Z, r.W);
3244 // extract the axes vectors
3245 Vector3 vX = new Vector3(1f,0f,0f);
3246 Vector3 vY = new Vector3(0f,1f,0f);
3247 Vector3 vZ = new Vector3(0f,0f,1f);
3248 vX = vX * locrot;
3249 vY = vY * locrot;
3250 vZ = vZ * locrot;
3251 // snapshot the current angle vectors
3252 m_lockX = vX;
3253 m_lockY = vY;
3254 m_lockZ = vZ;
3255 // m_lockRot = locrot;
3256 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero);
3257 d.JointAttach(Amotor, Body, IntPtr.Zero);
3258 d.JointSetAMotorMode(Amotor, 0); // User mode??
3259//Console.WriteLine("New Amotor Created for {0}", m_primName);
3260
3261 float axisnum = 3; // how many to lock
3262 axisnum = (axisnum - (m_rotateEnable.X + m_rotateEnable.Y + m_rotateEnable.Z));
3263 d.JointSetAMotorNumAxes(Amotor,(int)axisnum);
3264//Console.WriteLine("AxisNum={0}",(int)axisnum);
3265
3266 int i = 0;
3267
3268 if (m_rotateEnable.X == 0)
3269 {
3270 d.JointSetAMotorAxis(Amotor, i, 0, m_lockX.X, m_lockX.Y, m_lockX.Z);
3271//Console.WriteLine("AxisX {0} set to {1}", i, m_lockX);
3272 i++;
3273 }
3274
3275 if (m_rotateEnable.Y == 0)
3276 {
3277 d.JointSetAMotorAxis(Amotor, i, 0, m_lockY.X, m_lockY.Y, m_lockY.Z);
3278//Console.WriteLine("AxisY {0} set to {1}", i, m_lockY);
3279 i++;
3280 }
3281
3282 if (m_rotateEnable.Z == 0)
3283 {
3284 d.JointSetAMotorAxis(Amotor, i, 0, m_lockZ.X, m_lockZ.Y, m_lockZ.Z);
3285//Console.WriteLine("AxisZ {0} set to {1}", i, m_lockZ);
3286 i++;
3287 }
3288
3289 // These lowstops and high stops are effectively (no wiggle room)
3290 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, 0f);
3291 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, 0f);
3292 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, 0f);
3293 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0f);
3294 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0f);
3295 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0f);
3296 d.JointSetAMotorParam(Amotor, (int) dParam.Vel, 0f);
3297 d.JointSetAMotorParam(Amotor, (int) dParam.Vel3, 0f);
3298 d.JointSetAMotorParam(Amotor, (int) dParam.Vel2, 0f);
3299 d.JointSetAMotorParam(Amotor, (int)dParam.StopCFM, 0f);
3300 d.JointSetAMotorParam(Amotor, (int)dParam.StopCFM3, 0f);
3301 d.JointSetAMotorParam(Amotor, (int)dParam.StopCFM2, 0f);
3302 } // else none are locked
3303 } // end Rotation Update
3304
3305
3306 // VEHICLE processing ==========================================
3307 if (m_type != Vehicle.TYPE_NONE)
3308 {
3309 // get body attitude
3310 d.Quaternion rot = d.BodyGetQuaternion(Body);
3311 Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object
3312 Quaternion irotq = Quaternion.Inverse(rotq);
3313
3314 // VEHICLE Linear Motion
3315 d.Vector3 velnow = d.BodyGetLinearVel(Body); // this is in world frame
3316 Vector3 vel_now = new Vector3(velnow.X, velnow.Y, velnow.Z);
3317 m_lLinObjectVel = vel_now * irotq;
3318 if (m_linearMotorDecayTimescale < 300.0f) //setting of 300 or more disables decay rate
3319 {
3320 if ( Vector3.Mag(m_lLinMotorDVel) < 1.0f)
3321 {
3322 float decayfactor = m_linearMotorDecayTimescale/timestep;
3323 Vector3 decayAmount = (m_lLinMotorDVel/decayfactor);
3324 m_lLinMotorDVel -= decayAmount;
3325 }
3326 else
3327 {
3328 float decayfactor = 3.0f - (0.57f * (float)Math.Log((double)(m_linearMotorDecayTimescale)));
3329 Vector3 decel = Vector3.Normalize(m_lLinMotorDVel) * decayfactor * timestep;
3330 m_lLinMotorDVel -= decel;
3331 }
3332 if (m_lLinMotorDVel.ApproxEquals(Vector3.Zero, 0.01f))
3333 {
3334 m_lLinMotorDVel = Vector3.Zero;
3335 }
3336
3337 /* else
3338 {
3339 if (Math.Abs(m_lLinMotorDVel.X) < Math.Abs(m_lLinObjectVel.X)) m_lLinObjectVel.X = m_lLinMotorDVel.X;
3340 if (Math.Abs(m_lLinMotorDVel.Y) < Math.Abs(m_lLinObjectVel.Y)) m_lLinObjectVel.Y = m_lLinMotorDVel.Y;
3341 if (Math.Abs(m_lLinMotorDVel.Z) < Math.Abs(m_lLinObjectVel.Z)) m_lLinObjectVel.Z = m_lLinMotorDVel.Z;
3342 } */
3343 } // end linear motor decay
3344
3345 if ( (! m_lLinMotorDVel.ApproxEquals(Vector3.Zero, 0.01f)) || (! m_lLinObjectVel.ApproxEquals(Vector3.Zero, 0.01f)) )
3346 {
3347 if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body);
3348 if (m_linearMotorTimescale < 300.0f)
3349 {
3350 Vector3 attack_error = m_lLinMotorDVel - m_lLinObjectVel;
3351 float linfactor = m_linearMotorTimescale/timestep;
3352 Vector3 attackAmount = (attack_error/linfactor) * 1.3f;
3353 m_lLinObjectVel += attackAmount;
3354 }
3355 if (m_linearFrictionTimescale.X < 300.0f)
3356 {
3357 float fricfactor = m_linearFrictionTimescale.X / timestep;
3358 float fricX = m_lLinObjectVel.X / fricfactor;
3359 m_lLinObjectVel.X -= fricX;
3360 }
3361 if (m_linearFrictionTimescale.Y < 300.0f)
3362 {
3363 float fricfactor = m_linearFrictionTimescale.Y / timestep;
3364 float fricY = m_lLinObjectVel.Y / fricfactor;
3365 m_lLinObjectVel.Y -= fricY;
3366 }
3367 if (m_linearFrictionTimescale.Z < 300.0f)
3368 {
3369 float fricfactor = m_linearFrictionTimescale.Z / timestep;
3370 float fricZ = m_lLinObjectVel.Z / fricfactor;
3371 m_lLinObjectVel.Z -= fricZ;
3372 }
3373 }
3374 m_wLinObjectVel = m_lLinObjectVel * rotq;
3375
3376 // Gravity and Buoyancy
3377 Vector3 grav = Vector3.Zero;
3378 if(m_VehicleBuoyancy < 1.0f)
3379 {
3380 // There is some gravity, make a gravity force vector
3381 // that is applied after object velocity.
3382 d.Mass objMass;
3383 d.BodyGetMass(Body, out objMass);
3384 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
3385 grav.Z = _parent_scene.gravityz * objMass.mass * (1f - m_VehicleBuoyancy); // Applied later as a force
3386 } // else its 1.0, no gravity.
3387
3388 // Hovering
3389 if( (m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
3390 {
3391 // We should hover, get the target height
3392 d.Vector3 pos = d.BodyGetPosition(Body);
3393 if((m_flags & VehicleFlag.HOVER_WATER_ONLY) == VehicleFlag.HOVER_WATER_ONLY)
3394 {
3395 m_VhoverTargetHeight = _parent_scene.GetWaterLevel() + m_VhoverHeight;
3396 }
3397 else if((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) == VehicleFlag.HOVER_TERRAIN_ONLY)
3398 {
3399 m_VhoverTargetHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight;
3400 }
3401 else if((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) == VehicleFlag.HOVER_GLOBAL_HEIGHT)
3402 {
3403 m_VhoverTargetHeight = m_VhoverHeight;
3404 }
3405
3406 if((m_flags & VehicleFlag.HOVER_UP_ONLY) == VehicleFlag.HOVER_UP_ONLY)
3407 {
3408 // If body is aready heigher, use its height as target height
3409 if(pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z;
3410 }
3411
3412// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped
3413// m_VhoverTimescale = 0f; // time to acheive height
3414// timestep is time since last frame,in secs
3415 float herr0 = pos.Z - m_VhoverTargetHeight;
3416 // Replace Vertical speed with correction figure if significant
3417 if(Math.Abs(herr0) > 0.01f )
3418 {
3419 //? d.Mass objMass;
3420 //? d.BodyGetMass(Body, out objMass);
3421 m_wLinObjectVel.Z = - ( (herr0 * timestep * 50.0f) / m_VhoverTimescale);
3422 //KF: m_VhoverEfficiency is not yet implemented
3423 }
3424 else
3425 {
3426 m_wLinObjectVel.Z = 0f;
3427 }
3428 }
3429 else
3430 { // not hovering
3431 if (m_wLinObjectVel.Z == 0f)
3432 { // Gravity rules
3433 m_wLinObjectVel.Z = vel_now.Z;
3434 } // else the motor has it
3435 }
3436 linvel = m_wLinObjectVel;
3437
3438 // Vehicle Linear Motion done =======================================
3439 // Apply velocity
3440 d.BodySetLinearVel(Body, linvel.X, linvel.Y, linvel.Z);
3441 // apply gravity force
3442 d.BodyAddForce(Body, grav.X, grav.Y, grav.Z);
3443//if(frcount == 0) Console.WriteLine("Vel={0} Force={1}",linvel , grav);
3444 // end MoveLinear()
3445
3446
3447 // MoveAngular
3448 /*
3449 private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor
3450
3451 private float m_angularMotorTimescale = 0; // motor angular Attack rate set by LSL
3452 private float m_angularMotorDecayTimescale = 0; // motor angular Decay rate set by LSL
3453 private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular Friction set by LSL
3454
3455 private Vector3 m_angularMotorDVel = Vector3.Zero; // decayed angular motor
3456 private Vector3 m_angObjectVel = Vector3.Zero; // what was last applied to body
3457 */
3458//if(frcount == 0) Console.WriteLine("MoveAngular ");
3459
3460 d.Vector3 angularObjectVel = d.BodyGetAngularVel(Body);
3461 Vector3 angObjectVel = new Vector3(angularObjectVel.X, angularObjectVel.Y, angularObjectVel.Z);
3462 angObjectVel = angObjectVel * irotq; // ============ Converts to LOCAL rotation
3463
3464//if(frcount == 0) Console.WriteLine("V0 = {0}", angObjectVel);
3465
3466 // Decay Angular Motor 1. In SL this also depends on attack rate! decay ~= 23/Attack.
3467 float atk_decayfactor = 23.0f / (m_angularMotorTimescale * timestep);
3468 m_angularMotorDVel -= m_angularMotorDVel / atk_decayfactor;
3469 // Decay Angular Motor 2.
3470 if (m_angularMotorDecayTimescale < 300.0f)
3471 {
3472 if ( Vector3.Mag(m_angularMotorDVel) < 1.0f)
3473 {
3474 float decayfactor = (m_angularMotorDecayTimescale)/timestep;
3475 Vector3 decayAmount = (m_angularMotorDVel/decayfactor);
3476 m_angularMotorDVel -= decayAmount;
3477 }
3478 else
3479 {
3480 Vector3 decel = Vector3.Normalize(m_angularMotorDVel) * timestep / m_angularMotorDecayTimescale;
3481 m_angularMotorDVel -= decel;
3482 }
3483
3484 if (m_angularMotorDVel.ApproxEquals(Vector3.Zero, 0.01f))
3485 {
3486 m_angularMotorDVel = Vector3.Zero;
3487 }
3488 else
3489 {
3490 if (Math.Abs(m_angularMotorDVel.X) < Math.Abs(angObjectVel.X)) angObjectVel.X = m_angularMotorDVel.X;
3491 if (Math.Abs(m_angularMotorDVel.Y) < Math.Abs(angObjectVel.Y)) angObjectVel.Y = m_angularMotorDVel.Y;
3492 if (Math.Abs(m_angularMotorDVel.Z) < Math.Abs(angObjectVel.Z)) angObjectVel.Z = m_angularMotorDVel.Z;
3493 }
3494 } // end decay angular motor
3495//if(frcount == 0) Console.WriteLine("MotorDvel {0} Obj {1}", m_angularMotorDVel, angObjectVel);
3496
3497//if(frcount == 0) Console.WriteLine("VA = {0}", angObjectVel);
3498
3499 if ( (! m_angularMotorDVel.ApproxEquals(Vector3.Zero, 0.01f)) || (! angObjectVel.ApproxEquals(Vector3.Zero, 0.01f)) )
3500 { // if motor or object have motion
3501 if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body);
3502
3503 if (m_angularMotorTimescale < 300.0f)
3504 {
3505 Vector3 attack_error = m_angularMotorDVel - angObjectVel;
3506 float angfactor = m_angularMotorTimescale/timestep;
3507 Vector3 attackAmount = (attack_error/angfactor);
3508 angObjectVel += attackAmount;
3509//if(frcount == 0) Console.WriteLine("Accel {0} Attk {1}",FrAaccel, attackAmount);
3510//if(frcount == 0) Console.WriteLine("V2+= {0}", angObjectVel);
3511 }
3512
3513 angObjectVel.X -= angObjectVel.X / (m_angularFrictionTimescale.X * 0.7f / timestep);
3514 angObjectVel.Y -= angObjectVel.Y / (m_angularFrictionTimescale.Y * 0.7f / timestep);
3515 angObjectVel.Z -= angObjectVel.Z / (m_angularFrictionTimescale.Z * 0.7f / timestep);
3516 } // else no signif. motion
3517
3518//if(frcount == 0) Console.WriteLine("Dmotor {0} Obj {1}", m_angularMotorDVel, angObjectVel);
3519 // Bank section tba
3520 // Deflection section tba
3521//if(frcount == 0) Console.WriteLine("V3 = {0}", angObjectVel);
3522
3523
3524 /* // Rotation Axis Disables:
3525 if (!m_angularEnable.ApproxEquals(Vector3.One, 0.003f))
3526 {
3527 if (m_angularEnable.X == 0)
3528 angObjectVel.X = 0f;
3529 if (m_angularEnable.Y == 0)
3530 angObjectVel.Y = 0f;
3531 if (m_angularEnable.Z == 0)
3532 angObjectVel.Z = 0f;
3533 }
3534 */
3535 angObjectVel = angObjectVel * rotq; // ================ Converts to WORLD rotation
3536
3537 // Vertical attractor section
3538 Vector3 vertattr = Vector3.Zero;
3539
3540 if(m_verticalAttractionTimescale < 300)
3541 {
3542 float VAservo = 1.0f / (m_verticalAttractionTimescale * timestep);
3543 // make a vector pointing up
3544 Vector3 verterr = Vector3.Zero;
3545 verterr.Z = 1.0f;
3546 // rotate it to Body Angle
3547 verterr = verterr * rotq;
3548 // verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1.
3549 // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go
3550 // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body.
3551
3552 if (verterr.Z < 0.0f)
3553 { // Deflection from vertical exceeds 90-degrees. This method will ensure stable return to
3554 // vertical, BUT for some reason a z-rotation is imparted to the object. TBI.
3555//Console.WriteLine("InvertFlip");
3556 verterr.X = 2.0f - verterr.X;
3557 verterr.Y = 2.0f - verterr.Y;
3558 }
3559 verterr *= 0.5f;
3560 // verterror is 0 (no error) to +/- 1 (max error at 180-deg tilt)
3561 Vector3 xyav = angObjectVel;
3562 xyav.Z = 0.0f;
3563 if ((!xyav.ApproxEquals(Vector3.Zero, 0.001f)) || (verterr.Z < 0.49f))
3564 {
3565 // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so
3566 // Change Body angular velocity X based on Y, and Y based on X. Z is not changed.
3567 vertattr.X = verterr.Y;
3568 vertattr.Y = - verterr.X;
3569 vertattr.Z = 0f;
3570//if(frcount == 0) Console.WriteLine("VAerr=" + verterr);
3571
3572 // scaling appears better usingsquare-law
3573 float damped = m_verticalAttractionEfficiency * m_verticalAttractionEfficiency;
3574 float bounce = 1.0f - damped;
3575 // 0 = crit damp, 1 = bouncy
3576 float oavz = angObjectVel.Z; // retain z velocity
3577 // time-scaled correction, which sums, therefore is bouncy:
3578 angObjectVel = (angObjectVel + (vertattr * VAservo * 0.0333f)) * bounce;
3579 // damped, good @ < 90:
3580 angObjectVel = angObjectVel + (vertattr * VAservo * 0.0667f * damped);
3581 angObjectVel.Z = oavz;
3582//if(frcount == 0) Console.WriteLine("VA+");
3583//Console.WriteLine("VAttr {0} OAvel {1}", vertattr, angObjectVel);
3584 }
3585 else
3586 {
3587 // else error is very small
3588 angObjectVel.X = 0f;
3589 angObjectVel.Y = 0f;
3590//if(frcount == 0) Console.WriteLine("VA0");
3591 }
3592 } // else vertical attractor is off
3593//if(frcount == 0) Console.WriteLine("V1 = {0}", angObjectVel);
3594
3595
3596 m_lastAngularVelocity = angObjectVel;
3597 // apply Angular Velocity to body
3598 d.BodySetAngularVel (Body, m_lastAngularVelocity.X, m_lastAngularVelocity.Y, m_lastAngularVelocity.Z);
3599//if(frcount == 0) Console.WriteLine("V4 = {0}", m_lastAngularVelocity);
3600
3601 } // end VEHICLES
3602 else
3603 {
3604 // Dyamics (NON-'VEHICLES') are dealt with here ================================================================
3605
3606 if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); // KF add 161009
3607
3608 /// Dynamics Buoyancy
3609 //KF: m_buoyancy is set by llSetBuoyancy() and is for non-vehicle.
3610 // m_buoyancy: (unlimited value) <0=Falls fast; 0=1g; 1=0g; >1 = floats up
3611 // NB Prims in ODE are no subject to global gravity
3612 // This should only affect gravity operations
3613
3614 float m_mass = CalculateMass();
3615 // calculate z-force due togravity on object.
3616 fz = _parent_scene.gravityz * (1.0f - m_buoyancy) * m_mass; // force = acceleration * mass
3617 if ((m_usePID) && (m_PIDTau > 0.0f)) // Dynamics llMoveToTarget.
3618 {
3619 fz = 0; // llMoveToTarget ignores gravity.
3620 // it also ignores mass of object, and any physical resting on it.
3621 // Vector3 m_PIDTarget is where we are going
3622 // float m_PIDTau is time to get there
3623 fx = 0;
3624 fy = 0;
3625 d.Vector3 pos = d.BodyGetPosition(Body);
3626 Vector3 error = new Vector3(
3627 (m_PIDTarget.X - pos.X),
3628 (m_PIDTarget.Y - pos.Y),
3629 (m_PIDTarget.Z - pos.Z));
3630 if (error.ApproxEquals(Vector3.Zero,0.01f))
3631 { // Very close, Jump there and quit move
3632
3633 d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z);
3634 _target_velocity = Vector3.Zero;
3635 d.BodySetLinearVel(Body, _target_velocity.X, _target_velocity.Y, _target_velocity.Z);
3636 d.BodySetForce(Body, 0f, 0f, 0f);
3637 }
3638 else
3639 {
3640 float scale = 50.0f * timestep / m_PIDTau;
3641 if ((error.ApproxEquals(Vector3.Zero,0.5f)) && (_target_velocity != Vector3.Zero))
3642 {
3643 // Nearby, quit update of velocity
3644 }
3645 else
3646 { // Far, calc damped velocity
3647 _target_velocity = error * scale;
3648 }
3649 d.BodySetLinearVel(Body, _target_velocity.X, _target_velocity.Y, _target_velocity.Z);
3650 }
3651 } // end PID MoveToTarget
3652
3653
3654 /// Dynamics Hover ===================================================================================
3655 // Hover PID Controller can only run if the PIDcontroller is not in use.
3656 if (m_useHoverPID && !m_usePID)
3657 {
3658//Console.WriteLine("Hover " + m_primName);
3659
3660 // If we're using the PID controller, then we have no gravity
3661 fz = (-1 * _parent_scene.gravityz) * m_mass;
3662
3663 // no lock; for now it's only called from within Simulate()
3664
3665 // If the PID Controller isn't active then we set our force
3666 // calculating base velocity to the current position
3667
3668 if ((m_PIDTau < 1))
3669 {
3670 PID_G = PID_G / m_PIDTau;
3671 }
3672
3673 if ((PID_G - m_PIDTau) <= 0)
3674 {
3675 PID_G = m_PIDTau + 1;
3676 }
3677
3678
3679 // Where are we, and where are we headed?
3680 d.Vector3 pos = d.BodyGetPosition(Body);
3681// d.Vector3 vel = d.BodyGetLinearVel(Body);
3682
3683
3684 // Non-Vehicles have a limited set of Hover options.
3685 // determine what our target height really is based on HoverType
3686 switch (m_PIDHoverType)
3687 {
3688 case PIDHoverType.Ground:
3689 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y);
3690 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
3691 break;
3692 case PIDHoverType.GroundAndWater:
3693 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y);
3694 m_waterHeight = _parent_scene.GetWaterLevel();
3695 if (m_groundHeight > m_waterHeight)
3696 {
3697 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
3698 }
3699 else
3700 {
3701 m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight;
3702 }
3703 break;
3704
3705 } // end switch (m_PIDHoverType)
3706
3707
3708 _target_velocity =
3709 new Vector3(0.0f, 0.0f,
3710 (m_targetHoverHeight - pos.Z) * ((PID_G - m_PIDHoverTau) * timestep)
3711 );
3712
3713 // if velocity is zero, use position control; otherwise, velocity control
3714
3715 if (_target_velocity.ApproxEquals(Vector3.Zero, 0.1f))
3716 {
3717 // keep track of where we stopped. No more slippin' & slidin'
3718
3719 // We only want to deactivate the PID Controller if we think we want to have our surrogate
3720 // react to the physics scene by moving it's position.
3721 // Avatar to Avatar collisions
3722 // Prim to avatar collisions
3723 d.Vector3 dlinvel = vel;
3724 d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight);
3725 d.BodySetLinearVel(Body, dlinvel.X, dlinvel.Y, dlinvel.Z);
3726 d.BodyAddForce(Body, 0, 0, fz);
3727 //KF this prevents furthur motions return;
3728 }
3729 else
3730 {
3731 _zeroFlag = false;
3732
3733 // We're flying and colliding with something
3734 fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass);
3735 }
3736 } // end m_useHoverPID && !m_usePID
3737
3738
3739 /// Dynamics Apply Forces ===================================================================================
3740 fx *= m_mass;
3741 fy *= m_mass;
3742 //fz *= m_mass;
3743 fx += m_force.X;
3744 fy += m_force.Y;
3745 fz += m_force.Z;
3746
3747 //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString());
3748 if (fx != 0 || fy != 0 || fz != 0)
3749 {
3750 //m_taintdisable = true;
3751 //base.RaiseOutOfBounds(Position);
3752 //d.BodySetLinearVel(Body, fx, fy, 0f);
3753 if (!d.BodyIsEnabled(Body))
3754 {
3755 // A physical body at rest on a surface will auto-disable after a while,
3756 // this appears to re-enable it incase the surface it is upon vanishes,
3757 // and the body should fall again.
3758 d.BodySetLinearVel(Body, 0f, 0f, 0f);
3759 d.BodySetForce(Body, 0f, 0f, 0f);
3760 enableBodySoft();
3761 }
3762
3763 // 35x10 = 350n times the mass per second applied maximum.
3764 float nmax = 35f * m_mass;
3765 float nmin = -35f * m_mass;
3766
3767
3768 if (fx > nmax)
3769 fx = nmax;
3770 if (fx < nmin)
3771 fx = nmin;
3772 if (fy > nmax)
3773 fy = nmax;
3774 if (fy < nmin)
3775 fy = nmin;
3776 d.BodyAddForce(Body, fx, fy, fz);
3777 } // end apply forces
3778 } // end Vehicle/Dynamics
3779
3780 /// RotLookAt / LookAt =================================================================================
3781 if (m_useAPID)
3782 {
3783 // RotLookAt, apparently overrides all other rotation sources. Inputs:
3784 // Quaternion m_APIDTarget
3785 // float m_APIDStrength // From SL experiments, this is the time to get there
3786 // float m_APIDDamping // From SL experiments, this is damping, 1.0 = damped, 0.1 = wobbly
3787 // Also in SL the mass of the object has no effect on time to get there.
3788 // Factors:
3789 // get present body rotation
3790 float limit = 1.0f;
3791 float rscaler = 50f; // adjusts rotation damping time
3792 float lscaler = 10f; // adjusts linear damping time in llLookAt
3793 float RLAservo = 0f;
3794 Vector3 diff_axis;
3795 float diff_angle;
3796 d.Quaternion rot = d.BodyGetQuaternion(Body); // prim present rotation
3797 Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W);
3798 Quaternion rtarget = new Quaternion();
3799
3800 if(m_APIDTarget.W == -99.9f)
3801 {
3802 // this is really a llLookAt(), x,y,z is the target vector
3803 Vector3 target = new Vector3(m_APIDTarget.X, m_APIDTarget.Y, m_APIDTarget.Z);
3804 Vector3 ospin = new Vector3(1.0f, 0.0f, 0.0f) * rotq;
3805 Vector3 error = new Vector3(0.0f, 0.0f, 0.0f);
3806 float twopi = 2.0f * (float)Math.PI;
3807 Vector3 dir = target - _position;
3808 dir.Normalize();
3809 float tzrot = (float)Math.Atan2(dir.Y, dir.X);
3810 float txy = (float)Math.Sqrt((dir.X * dir.X) + (dir.Y * dir.Y));
3811 float terot = (float)Math.Atan2(dir.Z, txy);
3812 float ozrot = (float)Math.Atan2(ospin.Y, ospin.X);
3813 float oxy = (float)Math.Sqrt((ospin.X * ospin.X) + (ospin.Y * ospin.Y));
3814 float oerot = (float)Math.Atan2(ospin.Z, oxy);
3815 float ra = 2.0f * ((rotq.W * rotq.X) + (rotq.Y * rotq.Z));
3816 float rb = 1.0f - 2.0f * ((rotq.Y * rotq.Y)+(rotq.X * rotq.X));
3817 float roll = (float)Math.Atan2(ra, rb);
3818 float errorz = tzrot - ozrot;
3819 if(errorz > (float)Math.PI) errorz -= twopi;
3820 else if(errorz < -(float)Math.PI) errorz += twopi;
3821 float errory = oerot - terot;
3822 if(errory > (float)Math.PI) errory -= twopi;
3823 else if(errory < -(float)Math.PI) errory += twopi;
3824 diff_angle = Math.Abs(errorz) + Math.Abs(errory) + Math.Abs(roll);
3825 if(diff_angle > 0.01f * m_APIDdamper)
3826 {
3827 m_APIDdamper = 1.0f;
3828 RLAservo = timestep / m_APIDStrength * rscaler;
3829 errorz *= RLAservo;
3830 errory *= RLAservo;
3831 error.X = -roll * 8.0f;
3832 error.Y = errory;
3833 error.Z = errorz;
3834 error *= rotq;
3835 d.BodySetAngularVel (Body, error.X, error.Y, error.Z);
3836 }
3837 else
3838 {
3839 d.BodySetAngularVel (Body, 0.0f, 0.0f, 0.0f);
3840 m_APIDdamper = 2.0f;
3841 }
3842 }
3843 else
3844 {
3845 // this is a llRotLookAt()
3846 rtarget = m_APIDTarget;
3847
3848 Quaternion rot_diff = Quaternion.Inverse(rotq) * rtarget; // difference to desired rot
3849 rot_diff.GetAxisAngle(out diff_axis, out diff_angle); // convert to axis to point at & error angle
3850//if(frcount == 0) Console.WriteLine("axis {0} angle {1}",diff_axis * 57.3f, diff_angle);
3851
3852 // diff_axis.Normalize(); it already is!
3853 if(diff_angle > 0.01f * m_APIDdamper) // diff_angle is always +ve // if there is enough error
3854 {
3855 m_APIDdamper = 1.0f;
3856 Vector3 rotforce = new Vector3(diff_axis.X, diff_axis.Y, diff_axis.Z);
3857 rotforce = rotforce * rotq;
3858 if(diff_angle > limit) diff_angle = limit; // cap the rotate rate
3859 RLAservo = timestep / m_APIDStrength * lscaler;
3860 rotforce = rotforce * RLAservo * diff_angle ;
3861 d.BodySetAngularVel (Body, rotforce.X, rotforce.Y, rotforce.Z);
3862//Console.WriteLine("axis= " + diff_axis + " angle= " + diff_angle + "servo= " + RLAservo);
3863 }
3864 else
3865 { // close enough
3866 d.BodySetAngularVel (Body, 0.0f, 0.0f, 0.0f);
3867 m_APIDdamper = 2.0f;
3868 }
3869 } // end llLookAt/llRotLookAt
3870//if(frcount == 0) Console.WriteLine("mass= " + m_mass + " servo= " + RLAservo + " angle= " + diff_angle);
3871 } // end m_useAPID
3872 } // end root prims
3873 } // end Move()
3874 } // end class
3875}
diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODERayCastRequestManager.cs b/OpenSim/Region/Physics/ChOdePlugin/ODERayCastRequestManager.cs
new file mode 100644
index 0000000..712029e
--- /dev/null
+++ b/OpenSim/Region/Physics/ChOdePlugin/ODERayCastRequestManager.cs
@@ -0,0 +1,384 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Runtime.InteropServices;
32using System.Text;
33using OpenMetaverse;
34using OpenSim.Region.Physics.Manager;
35using Ode.NET;
36using log4net;
37
38namespace OpenSim.Region.Physics.OdePlugin
39{
40 /// <summary>
41 /// Processes raycast requests as ODE is in a state to be able to do them.
42 /// This ensures that it's thread safe and there will be no conflicts.
43 /// Requests get returned by a different thread then they were requested by.
44 /// </summary>
45 public class ODERayCastRequestManager
46 {
47 /// <summary>
48 /// Pending Raycast Requests
49 /// </summary>
50 protected List<ODERayCastRequest> m_PendingRequests = new List<ODERayCastRequest>();
51
52 /// <summary>
53 /// Scene that created this object.
54 /// </summary>
55 private OdeScene m_scene;
56
57 /// <summary>
58 /// ODE contact array to be filled by the collision testing
59 /// </summary>
60 d.ContactGeom[] contacts = new d.ContactGeom[5];
61
62 /// <summary>
63 /// ODE near callback delegate
64 /// </summary>
65 private d.NearCallback nearCallback;
66 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
67 private List<ContactResult> m_contactResults = new List<ContactResult>();
68
69
70 public ODERayCastRequestManager(OdeScene pScene)
71 {
72 m_scene = pScene;
73 nearCallback = near;
74
75 }
76
77 /// <summary>
78 /// Queues a raycast
79 /// </summary>
80 /// <param name="position">Origin of Ray</param>
81 /// <param name="direction">Ray normal</param>
82 /// <param name="length">Ray length</param>
83 /// <param name="retMethod">Return method to send the results</param>
84 public void QueueRequest(Vector3 position, Vector3 direction, float length, RaycastCallback retMethod)
85 {
86 lock (m_PendingRequests)
87 {
88 ODERayCastRequest req = new ODERayCastRequest();
89 req.callbackMethod = retMethod;
90 req.length = length;
91 req.Normal = direction;
92 req.Origin = position;
93
94 m_PendingRequests.Add(req);
95 }
96 }
97
98 /// <summary>
99 /// Process all queued raycast requests
100 /// </summary>
101 /// <returns>Time in MS the raycasts took to process.</returns>
102 public int ProcessQueuedRequests()
103 {
104 int time = System.Environment.TickCount;
105 lock (m_PendingRequests)
106 {
107 if (m_PendingRequests.Count > 0)
108 {
109 ODERayCastRequest[] reqs = m_PendingRequests.ToArray();
110 for (int i = 0; i < reqs.Length; i++)
111 {
112 try
113 {
114 if (reqs[i].callbackMethod != null) // quick optimization here, don't raycast
115 RayCast(reqs[i]); // if there isn't anyone to send results
116 }
117 catch
118 {
119 //Fail silently
120 //This can genuinely happen because raycast requests are queued, and the actor may have
121 //been removed from the scene since it was queued
122 }
123 }
124 /*
125 foreach (ODERayCastRequest req in m_PendingRequests)
126 {
127 if (req.callbackMethod != null) // quick optimization here, don't raycast
128 RayCast(req); // if there isn't anyone to send results to
129
130 }
131 */
132 m_PendingRequests.Clear();
133 }
134 }
135
136 lock (m_contactResults)
137 m_contactResults.Clear();
138
139 return System.Environment.TickCount - time;
140 }
141
142 /// <summary>
143 /// Method that actually initiates the raycast
144 /// </summary>
145 /// <param name="req"></param>
146 private void RayCast(ODERayCastRequest req)
147 {
148 // Create the ray
149 IntPtr ray = d.CreateRay(m_scene.space, req.length);
150 d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z);
151
152 // Collide test
153 d.SpaceCollide2(m_scene.space, ray, IntPtr.Zero, nearCallback);
154
155 // Remove Ray
156 d.GeomDestroy(ray);
157
158
159 // Define default results
160 bool hitYN = false;
161 uint hitConsumerID = 0;
162 float distance = 999999999999f;
163 Vector3 closestcontact = new Vector3(99999f, 99999f, 99999f);
164 Vector3 snormal = Vector3.Zero;
165
166 // Find closest contact and object.
167 lock (m_contactResults)
168 {
169 foreach (ContactResult cResult in m_contactResults)
170 {
171 if (Vector3.Distance(req.Origin, cResult.Pos) < Vector3.Distance(req.Origin, closestcontact))
172 {
173 closestcontact = cResult.Pos;
174 hitConsumerID = cResult.ConsumerID;
175 distance = cResult.Depth;
176 hitYN = true;
177 snormal = cResult.Normal;
178 }
179 }
180
181 m_contactResults.Clear();
182 }
183
184 // Return results
185 if (req.callbackMethod != null)
186 req.callbackMethod(hitYN, closestcontact, hitConsumerID, distance, snormal);
187 }
188
189 // This is the standard Near. Uses space AABBs to speed up detection.
190 private void near(IntPtr space, IntPtr g1, IntPtr g2)
191 {
192
193 //Don't test against heightfield Geom, or you'll be sorry!
194
195 /*
196 terminate called after throwing an instance of 'std::bad_alloc'
197 what(): std::bad_alloc
198 Stacktrace:
199
200 at (wrapper managed-to-native) Ode.NET.d.Collide (intptr,intptr,int,Ode.NET.d/ContactGeom[],int) <0x00004>
201 at (wrapper managed-to-native) Ode.NET.d.Collide (intptr,intptr,int,Ode.NET.d/ContactGeom[],int) <0xffffffff>
202 at OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.near (intptr,intptr,intptr) <0x00280>
203 at (wrapper native-to-managed) OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.near (intptr,intptr,intptr) <0xfff
204 fffff>
205 at (wrapper managed-to-native) Ode.NET.d.SpaceCollide2 (intptr,intptr,intptr,Ode.NET.d/NearCallback) <0x00004>
206 at (wrapper managed-to-native) Ode.NET.d.SpaceCollide2 (intptr,intptr,intptr,Ode.NET.d/NearCallback) <0xffffffff>
207 at OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.RayCast (OpenSim.Region.Physics.OdePlugin.ODERayCastRequest) <
208 0x00114>
209 at OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.ProcessQueuedRequests () <0x000eb>
210 at OpenSim.Region.Physics.OdePlugin.OdeScene.Simulate (single) <0x017e6>
211 at OpenSim.Region.Framework.Scenes.SceneGraph.UpdatePhysics (double) <0x00042>
212 at OpenSim.Region.Framework.Scenes.Scene.Update () <0x0039e>
213 at OpenSim.Region.Framework.Scenes.Scene.Heartbeat (object) <0x00019>
214 at (wrapper runtime-invoke) object.runtime_invoke_void__this___object (object,intptr,intptr,intptr) <0xffffffff>
215
216 Native stacktrace:
217
218 mono [0x80d2a42]
219 [0xb7f5840c]
220 /lib/i686/cmov/libc.so.6(abort+0x188) [0xb7d1a018]
221 /usr/lib/libstdc++.so.6(_ZN9__gnu_cxx27__verbose_terminate_handlerEv+0x158) [0xb45fc988]
222 /usr/lib/libstdc++.so.6 [0xb45fa865]
223 /usr/lib/libstdc++.so.6 [0xb45fa8a2]
224 /usr/lib/libstdc++.so.6 [0xb45fa9da]
225 /usr/lib/libstdc++.so.6(_Znwj+0x83) [0xb45fb033]
226 /usr/lib/libstdc++.so.6(_Znaj+0x1d) [0xb45fb11d]
227 libode.so(_ZN13dxHeightfield23dCollideHeightfieldZoneEiiiiP6dxGeomiiP12dContactGeomi+0xd04) [0xb46678e4]
228 libode.so(_Z19dCollideHeightfieldP6dxGeomS0_iP12dContactGeomi+0x54b) [0xb466832b]
229 libode.so(dCollide+0x102) [0xb46571b2]
230 [0x95cfdec9]
231 [0x8ea07fe1]
232 [0xab260146]
233 libode.so [0xb465a5c4]
234 libode.so(_ZN11dxHashSpace8collide2EPvP6dxGeomPFvS0_S2_S2_E+0x75) [0xb465bcf5]
235 libode.so(dSpaceCollide2+0x177) [0xb465ac67]
236 [0x95cf978e]
237 [0x8ea07945]
238 [0x95cf2bbc]
239 [0xab2787e7]
240 [0xab419fb3]
241 [0xab416657]
242 [0xab415bda]
243 [0xb609b08e]
244 mono(mono_runtime_delegate_invoke+0x34) [0x8192534]
245 mono [0x81a2f0f]
246 mono [0x81d28b6]
247 mono [0x81ea2c6]
248 /lib/i686/cmov/libpthread.so.0 [0xb7e744c0]
249 /lib/i686/cmov/libc.so.6(clone+0x5e) [0xb7dcd6de]
250 */
251
252 // Exclude heightfield geom
253
254 if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
255 return;
256 if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass || d.GeomGetClass(g2) == d.GeomClassID.HeightfieldClass)
257 return;
258
259 // Raytest against AABBs of spaces first, then dig into the spaces it hits for actual geoms.
260 if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2))
261 {
262 if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
263 return;
264
265 // Separating static prim geometry spaces.
266 // We'll be calling near recursivly if one
267 // of them is a space to find all of the
268 // contact points in the space
269 try
270 {
271 d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
272 }
273 catch (AccessViolationException)
274 {
275 m_log.Warn("[PHYSICS]: Unable to collide test a space");
276 return;
277 }
278 //Colliding a space or a geom with a space or a geom. so drill down
279
280 //Collide all geoms in each space..
281 //if (d.GeomIsSpace(g1)) d.SpaceCollide(g1, IntPtr.Zero, nearCallback);
282 //if (d.GeomIsSpace(g2)) d.SpaceCollide(g2, IntPtr.Zero, nearCallback);
283 return;
284 }
285
286 if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
287 return;
288
289 int count = 0;
290 try
291 {
292
293 if (g1 == g2)
294 return; // Can't collide with yourself
295
296 lock (contacts)
297 {
298 count = d.Collide(g1, g2, contacts.GetLength(0), contacts, d.ContactGeom.SizeOf);
299 }
300 }
301 catch (SEHException)
302 {
303 m_log.Error("[PHYSICS]: The Operating system shut down ODE because of corrupt memory. This could be a result of really irregular terrain. If this repeats continuously, restart using Basic Physics and terrain fill your terrain. Restarting the sim.");
304 }
305 catch (Exception e)
306 {
307 m_log.WarnFormat("[PHYSICS]: Unable to collide test an object: {0}", e.Message);
308 return;
309 }
310
311 PhysicsActor p1 = null;
312 PhysicsActor p2 = null;
313
314 if (g1 != IntPtr.Zero)
315 m_scene.actor_name_map.TryGetValue(g1, out p1);
316
317 if (g2 != IntPtr.Zero)
318 m_scene.actor_name_map.TryGetValue(g1, out p2);
319
320 // Loop over contacts, build results.
321 for (int i = 0; i < count; i++)
322 {
323 if (p1 != null) {
324 if (p1 is OdePrim)
325 {
326 ContactResult collisionresult = new ContactResult();
327
328 collisionresult.ConsumerID = ((OdePrim)p1).m_localID;
329 collisionresult.Pos = new Vector3(contacts[i].pos.X, contacts[i].pos.Y, contacts[i].pos.Z);
330 collisionresult.Depth = contacts[i].depth;
331 collisionresult.Normal = new Vector3(contacts[i].normal.X, contacts[i].normal.Y,
332 contacts[i].normal.Z);
333 lock (m_contactResults)
334 m_contactResults.Add(collisionresult);
335 }
336 }
337
338 if (p2 != null)
339 {
340 if (p2 is OdePrim)
341 {
342 ContactResult collisionresult = new ContactResult();
343
344 collisionresult.ConsumerID = ((OdePrim)p2).m_localID;
345 collisionresult.Pos = new Vector3(contacts[i].pos.X, contacts[i].pos.Y, contacts[i].pos.Z);
346 collisionresult.Depth = contacts[i].depth;
347 collisionresult.Normal = new Vector3(contacts[i].normal.X, contacts[i].normal.Y,
348 contacts[i].normal.Z);
349
350 lock (m_contactResults)
351 m_contactResults.Add(collisionresult);
352 }
353 }
354
355
356 }
357
358 }
359
360 /// <summary>
361 /// Dereference the creator scene so that it can be garbage collected if needed.
362 /// </summary>
363 internal void Dispose()
364 {
365 m_scene = null;
366 }
367 }
368
369 public struct ODERayCastRequest
370 {
371 public Vector3 Origin;
372 public Vector3 Normal;
373 public float length;
374 public RaycastCallback callbackMethod;
375 }
376
377 public struct ContactResult
378 {
379 public Vector3 Pos;
380 public float Depth;
381 public uint ConsumerID;
382 public Vector3 Normal;
383 }
384}
diff --git a/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs b/OpenSim/Region/Physics/ChOdePlugin/OdePhysicsJoint.cs
index ca7a4f8..b4a3c48 100644
--- a/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs
+++ b/OpenSim/Region/Physics/ChOdePlugin/OdePhysicsJoint.cs
@@ -26,51 +26,23 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using OpenMetaverse;
30using Nini.Config; 30using Ode.NET;
31using OpenSim.Framework; 31using OpenSim.Framework;
32using OpenSim.Region.Physics.Manager; 32using OpenSim.Region.Physics.Manager;
33using PhysXWrapper; 33using OpenSim.Region.Physics.OdePlugin;
34using Quaternion=OpenMetaverse.Quaternion;
35using System.Reflection;
36using log4net;
37using OpenMetaverse;
38 34
39namespace OpenSim.Region.Physics.PhysXPlugin 35namespace OpenSim.Region.Physics.OdePlugin
40{ 36{
41 /// <summary> 37 class OdePhysicsJoint : PhysicsJoint
42 /// Will be the PhysX plugin but for now will be a very basic physics engine
43 /// </summary>
44 public class PhysXPlugin : IPhysicsPlugin
45 { 38 {
46 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 39 public override bool IsInPhysicsEngine
47 private PhysXScene _mScene;
48
49 public PhysXPlugin()
50 {
51 }
52
53 public bool Init()
54 { 40 {
55 return true; 41 get
56 }
57
58 public PhysicsScene GetScene(string sceneIdentifier)
59 {
60 if (_mScene == null)
61 { 42 {
62 _mScene = new PhysXScene(sceneIdentifier); 43 return (jointID != IntPtr.Zero);
63 } 44 }
64 return (_mScene);
65 }
66
67 public string GetName()
68 {
69 return ("RealPhysX");
70 }
71
72 public void Dispose()
73 {
74 } 45 }
46 public IntPtr jointID;
75 } 47 }
76} 48}
diff --git a/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs
new file mode 100644
index 0000000..353db44
--- /dev/null
+++ b/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs
@@ -0,0 +1,3841 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28//#define USE_DRAWSTUFF
29
30using System;
31using System.Collections.Generic;
32using System.Reflection;
33using System.Runtime.InteropServices;
34using System.Threading;
35using System.IO;
36using System.Diagnostics;
37using log4net;
38using Nini.Config;
39using Ode.NET;
40#if USE_DRAWSTUFF
41using Drawstuff.NET;
42#endif
43using OpenSim.Framework;
44using OpenSim.Region.Physics.Manager;
45using OpenMetaverse;
46
47//using OpenSim.Region.Physics.OdePlugin.Meshing;
48
49namespace OpenSim.Region.Physics.OdePlugin
50{
51 /// <summary>
52 /// ODE plugin
53 /// </summary>
54 public class OdePlugin : IPhysicsPlugin
55 {
56 //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
57
58 private CollisionLocker ode;
59 private OdeScene _mScene;
60
61 public OdePlugin()
62 {
63 ode = new CollisionLocker();
64 }
65
66 public bool Init()
67 {
68 return true;
69 }
70
71 public PhysicsScene GetScene(String sceneIdentifier)
72 {
73 if (_mScene == null)
74 {
75 // Initializing ODE only when a scene is created allows alternative ODE plugins to co-habit (according to
76 // http://opensimulator.org/mantis/view.php?id=2750).
77 d.InitODE();
78
79 _mScene = new OdeScene(ode, sceneIdentifier);
80 }
81 return (_mScene);
82 }
83
84 public string GetName()
85 {
86 return ("ChODE");
87 }
88
89 public void Dispose()
90 {
91 }
92 }
93
94 public enum StatusIndicators : int
95 {
96 Generic = 0,
97 Start = 1,
98 End = 2
99 }
100
101 public struct sCollisionData
102 {
103 public uint ColliderLocalId;
104 public uint CollidedWithLocalId;
105 public int NumberOfCollisions;
106 public int CollisionType;
107 public int StatusIndicator;
108 public int lastframe;
109 }
110
111 [Flags]
112 public enum CollisionCategories : int
113 {
114 Disabled = 0,
115 Geom = 0x00000001,
116 Body = 0x00000002,
117 Space = 0x00000004,
118 Character = 0x00000008,
119 Land = 0x00000010,
120 Water = 0x00000020,
121 Wind = 0x00000040,
122 Sensor = 0x00000080,
123 Selected = 0x00000100
124 }
125
126 /// <summary>
127 /// Material type for a primitive
128 /// </summary>
129 public enum Material : int
130 {
131 /// <summary></summary>
132 Stone = 0,
133 /// <summary></summary>
134 Metal = 1,
135 /// <summary></summary>
136 Glass = 2,
137 /// <summary></summary>
138 Wood = 3,
139 /// <summary></summary>
140 Flesh = 4,
141 /// <summary></summary>
142 Plastic = 5,
143 /// <summary></summary>
144 Rubber = 6
145
146 }
147
148 public sealed class OdeScene : PhysicsScene
149 {
150 private readonly ILog m_log;
151 // private Dictionary<string, sCollisionData> m_storedCollisions = new Dictionary<string, sCollisionData>();
152
153 CollisionLocker ode;
154
155 private Random fluidRandomizer = new Random(Environment.TickCount);
156
157 private const uint m_regionWidth = Constants.RegionSize;
158 private const uint m_regionHeight = Constants.RegionSize;
159
160 private float ODE_STEPSIZE = 0.020f;
161 private float metersInSpace = 29.9f;
162 private float m_timeDilation = 1.0f;
163
164 public float gravityx = 0f;
165 public float gravityy = 0f;
166 public float gravityz = -9.8f;
167
168 private float contactsurfacelayer = 0.001f;
169
170 private int worldHashspaceLow = -4;
171 private int worldHashspaceHigh = 128;
172
173 private int smallHashspaceLow = -4;
174 private int smallHashspaceHigh = 66;
175
176 private float waterlevel = 0f;
177 private int framecount = 0;
178 //private int m_returncollisions = 10;
179
180 private readonly IntPtr contactgroup;
181
182 internal IntPtr LandGeom;
183 internal IntPtr WaterGeom;
184
185 private float nmTerrainContactFriction = 255.0f;
186 private float nmTerrainContactBounce = 0.1f;
187 private float nmTerrainContactERP = 0.1025f;
188
189 private float mTerrainContactFriction = 75f;
190 private float mTerrainContactBounce = 0.1f;
191 private float mTerrainContactERP = 0.05025f;
192
193 private float nmAvatarObjectContactFriction = 250f;
194 private float nmAvatarObjectContactBounce = 0.1f;
195
196 private float mAvatarObjectContactFriction = 75f;
197 private float mAvatarObjectContactBounce = 0.1f;
198
199 private float avPIDD = 3200f;
200 private float avPIDP = 1400f;
201 private float avCapRadius = 0.37f;
202 private float avStandupTensor = 2000000f;
203 private bool avCapsuleTilted = true; // true = old compatibility mode with leaning capsule; false = new corrected mode
204 public bool IsAvCapsuleTilted { get { return avCapsuleTilted; } set { avCapsuleTilted = value; } }
205 private float avDensity = 80f;
206 private float avHeightFudgeFactor = 0.52f;
207 private float avMovementDivisorWalk = 1.3f;
208 private float avMovementDivisorRun = 0.8f;
209 private float minimumGroundFlightOffset = 3f;
210 public float maximumMassObject = 10000.01f;
211
212 public bool meshSculptedPrim = true;
213 public bool forceSimplePrimMeshing = false;
214
215 public float meshSculptLOD = 32;
216 public float MeshSculptphysicalLOD = 16;
217
218 public float geomDefaultDensity = 10.000006836f;
219
220 public int geomContactPointsStartthrottle = 3;
221 public int geomUpdatesPerThrottledUpdate = 15;
222
223 public float bodyPIDD = 35f;
224 public float bodyPIDG = 25;
225
226 public int geomCrossingFailuresBeforeOutofbounds = 5;
227 public float geomRegionFence = 0.0f;
228
229 public float bodyMotorJointMaxforceTensor = 2;
230
231 public int bodyFramesAutoDisable = 20;
232
233 private DateTime m_lastframe = DateTime.UtcNow;
234
235 private float[] _watermap;
236 private bool m_filterCollisions = true;
237
238 private d.NearCallback nearCallback;
239 public d.TriCallback triCallback;
240 public d.TriArrayCallback triArrayCallback;
241 private readonly HashSet<OdeCharacter> _characters = new HashSet<OdeCharacter>();
242 private readonly HashSet<OdePrim> _prims = new HashSet<OdePrim>();
243 private readonly HashSet<OdePrim> _activeprims = new HashSet<OdePrim>();
244 private readonly HashSet<OdePrim> _taintedPrimH = new HashSet<OdePrim>();
245 private readonly Object _taintedPrimLock = new Object();
246 private readonly List<OdePrim> _taintedPrimL = new List<OdePrim>();
247 private readonly HashSet<OdeCharacter> _taintedActors = new HashSet<OdeCharacter>();
248 private readonly List<d.ContactGeom> _perloopContact = new List<d.ContactGeom>();
249 private readonly List<PhysicsActor> _collisionEventPrim = new List<PhysicsActor>();
250 private readonly HashSet<OdeCharacter> _badCharacter = new HashSet<OdeCharacter>();
251 public Dictionary<IntPtr, String> geom_name_map = new Dictionary<IntPtr, String>();
252 public Dictionary<IntPtr, PhysicsActor> actor_name_map = new Dictionary<IntPtr, PhysicsActor>();
253 private bool m_NINJA_physics_joints_enabled = false;
254 //private Dictionary<String, IntPtr> jointpart_name_map = new Dictionary<String,IntPtr>();
255 private readonly Dictionary<String, List<PhysicsJoint>> joints_connecting_actor = new Dictionary<String, List<PhysicsJoint>>();
256 private d.ContactGeom[] contacts;
257 private readonly List<PhysicsJoint> requestedJointsToBeCreated = new List<PhysicsJoint>(); // lock only briefly. accessed by external code (to request new joints) and by OdeScene.Simulate() to move those joints into pending/active
258 private readonly List<PhysicsJoint> pendingJoints = new List<PhysicsJoint>(); // can lock for longer. accessed only by OdeScene.
259 private readonly List<PhysicsJoint> activeJoints = new List<PhysicsJoint>(); // can lock for longer. accessed only by OdeScene.
260 private readonly List<string> requestedJointsToBeDeleted = new List<string>(); // lock only briefly. accessed by external code (to request deletion of joints) and by OdeScene.Simulate() to move those joints out of pending/active
261 private Object externalJointRequestsLock = new Object();
262 private readonly Dictionary<String, PhysicsJoint> SOPName_to_activeJoint = new Dictionary<String, PhysicsJoint>();
263 private readonly Dictionary<String, PhysicsJoint> SOPName_to_pendingJoint = new Dictionary<String, PhysicsJoint>();
264 private readonly DoubleDictionary<Vector3, IntPtr, IntPtr> RegionTerrain = new DoubleDictionary<Vector3, IntPtr, IntPtr>();
265 private readonly Dictionary<IntPtr,float[]> TerrainHeightFieldHeights = new Dictionary<IntPtr, float[]>();
266
267 private d.Contact ContactCopy; // local copy that can be modified
268 private d.Contact TerrainContact;
269 private d.Contact AvatarStaticprimContact; // was 'contact'
270 private d.Contact AvatarMovementprimContact;
271 private d.Contact AvatarMovementTerrainContact;
272 private d.Contact WaterContact;
273 private d.Contact[,] m_materialContacts;
274
275//Ckrinke: Comment out until used. We declare it, initialize it, but do not use it
276//Ckrinke private int m_randomizeWater = 200;
277 private int m_physicsiterations = 10;
278 private const float m_SkipFramesAtms = 0.40f; // Drop frames gracefully at a 400 ms lag
279 private readonly PhysicsActor PANull = new NullPhysicsActor();
280 private float step_time = 0.0f;
281//Ckrinke: Comment out until used. We declare it, initialize it, but do not use it
282//Ckrinke private int ms = 0;
283 public IntPtr world;
284 //private bool returncollisions = false;
285 // private uint obj1LocalID = 0;
286 private uint obj2LocalID = 0;
287 //private int ctype = 0;
288 private OdeCharacter cc1;
289 private OdePrim cp1;
290 private OdeCharacter cc2;
291 private OdePrim cp2;
292 //private int cStartStop = 0;
293 //private string cDictKey = "";
294
295 public IntPtr space;
296
297 //private IntPtr tmpSpace;
298 // split static geometry collision handling into spaces of 30 meters
299 public IntPtr[,] staticPrimspace;
300
301 public Object OdeLock;
302
303 public IMesher mesher;
304
305 private IConfigSource m_config;
306
307 public bool physics_logging = false;
308 public int physics_logging_interval = 0;
309 public bool physics_logging_append_existing_logfile = false;
310
311 public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f);
312 public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f);
313
314 // TODO: unused: private uint heightmapWidth = m_regionWidth + 1;
315 // TODO: unused: private uint heightmapHeight = m_regionHeight + 1;
316 // TODO: unused: private uint heightmapWidthSamples;
317 // TODO: unused: private uint heightmapHeightSamples;
318
319 private volatile int m_global_contactcount = 0;
320
321 private Vector3 m_worldOffset = Vector3.Zero;
322 public Vector2 WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize);
323 private PhysicsScene m_parentScene = null;
324
325 private ODERayCastRequestManager m_rayCastManager;
326
327 /// <summary>
328 /// Initiailizes the scene
329 /// Sets many properties that ODE requires to be stable
330 /// These settings need to be tweaked 'exactly' right or weird stuff happens.
331 /// </summary>
332 public OdeScene(CollisionLocker dode, string sceneIdentifier)
333 {
334 m_log
335 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.ToString() + "." + sceneIdentifier);
336
337 OdeLock = new Object();
338 ode = dode;
339 nearCallback = near;
340 triCallback = TriCallback;
341 triArrayCallback = TriArrayCallback;
342 m_rayCastManager = new ODERayCastRequestManager(this);
343 lock (OdeLock)
344 {
345 // Create the world and the first space
346 world = d.WorldCreate();
347 space = d.HashSpaceCreate(IntPtr.Zero);
348
349
350 contactgroup = d.JointGroupCreate(0);
351 //contactgroup
352
353 d.WorldSetAutoDisableFlag(world, false);
354 #if USE_DRAWSTUFF
355
356 Thread viewthread = new Thread(new ParameterizedThreadStart(startvisualization));
357 viewthread.Start();
358 #endif
359 }
360
361
362 _watermap = new float[258 * 258];
363
364 // Zero out the prim spaces array (we split our space into smaller spaces so
365 // we can hit test less.
366 }
367
368#if USE_DRAWSTUFF
369 public void startvisualization(object o)
370 {
371 ds.Functions fn;
372 fn.version = ds.VERSION;
373 fn.start = new ds.CallbackFunction(start);
374 fn.step = new ds.CallbackFunction(step);
375 fn.command = new ds.CallbackFunction(command);
376 fn.stop = null;
377 fn.path_to_textures = "./textures";
378 string[] args = new string[0];
379 ds.SimulationLoop(args.Length, args, 352, 288, ref fn);
380 }
381#endif
382
383 // Initialize the mesh plugin
384 public override void Initialise(IMesher meshmerizer, IConfigSource config)
385 {
386 mesher = meshmerizer;
387 m_config = config;
388 // Defaults
389
390 if (Environment.OSVersion.Platform == PlatformID.Unix)
391 {
392 avPIDD = 3200.0f;
393 avPIDP = 1400.0f;
394 avStandupTensor = 2000000f;
395 }
396 else
397 {
398 avPIDD = 2200.0f;
399 avPIDP = 900.0f;
400 avStandupTensor = 550000f;
401 }
402
403 int contactsPerCollision = 80;
404
405 if (m_config != null)
406 {
407 IConfig physicsconfig = m_config.Configs["ODEPhysicsSettings"];
408 if (physicsconfig != null)
409 {
410 gravityx = physicsconfig.GetFloat("world_gravityx", 0f);
411 gravityy = physicsconfig.GetFloat("world_gravityy", 0f);
412 gravityz = physicsconfig.GetFloat("world_gravityz", -9.8f);
413
414 worldHashspaceLow = physicsconfig.GetInt("world_hashspace_size_low", -4);
415 worldHashspaceHigh = physicsconfig.GetInt("world_hashspace_size_high", 128);
416
417 metersInSpace = physicsconfig.GetFloat("meters_in_small_space", 29.9f);
418 smallHashspaceLow = physicsconfig.GetInt("small_hashspace_size_low", -4);
419 smallHashspaceHigh = physicsconfig.GetInt("small_hashspace_size_high", 66);
420
421 contactsurfacelayer = physicsconfig.GetFloat("world_contact_surface_layer", 0.001f);
422
423 nmTerrainContactFriction = physicsconfig.GetFloat("nm_terraincontact_friction", 255.0f);
424 nmTerrainContactBounce = physicsconfig.GetFloat("nm_terraincontact_bounce", 0.1f);
425 nmTerrainContactERP = physicsconfig.GetFloat("nm_terraincontact_erp", 0.1025f);
426
427 mTerrainContactFriction = physicsconfig.GetFloat("m_terraincontact_friction", 75f);
428 mTerrainContactBounce = physicsconfig.GetFloat("m_terraincontact_bounce", 0.05f);
429 mTerrainContactERP = physicsconfig.GetFloat("m_terraincontact_erp", 0.05025f);
430
431 nmAvatarObjectContactFriction = physicsconfig.GetFloat("objectcontact_friction", 250f);
432 nmAvatarObjectContactBounce = physicsconfig.GetFloat("objectcontact_bounce", 0.2f);
433
434 mAvatarObjectContactFriction = physicsconfig.GetFloat("m_avatarobjectcontact_friction", 75f);
435 mAvatarObjectContactBounce = physicsconfig.GetFloat("m_avatarobjectcontact_bounce", 0.1f);
436
437 ODE_STEPSIZE = physicsconfig.GetFloat("world_stepsize", 0.020f);
438 m_physicsiterations = physicsconfig.GetInt("world_internal_steps_without_collisions", 10);
439
440 avDensity = physicsconfig.GetFloat("av_density", 80f);
441 avHeightFudgeFactor = physicsconfig.GetFloat("av_height_fudge_factor", 0.52f);
442 avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", 1.3f);
443 avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", 0.8f);
444 avCapRadius = physicsconfig.GetFloat("av_capsule_radius", 0.37f);
445 avCapsuleTilted = physicsconfig.GetBoolean("av_capsule_tilted", false);
446
447 contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80);
448
449 geomContactPointsStartthrottle = physicsconfig.GetInt("geom_contactpoints_start_throttling", 3);
450 geomUpdatesPerThrottledUpdate = physicsconfig.GetInt("geom_updates_before_throttled_update", 15);
451 geomCrossingFailuresBeforeOutofbounds = physicsconfig.GetInt("geom_crossing_failures_before_outofbounds", 5);
452 geomRegionFence = physicsconfig.GetFloat("region_border_fence", 0.0f);
453
454 geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", 10.000006836f);
455 bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", 20);
456
457 bodyPIDD = physicsconfig.GetFloat("body_pid_derivative", 35f);
458 bodyPIDG = physicsconfig.GetFloat("body_pid_gain", 25f);
459
460 forceSimplePrimMeshing = physicsconfig.GetBoolean("force_simple_prim_meshing", forceSimplePrimMeshing);
461 meshSculptedPrim = physicsconfig.GetBoolean("mesh_sculpted_prim", true);
462 meshSculptLOD = physicsconfig.GetFloat("mesh_lod", 32f);
463 MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f);
464 m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false);
465
466 if (Environment.OSVersion.Platform == PlatformID.Unix)
467 {
468 avPIDD = physicsconfig.GetFloat("av_pid_derivative_linux", 2200.0f);
469 avPIDP = physicsconfig.GetFloat("av_pid_proportional_linux", 900.0f);
470 avStandupTensor = physicsconfig.GetFloat("av_capsule_standup_tensor_linux", 550000f);
471 bodyMotorJointMaxforceTensor = physicsconfig.GetFloat("body_motor_joint_maxforce_tensor_linux", 5f);
472 }
473 else
474 {
475 avPIDD = physicsconfig.GetFloat("av_pid_derivative_win", 2200.0f);
476 avPIDP = physicsconfig.GetFloat("av_pid_proportional_win", 900.0f);
477 avStandupTensor = physicsconfig.GetFloat("av_capsule_standup_tensor_win", 550000f);
478 bodyMotorJointMaxforceTensor = physicsconfig.GetFloat("body_motor_joint_maxforce_tensor_win", 5f);
479 }
480
481 physics_logging = physicsconfig.GetBoolean("physics_logging", false);
482 physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0);
483 physics_logging_append_existing_logfile = physicsconfig.GetBoolean("physics_logging_append_existing_logfile", false);
484
485 m_NINJA_physics_joints_enabled = physicsconfig.GetBoolean("use_NINJA_physics_joints", false);
486 minimumGroundFlightOffset = physicsconfig.GetFloat("minimum_ground_flight_offset", 3f);
487 maximumMassObject = physicsconfig.GetFloat("maximum_mass_object", 10000.01f);
488 }
489 }
490
491 contacts = new d.ContactGeom[contactsPerCollision];
492
493 staticPrimspace = new IntPtr[(int)(300 / metersInSpace), (int)(300 / metersInSpace)];
494
495 // Avatar static on a Prim parameters
496 AvatarStaticprimContact.surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
497 AvatarStaticprimContact.surface.mu = 255.0f;
498 AvatarStaticprimContact.surface.bounce = 0.0f;
499 AvatarStaticprimContact.surface.soft_cfm = 0.0f;
500 AvatarStaticprimContact.surface.soft_erp = 0.30f; // If this is too small static Av will fall through a sloping prim. 1.0 prevents fall-thru
501
502 // Avatar moving on a Prim parameters
503 AvatarMovementprimContact.surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
504 AvatarMovementprimContact.surface.mu = 255.0f;
505 AvatarMovementprimContact.surface.bounce = 0.0f;
506 AvatarMovementprimContact.surface.soft_cfm = 0.0f; // if this is 0.01 then prims become phantom to Avs!
507 AvatarMovementprimContact.surface.soft_erp = 0.3f;
508
509 // Static Avatar on Terrain parameters
510 // Keeps Avatar in place better
511 TerrainContact.surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
512 TerrainContact.surface.mu = 255.0f;
513 TerrainContact.surface.bounce = 0.0f;
514 TerrainContact.surface.soft_cfm = 0.0f;
515 TerrainContact.surface.soft_erp = 0.05f;
516
517 // Moving Avatar on Terrain parameters
518 AvatarMovementTerrainContact.surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
519 AvatarMovementTerrainContact.surface.mu = 75f;
520 AvatarMovementTerrainContact.surface.bounce = 0.0f;
521 AvatarMovementTerrainContact.surface.soft_cfm = 0.0f;
522 AvatarMovementTerrainContact.surface.soft_erp = 0.05f;
523
524 // Avatar or prim the the water, this may not be used, possibly water is same as air?
525 WaterContact.surface.mode |= (d.ContactFlags.SoftERP | d.ContactFlags.SoftCFM);
526 WaterContact.surface.mu = 0.0f; // No friction
527 WaterContact.surface.bounce = 0.0f; // No bounce
528 WaterContact.surface.soft_cfm = 0.010f;
529 WaterContact.surface.soft_erp = 0.010f;
530
531
532 // Prim static or moving on a prim, depends on material type
533 m_materialContacts = new d.Contact[7,2];
534 // V 1 = Sliding; 0 = static or fell onto
535 m_materialContacts[(int)Material.Stone, 0] = new d.Contact();
536 m_materialContacts[(int)Material.Stone, 0].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
537 m_materialContacts[(int)Material.Stone, 0].surface.mu = 60f; // friction, 1 = slippery, 255 = no slip
538 m_materialContacts[(int)Material.Stone, 0].surface.bounce = 0.0f;
539 m_materialContacts[(int)Material.Stone, 0].surface.soft_cfm = 0.0f;
540 m_materialContacts[(int)Material.Stone, 0].surface.soft_erp = 0.50f; // erp also changes friction, more erp=less friction
541
542 m_materialContacts[(int)Material.Stone, 1] = new d.Contact();
543 m_materialContacts[(int)Material.Stone, 1].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
544 m_materialContacts[(int)Material.Stone, 1].surface.mu = 40f;
545 m_materialContacts[(int)Material.Stone, 1].surface.bounce = 0.0f;
546 m_materialContacts[(int)Material.Stone, 1].surface.soft_cfm = 0.0f;
547 m_materialContacts[(int)Material.Stone, 1].surface.soft_erp = 0.50f;
548
549 m_materialContacts[(int)Material.Metal, 0] = new d.Contact();
550 m_materialContacts[(int)Material.Metal, 0].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
551 m_materialContacts[(int)Material.Metal, 0].surface.mu = 15f;
552 m_materialContacts[(int)Material.Metal, 0].surface.bounce = 0.2f;
553 m_materialContacts[(int)Material.Metal, 0].surface.soft_cfm = 0.0f;
554 m_materialContacts[(int)Material.Metal, 0].surface.soft_erp = 0.50f;
555
556 m_materialContacts[(int)Material.Metal, 1] = new d.Contact();
557 m_materialContacts[(int)Material.Metal, 1].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
558 m_materialContacts[(int)Material.Metal, 1].surface.mu = 10f;
559 m_materialContacts[(int)Material.Metal, 1].surface.bounce = 0.2f;
560 m_materialContacts[(int)Material.Metal, 1].surface.soft_cfm = 0.0f;
561 m_materialContacts[(int)Material.Metal, 1].surface.soft_erp = 0.50f;
562
563 m_materialContacts[(int)Material.Glass, 0] = new d.Contact();
564 m_materialContacts[(int)Material.Glass, 0].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
565 m_materialContacts[(int)Material.Glass, 0].surface.mu = 7.5f;
566 m_materialContacts[(int)Material.Glass, 0].surface.bounce = 0.0f;
567 m_materialContacts[(int)Material.Glass, 0].surface.soft_cfm = 0.0f;
568 m_materialContacts[(int)Material.Glass, 0].surface.soft_erp = 0.50f;
569
570 m_materialContacts[(int)Material.Glass, 1] = new d.Contact();
571 m_materialContacts[(int)Material.Glass, 1].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
572 m_materialContacts[(int)Material.Glass, 1].surface.mu = 5f;
573 m_materialContacts[(int)Material.Glass, 1].surface.bounce = 0.0f;
574 m_materialContacts[(int)Material.Glass, 1].surface.soft_cfm = 0.0f;
575 m_materialContacts[(int)Material.Glass, 1].surface.soft_erp = 0.50f;
576
577 m_materialContacts[(int)Material.Wood, 0] = new d.Contact();
578 m_materialContacts[(int)Material.Wood, 0].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
579 m_materialContacts[(int)Material.Wood, 0].surface.mu = 45f;
580 m_materialContacts[(int)Material.Wood, 0].surface.bounce = 0.1f;
581 m_materialContacts[(int)Material.Wood, 0].surface.soft_cfm = 0.0f;
582 m_materialContacts[(int)Material.Wood, 0].surface.soft_erp = 0.50f;
583
584 m_materialContacts[(int)Material.Wood, 1] = new d.Contact();
585 m_materialContacts[(int)Material.Wood, 1].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
586 m_materialContacts[(int)Material.Wood, 1].surface.mu = 30f;
587 m_materialContacts[(int)Material.Wood, 1].surface.bounce = 0.1f;
588 m_materialContacts[(int)Material.Wood, 1].surface.soft_cfm = 0.0f;
589 m_materialContacts[(int)Material.Wood, 1].surface.soft_erp = 0.50f;
590
591 m_materialContacts[(int)Material.Flesh, 0] = new d.Contact();
592 m_materialContacts[(int)Material.Flesh, 0].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
593 m_materialContacts[(int)Material.Flesh, 0].surface.mu = 150f;
594 m_materialContacts[(int)Material.Flesh, 0].surface.bounce = 0.0f;
595 m_materialContacts[(int)Material.Flesh, 0].surface.soft_cfm = 0.0f;
596 m_materialContacts[(int)Material.Flesh, 0].surface.soft_erp = 0.50f;
597
598 m_materialContacts[(int)Material.Flesh, 1] = new d.Contact();
599 m_materialContacts[(int)Material.Flesh, 1].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
600 m_materialContacts[(int)Material.Flesh, 1].surface.mu = 100f;
601 m_materialContacts[(int)Material.Flesh, 1].surface.bounce = 0.0f;
602 m_materialContacts[(int)Material.Flesh, 1].surface.soft_cfm = 0.0f;
603 m_materialContacts[(int)Material.Flesh, 1].surface.soft_erp = 0.50f;
604
605 m_materialContacts[(int)Material.Plastic, 0] = new d.Contact();
606 m_materialContacts[(int)Material.Plastic, 0].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
607 m_materialContacts[(int)Material.Plastic, 0].surface.mu = 30f;
608 m_materialContacts[(int)Material.Plastic, 0].surface.bounce = 0.2f;
609 m_materialContacts[(int)Material.Plastic, 0].surface.soft_cfm = 0.0f;
610 m_materialContacts[(int)Material.Plastic, 0].surface.soft_erp = 0.50f;
611
612 m_materialContacts[(int)Material.Plastic, 1] = new d.Contact();
613 m_materialContacts[(int)Material.Plastic, 1].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
614 m_materialContacts[(int)Material.Plastic, 1].surface.mu = 20f;
615 m_materialContacts[(int)Material.Plastic, 1].surface.bounce = 0.2f;
616 m_materialContacts[(int)Material.Plastic, 1].surface.soft_cfm = 0.0f;
617 m_materialContacts[(int)Material.Plastic, 1].surface.soft_erp = 0.50f;
618
619 m_materialContacts[(int)Material.Rubber, 0] = new d.Contact();
620 m_materialContacts[(int)Material.Rubber, 0].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
621 m_materialContacts[(int)Material.Rubber, 0].surface.mu = 150f;
622 m_materialContacts[(int)Material.Rubber, 0].surface.bounce = 0.7f;
623 m_materialContacts[(int)Material.Rubber, 0].surface.soft_cfm = 0.0f;
624 m_materialContacts[(int)Material.Rubber, 0].surface.soft_erp = 0.50f;
625
626 m_materialContacts[(int)Material.Rubber, 1] = new d.Contact();
627 m_materialContacts[(int)Material.Rubber, 1].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce;
628 m_materialContacts[(int)Material.Rubber, 1].surface.mu = 100f;
629 m_materialContacts[(int)Material.Rubber, 1].surface.bounce = 0.7f;
630 m_materialContacts[(int)Material.Rubber, 1].surface.soft_cfm = 0.0f;
631 m_materialContacts[(int)Material.Rubber, 1].surface.soft_erp = 0.50f;
632
633 d.HashSpaceSetLevels(space, worldHashspaceLow, worldHashspaceHigh);
634
635 // Set the gravity,, don't disable things automatically (we set it explicitly on some things)
636
637 d.WorldSetGravity(world, gravityx, gravityy, gravityz);
638 d.WorldSetContactSurfaceLayer(world, contactsurfacelayer);
639
640
641 d.WorldSetLinearDampingThreshold(world, 256f);
642 d.WorldSetLinearDamping(world, 256f);
643// d.WorldSetLinearDampingThreshold(world, 0.01f);
644// d.WorldSetLinearDamping(world, 0.1f);
645 d.WorldSetAngularDampingThreshold(world, 256f);
646 d.WorldSetAngularDamping(world, 256f);
647 d.WorldSetMaxAngularSpeed(world, 256f);
648
649 // Set how many steps we go without running collision testing
650 // This is in addition to the step size.
651 // Essentially Steps * m_physicsiterations
652 d.WorldSetQuickStepNumIterations(world, m_physicsiterations);
653 //d.WorldSetContactMaxCorrectingVel(world, 1000.0f);
654
655
656
657 for (int i = 0; i < staticPrimspace.GetLength(0); i++)
658 {
659 for (int j = 0; j < staticPrimspace.GetLength(1); j++)
660 {
661 staticPrimspace[i, j] = IntPtr.Zero;
662 }
663 }
664 }
665
666 internal void waitForSpaceUnlock(IntPtr space)
667 {
668 //if (space != IntPtr.Zero)
669 //while (d.SpaceLockQuery(space)) { } // Wait and do nothing
670 }
671
672 /// <summary>
673 /// Debug space message for printing the space that a prim/avatar is in.
674 /// </summary>
675 /// <param name="pos"></param>
676 /// <returns>Returns which split up space the given position is in.</returns>
677 public string whichspaceamIin(Vector3 pos)
678 {
679 return calculateSpaceForGeom(pos).ToString();
680 }
681
682 #region Collision Detection
683
684 /// <summary>
685 /// This is our near callback. A geometry is near a body
686 /// </summary>
687 /// <param name="space">The space that contains the geoms. Remember, spaces are also geoms</param>
688 /// <param name="g1">a geometry or space</param>
689 /// <param name="g2">another geometry or space</param>
690 private void near(IntPtr space, IntPtr g1, IntPtr g2)
691 {
692 // no lock here! It's invoked from within Simulate(), which is thread-locked
693
694 // Test if we're colliding a geom with a space.
695 // If so we have to drill down into the space recursively
696//Console.WriteLine("near -----------"); //##
697 if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2))
698 {
699 if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
700 return;
701
702 // Separating static prim geometry spaces.
703 // We'll be calling near recursivly if one
704 // of them is a space to find all of the
705 // contact points in the space
706 try
707 {
708 d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
709 }
710 catch (AccessViolationException)
711 {
712 m_log.Warn("[PHYSICS]: Unable to collide test a space");
713 return;
714 }
715 //Colliding a space or a geom with a space or a geom. so drill down
716
717 //Collide all geoms in each space..
718 //if (d.GeomIsSpace(g1)) d.SpaceCollide(g1, IntPtr.Zero, nearCallback);
719 //if (d.GeomIsSpace(g2)) d.SpaceCollide(g2, IntPtr.Zero, nearCallback);
720 return;
721 }
722
723 if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
724 return;
725
726 IntPtr b1 = d.GeomGetBody(g1);
727 IntPtr b2 = d.GeomGetBody(g2);
728
729 // d.GeomClassID id = d.GeomGetClass(g1);
730
731 String name1 = null;
732 String name2 = null;
733
734 if (!geom_name_map.TryGetValue(g1, out name1))
735 {
736 name1 = "null";
737 }
738 if (!geom_name_map.TryGetValue(g2, out name2))
739 {
740 name2 = "null";
741 }
742
743 //if (id == d.GeomClassId.TriMeshClass)
744 //{
745 // m_log.InfoFormat("near: A collision was detected between {1} and {2}", 0, name1, name2);
746 //m_log.Debug("near: A collision was detected between {1} and {2}", 0, name1, name2);
747 //}
748
749 // Figure out how many contact points we have
750 int count = 0;
751 try
752 {
753 // Colliding Geom To Geom
754 // This portion of the function 'was' blatantly ripped off from BoxStack.cs
755
756 if (g1 == g2)
757 return; // Can't collide with yourself
758
759 if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
760 return;
761
762 lock (contacts)
763 {
764 count = d.Collide(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf);
765 if (count > contacts.Length)
766 m_log.Error("[PHYSICS]: Got " + count + " contacts when we asked for a maximum of " + contacts.Length);
767 }
768 }
769 catch (SEHException)
770 {
771 m_log.Error("[PHYSICS]: The Operating system shut down ODE because of corrupt memory. This could be a result of really irregular terrain. If this repeats continuously, restart using Basic Physics and terrain fill your terrain. Restarting the sim.");
772 ode.drelease(world);
773 base.TriggerPhysicsBasedRestart();
774 }
775 catch (Exception e)
776 {
777 m_log.WarnFormat("[PHYSICS]: Unable to collide test an object: {0}", e.Message);
778 return;
779 }
780
781 PhysicsActor p1;
782 PhysicsActor p2;
783
784 if (!actor_name_map.TryGetValue(g1, out p1))
785 {
786 p1 = PANull;
787 }
788
789 if (!actor_name_map.TryGetValue(g2, out p2))
790 {
791 p2 = PANull;
792 }
793
794 ContactPoint maxDepthContact = new ContactPoint();
795 if (p1.CollisionScore + count >= float.MaxValue)
796 p1.CollisionScore = 0;
797 p1.CollisionScore += count;
798
799 if (p2.CollisionScore + count >= float.MaxValue)
800 p2.CollisionScore = 0;
801 p2.CollisionScore += count;
802 for (int i = 0; i < count; i++)
803 {
804 d.ContactGeom curContact = contacts[i];
805
806 if (curContact.depth > maxDepthContact.PenetrationDepth)
807 {
808 maxDepthContact = new ContactPoint(
809 new Vector3(curContact.pos.X, curContact.pos.Y, curContact.pos.Z),
810 new Vector3(curContact.normal.X, curContact.normal.Y, curContact.normal.Z),
811 curContact.depth
812 );
813 }
814
815 //m_log.Warn("[CCOUNT]: " + count);
816 IntPtr joint;
817 // If we're colliding with terrain, use 'TerrainContact' instead of AvatarStaticprimContact.
818 // allows us to have different settings
819
820 // We only need to test p2 for 'jump crouch purposes'
821 if (p2 is OdeCharacter && p1.PhysicsActorType == (int)ActorTypes.Prim)
822 {
823 // Testing if the collision is at the feet of the avatar
824
825 //m_log.DebugFormat("[PHYSICS]: {0} - {1} - {2} - {3}", curContact.pos.Z, p2.Position.Z, (p2.Position.Z - curContact.pos.Z), (p2.Size.Z * 0.6f));
826//#@ if ((p2.Position.Z - curContact.pos.Z) > (p2.Size.Z * 0.6f))
827//#@ p2.IsColliding = true;
828 if ((p2.Position.Z - curContact.pos.Z) > (p2.Size.Z * 0.6f)){ //##
829 p2.IsColliding = true; //##
830 }else{
831
832 } //##
833 }
834 else
835 {
836 p2.IsColliding = true;
837 }
838
839 //if ((framecount % m_returncollisions) == 0)
840
841 switch (p1.PhysicsActorType)
842 {
843 case (int)ActorTypes.Agent:
844 p2.CollidingObj = true;
845 break;
846 case (int)ActorTypes.Prim:
847 if (p2.Velocity.LengthSquared() > 0.0f)
848 p2.CollidingObj = true;
849 break;
850 case (int)ActorTypes.Unknown:
851 p2.CollidingGround = true;
852 break;
853 default:
854 p2.CollidingGround = true;
855 break;
856 }
857
858 // we don't want prim or avatar to explode
859
860 #region InterPenetration Handling - Unintended physics explosions
861# region disabled code1
862
863 if (curContact.depth >= 0.08f)
864 {
865 //This is disabled at the moment only because it needs more tweaking
866 //It will eventually be uncommented
867 /*
868 if (AvatarStaticprimContact.depth >= 1.00f)
869 {
870 //m_log.Debug("[PHYSICS]: " + AvatarStaticprimContact.depth.ToString());
871 }
872
873 //If you interpenetrate a prim with an agent
874 if ((p2.PhysicsActorType == (int) ActorTypes.Agent &&
875 p1.PhysicsActorType == (int) ActorTypes.Prim) ||
876 (p1.PhysicsActorType == (int) ActorTypes.Agent &&
877 p2.PhysicsActorType == (int) ActorTypes.Prim))
878 {
879
880 //AvatarStaticprimContact.depth = AvatarStaticprimContact.depth * 4.15f;
881 /*
882 if (p2.PhysicsActorType == (int) ActorTypes.Agent)
883 {
884 p2.CollidingObj = true;
885 AvatarStaticprimContact.depth = 0.003f;
886 p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 2.5f);
887 OdeCharacter character = (OdeCharacter) p2;
888 character.SetPidStatus(true);
889 AvatarStaticprimContact.pos = new d.Vector3(AvatarStaticprimContact.pos.X + (p1.Size.X / 2), AvatarStaticprimContact.pos.Y + (p1.Size.Y / 2), AvatarStaticprimContact.pos.Z + (p1.Size.Z / 2));
890
891 }
892 else
893 {
894
895 //AvatarStaticprimContact.depth = 0.0000000f;
896 }
897 if (p1.PhysicsActorType == (int) ActorTypes.Agent)
898 {
899
900 p1.CollidingObj = true;
901 AvatarStaticprimContact.depth = 0.003f;
902 p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 2.5f);
903 AvatarStaticprimContact.pos = new d.Vector3(AvatarStaticprimContact.pos.X + (p2.Size.X / 2), AvatarStaticprimContact.pos.Y + (p2.Size.Y / 2), AvatarStaticprimContact.pos.Z + (p2.Size.Z / 2));
904 OdeCharacter character = (OdeCharacter)p1;
905 character.SetPidStatus(true);
906 }
907 else
908 {
909
910 //AvatarStaticprimContact.depth = 0.0000000f;
911 }
912
913
914
915 }
916*/
917 // If you interpenetrate a prim with another prim
918 /*
919 if (p1.PhysicsActorType == (int) ActorTypes.Prim && p2.PhysicsActorType == (int) ActorTypes.Prim)
920 {
921 #region disabledcode2
922 //OdePrim op1 = (OdePrim)p1;
923 //OdePrim op2 = (OdePrim)p2;
924 //op1.m_collisionscore++;
925 //op2.m_collisionscore++;
926
927 //if (op1.m_collisionscore > 8000 || op2.m_collisionscore > 8000)
928 //{
929 //op1.m_taintdisable = true;
930 //AddPhysicsActorTaint(p1);
931 //op2.m_taintdisable = true;
932 //AddPhysicsActorTaint(p2);
933 //}
934
935 //if (AvatarStaticprimContact.depth >= 0.25f)
936 //{
937 // Don't collide, one or both prim will expld.
938
939 //op1.m_interpenetrationcount++;
940 //op2.m_interpenetrationcount++;
941 //interpenetrations_before_disable = 200;
942 //if (op1.m_interpenetrationcount >= interpenetrations_before_disable)
943 //{
944 //op1.m_taintdisable = true;
945 //AddPhysicsActorTaint(p1);
946 //}
947 //if (op2.m_interpenetrationcount >= interpenetrations_before_disable)
948 //{
949 // op2.m_taintdisable = true;
950 //AddPhysicsActorTaint(p2);
951 //}
952
953 //AvatarStaticprimContact.depth = AvatarStaticprimContact.depth / 8f;
954 //AvatarStaticprimContact.normal = new d.Vector3(0, 0, 1);
955 //}
956 //if (op1.m_disabled || op2.m_disabled)
957 //{
958 //Manually disabled objects stay disabled
959 //AvatarStaticprimContact.depth = 0f;
960 //}
961 #endregion
962 }
963 */
964#endregion
965 if (curContact.depth >= 1.00f)
966 {
967 //m_log.Info("[P]: " + AvatarStaticprimContact.depth.ToString());
968 if ((p2.PhysicsActorType == (int) ActorTypes.Agent &&
969 p1.PhysicsActorType == (int) ActorTypes.Unknown) ||
970 (p1.PhysicsActorType == (int) ActorTypes.Agent &&
971 p2.PhysicsActorType == (int) ActorTypes.Unknown))
972 {
973 if (p2.PhysicsActorType == (int) ActorTypes.Agent)
974 {
975 if (p2 is OdeCharacter)
976 {
977 OdeCharacter character = (OdeCharacter) p2;
978
979 //p2.CollidingObj = true;
980 curContact.depth = 0.00000003f;
981 p2.Velocity = p2.Velocity + new Vector3(0f, 0f, 0.5f);
982 curContact.pos =
983 new d.Vector3(curContact.pos.X + (p1.Size.X/2),
984 curContact.pos.Y + (p1.Size.Y/2),
985 curContact.pos.Z + (p1.Size.Z/2));
986 character.SetPidStatus(true);
987 }
988 }
989
990
991 if (p1.PhysicsActorType == (int) ActorTypes.Agent)
992 {
993 if (p1 is OdeCharacter)
994 {
995 OdeCharacter character = (OdeCharacter) p1;
996
997 //p2.CollidingObj = true;
998 curContact.depth = 0.00000003f;
999 p1.Velocity = p1.Velocity + new Vector3(0f, 0f, 0.5f);
1000 curContact.pos =
1001 new d.Vector3(curContact.pos.X + (p1.Size.X/2),
1002 curContact.pos.Y + (p1.Size.Y/2),
1003 curContact.pos.Z + (p1.Size.Z/2));
1004 character.SetPidStatus(true);
1005 }
1006 }
1007 }
1008 }
1009 }
1010
1011 #endregion
1012
1013 // Logic for collision handling
1014 // Note, that if *all* contacts are skipped (VolumeDetect)
1015 // The prim still detects (and forwards) collision events but
1016 // appears to be phantom for the world
1017 Boolean skipThisContact = false;
1018
1019 if ((p1 is OdePrim) && (((OdePrim)p1).m_isVolumeDetect))
1020 skipThisContact = true; // No collision on volume detect prims
1021
1022 if (!skipThisContact && (p2 is OdePrim) && (((OdePrim)p2).m_isVolumeDetect))
1023 skipThisContact = true; // No collision on volume detect prims
1024
1025 if (!skipThisContact && curContact.depth < 0f)
1026 skipThisContact = true;
1027
1028 if (!skipThisContact && checkDupe(curContact, p2.PhysicsActorType))
1029 skipThisContact = true;
1030
1031 const int maxContactsbeforedeath = 4000;
1032 joint = IntPtr.Zero;
1033
1034 if (!skipThisContact)
1035 {
1036 // Add contact joints with materials params----------------------------------
1037 // p1 is what is being hit, p2 is the physical object doing the hitting
1038 int material = (int) Material.Wood;
1039 int movintYN = 0; // 1 = Sliding; 0 = static or fell onto
1040 if (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f) movintYN = 1;
1041
1042 // If we're colliding against terrain
1043 if (name1 == "Terrain" || name2 == "Terrain")
1044 {
1045 // If we're moving
1046 if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && (movintYN == 1))
1047 {
1048 //$ Av walk/run on terrain (not falling) Use the Avatar movement terrain contact
1049 AvatarMovementTerrainContact.geom = curContact;
1050 _perloopContact.Add(curContact);
1051 if (m_global_contactcount < maxContactsbeforedeath)
1052 {
1053 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementTerrainContact);
1054 m_global_contactcount++;
1055 }
1056 }
1057 else
1058 {
1059 if (p2.PhysicsActorType == (int)ActorTypes.Agent)
1060 {
1061 //$ Av standing on terrain, Use the non moving Avata terrain contact
1062 TerrainContact.geom = curContact;
1063 _perloopContact.Add(curContact);
1064 if (m_global_contactcount < maxContactsbeforedeath)
1065 {
1066 joint = d.JointCreateContact(world, contactgroup, ref TerrainContact);
1067 m_global_contactcount++;
1068 }
1069 }
1070 else
1071 {
1072 if (p2.PhysicsActorType == (int)ActorTypes.Prim && p1.PhysicsActorType == (int)ActorTypes.Prim)
1073 {
1074 //& THIS NEVER HAPPENS? prim prim contact In terrain contact?
1075 // int pj294950 = 0;
1076 // prim terrain contact
1077
1078 if (p2 is OdePrim)
1079 material = ((OdePrim)p2).m_material;
1080 //m_log.DebugFormat("Material: {0}", material);
1081 m_materialContacts[material, movintYN].geom = curContact;
1082 _perloopContact.Add(curContact);
1083
1084 if (m_global_contactcount < maxContactsbeforedeath)
1085 {
1086 joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, movintYN]);
1087 m_global_contactcount++;
1088
1089 }
1090
1091 }
1092 else
1093 {
1094 //$ prim on terrain contact
1095 if (p2 is OdePrim)
1096 material = ((OdePrim)p2).m_material;
1097 //m_log.DebugFormat("Material: {0}", material);
1098 m_materialContacts[material, movintYN].geom = curContact;
1099 _perloopContact.Add(curContact);
1100
1101 ContactCopy = m_materialContacts[material, movintYN];
1102 if(movintYN == 1)
1103 {
1104 // prevent excessive slide on terrain
1105 ContactCopy.surface.mu = m_materialContacts[material, movintYN].surface.mu * 30.0f;
1106 }
1107
1108 if (m_global_contactcount < maxContactsbeforedeath)
1109 {
1110 joint = d.JointCreateContact(world, contactgroup, ref ContactCopy);
1111 m_global_contactcount++;
1112 }
1113 }
1114 }
1115 }
1116 }
1117 else if (name1 == "Water" || name2 == "Water")
1118 {
1119 //$ This never happens! Perhaps water is treated like air?
1120 /*
1121 if ((p2.PhysicsActorType == (int) ActorTypes.Prim))
1122 {
1123 }
1124 else
1125 {
1126 }
1127 */
1128 //WaterContact.surface.soft_cfm = 0.0000f;
1129 //WaterContact.surface.soft_erp = 0.00000f;
1130 if (curContact.depth > 0.1f)
1131 {
1132 curContact.depth *= 52;
1133 //AvatarStaticprimContact.normal = new d.Vector3(0, 0, 1);
1134 //AvatarStaticprimContact.pos = new d.Vector3(0, 0, contact.pos.Z - 5f);
1135 }
1136 WaterContact.geom = curContact;
1137 _perloopContact.Add(curContact);
1138 if (m_global_contactcount < maxContactsbeforedeath)
1139 {
1140 joint = d.JointCreateContact(world, contactgroup, ref WaterContact);
1141 m_global_contactcount++;
1142 }
1143 //m_log.Info("[PHYSICS]: Prim Water Contact" + AvatarStaticprimContact.depth);
1144 }
1145 else
1146 {
1147
1148 // no terrain and no water, we're colliding with prim or avatar
1149 // check if we're moving
1150 if ((p2.PhysicsActorType == (int)ActorTypes.Agent))
1151 {
1152 //$ Avatar on Prim or other Avatar
1153 if (movintYN == 1)
1154 {
1155 // Use the AV Movement / prim contact
1156 AvatarMovementprimContact.geom = curContact;
1157 _perloopContact.Add(curContact);
1158 if (m_global_contactcount < maxContactsbeforedeath)
1159 {
1160 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementprimContact);
1161 m_global_contactcount++;
1162 }
1163 }
1164 else
1165 {
1166 // Use the Av non movement / prim contact
1167 AvatarStaticprimContact.geom = curContact;
1168 _perloopContact.Add(curContact);
1169 ContactCopy = AvatarStaticprimContact; // local copy so we can change locally
1170
1171 if (m_global_contactcount < maxContactsbeforedeath)
1172 {
1173 if (curContact.depth > 0.2)
1174 { // embedded, eject slowly
1175 ContactCopy.surface.soft_erp = 0.1f;
1176 ContactCopy.surface.soft_cfm = 0.1f;
1177 }
1178 else
1179 { // keep on the surface
1180 ContactCopy.surface.soft_erp = 0.3f;
1181 ContactCopy.surface.soft_cfm = 0.0f;
1182 }
1183 joint = d.JointCreateContact(world, contactgroup, ref ContactCopy);
1184 m_global_contactcount++;
1185 }
1186 }
1187 }
1188 else if (p2.PhysicsActorType == (int)ActorTypes.Prim)
1189 {
1190 //$ Prim on Prim
1191 //p1.PhysicsActorType
1192
1193 if (p2 is OdePrim) material = ((OdePrim)p2).m_material;
1194 //m_log.DebugFormat("Material: {0}", material);
1195
1196 m_materialContacts[material, movintYN].geom = curContact;
1197 _perloopContact.Add(curContact);
1198
1199 if (m_global_contactcount < maxContactsbeforedeath)
1200 {
1201 joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, movintYN]);
1202 m_global_contactcount++;
1203 }
1204 }
1205 }
1206
1207 if (m_global_contactcount < maxContactsbeforedeath && joint != IntPtr.Zero) // stack collide!
1208 {
1209 d.JointAttach(joint, b1, b2);
1210 m_global_contactcount++;
1211 }
1212
1213 }
1214 collision_accounting_events(p1, p2, maxDepthContact);
1215 if (count > geomContactPointsStartthrottle)
1216 {
1217 // If there are more then 3 contact points, it's likely
1218 // that we've got a pile of objects, so ...
1219 // We don't want to send out hundreds of terse updates over and over again
1220 // so lets throttle them and send them again after it's somewhat sorted out.
1221 p2.ThrottleUpdates = true;
1222 }
1223 //m_log.Debug(count.ToString());
1224 //m_log.Debug("near: A collision was detected between {1} and {2}", 0, name1, name2);
1225 } // end for i.. loop
1226 } // end near
1227
1228 private bool checkDupe(d.ContactGeom contactGeom, int atype)
1229 {
1230 bool result = false;
1231 //return result;
1232 if (!m_filterCollisions)
1233 return false;
1234
1235 ActorTypes at = (ActorTypes)atype;
1236 lock (_perloopContact)
1237 {
1238 foreach (d.ContactGeom contact in _perloopContact)
1239 {
1240 //if ((contact.g1 == contactGeom.g1 && contact.g2 == contactGeom.g2))
1241 //{
1242 // || (contact.g2 == contactGeom.g1 && contact.g1 == contactGeom.g2)
1243 if (at == ActorTypes.Agent)
1244 {
1245 if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)) && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom)
1246 {
1247
1248 if (Math.Abs(contact.depth - contactGeom.depth) < 0.052f)
1249 {
1250 //contactGeom.depth *= .00005f;
1251 //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth));
1252 // m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z));
1253 result = true;
1254 break;
1255 }
1256 else
1257 {
1258 //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth));
1259 }
1260 }
1261 else
1262 {
1263 //m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z));
1264 //int i = 0;
1265 }
1266 }
1267 else if (at == ActorTypes.Prim)
1268 {
1269 //d.AABB aabb1 = new d.AABB();
1270 //d.AABB aabb2 = new d.AABB();
1271
1272 //d.GeomGetAABB(contactGeom.g2, out aabb2);
1273 //d.GeomGetAABB(contactGeom.g1, out aabb1);
1274 //aabb1.
1275 if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)) && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom)
1276 {
1277 if (contactGeom.normal.X == contact.normal.X && contactGeom.normal.Y == contact.normal.Y && contactGeom.normal.Z == contact.normal.Z)
1278 {
1279 if (Math.Abs(contact.depth - contactGeom.depth) < 0.272f)
1280 {
1281 result = true;
1282 break;
1283 }
1284 }
1285 //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth));
1286 //m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z));
1287 }
1288
1289 }
1290
1291 //}
1292
1293 }
1294 }
1295 return result;
1296 }
1297
1298 private void collision_accounting_events(PhysicsActor p1, PhysicsActor p2, ContactPoint contact)
1299 {
1300 // obj1LocalID = 0;
1301 //returncollisions = false;
1302 obj2LocalID = 0;
1303 //ctype = 0;
1304 //cStartStop = 0;
1305 if (!p2.SubscribedEvents() && !p1.SubscribedEvents())
1306 return;
1307
1308 switch ((ActorTypes)p2.PhysicsActorType)
1309 {
1310 case ActorTypes.Agent:
1311 cc2 = (OdeCharacter)p2;
1312
1313 // obj1LocalID = cc2.m_localID;
1314 switch ((ActorTypes)p1.PhysicsActorType)
1315 {
1316 case ActorTypes.Agent:
1317 cc1 = (OdeCharacter)p1;
1318 obj2LocalID = cc1.m_localID;
1319 cc1.AddCollisionEvent(cc2.m_localID, contact);
1320 //ctype = (int)CollisionCategories.Character;
1321
1322 //if (cc1.CollidingObj)
1323 //cStartStop = (int)StatusIndicators.Generic;
1324 //else
1325 //cStartStop = (int)StatusIndicators.Start;
1326
1327 //returncollisions = true;
1328 break;
1329 case ActorTypes.Prim:
1330 if (p1 is OdePrim)
1331 {
1332 cp1 = (OdePrim) p1;
1333 obj2LocalID = cp1.m_localID;
1334 cp1.AddCollisionEvent(cc2.m_localID, contact);
1335 }
1336 //ctype = (int)CollisionCategories.Geom;
1337
1338 //if (cp1.CollidingObj)
1339 //cStartStop = (int)StatusIndicators.Generic;
1340 //else
1341 //cStartStop = (int)StatusIndicators.Start;
1342
1343 //returncollisions = true;
1344 break;
1345
1346 case ActorTypes.Ground:
1347 case ActorTypes.Unknown:
1348 obj2LocalID = 0;
1349 //ctype = (int)CollisionCategories.Land;
1350 //returncollisions = true;
1351 break;
1352 }
1353
1354 cc2.AddCollisionEvent(obj2LocalID, contact);
1355 break;
1356 case ActorTypes.Prim:
1357
1358 if (p2 is OdePrim)
1359 {
1360 cp2 = (OdePrim) p2;
1361
1362 // obj1LocalID = cp2.m_localID;
1363 switch ((ActorTypes) p1.PhysicsActorType)
1364 {
1365 case ActorTypes.Agent:
1366 if (p1 is OdeCharacter)
1367 {
1368 cc1 = (OdeCharacter) p1;
1369 obj2LocalID = cc1.m_localID;
1370 cc1.AddCollisionEvent(cp2.m_localID, contact);
1371 //ctype = (int)CollisionCategories.Character;
1372
1373 //if (cc1.CollidingObj)
1374 //cStartStop = (int)StatusIndicators.Generic;
1375 //else
1376 //cStartStop = (int)StatusIndicators.Start;
1377 //returncollisions = true;
1378 }
1379 break;
1380 case ActorTypes.Prim:
1381
1382 if (p1 is OdePrim)
1383 {
1384 cp1 = (OdePrim) p1;
1385 obj2LocalID = cp1.m_localID;
1386 cp1.AddCollisionEvent(cp2.m_localID, contact);
1387 //ctype = (int)CollisionCategories.Geom;
1388
1389 //if (cp1.CollidingObj)
1390 //cStartStop = (int)StatusIndicators.Generic;
1391 //else
1392 //cStartStop = (int)StatusIndicators.Start;
1393
1394 //returncollisions = true;
1395 }
1396 break;
1397
1398 case ActorTypes.Ground:
1399 case ActorTypes.Unknown:
1400 obj2LocalID = 0;
1401 //ctype = (int)CollisionCategories.Land;
1402
1403 //returncollisions = true;
1404 break;
1405 }
1406
1407 cp2.AddCollisionEvent(obj2LocalID, contact);
1408 }
1409 break;
1410 }
1411 //if (returncollisions)
1412 //{
1413
1414 //lock (m_storedCollisions)
1415 //{
1416 //cDictKey = obj1LocalID.ToString() + obj2LocalID.ToString() + cStartStop.ToString() + ctype.ToString();
1417 //if (m_storedCollisions.ContainsKey(cDictKey))
1418 //{
1419 //sCollisionData objd = m_storedCollisions[cDictKey];
1420 //objd.NumberOfCollisions += 1;
1421 //objd.lastframe = framecount;
1422 //m_storedCollisions[cDictKey] = objd;
1423 //}
1424 //else
1425 //{
1426 //sCollisionData objd = new sCollisionData();
1427 //objd.ColliderLocalId = obj1LocalID;
1428 //objd.CollidedWithLocalId = obj2LocalID;
1429 //objd.CollisionType = ctype;
1430 //objd.NumberOfCollisions = 1;
1431 //objd.lastframe = framecount;
1432 //objd.StatusIndicator = cStartStop;
1433 //m_storedCollisions.Add(cDictKey, objd);
1434 //}
1435 //}
1436 // }
1437 }
1438
1439 public int TriArrayCallback(IntPtr trimesh, IntPtr refObject, int[] triangleIndex, int triCount)
1440 {
1441 /* String name1 = null;
1442 String name2 = null;
1443
1444 if (!geom_name_map.TryGetValue(trimesh, out name1))
1445 {
1446 name1 = "null";
1447 }
1448 if (!geom_name_map.TryGetValue(refObject, out name2))
1449 {
1450 name2 = "null";
1451 }
1452
1453 m_log.InfoFormat("TriArrayCallback: A collision was detected between {1} and {2}", 0, name1, name2);
1454 */
1455 return 1;
1456 }
1457
1458 public int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex)
1459 {
1460 String name1 = null;
1461 String name2 = null;
1462
1463 if (!geom_name_map.TryGetValue(trimesh, out name1))
1464 {
1465 name1 = "null";
1466 }
1467
1468 if (!geom_name_map.TryGetValue(refObject, out name2))
1469 {
1470 name2 = "null";
1471 }
1472
1473 // m_log.InfoFormat("TriCallback: A collision was detected between {1} and {2}. Index was {3}", 0, name1, name2, triangleIndex);
1474
1475 d.Vector3 v0 = new d.Vector3();
1476 d.Vector3 v1 = new d.Vector3();
1477 d.Vector3 v2 = new d.Vector3();
1478
1479 d.GeomTriMeshGetTriangle(trimesh, 0, ref v0, ref v1, ref v2);
1480 // m_log.DebugFormat("Triangle {0} is <{1},{2},{3}>, <{4},{5},{6}>, <{7},{8},{9}>", triangleIndex, v0.X, v0.Y, v0.Z, v1.X, v1.Y, v1.Z, v2.X, v2.Y, v2.Z);
1481
1482 return 1;
1483 }
1484
1485 /// <summary>
1486 /// This is our collision testing routine in ODE
1487 /// </summary>
1488 /// <param name="timeStep"></param>
1489 private void collision_optimized(float timeStep)
1490 {
1491 _perloopContact.Clear();
1492
1493 lock (_characters)
1494 {
1495 foreach (OdeCharacter chr in _characters)
1496 {
1497 // Reset the collision values to false
1498 // since we don't know if we're colliding yet
1499
1500 // For some reason this can happen. Don't ask...
1501 //
1502 if (chr == null)
1503 continue;
1504
1505 if (chr.Shell == IntPtr.Zero || chr.Body == IntPtr.Zero)
1506 continue;
1507
1508 chr.IsColliding = false;
1509 chr.CollidingGround = false;
1510 chr.CollidingObj = false;
1511
1512 // test the avatar's geometry for collision with the space
1513 // This will return near and the space that they are the closest to
1514 // And we'll run this again against the avatar and the space segment
1515 // This will return with a bunch of possible objects in the space segment
1516 // and we'll run it again on all of them.
1517 try
1518 {
1519 d.SpaceCollide2(space, chr.Shell, IntPtr.Zero, nearCallback);
1520 }
1521 catch (AccessViolationException)
1522 {
1523 m_log.Warn("[PHYSICS]: Unable to space collide");
1524 }
1525 //float terrainheight = GetTerrainHeightAtXY(chr.Position.X, chr.Position.Y);
1526 //if (chr.Position.Z + (chr.Velocity.Z * timeStep) < terrainheight + 10)
1527 //{
1528 //chr.Position.Z = terrainheight + 10.0f;
1529 //forcedZ = true;
1530 //}
1531 }
1532 }
1533
1534 lock (_activeprims)
1535 {
1536 List<OdePrim> removeprims = null;
1537 foreach (OdePrim chr in _activeprims)
1538 {
1539 if (chr.Body != IntPtr.Zero && d.BodyIsEnabled(chr.Body) && (!chr.m_disabled))
1540 {
1541 try
1542 {
1543 lock (chr)
1544 {
1545 if (space != IntPtr.Zero && chr.prim_geom != IntPtr.Zero && chr.m_taintremove == false)
1546 {
1547 d.SpaceCollide2(space, chr.prim_geom, IntPtr.Zero, nearCallback);
1548 }
1549 else
1550 {
1551 if (removeprims == null)
1552 {
1553 removeprims = new List<OdePrim>();
1554 }
1555 removeprims.Add(chr);
1556 /// Commented this because it triggers on every bullet
1557 //m_log.Debug("[PHYSICS]: unable to collide test active prim against space. The space was zero, the geom was zero or it was in the process of being removed. Removed it from the active prim list. This needs to be fixed!");
1558 }
1559 }
1560 }
1561 catch (AccessViolationException)
1562 {
1563 m_log.Warn("[PHYSICS]: Unable to space collide");
1564 }
1565 }
1566 }
1567 if (removeprims != null)
1568 {
1569 foreach (OdePrim chr in removeprims)
1570 {
1571 _activeprims.Remove(chr);
1572 }
1573 }
1574 }
1575
1576 _perloopContact.Clear();
1577 }
1578
1579 #endregion
1580
1581 public override void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents)
1582 {
1583 m_worldOffset = offset;
1584 WorldExtents = new Vector2(extents.X, extents.Y);
1585 m_parentScene = pScene;
1586
1587 }
1588
1589 // Recovered for use by fly height. Kitto Flora
1590 public float GetTerrainHeightAtXY(float x, float y)
1591 {
1592
1593 int offsetX = ((int)(x / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
1594 int offsetY = ((int)(y / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
1595
1596 IntPtr heightFieldGeom = IntPtr.Zero;
1597
1598 if (RegionTerrain.TryGetValue(new Vector3(offsetX,offsetY,0), out heightFieldGeom))
1599 {
1600 if (heightFieldGeom != IntPtr.Zero)
1601 {
1602 if (TerrainHeightFieldHeights.ContainsKey(heightFieldGeom))
1603 {
1604
1605 int index;
1606
1607
1608 if ((int)x > WorldExtents.X || (int)y > WorldExtents.Y ||
1609 (int)x < 0.001f || (int)y < 0.001f)
1610 return 0;
1611
1612 x = x - offsetX;
1613 y = y - offsetY;
1614
1615 index = (int)((int)x * ((int)Constants.RegionSize + 2) + (int)y);
1616
1617 if (index < TerrainHeightFieldHeights[heightFieldGeom].Length)
1618 {
1619 //m_log.DebugFormat("x{0} y{1} = {2}", x, y, (float)TerrainHeightFieldHeights[heightFieldGeom][index]);
1620 return (float)TerrainHeightFieldHeights[heightFieldGeom][index];
1621 }
1622
1623 else
1624 return 0f;
1625 }
1626 else
1627 {
1628 return 0f;
1629 }
1630
1631 }
1632 else
1633 {
1634 return 0f;
1635 }
1636
1637 }
1638 else
1639 {
1640 return 0f;
1641 }
1642
1643
1644 }
1645// End recovered. Kitto Flora
1646
1647 public void addCollisionEventReporting(PhysicsActor obj)
1648 {
1649 lock (_collisionEventPrim)
1650 {
1651 if (!_collisionEventPrim.Contains(obj))
1652 _collisionEventPrim.Add(obj);
1653 }
1654 }
1655
1656 public void remCollisionEventReporting(PhysicsActor obj)
1657 {
1658 lock (_collisionEventPrim)
1659 {
1660 if (!_collisionEventPrim.Contains(obj))
1661 _collisionEventPrim.Remove(obj);
1662 }
1663 }
1664
1665 #region Add/Remove Entities
1666
1667 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying)
1668 {
1669 Vector3 pos;
1670 pos.X = position.X;
1671 pos.Y = position.Y;
1672 pos.Z = position.Z;
1673 OdeCharacter newAv = new OdeCharacter(avName, this, pos, ode, size, avPIDD, avPIDP, avCapRadius, avStandupTensor, avDensity, avHeightFudgeFactor, avMovementDivisorWalk, avMovementDivisorRun);
1674 newAv.Flying = isFlying;
1675 newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset;
1676
1677 return newAv;
1678 }
1679
1680 public void AddCharacter(OdeCharacter chr)
1681 {
1682 lock (_characters)
1683 {
1684 if (!_characters.Contains(chr))
1685 {
1686 _characters.Add(chr);
1687 if (chr.bad)
1688 m_log.DebugFormat("[PHYSICS] Added BAD actor {0} to characters list", chr.m_uuid);
1689 }
1690 }
1691 }
1692
1693 public void RemoveCharacter(OdeCharacter chr)
1694 {
1695 lock (_characters)
1696 {
1697 if (_characters.Contains(chr))
1698 {
1699 _characters.Remove(chr);
1700 }
1701 }
1702 }
1703 public void BadCharacter(OdeCharacter chr)
1704 {
1705 lock (_badCharacter)
1706 {
1707 if (!_badCharacter.Contains(chr))
1708 _badCharacter.Add(chr);
1709 }
1710 }
1711
1712 public override void RemoveAvatar(PhysicsActor actor)
1713 {
1714 //m_log.Debug("[PHYSICS]:ODELOCK");
1715 ((OdeCharacter) actor).Destroy();
1716
1717 }
1718
1719 private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation,
1720 IMesh mesh, PrimitiveBaseShape pbs, bool isphysical, uint localid)
1721 {
1722
1723 Vector3 pos = position;
1724 Vector3 siz = size;
1725 Quaternion rot = rotation;
1726
1727 OdePrim newPrim;
1728 lock (OdeLock)
1729 {
1730 newPrim = new OdePrim(name, this, pos, siz, rot, mesh, pbs, isphysical, ode, localid);
1731
1732 lock (_prims)
1733 _prims.Add(newPrim);
1734 }
1735
1736 return newPrim;
1737 }
1738
1739 public void addActivePrim(OdePrim activatePrim)
1740 {
1741 // adds active prim.. (ones that should be iterated over in collisions_optimized
1742 lock (_activeprims)
1743 {
1744 if (!_activeprims.Contains(activatePrim))
1745 _activeprims.Add(activatePrim);
1746 //else
1747 // m_log.Warn("[PHYSICS]: Double Entry in _activeprims detected, potential crash immenent");
1748 }
1749 }
1750
1751 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
1752 Vector3 size, Quaternion rotation, bool isPhysical, uint localid)
1753 {
1754 PhysicsActor result;
1755 IMesh mesh = null;
1756
1757 if (needsMeshing(pbs))
1758 mesh = mesher.CreateMesh(primName, pbs, size, 32f, isPhysical);
1759
1760 result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical, localid);
1761
1762 return result;
1763 }
1764
1765 public override float TimeDilation
1766 {
1767 get { return m_timeDilation; }
1768 }
1769
1770 public override bool SupportsNINJAJoints
1771 {
1772 get { return m_NINJA_physics_joints_enabled; }
1773 }
1774
1775 // internal utility function: must be called within a lock (OdeLock)
1776 private void InternalAddActiveJoint(PhysicsJoint joint)
1777 {
1778 activeJoints.Add(joint);
1779 SOPName_to_activeJoint.Add(joint.ObjectNameInScene, joint);
1780 }
1781
1782 // internal utility function: must be called within a lock (OdeLock)
1783 private void InternalAddPendingJoint(OdePhysicsJoint joint)
1784 {
1785 pendingJoints.Add(joint);
1786 SOPName_to_pendingJoint.Add(joint.ObjectNameInScene, joint);
1787 }
1788
1789 // internal utility function: must be called within a lock (OdeLock)
1790 private void InternalRemovePendingJoint(PhysicsJoint joint)
1791 {
1792 pendingJoints.Remove(joint);
1793 SOPName_to_pendingJoint.Remove(joint.ObjectNameInScene);
1794 }
1795
1796 // internal utility function: must be called within a lock (OdeLock)
1797 private void InternalRemoveActiveJoint(PhysicsJoint joint)
1798 {
1799 activeJoints.Remove(joint);
1800 SOPName_to_activeJoint.Remove(joint.ObjectNameInScene);
1801 }
1802
1803 public override void DumpJointInfo()
1804 {
1805 string hdr = "[NINJA] JOINTINFO: ";
1806 foreach (PhysicsJoint j in pendingJoints)
1807 {
1808 m_log.Debug(hdr + " pending joint, Name: " + j.ObjectNameInScene + " raw parms:" + j.RawParams);
1809 }
1810 m_log.Debug(hdr + pendingJoints.Count + " total pending joints");
1811 foreach (string jointName in SOPName_to_pendingJoint.Keys)
1812 {
1813 m_log.Debug(hdr + " pending joints dict contains Name: " + jointName);
1814 }
1815 m_log.Debug(hdr + SOPName_to_pendingJoint.Keys.Count + " total pending joints dict entries");
1816 foreach (PhysicsJoint j in activeJoints)
1817 {
1818 m_log.Debug(hdr + " active joint, Name: " + j.ObjectNameInScene + " raw parms:" + j.RawParams);
1819 }
1820 m_log.Debug(hdr + activeJoints.Count + " total active joints");
1821 foreach (string jointName in SOPName_to_activeJoint.Keys)
1822 {
1823 m_log.Debug(hdr + " active joints dict contains Name: " + jointName);
1824 }
1825 m_log.Debug(hdr + SOPName_to_activeJoint.Keys.Count + " total active joints dict entries");
1826
1827 m_log.Debug(hdr + " Per-body joint connectivity information follows.");
1828 m_log.Debug(hdr + joints_connecting_actor.Keys.Count + " bodies are connected by joints.");
1829 foreach (string actorName in joints_connecting_actor.Keys)
1830 {
1831 m_log.Debug(hdr + " Actor " + actorName + " has the following joints connecting it");
1832 foreach (PhysicsJoint j in joints_connecting_actor[actorName])
1833 {
1834 m_log.Debug(hdr + " * joint Name: " + j.ObjectNameInScene + " raw parms:" + j.RawParams);
1835 }
1836 m_log.Debug(hdr + joints_connecting_actor[actorName].Count + " connecting joints total for this actor");
1837 }
1838 }
1839
1840 public override void RequestJointDeletion(string ObjectNameInScene)
1841 {
1842 lock (externalJointRequestsLock)
1843 {
1844 if (!requestedJointsToBeDeleted.Contains(ObjectNameInScene)) // forbid same deletion request from entering twice to prevent spurious deletions processed asynchronously
1845 {
1846 requestedJointsToBeDeleted.Add(ObjectNameInScene);
1847 }
1848 }
1849 }
1850
1851 private void DeleteRequestedJoints()
1852 {
1853 List<string> myRequestedJointsToBeDeleted;
1854 lock (externalJointRequestsLock)
1855 {
1856 // make a local copy of the shared list for processing (threading issues)
1857 myRequestedJointsToBeDeleted = new List<string>(requestedJointsToBeDeleted);
1858 }
1859
1860 foreach (string jointName in myRequestedJointsToBeDeleted)
1861 {
1862 lock (OdeLock)
1863 {
1864 //m_log.Debug("[NINJA] trying to deleting requested joint " + jointName);
1865 if (SOPName_to_activeJoint.ContainsKey(jointName) || SOPName_to_pendingJoint.ContainsKey(jointName))
1866 {
1867 OdePhysicsJoint joint = null;
1868 if (SOPName_to_activeJoint.ContainsKey(jointName))
1869 {
1870 joint = SOPName_to_activeJoint[jointName] as OdePhysicsJoint;
1871 InternalRemoveActiveJoint(joint);
1872 }
1873 else if (SOPName_to_pendingJoint.ContainsKey(jointName))
1874 {
1875 joint = SOPName_to_pendingJoint[jointName] as OdePhysicsJoint;
1876 InternalRemovePendingJoint(joint);
1877 }
1878
1879 if (joint != null)
1880 {
1881 //m_log.Debug("joint.BodyNames.Count is " + joint.BodyNames.Count + " and contents " + joint.BodyNames);
1882 for (int iBodyName = 0; iBodyName < 2; iBodyName++)
1883 {
1884 string bodyName = joint.BodyNames[iBodyName];
1885 if (bodyName != "NULL")
1886 {
1887 joints_connecting_actor[bodyName].Remove(joint);
1888 if (joints_connecting_actor[bodyName].Count == 0)
1889 {
1890 joints_connecting_actor.Remove(bodyName);
1891 }
1892 }
1893 }
1894
1895 DoJointDeactivated(joint);
1896 if (joint.jointID != IntPtr.Zero)
1897 {
1898 d.JointDestroy(joint.jointID);
1899 joint.jointID = IntPtr.Zero;
1900 //DoJointErrorMessage(joint, "successfully destroyed joint " + jointName);
1901 }
1902 else
1903 {
1904 //m_log.Warn("[NINJA] Ignoring re-request to destroy joint " + jointName);
1905 }
1906 }
1907 else
1908 {
1909 // DoJointErrorMessage(joint, "coult not find joint to destroy based on name " + jointName);
1910 }
1911 }
1912 else
1913 {
1914 // DoJointErrorMessage(joint, "WARNING - joint removal failed, joint " + jointName);
1915 }
1916 }
1917 }
1918
1919 // remove processed joints from the shared list
1920 lock (externalJointRequestsLock)
1921 {
1922 foreach (string jointName in myRequestedJointsToBeDeleted)
1923 {
1924 requestedJointsToBeDeleted.Remove(jointName);
1925 }
1926 }
1927 }
1928
1929 // for pending joints we don't know if their associated bodies exist yet or not.
1930 // the joint is actually created during processing of the taints
1931 private void CreateRequestedJoints()
1932 {
1933 List<PhysicsJoint> myRequestedJointsToBeCreated;
1934 lock (externalJointRequestsLock)
1935 {
1936 // make a local copy of the shared list for processing (threading issues)
1937 myRequestedJointsToBeCreated = new List<PhysicsJoint>(requestedJointsToBeCreated);
1938 }
1939
1940 foreach (PhysicsJoint joint in myRequestedJointsToBeCreated)
1941 {
1942 lock (OdeLock)
1943 {
1944 if (SOPName_to_pendingJoint.ContainsKey(joint.ObjectNameInScene) && SOPName_to_pendingJoint[joint.ObjectNameInScene] != null)
1945 {
1946 DoJointErrorMessage(joint, "WARNING: ignoring request to re-add already pending joint Name:" + joint.ObjectNameInScene + " type:" + joint.Type + " parms: " + joint.RawParams + " pos: " + joint.Position + " rot:" + joint.Rotation);
1947 continue;
1948 }
1949 if (SOPName_to_activeJoint.ContainsKey(joint.ObjectNameInScene) && SOPName_to_activeJoint[joint.ObjectNameInScene] != null)
1950 {
1951 DoJointErrorMessage(joint, "WARNING: ignoring request to re-add already active joint Name:" + joint.ObjectNameInScene + " type:" + joint.Type + " parms: " + joint.RawParams + " pos: " + joint.Position + " rot:" + joint.Rotation);
1952 continue;
1953 }
1954
1955 InternalAddPendingJoint(joint as OdePhysicsJoint);
1956
1957 if (joint.BodyNames.Count >= 2)
1958 {
1959 for (int iBodyName = 0; iBodyName < 2; iBodyName++)
1960 {
1961 string bodyName = joint.BodyNames[iBodyName];
1962 if (bodyName != "NULL")
1963 {
1964 if (!joints_connecting_actor.ContainsKey(bodyName))
1965 {
1966 joints_connecting_actor.Add(bodyName, new List<PhysicsJoint>());
1967 }
1968 joints_connecting_actor[bodyName].Add(joint);
1969 }
1970 }
1971 }
1972 }
1973 }
1974
1975 // remove processed joints from shared list
1976 lock (externalJointRequestsLock)
1977 {
1978 foreach (PhysicsJoint joint in myRequestedJointsToBeCreated)
1979 {
1980 requestedJointsToBeCreated.Remove(joint);
1981 }
1982 }
1983
1984 }
1985
1986 // public function to add an request for joint creation
1987 // this joint will just be added to a waiting list that is NOT processed during the main
1988 // Simulate() loop (to avoid deadlocks). After Simulate() is finished, we handle unprocessed joint requests.
1989
1990 public override PhysicsJoint RequestJointCreation(string objectNameInScene, PhysicsJointType jointType, Vector3 position,
1991 Quaternion rotation, string parms, List<string> bodyNames, string trackedBodyName, Quaternion localRotation)
1992
1993 {
1994
1995 OdePhysicsJoint joint = new OdePhysicsJoint();
1996 joint.ObjectNameInScene = objectNameInScene;
1997 joint.Type = jointType;
1998 joint.Position = position;
1999 joint.Rotation = rotation;
2000 joint.RawParams = parms;
2001 joint.BodyNames = new List<string>(bodyNames);
2002 joint.TrackedBodyName = trackedBodyName;
2003 joint.LocalRotation = localRotation;
2004 joint.jointID = IntPtr.Zero;
2005 joint.ErrorMessageCount = 0;
2006
2007 lock (externalJointRequestsLock)
2008 {
2009 if (!requestedJointsToBeCreated.Contains(joint)) // forbid same creation request from entering twice
2010 {
2011 requestedJointsToBeCreated.Add(joint);
2012 }
2013 }
2014 return joint;
2015 }
2016
2017 private void RemoveAllJointsConnectedToActor(PhysicsActor actor)
2018 {
2019 //m_log.Debug("RemoveAllJointsConnectedToActor: start");
2020 if (actor.SOPName != null && joints_connecting_actor.ContainsKey(actor.SOPName) && joints_connecting_actor[actor.SOPName] != null)
2021 {
2022
2023 List<PhysicsJoint> jointsToRemove = new List<PhysicsJoint>();
2024 //TODO: merge these 2 loops (originally it was needed to avoid altering a list being iterated over, but it is no longer needed due to the joint request queue mechanism)
2025 foreach (PhysicsJoint j in joints_connecting_actor[actor.SOPName])
2026 {
2027 jointsToRemove.Add(j);
2028 }
2029 foreach (PhysicsJoint j in jointsToRemove)
2030 {
2031 //m_log.Debug("RemoveAllJointsConnectedToActor: about to request deletion of " + j.ObjectNameInScene);
2032 RequestJointDeletion(j.ObjectNameInScene);
2033 //m_log.Debug("RemoveAllJointsConnectedToActor: done request deletion of " + j.ObjectNameInScene);
2034 j.TrackedBodyName = null; // *IMMEDIATELY* prevent any further movement of this joint (else a deleted actor might cause spurious tracking motion of the joint for a few frames, leading to the joint proxy object disappearing)
2035 }
2036 }
2037 }
2038
2039 public override void RemoveAllJointsConnectedToActorThreadLocked(PhysicsActor actor)
2040 {
2041 //m_log.Debug("RemoveAllJointsConnectedToActorThreadLocked: start");
2042 lock (OdeLock)
2043 {
2044 //m_log.Debug("RemoveAllJointsConnectedToActorThreadLocked: got lock");
2045 RemoveAllJointsConnectedToActor(actor);
2046 }
2047 }
2048
2049 // normally called from within OnJointMoved, which is called from within a lock (OdeLock)
2050 public override Vector3 GetJointAnchor(PhysicsJoint joint)
2051 {
2052 Debug.Assert(joint.IsInPhysicsEngine);
2053 d.Vector3 pos = new d.Vector3();
2054
2055 if (!(joint is OdePhysicsJoint))
2056 {
2057 DoJointErrorMessage(joint, "warning: non-ODE joint requesting anchor: " + joint.ObjectNameInScene);
2058 }
2059 else
2060 {
2061 OdePhysicsJoint odeJoint = (OdePhysicsJoint)joint;
2062 switch (odeJoint.Type)
2063 {
2064 case PhysicsJointType.Ball:
2065 d.JointGetBallAnchor(odeJoint.jointID, out pos);
2066 break;
2067 case PhysicsJointType.Hinge:
2068 d.JointGetHingeAnchor(odeJoint.jointID, out pos);
2069 break;
2070 }
2071 }
2072 return new Vector3(pos.X, pos.Y, pos.Z);
2073 }
2074
2075 // normally called from within OnJointMoved, which is called from within a lock (OdeLock)
2076 // WARNING: ODE sometimes returns <0,0,0> as the joint axis! Therefore this function
2077 // appears to be unreliable. Fortunately we can compute the joint axis ourselves by
2078 // keeping track of the joint's original orientation relative to one of the involved bodies.
2079 public override Vector3 GetJointAxis(PhysicsJoint joint)
2080 {
2081 Debug.Assert(joint.IsInPhysicsEngine);
2082 d.Vector3 axis = new d.Vector3();
2083
2084 if (!(joint is OdePhysicsJoint))
2085 {
2086 DoJointErrorMessage(joint, "warning: non-ODE joint requesting anchor: " + joint.ObjectNameInScene);
2087 }
2088 else
2089 {
2090 OdePhysicsJoint odeJoint = (OdePhysicsJoint)joint;
2091 switch (odeJoint.Type)
2092 {
2093 case PhysicsJointType.Ball:
2094 DoJointErrorMessage(joint, "warning - axis requested for ball joint: " + joint.ObjectNameInScene);
2095 break;
2096 case PhysicsJointType.Hinge:
2097 d.JointGetHingeAxis(odeJoint.jointID, out axis);
2098 break;
2099 }
2100 }
2101 return new Vector3(axis.X, axis.Y, axis.Z);
2102 }
2103
2104
2105 public void remActivePrim(OdePrim deactivatePrim)
2106 {
2107 lock (_activeprims)
2108 {
2109 _activeprims.Remove(deactivatePrim);
2110 }
2111 }
2112
2113 public override void RemovePrim(PhysicsActor prim)
2114 {
2115 if (prim is OdePrim)
2116 {
2117 lock (OdeLock)
2118 {
2119 OdePrim p = (OdePrim) prim;
2120
2121 p.setPrimForRemoval();
2122 AddPhysicsActorTaint(prim);
2123 //RemovePrimThreadLocked(p);
2124 }
2125 }
2126 }
2127
2128 /// <summary>
2129 /// This is called from within simulate but outside the locked portion
2130 /// We need to do our own locking here
2131 /// Essentially, we need to remove the prim from our space segment, whatever segment it's in.
2132 ///
2133 /// If there are no more prim in the segment, we need to empty (spacedestroy)the segment and reclaim memory
2134 /// that the space was using.
2135 /// </summary>
2136 /// <param name="prim"></param>
2137 public void RemovePrimThreadLocked(OdePrim prim)
2138 {
2139//Console.WriteLine("RemovePrimThreadLocked " + prim.m_primName);
2140 lock (prim)
2141 {
2142 remCollisionEventReporting(prim);
2143 lock (ode)
2144 {
2145 if (prim.prim_geom != IntPtr.Zero)
2146 {
2147 prim.ResetTaints();
2148
2149 if (prim.IsPhysical)
2150 {
2151 prim.disableBody();
2152 if (prim.childPrim)
2153 {
2154 prim.childPrim = false;
2155 prim.Body = IntPtr.Zero;
2156 prim.m_disabled = true;
2157 prim.IsPhysical = false;
2158 }
2159
2160
2161 }
2162 // we don't want to remove the main space
2163
2164 // If the geometry is in the targetspace, remove it from the target space
2165 //m_log.Warn(prim.m_targetSpace);
2166
2167 //if (prim.m_targetSpace != IntPtr.Zero)
2168 //{
2169 //if (d.SpaceQuery(prim.m_targetSpace, prim.prim_geom))
2170 //{
2171
2172 //if (d.GeomIsSpace(prim.m_targetSpace))
2173 //{
2174 //waitForSpaceUnlock(prim.m_targetSpace);
2175 //d.SpaceRemove(prim.m_targetSpace, prim.prim_geom);
2176 prim.m_targetSpace = IntPtr.Zero;
2177 //}
2178 //else
2179 //{
2180 // m_log.Info("[Physics]: Invalid Scene passed to 'removeprim from scene':" +
2181 //((OdePrim)prim).m_targetSpace.ToString());
2182 //}
2183
2184 //}
2185 //}
2186 //m_log.Warn(prim.prim_geom);
2187 try
2188 {
2189 if (prim.prim_geom != IntPtr.Zero)
2190 {
2191
2192//string tPA;
2193//geom_name_map.TryGetValue(prim.prim_geom, out tPA);
2194//Console.WriteLine("**** Remove {0}", tPA);
2195 if(geom_name_map.ContainsKey(prim.prim_geom)) geom_name_map.Remove(prim.prim_geom);
2196 if(actor_name_map.ContainsKey(prim.prim_geom)) actor_name_map.Remove(prim.prim_geom);
2197 d.GeomDestroy(prim.prim_geom);
2198 prim.prim_geom = IntPtr.Zero;
2199 }
2200 else
2201 {
2202 m_log.Warn("[PHYSICS]: Unable to remove prim from physics scene");
2203 }
2204 }
2205 catch (AccessViolationException)
2206 {
2207 m_log.Info("[PHYSICS]: Couldn't remove prim from physics scene, it was already be removed.");
2208 }
2209 lock (_prims)
2210 _prims.Remove(prim);
2211
2212 //If there are no more geometries in the sub-space, we don't need it in the main space anymore
2213 //if (d.SpaceGetNumGeoms(prim.m_targetSpace) == 0)
2214 //{
2215 //if (prim.m_targetSpace != null)
2216 //{
2217 //if (d.GeomIsSpace(prim.m_targetSpace))
2218 //{
2219 //waitForSpaceUnlock(prim.m_targetSpace);
2220 //d.SpaceRemove(space, prim.m_targetSpace);
2221 // free up memory used by the space.
2222 //d.SpaceDestroy(prim.m_targetSpace);
2223 //int[] xyspace = calculateSpaceArrayItemFromPos(prim.Position);
2224 //resetSpaceArrayItemToZero(xyspace[0], xyspace[1]);
2225 //}
2226 //else
2227 //{
2228 //m_log.Info("[Physics]: Invalid Scene passed to 'removeprim from scene':" +
2229 //((OdePrim) prim).m_targetSpace.ToString());
2230 //}
2231 //}
2232 //}
2233
2234 if (SupportsNINJAJoints)
2235 {
2236 RemoveAllJointsConnectedToActorThreadLocked(prim);
2237 }
2238 }
2239 }
2240 }
2241 }
2242
2243 #endregion
2244
2245 #region Space Separation Calculation
2246
2247 /// <summary>
2248 /// Takes a space pointer and zeros out the array we're using to hold the spaces
2249 /// </summary>
2250 /// <param name="pSpace"></param>
2251 public void resetSpaceArrayItemToZero(IntPtr pSpace)
2252 {
2253 for (int x = 0; x < staticPrimspace.GetLength(0); x++)
2254 {
2255 for (int y = 0; y < staticPrimspace.GetLength(1); y++)
2256 {
2257 if (staticPrimspace[x, y] == pSpace)
2258 staticPrimspace[x, y] = IntPtr.Zero;
2259 }
2260 }
2261 }
2262
2263 public void resetSpaceArrayItemToZero(int arrayitemX, int arrayitemY)
2264 {
2265 staticPrimspace[arrayitemX, arrayitemY] = IntPtr.Zero;
2266 }
2267
2268 /// <summary>
2269 /// Called when a static prim moves. Allocates a space for the prim based on its position
2270 /// </summary>
2271 /// <param name="geom">the pointer to the geom that moved</param>
2272 /// <param name="pos">the position that the geom moved to</param>
2273 /// <param name="currentspace">a pointer to the space it was in before it was moved.</param>
2274 /// <returns>a pointer to the new space it's in</returns>
2275 public IntPtr recalculateSpaceForGeom(IntPtr geom, Vector3 pos, IntPtr currentspace)
2276 {
2277 // Called from setting the Position and Size of an ODEPrim so
2278 // it's already in locked space.
2279
2280 // we don't want to remove the main space
2281 // we don't need to test physical here because this function should
2282 // never be called if the prim is physical(active)
2283
2284 // All physical prim end up in the root space
2285 //Thread.Sleep(20);
2286 if (currentspace != space)
2287 {
2288 //m_log.Info("[SPACE]: C:" + currentspace.ToString() + " g:" + geom.ToString());
2289 //if (currentspace == IntPtr.Zero)
2290 //{
2291 //int adfadf = 0;
2292 //}
2293 if (d.SpaceQuery(currentspace, geom) && currentspace != IntPtr.Zero)
2294 {
2295 if (d.GeomIsSpace(currentspace))
2296 {
2297 waitForSpaceUnlock(currentspace);
2298 d.SpaceRemove(currentspace, geom);
2299 }
2300 else
2301 {
2302 m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + currentspace +
2303 " Geom:" + geom);
2304 }
2305 }
2306 else
2307 {
2308 IntPtr sGeomIsIn = d.GeomGetSpace(geom);
2309 if (sGeomIsIn != IntPtr.Zero)
2310 {
2311 if (d.GeomIsSpace(currentspace))
2312 {
2313 waitForSpaceUnlock(sGeomIsIn);
2314 d.SpaceRemove(sGeomIsIn, geom);
2315 }
2316 else
2317 {
2318 m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" +
2319 sGeomIsIn + " Geom:" + geom);
2320 }
2321 }
2322 }
2323
2324 //If there are no more geometries in the sub-space, we don't need it in the main space anymore
2325 if (d.SpaceGetNumGeoms(currentspace) == 0)
2326 {
2327 if (currentspace != IntPtr.Zero)
2328 {
2329 if (d.GeomIsSpace(currentspace))
2330 {
2331 waitForSpaceUnlock(currentspace);
2332 waitForSpaceUnlock(space);
2333 d.SpaceRemove(space, currentspace);
2334 // free up memory used by the space.
2335
2336 //d.SpaceDestroy(currentspace);
2337 resetSpaceArrayItemToZero(currentspace);
2338 }
2339 else
2340 {
2341 m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" +
2342 currentspace + " Geom:" + geom);
2343 }
2344 }
2345 }
2346 }
2347 else
2348 {
2349 // this is a physical object that got disabled. ;.;
2350 if (currentspace != IntPtr.Zero && geom != IntPtr.Zero)
2351 {
2352 if (d.SpaceQuery(currentspace, geom))
2353 {
2354 if (d.GeomIsSpace(currentspace))
2355 {
2356 waitForSpaceUnlock(currentspace);
2357 d.SpaceRemove(currentspace, geom);
2358 }
2359 else
2360 {
2361 m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" +
2362 currentspace + " Geom:" + geom);
2363 }
2364 }
2365 else
2366 {
2367 IntPtr sGeomIsIn = d.GeomGetSpace(geom);
2368 if (sGeomIsIn != IntPtr.Zero)
2369 {
2370 if (d.GeomIsSpace(sGeomIsIn))
2371 {
2372 waitForSpaceUnlock(sGeomIsIn);
2373 d.SpaceRemove(sGeomIsIn, geom);
2374 }
2375 else
2376 {
2377 m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" +
2378 sGeomIsIn + " Geom:" + geom);
2379 }
2380 }
2381 }
2382 }
2383 }
2384
2385 // The routines in the Position and Size sections do the 'inserting' into the space,
2386 // so all we have to do is make sure that the space that we're putting the prim into
2387 // is in the 'main' space.
2388 int[] iprimspaceArrItem = calculateSpaceArrayItemFromPos(pos);
2389 IntPtr newspace = calculateSpaceForGeom(pos);
2390
2391 if (newspace == IntPtr.Zero)
2392 {
2393 newspace = createprimspace(iprimspaceArrItem[0], iprimspaceArrItem[1]);
2394 d.HashSpaceSetLevels(newspace, smallHashspaceLow, smallHashspaceHigh);
2395 }
2396
2397 return newspace;
2398 }
2399
2400 /// <summary>
2401 /// Creates a new space at X Y
2402 /// </summary>
2403 /// <param name="iprimspaceArrItemX"></param>
2404 /// <param name="iprimspaceArrItemY"></param>
2405 /// <returns>A pointer to the created space</returns>
2406 public IntPtr createprimspace(int iprimspaceArrItemX, int iprimspaceArrItemY)
2407 {
2408 // creating a new space for prim and inserting it into main space.
2409 staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY] = d.HashSpaceCreate(IntPtr.Zero);
2410 d.GeomSetCategoryBits(staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY], (int)CollisionCategories.Space);
2411 waitForSpaceUnlock(space);
2412 d.SpaceSetSublevel(space, 1);
2413 d.SpaceAdd(space, staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY]);
2414 return staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY];
2415 }
2416
2417 /// <summary>
2418 /// Calculates the space the prim should be in by its position
2419 /// </summary>
2420 /// <param name="pos"></param>
2421 /// <returns>a pointer to the space. This could be a new space or reused space.</returns>
2422 public IntPtr calculateSpaceForGeom(Vector3 pos)
2423 {
2424 int[] xyspace = calculateSpaceArrayItemFromPos(pos);
2425 //m_log.Info("[Physics]: Attempting to use arrayItem: " + xyspace[0].ToString() + "," + xyspace[1].ToString());
2426 return staticPrimspace[xyspace[0], xyspace[1]];
2427 }
2428
2429 /// <summary>
2430 /// Holds the space allocation logic
2431 /// </summary>
2432 /// <param name="pos"></param>
2433 /// <returns>an array item based on the position</returns>
2434 public int[] calculateSpaceArrayItemFromPos(Vector3 pos)
2435 {
2436 int[] returnint = new int[2];
2437
2438 returnint[0] = (int) (pos.X/metersInSpace);
2439
2440 if (returnint[0] > ((int) (259f/metersInSpace)))
2441 returnint[0] = ((int) (259f/metersInSpace));
2442 if (returnint[0] < 0)
2443 returnint[0] = 0;
2444
2445 returnint[1] = (int) (pos.Y/metersInSpace);
2446 if (returnint[1] > ((int) (259f/metersInSpace)))
2447 returnint[1] = ((int) (259f/metersInSpace));
2448 if (returnint[1] < 0)
2449 returnint[1] = 0;
2450
2451 return returnint;
2452 }
2453
2454 #endregion
2455
2456 /// <summary>
2457 /// Routine to figure out if we need to mesh this prim with our mesher
2458 /// </summary>
2459 /// <param name="pbs"></param>
2460 /// <returns></returns>
2461 public bool needsMeshing(PrimitiveBaseShape pbs)
2462 {
2463 // most of this is redundant now as the mesher will return null if it cant mesh a prim
2464 // but we still need to check for sculptie meshing being enabled so this is the most
2465 // convenient place to do it for now...
2466
2467 // //if (pbs.PathCurve == (byte)Primitive.PathCurve.Circle && pbs.ProfileCurve == (byte)Primitive.ProfileCurve.Circle && pbs.PathScaleY <= 0.75f)
2468 // //m_log.Debug("needsMeshing: " + " pathCurve: " + pbs.PathCurve.ToString() + " profileCurve: " + pbs.ProfileCurve.ToString() + " pathScaleY: " + Primitive.UnpackPathScale(pbs.PathScaleY).ToString());
2469 int iPropertiesNotSupportedDefault = 0;
2470
2471 if (pbs.SculptEntry && !meshSculptedPrim)
2472 {
2473#if SPAM
2474 m_log.Warn("NonMesh");
2475#endif
2476 return false;
2477 }
2478
2479 // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since ODE can use an internal representation for the prim
2480 if (!forceSimplePrimMeshing)
2481 {
2482 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
2483 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
2484 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
2485 {
2486
2487 if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
2488 && pbs.ProfileHollow == 0
2489 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
2490 && pbs.PathBegin == 0 && pbs.PathEnd == 0
2491 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
2492 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
2493 && pbs.PathShearX == 0 && pbs.PathShearY == 0)
2494 {
2495#if SPAM
2496 m_log.Warn("NonMesh");
2497#endif
2498 return false;
2499 }
2500 }
2501 }
2502
2503 if (pbs.ProfileHollow != 0)
2504 iPropertiesNotSupportedDefault++;
2505
2506 if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
2507 iPropertiesNotSupportedDefault++;
2508
2509 if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
2510 iPropertiesNotSupportedDefault++;
2511
2512 if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
2513 iPropertiesNotSupportedDefault++;
2514
2515 if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
2516 iPropertiesNotSupportedDefault++;
2517
2518 if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
2519 iPropertiesNotSupportedDefault++;
2520
2521 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 && (pbs.Scale.X != pbs.Scale.Y || pbs.Scale.Y != pbs.Scale.Z || pbs.Scale.Z != pbs.Scale.X))
2522 iPropertiesNotSupportedDefault++;
2523
2524 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte) Extrusion.Curve1)
2525 iPropertiesNotSupportedDefault++;
2526
2527 // test for torus
2528 if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
2529 {
2530 if (pbs.PathCurve == (byte)Extrusion.Curve1)
2531 {
2532 iPropertiesNotSupportedDefault++;
2533 }
2534 }
2535 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
2536 {
2537 if (pbs.PathCurve == (byte)Extrusion.Straight)
2538 {
2539 iPropertiesNotSupportedDefault++;
2540 }
2541
2542 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
2543 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
2544 {
2545 iPropertiesNotSupportedDefault++;
2546 }
2547 }
2548 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
2549 {
2550 if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
2551 {
2552 iPropertiesNotSupportedDefault++;
2553 }
2554 }
2555 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
2556 {
2557 if (pbs.PathCurve == (byte)Extrusion.Straight)
2558 {
2559 iPropertiesNotSupportedDefault++;
2560 }
2561 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
2562 {
2563 iPropertiesNotSupportedDefault++;
2564 }
2565 }
2566
2567
2568 if (iPropertiesNotSupportedDefault == 0)
2569 {
2570#if SPAM
2571 m_log.Warn("NonMesh");
2572#endif
2573 return false;
2574 }
2575#if SPAM
2576 m_log.Debug("Mesh");
2577#endif
2578 return true;
2579 }
2580
2581 /// <summary>
2582 /// Called after our prim properties are set Scale, position etc.
2583 /// We use this event queue like method to keep changes to the physical scene occuring in the threadlocked mutex
2584 /// This assures us that we have no race conditions
2585 /// </summary>
2586 /// <param name="prim"></param>
2587 public override void AddPhysicsActorTaint(PhysicsActor prim)
2588 {
2589
2590 if (prim is OdePrim)
2591 {
2592 OdePrim taintedprim = ((OdePrim) prim);
2593 lock (_taintedPrimLock)
2594 {
2595 if (!(_taintedPrimH.Contains(taintedprim)))
2596 {
2597//Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.m_primName);
2598 _taintedPrimH.Add(taintedprim); // HashSet for searching
2599 _taintedPrimL.Add(taintedprim); // List for ordered readout
2600 }
2601 }
2602 return;
2603 }
2604 else if (prim is OdeCharacter)
2605 {
2606 OdeCharacter taintedchar = ((OdeCharacter)prim);
2607 lock (_taintedActors)
2608 {
2609 if (!(_taintedActors.Contains(taintedchar)))
2610 {
2611 _taintedActors.Add(taintedchar);
2612 if (taintedchar.bad)
2613 m_log.DebugFormat("[PHYSICS]: Added BAD actor {0} to tainted actors", taintedchar.m_uuid);
2614 }
2615 }
2616 }
2617 }
2618
2619 /// <summary>
2620 /// This is our main simulate loop
2621 /// It's thread locked by a Mutex in the scene.
2622 /// It holds Collisions, it instructs ODE to step through the physical reactions
2623 /// It moves the objects around in memory
2624 /// It calls the methods that report back to the object owners.. (scenepresence, SceneObjectGroup)
2625 /// </summary>
2626 /// <param name="timeStep"></param>
2627 /// <returns></returns>
2628 public override float Simulate(float timeStep)
2629 {
2630 if (framecount >= int.MaxValue)
2631 framecount = 0;
2632 //if (m_worldOffset != Vector3.Zero)
2633 // return 0;
2634
2635 framecount++;
2636
2637 DateTime now = DateTime.UtcNow;
2638 TimeSpan SinceLastFrame = now - m_lastframe;
2639 m_lastframe = now;
2640 float realtime = (float)SinceLastFrame.TotalSeconds;
2641// Console.WriteLine("ts={0} rt={1}", timeStep, realtime);
2642 timeStep = realtime;
2643
2644 // float fps = 1.0f / realtime;
2645 float fps = 0.0f; // number of ODE steps in this Simulate step
2646 //m_log.Info(timeStep.ToString());
2647 step_time += timeStep;
2648
2649 // If We're loaded down by something else,
2650 // or debugging with the Visual Studio project on pause
2651 // skip a few frames to catch up gracefully.
2652 // without shooting the physicsactors all over the place
2653
2654 if (step_time >= m_SkipFramesAtms)
2655 {
2656 // Instead of trying to catch up, it'll do 5 physics frames only
2657 step_time = ODE_STEPSIZE;
2658 m_physicsiterations = 5;
2659 }
2660 else
2661 {
2662 m_physicsiterations = 10;
2663 }
2664
2665 if (SupportsNINJAJoints)
2666 {
2667 DeleteRequestedJoints(); // this must be outside of the lock (OdeLock) to avoid deadlocks
2668 CreateRequestedJoints(); // this must be outside of the lock (OdeLock) to avoid deadlocks
2669 }
2670
2671 lock (OdeLock)
2672 {
2673 // Process 10 frames if the sim is running normal..
2674 // process 5 frames if the sim is running slow
2675 //try
2676 //{
2677 //d.WorldSetQuickStepNumIterations(world, m_physicsiterations);
2678 //}
2679 //catch (StackOverflowException)
2680 //{
2681 // m_log.Error("[PHYSICS]: The operating system wasn't able to allocate enough memory for the simulation. Restarting the sim.");
2682 // ode.drelease(world);
2683 //base.TriggerPhysicsBasedRestart();
2684 //}
2685
2686 int i = 0;
2687
2688 // Figure out the Frames Per Second we're going at.
2689 //(step_time == 0.004f, there's 250 of those per second. Times the step time/step size
2690
2691 // fps = (step_time / ODE_STEPSIZE) * 1000;
2692 // HACK: Using a time dilation of 1.0 to debug rubberbanding issues
2693 //m_timeDilation = Math.Min((step_time / ODE_STEPSIZE) / (0.09375f / ODE_STEPSIZE), 1.0f);
2694
2695 // step_time = 0.09375f;
2696
2697 while (step_time > 0.0f)
2698 {
2699 //lock (ode)
2700 //{
2701 //if (!ode.lockquery())
2702 //{
2703 // ode.dlock(world);
2704 try
2705 {
2706 // Insert, remove Characters
2707 bool processedtaints = false;
2708
2709 lock (_taintedActors)
2710 {
2711 if (_taintedActors.Count > 0)
2712 {
2713 foreach (OdeCharacter character in _taintedActors)
2714 {
2715
2716 character.ProcessTaints(ODE_STEPSIZE);
2717
2718 processedtaints = true;
2719 //character.m_collisionscore = 0;
2720 }
2721
2722 if (processedtaints)
2723 _taintedActors.Clear();
2724 }
2725 } // end lock _taintedActors
2726
2727 // Modify other objects in the scene.
2728 processedtaints = false;
2729
2730 lock (_taintedPrimLock)
2731 {
2732 foreach (OdePrim prim in _taintedPrimL)
2733 {
2734 if (prim.m_taintremove)
2735 {
2736 //Console.WriteLine("Simulate calls RemovePrimThreadLocked");
2737 RemovePrimThreadLocked(prim);
2738 }
2739 else
2740 {
2741 //Console.WriteLine("Simulate calls ProcessTaints");
2742 prim.ProcessTaints(ODE_STEPSIZE);
2743 }
2744 processedtaints = true;
2745 prim.m_collisionscore = 0;
2746
2747 // This loop can block up the Heartbeat for a very long time on large regions.
2748 // We need to let the Watchdog know that the Heartbeat is not dead
2749 // NOTE: This is currently commented out, but if things like OAR loading are
2750 // timing the heartbeat out we will need to uncomment it
2751 //Watchdog.UpdateThread();
2752 }
2753
2754 if (SupportsNINJAJoints)
2755 {
2756 // Create pending joints, if possible
2757
2758 // joints can only be processed after ALL bodies are processed (and exist in ODE), since creating
2759 // a joint requires specifying the body id of both involved bodies
2760 if (pendingJoints.Count > 0)
2761 {
2762 List<PhysicsJoint> successfullyProcessedPendingJoints = new List<PhysicsJoint>();
2763 //DoJointErrorMessage(joints_connecting_actor, "taint: " + pendingJoints.Count + " pending joints");
2764 foreach (PhysicsJoint joint in pendingJoints)
2765 {
2766 //DoJointErrorMessage(joint, "taint: time to create joint with parms: " + joint.RawParams);
2767 string[] jointParams = joint.RawParams.Split(" ".ToCharArray(),
2768 System.StringSplitOptions.RemoveEmptyEntries);
2769 List<IntPtr> jointBodies = new List<IntPtr>();
2770 bool allJointBodiesAreReady = true;
2771 foreach (string jointParam in jointParams)
2772 {
2773 if (jointParam == "NULL")
2774 {
2775 //DoJointErrorMessage(joint, "attaching NULL joint to world");
2776 jointBodies.Add(IntPtr.Zero);
2777 }
2778 else
2779 {
2780 //DoJointErrorMessage(joint, "looking for prim name: " + jointParam);
2781 bool foundPrim = false;
2782 lock (_prims)
2783 {
2784 foreach (OdePrim prim in _prims) // FIXME: inefficient
2785 {
2786 if (prim.SOPName == jointParam)
2787 {
2788 //DoJointErrorMessage(joint, "found for prim name: " + jointParam);
2789 if (prim.IsPhysical && prim.Body != IntPtr.Zero)
2790 {
2791 jointBodies.Add(prim.Body);
2792 foundPrim = true;
2793 break;
2794 }
2795 else
2796 {
2797 DoJointErrorMessage(joint, "prim name " + jointParam +
2798 " exists but is not (yet) physical; deferring joint creation. " +
2799 "IsPhysical property is " + prim.IsPhysical +
2800 " and body is " + prim.Body);
2801 foundPrim = false;
2802 break;
2803 }
2804 }
2805 }
2806 }
2807 if (foundPrim)
2808 {
2809 // all is fine
2810 }
2811 else
2812 {
2813 allJointBodiesAreReady = false;
2814 break;
2815 }
2816 }
2817 }
2818 if (allJointBodiesAreReady)
2819 {
2820 //DoJointErrorMessage(joint, "allJointBodiesAreReady for " + joint.ObjectNameInScene + " with parms " + joint.RawParams);
2821 if (jointBodies[0] == jointBodies[1])
2822 {
2823 DoJointErrorMessage(joint, "ERROR: joint cannot be created; the joint bodies are the same, body1==body2. Raw body is " + jointBodies[0] + ". raw parms: " + joint.RawParams);
2824 }
2825 else
2826 {
2827 switch (joint.Type)
2828 {
2829 case PhysicsJointType.Ball:
2830 {
2831 IntPtr odeJoint;
2832 //DoJointErrorMessage(joint, "ODE creating ball joint ");
2833 odeJoint = d.JointCreateBall(world, IntPtr.Zero);
2834 //DoJointErrorMessage(joint, "ODE attaching ball joint: " + odeJoint + " with b1:" + jointBodies[0] + " b2:" + jointBodies[1]);
2835 d.JointAttach(odeJoint, jointBodies[0], jointBodies[1]);
2836 //DoJointErrorMessage(joint, "ODE setting ball anchor: " + odeJoint + " to vec:" + joint.Position);
2837 d.JointSetBallAnchor(odeJoint,
2838 joint.Position.X,
2839 joint.Position.Y,
2840 joint.Position.Z);
2841 //DoJointErrorMessage(joint, "ODE joint setting OK");
2842 //DoJointErrorMessage(joint, "The ball joint's bodies are here: b0: ");
2843 //DoJointErrorMessage(joint, "" + (jointBodies[0] != IntPtr.Zero ? "" + d.BodyGetPosition(jointBodies[0]) : "fixed environment"));
2844 //DoJointErrorMessage(joint, "The ball joint's bodies are here: b1: ");
2845 //DoJointErrorMessage(joint, "" + (jointBodies[1] != IntPtr.Zero ? "" + d.BodyGetPosition(jointBodies[1]) : "fixed environment"));
2846
2847 if (joint is OdePhysicsJoint)
2848 {
2849 ((OdePhysicsJoint)joint).jointID = odeJoint;
2850 }
2851 else
2852 {
2853 DoJointErrorMessage(joint, "WARNING: non-ode joint in ODE!");
2854 }
2855 }
2856 break;
2857 case PhysicsJointType.Hinge:
2858 {
2859 IntPtr odeJoint;
2860 //DoJointErrorMessage(joint, "ODE creating hinge joint ");
2861 odeJoint = d.JointCreateHinge(world, IntPtr.Zero);
2862 //DoJointErrorMessage(joint, "ODE attaching hinge joint: " + odeJoint + " with b1:" + jointBodies[0] + " b2:" + jointBodies[1]);
2863 d.JointAttach(odeJoint, jointBodies[0], jointBodies[1]);
2864 //DoJointErrorMessage(joint, "ODE setting hinge anchor: " + odeJoint + " to vec:" + joint.Position);
2865 d.JointSetHingeAnchor(odeJoint,
2866 joint.Position.X,
2867 joint.Position.Y,
2868 joint.Position.Z);
2869 // We use the orientation of the x-axis of the joint's coordinate frame
2870 // as the axis for the hinge.
2871
2872 // Therefore, we must get the joint's coordinate frame based on the
2873 // joint.Rotation field, which originates from the orientation of the
2874 // joint's proxy object in the scene.
2875
2876 // The joint's coordinate frame is defined as the transformation matrix
2877 // that converts a vector from joint-local coordinates into world coordinates.
2878 // World coordinates are defined as the XYZ coordinate system of the sim,
2879 // as shown in the top status-bar of the viewer.
2880
2881 // Once we have the joint's coordinate frame, we extract its X axis (AtAxis)
2882 // and use that as the hinge axis.
2883
2884 //joint.Rotation.Normalize();
2885 Matrix4 proxyFrame = Matrix4.CreateFromQuaternion(joint.Rotation);
2886
2887 // Now extract the X axis of the joint's coordinate frame.
2888
2889 // Do not try to use proxyFrame.AtAxis or you will become mired in the
2890 // tar pit of transposed, inverted, and generally messed-up orientations.
2891 // (In other words, Matrix4.AtAxis() is borked.)
2892 // Vector3 jointAxis = proxyFrame.AtAxis; <--- this path leadeth to madness
2893
2894 // Instead, compute the X axis of the coordinate frame by transforming
2895 // the (1,0,0) vector. At least that works.
2896
2897 //m_log.Debug("PHY: making axis: complete matrix is " + proxyFrame);
2898 Vector3 jointAxis = Vector3.Transform(Vector3.UnitX, proxyFrame);
2899 //m_log.Debug("PHY: making axis: hinge joint axis is " + jointAxis);
2900 //DoJointErrorMessage(joint, "ODE setting hinge axis: " + odeJoint + " to vec:" + jointAxis);
2901 d.JointSetHingeAxis(odeJoint,
2902 jointAxis.X,
2903 jointAxis.Y,
2904 jointAxis.Z);
2905 //d.JointSetHingeParam(odeJoint, (int)dParam.CFM, 0.1f);
2906 if (joint is OdePhysicsJoint)
2907 {
2908 ((OdePhysicsJoint)joint).jointID = odeJoint;
2909 }
2910 else
2911 {
2912 DoJointErrorMessage(joint, "WARNING: non-ode joint in ODE!");
2913 }
2914 }
2915 break;
2916 }
2917 successfullyProcessedPendingJoints.Add(joint);
2918 }
2919 }
2920 else
2921 {
2922 DoJointErrorMessage(joint, "joint could not yet be created; still pending");
2923 }
2924 }
2925 foreach (PhysicsJoint successfullyProcessedJoint in successfullyProcessedPendingJoints)
2926 {
2927 //DoJointErrorMessage(successfullyProcessedJoint, "finalizing succesfully procsssed joint " + successfullyProcessedJoint.ObjectNameInScene + " parms " + successfullyProcessedJoint.RawParams);
2928 //DoJointErrorMessage(successfullyProcessedJoint, "removing from pending");
2929 InternalRemovePendingJoint(successfullyProcessedJoint);
2930 //DoJointErrorMessage(successfullyProcessedJoint, "adding to active");
2931 InternalAddActiveJoint(successfullyProcessedJoint);
2932 //DoJointErrorMessage(successfullyProcessedJoint, "done");
2933 }
2934 }
2935 } // end SupportsNINJAJoints
2936
2937 if (processedtaints)
2938//Console.WriteLine("Simulate calls Clear of _taintedPrim list");
2939 _taintedPrimH.Clear(); // ??? if this only ???
2940 _taintedPrimL.Clear();
2941 } // end lock _taintedPrimLock
2942
2943 // Move characters
2944 lock (_characters)
2945 {
2946 List<OdeCharacter> defects = new List<OdeCharacter>();
2947 foreach (OdeCharacter actor in _characters)
2948 {
2949 if (actor != null)
2950 actor.Move(ODE_STEPSIZE, defects);
2951 }
2952 if (0 != defects.Count)
2953 {
2954 foreach (OdeCharacter defect in defects)
2955 {
2956 RemoveCharacter(defect);
2957 }
2958 }
2959 } // end lock _characters
2960
2961 // Move other active objects
2962 lock (_activeprims)
2963 {
2964 foreach (OdePrim prim in _activeprims)
2965 {
2966 prim.m_collisionscore = 0;
2967 prim.Move(ODE_STEPSIZE);
2968 }
2969 } // end lock _activeprims
2970
2971 //if ((framecount % m_randomizeWater) == 0)
2972 // randomizeWater(waterlevel);
2973
2974 //int RayCastTimeMS = m_rayCastManager.ProcessQueuedRequests();
2975 m_rayCastManager.ProcessQueuedRequests();
2976
2977 collision_optimized(ODE_STEPSIZE);
2978
2979 lock (_collisionEventPrim)
2980 {
2981 foreach (PhysicsActor obj in _collisionEventPrim)
2982 {
2983 if (obj == null)
2984 continue;
2985
2986 switch ((ActorTypes)obj.PhysicsActorType)
2987 {
2988 case ActorTypes.Agent:
2989 OdeCharacter cobj = (OdeCharacter)obj;
2990 cobj.AddCollisionFrameTime(100);
2991 cobj.SendCollisions();
2992 break;
2993 case ActorTypes.Prim:
2994 OdePrim pobj = (OdePrim)obj;
2995 pobj.SendCollisions();
2996 break;
2997 }
2998 }
2999 } // end lock _collisionEventPrim
3000
3001 //if (m_global_contactcount > 5)
3002 //{
3003 // m_log.DebugFormat("[PHYSICS]: Contacts:{0}", m_global_contactcount);
3004 //}
3005
3006 m_global_contactcount = 0;
3007
3008 d.WorldQuickStep(world, ODE_STEPSIZE);
3009 d.JointGroupEmpty(contactgroup);
3010 fps++;
3011 //ode.dunlock(world);
3012 } // end try
3013 catch (Exception e)
3014 {
3015 m_log.ErrorFormat("[PHYSICS]: {0}, {1}, {2}", e.Message, e.TargetSite, e);
3016 ode.dunlock(world);
3017 }
3018
3019 step_time -= ODE_STEPSIZE;
3020 i++;
3021 //}
3022 //else
3023 //{
3024 //fps = 0;
3025 //}
3026 //}
3027 } // end while (step_time > 0.0f)
3028
3029 lock (_characters)
3030 {
3031 foreach (OdeCharacter actor in _characters)
3032 {
3033 if (actor != null)
3034 {
3035 if (actor.bad)
3036 m_log.WarnFormat("[PHYSICS]: BAD Actor {0} in _characters list was not removed?", actor.m_uuid);
3037 actor.UpdatePositionAndVelocity();
3038 }
3039 }
3040 }
3041
3042 lock (_badCharacter)
3043 {
3044 if (_badCharacter.Count > 0)
3045 {
3046 foreach (OdeCharacter chr in _badCharacter)
3047 {
3048 RemoveCharacter(chr);
3049 }
3050 _badCharacter.Clear();
3051 }
3052 }
3053
3054 lock (_activeprims)
3055 {
3056 //if (timeStep < 0.2f)
3057 {
3058 foreach (OdePrim actor in _activeprims)
3059 {
3060 if (actor.IsPhysical && (d.BodyIsEnabled(actor.Body) || !actor._zeroFlag))
3061 {
3062 actor.UpdatePositionAndVelocity();
3063
3064 if (SupportsNINJAJoints)
3065 {
3066 // If an actor moved, move its joint proxy objects as well.
3067 // There seems to be an event PhysicsActor.OnPositionUpdate that could be used
3068 // for this purpose but it is never called! So we just do the joint
3069 // movement code here.
3070
3071 if (actor.SOPName != null &&
3072 joints_connecting_actor.ContainsKey(actor.SOPName) &&
3073 joints_connecting_actor[actor.SOPName] != null &&
3074 joints_connecting_actor[actor.SOPName].Count > 0)
3075 {
3076 foreach (PhysicsJoint affectedJoint in joints_connecting_actor[actor.SOPName])
3077 {
3078 if (affectedJoint.IsInPhysicsEngine)
3079 {
3080 DoJointMoved(affectedJoint);
3081 }
3082 else
3083 {
3084 DoJointErrorMessage(affectedJoint, "a body connected to a joint was moved, but the joint doesn't exist yet! this will lead to joint error. joint was: " + affectedJoint.ObjectNameInScene + " parms:" + affectedJoint.RawParams);
3085 }
3086 }
3087 }
3088 }
3089 }
3090 }
3091 }
3092 } // end lock _activeprims
3093
3094 //DumpJointInfo();
3095
3096 // Finished with all sim stepping. If requested, dump world state to file for debugging.
3097 // TODO: This call to the export function is already inside lock (OdeLock) - but is an extra lock needed?
3098 // TODO: This overwrites all dump files in-place. Should this be a growing logfile, or separate snapshots?
3099 if (physics_logging && (physics_logging_interval>0) && (framecount % physics_logging_interval == 0))
3100 {
3101 string fname = "state-" + world.ToString() + ".DIF"; // give each physics world a separate filename
3102 string prefix = "world" + world.ToString(); // prefix for variable names in exported .DIF file
3103
3104 if (physics_logging_append_existing_logfile)
3105 {
3106 string header = "-------------- START OF PHYSICS FRAME " + framecount.ToString() + " --------------";
3107 TextWriter fwriter = File.AppendText(fname);
3108 fwriter.WriteLine(header);
3109 fwriter.Close();
3110 }
3111 d.WorldExportDIF(world, fname, physics_logging_append_existing_logfile, prefix);
3112 }
3113 } // end lock OdeLock
3114
3115 return fps * 1000.0f; //NB This is a FRAME COUNT, not a time! AND is divide by 1000 in SimStatusReporter!
3116 } // end Simulate
3117
3118 public override void GetResults()
3119 {
3120 }
3121
3122 public override bool IsThreaded
3123 {
3124 // for now we won't be multithreaded
3125 get { return (false); }
3126 }
3127
3128 #region ODE Specific Terrain Fixes
3129 public float[] ResizeTerrain512NearestNeighbour(float[] heightMap)
3130 {
3131 float[] returnarr = new float[262144];
3132 float[,] resultarr = new float[(int)WorldExtents.X, (int)WorldExtents.Y];
3133
3134 // Filling out the array into its multi-dimensional components
3135 for (int y = 0; y < WorldExtents.Y; y++)
3136 {
3137 for (int x = 0; x < WorldExtents.X; x++)
3138 {
3139 resultarr[y, x] = heightMap[y * (int)WorldExtents.Y + x];
3140 }
3141 }
3142
3143 // Resize using Nearest Neighbour
3144
3145 // This particular way is quick but it only works on a multiple of the original
3146
3147 // The idea behind this method can be described with the following diagrams
3148 // second pass and third pass happen in the same loop really.. just separated
3149 // them to show what this does.
3150
3151 // First Pass
3152 // ResultArr:
3153 // 1,1,1,1,1,1
3154 // 1,1,1,1,1,1
3155 // 1,1,1,1,1,1
3156 // 1,1,1,1,1,1
3157 // 1,1,1,1,1,1
3158 // 1,1,1,1,1,1
3159
3160 // Second Pass
3161 // ResultArr2:
3162 // 1,,1,,1,,1,,1,,1,
3163 // ,,,,,,,,,,
3164 // 1,,1,,1,,1,,1,,1,
3165 // ,,,,,,,,,,
3166 // 1,,1,,1,,1,,1,,1,
3167 // ,,,,,,,,,,
3168 // 1,,1,,1,,1,,1,,1,
3169 // ,,,,,,,,,,
3170 // 1,,1,,1,,1,,1,,1,
3171 // ,,,,,,,,,,
3172 // 1,,1,,1,,1,,1,,1,
3173
3174 // Third pass fills in the blanks
3175 // ResultArr2:
3176 // 1,1,1,1,1,1,1,1,1,1,1,1
3177 // 1,1,1,1,1,1,1,1,1,1,1,1
3178 // 1,1,1,1,1,1,1,1,1,1,1,1
3179 // 1,1,1,1,1,1,1,1,1,1,1,1
3180 // 1,1,1,1,1,1,1,1,1,1,1,1
3181 // 1,1,1,1,1,1,1,1,1,1,1,1
3182 // 1,1,1,1,1,1,1,1,1,1,1,1
3183 // 1,1,1,1,1,1,1,1,1,1,1,1
3184 // 1,1,1,1,1,1,1,1,1,1,1,1
3185 // 1,1,1,1,1,1,1,1,1,1,1,1
3186 // 1,1,1,1,1,1,1,1,1,1,1,1
3187
3188 // X,Y = .
3189 // X+1,y = ^
3190 // X,Y+1 = *
3191 // X+1,Y+1 = #
3192
3193 // Filling in like this;
3194 // .*
3195 // ^#
3196 // 1st .
3197 // 2nd *
3198 // 3rd ^
3199 // 4th #
3200 // on single loop.
3201
3202 float[,] resultarr2 = new float[512, 512];
3203 for (int y = 0; y < WorldExtents.Y; y++)
3204 {
3205 for (int x = 0; x < WorldExtents.X; x++)
3206 {
3207 resultarr2[y * 2, x * 2] = resultarr[y, x];
3208
3209 if (y < WorldExtents.Y)
3210 {
3211 resultarr2[(y * 2) + 1, x * 2] = resultarr[y, x];
3212 }
3213 if (x < WorldExtents.X)
3214 {
3215 resultarr2[y * 2, (x * 2) + 1] = resultarr[y, x];
3216 }
3217 if (x < WorldExtents.X && y < WorldExtents.Y)
3218 {
3219 resultarr2[(y * 2) + 1, (x * 2) + 1] = resultarr[y, x];
3220 }
3221 }
3222 }
3223
3224 //Flatten out the array
3225 int i = 0;
3226 for (int y = 0; y < 512; y++)
3227 {
3228 for (int x = 0; x < 512; x++)
3229 {
3230 if (resultarr2[y, x] <= 0)
3231 returnarr[i] = 0.0000001f;
3232 else
3233 returnarr[i] = resultarr2[y, x];
3234
3235 i++;
3236 }
3237 }
3238
3239 return returnarr;
3240 }
3241
3242 public float[] ResizeTerrain512Interpolation(float[] heightMap)
3243 {
3244 float[] returnarr = new float[262144];
3245 float[,] resultarr = new float[512,512];
3246
3247 // Filling out the array into its multi-dimensional components
3248 for (int y = 0; y < 256; y++)
3249 {
3250 for (int x = 0; x < 256; x++)
3251 {
3252 resultarr[y, x] = heightMap[y * 256 + x];
3253 }
3254 }
3255
3256 // Resize using interpolation
3257
3258 // This particular way is quick but it only works on a multiple of the original
3259
3260 // The idea behind this method can be described with the following diagrams
3261 // second pass and third pass happen in the same loop really.. just separated
3262 // them to show what this does.
3263
3264 // First Pass
3265 // ResultArr:
3266 // 1,1,1,1,1,1
3267 // 1,1,1,1,1,1
3268 // 1,1,1,1,1,1
3269 // 1,1,1,1,1,1
3270 // 1,1,1,1,1,1
3271 // 1,1,1,1,1,1
3272
3273 // Second Pass
3274 // ResultArr2:
3275 // 1,,1,,1,,1,,1,,1,
3276 // ,,,,,,,,,,
3277 // 1,,1,,1,,1,,1,,1,
3278 // ,,,,,,,,,,
3279 // 1,,1,,1,,1,,1,,1,
3280 // ,,,,,,,,,,
3281 // 1,,1,,1,,1,,1,,1,
3282 // ,,,,,,,,,,
3283 // 1,,1,,1,,1,,1,,1,
3284 // ,,,,,,,,,,
3285 // 1,,1,,1,,1,,1,,1,
3286
3287 // Third pass fills in the blanks
3288 // ResultArr2:
3289 // 1,1,1,1,1,1,1,1,1,1,1,1
3290 // 1,1,1,1,1,1,1,1,1,1,1,1
3291 // 1,1,1,1,1,1,1,1,1,1,1,1
3292 // 1,1,1,1,1,1,1,1,1,1,1,1
3293 // 1,1,1,1,1,1,1,1,1,1,1,1
3294 // 1,1,1,1,1,1,1,1,1,1,1,1
3295 // 1,1,1,1,1,1,1,1,1,1,1,1
3296 // 1,1,1,1,1,1,1,1,1,1,1,1
3297 // 1,1,1,1,1,1,1,1,1,1,1,1
3298 // 1,1,1,1,1,1,1,1,1,1,1,1
3299 // 1,1,1,1,1,1,1,1,1,1,1,1
3300
3301 // X,Y = .
3302 // X+1,y = ^
3303 // X,Y+1 = *
3304 // X+1,Y+1 = #
3305
3306 // Filling in like this;
3307 // .*
3308 // ^#
3309 // 1st .
3310 // 2nd *
3311 // 3rd ^
3312 // 4th #
3313 // on single loop.
3314
3315 float[,] resultarr2 = new float[512,512];
3316 for (int y = 0; y < (int)Constants.RegionSize; y++)
3317 {
3318 for (int x = 0; x < (int)Constants.RegionSize; x++)
3319 {
3320 resultarr2[y*2, x*2] = resultarr[y, x];
3321
3322 if (y < (int)Constants.RegionSize)
3323 {
3324 if (y + 1 < (int)Constants.RegionSize)
3325 {
3326 if (x + 1 < (int)Constants.RegionSize)
3327 {
3328 resultarr2[(y*2) + 1, x*2] = ((resultarr[y, x] + resultarr[y + 1, x] +
3329 resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4);
3330 }
3331 else
3332 {
3333 resultarr2[(y*2) + 1, x*2] = ((resultarr[y, x] + resultarr[y + 1, x])/2);
3334 }
3335 }
3336 else
3337 {
3338 resultarr2[(y*2) + 1, x*2] = resultarr[y, x];
3339 }
3340 }
3341 if (x < (int)Constants.RegionSize)
3342 {
3343 if (x + 1 < (int)Constants.RegionSize)
3344 {
3345 if (y + 1 < (int)Constants.RegionSize)
3346 {
3347 resultarr2[y*2, (x*2) + 1] = ((resultarr[y, x] + resultarr[y + 1, x] +
3348 resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4);
3349 }
3350 else
3351 {
3352 resultarr2[y*2, (x*2) + 1] = ((resultarr[y, x] + resultarr[y, x + 1])/2);
3353 }
3354 }
3355 else
3356 {
3357 resultarr2[y*2, (x*2) + 1] = resultarr[y, x];
3358 }
3359 }
3360 if (x < (int)Constants.RegionSize && y < (int)Constants.RegionSize)
3361 {
3362 if ((x + 1 < (int)Constants.RegionSize) && (y + 1 < (int)Constants.RegionSize))
3363 {
3364 resultarr2[(y*2) + 1, (x*2) + 1] = ((resultarr[y, x] + resultarr[y + 1, x] +
3365 resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4);
3366 }
3367 else
3368 {
3369 resultarr2[(y*2) + 1, (x*2) + 1] = resultarr[y, x];
3370 }
3371 }
3372 }
3373 }
3374 //Flatten out the array
3375 int i = 0;
3376 for (int y = 0; y < 512; y++)
3377 {
3378 for (int x = 0; x < 512; x++)
3379 {
3380 if (Single.IsNaN(resultarr2[y, x]) || Single.IsInfinity(resultarr2[y, x]))
3381 {
3382 m_log.Warn("[PHYSICS]: Non finite heightfield element detected. Setting it to 0");
3383 resultarr2[y, x] = 0;
3384 }
3385 returnarr[i] = resultarr2[y, x];
3386 i++;
3387 }
3388 }
3389
3390 return returnarr;
3391 }
3392
3393 #endregion
3394
3395 public override void SetTerrain(float[] heightMap)
3396 {
3397 if (m_worldOffset != Vector3.Zero && m_parentScene != null)
3398 {
3399 if (m_parentScene is OdeScene)
3400 {
3401 ((OdeScene)m_parentScene).SetTerrain(heightMap, m_worldOffset);
3402 }
3403 }
3404 else
3405 {
3406 SetTerrain(heightMap, m_worldOffset);
3407 }
3408 }
3409
3410 public void SetTerrain(float[] heightMap, Vector3 pOffset)
3411 {
3412
3413 uint regionsize = (uint) Constants.RegionSize; // visible region size eg. 256(M)
3414
3415 uint heightmapWidth = regionsize + 1; // ODE map size 257 x 257 (Meters) (1 extra
3416 uint heightmapHeight = regionsize + 1;
3417
3418 uint heightmapWidthSamples = (uint)regionsize + 2; // Sample file size, 258 x 258 samples
3419 uint heightmapHeightSamples = (uint)regionsize + 2;
3420
3421 // Array of height samples for ODE
3422 float[] _heightmap;
3423 _heightmap = new float[(heightmapWidthSamples * heightmapHeightSamples)]; // loaded samples 258 x 258
3424
3425 // Other ODE parameters
3426 const float scale = 1.0f;
3427 const float offset = 0.0f;
3428 const float thickness = 2.0f; // Was 0.2f, Larger appears to prevent Av fall-through
3429 const int wrap = 0;
3430
3431 float hfmin = 2000f;
3432 float hfmax = -2000f;
3433 float minele = 0.0f; // Dont allow -ve heights
3434
3435 uint x = 0;
3436 uint y = 0;
3437 uint xx = 0;
3438 uint yy = 0;
3439
3440 // load the height samples array from the heightMap
3441 for ( x = 0; x < heightmapWidthSamples; x++) // 0 to 257
3442 {
3443 for ( y = 0; y < heightmapHeightSamples; y++) // 0 to 257
3444 {
3445 xx = x - 1;
3446 if (xx < 0) xx = 0;
3447 if (xx > (regionsize - 1)) xx = regionsize - 1;
3448
3449 yy = y - 1;
3450 if (yy < 0) yy = 0;
3451 if (yy > (regionsize - 1)) yy = regionsize - 1;
3452 // Input xx = 0 0 1 2 ..... 254 255 255 256 total in
3453 // Output x = 0 1 2 3 ..... 255 256 257 258 total out
3454 float val= heightMap[(yy * regionsize) + xx]; // input from heightMap, <0-255 * 256> <0-255>
3455 if (val < minele) val = minele;
3456 _heightmap[x * (regionsize + 2) + y] = val; // samples output to _heightmap, <0-257 * 258> <0-257>
3457 hfmin = (val < hfmin) ? val : hfmin;
3458 hfmax = (val > hfmax) ? val : hfmax;
3459 }
3460 }
3461
3462 lock (OdeLock)
3463 {
3464 IntPtr GroundGeom = IntPtr.Zero;
3465 if (RegionTerrain.TryGetValue(pOffset, out GroundGeom))
3466 {
3467 RegionTerrain.Remove(pOffset);
3468 if (GroundGeom != IntPtr.Zero)
3469 {
3470 if (TerrainHeightFieldHeights.ContainsKey(GroundGeom))
3471 {
3472 TerrainHeightFieldHeights.Remove(GroundGeom);
3473 }
3474 d.SpaceRemove(space, GroundGeom);
3475 d.GeomDestroy(GroundGeom);
3476 }
3477 }
3478 IntPtr HeightmapData = d.GeomHeightfieldDataCreate();
3479 d.GeomHeightfieldDataBuildSingle(HeightmapData, _heightmap, 0,
3480 heightmapWidth, heightmapHeight, (int)heightmapWidthSamples,
3481 (int)heightmapHeightSamples, scale, offset, thickness, wrap);
3482 d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1);
3483 GroundGeom = d.CreateHeightfield(space, HeightmapData, 1);
3484 if (GroundGeom != IntPtr.Zero)
3485 {
3486 d.GeomSetCategoryBits(GroundGeom, (int)(CollisionCategories.Land));
3487 d.GeomSetCollideBits(GroundGeom, (int)(CollisionCategories.Space));
3488 }
3489 geom_name_map[GroundGeom] = "Terrain";
3490
3491 d.Matrix3 R = new d.Matrix3();
3492
3493 Quaternion q1 = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 1.5707f);
3494 Quaternion q2 = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), 1.5707f);
3495 //Axiom.Math.Quaternion q3 = Axiom.Math.Quaternion.FromAngleAxis(3.14f, new Axiom.Math.Vector3(0, 0, 1));
3496
3497 q1 = q1 * q2;
3498 //q1 = q1 * q3;
3499 Vector3 v3;
3500 float angle;
3501 q1.GetAxisAngle(out v3, out angle);
3502
3503 d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle);
3504 d.GeomSetRotation(GroundGeom, ref R);
3505 d.GeomSetPosition(GroundGeom, (pOffset.X + (regionsize * 0.5f)) - 0.5f, (pOffset.Y + (regionsize * 0.5f)) - 0.5f, 0);
3506 IntPtr testGround = IntPtr.Zero;
3507 if (RegionTerrain.TryGetValue(pOffset, out testGround))
3508 {
3509 RegionTerrain.Remove(pOffset);
3510 }
3511 RegionTerrain.Add(pOffset, GroundGeom, GroundGeom);
3512 TerrainHeightFieldHeights.Add(GroundGeom,_heightmap);
3513 }
3514 }
3515
3516 public override void DeleteTerrain()
3517 {
3518 }
3519
3520 public float GetWaterLevel()
3521 {
3522 return waterlevel;
3523 }
3524
3525 public override bool SupportsCombining()
3526 {
3527 return true;
3528 }
3529
3530 public override void UnCombine(PhysicsScene pScene)
3531 {
3532 IntPtr localGround = IntPtr.Zero;
3533// float[] localHeightfield;
3534 bool proceed = false;
3535 List<IntPtr> geomDestroyList = new List<IntPtr>();
3536
3537 lock (OdeLock)
3538 {
3539 if (RegionTerrain.TryGetValue(Vector3.Zero, out localGround))
3540 {
3541 foreach (IntPtr geom in TerrainHeightFieldHeights.Keys)
3542 {
3543 if (geom == localGround)
3544 {
3545// localHeightfield = TerrainHeightFieldHeights[geom];
3546 proceed = true;
3547 }
3548 else
3549 {
3550 geomDestroyList.Add(geom);
3551 }
3552 }
3553
3554 if (proceed)
3555 {
3556 m_worldOffset = Vector3.Zero;
3557 WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize);
3558 m_parentScene = null;
3559
3560 foreach (IntPtr g in geomDestroyList)
3561 {
3562 // removingHeightField needs to be done or the garbage collector will
3563 // collect the terrain data before we tell ODE to destroy it causing
3564 // memory corruption
3565 if (TerrainHeightFieldHeights.ContainsKey(g))
3566 {
3567// float[] removingHeightField = TerrainHeightFieldHeights[g];
3568 TerrainHeightFieldHeights.Remove(g);
3569
3570 if (RegionTerrain.ContainsKey(g))
3571 {
3572 RegionTerrain.Remove(g);
3573 }
3574
3575 d.GeomDestroy(g);
3576 //removingHeightField = new float[0];
3577 }
3578 }
3579
3580 }
3581 else
3582 {
3583 m_log.Warn("[PHYSICS]: Couldn't proceed with UnCombine. Region has inconsistant data.");
3584
3585 }
3586 }
3587 }
3588 }
3589
3590 public override void SetWaterLevel(float baseheight)
3591 {
3592 waterlevel = baseheight;
3593 randomizeWater(waterlevel);
3594 }
3595
3596 public void randomizeWater(float baseheight)
3597 {
3598 const uint heightmapWidth = m_regionWidth + 2;
3599 const uint heightmapHeight = m_regionHeight + 2;
3600 const uint heightmapWidthSamples = m_regionWidth + 2;
3601 const uint heightmapHeightSamples = m_regionHeight + 2;
3602 const float scale = 1.0f;
3603 const float offset = 0.0f;
3604 const float thickness = 2.9f;
3605 const int wrap = 0;
3606
3607 for (int i = 0; i < (258 * 258); i++)
3608 {
3609 _watermap[i] = (baseheight-0.1f) + ((float)fluidRandomizer.Next(1,9) / 10f);
3610 // m_log.Info((baseheight - 0.1f) + ((float)fluidRandomizer.Next(1, 9) / 10f));
3611 }
3612
3613 lock (OdeLock)
3614 {
3615 if (WaterGeom != IntPtr.Zero)
3616 {
3617 d.SpaceRemove(space, WaterGeom);
3618 }
3619 IntPtr HeightmapData = d.GeomHeightfieldDataCreate();
3620 d.GeomHeightfieldDataBuildSingle(HeightmapData, _watermap, 0, heightmapWidth, heightmapHeight,
3621 (int)heightmapWidthSamples, (int)heightmapHeightSamples, scale,
3622 offset, thickness, wrap);
3623 d.GeomHeightfieldDataSetBounds(HeightmapData, m_regionWidth, m_regionHeight);
3624 WaterGeom = d.CreateHeightfield(space, HeightmapData, 1);
3625 if (WaterGeom != IntPtr.Zero)
3626 {
3627 d.GeomSetCategoryBits(WaterGeom, (int)(CollisionCategories.Water));
3628 d.GeomSetCollideBits(WaterGeom, (int)(CollisionCategories.Space));
3629
3630 }
3631 geom_name_map[WaterGeom] = "Water";
3632
3633 d.Matrix3 R = new d.Matrix3();
3634
3635 Quaternion q1 = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 1.5707f);
3636 Quaternion q2 = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), 1.5707f);
3637 //Axiom.Math.Quaternion q3 = Axiom.Math.Quaternion.FromAngleAxis(3.14f, new Axiom.Math.Vector3(0, 0, 1));
3638
3639 q1 = q1 * q2;
3640 //q1 = q1 * q3;
3641 Vector3 v3;
3642 float angle;
3643 q1.GetAxisAngle(out v3, out angle);
3644
3645 d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle);
3646 d.GeomSetRotation(WaterGeom, ref R);
3647 d.GeomSetPosition(WaterGeom, 128, 128, 0);
3648
3649 }
3650
3651 }
3652
3653 public override void Dispose()
3654 {
3655 m_rayCastManager.Dispose();
3656 m_rayCastManager = null;
3657
3658 lock (OdeLock)
3659 {
3660 lock (_prims)
3661 {
3662 foreach (OdePrim prm in _prims)
3663 {
3664 RemovePrim(prm);
3665 }
3666 }
3667
3668 //foreach (OdeCharacter act in _characters)
3669 //{
3670 //RemoveAvatar(act);
3671 //}
3672 d.WorldDestroy(world);
3673 //d.CloseODE();
3674 }
3675 }
3676 public override Dictionary<uint, float> GetTopColliders()
3677 {
3678 Dictionary<uint, float> returncolliders = new Dictionary<uint, float>();
3679 int cnt = 0;
3680 lock (_prims)
3681 {
3682 foreach (OdePrim prm in _prims)
3683 {
3684 if (prm.CollisionScore > 0)
3685 {
3686 returncolliders.Add(prm.m_localID, prm.CollisionScore);
3687 cnt++;
3688 prm.CollisionScore = 0f;
3689 if (cnt > 25)
3690 {
3691 break;
3692 }
3693 }
3694 }
3695 }
3696 return returncolliders;
3697 }
3698
3699 public override bool SupportsRayCast()
3700 {
3701 return true;
3702 }
3703
3704 public override void RaycastWorld(Vector3 position, Vector3 direction, float length, RaycastCallback retMethod)
3705 {
3706 if (retMethod != null)
3707 {
3708 m_rayCastManager.QueueRequest(position, direction, length, retMethod);
3709 }
3710 }
3711
3712#if USE_DRAWSTUFF
3713 // Keyboard callback
3714 public void command(int cmd)
3715 {
3716 IntPtr geom;
3717 d.Mass mass;
3718 d.Vector3 sides = new d.Vector3(d.RandReal() * 0.5f + 0.1f, d.RandReal() * 0.5f + 0.1f, d.RandReal() * 0.5f + 0.1f);
3719
3720
3721
3722 Char ch = Char.ToLower((Char)cmd);
3723 switch ((Char)ch)
3724 {
3725 case 'w':
3726 try
3727 {
3728 Vector3 rotate = (new Vector3(1, 0, 0) * Quaternion.CreateFromEulers(hpr.Z * Utils.DEG_TO_RAD, hpr.Y * Utils.DEG_TO_RAD, hpr.X * Utils.DEG_TO_RAD));
3729
3730 xyz.X += rotate.X; xyz.Y += rotate.Y; xyz.Z += rotate.Z;
3731 ds.SetViewpoint(ref xyz, ref hpr);
3732 }
3733 catch (ArgumentException)
3734 { hpr.X = 0; }
3735 break;
3736
3737 case 'a':
3738 hpr.X++;
3739 ds.SetViewpoint(ref xyz, ref hpr);
3740 break;
3741
3742 case 's':
3743 try
3744 {
3745 Vector3 rotate2 = (new Vector3(-1, 0, 0) * Quaternion.CreateFromEulers(hpr.Z * Utils.DEG_TO_RAD, hpr.Y * Utils.DEG_TO_RAD, hpr.X * Utils.DEG_TO_RAD));
3746
3747 xyz.X += rotate2.X; xyz.Y += rotate2.Y; xyz.Z += rotate2.Z;
3748 ds.SetViewpoint(ref xyz, ref hpr);
3749 }
3750 catch (ArgumentException)
3751 { hpr.X = 0; }
3752 break;
3753 case 'd':
3754 hpr.X--;
3755 ds.SetViewpoint(ref xyz, ref hpr);
3756 break;
3757 case 'r':
3758 xyz.Z++;
3759 ds.SetViewpoint(ref xyz, ref hpr);
3760 break;
3761 case 'f':
3762 xyz.Z--;
3763 ds.SetViewpoint(ref xyz, ref hpr);
3764 break;
3765 case 'e':
3766 xyz.Y++;
3767 ds.SetViewpoint(ref xyz, ref hpr);
3768 break;
3769 case 'q':
3770 xyz.Y--;
3771 ds.SetViewpoint(ref xyz, ref hpr);
3772 break;
3773 }
3774 }
3775
3776 public void step(int pause)
3777 {
3778
3779 ds.SetColor(1.0f, 1.0f, 0.0f);
3780 ds.SetTexture(ds.Texture.Wood);
3781 lock (_prims)
3782 {
3783 foreach (OdePrim prm in _prims)
3784 {
3785 //IntPtr body = d.GeomGetBody(prm.prim_geom);
3786 if (prm.prim_geom != IntPtr.Zero)
3787 {
3788 d.Vector3 pos;
3789 d.GeomCopyPosition(prm.prim_geom, out pos);
3790 //d.BodyCopyPosition(body, out pos);
3791
3792 d.Matrix3 R;
3793 d.GeomCopyRotation(prm.prim_geom, out R);
3794 //d.BodyCopyRotation(body, out R);
3795
3796
3797 d.Vector3 sides = new d.Vector3();
3798 sides.X = prm.Size.X;
3799 sides.Y = prm.Size.Y;
3800 sides.Z = prm.Size.Z;
3801
3802 ds.DrawBox(ref pos, ref R, ref sides);
3803 }
3804 }
3805 }
3806 ds.SetColor(1.0f, 0.0f, 0.0f);
3807 lock (_characters)
3808 {
3809 foreach (OdeCharacter chr in _characters)
3810 {
3811 if (chr.Shell != IntPtr.Zero)
3812 {
3813 IntPtr body = d.GeomGetBody(chr.Shell);
3814
3815 d.Vector3 pos;
3816 d.GeomCopyPosition(chr.Shell, out pos);
3817 //d.BodyCopyPosition(body, out pos);
3818
3819 d.Matrix3 R;
3820 d.GeomCopyRotation(chr.Shell, out R);
3821 //d.BodyCopyRotation(body, out R);
3822
3823 ds.DrawCapsule(ref pos, ref R, chr.Size.Z, 0.35f);
3824 d.Vector3 sides = new d.Vector3();
3825 sides.X = 0.5f;
3826 sides.Y = 0.5f;
3827 sides.Z = 0.5f;
3828
3829 ds.DrawBox(ref pos, ref R, ref sides);
3830 }
3831 }
3832 }
3833 }
3834
3835 public void start(int unused)
3836 {
3837 ds.SetViewpoint(ref xyz, ref hpr);
3838 }
3839#endif
3840 }
3841}
diff --git a/OpenSim/Region/Physics/ChOdePlugin/Tests/ODETestClass.cs b/OpenSim/Region/Physics/ChOdePlugin/Tests/ODETestClass.cs
new file mode 100644
index 0000000..69e2d03
--- /dev/null
+++ b/OpenSim/Region/Physics/ChOdePlugin/Tests/ODETestClass.cs
@@ -0,0 +1,122 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using Nini.Config;
30using NUnit.Framework;
31using OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Region.Physics.Manager;
34using log4net;
35using System.Reflection;
36
37namespace OpenSim.Region.Physics.OdePlugin
38{
39 [TestFixture]
40 public class ODETestClass
41 {
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43
44 private OdePlugin cbt;
45 private PhysicsScene ps;
46 private IMeshingPlugin imp;
47
48 [SetUp]
49 public void Initialize()
50 {
51 // Loading ODEPlugin
52 cbt = new OdePlugin();
53 // Loading Zero Mesher
54 imp = new ZeroMesherPlugin();
55 // Getting Physics Scene
56 ps = cbt.GetScene("test");
57 // Initializing Physics Scene.
58 ps.Initialise(imp.GetMesher(),null);
59 float[] _heightmap = new float[(int)Constants.RegionSize * (int)Constants.RegionSize];
60 for (int i = 0; i < ((int)Constants.RegionSize * (int)Constants.RegionSize); i++)
61 {
62 _heightmap[i] = 21f;
63 }
64 ps.SetTerrain(_heightmap);
65 }
66
67 [TearDown]
68 public void Terminate()
69 {
70 ps.DeleteTerrain();
71 ps.Dispose();
72
73 }
74
75 [Test]
76 public void CreateAndDropPhysicalCube()
77 {
78 PrimitiveBaseShape newcube = PrimitiveBaseShape.CreateBox();
79 Vector3 position = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), 128f);
80 Vector3 size = new Vector3(0.5f, 0.5f, 0.5f);
81 Quaternion rot = Quaternion.Identity;
82 PhysicsActor prim = ps.AddPrimShape("CoolShape", newcube, position, size, rot, true);
83 OdePrim oprim = (OdePrim)prim;
84 OdeScene pscene = (OdeScene) ps;
85
86 Assert.That(oprim.m_taintadd);
87
88 prim.LocalID = 5;
89
90 for (int i = 0; i < 58; i++)
91 {
92 ps.Simulate(0.133f);
93
94 Assert.That(oprim.prim_geom != (IntPtr)0);
95
96 Assert.That(oprim.m_targetSpace != (IntPtr)0);
97
98 //Assert.That(oprim.m_targetSpace == pscene.space);
99 m_log.Info("TargetSpace: " + oprim.m_targetSpace + " - SceneMainSpace: " + pscene.space);
100
101 Assert.That(!oprim.m_taintadd);
102 m_log.Info("Prim Position (" + oprim.m_localID + "): " + prim.Position.ToString());
103
104 // Make sure we're above the ground
105 //Assert.That(prim.Position.Z > 20f);
106 //m_log.Info("PrimCollisionScore (" + oprim.m_localID + "): " + oprim.m_collisionscore);
107
108 // Make sure we've got a Body
109 Assert.That(oprim.Body != (IntPtr)0);
110 //m_log.Info(
111 }
112
113 // Make sure we're not somewhere above the ground
114 Assert.That(prim.Position.Z < 21.5f);
115
116 ps.RemovePrim(prim);
117 Assert.That(oprim.m_taintremove);
118 ps.Simulate(0.133f);
119 Assert.That(oprim.Body == (IntPtr)0);
120 }
121 }
122}
diff --git a/OpenSim/Region/Physics/ChOdePlugin/drawstuff.cs b/OpenSim/Region/Physics/ChOdePlugin/drawstuff.cs
new file mode 100644
index 0000000..87ca446
--- /dev/null
+++ b/OpenSim/Region/Physics/ChOdePlugin/drawstuff.cs
@@ -0,0 +1,98 @@
1/*
2 * Copyright ODE
3 * Ode.NET - .NET bindings for ODE
4 * Jason Perkins (starkos@industriousone.com)
5 * Licensed under the New BSD
6 * Part of the OpenDynamicsEngine
7Open Dynamics Engine
8Copyright (c) 2001-2007, Russell L. Smith.
9All rights reserved.
10
11Redistribution and use in source and binary forms, with or without
12modification, are permitted provided that the following conditions
13are met:
14
15Redistributions of source code must retain the above copyright notice,
16this list of conditions and the following disclaimer.
17
18Redistributions in binary form must reproduce the above copyright notice,
19this list of conditions and the following disclaimer in the documentation
20and/or other materials provided with the distribution.
21
22Neither the names of ODE's copyright owner nor the names of its
23contributors may be used to endorse or promote products derived from
24this software without specific prior written permission.
25
26THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
29FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
32TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 *
38 *
39 */
40
41using System;
42using System.Runtime.InteropServices;
43using Ode.NET;
44
45namespace Drawstuff.NET
46{
47#if dDOUBLE
48 using dReal = System.Double;
49#else
50 using dReal = System.Single;
51#endif
52
53 public static class ds
54 {
55 public const int VERSION = 2;
56
57 public enum Texture
58 {
59 None,
60 Wood
61 }
62
63 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
64 public delegate void CallbackFunction(int arg);
65
66 [StructLayout(LayoutKind.Sequential)]
67 public struct Functions
68 {
69 public int version;
70 public CallbackFunction start;
71 public CallbackFunction step;
72 public CallbackFunction command;
73 public CallbackFunction stop;
74 public string path_to_textures;
75 }
76
77 [DllImport("drawstuff", EntryPoint = "dsDrawBox")]
78 public static extern void DrawBox(ref d.Vector3 pos, ref d.Matrix3 R, ref d.Vector3 sides);
79
80 [DllImport("drawstuff", EntryPoint = "dsDrawCapsule")]
81 public static extern void DrawCapsule(ref d.Vector3 pos, ref d.Matrix3 R, dReal length, dReal radius);
82
83 [DllImport("drawstuff", EntryPoint = "dsDrawConvex")]
84 public static extern void DrawConvex(ref d.Vector3 pos, ref d.Matrix3 R, dReal[] planes, int planeCount, dReal[] points, int pointCount, int[] polygons);
85
86 [DllImport("drawstuff", EntryPoint = "dsSetColor")]
87 public static extern void SetColor(float red, float green, float blue);
88
89 [DllImport("drawstuff", EntryPoint = "dsSetTexture")]
90 public static extern void SetTexture(Texture texture);
91
92 [DllImport("drawstuff", EntryPoint = "dsSetViewpoint")]
93 public static extern void SetViewpoint(ref d.Vector3 xyz, ref d.Vector3 hpr);
94
95 [DllImport("drawstuff", EntryPoint = "dsSimulationLoop")]
96 public static extern void SimulationLoop(int argc, string[] argv, int window_width, int window_height, ref Functions fn);
97 }
98}
diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
index 2a6163c..514d9ad 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
@@ -122,6 +122,9 @@ namespace OpenSim.Region.Physics.Manager
122 /// <param name="prim"></param> 122 /// <param name="prim"></param>
123 public abstract void RemovePrim(PhysicsActor prim); 123 public abstract void RemovePrim(PhysicsActor prim);
124 124
125 //public abstract PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
126 // Vector3 size, Quaternion rotation); //To be removed - Actually removed!
127
125 public abstract PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, 128 public abstract PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
126 Vector3 size, Quaternion rotation, bool isPhysical, uint localid); 129 Vector3 size, Quaternion rotation, bool isPhysical, uint localid);
127 130
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
index 75364b7..62e3763 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
@@ -595,8 +595,8 @@ namespace OpenSim.Region.Physics.OdePlugin
595 break; 595 break;
596 596
597 case HollowShape.Circle: 597 case HollowShape.Circle:
598 // Hollow shape is a perfect cyllinder in respect to the cube's scale 598 // Hollow shape is a perfect cylinder in respect to the cube's scale
599 // Cyllinder hollow volume calculation 599 // Cylinder hollow volume calculation
600 600
601 hollowVolume *= 0.1963495f * 3.07920140172638f; 601 hollowVolume *= 0.1963495f * 3.07920140172638f;
602 break; 602 break;
@@ -2837,7 +2837,7 @@ Console.WriteLine(" JointCreateFixed");
2837 } 2837 }
2838 public override bool PIDActive { set { m_usePID = value; } } 2838 public override bool PIDActive { set { m_usePID = value; } }
2839 public override float PIDTau { set { m_PIDTau = value; } } 2839 public override float PIDTau { set { m_PIDTau = value; } }
2840 2840
2841 public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } } 2841 public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } }
2842 public override bool PIDHoverActive { set { m_useHoverPID = value; } } 2842 public override bool PIDHoverActive { set { m_useHoverPID = value; } }
2843 public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } } 2843 public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } }
diff --git a/OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs b/OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs
index 8d7d3b3..7e3ec63 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs
@@ -137,8 +137,15 @@ namespace OpenSim.Region.Physics.OdePlugin
137 ODERayCastRequest[] reqs = m_PendingRequests.ToArray(); 137 ODERayCastRequest[] reqs = m_PendingRequests.ToArray();
138 for (int i = 0; i < reqs.Length; i++) 138 for (int i = 0; i < reqs.Length; i++)
139 { 139 {
140 if (reqs[i].callbackMethod != null) // quick optimization here, don't raycast 140 try
141 RayCast(reqs[i]); // if there isn't anyone to send results 141 {
142 if (reqs[i].callbackMethod != null) // quick optimization here, don't raycast
143 RayCast(reqs[i]); // if there isn't anyone to send results
144 }
145 catch
146 {
147 //Fail silently
148 }
142 } 149 }
143 150
144 m_PendingRequests.Clear(); 151 m_PendingRequests.Clear();
diff --git a/OpenSim/Region/Physics/POSPlugin/POSPrim.cs b/OpenSim/Region/Physics/POSPlugin/POSPrim.cs
index e4fd7eb..2ea8bfc 100644
--- a/OpenSim/Region/Physics/POSPlugin/POSPrim.cs
+++ b/OpenSim/Region/Physics/POSPlugin/POSPrim.cs
@@ -297,7 +297,7 @@ namespace OpenSim.Region.Physics.POSPlugin
297 { 297 {
298 set { return; } 298 set { return; }
299 } 299 }
300 300
301 public override Quaternion APIDTarget 301 public override Quaternion APIDTarget
302 { 302 {
303 set { return; } 303 set { return; }
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
index 09da97a..3c36943 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
@@ -89,89 +89,7 @@ namespace OpenSim.Region.RegionCombinerModule
89 public void RegionLoaded(Scene scene) 89 public void RegionLoaded(Scene scene)
90 { 90 {
91 if (enabledYN) 91 if (enabledYN)
92 {
93 RegionLoadedDoWork(scene); 92 RegionLoadedDoWork(scene);
94
95 scene.EventManager.OnNewPresence += NewPresence;
96 }
97 }
98
99 private void NewPresence(ScenePresence presence)
100 {
101 if (presence.IsChildAgent)
102 {
103 byte[] throttleData;
104
105 try
106 {
107 throttleData = presence.ControllingClient.GetThrottlesPacked(1);
108 }
109 catch (NotImplementedException)
110 {
111 return;
112 }
113
114 if (throttleData == null)
115 return;
116
117 if (throttleData.Length == 0)
118 return;
119
120 if (throttleData.Length != 28)
121 return;
122
123 byte[] adjData;
124 int pos = 0;
125
126 if (!BitConverter.IsLittleEndian)
127 {
128 byte[] newData = new byte[7 * 4];
129 Buffer.BlockCopy(throttleData, 0, newData, 0, 7 * 4);
130
131 for (int i = 0; i < 7; i++)
132 Array.Reverse(newData, i * 4, 4);
133
134 adjData = newData;
135 }
136 else
137 {
138 adjData = throttleData;
139 }
140
141 // 0.125f converts from bits to bytes
142 int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
143 int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
144 int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
145 int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
146 int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
147 int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
148 int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
149 // State is a subcategory of task that we allocate a percentage to
150
151
152 //int total = resend + land + wind + cloud + task + texture + asset;
153
154 byte[] data = new byte[7 * 4];
155 int ii = 0;
156
157 Buffer.BlockCopy(Utils.FloatToBytes(resend), 0, data, ii, 4); ii += 4;
158 Buffer.BlockCopy(Utils.FloatToBytes(land * 50), 0, data, ii, 4); ii += 4;
159 Buffer.BlockCopy(Utils.FloatToBytes(wind), 0, data, ii, 4); ii += 4;
160 Buffer.BlockCopy(Utils.FloatToBytes(cloud), 0, data, ii, 4); ii += 4;
161 Buffer.BlockCopy(Utils.FloatToBytes(task), 0, data, ii, 4); ii += 4;
162 Buffer.BlockCopy(Utils.FloatToBytes(texture), 0, data, ii, 4); ii += 4;
163 Buffer.BlockCopy(Utils.FloatToBytes(asset), 0, data, ii, 4);
164
165 try
166 {
167 presence.ControllingClient.SetChildAgentThrottle(data);
168 }
169 catch (NotImplementedException)
170 {
171 return;
172 }
173
174 }
175 } 93 }
176 94
177 private void RegionLoadedDoWork(Scene scene) 95 private void RegionLoadedDoWork(Scene scene)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
index ee32755..61e4934 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
@@ -248,6 +248,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
248 248
249 } 249 }
250 250
251 public static void StateChange(IScriptEngine engine, uint localID, UUID itemID)
252 {
253 // Remove a specific script
254
255 // Remove dataserver events
256 m_Dataserver[engine].RemoveEvents(localID, itemID);
257
258 IWorldComm comms = engine.World.RequestModuleInterface<IWorldComm>();
259 if (comms != null)
260 comms.DeleteListener(itemID);
261
262 IXMLRPC xmlrpc = engine.World.RequestModuleInterface<IXMLRPC>();
263 xmlrpc.DeleteChannels(itemID);
264 xmlrpc.CancelSRDRequests(itemID);
265
266 // Remove Sensors
267 m_SensorRepeat[engine].UnSetSenseRepeaterEvents(localID, itemID);
268
269 }
270
251 public static Object[] GetSerializationData(IScriptEngine engine, UUID itemID) 271 public static Object[] GetSerializationData(IScriptEngine engine, UUID itemID)
252 { 272 {
253 List<Object> data = new List<Object>(); 273 List<Object> data = new List<Object>();
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs
new file mode 100644
index 0000000..489c1c6
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs
@@ -0,0 +1,118 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Reflection;
30using System.Collections;
31using System.Collections.Generic;
32using System.Runtime.Remoting.Lifetime;
33using OpenMetaverse;
34using Nini.Config;
35using OpenSim;
36using OpenSim.Framework;
37using OpenSim.Region.CoreModules.World.LightShare;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Region.ScriptEngine.Shared;
41using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
42using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
43using OpenSim.Region.ScriptEngine.Interfaces;
44using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces;
45using OpenSim.Services.Interfaces;
46
47using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
48using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
49using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
50using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
51using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
52using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
53using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
54
55namespace OpenSim.Region.ScriptEngine.Shared.Api
56{
57 [Serializable]
58 public class CM_Api : MarshalByRefObject, ICM_Api, IScriptApi
59 {
60 internal IScriptEngine m_ScriptEngine;
61 internal SceneObjectPart m_host;
62 internal uint m_localID;
63 internal UUID m_itemID;
64 internal bool m_CMFunctionsEnabled = false;
65
66 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID)
67 {
68 m_ScriptEngine = ScriptEngine;
69 m_host = host;
70 m_localID = localID;
71 m_itemID = itemID;
72
73 if (m_ScriptEngine.Config.GetBoolean("AllowCareminsterFunctions", false))
74 m_CMFunctionsEnabled = true;
75 }
76
77 public override Object InitializeLifetimeService()
78 {
79 ILease lease = (ILease)base.InitializeLifetimeService();
80
81 if (lease.CurrentState == LeaseState.Initial)
82 {
83 lease.InitialLeaseTime = TimeSpan.FromMinutes(0);
84 // lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0);
85 // lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0);
86 }
87 return lease;
88 }
89
90 public Scene World
91 {
92 get { return m_ScriptEngine.World; }
93 }
94
95 public string cmDetectedCountry(int number)
96 {
97 m_host.AddScriptLPS(1);
98 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, number);
99 if (detectedParams == null)
100 return String.Empty;
101 return detectedParams.Country;
102 }
103
104 public string cmGetAgentCountry(LSL_Key key)
105 {
106 if (!World.Permissions.IsGod(m_host.OwnerID))
107 return String.Empty;
108
109 UUID uuid;
110
111 if (!UUID.TryParse(key, out uuid))
112 return String.Empty;
113
114 UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
115 return account.UserCountry;
116 }
117 }
118}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 67dee02..7ed41f2 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -28,10 +28,12 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Diagnostics; //for [DebuggerNonUserCode]
31using System.Runtime.Remoting.Lifetime; 32using System.Runtime.Remoting.Lifetime;
32using System.Text; 33using System.Text;
33using System.Threading; 34using System.Threading;
34using System.Text.RegularExpressions; 35using System.Text.RegularExpressions;
36using System.Timers;
35using Nini.Config; 37using Nini.Config;
36using log4net; 38using log4net;
37using OpenMetaverse; 39using OpenMetaverse;
@@ -44,6 +46,7 @@ using OpenSim.Region.CoreModules.World.Land;
44using OpenSim.Region.CoreModules.World.Terrain; 46using OpenSim.Region.CoreModules.World.Terrain;
45using OpenSim.Region.Framework.Interfaces; 47using OpenSim.Region.Framework.Interfaces;
46using OpenSim.Region.Framework.Scenes; 48using OpenSim.Region.Framework.Scenes;
49using OpenSim.Region.Framework.Scenes.Serialization;
47using OpenSim.Region.Framework.Scenes.Animation; 50using OpenSim.Region.Framework.Scenes.Animation;
48using OpenSim.Region.Physics.Manager; 51using OpenSim.Region.Physics.Manager;
49using OpenSim.Region.ScriptEngine.Shared; 52using OpenSim.Region.ScriptEngine.Shared;
@@ -65,6 +68,7 @@ using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
65using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; 68using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
66using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; 69using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
67using System.Reflection; 70using System.Reflection;
71using Timer = System.Timers.Timer;
68 72
69namespace OpenSim.Region.ScriptEngine.Shared.Api 73namespace OpenSim.Region.ScriptEngine.Shared.Api
70{ 74{
@@ -99,16 +103,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
99 protected int m_notecardLineReadCharsMax = 255; 103 protected int m_notecardLineReadCharsMax = 255;
100 protected int m_scriptConsoleChannel = 0; 104 protected int m_scriptConsoleChannel = 0;
101 protected bool m_scriptConsoleChannelEnabled = false; 105 protected bool m_scriptConsoleChannelEnabled = false;
106 protected bool m_debuggerSafe = false;
102 protected IUrlModule m_UrlModule = null; 107 protected IUrlModule m_UrlModule = null;
103 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = 108 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache =
104 new Dictionary<UUID, UserInfoCacheEntry>(); 109 new Dictionary<UUID, UserInfoCacheEntry>();
105 110
111 protected Timer m_ShoutSayTimer;
112 protected int m_SayShoutCount = 0;
113
106 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) 114 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID)
107 { 115 {
116 m_ShoutSayTimer = new Timer(1000);
117 m_ShoutSayTimer.Elapsed += SayShoutTimerElapsed;
118 m_ShoutSayTimer.AutoReset = true;
119 m_ShoutSayTimer.Start();
120
108 m_ScriptEngine = ScriptEngine; 121 m_ScriptEngine = ScriptEngine;
109 m_host = host; 122 m_host = host;
110 m_localID = localID; 123 m_localID = localID;
111 m_itemID = itemID; 124 m_itemID = itemID;
125 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
112 126
113 m_ScriptDelayFactor = 127 m_ScriptDelayFactor =
114 m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f); 128 m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f);
@@ -156,6 +170,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
156 get { return m_ScriptEngine.World; } 170 get { return m_ScriptEngine.World; }
157 } 171 }
158 172
173 [DebuggerNonUserCode]
159 public void state(string newState) 174 public void state(string newState)
160 { 175 {
161 m_ScriptEngine.SetState(m_itemID, newState); 176 m_ScriptEngine.SetState(m_itemID, newState);
@@ -165,6 +180,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
165 /// Reset the named script. The script must be present 180 /// Reset the named script. The script must be present
166 /// in the same prim. 181 /// in the same prim.
167 /// </summary> 182 /// </summary>
183 [DebuggerNonUserCode]
168 public void llResetScript() 184 public void llResetScript()
169 { 185 {
170 m_host.AddScriptLPS(1); 186 m_host.AddScriptLPS(1);
@@ -221,9 +237,62 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
221 } 237 }
222 } 238 }
223 239
240 public List<ScenePresence> GetLinkAvatars(int linkType)
241 {
242 List<ScenePresence> ret = new List<ScenePresence>();
243 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
244 return ret;
245
246 List<ScenePresence> avs = m_host.ParentGroup.GetLinkedAvatars();
247
248 switch (linkType)
249 {
250 case ScriptBaseClass.LINK_SET:
251 return avs;
252
253 case ScriptBaseClass.LINK_ROOT:
254 return ret;
255
256 case ScriptBaseClass.LINK_ALL_OTHERS:
257 return avs;
258
259 case ScriptBaseClass.LINK_ALL_CHILDREN:
260 return avs;
261
262 case ScriptBaseClass.LINK_THIS:
263 return ret;
264
265 default:
266 if (linkType < 0)
267 return ret;
268
269 int partCount = m_host.ParentGroup.GetPartCount();
270
271 if (linkType <= partCount)
272 {
273 return ret;
274 }
275 else
276 {
277 linkType = linkType - partCount;
278 if (linkType > avs.Count)
279 {
280 return ret;
281 }
282 else
283 {
284 ret.Add(avs[linkType-1]);
285 return ret;
286 }
287 }
288 }
289 }
290
224 public List<SceneObjectPart> GetLinkParts(int linkType) 291 public List<SceneObjectPart> GetLinkParts(int linkType)
225 { 292 {
226 List<SceneObjectPart> ret = new List<SceneObjectPart>(); 293 List<SceneObjectPart> ret = new List<SceneObjectPart>();
294 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
295 return ret;
227 ret.Add(m_host); 296 ret.Add(m_host);
228 297
229 switch (linkType) 298 switch (linkType)
@@ -270,40 +339,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
270 protected UUID InventorySelf() 339 protected UUID InventorySelf()
271 { 340 {
272 UUID invItemID = new UUID(); 341 UUID invItemID = new UUID();
273 342 bool unlock = false;
274 lock (m_host.TaskInventory) 343 if (!m_host.TaskInventory.IsReadLockedByMe())
275 { 344 {
276 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 345 m_host.TaskInventory.LockItemsForRead(true);
346 unlock = true;
347 }
348 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
349 {
350 if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID)
277 { 351 {
278 if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID) 352 invItemID = inv.Key;
279 { 353 break;
280 invItemID = inv.Key;
281 break;
282 }
283 } 354 }
284 } 355 }
285 356 if (unlock)
357 {
358 m_host.TaskInventory.LockItemsForRead(false);
359 }
286 return invItemID; 360 return invItemID;
287 } 361 }
288 362
289 protected UUID InventoryKey(string name, int type) 363 protected UUID InventoryKey(string name, int type)
290 { 364 {
291 m_host.AddScriptLPS(1); 365 m_host.AddScriptLPS(1);
292 366 m_host.TaskInventory.LockItemsForRead(true);
293 lock (m_host.TaskInventory) 367
368 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
294 { 369 {
295 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 370 if (inv.Value.Name == name)
296 { 371 {
297 if (inv.Value.Name == name) 372 m_host.TaskInventory.LockItemsForRead(false);
373
374 if (inv.Value.Type != type)
298 { 375 {
299 if (inv.Value.Type != type) 376 return UUID.Zero;
300 return UUID.Zero;
301
302 return inv.Value.AssetID;
303 } 377 }
378
379 return inv.Value.AssetID;
304 } 380 }
305 } 381 }
306 382
383 m_host.TaskInventory.LockItemsForRead(false);
307 return UUID.Zero; 384 return UUID.Zero;
308 } 385 }
309 386
@@ -311,17 +388,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
311 { 388 {
312 m_host.AddScriptLPS(1); 389 m_host.AddScriptLPS(1);
313 390
314 lock (m_host.TaskInventory) 391
392 m_host.TaskInventory.LockItemsForRead(true);
393
394 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
315 { 395 {
316 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 396 if (inv.Value.Name == name)
317 { 397 {
318 if (inv.Value.Name == name) 398 m_host.TaskInventory.LockItemsForRead(false);
319 { 399 return inv.Value.AssetID;
320 return inv.Value.AssetID;
321 }
322 } 400 }
323 } 401 }
324 402
403 m_host.TaskInventory.LockItemsForRead(false);
404
405
325 return UUID.Zero; 406 return UUID.Zero;
326 } 407 }
327 408
@@ -463,31 +544,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
463 544
464 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke 545 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
465 546
466 /// <summary> 547 // Utility function for llRot2Euler
467 /// Convert an LSL rotation to a Euler vector. 548
468 /// </summary> 549 // normalize an angle between -PI and PI (-180 to +180 degrees)
469 /// <remarks> 550 protected double NormalizeAngle(double angle)
470 /// Using algorithm based off http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/quat_2_euler_paper_ver2-1.pdf
471 /// to avoid issues with singularity and rounding with Y rotation of +/- PI/2
472 /// </remarks>
473 /// <param name="r"></param>
474 /// <returns></returns>
475 public LSL_Vector llRot2Euler(LSL_Rotation r)
476 { 551 {
477 m_host.AddScriptLPS(1); 552 if (angle > -Math.PI && angle < Math.PI)
553 return angle;
478 554
479 LSL_Vector v = new LSL_Vector(0.0, 0.0, 1.0) * r; // Z axis unit vector unaffected by Z rotation component of r. 555 int numPis = (int)(Math.PI / angle);
480 double m = LSL_Vector.Mag(v); // Just in case v isn't normalized, need magnitude for Asin() operation later. 556 double remainder = angle - Math.PI * numPis;
481 if (m == 0.0) return new LSL_Vector(); 557 if (numPis % 2 == 1)
482 double x = Math.Atan2(-v.y, v.z); 558 return Math.PI - angle;
483 double sin = v.x / m; 559 return remainder;
484 if (sin < -0.999999 || sin > 0.999999) x = 0.0; // Force X rotation to 0 at the singularities. 560 }
485 double y = Math.Asin(sin); 561
486 // Rotate X axis unit vector by r and unwind the X and Y rotations leaving only the Z rotation 562 public LSL_Vector llRot2Euler(LSL_Rotation q1)
487 v = new LSL_Vector(1.0, 0.0, 0.0) * ((r * new LSL_Rotation(Math.Sin(-x / 2.0), 0.0, 0.0, Math.Cos(-x / 2.0))) * new LSL_Rotation(0.0, Math.Sin(-y / 2.0), 0.0, Math.Cos(-y / 2.0))); 563 {
488 double z = Math.Atan2(v.y, v.x); 564 m_host.AddScriptLPS(1);
565 LSL_Vector eul = new LSL_Vector();
489 566
490 return new LSL_Vector(x, y, z); 567 double sqw = q1.s*q1.s;
568 double sqx = q1.x*q1.x;
569 double sqy = q1.z*q1.z;
570 double sqz = q1.y*q1.y;
571 double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
572 double test = q1.x*q1.z + q1.y*q1.s;
573 if (test > 0.4999*unit) { // singularity at north pole
574 eul.z = 2 * Math.Atan2(q1.x,q1.s);
575 eul.y = Math.PI/2;
576 eul.x = 0;
577 return eul;
578 }
579 if (test < -0.4999*unit) { // singularity at south pole
580 eul.z = -2 * Math.Atan2(q1.x,q1.s);
581 eul.y = -Math.PI/2;
582 eul.x = 0;
583 return eul;
584 }
585 eul.z = Math.Atan2(2*q1.z*q1.s-2*q1.x*q1.y , sqx - sqy - sqz + sqw);
586 eul.y = Math.Asin(2*test/unit);
587 eul.x = Math.Atan2(2*q1.x*q1.s-2*q1.z*q1.y , -sqx + sqy - sqz + sqw);
588 return eul;
491 } 589 }
492 590
493 /* From wiki: 591 /* From wiki:
@@ -689,77 +787,76 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
689 { 787 {
690 //A and B should both be normalized 788 //A and B should both be normalized
691 m_host.AddScriptLPS(1); 789 m_host.AddScriptLPS(1);
692 LSL_Rotation rotBetween; 790 /* This method is more accurate than the SL one, and thus causes problems
693 // Check for zero vectors. If either is zero, return zero rotation. Otherwise, 791 for scripts that deal with the SL inaccuracy around 180-degrees -.- .._.
694 // continue calculation. 792
695 if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f)) 793 double dotProduct = LSL_Vector.Dot(a, b);
794 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
795 double magProduct = LSL_Vector.Mag(a) * LSL_Vector.Mag(b);
796 double angle = Math.Acos(dotProduct / magProduct);
797 LSL_Vector axis = LSL_Vector.Norm(crossProduct);
798 double s = Math.Sin(angle / 2);
799
800 double x = axis.x * s;
801 double y = axis.y * s;
802 double z = axis.z * s;
803 double w = Math.Cos(angle / 2);
804
805 if (Double.IsNaN(x) || Double.IsNaN(y) || Double.IsNaN(z) || Double.IsNaN(w))
806 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
807
808 return new LSL_Rotation((float)x, (float)y, (float)z, (float)w);
809 */
810
811 // This method mimics the 180 errors found in SL
812 // See www.euclideanspace.com... angleBetween
813 LSL_Vector vec_a = a;
814 LSL_Vector vec_b = b;
815
816 // Eliminate zero length
817 LSL_Float vec_a_mag = LSL_Vector.Mag(vec_a);
818 LSL_Float vec_b_mag = LSL_Vector.Mag(vec_b);
819 if (vec_a_mag < 0.00001 ||
820 vec_b_mag < 0.00001)
696 { 821 {
697 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); 822 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
698 } 823 }
699 else 824
825 // Normalize
826 vec_a = llVecNorm(vec_a);
827 vec_b = llVecNorm(vec_b);
828
829 // Calculate axis and rotation angle
830 LSL_Vector axis = vec_a % vec_b;
831 LSL_Float cos_theta = vec_a * vec_b;
832
833 // Check if parallel
834 if (cos_theta > 0.99999)
700 { 835 {
701 a = LSL_Vector.Norm(a); 836 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
702 b = LSL_Vector.Norm(b); 837 }
703 double dotProduct = LSL_Vector.Dot(a, b); 838
704 // There are two degenerate cases possible. These are for vectors 180 or 839 // Check if anti-parallel
705 // 0 degrees apart. These have to be detected and handled individually. 840 else if (cos_theta < -0.99999)
706 // 841 {
707 // Check for vectors 180 degrees apart. 842 LSL_Vector orthog_axis = new LSL_Vector(1.0, 0.0, 0.0) - (vec_a.x / (vec_a * vec_a) * vec_a);
708 // A dot product of -1 would mean the angle between vectors is 180 degrees. 843 if (LSL_Vector.Mag(orthog_axis) < 0.000001) orthog_axis = new LSL_Vector(0.0, 0.0, 1.0);
709 if (dotProduct < -0.9999999f) 844 return new LSL_Rotation((float)orthog_axis.x, (float)orthog_axis.y, (float)orthog_axis.z, 0.0);
710 { 845 }
711 // First assume X axis is orthogonal to the vectors. 846 else // other rotation
712 LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f); 847 {
713 orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a)); 848 LSL_Float theta = (LSL_Float)Math.Acos(cos_theta) * 0.5f;
714 // Check for near zero vector. A very small non-zero number here will create 849 axis = llVecNorm(axis);
715 // a rotation in an undesired direction. 850 double x, y, z, s, t;
716 if (LSL_Vector.Mag(orthoVector) > 0.0001) 851 s = Math.Cos(theta);
717 { 852 t = Math.Sin(theta);
718 rotBetween = new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f); 853 x = axis.x * t;
719 } 854 y = axis.y * t;
720 // If the magnitude of the vector was near zero, then assume the X axis is not 855 z = axis.z * t;
721 // orthogonal and use the Z axis instead. 856 return new LSL_Rotation(x,y,z,s);
722 else
723 {
724 // Set 180 z rotation.
725 rotBetween = new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f);
726 }
727 }
728 // Check for parallel vectors.
729 // A dot product of 1 would mean the angle between vectors is 0 degrees.
730 else if (dotProduct > 0.9999999f)
731 {
732 // Set zero rotation.
733 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
734 }
735 else
736 {
737 // All special checks have been performed so get the axis of rotation.
738 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
739 // Quarternion s value is the length of the unit vector + dot product.
740 double qs = 1.0 + dotProduct;
741 rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs);
742 // Normalize the rotation.
743 double mag = LSL_Rotation.Mag(rotBetween);
744 // We shouldn't have to worry about a divide by zero here. The qs value will be
745 // non-zero because we already know if we're here, then the dotProduct is not -1 so
746 // qs will not be zero. Also, we've already handled the input vectors being zero so the
747 // crossProduct vector should also not be zero.
748 rotBetween.x = rotBetween.x / mag;
749 rotBetween.y = rotBetween.y / mag;
750 rotBetween.z = rotBetween.z / mag;
751 rotBetween.s = rotBetween.s / mag;
752 // Check for undefined values and set zero rotation if any found. This code might not actually be required
753 // any longer since zero vectors are checked for at the top.
754 if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) || Double.IsNaN(rotBetween.s))
755 {
756 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
757 }
758 }
759 } 857 }
760 return rotBetween;
761 } 858 }
762 859
763 public void llWhisper(int channelID, string text) 860 public void llWhisper(int channelID, string text)
764 { 861 {
765 m_host.AddScriptLPS(1); 862 m_host.AddScriptLPS(1);
@@ -779,6 +876,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
779 { 876 {
780 m_host.AddScriptLPS(1); 877 m_host.AddScriptLPS(1);
781 878
879 if (channelID == 0)
880 m_SayShoutCount++;
881
882 if (m_SayShoutCount >= 11)
883 ScriptSleep(2000);
884
782 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel)) 885 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel))
783 { 886 {
784 Console.WriteLine(text); 887 Console.WriteLine(text);
@@ -801,6 +904,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
801 { 904 {
802 m_host.AddScriptLPS(1); 905 m_host.AddScriptLPS(1);
803 906
907 if (channelID == 0)
908 m_SayShoutCount++;
909
910 if (m_SayShoutCount >= 11)
911 ScriptSleep(2000);
912
804 if (text.Length > 1023) 913 if (text.Length > 1023)
805 text = text.Substring(0, 1023); 914 text = text.Substring(0, 1023);
806 915
@@ -1101,10 +1210,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1101 return detectedParams.TouchUV; 1210 return detectedParams.TouchUV;
1102 } 1211 }
1103 1212
1213 [DebuggerNonUserCode]
1104 public virtual void llDie() 1214 public virtual void llDie()
1105 { 1215 {
1106 m_host.AddScriptLPS(1); 1216 m_host.AddScriptLPS(1);
1107 throw new SelfDeleteException(); 1217 if (!m_host.ParentGroup.IsAttachment) throw new SelfDeleteException();
1108 } 1218 }
1109 1219
1110 public LSL_Float llGround(LSL_Vector offset) 1220 public LSL_Float llGround(LSL_Vector offset)
@@ -1177,6 +1287,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1177 1287
1178 public void llSetStatus(int status, int value) 1288 public void llSetStatus(int status, int value)
1179 { 1289 {
1290 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
1291 return;
1180 m_host.AddScriptLPS(1); 1292 m_host.AddScriptLPS(1);
1181 1293
1182 int statusrotationaxis = 0; 1294 int statusrotationaxis = 0;
@@ -1406,6 +1518,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1406 { 1518 {
1407 m_host.AddScriptLPS(1); 1519 m_host.AddScriptLPS(1);
1408 1520
1521 SetColor(m_host, color, face);
1522 }
1523
1524 protected void SetColor(SceneObjectPart part, LSL_Vector color, int face)
1525 {
1526 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1527 return;
1528
1529 Primitive.TextureEntry tex = part.Shape.Textures;
1530 Color4 texcolor;
1531 if (face >= 0 && face < GetNumberOfSides(part))
1532 {
1533 texcolor = tex.CreateFace((uint)face).RGBA;
1534 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1535 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1536 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1537 tex.FaceTextures[face].RGBA = texcolor;
1538 part.UpdateTextureEntry(tex.GetBytes());
1539 return;
1540 }
1541 else if (face == ScriptBaseClass.ALL_SIDES)
1542 {
1543 for (uint i = 0; i < GetNumberOfSides(part); i++)
1544 {
1545 if (tex.FaceTextures[i] != null)
1546 {
1547 texcolor = tex.FaceTextures[i].RGBA;
1548 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1549 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1550 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1551 tex.FaceTextures[i].RGBA = texcolor;
1552 }
1553 texcolor = tex.DefaultTexture.RGBA;
1554 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1555 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1556 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1557 tex.DefaultTexture.RGBA = texcolor;
1558 }
1559 part.UpdateTextureEntry(tex.GetBytes());
1560 return;
1561 }
1562
1409 if (face == ScriptBaseClass.ALL_SIDES) 1563 if (face == ScriptBaseClass.ALL_SIDES)
1410 face = SceneObjectPart.ALL_SIDES; 1564 face = SceneObjectPart.ALL_SIDES;
1411 1565
@@ -1414,6 +1568,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1414 1568
1415 public void SetTexGen(SceneObjectPart part, int face,int style) 1569 public void SetTexGen(SceneObjectPart part, int face,int style)
1416 { 1570 {
1571 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1572 return;
1573
1417 Primitive.TextureEntry tex = part.Shape.Textures; 1574 Primitive.TextureEntry tex = part.Shape.Textures;
1418 MappingType textype; 1575 MappingType textype;
1419 textype = MappingType.Default; 1576 textype = MappingType.Default;
@@ -1444,6 +1601,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1444 1601
1445 public void SetGlow(SceneObjectPart part, int face, float glow) 1602 public void SetGlow(SceneObjectPart part, int face, float glow)
1446 { 1603 {
1604 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1605 return;
1606
1447 Primitive.TextureEntry tex = part.Shape.Textures; 1607 Primitive.TextureEntry tex = part.Shape.Textures;
1448 if (face >= 0 && face < GetNumberOfSides(part)) 1608 if (face >= 0 && face < GetNumberOfSides(part))
1449 { 1609 {
@@ -1469,6 +1629,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1469 1629
1470 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump) 1630 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump)
1471 { 1631 {
1632 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1633 return;
1472 1634
1473 Shininess sval = new Shininess(); 1635 Shininess sval = new Shininess();
1474 1636
@@ -1519,6 +1681,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1519 1681
1520 public void SetFullBright(SceneObjectPart part, int face, bool bright) 1682 public void SetFullBright(SceneObjectPart part, int face, bool bright)
1521 { 1683 {
1684 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1685 return;
1686
1522 Primitive.TextureEntry tex = part.Shape.Textures; 1687 Primitive.TextureEntry tex = part.Shape.Textures;
1523 if (face >= 0 && face < GetNumberOfSides(part)) 1688 if (face >= 0 && face < GetNumberOfSides(part))
1524 { 1689 {
@@ -1579,13 +1744,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1579 m_host.AddScriptLPS(1); 1744 m_host.AddScriptLPS(1);
1580 1745
1581 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1746 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1582 1747 if (parts.Count > 0)
1583 foreach (SceneObjectPart part in parts) 1748 {
1584 SetAlpha(part, alpha, face); 1749 try
1750 {
1751 parts[0].ParentGroup.areUpdatesSuspended = true;
1752 foreach (SceneObjectPart part in parts)
1753 SetAlpha(part, alpha, face);
1754 }
1755 finally
1756 {
1757 parts[0].ParentGroup.areUpdatesSuspended = false;
1758 }
1759 }
1585 } 1760 }
1586 1761
1587 protected void SetAlpha(SceneObjectPart part, double alpha, int face) 1762 protected void SetAlpha(SceneObjectPart part, double alpha, int face)
1588 { 1763 {
1764 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1765 return;
1766
1589 Primitive.TextureEntry tex = part.Shape.Textures; 1767 Primitive.TextureEntry tex = part.Shape.Textures;
1590 Color4 texcolor; 1768 Color4 texcolor;
1591 if (face >= 0 && face < GetNumberOfSides(part)) 1769 if (face >= 0 && face < GetNumberOfSides(part))
@@ -1638,7 +1816,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1638 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction, 1816 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction,
1639 float wind, float tension, LSL_Vector Force) 1817 float wind, float tension, LSL_Vector Force)
1640 { 1818 {
1641 if (part == null) 1819 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1642 return; 1820 return;
1643 1821
1644 if (flexi) 1822 if (flexi)
@@ -1672,7 +1850,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1672 /// <param name="falloff"></param> 1850 /// <param name="falloff"></param>
1673 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff) 1851 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
1674 { 1852 {
1675 if (part == null) 1853 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1676 return; 1854 return;
1677 1855
1678 if (light) 1856 if (light)
@@ -1749,15 +1927,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1749 m_host.AddScriptLPS(1); 1927 m_host.AddScriptLPS(1);
1750 1928
1751 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1929 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1752 1930 if (parts.Count > 0)
1753 foreach (SceneObjectPart part in parts) 1931 {
1754 SetTexture(part, texture, face); 1932 try
1755 1933 {
1934 parts[0].ParentGroup.areUpdatesSuspended = true;
1935 foreach (SceneObjectPart part in parts)
1936 SetTexture(part, texture, face);
1937 }
1938 finally
1939 {
1940 parts[0].ParentGroup.areUpdatesSuspended = false;
1941 }
1942 }
1756 ScriptSleep(200); 1943 ScriptSleep(200);
1757 } 1944 }
1758 1945
1759 protected void SetTexture(SceneObjectPart part, string texture, int face) 1946 protected void SetTexture(SceneObjectPart part, string texture, int face)
1760 { 1947 {
1948 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1949 return;
1950
1761 UUID textureID = new UUID(); 1951 UUID textureID = new UUID();
1762 1952
1763 textureID = InventoryKey(texture, (int)AssetType.Texture); 1953 textureID = InventoryKey(texture, (int)AssetType.Texture);
@@ -1802,6 +1992,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1802 1992
1803 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face) 1993 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face)
1804 { 1994 {
1995 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1996 return;
1997
1805 Primitive.TextureEntry tex = part.Shape.Textures; 1998 Primitive.TextureEntry tex = part.Shape.Textures;
1806 if (face >= 0 && face < GetNumberOfSides(part)) 1999 if (face >= 0 && face < GetNumberOfSides(part))
1807 { 2000 {
@@ -1838,6 +2031,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1838 2031
1839 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face) 2032 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face)
1840 { 2033 {
2034 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2035 return;
2036
1841 Primitive.TextureEntry tex = part.Shape.Textures; 2037 Primitive.TextureEntry tex = part.Shape.Textures;
1842 if (face >= 0 && face < GetNumberOfSides(part)) 2038 if (face >= 0 && face < GetNumberOfSides(part))
1843 { 2039 {
@@ -1874,6 +2070,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1874 2070
1875 protected void RotateTexture(SceneObjectPart part, double rotation, int face) 2071 protected void RotateTexture(SceneObjectPart part, double rotation, int face)
1876 { 2072 {
2073 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2074 return;
2075
1877 Primitive.TextureEntry tex = part.Shape.Textures; 2076 Primitive.TextureEntry tex = part.Shape.Textures;
1878 if (face >= 0 && face < GetNumberOfSides(part)) 2077 if (face >= 0 && face < GetNumberOfSides(part))
1879 { 2078 {
@@ -1980,24 +2179,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1980 2179
1981 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos) 2180 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos)
1982 { 2181 {
1983 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) 2182 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1984 LSL_Vector currentPos = GetPartLocalPos(part); 2183 return;
1985 2184
1986 float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y); 2185 LSL_Vector currentPos = GetPartLocalPos(part);
1987 bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true); 2186 LSL_Vector toPos = GetSetPosTarget(part, targetPos, currentPos);
1988 2187
1989 if (part.ParentGroup.RootPart == part) 2188 if (part.ParentGroup.RootPart == part)
1990 { 2189 {
1991 if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0)
1992 targetPos.z = ground;
1993 SceneObjectGroup parent = part.ParentGroup; 2190 SceneObjectGroup parent = part.ParentGroup;
1994 LSL_Vector real_vec = SetPosAdjust(currentPos, targetPos); 2191 parent.UpdateGroupPosition(new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z));
1995 parent.UpdateGroupPosition(new Vector3((float)real_vec.x, (float)real_vec.y, (float)real_vec.z));
1996 } 2192 }
1997 else 2193 else
1998 { 2194 {
1999 LSL_Vector rel_vec = SetPosAdjust(currentPos, targetPos); 2195 part.OffsetPosition = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z);
2000 part.OffsetPosition = new Vector3((float)rel_vec.x, (float)rel_vec.y, (float)rel_vec.z);
2001 SceneObjectGroup parent = part.ParentGroup; 2196 SceneObjectGroup parent = part.ParentGroup;
2002 parent.HasGroupChanged = true; 2197 parent.HasGroupChanged = true;
2003 parent.ScheduleGroupForTerseUpdate(); 2198 parent.ScheduleGroupForTerseUpdate();
@@ -2048,9 +2243,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2048 m_host.AddScriptLPS(1); 2243 m_host.AddScriptLPS(1);
2049 2244
2050 // try to let this work as in SL... 2245 // try to let this work as in SL...
2051 if (m_host.ParentID == 0) 2246 if (m_host.LinkNum < 2)
2052 { 2247 {
2053 // special case: If we are root, rotate complete SOG to new rotation 2248 // Special case: If we are root, rotate complete SOG to new
2249 // rotation.
2250 // We are root if the link number is 0 (single prim) or 1
2251 // (root prim). ParentID may be nonzero in attachments and
2252 // using it would cause attachments and HUDs to rotate
2253 // to the wrong positions.
2054 SetRot(m_host, Rot2Quaternion(rot)); 2254 SetRot(m_host, Rot2Quaternion(rot));
2055 } 2255 }
2056 else 2256 else
@@ -2075,6 +2275,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2075 2275
2076 protected void SetRot(SceneObjectPart part, Quaternion rot) 2276 protected void SetRot(SceneObjectPart part, Quaternion rot)
2077 { 2277 {
2278 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2279 return;
2280
2078 part.UpdateRotation(rot); 2281 part.UpdateRotation(rot);
2079 // Update rotation does not move the object in the physics scene if it's a linkset. 2282 // Update rotation does not move the object in the physics scene if it's a linkset.
2080 2283
@@ -2698,12 +2901,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2698 2901
2699 m_host.AddScriptLPS(1); 2902 m_host.AddScriptLPS(1);
2700 2903
2904 m_host.TaskInventory.LockItemsForRead(true);
2701 TaskInventoryItem item = m_host.TaskInventory[invItemID]; 2905 TaskInventoryItem item = m_host.TaskInventory[invItemID];
2702 2906 m_host.TaskInventory.LockItemsForRead(false);
2703 lock (m_host.TaskInventory)
2704 {
2705 item = m_host.TaskInventory[invItemID];
2706 }
2707 2907
2708 if (item.PermsGranter == UUID.Zero) 2908 if (item.PermsGranter == UUID.Zero)
2709 return 0; 2909 return 0;
@@ -2778,6 +2978,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2778 if (dist > m_ScriptDistanceFactor * 10.0f) 2978 if (dist > m_ScriptDistanceFactor * 10.0f)
2779 return; 2979 return;
2780 2980
2981 //Clone is thread-safe
2781 TaskInventoryDictionary partInventory = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 2982 TaskInventoryDictionary partInventory = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
2782 2983
2783 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in partInventory) 2984 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in partInventory)
@@ -2806,7 +3007,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2806 // objects rezzed with this method are die_at_edge by default. 3007 // objects rezzed with this method are die_at_edge by default.
2807 new_group.RootPart.SetDieAtEdge(true); 3008 new_group.RootPart.SetDieAtEdge(true);
2808 3009
2809 new_group.ResumeScripts(); 3010 Util.FireAndForget(delegate (object x)
3011 {
3012 new_group.ResumeScripts();
3013 });
2810 3014
2811 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams( 3015 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
2812 "object_rez", new Object[] { 3016 "object_rez", new Object[] {
@@ -2839,34 +3043,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2839 public void llLookAt(LSL_Vector target, double strength, double damping) 3043 public void llLookAt(LSL_Vector target, double strength, double damping)
2840 { 3044 {
2841 m_host.AddScriptLPS(1); 3045 m_host.AddScriptLPS(1);
2842 // Determine where we are looking from
2843 LSL_Vector from = llGetPos();
2844 3046
2845 // Work out the normalised vector from the source to the target 3047 // Get the normalized vector to the target
2846 LSL_Vector delta = llVecNorm(target - from); 3048 LSL_Vector d1 = llVecNorm(target - llGetPos());
2847 LSL_Vector angle = new LSL_Vector(0,0,0);
2848 3049
2849 // Calculate the yaw 3050 // Get the bearing (yaw)
2850 // subtracting PI_BY_TWO is required to compensate for the odd SL co-ordinate system 3051 LSL_Vector a1 = new LSL_Vector(0,0,0);
2851 angle.x = llAtan2(delta.z, delta.y) - ScriptBaseClass.PI_BY_TWO; 3052 a1.z = llAtan2(d1.y, d1.x);
2852 3053
2853 // Calculate pitch 3054 // Get the elevation (pitch)
2854 angle.y = llAtan2(delta.x, llSqrt((delta.y * delta.y) + (delta.z * delta.z))); 3055 LSL_Vector a2 = new LSL_Vector(0,0,0);
3056 a2.y= -llAtan2(d1.z, llSqrt((d1.x * d1.x) + (d1.y * d1.y)));
2855 3057
2856 // we need to convert from a vector describing 3058 LSL_Rotation r1 = llEuler2Rot(a1);
2857 // the angles of rotation in radians into rotation value 3059 LSL_Rotation r2 = llEuler2Rot(a2);
3060 LSL_Rotation r3 = new LSL_Rotation(0.000000, 0.707107, 0.000000, 0.707107);
2858 3061
2859 LSL_Rotation rot = llEuler2Rot(angle); 3062 if (m_host.PhysActor == null || !m_host.PhysActor.IsPhysical)
2860
2861 // Per discussion with Melanie, for non-physical objects llLookAt appears to simply
2862 // set the rotation of the object, copy that behavior
2863 if (strength == 0 || m_host.PhysActor == null || !m_host.PhysActor.IsPhysical)
2864 { 3063 {
2865 llSetRot(rot); 3064 // Do nothing if either value is 0 (this has been checked in SL)
3065 if (strength <= 0.0 || damping <= 0.0)
3066 return;
3067
3068 llSetRot(r3 * r2 * r1);
2866 } 3069 }
2867 else 3070 else
2868 { 3071 {
2869 m_host.StartLookAt(Rot2Quaternion(rot), (float)strength, (float)damping); 3072 if (strength == 0)
3073 {
3074 llSetRot(r3 * r2 * r1);
3075 return;
3076 }
3077
3078 m_host.StartLookAt(Rot2Quaternion(r3 * r2 * r1), (float)strength, (float)damping);
2870 } 3079 }
2871 } 3080 }
2872 3081
@@ -2916,13 +3125,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2916 { 3125 {
2917 TaskInventoryItem item; 3126 TaskInventoryItem item;
2918 3127
2919 lock (m_host.TaskInventory) 3128 m_host.TaskInventory.LockItemsForRead(true);
3129 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2920 { 3130 {
2921 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3131 m_host.TaskInventory.LockItemsForRead(false);
2922 return; 3132 return;
2923 else 3133 }
2924 item = m_host.TaskInventory[InventorySelf()]; 3134 else
3135 {
3136 item = m_host.TaskInventory[InventorySelf()];
2925 } 3137 }
3138 m_host.TaskInventory.LockItemsForRead(false);
2926 3139
2927 if (item.PermsGranter != UUID.Zero) 3140 if (item.PermsGranter != UUID.Zero)
2928 { 3141 {
@@ -2944,13 +3157,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2944 { 3157 {
2945 TaskInventoryItem item; 3158 TaskInventoryItem item;
2946 3159
3160 m_host.TaskInventory.LockItemsForRead(true);
2947 lock (m_host.TaskInventory) 3161 lock (m_host.TaskInventory)
2948 { 3162 {
3163
2949 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3164 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3165 {
3166 m_host.TaskInventory.LockItemsForRead(false);
2950 return; 3167 return;
3168 }
2951 else 3169 else
3170 {
2952 item = m_host.TaskInventory[InventorySelf()]; 3171 item = m_host.TaskInventory[InventorySelf()];
3172 }
2953 } 3173 }
3174 m_host.TaskInventory.LockItemsForRead(false);
2954 3175
2955 m_host.AddScriptLPS(1); 3176 m_host.AddScriptLPS(1);
2956 3177
@@ -2982,19 +3203,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2982 { 3203 {
2983 m_host.AddScriptLPS(1); 3204 m_host.AddScriptLPS(1);
2984 3205
2985// if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
2986// return;
2987
2988 TaskInventoryItem item; 3206 TaskInventoryItem item;
2989 3207
2990 lock (m_host.TaskInventory) 3208 m_host.TaskInventory.LockItemsForRead(true);
3209
3210 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2991 { 3211 {
2992 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3212 m_host.TaskInventory.LockItemsForRead(false);
2993 return; 3213 return;
2994 else 3214 }
2995 item = m_host.TaskInventory[InventorySelf()]; 3215 else
3216 {
3217 item = m_host.TaskInventory[InventorySelf()];
2996 } 3218 }
2997 3219
3220 m_host.TaskInventory.LockItemsForRead(false);
3221
2998 if (item.PermsGranter != m_host.OwnerID) 3222 if (item.PermsGranter != m_host.OwnerID)
2999 return; 3223 return;
3000 3224
@@ -3019,13 +3243,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3019 3243
3020 TaskInventoryItem item; 3244 TaskInventoryItem item;
3021 3245
3022 lock (m_host.TaskInventory) 3246 m_host.TaskInventory.LockItemsForRead(true);
3247
3248 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3023 { 3249 {
3024 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3250 m_host.TaskInventory.LockItemsForRead(false);
3025 return; 3251 return;
3026 else
3027 item = m_host.TaskInventory[InventorySelf()];
3028 } 3252 }
3253 else
3254 {
3255 item = m_host.TaskInventory[InventorySelf()];
3256 }
3257 m_host.TaskInventory.LockItemsForRead(false);
3258
3029 3259
3030 if (item.PermsGranter != m_host.OwnerID) 3260 if (item.PermsGranter != m_host.OwnerID)
3031 return; 3261 return;
@@ -3072,6 +3302,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3072 3302
3073 public void llInstantMessage(string user, string message) 3303 public void llInstantMessage(string user, string message)
3074 { 3304 {
3305 UUID result;
3306 if (!UUID.TryParse(user, out result))
3307 {
3308 ShoutError("An invalid key was passed to llInstantMessage");
3309 ScriptSleep(2000);
3310 return;
3311 }
3312
3313
3075 m_host.AddScriptLPS(1); 3314 m_host.AddScriptLPS(1);
3076 3315
3077 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. 3316 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
@@ -3086,14 +3325,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3086 UUID friendTransactionID = UUID.Random(); 3325 UUID friendTransactionID = UUID.Random();
3087 3326
3088 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); 3327 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
3089 3328
3090 GridInstantMessage msg = new GridInstantMessage(); 3329 GridInstantMessage msg = new GridInstantMessage();
3091 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; 3330 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid;
3092 msg.toAgentID = new Guid(user); // toAgentID.Guid; 3331 msg.toAgentID = new Guid(user); // toAgentID.Guid;
3093 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here 3332 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here
3094// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message); 3333// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message);
3095// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString()); 3334// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString());
3096 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; 3335// DateTime dt = DateTime.UtcNow;
3336//
3337// // Ticks from UtcNow, but make it look like local. Evil, huh?
3338// dt = DateTime.SpecifyKind(dt, DateTimeKind.Local);
3339//
3340// try
3341// {
3342// // Convert that to the PST timezone
3343// TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
3344// dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo);
3345// }
3346// catch
3347// {
3348// // No logging here, as it could be VERY spammy
3349// }
3350//
3351// // And make it look local again to fool the unix time util
3352// dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
3353
3354 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
3355
3097 //if (client != null) 3356 //if (client != null)
3098 //{ 3357 //{
3099 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName; 3358 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
@@ -3107,12 +3366,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3107 msg.message = message.Substring(0, 1024); 3366 msg.message = message.Substring(0, 1024);
3108 else 3367 else
3109 msg.message = message; 3368 msg.message = message;
3110 msg.dialog = (byte)19; // messgage from script ??? // dialog; 3369 msg.dialog = (byte)19; // MessageFromObject
3111 msg.fromGroup = false;// fromGroup; 3370 msg.fromGroup = false;// fromGroup;
3112 msg.offline = (byte)0; //offline; 3371 msg.offline = (byte)0; //offline;
3113 msg.ParentEstateID = 0; //ParentEstateID; 3372 msg.ParentEstateID = World.RegionInfo.EstateSettings.EstateID;
3114 msg.Position = new Vector3(m_host.AbsolutePosition); 3373 msg.Position = new Vector3(m_host.AbsolutePosition);
3115 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; 3374 msg.RegionID = World.RegionInfo.RegionID.Guid;
3116 msg.binaryBucket 3375 msg.binaryBucket
3117 = Util.StringToBytes256( 3376 = Util.StringToBytes256(
3118 "{0}/{1}/{2}/{3}", 3377 "{0}/{1}/{2}/{3}",
@@ -3140,7 +3399,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3140 } 3399 }
3141 3400
3142 emailModule.SendEmail(m_host.UUID, address, subject, message); 3401 emailModule.SendEmail(m_host.UUID, address, subject, message);
3143 ScriptSleep(20000); 3402 ScriptSleep(15000);
3144 } 3403 }
3145 3404
3146 public void llGetNextEmail(string address, string subject) 3405 public void llGetNextEmail(string address, string subject)
@@ -3279,14 +3538,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3279 3538
3280 TaskInventoryItem item; 3539 TaskInventoryItem item;
3281 3540
3282 lock (m_host.TaskInventory) 3541 m_host.TaskInventory.LockItemsForRead(true);
3542 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3283 { 3543 {
3284 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3544 m_host.TaskInventory.LockItemsForRead(false);
3285 return; 3545 return;
3286 else
3287 item = m_host.TaskInventory[InventorySelf()];
3288 } 3546 }
3289 3547 else
3548 {
3549 item = m_host.TaskInventory[InventorySelf()];
3550 }
3551 m_host.TaskInventory.LockItemsForRead(false);
3290 if (item.PermsGranter == UUID.Zero) 3552 if (item.PermsGranter == UUID.Zero)
3291 return; 3553 return;
3292 3554
@@ -3316,13 +3578,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3316 3578
3317 TaskInventoryItem item; 3579 TaskInventoryItem item;
3318 3580
3319 lock (m_host.TaskInventory) 3581 m_host.TaskInventory.LockItemsForRead(true);
3582 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3320 { 3583 {
3321 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3584 m_host.TaskInventory.LockItemsForRead(false);
3322 return; 3585 return;
3323 else
3324 item = m_host.TaskInventory[InventorySelf()];
3325 } 3586 }
3587 else
3588 {
3589 item = m_host.TaskInventory[InventorySelf()];
3590 }
3591 m_host.TaskInventory.LockItemsForRead(false);
3592
3326 3593
3327 if (item.PermsGranter == UUID.Zero) 3594 if (item.PermsGranter == UUID.Zero)
3328 return; 3595 return;
@@ -3389,10 +3656,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3389 3656
3390 TaskInventoryItem item; 3657 TaskInventoryItem item;
3391 3658
3392 lock (m_host.TaskInventory) 3659
3660 m_host.TaskInventory.LockItemsForRead(true);
3661 if (!m_host.TaskInventory.ContainsKey(invItemID))
3662 {
3663 m_host.TaskInventory.LockItemsForRead(false);
3664 return;
3665 }
3666 else
3393 { 3667 {
3394 item = m_host.TaskInventory[invItemID]; 3668 item = m_host.TaskInventory[invItemID];
3395 } 3669 }
3670 m_host.TaskInventory.LockItemsForRead(false);
3396 3671
3397 if (agentID == UUID.Zero || perm == 0) // Releasing permissions 3672 if (agentID == UUID.Zero || perm == 0) // Releasing permissions
3398 { 3673 {
@@ -3420,15 +3695,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3420 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | 3695 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
3421 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3696 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3422 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3697 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3698 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3423 ScriptBaseClass.PERMISSION_ATTACH; 3699 ScriptBaseClass.PERMISSION_ATTACH;
3424 3700
3425 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3701 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3426 { 3702 {
3427 lock (m_host.TaskInventory) 3703 m_host.TaskInventory.LockItemsForWrite(true);
3428 { 3704 m_host.TaskInventory[invItemID].PermsGranter = agentID;
3429 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3705 m_host.TaskInventory[invItemID].PermsMask = perm;
3430 m_host.TaskInventory[invItemID].PermsMask = perm; 3706 m_host.TaskInventory.LockItemsForWrite(false);
3431 }
3432 3707
3433 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3708 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3434 "run_time_permissions", new Object[] { 3709 "run_time_permissions", new Object[] {
@@ -3438,28 +3713,44 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3438 return; 3713 return;
3439 } 3714 }
3440 } 3715 }
3441 else if (m_host.SitTargetAvatar == agentID) // Sitting avatar 3716 else
3442 { 3717 {
3443 // When agent is sitting, certain permissions are implicit if requested from sitting agent 3718 bool sitting = false;
3444 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3719 if (m_host.SitTargetAvatar == agentID)
3445 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3720 {
3446 ScriptBaseClass.PERMISSION_TRACK_CAMERA | 3721 sitting = true;
3447 ScriptBaseClass.PERMISSION_TAKE_CONTROLS; 3722 }
3723 else
3724 {
3725 foreach (SceneObjectPart p in m_host.ParentGroup.Parts)
3726 {
3727 if (p.SitTargetAvatar == agentID)
3728 sitting = true;
3729 }
3730 }
3448 3731
3449 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3732 if (sitting)
3450 { 3733 {
3451 lock (m_host.TaskInventory) 3734 // When agent is sitting, certain permissions are implicit if requested from sitting agent
3735 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3736 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3737 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3738 ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
3739
3740 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3452 { 3741 {
3742 m_host.TaskInventory.LockItemsForWrite(true);
3453 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3743 m_host.TaskInventory[invItemID].PermsGranter = agentID;
3454 m_host.TaskInventory[invItemID].PermsMask = perm; 3744 m_host.TaskInventory[invItemID].PermsMask = perm;
3455 } 3745 m_host.TaskInventory.LockItemsForWrite(false);
3456 3746
3457 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3747 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3458 "run_time_permissions", new Object[] { 3748 "run_time_permissions", new Object[] {
3459 new LSL_Integer(perm) }, 3749 new LSL_Integer(perm) },
3460 new DetectParams[0])); 3750 new DetectParams[0]));
3461 3751
3462 return; 3752 return;
3753 }
3463 } 3754 }
3464 } 3755 }
3465 3756
@@ -3473,11 +3764,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3473 3764
3474 if (!m_waitingForScriptAnswer) 3765 if (!m_waitingForScriptAnswer)
3475 { 3766 {
3476 lock (m_host.TaskInventory) 3767 m_host.TaskInventory.LockItemsForWrite(true);
3477 { 3768 m_host.TaskInventory[invItemID].PermsGranter = agentID;
3478 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3769 m_host.TaskInventory[invItemID].PermsMask = 0;
3479 m_host.TaskInventory[invItemID].PermsMask = 0; 3770 m_host.TaskInventory.LockItemsForWrite(false);
3480 }
3481 3771
3482 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; 3772 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
3483 m_waitingForScriptAnswer=true; 3773 m_waitingForScriptAnswer=true;
@@ -3512,10 +3802,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3512 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) 3802 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
3513 llReleaseControls(); 3803 llReleaseControls();
3514 3804
3515 lock (m_host.TaskInventory) 3805
3516 { 3806 m_host.TaskInventory.LockItemsForWrite(true);
3517 m_host.TaskInventory[invItemID].PermsMask = answer; 3807 m_host.TaskInventory[invItemID].PermsMask = answer;
3518 } 3808 m_host.TaskInventory.LockItemsForWrite(false);
3809
3519 3810
3520 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3811 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3521 "run_time_permissions", new Object[] { 3812 "run_time_permissions", new Object[] {
@@ -3527,16 +3818,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3527 { 3818 {
3528 m_host.AddScriptLPS(1); 3819 m_host.AddScriptLPS(1);
3529 3820
3530 lock (m_host.TaskInventory) 3821 m_host.TaskInventory.LockItemsForRead(true);
3822
3823 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3531 { 3824 {
3532 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 3825 if (item.Type == 10 && item.ItemID == m_itemID)
3533 { 3826 {
3534 if (item.Type == 10 && item.ItemID == m_itemID) 3827 m_host.TaskInventory.LockItemsForRead(false);
3535 { 3828 return item.PermsGranter.ToString();
3536 return item.PermsGranter.ToString();
3537 }
3538 } 3829 }
3539 } 3830 }
3831 m_host.TaskInventory.LockItemsForRead(false);
3540 3832
3541 return UUID.Zero.ToString(); 3833 return UUID.Zero.ToString();
3542 } 3834 }
@@ -3545,19 +3837,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3545 { 3837 {
3546 m_host.AddScriptLPS(1); 3838 m_host.AddScriptLPS(1);
3547 3839
3548 lock (m_host.TaskInventory) 3840 m_host.TaskInventory.LockItemsForRead(true);
3841
3842 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3549 { 3843 {
3550 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 3844 if (item.Type == 10 && item.ItemID == m_itemID)
3551 { 3845 {
3552 if (item.Type == 10 && item.ItemID == m_itemID) 3846 int perms = item.PermsMask;
3553 { 3847 if (m_automaticLinkPermission)
3554 int perms = item.PermsMask; 3848 perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS;
3555 if (m_automaticLinkPermission) 3849 m_host.TaskInventory.LockItemsForRead(false);
3556 perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS; 3850 return perms;
3557 return perms;
3558 }
3559 } 3851 }
3560 } 3852 }
3853 m_host.TaskInventory.LockItemsForRead(false);
3561 3854
3562 return 0; 3855 return 0;
3563 } 3856 }
@@ -3579,9 +3872,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3579 public void llSetLinkColor(int linknumber, LSL_Vector color, int face) 3872 public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
3580 { 3873 {
3581 List<SceneObjectPart> parts = GetLinkParts(linknumber); 3874 List<SceneObjectPart> parts = GetLinkParts(linknumber);
3582 3875 if (parts.Count > 0)
3583 foreach (SceneObjectPart part in parts) 3876 {
3584 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); 3877 try
3878 {
3879 parts[0].ParentGroup.areUpdatesSuspended = true;
3880 foreach (SceneObjectPart part in parts)
3881 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face);
3882 }
3883 finally
3884 {
3885 parts[0].ParentGroup.areUpdatesSuspended = false;
3886 }
3887 }
3585 } 3888 }
3586 3889
3587 public void llCreateLink(string target, int parent) 3890 public void llCreateLink(string target, int parent)
@@ -3594,11 +3897,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3594 return; 3897 return;
3595 3898
3596 TaskInventoryItem item; 3899 TaskInventoryItem item;
3597 lock (m_host.TaskInventory) 3900 m_host.TaskInventory.LockItemsForRead(true);
3598 { 3901 item = m_host.TaskInventory[invItemID];
3599 item = m_host.TaskInventory[invItemID]; 3902 m_host.TaskInventory.LockItemsForRead(false);
3600 } 3903
3601
3602 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 3904 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
3603 && !m_automaticLinkPermission) 3905 && !m_automaticLinkPermission)
3604 { 3906 {
@@ -3615,11 +3917,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3615 3917
3616 if (targetPart.ParentGroup.AttachmentPoint != 0) 3918 if (targetPart.ParentGroup.AttachmentPoint != 0)
3617 return; // Fail silently if attached 3919 return; // Fail silently if attached
3920
3921 if (targetPart.ParentGroup.RootPart.OwnerID != m_host.ParentGroup.RootPart.OwnerID)
3922 return;
3923
3618 SceneObjectGroup parentPrim = null, childPrim = null; 3924 SceneObjectGroup parentPrim = null, childPrim = null;
3619 3925
3620 if (targetPart != null) 3926 if (targetPart != null)
3621 { 3927 {
3622 if (parent != 0) { 3928 if (parent != 0)
3929 {
3623 parentPrim = m_host.ParentGroup; 3930 parentPrim = m_host.ParentGroup;
3624 childPrim = targetPart.ParentGroup; 3931 childPrim = targetPart.ParentGroup;
3625 } 3932 }
@@ -3650,16 +3957,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3650 m_host.AddScriptLPS(1); 3957 m_host.AddScriptLPS(1);
3651 UUID invItemID = InventorySelf(); 3958 UUID invItemID = InventorySelf();
3652 3959
3653 lock (m_host.TaskInventory) 3960 m_host.TaskInventory.LockItemsForRead(true);
3654 {
3655 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 3961 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
3656 && !m_automaticLinkPermission) 3962 && !m_automaticLinkPermission)
3657 { 3963 {
3658 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!"); 3964 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
3965 m_host.TaskInventory.LockItemsForRead(false);
3659 return; 3966 return;
3660 } 3967 }
3661 } 3968 m_host.TaskInventory.LockItemsForRead(false);
3662 3969
3663 if (linknum < ScriptBaseClass.LINK_THIS) 3970 if (linknum < ScriptBaseClass.LINK_THIS)
3664 return; 3971 return;
3665 3972
@@ -3698,10 +4005,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3698 // Restructuring Multiple Prims. 4005 // Restructuring Multiple Prims.
3699 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts); 4006 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
3700 parts.Remove(parentPrim.RootPart); 4007 parts.Remove(parentPrim.RootPart);
3701 foreach (SceneObjectPart part in parts) 4008 if (parts.Count > 0)
3702 { 4009 {
3703 parentPrim.DelinkFromGroup(part.LocalId, true); 4010 try
4011 {
4012 parts[0].ParentGroup.areUpdatesSuspended = true;
4013 foreach (SceneObjectPart part in parts)
4014 {
4015 parentPrim.DelinkFromGroup(part.LocalId, true);
4016 }
4017 }
4018 finally
4019 {
4020 parts[0].ParentGroup.areUpdatesSuspended = false;
4021 }
3704 } 4022 }
4023
3705 parentPrim.HasGroupChanged = true; 4024 parentPrim.HasGroupChanged = true;
3706 parentPrim.ScheduleGroupForFullUpdate(); 4025 parentPrim.ScheduleGroupForFullUpdate();
3707 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 4026 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
@@ -3710,12 +4029,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3710 { 4029 {
3711 SceneObjectPart newRoot = parts[0]; 4030 SceneObjectPart newRoot = parts[0];
3712 parts.Remove(newRoot); 4031 parts.Remove(newRoot);
3713 foreach (SceneObjectPart part in parts) 4032
4033 try
3714 { 4034 {
3715 // Required for linking 4035 parts[0].ParentGroup.areUpdatesSuspended = true;
3716 part.ClearUpdateSchedule(); 4036 foreach (SceneObjectPart part in parts)
3717 newRoot.ParentGroup.LinkToGroup(part.ParentGroup); 4037 {
4038 part.ClearUpdateSchedule();
4039 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
4040 }
3718 } 4041 }
4042 finally
4043 {
4044 parts[0].ParentGroup.areUpdatesSuspended = false;
4045 }
4046
4047
3719 newRoot.ParentGroup.HasGroupChanged = true; 4048 newRoot.ParentGroup.HasGroupChanged = true;
3720 newRoot.ParentGroup.ScheduleGroupForFullUpdate(); 4049 newRoot.ParentGroup.ScheduleGroupForFullUpdate();
3721 } 4050 }
@@ -3735,6 +4064,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3735 public void llBreakAllLinks() 4064 public void llBreakAllLinks()
3736 { 4065 {
3737 m_host.AddScriptLPS(1); 4066 m_host.AddScriptLPS(1);
4067
4068 UUID invItemID = InventorySelf();
4069
4070 TaskInventoryItem item;
4071 m_host.TaskInventory.LockItemsForRead(true);
4072 item = m_host.TaskInventory[invItemID];
4073 m_host.TaskInventory.LockItemsForRead(false);
4074
4075 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4076 && !m_automaticLinkPermission)
4077 {
4078 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
4079 return;
4080 }
4081
3738 SceneObjectGroup parentPrim = m_host.ParentGroup; 4082 SceneObjectGroup parentPrim = m_host.ParentGroup;
3739 if (parentPrim.AttachmentPoint != 0) 4083 if (parentPrim.AttachmentPoint != 0)
3740 return; // Fail silently if attached 4084 return; // Fail silently if attached
@@ -3754,25 +4098,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3754 public LSL_String llGetLinkKey(int linknum) 4098 public LSL_String llGetLinkKey(int linknum)
3755 { 4099 {
3756 m_host.AddScriptLPS(1); 4100 m_host.AddScriptLPS(1);
3757 List<UUID> keytable = new List<UUID>();
3758 // parse for sitting avatare-uuids
3759 World.ForEachRootScenePresence(delegate(ScenePresence presence)
3760 {
3761 if (presence.ParentID != 0 && m_host.ParentGroup.HasChildPrim(presence.ParentID))
3762 keytable.Add(presence.UUID);
3763 });
3764
3765 int totalprims = m_host.ParentGroup.PrimCount + keytable.Count;
3766 if (linknum > m_host.ParentGroup.PrimCount && linknum <= totalprims)
3767 {
3768 return keytable[totalprims - linknum].ToString();
3769 }
3770
3771 if (linknum == 1 && m_host.ParentGroup.PrimCount == 1 && keytable.Count == 1)
3772 {
3773 return m_host.UUID.ToString();
3774 }
3775
3776 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum); 4101 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
3777 if (part != null) 4102 if (part != null)
3778 { 4103 {
@@ -3780,6 +4105,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3780 } 4105 }
3781 else 4106 else
3782 { 4107 {
4108 if (linknum > m_host.ParentGroup.PrimCount || (linknum == 1 && m_host.ParentGroup.PrimCount == 1))
4109 {
4110 linknum -= (m_host.ParentGroup.PrimCount) + 1;
4111
4112 if (linknum < 0)
4113 return UUID.Zero.ToString();
4114
4115 List<ScenePresence> avatars = GetLinkAvatars(ScriptBaseClass.LINK_SET);
4116 if (avatars.Count > linknum)
4117 {
4118 return avatars[linknum].UUID.ToString();
4119 }
4120 }
3783 return UUID.Zero.ToString(); 4121 return UUID.Zero.ToString();
3784 } 4122 }
3785 } 4123 }
@@ -3878,17 +4216,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3878 m_host.AddScriptLPS(1); 4216 m_host.AddScriptLPS(1);
3879 int count = 0; 4217 int count = 0;
3880 4218
3881 lock (m_host.TaskInventory) 4219 m_host.TaskInventory.LockItemsForRead(true);
4220 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3882 { 4221 {
3883 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4222 if (inv.Value.Type == type || type == -1)
3884 { 4223 {
3885 if (inv.Value.Type == type || type == -1) 4224 count = count + 1;
3886 {
3887 count = count + 1;
3888 }
3889 } 4225 }
3890 } 4226 }
3891 4227
4228 m_host.TaskInventory.LockItemsForRead(false);
3892 return count; 4229 return count;
3893 } 4230 }
3894 4231
@@ -3897,16 +4234,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3897 m_host.AddScriptLPS(1); 4234 m_host.AddScriptLPS(1);
3898 ArrayList keys = new ArrayList(); 4235 ArrayList keys = new ArrayList();
3899 4236
3900 lock (m_host.TaskInventory) 4237 m_host.TaskInventory.LockItemsForRead(true);
4238 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3901 { 4239 {
3902 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4240 if (inv.Value.Type == type || type == -1)
3903 { 4241 {
3904 if (inv.Value.Type == type || type == -1) 4242 keys.Add(inv.Value.Name);
3905 {
3906 keys.Add(inv.Value.Name);
3907 }
3908 } 4243 }
3909 } 4244 }
4245 m_host.TaskInventory.LockItemsForRead(false);
3910 4246
3911 if (keys.Count == 0) 4247 if (keys.Count == 0)
3912 { 4248 {
@@ -3943,25 +4279,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3943 } 4279 }
3944 4280
3945 // move the first object found with this inventory name 4281 // move the first object found with this inventory name
3946 lock (m_host.TaskInventory) 4282 m_host.TaskInventory.LockItemsForRead(true);
4283 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3947 { 4284 {
3948 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4285 if (inv.Value.Name == inventory)
3949 { 4286 {
3950 if (inv.Value.Name == inventory) 4287 found = true;
3951 { 4288 objId = inv.Key;
3952 found = true; 4289 assetType = inv.Value.Type;
3953 objId = inv.Key; 4290 objName = inv.Value.Name;
3954 assetType = inv.Value.Type; 4291 break;
3955 objName = inv.Value.Name;
3956 break;
3957 }
3958 } 4292 }
3959 } 4293 }
4294 m_host.TaskInventory.LockItemsForRead(false);
3960 4295
3961 if (!found) 4296 if (!found)
3962 { 4297 {
3963 llSay(0, String.Format("Could not find object '{0}'", inventory)); 4298 llSay(0, String.Format("Could not find object '{0}'", inventory));
3964 throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory)); 4299 return;
4300// throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
3965 } 4301 }
3966 4302
3967 // check if destination is an object 4303 // check if destination is an object
@@ -3987,48 +4323,68 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3987 return; 4323 return;
3988 } 4324 }
3989 } 4325 }
4326
3990 // destination is an avatar 4327 // destination is an avatar
3991 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId); 4328 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId);
3992 4329
3993 if (agentItem == null) 4330 if (agentItem == null)
3994 return; 4331 return;
3995 4332
3996 byte[] bucket = new byte[17]; 4333 byte[] bucket = new byte[1];
3997 bucket[0] = (byte)assetType; 4334 bucket[0] = (byte)assetType;
3998 byte[] objBytes = agentItem.ID.GetBytes(); 4335 //byte[] objBytes = agentItem.ID.GetBytes();
3999 Array.Copy(objBytes, 0, bucket, 1, 16); 4336 //Array.Copy(objBytes, 0, bucket, 1, 16);
4000 4337
4001 GridInstantMessage msg = new GridInstantMessage(World, 4338 GridInstantMessage msg = new GridInstantMessage(World,
4002 m_host.UUID, m_host.Name+", an object owned by "+ 4339 m_host.OwnerID, m_host.Name, destId,
4003 resolveName(m_host.OwnerID)+",", destId,
4004 (byte)InstantMessageDialog.TaskInventoryOffered, 4340 (byte)InstantMessageDialog.TaskInventoryOffered,
4005 false, objName+"\n"+m_host.Name+" is located at "+ 4341 false, objName+". "+m_host.Name+" is located at "+
4006 World.RegionInfo.RegionName+" "+ 4342 World.RegionInfo.RegionName+" "+
4007 m_host.AbsolutePosition.ToString(), 4343 m_host.AbsolutePosition.ToString(),
4008 agentItem.ID, true, m_host.AbsolutePosition, 4344 agentItem.ID, true, m_host.AbsolutePosition,
4009 bucket); 4345 bucket);
4010 if (m_TransferModule != null) 4346
4011 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 4347 ScenePresence sp;
4348
4349 if (World.TryGetScenePresence(destId, out sp))
4350 {
4351 sp.ControllingClient.SendInstantMessage(msg);
4352 }
4353 else
4354 {
4355 if (m_TransferModule != null)
4356 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
4357 }
4358
4359 //This delay should only occur when giving inventory to avatars.
4012 ScriptSleep(3000); 4360 ScriptSleep(3000);
4013 } 4361 }
4014 } 4362 }
4015 4363
4364 [DebuggerNonUserCode]
4016 public void llRemoveInventory(string name) 4365 public void llRemoveInventory(string name)
4017 { 4366 {
4018 m_host.AddScriptLPS(1); 4367 m_host.AddScriptLPS(1);
4019 4368
4020 lock (m_host.TaskInventory) 4369 List<TaskInventoryItem> inv;
4370 try
4021 { 4371 {
4022 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4372 m_host.TaskInventory.LockItemsForRead(true);
4373 inv = new List<TaskInventoryItem>(m_host.TaskInventory.Values);
4374 }
4375 finally
4376 {
4377 m_host.TaskInventory.LockItemsForRead(false);
4378 }
4379 foreach (TaskInventoryItem item in inv)
4380 {
4381 if (item.Name == name)
4023 { 4382 {
4024 if (item.Name == name) 4383 if (item.ItemID == m_itemID)
4025 { 4384 throw new ScriptDeleteException();
4026 if (item.ItemID == m_itemID) 4385 else
4027 throw new ScriptDeleteException(); 4386 m_host.Inventory.RemoveInventoryItem(item.ItemID);
4028 else 4387 return;
4029 m_host.Inventory.RemoveInventoryItem(item.ItemID);
4030 return;
4031 }
4032 } 4388 }
4033 } 4389 }
4034 } 4390 }
@@ -4063,112 +4419,122 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4063 { 4419 {
4064 m_host.AddScriptLPS(1); 4420 m_host.AddScriptLPS(1);
4065 4421
4066 UUID uuid = (UUID)id; 4422 UUID uuid;
4067 PresenceInfo pinfo = null; 4423 if (UUID.TryParse(id, out uuid))
4068 UserAccount account;
4069
4070 UserInfoCacheEntry ce;
4071 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4072 { 4424 {
4073 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); 4425 PresenceInfo pinfo = null;
4074 if (account == null) 4426 UserAccount account;
4427
4428 UserInfoCacheEntry ce;
4429 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4075 { 4430 {
4076 m_userInfoCache[uuid] = null; // Cache negative 4431 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
4077 return UUID.Zero.ToString(); 4432 if (account == null)
4078 } 4433 {
4434 m_userInfoCache[uuid] = null; // Cache negative
4435 return UUID.Zero.ToString();
4436 }
4079 4437
4080 4438
4081 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); 4439 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4082 if (pinfos != null && pinfos.Length > 0) 4440 if (pinfos != null && pinfos.Length > 0)
4083 {
4084 foreach (PresenceInfo p in pinfos)
4085 { 4441 {
4086 if (p.RegionID != UUID.Zero) 4442 foreach (PresenceInfo p in pinfos)
4087 { 4443 {
4088 pinfo = p; 4444 if (p.RegionID != UUID.Zero)
4445 {
4446 pinfo = p;
4447 }
4089 } 4448 }
4090 } 4449 }
4091 }
4092 4450
4093 ce = new UserInfoCacheEntry(); 4451 ce = new UserInfoCacheEntry();
4094 ce.time = Util.EnvironmentTickCount(); 4452 ce.time = Util.EnvironmentTickCount();
4095 ce.account = account; 4453 ce.account = account;
4096 ce.pinfo = pinfo; 4454 ce.pinfo = pinfo;
4097 } 4455 m_userInfoCache[uuid] = ce;
4098 else 4456 }
4099 { 4457 else
4100 if (ce == null) 4458 {
4101 return UUID.Zero.ToString(); 4459 if (ce == null)
4460 return UUID.Zero.ToString();
4102 4461
4103 account = ce.account; 4462 account = ce.account;
4104 pinfo = ce.pinfo; 4463 pinfo = ce.pinfo;
4105 } 4464 }
4106 4465
4107 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000) 4466 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000)
4108 {
4109 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4110 if (pinfos != null && pinfos.Length > 0)
4111 { 4467 {
4112 foreach (PresenceInfo p in pinfos) 4468 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4469 if (pinfos != null && pinfos.Length > 0)
4113 { 4470 {
4114 if (p.RegionID != UUID.Zero) 4471 foreach (PresenceInfo p in pinfos)
4115 { 4472 {
4116 pinfo = p; 4473 if (p.RegionID != UUID.Zero)
4474 {
4475 pinfo = p;
4476 }
4117 } 4477 }
4118 } 4478 }
4119 } 4479 else
4120 else 4480 pinfo = null;
4121 pinfo = null;
4122 4481
4123 ce.time = Util.EnvironmentTickCount(); 4482 ce.time = Util.EnvironmentTickCount();
4124 ce.pinfo = pinfo; 4483 ce.pinfo = pinfo;
4125 } 4484 }
4126 4485
4127 string reply = String.Empty; 4486 string reply = String.Empty;
4128 4487
4129 switch (data) 4488 switch (data)
4130 { 4489 {
4131 case 1: // DATA_ONLINE (0|1) 4490 case 1: // DATA_ONLINE (0|1)
4132 if (pinfo != null && pinfo.RegionID != UUID.Zero) 4491 if (pinfo != null && pinfo.RegionID != UUID.Zero)
4133 reply = "1"; 4492 reply = "1";
4134 else 4493 else
4135 reply = "0"; 4494 reply = "0";
4136 break; 4495 break;
4137 case 2: // DATA_NAME (First Last) 4496 case 2: // DATA_NAME (First Last)
4138 reply = account.FirstName + " " + account.LastName; 4497 reply = account.FirstName + " " + account.LastName;
4139 break; 4498 break;
4140 case 3: // DATA_BORN (YYYY-MM-DD) 4499 case 3: // DATA_BORN (YYYY-MM-DD)
4141 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); 4500 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
4142 born = born.AddSeconds(account.Created); 4501 born = born.AddSeconds(account.Created);
4143 reply = born.ToString("yyyy-MM-dd"); 4502 reply = born.ToString("yyyy-MM-dd");
4144 break; 4503 break;
4145 case 4: // DATA_RATING (0,0,0,0,0,0) 4504 case 4: // DATA_RATING (0,0,0,0,0,0)
4146 reply = "0,0,0,0,0,0"; 4505 reply = "0,0,0,0,0,0";
4147 break; 4506 break;
4148 case 8: // DATA_PAYINFO (0|1|2|3) 4507 case 8: // DATA_PAYINFO (0|1|2|3)
4149 reply = "0"; 4508 reply = "0";
4150 break; 4509 break;
4151 default: 4510 default:
4152 return UUID.Zero.ToString(); // Raise no event 4511 return UUID.Zero.ToString(); // Raise no event
4153 } 4512 }
4154 4513
4155 UUID rq = UUID.Random(); 4514 UUID rq = UUID.Random();
4156 4515
4157 UUID tid = AsyncCommands. 4516 UUID tid = AsyncCommands.
4158 DataserverPlugin.RegisterRequest(m_localID, 4517 DataserverPlugin.RegisterRequest(m_localID,
4159 m_itemID, rq.ToString()); 4518 m_itemID, rq.ToString());
4160 4519
4161 AsyncCommands. 4520 AsyncCommands.
4162 DataserverPlugin.DataserverReply(rq.ToString(), reply); 4521 DataserverPlugin.DataserverReply(rq.ToString(), reply);
4163 4522
4164 ScriptSleep(100); 4523 ScriptSleep(100);
4165 return tid.ToString(); 4524 return tid.ToString();
4525 }
4526 else
4527 {
4528 ShoutError("Invalid UUID passed to llRequestAgentData.");
4529 }
4530 return "";
4166 } 4531 }
4167 4532
4168 public LSL_String llRequestInventoryData(string name) 4533 public LSL_String llRequestInventoryData(string name)
4169 { 4534 {
4170 m_host.AddScriptLPS(1); 4535 m_host.AddScriptLPS(1);
4171 4536
4537 //Clone is thread safe
4172 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 4538 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
4173 4539
4174 foreach (TaskInventoryItem item in itemDictionary.Values) 4540 foreach (TaskInventoryItem item in itemDictionary.Values)
@@ -4222,6 +4588,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4222 ScenePresence presence = World.GetScenePresence(agentId); 4588 ScenePresence presence = World.GetScenePresence(agentId);
4223 if (presence != null) 4589 if (presence != null)
4224 { 4590 {
4591 // agent must not be a god
4592 if (presence.UserLevel >= 200) return;
4593
4225 // agent must be over the owners land 4594 // agent must be over the owners land
4226 if (m_host.OwnerID == World.LandChannel.GetLandObject( 4595 if (m_host.OwnerID == World.LandChannel.GetLandObject(
4227 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) 4596 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
@@ -4244,7 +4613,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4244 UUID av = new UUID(); 4613 UUID av = new UUID();
4245 if (!UUID.TryParse(agent,out av)) 4614 if (!UUID.TryParse(agent,out av))
4246 { 4615 {
4247 LSLError("First parameter to llDialog needs to be a key"); 4616 //LSLError("First parameter to llDialog needs to be a key");
4248 return; 4617 return;
4249 } 4618 }
4250 4619
@@ -4281,17 +4650,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4281 UUID soundId = UUID.Zero; 4650 UUID soundId = UUID.Zero;
4282 if (!UUID.TryParse(impact_sound, out soundId)) 4651 if (!UUID.TryParse(impact_sound, out soundId))
4283 { 4652 {
4284 lock (m_host.TaskInventory) 4653 m_host.TaskInventory.LockItemsForRead(true);
4654 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
4285 { 4655 {
4286 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4656 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound)
4287 { 4657 {
4288 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound) 4658 soundId = item.AssetID;
4289 { 4659 break;
4290 soundId = item.AssetID;
4291 break;
4292 }
4293 } 4660 }
4294 } 4661 }
4662 m_host.TaskInventory.LockItemsForRead(false);
4295 } 4663 }
4296 m_host.CollisionSound = soundId; 4664 m_host.CollisionSound = soundId;
4297 m_host.CollisionSoundVolume = (float)impact_volume; 4665 m_host.CollisionSoundVolume = (float)impact_volume;
@@ -4331,6 +4699,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4331 UUID partItemID; 4699 UUID partItemID;
4332 foreach (SceneObjectPart part in parts) 4700 foreach (SceneObjectPart part in parts)
4333 { 4701 {
4702 //Clone is thread safe
4334 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); 4703 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
4335 4704
4336 foreach (TaskInventoryItem item in itemsDictionary.Values) 4705 foreach (TaskInventoryItem item in itemsDictionary.Values)
@@ -4545,17 +4914,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4545 4914
4546 m_host.AddScriptLPS(1); 4915 m_host.AddScriptLPS(1);
4547 4916
4548 lock (m_host.TaskInventory) 4917 m_host.TaskInventory.LockItemsForRead(true);
4918 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
4549 { 4919 {
4550 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4920 if (item.Type == 10 && item.ItemID == m_itemID)
4551 { 4921 {
4552 if (item.Type == 10 && item.ItemID == m_itemID) 4922 result = item.Name!=null?item.Name:String.Empty;
4553 { 4923 break;
4554 result = item.Name != null ? item.Name : String.Empty;
4555 break;
4556 }
4557 } 4924 }
4558 } 4925 }
4926 m_host.TaskInventory.LockItemsForRead(false);
4559 4927
4560 return result; 4928 return result;
4561 } 4929 }
@@ -4728,23 +5096,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4728 { 5096 {
4729 m_host.AddScriptLPS(1); 5097 m_host.AddScriptLPS(1);
4730 5098
4731 lock (m_host.TaskInventory) 5099 m_host.TaskInventory.LockItemsForRead(true);
5100 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
4732 { 5101 {
4733 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 5102 if (inv.Value.Name == name)
4734 { 5103 {
4735 if (inv.Value.Name == name) 5104 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
4736 { 5105 {
4737 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) 5106 m_host.TaskInventory.LockItemsForRead(false);
4738 { 5107 return inv.Value.AssetID.ToString();
4739 return inv.Value.AssetID.ToString(); 5108 }
4740 } 5109 else
4741 else 5110 {
4742 { 5111 m_host.TaskInventory.LockItemsForRead(false);
4743 return UUID.Zero.ToString(); 5112 return UUID.Zero.ToString();
4744 }
4745 } 5113 }
4746 } 5114 }
4747 } 5115 }
5116 m_host.TaskInventory.LockItemsForRead(false);
4748 5117
4749 return UUID.Zero.ToString(); 5118 return UUID.Zero.ToString();
4750 } 5119 }
@@ -4897,14 +5266,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4897 { 5266 {
4898 m_host.AddScriptLPS(1); 5267 m_host.AddScriptLPS(1);
4899 5268
4900 if (src == null) 5269 return src.Length;
4901 {
4902 return 0;
4903 }
4904 else
4905 {
4906 return src.Length;
4907 }
4908 } 5270 }
4909 5271
4910 public LSL_Integer llList2Integer(LSL_List src, int index) 5272 public LSL_Integer llList2Integer(LSL_List src, int index)
@@ -4950,7 +5312,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4950 else if (src.Data[index] is LSL_Float) 5312 else if (src.Data[index] is LSL_Float)
4951 return Convert.ToDouble(((LSL_Float) src.Data[index]).value); 5313 return Convert.ToDouble(((LSL_Float) src.Data[index]).value);
4952 else if (src.Data[index] is LSL_String) 5314 else if (src.Data[index] is LSL_String)
4953 return Convert.ToDouble(((LSL_String) src.Data[index]).m_string); 5315 {
5316 string str = ((LSL_String) src.Data[index]).m_string;
5317 Match m = Regex.Match(str, "^\\s*(-?\\+?[,0-9]+\\.?[0-9]*)");
5318 if (m != Match.Empty)
5319 {
5320 str = m.Value;
5321 double d = 0.0;
5322 if (!Double.TryParse(str, out d))
5323 return 0.0;
5324
5325 return d;
5326 }
5327 return 0.0;
5328 }
4954 return Convert.ToDouble(src.Data[index]); 5329 return Convert.ToDouble(src.Data[index]);
4955 } 5330 }
4956 catch (FormatException) 5331 catch (FormatException)
@@ -5223,7 +5598,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5223 } 5598 }
5224 } 5599 }
5225 } 5600 }
5226 else { 5601 else
5602 {
5227 object[] array = new object[src.Length]; 5603 object[] array = new object[src.Length];
5228 Array.Copy(src.Data, 0, array, 0, src.Length); 5604 Array.Copy(src.Data, 0, array, 0, src.Length);
5229 result = new LSL_List(array); 5605 result = new LSL_List(array);
@@ -5672,10 +6048,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5672 m_host.AddScriptLPS(1); 6048 m_host.AddScriptLPS(1);
5673 6049
5674 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6050 List<SceneObjectPart> parts = GetLinkParts(linknumber);
5675 6051 if (parts.Count > 0)
5676 foreach (var part in parts)
5677 { 6052 {
5678 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); 6053 try
6054 {
6055 parts[0].ParentGroup.areUpdatesSuspended = true;
6056 foreach (var part in parts)
6057 {
6058 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6059 }
6060 }
6061 finally
6062 {
6063 parts[0].ParentGroup.areUpdatesSuspended = false;
6064 }
5679 } 6065 }
5680 } 6066 }
5681 6067
@@ -5729,6 +6115,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5729 ScriptSleep(5000); 6115 ScriptSleep(5000);
5730 } 6116 }
5731 6117
6118 public LSL_List llParseString2List(string str, LSL_List separators, LSL_List in_spacers)
6119 {
6120 return ParseString2List(str, separators, in_spacers, false);
6121 }
6122
5732 public LSL_Integer llOverMyLand(string id) 6123 public LSL_Integer llOverMyLand(string id)
5733 { 6124 {
5734 m_host.AddScriptLPS(1); 6125 m_host.AddScriptLPS(1);
@@ -5793,8 +6184,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5793 UUID agentId = new UUID(); 6184 UUID agentId = new UUID();
5794 if (!UUID.TryParse(agent, out agentId)) 6185 if (!UUID.TryParse(agent, out agentId))
5795 return new LSL_Integer(0); 6186 return new LSL_Integer(0);
6187 if (agentId == m_host.GroupID)
6188 return new LSL_Integer(1);
5796 ScenePresence presence = World.GetScenePresence(agentId); 6189 ScenePresence presence = World.GetScenePresence(agentId);
5797 if (presence == null || presence.IsChildAgent) // Return flase for child agents 6190 if (presence == null || presence.IsChildAgent) // Return false for child agents
5798 return new LSL_Integer(0); 6191 return new LSL_Integer(0);
5799 IClientAPI client = presence.ControllingClient; 6192 IClientAPI client = presence.ControllingClient;
5800 if (m_host.GroupID == client.ActiveGroupId) 6193 if (m_host.GroupID == client.ActiveGroupId)
@@ -5929,7 +6322,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5929 return m_host.ParentGroup.AttachmentPoint; 6322 return m_host.ParentGroup.AttachmentPoint;
5930 } 6323 }
5931 6324
5932 public LSL_Integer llGetFreeMemory() 6325 public virtual LSL_Integer llGetFreeMemory()
5933 { 6326 {
5934 m_host.AddScriptLPS(1); 6327 m_host.AddScriptLPS(1);
5935 // Make scripts designed for LSO happy 6328 // Make scripts designed for LSO happy
@@ -6046,7 +6439,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6046 SetParticleSystem(m_host, rules); 6439 SetParticleSystem(m_host, rules);
6047 } 6440 }
6048 6441
6049 private void SetParticleSystem(SceneObjectPart part, LSL_List rules) { 6442 private void SetParticleSystem(SceneObjectPart part, LSL_List rules)
6443 {
6050 6444
6051 6445
6052 if (rules.Length == 0) 6446 if (rules.Length == 0)
@@ -6240,14 +6634,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6240 6634
6241 protected UUID GetTaskInventoryItem(string name) 6635 protected UUID GetTaskInventoryItem(string name)
6242 { 6636 {
6243 lock (m_host.TaskInventory) 6637 m_host.TaskInventory.LockItemsForRead(true);
6638 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6244 { 6639 {
6245 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 6640 if (inv.Value.Name == name)
6246 { 6641 {
6247 if (inv.Value.Name == name) 6642 m_host.TaskInventory.LockItemsForRead(false);
6248 return inv.Key; 6643 return inv.Key;
6249 } 6644 }
6250 } 6645 }
6646 m_host.TaskInventory.LockItemsForRead(false);
6251 6647
6252 return UUID.Zero; 6648 return UUID.Zero;
6253 } 6649 }
@@ -6285,16 +6681,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6285 if (folderID == UUID.Zero) 6681 if (folderID == UUID.Zero)
6286 return; 6682 return;
6287 6683
6288 byte[] bucket = new byte[17]; 6684 byte[] bucket = new byte[1];
6289 bucket[0] = (byte)AssetType.Folder; 6685 bucket[0] = (byte)AssetType.Folder;
6290 byte[] objBytes = folderID.GetBytes(); 6686 //byte[] objBytes = folderID.GetBytes();
6291 Array.Copy(objBytes, 0, bucket, 1, 16); 6687 //Array.Copy(objBytes, 0, bucket, 1, 16);
6292 6688
6293 GridInstantMessage msg = new GridInstantMessage(World, 6689 GridInstantMessage msg = new GridInstantMessage(World,
6294 m_host.UUID, m_host.Name+", an object owned by "+ 6690 m_host.OwnerID, m_host.Name, destID,
6295 resolveName(m_host.OwnerID)+",", destID, 6691 (byte)InstantMessageDialog.TaskInventoryOffered,
6296 (byte)InstantMessageDialog.InventoryOffered, 6692 false, category+". "+m_host.Name+" is located at "+
6297 false, category+"\n"+m_host.Name+" is located at "+
6298 World.RegionInfo.RegionName+" "+ 6693 World.RegionInfo.RegionName+" "+
6299 m_host.AbsolutePosition.ToString(), 6694 m_host.AbsolutePosition.ToString(),
6300 folderID, true, m_host.AbsolutePosition, 6695 folderID, true, m_host.AbsolutePosition,
@@ -6497,13 +6892,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6497 UUID av = new UUID(); 6892 UUID av = new UUID();
6498 if (!UUID.TryParse(avatar,out av)) 6893 if (!UUID.TryParse(avatar,out av))
6499 { 6894 {
6500 LSLError("First parameter to llDialog needs to be a key"); 6895 //LSLError("First parameter to llDialog needs to be a key");
6501 return; 6896 return;
6502 } 6897 }
6503 if (buttons.Length < 1) 6898 if (buttons.Length < 1)
6504 { 6899 {
6505 LSLError("No less than 1 button can be shown"); 6900 buttons.Add("OK");
6506 return;
6507 } 6901 }
6508 if (buttons.Length > 12) 6902 if (buttons.Length > 12)
6509 { 6903 {
@@ -6520,7 +6914,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6520 } 6914 }
6521 if (buttons.Data[i].ToString().Length > 24) 6915 if (buttons.Data[i].ToString().Length > 24)
6522 { 6916 {
6523 LSLError("button label cannot be longer than 24 characters"); 6917 llWhisper(ScriptBaseClass.DEBUG_CHANNEL, "button label cannot be longer than 24 characters");
6524 return; 6918 return;
6525 } 6919 }
6526 buts[i] = buttons.Data[i].ToString(); 6920 buts[i] = buttons.Data[i].ToString();
@@ -6579,22 +6973,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6579 } 6973 }
6580 6974
6581 // copy the first script found with this inventory name 6975 // copy the first script found with this inventory name
6582 lock (m_host.TaskInventory) 6976 TaskInventoryItem scriptItem = null;
6977 m_host.TaskInventory.LockItemsForRead(true);
6978 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6583 { 6979 {
6584 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 6980 if (inv.Value.Name == name)
6585 { 6981 {
6586 if (inv.Value.Name == name) 6982 // make sure the object is a script
6983 if (10 == inv.Value.Type)
6587 { 6984 {
6588 // make sure the object is a script 6985 found = true;
6589 if (10 == inv.Value.Type) 6986 srcId = inv.Key;
6590 { 6987 scriptItem = inv.Value;
6591 found = true; 6988 break;
6592 srcId = inv.Key;
6593 break;
6594 }
6595 } 6989 }
6596 } 6990 }
6597 } 6991 }
6992 m_host.TaskInventory.LockItemsForRead(false);
6598 6993
6599 if (!found) 6994 if (!found)
6600 { 6995 {
@@ -6602,9 +6997,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6602 return; 6997 return;
6603 } 6998 }
6604 6999
6605 // the rest of the permission checks are done in RezScript, so check the pin there as well 7000 SceneObjectPart dest = World.GetSceneObjectPart(destId);
6606 World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param); 7001 if (dest != null)
7002 {
7003 if ((scriptItem.BasePermissions & (uint)PermissionMask.Transfer) != 0 || dest.ParentGroup.RootPart.OwnerID == m_host.ParentGroup.RootPart.OwnerID)
7004 {
7005 // the rest of the permission checks are done in RezScript, so check the pin there as well
7006 World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param);
6607 7007
7008 if ((scriptItem.BasePermissions & (uint)PermissionMask.Copy) == 0)
7009 m_host.Inventory.RemoveInventoryItem(srcId);
7010 }
7011 }
6608 // this will cause the delay even if the script pin or permissions were wrong - seems ok 7012 // this will cause the delay even if the script pin or permissions were wrong - seems ok
6609 ScriptSleep(3000); 7013 ScriptSleep(3000);
6610 } 7014 }
@@ -6667,19 +7071,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6667 public LSL_String llMD5String(string src, int nonce) 7071 public LSL_String llMD5String(string src, int nonce)
6668 { 7072 {
6669 m_host.AddScriptLPS(1); 7073 m_host.AddScriptLPS(1);
6670 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString())); 7074 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString()), Encoding.UTF8);
6671 } 7075 }
6672 7076
6673 public LSL_String llSHA1String(string src) 7077 public LSL_String llSHA1String(string src)
6674 { 7078 {
6675 m_host.AddScriptLPS(1); 7079 m_host.AddScriptLPS(1);
6676 return Util.SHA1Hash(src).ToLower(); 7080 return Util.SHA1Hash(src, Encoding.UTF8).ToLower();
6677 } 7081 }
6678 7082
6679 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) 7083 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve)
6680 { 7084 {
6681 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7085 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6682 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7086 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7087 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7088 return shapeBlock;
6683 7089
6684 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && 7090 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
6685 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && 7091 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
@@ -6784,6 +7190,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6784 // Prim type box, cylinder and prism. 7190 // Prim type box, cylinder and prism.
6785 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte profileshape, byte pathcurve) 7191 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte profileshape, byte pathcurve)
6786 { 7192 {
7193 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7194 return;
7195
6787 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7196 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6788 ObjectShapePacket.ObjectDataBlock shapeBlock; 7197 ObjectShapePacket.ObjectDataBlock shapeBlock;
6789 7198
@@ -6837,6 +7246,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6837 // Prim type sphere. 7246 // Prim type sphere.
6838 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve) 7247 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve)
6839 { 7248 {
7249 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7250 return;
7251
6840 ObjectShapePacket.ObjectDataBlock shapeBlock; 7252 ObjectShapePacket.ObjectDataBlock shapeBlock;
6841 7253
6842 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); 7254 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@@ -6878,6 +7290,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6878 // Prim type torus, tube and ring. 7290 // Prim type torus, tube and ring.
6879 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector holesize, LSL_Vector topshear, LSL_Vector profilecut, LSL_Vector taper_a, float revolutions, float radiusoffset, float skew, byte profileshape, byte pathcurve) 7291 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector holesize, LSL_Vector topshear, LSL_Vector profilecut, LSL_Vector taper_a, float revolutions, float radiusoffset, float skew, byte profileshape, byte pathcurve)
6880 { 7292 {
7293 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7294 return;
7295
6881 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7296 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6882 ObjectShapePacket.ObjectDataBlock shapeBlock; 7297 ObjectShapePacket.ObjectDataBlock shapeBlock;
6883 7298
@@ -7013,6 +7428,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7013 // Prim type sculpt. 7428 // Prim type sculpt.
7014 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve) 7429 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve)
7015 { 7430 {
7431 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7432 return;
7433
7016 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7434 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7017 UUID sculptId; 7435 UUID sculptId;
7018 7436
@@ -7029,13 +7447,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7029 shapeBlock.PathScaleX = 100; 7447 shapeBlock.PathScaleX = 100;
7030 shapeBlock.PathScaleY = 150; 7448 shapeBlock.PathScaleY = 150;
7031 7449
7032 if (type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_CYLINDER && 7450 if ((type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_CYLINDER) == 0 &&
7033 type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_PLANE && 7451 (type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_PLANE) == 0 &&
7034 type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE && 7452 (type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE) == 0 &&
7035 type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS) 7453 (type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS) == 0)
7036 { 7454 {
7037 // default 7455 // default
7038 type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE; 7456 type = type | (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
7039 } 7457 }
7040 7458
7041 part.Shape.SetSculptProperties((byte)type, sculptId); 7459 part.Shape.SetSculptProperties((byte)type, sculptId);
@@ -7051,32 +7469,87 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7051 ScriptSleep(200); 7469 ScriptSleep(200);
7052 } 7470 }
7053 7471
7054 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) 7472 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
7055 { 7473 {
7056 m_host.AddScriptLPS(1); 7474 m_host.AddScriptLPS(1);
7057 7475
7058 setLinkPrimParams(linknumber, rules); 7476 setLinkPrimParams(linknumber, rules);
7059
7060 ScriptSleep(200);
7061 } 7477 }
7062 7478
7063 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) 7479 private void setLinkPrimParams(int linknumber, LSL_List rules)
7064 { 7480 {
7065 m_host.AddScriptLPS(1); 7481 List<SceneObjectPart> parts = GetLinkParts(linknumber);
7482 List<ScenePresence> avatars = GetLinkAvatars(linknumber);
7483 if (parts.Count>0)
7484 {
7485 try
7486 {
7487 parts[0].ParentGroup.areUpdatesSuspended = true;
7488 foreach (SceneObjectPart part in parts)
7489 SetPrimParams(part, rules);
7490 }
7491 finally
7492 {
7493 parts[0].ParentGroup.areUpdatesSuspended = false;
7494 }
7495 }
7496 if (avatars.Count > 0)
7497 {
7498 foreach (ScenePresence avatar in avatars)
7499 SetPrimParams(avatar, rules);
7500 }
7501 }
7066 7502
7067 setLinkPrimParams(linknumber, rules); 7503 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
7504 {
7505 llSetLinkPrimitiveParamsFast(linknumber, rules);
7506 ScriptSleep(200);
7068 } 7507 }
7069 7508
7070 protected void setLinkPrimParams(int linknumber, LSL_List rules) 7509 protected void SetPrimParams(ScenePresence av, LSL_List rules)
7071 { 7510 {
7072 List<SceneObjectPart> parts = GetLinkParts(linknumber); 7511 //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset.
7512 //We only support PRIM_POSITION and PRIM_ROTATION
7073 7513
7074 foreach (SceneObjectPart part in parts) 7514 int idx = 0;
7075 SetPrimParams(part, rules); 7515
7516 while (idx < rules.Length)
7517 {
7518 int code = rules.GetLSLIntegerItem(idx++);
7519
7520 int remain = rules.Length - idx;
7521
7522
7523
7524 switch (code)
7525 {
7526 case (int)ScriptBaseClass.PRIM_POSITION:
7527 if (remain < 1)
7528 return;
7529 LSL_Vector v;
7530 v = rules.GetVector3Item(idx++);
7531 av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
7532 av.SendAvatarDataToAllAgents();
7533
7534 break;
7535
7536 case (int)ScriptBaseClass.PRIM_ROTATION:
7537 if (remain < 1)
7538 return;
7539 LSL_Rotation r;
7540 r = rules.GetQuaternionItem(idx++);
7541 av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
7542 av.SendAvatarDataToAllAgents();
7543 break;
7544 }
7545 }
7076 } 7546 }
7077 7547
7078 protected void SetPrimParams(SceneObjectPart part, LSL_List rules) 7548 protected void SetPrimParams(SceneObjectPart part, LSL_List rules)
7079 { 7549 {
7550 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7551 return;
7552
7080 int idx = 0; 7553 int idx = 0;
7081 7554
7082 bool positionChanged = false; 7555 bool positionChanged = false;
@@ -7104,6 +7577,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7104 currentPosition = GetSetPosTarget(part, v, currentPosition); 7577 currentPosition = GetSetPosTarget(part, v, currentPosition);
7105 7578
7106 break; 7579 break;
7580 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
7581 if (remain < 1)
7582 return;
7583
7584 v=rules.GetVector3Item(idx++);
7585 positionChanged = true;
7586 currentPosition = GetSetPosTarget(part, v, currentPosition);
7587
7588 break;
7107 case (int)ScriptBaseClass.PRIM_SIZE: 7589 case (int)ScriptBaseClass.PRIM_SIZE:
7108 if (remain < 1) 7590 if (remain < 1)
7109 return; 7591 return;
@@ -7481,6 +7963,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7481 } 7963 }
7482 } 7964 }
7483 } 7965 }
7966
7967 if (positionChanged)
7968 {
7969 if (part.ParentGroup.RootPart == part)
7970 {
7971 SceneObjectGroup parent = part.ParentGroup;
7972 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
7973 }
7974 else
7975 {
7976 part.OffsetPosition = new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z);
7977 SceneObjectGroup parent = part.ParentGroup;
7978 parent.HasGroupChanged = true;
7979 parent.ScheduleGroupForTerseUpdate();
7980 }
7981 }
7484 } 7982 }
7485 7983
7486 public LSL_String llStringToBase64(string str) 7984 public LSL_String llStringToBase64(string str)
@@ -7641,13 +8139,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7641 public LSL_Integer llGetNumberOfPrims() 8139 public LSL_Integer llGetNumberOfPrims()
7642 { 8140 {
7643 m_host.AddScriptLPS(1); 8141 m_host.AddScriptLPS(1);
7644 int avatarCount = 0; 8142 int avatarCount = m_host.ParentGroup.GetLinkedAvatars().Count;
7645 World.ForEachRootScenePresence(delegate(ScenePresence presence) 8143
7646 {
7647 if (presence.ParentID != 0 && m_host.ParentGroup.HasChildPrim(presence.ParentID))
7648 avatarCount++;
7649 });
7650
7651 return m_host.ParentGroup.PrimCount + avatarCount; 8144 return m_host.ParentGroup.PrimCount + avatarCount;
7652 } 8145 }
7653 8146
@@ -7663,55 +8156,98 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7663 m_host.AddScriptLPS(1); 8156 m_host.AddScriptLPS(1);
7664 UUID objID = UUID.Zero; 8157 UUID objID = UUID.Zero;
7665 LSL_List result = new LSL_List(); 8158 LSL_List result = new LSL_List();
8159
8160 // If the ID is not valid, return null result
7666 if (!UUID.TryParse(obj, out objID)) 8161 if (!UUID.TryParse(obj, out objID))
7667 { 8162 {
7668 result.Add(new LSL_Vector()); 8163 result.Add(new LSL_Vector());
7669 result.Add(new LSL_Vector()); 8164 result.Add(new LSL_Vector());
7670 return result; 8165 return result;
7671 } 8166 }
8167
8168 // Check if this is an attached prim. If so, replace
8169 // the UUID with the avatar UUID and report it's bounding box
8170 SceneObjectPart part = World.GetSceneObjectPart(objID);
8171 if (part != null && part.ParentGroup.IsAttachment)
8172 objID = part.ParentGroup.AttachedAvatar;
8173
8174 // Find out if this is an avatar ID. If so, return it's box
7672 ScenePresence presence = World.GetScenePresence(objID); 8175 ScenePresence presence = World.GetScenePresence(objID);
7673 if (presence != null) 8176 if (presence != null)
7674 { 8177 {
7675 if (presence.ParentID == 0) // not sat on an object 8178 // As per LSL Wiki, there is no difference between sitting
8179 // and standing avatar since server 1.36
8180 LSL_Vector lower;
8181 LSL_Vector upper;
8182 if (presence.Animator.Animations.DefaultAnimation.AnimID
8183 == AnimationSet.Animations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
7676 { 8184 {
7677 LSL_Vector lower; 8185 // This is for ground sitting avatars
7678 LSL_Vector upper; 8186 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7679 if (presence.Animator.Animations.DefaultAnimation.AnimID 8187 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7680 == AnimationSet.Animations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) 8188 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7681 {
7682 // This is for ground sitting avatars
7683 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7684 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7685 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7686 }
7687 else
7688 {
7689 // This is for standing/flying avatars
7690 float height = presence.Appearance.AvatarHeight / 2.0f;
7691 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7692 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7693 }
7694 result.Add(lower);
7695 result.Add(upper);
7696 return result;
7697 } 8189 }
7698 else 8190 else
7699 { 8191 {
7700 // sitting on an object so we need the bounding box of that 8192 // This is for standing/flying avatars
7701 // which should include the avatar so set the UUID to the 8193 float height = presence.Appearance.AvatarHeight / 2.0f;
7702 // UUID of the object the avatar is sat on and allow it to fall through 8194 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7703 // to processing an object 8195 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7704 SceneObjectPart p = World.GetSceneObjectPart(presence.ParentID);
7705 objID = p.UUID;
7706 } 8196 }
8197
8198 // Adjust to the documented error offsets (see LSL Wiki)
8199 lower += new LSL_Vector(0.05f, 0.05f, 0.05f);
8200 upper -= new LSL_Vector(0.05f, 0.05f, 0.05f);
8201
8202 if (lower.x > upper.x)
8203 lower.x = upper.x;
8204 if (lower.y > upper.y)
8205 lower.y = upper.y;
8206 if (lower.z > upper.z)
8207 lower.z = upper.z;
8208
8209 result.Add(lower);
8210 result.Add(upper);
8211 return result;
7707 } 8212 }
7708 SceneObjectPart part = World.GetSceneObjectPart(objID); 8213
8214 part = World.GetSceneObjectPart(objID);
7709 // Currently only works for single prims without a sitting avatar 8215 // Currently only works for single prims without a sitting avatar
7710 if (part != null) 8216 if (part != null)
7711 { 8217 {
7712 Vector3 halfSize = part.Scale / 2.0f; 8218 float minX;
7713 LSL_Vector lower = new LSL_Vector(halfSize.X * -1.0f, halfSize.Y * -1.0f, halfSize.Z * -1.0f); 8219 float maxX;
7714 LSL_Vector upper = new LSL_Vector(halfSize.X, halfSize.Y, halfSize.Z); 8220 float minY;
8221 float maxY;
8222 float minZ;
8223 float maxZ;
8224
8225 // This BBox is in sim coordinates, with the offset being
8226 // a contained point.
8227 Vector3[] offsets = Scene.GetCombinedBoundingBox(new List<SceneObjectGroup> { part.ParentGroup },
8228 out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
8229
8230 minX -= offsets[0].X;
8231 maxX -= offsets[0].X;
8232 minY -= offsets[0].Y;
8233 maxY -= offsets[0].Y;
8234 minZ -= offsets[0].Z;
8235 maxZ -= offsets[0].Z;
8236
8237 LSL_Vector lower;
8238 LSL_Vector upper;
8239
8240 // Adjust to the documented error offsets (see LSL Wiki)
8241 lower = new LSL_Vector(minX + 0.05f, minY + 0.05f, minZ + 0.05f);
8242 upper = new LSL_Vector(maxX - 0.05f, maxY - 0.05f, maxZ - 0.05f);
8243
8244 if (lower.x > upper.x)
8245 lower.x = upper.x;
8246 if (lower.y > upper.y)
8247 lower.y = upper.y;
8248 if (lower.z > upper.z)
8249 lower.z = upper.z;
8250
7715 result.Add(lower); 8251 result.Add(lower);
7716 result.Add(upper); 8252 result.Add(upper);
7717 return result; 8253 return result;
@@ -7791,13 +8327,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7791 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X, 8327 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X,
7792 part.AbsolutePosition.Y, 8328 part.AbsolutePosition.Y,
7793 part.AbsolutePosition.Z); 8329 part.AbsolutePosition.Z);
7794 // For some reason, the part.AbsolutePosition.* values do not change if the
7795 // linkset is rotated; they always reflect the child prim's world position
7796 // as though the linkset is unrotated. This is incompatible behavior with SL's
7797 // implementation, so will break scripts imported from there (not to mention it
7798 // makes it more difficult to determine a child prim's actual inworld position).
7799 if (part.ParentID != 0)
7800 v = ((v - llGetRootPosition()) * llGetRootRotation()) + llGetRootPosition();
7801 res.Add(v); 8330 res.Add(v);
7802 break; 8331 break;
7803 8332
@@ -7968,56 +8497,92 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7968 case (int)ScriptBaseClass.PRIM_BUMP_SHINY: 8497 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
7969 if (remain < 1) 8498 if (remain < 1)
7970 return res; 8499 return res;
7971 8500 face = (int)rules.GetLSLIntegerItem(idx++);
7972 face=(int)rules.GetLSLIntegerItem(idx++);
7973 8501
7974 tex = part.Shape.Textures; 8502 tex = part.Shape.Textures;
8503 int shiny;
7975 if (face == ScriptBaseClass.ALL_SIDES) 8504 if (face == ScriptBaseClass.ALL_SIDES)
7976 { 8505 {
7977 for (face = 0; face < GetNumberOfSides(part); face++) 8506 for (face = 0; face < GetNumberOfSides(part); face++)
7978 { 8507 {
7979 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8508 Shininess shinyness = tex.GetFace((uint)face).Shiny;
7980 // Convert Shininess to PRIM_SHINY_* 8509 if (shinyness == Shininess.High)
7981 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8510 {
7982 // PRIM_BUMP_* 8511 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
7983 res.Add(new LSL_Integer((int)texface.Bump)); 8512 }
8513 else if (shinyness == Shininess.Medium)
8514 {
8515 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8516 }
8517 else if (shinyness == Shininess.Low)
8518 {
8519 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8520 }
8521 else
8522 {
8523 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8524 }
8525 res.Add(new LSL_Integer(shiny));
8526 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
7984 } 8527 }
7985 } 8528 }
7986 else 8529 else
7987 { 8530 {
7988 if (face >= 0 && face < GetNumberOfSides(part)) 8531 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8532 if (shinyness == Shininess.High)
7989 { 8533 {
7990 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8534 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
7991 // Convert Shininess to PRIM_SHINY_* 8535 }
7992 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8536 else if (shinyness == Shininess.Medium)
7993 // PRIM_BUMP_* 8537 {
7994 res.Add(new LSL_Integer((int)texface.Bump)); 8538 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
7995 } 8539 }
8540 else if (shinyness == Shininess.Low)
8541 {
8542 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8543 }
8544 else
8545 {
8546 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8547 }
8548 res.Add(new LSL_Integer(shiny));
8549 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
7996 } 8550 }
7997 break; 8551 break;
7998 8552
7999 case (int)ScriptBaseClass.PRIM_FULLBRIGHT: 8553 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
8000 if (remain < 1) 8554 if (remain < 1)
8001 return res; 8555 return res;
8002 8556 face = (int)rules.GetLSLIntegerItem(idx++);
8003 face=(int)rules.GetLSLIntegerItem(idx++);
8004 8557
8005 tex = part.Shape.Textures; 8558 tex = part.Shape.Textures;
8559 int fullbright;
8006 if (face == ScriptBaseClass.ALL_SIDES) 8560 if (face == ScriptBaseClass.ALL_SIDES)
8007 { 8561 {
8008 for (face = 0; face < GetNumberOfSides(part); face++) 8562 for (face = 0; face < GetNumberOfSides(part); face++)
8009 { 8563 {
8010 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8564 if (tex.GetFace((uint)face).Fullbright == true)
8011 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 8565 {
8566 fullbright = ScriptBaseClass.TRUE;
8567 }
8568 else
8569 {
8570 fullbright = ScriptBaseClass.FALSE;
8571 }
8572 res.Add(new LSL_Integer(fullbright));
8012 } 8573 }
8013 } 8574 }
8014 else 8575 else
8015 { 8576 {
8016 if (face >= 0 && face < GetNumberOfSides(part)) 8577 if (tex.GetFace((uint)face).Fullbright == true)
8017 { 8578 {
8018 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8579 fullbright = ScriptBaseClass.TRUE;
8019 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0));
8020 } 8580 }
8581 else
8582 {
8583 fullbright = ScriptBaseClass.FALSE;
8584 }
8585 res.Add(new LSL_Integer(fullbright));
8021 } 8586 }
8022 break; 8587 break;
8023 8588
@@ -8039,27 +8604,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8039 break; 8604 break;
8040 8605
8041 case (int)ScriptBaseClass.PRIM_TEXGEN: 8606 case (int)ScriptBaseClass.PRIM_TEXGEN:
8607 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
8042 if (remain < 1) 8608 if (remain < 1)
8043 return res; 8609 return res;
8044 8610 face = (int)rules.GetLSLIntegerItem(idx++);
8045 face=(int)rules.GetLSLIntegerItem(idx++);
8046 8611
8047 tex = part.Shape.Textures; 8612 tex = part.Shape.Textures;
8048 if (face == ScriptBaseClass.ALL_SIDES) 8613 if (face == ScriptBaseClass.ALL_SIDES)
8049 { 8614 {
8050 for (face = 0; face < GetNumberOfSides(part); face++) 8615 for (face = 0; face < GetNumberOfSides(part); face++)
8051 { 8616 {
8052 MappingType texgen = tex.GetFace((uint)face).TexMapType; 8617 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8053 // Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc. 8618 {
8054 res.Add(new LSL_Integer((uint)texgen >> 1)); 8619 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8620 }
8621 else
8622 {
8623 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8624 }
8055 } 8625 }
8056 } 8626 }
8057 else 8627 else
8058 { 8628 {
8059 if (face >= 0 && face < GetNumberOfSides(part)) 8629 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8630 {
8631 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8632 }
8633 else
8060 { 8634 {
8061 MappingType texgen = tex.GetFace((uint)face).TexMapType; 8635 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8062 res.Add(new LSL_Integer((uint)texgen >> 1));
8063 } 8636 }
8064 } 8637 }
8065 break; 8638 break;
@@ -8082,28 +8655,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8082 case (int)ScriptBaseClass.PRIM_GLOW: 8655 case (int)ScriptBaseClass.PRIM_GLOW:
8083 if (remain < 1) 8656 if (remain < 1)
8084 return res; 8657 return res;
8085 8658 face = (int)rules.GetLSLIntegerItem(idx++);
8086 face=(int)rules.GetLSLIntegerItem(idx++);
8087 8659
8088 tex = part.Shape.Textures; 8660 tex = part.Shape.Textures;
8661 float primglow;
8089 if (face == ScriptBaseClass.ALL_SIDES) 8662 if (face == ScriptBaseClass.ALL_SIDES)
8090 { 8663 {
8091 for (face = 0; face < GetNumberOfSides(part); face++) 8664 for (face = 0; face < GetNumberOfSides(part); face++)
8092 { 8665 {
8093 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8666 primglow = tex.GetFace((uint)face).Glow;
8094 res.Add(new LSL_Float(texface.Glow)); 8667 res.Add(new LSL_Float(primglow));
8095 } 8668 }
8096 } 8669 }
8097 else 8670 else
8098 { 8671 {
8099 if (face >= 0 && face < GetNumberOfSides(part)) 8672 primglow = tex.GetFace((uint)face).Glow;
8100 { 8673 res.Add(new LSL_Float(primglow));
8101 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
8102 res.Add(new LSL_Float(texface.Glow));
8103 }
8104 } 8674 }
8105 break; 8675 break;
8106
8107 case (int)ScriptBaseClass.PRIM_TEXT: 8676 case (int)ScriptBaseClass.PRIM_TEXT:
8108 Color4 textColor = part.GetTextColor(); 8677 Color4 textColor = part.GetTextColor();
8109 res.Add(new LSL_String(part.Text)); 8678 res.Add(new LSL_String(part.Text));
@@ -8655,8 +9224,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8655 // The function returns an ordered list 9224 // The function returns an ordered list
8656 // representing the tokens found in the supplied 9225 // representing the tokens found in the supplied
8657 // sources string. If two successive tokenizers 9226 // sources string. If two successive tokenizers
8658 // are encountered, then a NULL entry is added 9227 // are encountered, then a null-string entry is
8659 // to the list. 9228 // added to the list.
8660 // 9229 //
8661 // It is a precondition that the source and 9230 // It is a precondition that the source and
8662 // toekizer lisst are non-null. If they are null, 9231 // toekizer lisst are non-null. If they are null,
@@ -8664,7 +9233,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8664 // while their lengths are being determined. 9233 // while their lengths are being determined.
8665 // 9234 //
8666 // A small amount of working memoryis required 9235 // A small amount of working memoryis required
8667 // of approximately 8*#tokenizers. 9236 // of approximately 8*#tokenizers + 8*srcstrlen.
8668 // 9237 //
8669 // There are many ways in which this function 9238 // There are many ways in which this function
8670 // can be implemented, this implementation is 9239 // can be implemented, this implementation is
@@ -8680,155 +9249,124 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8680 // and eliminates redundant tokenizers as soon 9249 // and eliminates redundant tokenizers as soon
8681 // as is possible. 9250 // as is possible.
8682 // 9251 //
8683 // The implementation tries to avoid any copying 9252 // The implementation tries to minimize temporary
8684 // of arrays or other objects. 9253 // garbage generation.
8685 // </remarks> 9254 // </remarks>
8686 9255
8687 private LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls) 9256 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8688 { 9257 {
8689 int beginning = 0; 9258 return ParseString2List(src, separators, spacers, true);
8690 int srclen = src.Length; 9259 }
8691 int seplen = separators.Length;
8692 object[] separray = separators.Data;
8693 int spclen = spacers.Length;
8694 object[] spcarray = spacers.Data;
8695 int mlen = seplen+spclen;
8696
8697 int[] offset = new int[mlen+1];
8698 bool[] active = new bool[mlen];
8699
8700 int best;
8701 int j;
8702
8703 // Initial capacity reduces resize cost
8704 9260
8705 LSL_List tokens = new LSL_List(); 9261 private LSL_List ParseString2List(string src, LSL_List separators, LSL_List spacers, bool keepNulls)
9262 {
9263 int srclen = src.Length;
9264 int seplen = separators.Length;
9265 object[] separray = separators.Data;
9266 int spclen = spacers.Length;
9267 object[] spcarray = spacers.Data;
9268 int dellen = 0;
9269 string[] delarray = new string[seplen+spclen];
8706 9270
8707 // All entries are initially valid 9271 int outlen = 0;
9272 string[] outarray = new string[srclen*2+1];
8708 9273
8709 for (int i = 0; i < mlen; i++) 9274 int i, j;
8710 active[i] = true; 9275 string d;
8711 9276
8712 offset[mlen] = srclen; 9277 m_host.AddScriptLPS(1);
8713 9278
8714 while (beginning < srclen) 9279 /*
9280 * Convert separator and spacer lists to C# strings.
9281 * Also filter out null strings so we don't hang.
9282 */
9283 for (i = 0; i < seplen; i ++)
8715 { 9284 {
9285 d = separray[i].ToString();
9286 if (d.Length > 0)
9287 {
9288 delarray[dellen++] = d;
9289 }
9290 }
9291 seplen = dellen;
8716 9292
8717 best = mlen; // as bad as it gets 9293 for (i = 0; i < spclen; i ++)
9294 {
9295 d = spcarray[i].ToString();
9296 if (d.Length > 0)
9297 {
9298 delarray[dellen++] = d;
9299 }
9300 }
8718 9301
8719 // Scan for separators 9302 /*
9303 * Scan through source string from beginning to end.
9304 */
9305 for (i = 0;;)
9306 {
8720 9307
8721 for (j = 0; j < seplen; j++) 9308 /*
9309 * Find earliest delimeter in src starting at i (if any).
9310 */
9311 int earliestDel = -1;
9312 int earliestSrc = srclen;
9313 string earliestStr = null;
9314 for (j = 0; j < dellen; j ++)
8722 { 9315 {
8723 if (separray[j].ToString() == String.Empty) 9316 d = delarray[j];
8724 active[j] = false; 9317 if (d != null)
8725
8726 if (active[j])
8727 { 9318 {
8728 // scan all of the markers 9319 int index = src.IndexOf(d, i);
8729 if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1) 9320 if (index < 0)
8730 { 9321 {
8731 // not present at all 9322 delarray[j] = null; // delim nowhere in src, don't check it anymore
8732 active[j] = false;
8733 } 9323 }
8734 else 9324 else if (index < earliestSrc)
8735 { 9325 {
8736 // present and correct 9326 earliestSrc = index; // where delimeter starts in source string
8737 if (offset[j] < offset[best]) 9327 earliestDel = j; // where delimeter is in delarray[]
8738 { 9328 earliestStr = d; // the delimeter string from delarray[]
8739 // closest so far 9329 if (index == i) break; // can't do any better than found at beg of string
8740 best = j;
8741 if (offset[best] == beginning)
8742 break;
8743 }
8744 } 9330 }
8745 } 9331 }
8746 } 9332 }
8747 9333
8748 // Scan for spacers 9334 /*
8749 9335 * Output source string starting at i through start of earliest delimeter.
8750 if (offset[best] != beginning) 9336 */
9337 if (keepNulls || (earliestSrc > i))
8751 { 9338 {
8752 for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) 9339 outarray[outlen++] = src.Substring(i, earliestSrc - i);
8753 {
8754 if (spcarray[j-seplen].ToString() == String.Empty)
8755 active[j] = false;
8756
8757 if (active[j])
8758 {
8759 // scan all of the markers
8760 if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1)
8761 {
8762 // not present at all
8763 active[j] = false;
8764 }
8765 else
8766 {
8767 // present and correct
8768 if (offset[j] < offset[best])
8769 {
8770 // closest so far
8771 best = j;
8772 }
8773 }
8774 }
8775 }
8776 } 9340 }
8777 9341
8778 // This is the normal exit from the scanning loop 9342 /*
9343 * If no delimeter found at or after i, we're done scanning.
9344 */
9345 if (earliestDel < 0) break;
8779 9346
8780 if (best == mlen) 9347 /*
9348 * If delimeter was a spacer, output the spacer.
9349 */
9350 if (earliestDel >= seplen)
8781 { 9351 {
8782 // no markers were found on this pass 9352 outarray[outlen++] = earliestStr;
8783 // so we're pretty much done
8784 if ((keepNulls) || ((!keepNulls) && (srclen - beginning) > 0))
8785 tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning)));
8786 break;
8787 } 9353 }
8788 9354
8789 // Otherwise we just add the newly delimited token 9355 /*
8790 // and recalculate where the search should continue. 9356 * Look at rest of src string following delimeter.
8791 if ((keepNulls) || ((!keepNulls) && (offset[best] - beginning) > 0)) 9357 */
8792 tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning))); 9358 i = earliestSrc + earliestStr.Length;
8793
8794 if (best < seplen)
8795 {
8796 beginning = offset[best] + (separray[best].ToString()).Length;
8797 }
8798 else
8799 {
8800 beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
8801 string str = spcarray[best - seplen].ToString();
8802 if ((keepNulls) || ((!keepNulls) && (str.Length > 0)))
8803 tokens.Add(new LSL_String(str));
8804 }
8805 } 9359 }
8806 9360
8807 // This an awkward an not very intuitive boundary case. If the 9361 /*
8808 // last substring is a tokenizer, then there is an implied trailing 9362 * Make up an exact-sized output array suitable for an LSL_List object.
8809 // null list entry. Hopefully the single comparison will not be too 9363 */
8810 // arduous. Alternatively the 'break' could be replced with a return 9364 object[] outlist = new object[outlen];
8811 // but that's shabby programming. 9365 for (i = 0; i < outlen; i ++)
8812
8813 if ((beginning == srclen) && (keepNulls))
8814 { 9366 {
8815 if (srclen != 0) 9367 outlist[i] = new LSL_String(outarray[i]);
8816 tokens.Add(new LSL_String(""));
8817 } 9368 }
8818 9369 return new LSL_List(outlist);
8819 return tokens;
8820 }
8821
8822 public LSL_List llParseString2List(string src, LSL_List separators, LSL_List spacers)
8823 {
8824 m_host.AddScriptLPS(1);
8825 return this.ParseString(src, separators, spacers, false);
8826 }
8827
8828 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8829 {
8830 m_host.AddScriptLPS(1);
8831 return this.ParseString(src, separators, spacers, true);
8832 } 9370 }
8833 9371
8834 public LSL_Integer llGetObjectPermMask(int mask) 9372 public LSL_Integer llGetObjectPermMask(int mask)
@@ -8905,28 +9443,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8905 { 9443 {
8906 m_host.AddScriptLPS(1); 9444 m_host.AddScriptLPS(1);
8907 9445
8908 lock (m_host.TaskInventory) 9446 m_host.TaskInventory.LockItemsForRead(true);
9447 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
8909 { 9448 {
8910 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9449 if (inv.Value.Name == item)
8911 { 9450 {
8912 if (inv.Value.Name == item) 9451 m_host.TaskInventory.LockItemsForRead(false);
9452 switch (mask)
8913 { 9453 {
8914 switch (mask) 9454 case 0:
8915 { 9455 return (int)inv.Value.BasePermissions;
8916 case 0: 9456 case 1:
8917 return (int)inv.Value.BasePermissions; 9457 return (int)inv.Value.CurrentPermissions;
8918 case 1: 9458 case 2:
8919 return (int)inv.Value.CurrentPermissions; 9459 return (int)inv.Value.GroupPermissions;
8920 case 2: 9460 case 3:
8921 return (int)inv.Value.GroupPermissions; 9461 return (int)inv.Value.EveryonePermissions;
8922 case 3: 9462 case 4:
8923 return (int)inv.Value.EveryonePermissions; 9463 return (int)inv.Value.NextPermissions;
8924 case 4:
8925 return (int)inv.Value.NextPermissions;
8926 }
8927 } 9464 }
8928 } 9465 }
8929 } 9466 }
9467 m_host.TaskInventory.LockItemsForRead(false);
8930 9468
8931 return -1; 9469 return -1;
8932 } 9470 }
@@ -8973,16 +9511,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8973 { 9511 {
8974 m_host.AddScriptLPS(1); 9512 m_host.AddScriptLPS(1);
8975 9513
8976 lock (m_host.TaskInventory) 9514 m_host.TaskInventory.LockItemsForRead(true);
9515 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
8977 { 9516 {
8978 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9517 if (inv.Value.Name == item)
8979 { 9518 {
8980 if (inv.Value.Name == item) 9519 m_host.TaskInventory.LockItemsForRead(false);
8981 { 9520 return inv.Value.CreatorID.ToString();
8982 return inv.Value.CreatorID.ToString();
8983 }
8984 } 9521 }
8985 } 9522 }
9523 m_host.TaskInventory.LockItemsForRead(false);
8986 9524
8987 llSay(0, "No item name '" + item + "'"); 9525 llSay(0, "No item name '" + item + "'");
8988 9526
@@ -9130,7 +9668,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9130 } 9668 }
9131 9669
9132 /// <summary> 9670 /// <summary>
9133 /// illListReplaceList removes the sub-list defined by the inclusive indices 9671 /// llListReplaceList removes the sub-list defined by the inclusive indices
9134 /// start and end and inserts the src list in its place. The inclusive 9672 /// start and end and inserts the src list in its place. The inclusive
9135 /// nature of the indices means that at least one element must be deleted 9673 /// nature of the indices means that at least one element must be deleted
9136 /// if the indices are within the bounds of the existing list. I.e. 2,2 9674 /// if the indices are within the bounds of the existing list. I.e. 2,2
@@ -9187,16 +9725,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9187 // based upon end. Note that if end exceeds the upper 9725 // based upon end. Note that if end exceeds the upper
9188 // bound in this case, the entire destination list 9726 // bound in this case, the entire destination list
9189 // is removed. 9727 // is removed.
9190 else 9728 else if (start == 0)
9191 { 9729 {
9192 if (end + 1 < dest.Length) 9730 if (end + 1 < dest.Length)
9193 {
9194 return src + dest.GetSublist(end + 1, -1); 9731 return src + dest.GetSublist(end + 1, -1);
9195 }
9196 else 9732 else
9197 {
9198 return src; 9733 return src;
9199 } 9734 }
9735 else // Start < 0
9736 {
9737 if (end + 1 < dest.Length)
9738 return dest.GetSublist(end + 1, -1);
9739 else
9740 return new LSL_List();
9200 } 9741 }
9201 } 9742 }
9202 // Finally, if start > end, we strip away a prefix and 9743 // Finally, if start > end, we strip away a prefix and
@@ -9247,17 +9788,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9247 int width = 0; 9788 int width = 0;
9248 int height = 0; 9789 int height = 0;
9249 9790
9250 ParcelMediaCommandEnum? commandToSend = null; 9791 uint commandToSend = 0;
9251 float time = 0.0f; // default is from start 9792 float time = 0.0f; // default is from start
9252 9793
9253 ScenePresence presence = null; 9794 ScenePresence presence = null;
9254 9795
9255 for (int i = 0; i < commandList.Data.Length; i++) 9796 for (int i = 0; i < commandList.Data.Length; i++)
9256 { 9797 {
9257 ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i]; 9798 uint command = (uint)(commandList.GetLSLIntegerItem(i));
9258 switch (command) 9799 switch (command)
9259 { 9800 {
9260 case ParcelMediaCommandEnum.Agent: 9801 case (uint)ParcelMediaCommandEnum.Agent:
9261 // we send only to one agent 9802 // we send only to one agent
9262 if ((i + 1) < commandList.Length) 9803 if ((i + 1) < commandList.Length)
9263 { 9804 {
@@ -9274,25 +9815,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9274 } 9815 }
9275 break; 9816 break;
9276 9817
9277 case ParcelMediaCommandEnum.Loop: 9818 case (uint)ParcelMediaCommandEnum.Loop:
9278 loop = 1; 9819 loop = 1;
9279 commandToSend = command; 9820 commandToSend = command;
9280 update = true; //need to send the media update packet to set looping 9821 update = true; //need to send the media update packet to set looping
9281 break; 9822 break;
9282 9823
9283 case ParcelMediaCommandEnum.Play: 9824 case (uint)ParcelMediaCommandEnum.Play:
9284 loop = 0; 9825 loop = 0;
9285 commandToSend = command; 9826 commandToSend = command;
9286 update = true; //need to send the media update packet to make sure it doesn't loop 9827 update = true; //need to send the media update packet to make sure it doesn't loop
9287 break; 9828 break;
9288 9829
9289 case ParcelMediaCommandEnum.Pause: 9830 case (uint)ParcelMediaCommandEnum.Pause:
9290 case ParcelMediaCommandEnum.Stop: 9831 case (uint)ParcelMediaCommandEnum.Stop:
9291 case ParcelMediaCommandEnum.Unload: 9832 case (uint)ParcelMediaCommandEnum.Unload:
9292 commandToSend = command; 9833 commandToSend = command;
9293 break; 9834 break;
9294 9835
9295 case ParcelMediaCommandEnum.Url: 9836 case (uint)ParcelMediaCommandEnum.Url:
9296 if ((i + 1) < commandList.Length) 9837 if ((i + 1) < commandList.Length)
9297 { 9838 {
9298 if (commandList.Data[i + 1] is LSL_String) 9839 if (commandList.Data[i + 1] is LSL_String)
@@ -9305,7 +9846,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9305 } 9846 }
9306 break; 9847 break;
9307 9848
9308 case ParcelMediaCommandEnum.Texture: 9849 case (uint)ParcelMediaCommandEnum.Texture:
9309 if ((i + 1) < commandList.Length) 9850 if ((i + 1) < commandList.Length)
9310 { 9851 {
9311 if (commandList.Data[i + 1] is LSL_String) 9852 if (commandList.Data[i + 1] is LSL_String)
@@ -9318,7 +9859,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9318 } 9859 }
9319 break; 9860 break;
9320 9861
9321 case ParcelMediaCommandEnum.Time: 9862 case (uint)ParcelMediaCommandEnum.Time:
9322 if ((i + 1) < commandList.Length) 9863 if ((i + 1) < commandList.Length)
9323 { 9864 {
9324 if (commandList.Data[i + 1] is LSL_Float) 9865 if (commandList.Data[i + 1] is LSL_Float)
@@ -9330,7 +9871,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9330 } 9871 }
9331 break; 9872 break;
9332 9873
9333 case ParcelMediaCommandEnum.AutoAlign: 9874 case (uint)ParcelMediaCommandEnum.AutoAlign:
9334 if ((i + 1) < commandList.Length) 9875 if ((i + 1) < commandList.Length)
9335 { 9876 {
9336 if (commandList.Data[i + 1] is LSL_Integer) 9877 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9344,7 +9885,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9344 } 9885 }
9345 break; 9886 break;
9346 9887
9347 case ParcelMediaCommandEnum.Type: 9888 case (uint)ParcelMediaCommandEnum.Type:
9348 if ((i + 1) < commandList.Length) 9889 if ((i + 1) < commandList.Length)
9349 { 9890 {
9350 if (commandList.Data[i + 1] is LSL_String) 9891 if (commandList.Data[i + 1] is LSL_String)
@@ -9357,7 +9898,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9357 } 9898 }
9358 break; 9899 break;
9359 9900
9360 case ParcelMediaCommandEnum.Desc: 9901 case (uint)ParcelMediaCommandEnum.Desc:
9361 if ((i + 1) < commandList.Length) 9902 if ((i + 1) < commandList.Length)
9362 { 9903 {
9363 if (commandList.Data[i + 1] is LSL_String) 9904 if (commandList.Data[i + 1] is LSL_String)
@@ -9370,7 +9911,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9370 } 9911 }
9371 break; 9912 break;
9372 9913
9373 case ParcelMediaCommandEnum.Size: 9914 case (uint)ParcelMediaCommandEnum.Size:
9374 if ((i + 2) < commandList.Length) 9915 if ((i + 2) < commandList.Length)
9375 { 9916 {
9376 if (commandList.Data[i + 1] is LSL_Integer) 9917 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9440,7 +9981,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9440 } 9981 }
9441 } 9982 }
9442 9983
9443 if (commandToSend != null) 9984 if (commandToSend != 0)
9444 { 9985 {
9445 // the commandList contained a start/stop/... command, too 9986 // the commandList contained a start/stop/... command, too
9446 if (presence == null) 9987 if (presence == null)
@@ -9477,7 +10018,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9477 10018
9478 if (aList.Data[i] != null) 10019 if (aList.Data[i] != null)
9479 { 10020 {
9480 switch ((ParcelMediaCommandEnum) aList.Data[i]) 10021 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString()))
9481 { 10022 {
9482 case ParcelMediaCommandEnum.Url: 10023 case ParcelMediaCommandEnum.Url:
9483 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL)); 10024 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL));
@@ -9520,16 +10061,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9520 { 10061 {
9521 m_host.AddScriptLPS(1); 10062 m_host.AddScriptLPS(1);
9522 10063
9523 lock (m_host.TaskInventory) 10064 m_host.TaskInventory.LockItemsForRead(true);
10065 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9524 { 10066 {
9525 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 10067 if (inv.Value.Name == name)
9526 { 10068 {
9527 if (inv.Value.Name == name) 10069 m_host.TaskInventory.LockItemsForRead(false);
9528 { 10070 return inv.Value.Type;
9529 return inv.Value.Type;
9530 }
9531 } 10071 }
9532 } 10072 }
10073 m_host.TaskInventory.LockItemsForRead(false);
9533 10074
9534 return -1; 10075 return -1;
9535 } 10076 }
@@ -9540,15 +10081,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9540 10081
9541 if (quick_pay_buttons.Data.Length < 4) 10082 if (quick_pay_buttons.Data.Length < 4)
9542 { 10083 {
9543 LSLError("List must have at least 4 elements"); 10084 int x;
9544 return; 10085 for (x=quick_pay_buttons.Data.Length; x<= 4; x++)
10086 {
10087 quick_pay_buttons.Add(ScriptBaseClass.PAY_HIDE);
10088 }
9545 } 10089 }
9546 m_host.ParentGroup.RootPart.PayPrice[0]=price; 10090 int[] nPrice = new int[5];
9547 10091 nPrice[0] = price;
9548 m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; 10092 nPrice[1] = quick_pay_buttons.GetLSLIntegerItem(0);
9549 m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; 10093 nPrice[2] = quick_pay_buttons.GetLSLIntegerItem(1);
9550 m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; 10094 nPrice[3] = quick_pay_buttons.GetLSLIntegerItem(2);
9551 m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; 10095 nPrice[4] = quick_pay_buttons.GetLSLIntegerItem(3);
10096 m_host.ParentGroup.RootPart.PayPrice = nPrice;
9552 m_host.ParentGroup.HasGroupChanged = true; 10097 m_host.ParentGroup.HasGroupChanged = true;
9553 } 10098 }
9554 10099
@@ -9560,17 +10105,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9560 if (invItemID == UUID.Zero) 10105 if (invItemID == UUID.Zero)
9561 return new LSL_Vector(); 10106 return new LSL_Vector();
9562 10107
9563 lock (m_host.TaskInventory) 10108 m_host.TaskInventory.LockItemsForRead(true);
10109 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
9564 { 10110 {
9565 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) 10111 m_host.TaskInventory.LockItemsForRead(false);
9566 return new LSL_Vector(); 10112 return new LSL_Vector();
10113 }
9567 10114
9568 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) 10115 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
9569 { 10116 {
9570 ShoutError("No permissions to track the camera"); 10117 ShoutError("No permissions to track the camera");
9571 return new LSL_Vector(); 10118 m_host.TaskInventory.LockItemsForRead(false);
9572 } 10119 return new LSL_Vector();
9573 } 10120 }
10121 m_host.TaskInventory.LockItemsForRead(false);
9574 10122
9575 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10123 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
9576 if (presence != null) 10124 if (presence != null)
@@ -9588,17 +10136,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9588 if (invItemID == UUID.Zero) 10136 if (invItemID == UUID.Zero)
9589 return new LSL_Rotation(); 10137 return new LSL_Rotation();
9590 10138
9591 lock (m_host.TaskInventory) 10139 m_host.TaskInventory.LockItemsForRead(true);
10140 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
9592 { 10141 {
9593 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) 10142 m_host.TaskInventory.LockItemsForRead(false);
9594 return new LSL_Rotation(); 10143 return new LSL_Rotation();
9595
9596 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
9597 {
9598 ShoutError("No permissions to track the camera");
9599 return new LSL_Rotation();
9600 }
9601 } 10144 }
10145 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
10146 {
10147 ShoutError("No permissions to track the camera");
10148 m_host.TaskInventory.LockItemsForRead(false);
10149 return new LSL_Rotation();
10150 }
10151 m_host.TaskInventory.LockItemsForRead(false);
9602 10152
9603 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10153 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
9604 if (presence != null) 10154 if (presence != null)
@@ -9660,8 +10210,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9660 { 10210 {
9661 m_host.AddScriptLPS(1); 10211 m_host.AddScriptLPS(1);
9662 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, 0); 10212 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, 0);
9663 if (detectedParams == null) return; // only works on the first detected avatar 10213 if (detectedParams == null)
9664 10214 {
10215 if (m_host.ParentGroup.IsAttachment == true)
10216 {
10217 detectedParams = new DetectParams();
10218 detectedParams.Key = m_host.OwnerID;
10219 }
10220 else
10221 {
10222 return;
10223 }
10224 }
10225
9665 ScenePresence avatar = World.GetScenePresence(detectedParams.Key); 10226 ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
9666 if (avatar != null) 10227 if (avatar != null)
9667 { 10228 {
@@ -9669,6 +10230,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9669 new Vector3((float)pos.x, (float)pos.y, (float)pos.z), 10230 new Vector3((float)pos.x, (float)pos.y, (float)pos.z),
9670 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z)); 10231 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z));
9671 } 10232 }
10233
9672 ScriptSleep(1000); 10234 ScriptSleep(1000);
9673 } 10235 }
9674 10236
@@ -9761,14 +10323,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9761 if (objectID == UUID.Zero) return; 10323 if (objectID == UUID.Zero) return;
9762 10324
9763 UUID agentID; 10325 UUID agentID;
9764 lock (m_host.TaskInventory) 10326 m_host.TaskInventory.LockItemsForRead(true);
9765 { 10327 // we need the permission first, to know which avatar we want to set the camera for
9766 // we need the permission first, to know which avatar we want to set the camera for 10328 agentID = m_host.TaskInventory[invItemID].PermsGranter;
9767 agentID = m_host.TaskInventory[invItemID].PermsGranter;
9768 10329
9769 if (agentID == UUID.Zero) return; 10330 if (agentID == UUID.Zero)
9770 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return; 10331 {
10332 m_host.TaskInventory.LockItemsForRead(false);
10333 return;
10334 }
10335 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0)
10336 {
10337 m_host.TaskInventory.LockItemsForRead(false);
10338 return;
9771 } 10339 }
10340 m_host.TaskInventory.LockItemsForRead(false);
9772 10341
9773 ScenePresence presence = World.GetScenePresence(agentID); 10342 ScenePresence presence = World.GetScenePresence(agentID);
9774 10343
@@ -9777,12 +10346,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9777 10346
9778 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>(); 10347 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
9779 object[] data = rules.Data; 10348 object[] data = rules.Data;
9780 for (int i = 0; i < data.Length; ++i) { 10349 for (int i = 0; i < data.Length; ++i)
10350 {
9781 int type = Convert.ToInt32(data[i++].ToString()); 10351 int type = Convert.ToInt32(data[i++].ToString());
9782 if (i >= data.Length) break; // odd number of entries => ignore the last 10352 if (i >= data.Length) break; // odd number of entries => ignore the last
9783 10353
9784 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3) 10354 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
9785 switch (type) { 10355 switch (type)
10356 {
9786 case ScriptBaseClass.CAMERA_FOCUS: 10357 case ScriptBaseClass.CAMERA_FOCUS:
9787 case ScriptBaseClass.CAMERA_FOCUS_OFFSET: 10358 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
9788 case ScriptBaseClass.CAMERA_POSITION: 10359 case ScriptBaseClass.CAMERA_POSITION:
@@ -9818,12 +10389,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9818 10389
9819 // we need the permission first, to know which avatar we want to clear the camera for 10390 // we need the permission first, to know which avatar we want to clear the camera for
9820 UUID agentID; 10391 UUID agentID;
9821 lock (m_host.TaskInventory) 10392 m_host.TaskInventory.LockItemsForRead(true);
10393 agentID = m_host.TaskInventory[invItemID].PermsGranter;
10394 if (agentID == UUID.Zero)
9822 { 10395 {
9823 agentID = m_host.TaskInventory[invItemID].PermsGranter; 10396 m_host.TaskInventory.LockItemsForRead(false);
9824 if (agentID == UUID.Zero) return; 10397 return;
9825 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return;
9826 } 10398 }
10399 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0)
10400 {
10401 m_host.TaskInventory.LockItemsForRead(false);
10402 return;
10403 }
10404 m_host.TaskInventory.LockItemsForRead(false);
9827 10405
9828 ScenePresence presence = World.GetScenePresence(agentID); 10406 ScenePresence presence = World.GetScenePresence(agentID);
9829 10407
@@ -9890,19 +10468,65 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9890 public LSL_String llXorBase64StringsCorrect(string str1, string str2) 10468 public LSL_String llXorBase64StringsCorrect(string str1, string str2)
9891 { 10469 {
9892 m_host.AddScriptLPS(1); 10470 m_host.AddScriptLPS(1);
9893 string ret = String.Empty; 10471
9894 string src1 = llBase64ToString(str1); 10472 if (str1 == String.Empty)
9895 string src2 = llBase64ToString(str2); 10473 return String.Empty;
9896 int c = 0; 10474 if (str2 == String.Empty)
9897 for (int i = 0; i < src1.Length; i++) 10475 return str1;
10476
10477 int len = str2.Length;
10478 if ((len % 4) != 0) // LL is EVIL!!!!
10479 {
10480 while (str2.EndsWith("="))
10481 str2 = str2.Substring(0, str2.Length - 1);
10482
10483 len = str2.Length;
10484 int mod = len % 4;
10485
10486 if (mod == 1)
10487 str2 = str2.Substring(0, str2.Length - 1);
10488 else if (mod == 2)
10489 str2 += "==";
10490 else if (mod == 3)
10491 str2 += "=";
10492 }
10493
10494 byte[] data1;
10495 byte[] data2;
10496 try
9898 { 10497 {
9899 ret += (char) (src1[i] ^ src2[c]); 10498 data1 = Convert.FromBase64String(str1);
10499 data2 = Convert.FromBase64String(str2);
10500 }
10501 catch (Exception)
10502 {
10503 return new LSL_String(String.Empty);
10504 }
9900 10505
9901 c++; 10506 byte[] d2 = new Byte[data1.Length];
9902 if (c >= src2.Length) 10507 int pos = 0;
9903 c = 0; 10508
10509 if (data1.Length <= data2.Length)
10510 {
10511 Array.Copy(data2, 0, d2, 0, data1.Length);
9904 } 10512 }
9905 return llStringToBase64(ret); 10513 else
10514 {
10515 while (pos < data1.Length)
10516 {
10517 len = data1.Length - pos;
10518 if (len > data2.Length)
10519 len = data2.Length;
10520
10521 Array.Copy(data2, 0, d2, pos, len);
10522 pos += len;
10523 }
10524 }
10525
10526 for (pos = 0 ; pos < data1.Length ; pos++ )
10527 data1[pos] ^= d2[pos];
10528
10529 return Convert.ToBase64String(data1);
9906 } 10530 }
9907 10531
9908 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body) 10532 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
@@ -9959,12 +10583,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9959 Regex r = new Regex(authregex); 10583 Regex r = new Regex(authregex);
9960 int[] gnums = r.GetGroupNumbers(); 10584 int[] gnums = r.GetGroupNumbers();
9961 Match m = r.Match(url); 10585 Match m = r.Match(url);
9962 if (m.Success) { 10586 if (m.Success)
9963 for (int i = 1; i < gnums.Length; i++) { 10587 {
10588 for (int i = 1; i < gnums.Length; i++)
10589 {
9964 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]]; 10590 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]];
9965 //CaptureCollection cc = g.Captures; 10591 //CaptureCollection cc = g.Captures;
9966 } 10592 }
9967 if (m.Groups.Count == 5) { 10593 if (m.Groups.Count == 5)
10594 {
9968 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString()))); 10595 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString())));
9969 url = m.Groups[1].ToString() + m.Groups[4].ToString(); 10596 url = m.Groups[1].ToString() + m.Groups[4].ToString();
9970 } 10597 }
@@ -10250,15 +10877,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10250 10877
10251 internal UUID ScriptByName(string name) 10878 internal UUID ScriptByName(string name)
10252 { 10879 {
10253 lock (m_host.TaskInventory) 10880 m_host.TaskInventory.LockItemsForRead(true);
10881
10882 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
10254 { 10883 {
10255 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 10884 if (item.Type == 10 && item.Name == name)
10256 { 10885 {
10257 if (item.Type == 10 && item.Name == name) 10886 m_host.TaskInventory.LockItemsForRead(false);
10258 return item.ItemID; 10887 return item.ItemID;
10259 } 10888 }
10260 } 10889 }
10261 10890
10891 m_host.TaskInventory.LockItemsForRead(false);
10892
10262 return UUID.Zero; 10893 return UUID.Zero;
10263 } 10894 }
10264 10895
@@ -10299,6 +10930,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10299 { 10930 {
10300 m_host.AddScriptLPS(1); 10931 m_host.AddScriptLPS(1);
10301 10932
10933 //Clone is thread safe
10302 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 10934 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10303 10935
10304 UUID assetID = UUID.Zero; 10936 UUID assetID = UUID.Zero;
@@ -10361,6 +10993,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10361 { 10993 {
10362 m_host.AddScriptLPS(1); 10994 m_host.AddScriptLPS(1);
10363 10995
10996 //Clone is thread safe
10364 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 10997 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10365 10998
10366 UUID assetID = UUID.Zero; 10999 UUID assetID = UUID.Zero;
@@ -10441,15 +11074,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10441 return GetLinkPrimitiveParams(obj, rules); 11074 return GetLinkPrimitiveParams(obj, rules);
10442 } 11075 }
10443 11076
10444 public void print(string str) 11077 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
10445 { 11078 {
10446 // yes, this is a real LSL function. See: http://wiki.secondlife.com/wiki/Print 11079 List<SceneObjectPart> parts = GetLinkParts(link);
10447 IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_itemID, "OSSL"); 11080 if (parts.Count < 1)
10448 if (ossl != null) 11081 return 0;
10449 { 11082
10450 ossl.CheckThreatLevel(ThreatLevel.High, "print"); 11083 return GetNumberOfSides(parts[0]);
10451 m_log.Info("LSL print():" + str);
10452 }
10453 } 11084 }
10454 11085
10455 private string Name2Username(string name) 11086 private string Name2Username(string name)
@@ -10495,153 +11126,392 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10495 return rq.ToString(); 11126 return rq.ToString();
10496 } 11127 }
10497 11128
11129 private void SayShoutTimerElapsed(Object sender, ElapsedEventArgs args)
11130 {
11131 m_SayShoutCount = 0;
11132 }
11133
11134 private struct Tri
11135 {
11136 public Vector3 p1;
11137 public Vector3 p2;
11138 public Vector3 p3;
11139 }
11140
11141 private bool InBoundingBox(ScenePresence avatar, Vector3 point)
11142 {
11143 float height = avatar.Appearance.AvatarHeight;
11144 Vector3 b1 = avatar.AbsolutePosition + new Vector3(-0.22f, -0.22f, -height/2);
11145 Vector3 b2 = avatar.AbsolutePosition + new Vector3(0.22f, 0.22f, height/2);
11146
11147 if (point.X > b1.X && point.X < b2.X &&
11148 point.Y > b1.Y && point.Y < b2.Y &&
11149 point.Z > b1.Z && point.Z < b2.Z)
11150 return true;
11151 return false;
11152 }
11153
11154 private ContactResult[] AvatarIntersection(Vector3 rayStart, Vector3 rayEnd)
11155 {
11156 List<ContactResult> contacts = new List<ContactResult>();
11157
11158 Vector3 ab = rayEnd - rayStart;
11159
11160 World.ForEachScenePresence(delegate(ScenePresence sp)
11161 {
11162 Vector3 ac = sp.AbsolutePosition - rayStart;
11163 Vector3 bc = sp.AbsolutePosition - rayEnd;
11164
11165 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11166
11167 if (d > 1.5)
11168 return;
11169
11170 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
11171
11172 if (d2 > 0)
11173 return;
11174
11175 double dp = Math.Sqrt(Vector3.Mag(ac) * Vector3.Mag(ac) - d * d);
11176 Vector3 p = rayStart + Vector3.Divide(Vector3.Multiply(ab, (float)dp), (float)Vector3.Mag(ab));
11177
11178 if (!InBoundingBox(sp, p))
11179 return;
11180
11181 ContactResult result = new ContactResult ();
11182 result.ConsumerID = sp.LocalId;
11183 result.Depth = Vector3.Distance(rayStart, p);
11184 result.Normal = Vector3.Zero;
11185 result.Pos = p;
11186
11187 contacts.Add(result);
11188 });
11189
11190 return contacts.ToArray();
11191 }
11192
11193 private ContactResult[] ObjectIntersection(Vector3 rayStart, Vector3 rayEnd, bool includePhysical, bool includeNonPhysical, bool includePhantom)
11194 {
11195 Ray ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart));
11196 List<ContactResult> contacts = new List<ContactResult>();
11197
11198 Vector3 ab = rayEnd - rayStart;
11199
11200 World.ForEachSOG(delegate(SceneObjectGroup group)
11201 {
11202 if (m_host.ParentGroup == group)
11203 return;
11204
11205 if (group.IsAttachment)
11206 return;
11207
11208 if (group.RootPart.PhysActor == null)
11209 {
11210 if (!includePhantom)
11211 return;
11212 }
11213 else
11214 {
11215 if (group.RootPart.PhysActor.IsPhysical)
11216 {
11217 if (!includePhysical)
11218 return;
11219 }
11220 else
11221 {
11222 if (!includeNonPhysical)
11223 return;
11224 }
11225 }
11226
11227 // Find the radius ouside of which we don't even need to hit test
11228 float minX;
11229 float maxX;
11230 float minY;
11231 float maxY;
11232 float minZ;
11233 float maxZ;
11234
11235 float radius = 0.0f;
11236
11237 group.GetAxisAlignedBoundingBoxRaw(out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
11238
11239 if (Math.Abs(minX) > radius)
11240 radius = Math.Abs(minX);
11241 if (Math.Abs(minY) > radius)
11242 radius = Math.Abs(minY);
11243 if (Math.Abs(minZ) > radius)
11244 radius = Math.Abs(minZ);
11245 if (Math.Abs(maxX) > radius)
11246 radius = Math.Abs(maxX);
11247 if (Math.Abs(maxY) > radius)
11248 radius = Math.Abs(maxY);
11249 if (Math.Abs(maxZ) > radius)
11250 radius = Math.Abs(maxZ);
11251
11252 Vector3 ac = group.AbsolutePosition - rayStart;
11253 Vector3 bc = group.AbsolutePosition - rayEnd;
11254
11255 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11256
11257 // Too far off ray, don't bother
11258 if (d > radius)
11259 return;
11260
11261 // Behind ray, drop
11262 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
11263 if (d2 > 0)
11264 return;
11265
11266 EntityIntersection intersection = group.TestIntersection(ray, true, false);
11267 // Miss.
11268 if (!intersection.HitTF)
11269 return;
11270
11271 ContactResult result = new ContactResult ();
11272 result.ConsumerID = group.LocalId;
11273 result.Depth = intersection.distance;
11274 result.Normal = intersection.normal;
11275 result.Pos = intersection.ipoint;
11276
11277 contacts.Add(result);
11278 });
11279
11280 return contacts.ToArray();
11281 }
11282
11283 private ContactResult? GroundIntersection(Vector3 rayStart, Vector3 rayEnd)
11284 {
11285 double[,] heightfield = World.Heightmap.GetDoubles();
11286 List<ContactResult> contacts = new List<ContactResult>();
11287
11288 double min = 2048.0;
11289 double max = 0.0;
11290
11291 // Find the min and max of the heightfield
11292 for (int x = 0 ; x < World.Heightmap.Width ; x++)
11293 {
11294 for (int y = 0 ; y < World.Heightmap.Height ; y++)
11295 {
11296 if (heightfield[x, y] > max)
11297 max = heightfield[x, y];
11298 if (heightfield[x, y] < min)
11299 min = heightfield[x, y];
11300 }
11301 }
11302
11303
11304 // A ray extends past rayEnd, but doesn't go back before
11305 // rayStart. If the start is above the highest point of the ground
11306 // and the ray goes up, we can't hit the ground. Ever.
11307 if (rayStart.Z > max && rayEnd.Z >= rayStart.Z)
11308 return null;
11309
11310 // Same for going down
11311 if (rayStart.Z < min && rayEnd.Z <= rayStart.Z)
11312 return null;
11313
11314 List<Tri> trilist = new List<Tri>();
11315
11316 // Create our triangle list
11317 for (int x = 1 ; x < World.Heightmap.Width ; x++)
11318 {
11319 for (int y = 1 ; y < World.Heightmap.Height ; y++)
11320 {
11321 Tri t1 = new Tri();
11322 Tri t2 = new Tri();
11323
11324 Vector3 p1 = new Vector3(x-1, y-1, (float)heightfield[x-1, y-1]);
11325 Vector3 p2 = new Vector3(x, y-1, (float)heightfield[x, y-1]);
11326 Vector3 p3 = new Vector3(x, y, (float)heightfield[x, y]);
11327 Vector3 p4 = new Vector3(x-1, y, (float)heightfield[x-1, y]);
11328
11329 t1.p1 = p1;
11330 t1.p2 = p2;
11331 t1.p3 = p3;
11332
11333 t2.p1 = p3;
11334 t2.p2 = p4;
11335 t2.p3 = p1;
11336
11337 trilist.Add(t1);
11338 trilist.Add(t2);
11339 }
11340 }
11341
11342 // Ray direction
11343 Vector3 rayDirection = rayEnd - rayStart;
11344
11345 foreach (Tri t in trilist)
11346 {
11347 // Compute triangle plane normal and edges
11348 Vector3 u = t.p2 - t.p1;
11349 Vector3 v = t.p3 - t.p1;
11350 Vector3 n = Vector3.Cross(u, v);
11351
11352 if (n == Vector3.Zero)
11353 continue;
11354
11355 Vector3 w0 = rayStart - t.p1;
11356 double a = -Vector3.Dot(n, w0);
11357 double b = Vector3.Dot(n, rayDirection);
11358
11359 // Not intersecting the plane, or in plane (same thing)
11360 // Ignoring this MAY cause the ground to not be detected
11361 // sometimes
11362 if (Math.Abs(b) < 0.000001)
11363 continue;
11364
11365 double r = a / b;
11366
11367 // ray points away from plane
11368 if (r < 0.0)
11369 continue;
11370
11371 Vector3 ip = rayStart + Vector3.Multiply(rayDirection, (float)r);
11372
11373 float uu = Vector3.Dot(u, u);
11374 float uv = Vector3.Dot(u, v);
11375 float vv = Vector3.Dot(v, v);
11376 Vector3 w = ip - t.p1;
11377 float wu = Vector3.Dot(w, u);
11378 float wv = Vector3.Dot(w, v);
11379 float d = uv * uv - uu * vv;
11380
11381 float cs = (uv * wv - vv * wu) / d;
11382 if (cs < 0 || cs > 1.0)
11383 continue;
11384 float ct = (uv * wu - uu * wv) / d;
11385 if (ct < 0 || (cs + ct) > 1.0)
11386 continue;
11387
11388 // Add contact point
11389 ContactResult result = new ContactResult ();
11390 result.ConsumerID = 0;
11391 result.Depth = Vector3.Distance(rayStart, ip);
11392 result.Normal = n;
11393 result.Pos = ip;
11394
11395 contacts.Add(result);
11396 }
11397
11398 if (contacts.Count == 0)
11399 return null;
11400
11401 contacts.Sort(delegate(ContactResult a, ContactResult b)
11402 {
11403 return (int)(a.Depth - b.Depth);
11404 });
11405
11406 return contacts[0];
11407 }
11408
10498 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) 11409 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
10499 { 11410 {
11411 LSL_List list = new LSL_List();
11412
10500 m_host.AddScriptLPS(1); 11413 m_host.AddScriptLPS(1);
10501 11414
10502 Vector3 dir = new Vector3((float)(end-start).x, (float)(end-start).y, (float)(end-start).z); 11415 Vector3 rayStart = new Vector3((float)start.x, (float)start.y, (float)start.z);
10503 Vector3 startvector = new Vector3((float)start.x, (float)start.y, (float)start.z); 11416 Vector3 rayEnd = new Vector3((float)end.x, (float)end.y, (float)end.z);
10504 Vector3 endvector = new Vector3((float)end.x, (float)end.y, (float)end.z); 11417 Vector3 dir = rayEnd - rayStart;
10505 11418
10506 int count = 0; 11419 int count = 1;
10507// int detectPhantom = 0; 11420 bool detectPhantom = false;
10508 int dataFlags = 0; 11421 int dataFlags = 0;
10509 int rejectTypes = 0; 11422 int rejectTypes = 0;
10510 11423
10511 for (int i = 0; i < options.Length; i += 2) 11424 for (int i = 0; i < options.Length; i += 2)
10512 { 11425 {
10513 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS) 11426 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS)
10514 {
10515 count = options.GetLSLIntegerItem(i + 1); 11427 count = options.GetLSLIntegerItem(i + 1);
10516 } 11428 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM)
10517// else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM) 11429 detectPhantom = (options.GetLSLIntegerItem(i + 1) > 0);
10518// {
10519// detectPhantom = options.GetLSLIntegerItem(i + 1);
10520// }
10521 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS) 11430 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS)
10522 {
10523 dataFlags = options.GetLSLIntegerItem(i + 1); 11431 dataFlags = options.GetLSLIntegerItem(i + 1);
10524 }
10525 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES) 11432 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES)
10526 {
10527 rejectTypes = options.GetLSLIntegerItem(i + 1); 11433 rejectTypes = options.GetLSLIntegerItem(i + 1);
10528 }
10529 } 11434 }
10530 11435
10531 LSL_List list = new LSL_List(); 11436 if (count > 16)
10532 List<ContactResult> results = World.PhysicsScene.RaycastWorld(startvector, dir, dir.Length(), count); 11437 count = 16;
10533
10534 double distance = Util.GetDistanceTo(startvector, endvector);
10535 11438
10536 if (distance == 0) 11439 List<ContactResult> results = new List<ContactResult>();
10537 distance = 0.001;
10538
10539 Vector3 posToCheck = startvector;
10540 ITerrainChannel channel = World.RequestModuleInterface<ITerrainChannel>();
10541 11440
10542 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND); 11441 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND);
10543 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS); 11442 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS);
10544 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL); 11443 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL);
10545 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); 11444 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL);
10546 11445
10547 for (float i = 0; i <= distance; i += 0.1f) 11446 if (checkTerrain)
10548 { 11447 {
10549 posToCheck = startvector + (dir * (i / (float)distance)); 11448 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
11449 if (groundContact != null)
11450 results.Add((ContactResult)groundContact);
11451 }
10550 11452
10551 if (checkTerrain && channel[(int)(posToCheck.X + startvector.X), (int)(posToCheck.Y + startvector.Y)] < posToCheck.Z) 11453 if (checkAgents)
10552 { 11454 {
10553 ContactResult result = new ContactResult(); 11455 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
10554 result.ConsumerID = 0; 11456 foreach (ContactResult r in agentHits)
10555 result.Depth = 0; 11457 results.Add(r);
10556 result.Normal = Vector3.Zero; 11458 }
10557 result.Pos = posToCheck;
10558 results.Add(result);
10559 checkTerrain = false;
10560 }
10561 11459
10562 if (checkAgents) 11460 if (checkPhysical || checkNonPhysical)
10563 { 11461 {
10564 World.ForEachRootScenePresence(delegate(ScenePresence sp) 11462 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom);
10565 { 11463 foreach (ContactResult r in objectHits)
10566 if (sp.AbsolutePosition.ApproxEquals(posToCheck, sp.PhysicsActor.Size.X)) 11464 results.Add(r);
10567 {
10568 ContactResult result = new ContactResult ();
10569 result.ConsumerID = sp.LocalId;
10570 result.Depth = 0;
10571 result.Normal = Vector3.Zero;
10572 result.Pos = posToCheck;
10573 results.Add(result);
10574 }
10575 });
10576 }
10577 } 11465 }
10578 11466
10579 int refcount = 0; 11467 results.Sort(delegate(ContactResult a, ContactResult b)
11468 {
11469 return (int)(a.Depth - b.Depth);
11470 });
11471
11472 int values = 0;
10580 foreach (ContactResult result in results) 11473 foreach (ContactResult result in results)
10581 { 11474 {
10582 if ((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) 11475 UUID itemID = UUID.Zero;
10583 == ScriptBaseClass.RC_REJECT_LAND && result.ConsumerID == 0) 11476 int linkNum = 0;
10584 continue;
10585
10586 ISceneEntity entity = World.GetSceneObjectPart(result.ConsumerID);
10587 11477
10588 if (entity == null && (rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) != ScriptBaseClass.RC_REJECT_AGENTS) 11478 SceneObjectPart part = World.GetSceneObjectPart(result.ConsumerID);
10589 entity = World.GetScenePresence(result.ConsumerID); //Only check if we should be looking for agents 11479 // It's a prim!
10590 11480 if (part != null)
10591 if (entity == null)
10592 { 11481 {
10593 list.Add(UUID.Zero); 11482 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY)
10594 11483 itemID = part.ParentGroup.UUID;
10595 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) 11484 else
10596 list.Add(0); 11485 itemID = part.UUID;
10597
10598 list.Add(result.Pos);
10599
10600 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
10601 list.Add(result.Normal);
10602 11486
10603 continue; //Can't find it, so add UUID.Zero 11487 linkNum = part.LinkNum;
10604 } 11488 }
10605 11489 else
10606 /*if (detectPhantom == 0 && intersection.obj is ISceneChildEntity &&
10607 ((ISceneChildEntity)intersection.obj).PhysActor == null)
10608 continue;*/ //Can't do this ATM, physics engine knows only of non phantom objects
10609
10610 if (entity is SceneObjectPart)
10611 { 11490 {
10612 if (((SceneObjectPart)entity).PhysActor != null && ((SceneObjectPart)entity).PhysActor.IsPhysical) 11491 ScenePresence sp = World.GetScenePresence(result.ConsumerID);
10613 { 11492 /// It it a boy? a girl?
10614 if (!checkPhysical) 11493 if (sp != null)
10615 continue; 11494 itemID = sp.UUID;
10616 }
10617 else
10618 {
10619 if (!checkNonPhysical)
10620 continue;
10621 }
10622 } 11495 }
10623 11496
10624 refcount++; 11497 list.Add(new LSL_String(itemID.ToString()));
10625 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY && entity is SceneObjectPart) 11498 list.Add(new LSL_String(result.Pos.ToString()));
10626 list.Add(((SceneObjectPart)entity).ParentGroup.UUID);
10627 else
10628 list.Add(entity.UUID);
10629 11499
10630 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) 11500 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
10631 { 11501 list.Add(new LSL_Integer(linkNum));
10632 if (entity is SceneObjectPart)
10633 list.Add(((SceneObjectPart)entity).LinkNum);
10634 else
10635 list.Add(0);
10636 }
10637 11502
10638 list.Add(result.Pos);
10639 11503
10640 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) 11504 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
10641 list.Add(result.Normal); 11505 list.Add(new LSL_Vector(result.Normal.X, result.Normal.Y, result.Normal.Z));
11506
11507 values++;
11508 count--;
11509
11510 if (count == 0)
11511 break;
10642 } 11512 }
10643 11513
10644 list.Add(refcount); //The status code, either the # of contacts, RCERR_SIM_PERF_LOW, or RCERR_CAST_TIME_EXCEEDED 11514 list.Add(new LSL_Integer(values));
10645 11515
10646 return list; 11516 return list;
10647 } 11517 }
@@ -10681,7 +11551,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10681 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD: 11551 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD:
10682 if (!isAccount) return 0; 11552 if (!isAccount) return 0;
10683 if (estate.HasAccess(id)) return 1; 11553 if (estate.HasAccess(id)) return 1;
10684 if (estate.IsBanned(id)) 11554 if (estate.IsBanned(id, World.GetUserFlags(id)))
10685 estate.RemoveBan(id); 11555 estate.RemoveBan(id);
10686 estate.AddEstateUser(id); 11556 estate.AddEstateUser(id);
10687 break; 11557 break;
@@ -10700,14 +11570,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10700 break; 11570 break;
10701 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD: 11571 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD:
10702 if (!isAccount) return 0; 11572 if (!isAccount) return 0;
10703 if (estate.IsBanned(id)) return 1; 11573 if (estate.IsBanned(id, World.GetUserFlags(id))) return 1;
10704 EstateBan ban = new EstateBan(); 11574 EstateBan ban = new EstateBan();
10705 ban.EstateID = estate.EstateID; 11575 ban.EstateID = estate.EstateID;
10706 ban.BannedUserID = id; 11576 ban.BannedUserID = id;
10707 estate.AddBan(ban); 11577 estate.AddBan(ban);
10708 break; 11578 break;
10709 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE: 11579 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE:
10710 if (!isAccount || !estate.IsBanned(id)) return 0; 11580 if (!isAccount || !estate.IsBanned(id, World.GetUserFlags(id))) return 0;
10711 estate.RemoveBan(id); 11581 estate.RemoveBan(id);
10712 break; 11582 break;
10713 default: return 0; 11583 default: return 0;
@@ -10733,22 +11603,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10733 NotImplemented("llGetSPMaxMemory"); 11603 NotImplemented("llGetSPMaxMemory");
10734 } 11604 }
10735 11605
10736 public void llGetUsedMemory() 11606 public virtual LSL_Integer llGetUsedMemory()
10737 { 11607 {
10738 m_host.AddScriptLPS(1); 11608 m_host.AddScriptLPS(1);
10739 NotImplemented("llGetUsedMemory"); 11609 NotImplemented("llGetUsedMemory");
11610 return 0;
10740 } 11611 }
10741 11612
10742 public void llScriptProfiler(LSL_Integer flags) 11613 public void llScriptProfiler(LSL_Integer flags)
10743 { 11614 {
10744 m_host.AddScriptLPS(1); 11615 m_host.AddScriptLPS(1);
10745 NotImplemented("llScriptProfiler"); 11616 //NotImplemented("llScriptProfiler");
10746 } 11617 }
10747 11618
10748 public void llSetSoundQueueing(int queue) 11619 public void llSetSoundQueueing(int queue)
10749 { 11620 {
10750 m_host.AddScriptLPS(1); 11621 m_host.AddScriptLPS(1);
10751 NotImplemented("llSetSoundQueueing");
10752 } 11622 }
10753 11623
10754 public void llCollisionSprite(string impact_sprite) 11624 public void llCollisionSprite(string impact_sprite)
@@ -10760,7 +11630,133 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10760 public void llGodLikeRezObject(string inventory, LSL_Vector pos) 11630 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
10761 { 11631 {
10762 m_host.AddScriptLPS(1); 11632 m_host.AddScriptLPS(1);
10763 NotImplemented("llGodLikeRezObject"); 11633
11634 if (!World.Permissions.IsGod(m_host.OwnerID))
11635 NotImplemented("llGodLikeRezObject");
11636
11637 AssetBase rezAsset = World.AssetService.Get(inventory);
11638 if (rezAsset == null)
11639 {
11640 llSay(0, "Asset not found");
11641 return;
11642 }
11643
11644 SceneObjectGroup group = null;
11645
11646 try
11647 {
11648 string xmlData = Utils.BytesToString(rezAsset.Data);
11649 group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
11650 }
11651 catch
11652 {
11653 llSay(0, "Asset not found");
11654 return;
11655 }
11656
11657 if (group == null)
11658 {
11659 llSay(0, "Asset not found");
11660 return;
11661 }
11662
11663 group.RootPart.AttachPoint = group.RootPart.Shape.State;
11664 group.RootPart.AttachOffset = group.AbsolutePosition;
11665
11666 group.ResetIDs();
11667
11668 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
11669 World.AddNewSceneObject(group, true, llpos, Quaternion.Identity, Vector3.Zero);
11670 group.CreateScriptInstances(0, true, World.DefaultScriptEngine, 3);
11671 group.ScheduleGroupForFullUpdate();
11672
11673 // objects rezzed with this method are die_at_edge by default.
11674 group.RootPart.SetDieAtEdge(true);
11675
11676 group.ResumeScripts();
11677
11678 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
11679 "object_rez", new Object[] {
11680 new LSL_String(
11681 group.RootPart.UUID.ToString()) },
11682 new DetectParams[0]));
11683 }
11684
11685 public LSL_String llTransferLindenDollars(string destination, int amount)
11686 {
11687 UUID txn = UUID.Random();
11688
11689 Util.FireAndForget(delegate(object x)
11690 {
11691 int replycode = 0;
11692 string replydata = destination + "," + amount.ToString();
11693
11694 try
11695 {
11696 UUID invItemID=InventorySelf();
11697 if (invItemID == UUID.Zero)
11698 {
11699 replydata = "SERVICE_ERROR";
11700 return;
11701 }
11702
11703 m_host.AddScriptLPS(1);
11704
11705 m_host.TaskInventory.LockItemsForRead(true);
11706 TaskInventoryItem item = m_host.TaskInventory[invItemID];
11707 m_host.TaskInventory.LockItemsForRead(false);
11708
11709 if (item.PermsGranter == UUID.Zero)
11710 {
11711 replydata = "MISSING_PERMISSION_DEBIT";
11712 return;
11713 }
11714
11715 if ((item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
11716 {
11717 replydata = "MISSING_PERMISSION_DEBIT";
11718 return;
11719 }
11720
11721 UUID toID = new UUID();
11722
11723 if (!UUID.TryParse(destination, out toID))
11724 {
11725 replydata = "INVALID_AGENT";
11726 return;
11727 }
11728
11729 IMoneyModule money = World.RequestModuleInterface<IMoneyModule>();
11730
11731 if (money == null)
11732 {
11733 replydata = "TRANSFERS_DISABLED";
11734 return;
11735 }
11736
11737 bool result = money.ObjectGiveMoney(
11738 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
11739
11740 if (result)
11741 {
11742 replycode = 1;
11743 return;
11744 }
11745
11746 replydata = "LINDENDOLLAR_INSUFFICIENTFUNDS";
11747 }
11748 finally
11749 {
11750 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
11751 "transaction_result", new Object[] {
11752 new LSL_String(txn.ToString()),
11753 new LSL_Integer(replycode),
11754 new LSL_String(replydata) },
11755 new DetectParams[0]));
11756 }
11757 });
11758
11759 return txn.ToString();
10764 } 11760 }
10765 11761
10766 #endregion 11762 #endregion
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index b1583eb..1f1d45e 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -137,6 +137,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
137 internal ThreatLevel m_MaxThreatLevel = ThreatLevel.VeryLow; 137 internal ThreatLevel m_MaxThreatLevel = ThreatLevel.VeryLow;
138 internal float m_ScriptDelayFactor = 1.0f; 138 internal float m_ScriptDelayFactor = 1.0f;
139 internal float m_ScriptDistanceFactor = 1.0f; 139 internal float m_ScriptDistanceFactor = 1.0f;
140 internal bool m_debuggerSafe = false;
140 internal Dictionary<string, FunctionPerms > m_FunctionPerms = new Dictionary<string, FunctionPerms >(); 141 internal Dictionary<string, FunctionPerms > m_FunctionPerms = new Dictionary<string, FunctionPerms >();
141 142
142 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) 143 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID)
@@ -145,6 +146,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
145 m_host = host; 146 m_host = host;
146 m_localID = localID; 147 m_localID = localID;
147 m_itemID = itemID; 148 m_itemID = itemID;
149 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
148 150
149 if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false)) 151 if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false))
150 m_OSFunctionsEnabled = true; 152 m_OSFunctionsEnabled = true;
@@ -206,7 +208,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
206 208
207 internal void OSSLError(string msg) 209 internal void OSSLError(string msg)
208 { 210 {
209 throw new Exception("OSSL Runtime Error: " + msg); 211 if (m_debuggerSafe)
212 {
213 OSSLShoutError(msg);
214 }
215 else
216 {
217 throw new Exception("OSSL Runtime Error: " + msg);
218 }
210 } 219 }
211 220
212 private void InitLSL() 221 private void InitLSL()
@@ -917,18 +926,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
917 if (target != null) 926 if (target != null)
918 { 927 {
919 UUID animID=UUID.Zero; 928 UUID animID=UUID.Zero;
920 lock (m_host.TaskInventory) 929 m_host.TaskInventory.LockItemsForRead(true);
930 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
921 { 931 {
922 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 932 if (inv.Value.Name == animation)
923 { 933 {
924 if (inv.Value.Name == animation) 934 if (inv.Value.Type == (int)AssetType.Animation)
925 { 935 animID = inv.Value.AssetID;
926 if (inv.Value.Type == (int)AssetType.Animation) 936 continue;
927 animID = inv.Value.AssetID;
928 continue;
929 }
930 } 937 }
931 } 938 }
939 m_host.TaskInventory.LockItemsForRead(false);
932 if (animID == UUID.Zero) 940 if (animID == UUID.Zero)
933 target.Animator.AddAnimation(animation, m_host.UUID); 941 target.Animator.AddAnimation(animation, m_host.UUID);
934 else 942 else
@@ -955,18 +963,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
955 if (target != null) 963 if (target != null)
956 { 964 {
957 UUID animID = UUID.Zero; 965 UUID animID = UUID.Zero;
958 lock (m_host.TaskInventory) 966 m_host.TaskInventory.LockItemsForRead(true);
967 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
959 { 968 {
960 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 969 if (inv.Value.Name == animation)
961 { 970 {
962 if (inv.Value.Name == animation) 971 if (inv.Value.Type == (int)AssetType.Animation)
963 { 972 animID = inv.Value.AssetID;
964 if (inv.Value.Type == (int)AssetType.Animation) 973 continue;
965 animID = inv.Value.AssetID;
966 continue;
967 }
968 } 974 }
969 } 975 }
976 m_host.TaskInventory.LockItemsForRead(false);
970 977
971 if (animID == UUID.Zero) 978 if (animID == UUID.Zero)
972 target.Animator.RemoveAnimation(animation); 979 target.Animator.RemoveAnimation(animation);
@@ -1798,6 +1805,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1798 1805
1799 if (!UUID.TryParse(notecardNameOrUuid, out assetID)) 1806 if (!UUID.TryParse(notecardNameOrUuid, out assetID))
1800 { 1807 {
1808 m_host.TaskInventory.LockItemsForRead(true);
1801 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 1809 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
1802 { 1810 {
1803 if (item.Type == 7 && item.Name == notecardNameOrUuid) 1811 if (item.Type == 7 && item.Name == notecardNameOrUuid)
@@ -1805,6 +1813,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1805 assetID = item.AssetID; 1813 assetID = item.AssetID;
1806 } 1814 }
1807 } 1815 }
1816 m_host.TaskInventory.LockItemsForRead(false);
1808 } 1817 }
1809 1818
1810 if (assetID == UUID.Zero) 1819 if (assetID == UUID.Zero)
@@ -2233,7 +2242,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2233 CheckThreatLevel(ThreatLevel.High, "osNpcCreate"); 2242 CheckThreatLevel(ThreatLevel.High, "osNpcCreate");
2234 m_host.AddScriptLPS(1); 2243 m_host.AddScriptLPS(1);
2235 2244
2236 return NpcCreate(firstname, lastname, position, notecard, false, true); 2245 return NpcCreate(firstname, lastname, position, notecard, true, false);
2237 } 2246 }
2238 2247
2239 public LSL_Key osNpcCreate(string firstname, string lastname, LSL_Vector position, string notecard, int options) 2248 public LSL_Key osNpcCreate(string firstname, string lastname, LSL_Vector position, string notecard, int options)
@@ -2244,24 +2253,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2244 return NpcCreate( 2253 return NpcCreate(
2245 firstname, lastname, position, notecard, 2254 firstname, lastname, position, notecard,
2246 (options & ScriptBaseClass.OS_NPC_NOT_OWNED) == 0, 2255 (options & ScriptBaseClass.OS_NPC_NOT_OWNED) == 0,
2247 (options & ScriptBaseClass.OS_NPC_SENSE_AS_AGENT) == 0); 2256 false);
2257// (options & ScriptBaseClass.OS_NPC_SENSE_AS_AGENT) == 0);
2248 } 2258 }
2249 2259
2250 private LSL_Key NpcCreate( 2260 private LSL_Key NpcCreate(
2251 string firstname, string lastname, LSL_Vector position, string notecard, bool owned, bool senseAsAgent) 2261 string firstname, string lastname, LSL_Vector position, string notecard, bool owned, bool senseAsAgent)
2252 { 2262 {
2263 if (!owned)
2264 OSSLError("Unowned NPCs are unsupported");
2265
2266 string groupTitle = String.Empty;
2267
2268 if (firstname != String.Empty || lastname != String.Empty)
2269 {
2270 if (firstname != "Shown outfit:")
2271 groupTitle = "- NPC -";
2272 }
2273
2253 INPCModule module = World.RequestModuleInterface<INPCModule>(); 2274 INPCModule module = World.RequestModuleInterface<INPCModule>();
2254 if (module != null) 2275 if (module != null)
2255 { 2276 {
2256 AvatarAppearance appearance = null; 2277 AvatarAppearance appearance = null;
2257 2278
2258 UUID id; 2279// UUID id;
2259 if (UUID.TryParse(notecard, out id)) 2280// if (UUID.TryParse(notecard, out id))
2260 { 2281// {
2261 ScenePresence clonePresence = World.GetScenePresence(id); 2282// ScenePresence clonePresence = World.GetScenePresence(id);
2262 if (clonePresence != null) 2283// if (clonePresence != null)
2263 appearance = clonePresence.Appearance; 2284// appearance = clonePresence.Appearance;
2264 } 2285// }
2265 2286
2266 if (appearance == null) 2287 if (appearance == null)
2267 { 2288 {
@@ -2289,6 +2310,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2289 World, 2310 World,
2290 appearance); 2311 appearance);
2291 2312
2313 ScenePresence sp;
2314 if (World.TryGetScenePresence(x, out sp))
2315 {
2316 sp.Grouptitle = groupTitle;
2317 sp.SendAvatarDataToAllAgents();
2318 }
2292 return new LSL_Key(x.ToString()); 2319 return new LSL_Key(x.ToString());
2293 } 2320 }
2294 2321
@@ -2565,7 +2592,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2565 if (!module.CheckPermissions(npcId, m_host.OwnerID)) 2592 if (!module.CheckPermissions(npcId, m_host.OwnerID))
2566 return; 2593 return;
2567 2594
2568 module.DeleteNPC(npcId, World); 2595 Util.FireAndForget(delegate(object x) {
2596 module.DeleteNPC(npcId, World);
2597 });
2569 } 2598 }
2570 } 2599 }
2571 2600
@@ -2917,4 +2946,4 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2917 return date.ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ"); 2946 return date.ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ");
2918 } 2947 }
2919 } 2948 }
2920} \ No newline at end of file 2949}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
index 3e0e452..2a0ce44 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
@@ -209,7 +209,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
209 // Is the sensor type is AGENT and not SCRIPTED then include agents 209 // Is the sensor type is AGENT and not SCRIPTED then include agents
210 if ((ts.type & (AGENT | AGENT_BY_USERNAME | NPC)) != 0 && (ts.type & SCRIPTED) == 0) 210 if ((ts.type & (AGENT | AGENT_BY_USERNAME | NPC)) != 0 && (ts.type & SCRIPTED) == 0)
211 { 211 {
212 sensedEntities.AddRange(doAgentSensor(ts)); 212 sensedEntities.AddRange(doAgentSensor(ts));
213 } 213 }
214 214
215 // If SCRIPTED or PASSIVE or ACTIVE check objects 215 // If SCRIPTED or PASSIVE or ACTIVE check objects
@@ -306,13 +306,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
306 float dy; 306 float dy;
307 float dz; 307 float dz;
308 308
309 Quaternion q = SensePoint.RotationOffset; 309// Quaternion q = SensePoint.RotationOffset;
310 Quaternion q = SensePoint.GetWorldRotation(); // non-attached prim Sensor *always* uses World rotation!
310 if (SensePoint.ParentGroup.IsAttachment) 311 if (SensePoint.ParentGroup.IsAttachment)
311 { 312 {
312 // In attachments, the sensor cone always orients with the 313 // In attachments, the sensor cone always orients with the
313 // avatar rotation. This may include a nonzero elevation if 314 // avatar rotation. This may include a nonzero elevation if
314 // in mouselook. 315 // in mouselook.
315 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar); 316 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar);
317 fromRegionPos = avatar.AbsolutePosition;
316 q = avatar.Rotation; 318 q = avatar.Rotation;
317 } 319 }
318 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); 320 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W);
@@ -435,6 +437,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
435 // avatar rotation. This may include a nonzero elevation if 437 // avatar rotation. This may include a nonzero elevation if
436 // in mouselook. 438 // in mouselook.
437 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar); 439 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar);
440 if (avatar == null)
441 return sensedEntities;
442 fromRegionPos = avatar.AbsolutePosition;
438 q = avatar.Rotation; 443 q = avatar.Rotation;
439 } 444 }
440 445
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs
index eeb59d9..2fd33fe 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs
@@ -109,25 +109,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
109 if (Timers.Count == 0) 109 if (Timers.Count == 0)
110 return; 110 return;
111 111
112 Dictionary<string, TimerClass>.ValueCollection tvals;
112 lock (TimerListLock) 113 lock (TimerListLock)
113 { 114 {
114 // Go through all timers 115 // Go through all timers
115 Dictionary<string, TimerClass>.ValueCollection tvals = Timers.Values; 116 tvals = Timers.Values;
116 foreach (TimerClass ts in tvals) 117 }
118
119 foreach (TimerClass ts in tvals)
120 {
121 // Time has passed?
122 if (ts.next < DateTime.Now.Ticks)
117 { 123 {
118 // Time has passed? 124 //m_log.Debug("Time has passed: Now: " + DateTime.Now.Ticks + ", Passed: " + ts.next);
119 if (ts.next < DateTime.Now.Ticks) 125 // Add it to queue
120 { 126 m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID,
121 //m_log.Debug("Time has passed: Now: " + DateTime.Now.Ticks + ", Passed: " + ts.next); 127 new EventParams("timer", new Object[0],
122 // Add it to queue 128 new DetectParams[0]));
123 m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID, 129 // set next interval
124 new EventParams("timer", new Object[0], 130
125 new DetectParams[0])); 131 //ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
126 // set next interval 132 ts.next = DateTime.Now.Ticks + ts.interval;
127
128 //ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
129 ts.next = DateTime.Now.Ticks + ts.interval;
130 }
131 } 133 }
132 } 134 }
133 } 135 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs
new file mode 100644
index 0000000..ab215f3
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs
@@ -0,0 +1,46 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System.Collections;
29using OpenSim.Region.ScriptEngine.Interfaces;
30
31using key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
32using rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
33using vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
34using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
35using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
36using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
37using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
38
39namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
40{
41 public interface ICM_Api
42 {
43 string cmDetectedCountry(int num);
44 string cmGetAgentCountry(key key);
45 }
46}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
index b66537f..73131e6 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
@@ -123,6 +123,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
123 LSL_Float llGetEnergy(); 123 LSL_Float llGetEnergy();
124 LSL_Vector llGetForce(); 124 LSL_Vector llGetForce();
125 LSL_Integer llGetFreeMemory(); 125 LSL_Integer llGetFreeMemory();
126 LSL_Integer llGetUsedMemory();
126 LSL_Integer llGetFreeURLs(); 127 LSL_Integer llGetFreeURLs();
127 LSL_Vector llGetGeometricCenter(); 128 LSL_Vector llGetGeometricCenter();
128 LSL_Float llGetGMTclock(); 129 LSL_Float llGetGMTclock();
@@ -200,6 +201,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
200 void llGiveInventory(string destination, string inventory); 201 void llGiveInventory(string destination, string inventory);
201 void llGiveInventoryList(string destination, string category, LSL_List inventory); 202 void llGiveInventoryList(string destination, string category, LSL_List inventory);
202 LSL_Integer llGiveMoney(string destination, int amount); 203 LSL_Integer llGiveMoney(string destination, int amount);
204 LSL_String llTransferLindenDollars(string destination, int amount);
203 void llGodLikeRezObject(string inventory, LSL_Vector pos); 205 void llGodLikeRezObject(string inventory, LSL_Vector pos);
204 LSL_Float llGround(LSL_Vector offset); 206 LSL_Float llGround(LSL_Vector offset);
205 LSL_Vector llGroundContour(LSL_Vector offset); 207 LSL_Vector llGroundContour(LSL_Vector offset);
@@ -407,7 +409,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
407 LSL_Vector llWind(LSL_Vector offset); 409 LSL_Vector llWind(LSL_Vector offset);
408 LSL_String llXorBase64Strings(string str1, string str2); 410 LSL_String llXorBase64Strings(string str1, string str2);
409 LSL_String llXorBase64StringsCorrect(string str1, string str2); 411 LSL_String llXorBase64StringsCorrect(string str1, string str2);
410 void print(string str); 412 LSL_Integer llGetLinkNumberOfSides(LSL_Integer link);
411 413
412 void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); 414 void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
413 LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules); 415 LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index dbc1dfc..ca24051 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -85,7 +85,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
85 // Avatar Info Commands 85 // Avatar Info Commands
86 string osGetAgentIP(string agent); 86 string osGetAgentIP(string agent);
87 LSL_List osGetAgents(); 87 LSL_List osGetAgents();
88 88
89 // Teleport commands 89 // Teleport commands
90 void osTeleportAgent(string agent, string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat); 90 void osTeleportAgent(string agent, string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat);
91 void osTeleportAgent(string agent, int regionX, int regionY, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat); 91 void osTeleportAgent(string agent, int regionX, int regionY, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs
new file mode 100644
index 0000000..4132dfa
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs
@@ -0,0 +1,71 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Runtime.Remoting.Lifetime;
30using System.Threading;
31using System.Reflection;
32using System.Collections;
33using System.Collections.Generic;
34using OpenSim.Framework;
35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.ScriptEngine.Interfaces;
37using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces;
38using integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
39using vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
40using rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
41using key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
42using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
43using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
44using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
45using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
46
47namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
48{
49 public partial class ScriptBaseClass : MarshalByRefObject
50 {
51 public ICM_Api m_CM_Functions;
52
53 public void ApiTypeCM(IScriptApi api)
54 {
55 if (!(api is ICM_Api))
56 return;
57
58 m_CM_Functions = (ICM_Api)api;
59 }
60
61 public string cmDetectedCountry(int num)
62 {
63 return m_CM_Functions.cmDetectedCountry(num);
64 }
65
66 public string cmGetAgentCountry(key key)
67 {
68 return m_CM_Functions.cmGetAgentCountry(key);
69 }
70 }
71}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs
index 9615315..943d7a2 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics; //for [DebuggerNonUserCode]
30using System.Reflection; 31using System.Reflection;
31using System.Runtime.Remoting.Lifetime; 32using System.Runtime.Remoting.Lifetime;
32using OpenSim.Region.ScriptEngine.Shared; 33using OpenSim.Region.ScriptEngine.Shared;
@@ -132,6 +133,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
132 return (eventFlags); 133 return (eventFlags);
133 } 134 }
134 135
136 [DebuggerNonUserCode]
135 public void ExecuteEvent(string state, string FunctionName, object[] args) 137 public void ExecuteEvent(string state, string FunctionName, object[] args)
136 { 138 {
137 // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory. 139 // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory.
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
index a69b4cb..9489957 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
@@ -282,6 +282,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
282 public const int CHANGED_REGION_START = 1024; //LL Changed the constant from CHANGED_REGION_RESTART 282 public const int CHANGED_REGION_START = 1024; //LL Changed the constant from CHANGED_REGION_RESTART
283 public const int CHANGED_MEDIA = 2048; 283 public const int CHANGED_MEDIA = 2048;
284 public const int CHANGED_ANIMATION = 16384; 284 public const int CHANGED_ANIMATION = 16384;
285 public const int CHANGED_POSITION = 32768;
285 public const int TYPE_INVALID = 0; 286 public const int TYPE_INVALID = 0;
286 public const int TYPE_INTEGER = 1; 287 public const int TYPE_INTEGER = 1;
287 public const int TYPE_FLOAT = 2; 288 public const int TYPE_FLOAT = 2;
@@ -378,6 +379,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
378 public const int PRIM_SCULPT_TYPE_TORUS = 2; 379 public const int PRIM_SCULPT_TYPE_TORUS = 2;
379 public const int PRIM_SCULPT_TYPE_PLANE = 3; 380 public const int PRIM_SCULPT_TYPE_PLANE = 3;
380 public const int PRIM_SCULPT_TYPE_CYLINDER = 4; 381 public const int PRIM_SCULPT_TYPE_CYLINDER = 4;
382 public const int PRIM_SCULPT_FLAG_INVERT = 64;
383 public const int PRIM_SCULPT_FLAG_MIRROR = 128;
381 384
382 public const int MASK_BASE = 0; 385 public const int MASK_BASE = 0;
383 public const int MASK_OWNER = 1; 386 public const int MASK_OWNER = 1;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
index 840d3a4..a27899f 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Diagnostics; //for [DebuggerNonUserCode]
29using System.Runtime.Remoting.Lifetime; 30using System.Runtime.Remoting.Lifetime;
30using System.Threading; 31using System.Threading;
31using System.Reflection; 32using System.Reflection;
@@ -164,6 +165,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
164 m_LSL_Functions.llBreakLink(linknum); 165 m_LSL_Functions.llBreakLink(linknum);
165 } 166 }
166 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
167 public LSL_Integer llCeil(double f) 173 public LSL_Integer llCeil(double f)
168 { 174 {
169 return m_LSL_Functions.llCeil(f); 175 return m_LSL_Functions.llCeil(f);
@@ -314,6 +320,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
314 m_LSL_Functions.llDialog(avatar, message, buttons, chat_channel); 320 m_LSL_Functions.llDialog(avatar, message, buttons, chat_channel);
315 } 321 }
316 322
323 [DebuggerNonUserCode]
317 public void llDie() 324 public void llDie()
318 { 325 {
319 m_LSL_Functions.llDie(); 326 m_LSL_Functions.llDie();
@@ -464,6 +471,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
464 return m_LSL_Functions.llGetFreeMemory(); 471 return m_LSL_Functions.llGetFreeMemory();
465 } 472 }
466 473
474 public LSL_Integer llGetUsedMemory()
475 {
476 return m_LSL_Functions.llGetUsedMemory();
477 }
478
467 public LSL_Integer llGetFreeURLs() 479 public LSL_Integer llGetFreeURLs()
468 { 480 {
469 return m_LSL_Functions.llGetFreeURLs(); 481 return m_LSL_Functions.llGetFreeURLs();
@@ -844,6 +856,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
844 return m_LSL_Functions.llGiveMoney(destination, amount); 856 return m_LSL_Functions.llGiveMoney(destination, amount);
845 } 857 }
846 858
859 public LSL_String llTransferLindenDollars(string destination, int amount)
860 {
861 return m_LSL_Functions.llTransferLindenDollars(destination, amount);
862 }
863
847 public void llGodLikeRezObject(string inventory, LSL_Vector pos) 864 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
848 { 865 {
849 m_LSL_Functions.llGodLikeRezObject(inventory, pos); 866 m_LSL_Functions.llGodLikeRezObject(inventory, pos);
@@ -1888,9 +1905,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1888 return m_LSL_Functions.llClearPrimMedia(face); 1905 return m_LSL_Functions.llClearPrimMedia(face);
1889 } 1906 }
1890 1907
1891 public void print(string str) 1908 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
1892 { 1909 {
1893 m_LSL_Functions.print(str); 1910 return m_LSL_Functions.llGetLinkNumberOfSides(link);
1894 } 1911 }
1895 } 1912 }
1896} 1913}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs
index 143b497..2e27f16 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs
@@ -72,9 +72,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
72 { 72 {
73 return m_LS_Functions.lsSetWindlightSceneTargeted(rules, target); 73 return m_LS_Functions.lsSetWindlightSceneTargeted(rules, target);
74 } 74 }
75
75 public void lsClearWindlightScene() 76 public void lsClearWindlightScene()
76 { 77 {
77 m_LS_Functions.lsClearWindlightScene(); 78 m_LS_Functions.lsClearWindlightScene();
78 } 79 }
80
81 public LSL_List cmGetWindlightScene(LSL_List rules)
82 {
83 return m_LS_Functions.lsGetWindlightScene(rules);
84 }
85
86 public int cmSetWindlightScene(LSL_List rules)
87 {
88 return m_LS_Functions.lsSetWindlightScene(rules);
89 }
90
91 public int cmSetWindlightSceneTargeted(LSL_List rules, key target)
92 {
93 return m_LS_Functions.lsSetWindlightSceneTargeted(rules, target);
94 }
95
96 public void cmClearWindlightScene()
97 {
98 m_LS_Functions.lsClearWindlightScene();
99 }
79 } 100 }
80} 101}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs
index edbbc2a..b138da3 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs
@@ -33,6 +33,7 @@ using System.Threading;
33using System.Reflection; 33using System.Reflection;
34using System.Collections; 34using System.Collections;
35using System.Collections.Generic; 35using System.Collections.Generic;
36using System.Diagnostics; //for [DebuggerNonUserCode]
36using OpenSim.Region.ScriptEngine.Interfaces; 37using OpenSim.Region.ScriptEngine.Interfaces;
37using OpenSim.Region.ScriptEngine.Shared; 38using OpenSim.Region.ScriptEngine.Shared;
38using OpenSim.Region.ScriptEngine.Shared.Api.Runtime; 39using OpenSim.Region.ScriptEngine.Shared.Api.Runtime;
@@ -90,6 +91,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
90 return (int)m_Executor.GetStateEventFlags(state); 91 return (int)m_Executor.GetStateEventFlags(state);
91 } 92 }
92 93
94 [DebuggerNonUserCode]
93 public void ExecuteEvent(string state, string FunctionName, object[] args) 95 public void ExecuteEvent(string state, string FunctionName, object[] args)
94 { 96 {
95 m_Executor.ExecuteEvent(state, FunctionName, args); 97 m_Executor.ExecuteEvent(state, FunctionName, args);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
index 8cebb4a..7e7e278 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
@@ -35,6 +35,7 @@ using OpenMetaverse;
35using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Region.CoreModules; 36using OpenSim.Region.CoreModules;
37using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Services.Interfaces;
38 39
39namespace OpenSim.Region.ScriptEngine.Shared 40namespace OpenSim.Region.ScriptEngine.Shared
40{ 41{
@@ -95,6 +96,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
95 Type = 0; 96 Type = 0;
96 Velocity = new LSL_Types.Vector3(); 97 Velocity = new LSL_Types.Vector3();
97 initializeSurfaceTouch(); 98 initializeSurfaceTouch();
99 Country = String.Empty;
98 } 100 }
99 101
100 public UUID Key; 102 public UUID Key;
@@ -126,6 +128,8 @@ namespace OpenSim.Region.ScriptEngine.Shared
126 private int touchFace; 128 private int touchFace;
127 public int TouchFace { get { return touchFace; } } 129 public int TouchFace { get { return touchFace; } }
128 130
131 public string Country;
132
129 // This can be done in two places including the constructor 133 // This can be done in two places including the constructor
130 // so be carefull what gets added here 134 // so be carefull what gets added here
131 private void initializeSurfaceTouch() 135 private void initializeSurfaceTouch()
@@ -173,6 +177,10 @@ namespace OpenSim.Region.ScriptEngine.Shared
173 return; 177 return;
174 178
175 Name = presence.Firstname + " " + presence.Lastname; 179 Name = presence.Firstname + " " + presence.Lastname;
180 UserAccount account = scene.UserAccountService.GetUserAccount(scene.RegionInfo.ScopeID, Key);
181 if (account != null)
182 Country = account.UserCountry;
183
176 Owner = Key; 184 Owner = Key;
177 Position = new LSL_Types.Vector3( 185 Position = new LSL_Types.Vector3(
178 presence.AbsolutePosition.X, 186 presence.AbsolutePosition.X,
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index 9b93135..34f2cc7 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.IO; 29using System.IO;
30using System.Diagnostics; //for [DebuggerNonUserCode]
30using System.Runtime.Remoting; 31using System.Runtime.Remoting;
31using System.Runtime.Remoting.Lifetime; 32using System.Runtime.Remoting.Lifetime;
32using System.Threading; 33using System.Threading;
@@ -264,13 +265,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
264 265
265 if (part != null) 266 if (part != null)
266 { 267 {
267 lock (part.TaskInventory) 268 part.TaskInventory.LockItemsForRead(true);
269 if (part.TaskInventory.ContainsKey(m_ItemID))
268 { 270 {
269 if (part.TaskInventory.ContainsKey(m_ItemID)) 271 m_thisScriptTask = part.TaskInventory[m_ItemID];
270 {
271 m_thisScriptTask = part.TaskInventory[m_ItemID];
272 }
273 } 272 }
273 part.TaskInventory.LockItemsForRead(false);
274 } 274 }
275 275
276 ApiManager am = new ApiManager(); 276 ApiManager am = new ApiManager();
@@ -469,14 +469,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
469 { 469 {
470 int permsMask; 470 int permsMask;
471 UUID permsGranter; 471 UUID permsGranter;
472 lock (part.TaskInventory) 472 part.TaskInventory.LockItemsForRead(true);
473 if (!part.TaskInventory.ContainsKey(m_ItemID))
473 { 474 {
474 if (!part.TaskInventory.ContainsKey(m_ItemID)) 475 part.TaskInventory.LockItemsForRead(false);
475 return; 476 return;
476
477 permsGranter = part.TaskInventory[m_ItemID].PermsGranter;
478 permsMask = part.TaskInventory[m_ItemID].PermsMask;
479 } 477 }
478 permsGranter = part.TaskInventory[m_ItemID].PermsGranter;
479 permsMask = part.TaskInventory[m_ItemID].PermsMask;
480 part.TaskInventory.LockItemsForRead(false);
480 481
481 if ((permsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0) 482 if ((permsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)
482 { 483 {
@@ -585,6 +586,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
585 return true; 586 return true;
586 } 587 }
587 588
589 [DebuggerNonUserCode] //Prevents the debugger from farting in this function
588 public void SetState(string state) 590 public void SetState(string state)
589 { 591 {
590 if (state == State) 592 if (state == State)
@@ -596,7 +598,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
596 new DetectParams[0])); 598 new DetectParams[0]));
597 PostEvent(new EventParams("state_entry", new Object[0], 599 PostEvent(new EventParams("state_entry", new Object[0],
598 new DetectParams[0])); 600 new DetectParams[0]));
599 601
600 throw new EventAbortException(); 602 throw new EventAbortException();
601 } 603 }
602 604
@@ -679,41 +681,42 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
679 /// <returns></returns> 681 /// <returns></returns>
680 public object EventProcessor() 682 public object EventProcessor()
681 { 683 {
682 lock (m_Script) 684 EventParams data = null;
683 {
684// m_log.DebugFormat("[XEngine]: EventProcessor() invoked for {0}.{1}", PrimName, ScriptName);
685 685
686 if (Suspended) 686// m_log.DebugFormat("[XEngine]: EventProcessor() invoked for {0}.{1}", PrimName, ScriptName);
687 return 0;
688 687
689 EventParams data = null; 688 if (Suspended)
689 return 0;
690 690
691 lock (m_EventQueue) 691 lock (m_EventQueue)
692 {
693 data = (EventParams) m_EventQueue.Dequeue();
694 if (data == null) // Shouldn't happen
692 { 695 {
693 data = (EventParams) m_EventQueue.Dequeue(); 696 if ((m_EventQueue.Count > 0) && m_RunEvents && (!m_ShuttingDown))
694 if (data == null) // Shouldn't happen
695 { 697 {
696 if ((m_EventQueue.Count > 0) && m_RunEvents && (!m_ShuttingDown)) 698 m_CurrentResult = m_Engine.QueueEventHandler(this);
697 {
698 m_CurrentResult = m_Engine.QueueEventHandler(this);
699 }
700 else
701 {
702 m_CurrentResult = null;
703 }
704 return 0;
705 } 699 }
706 700 else
707 if (data.EventName == "timer")
708 m_TimerQueued = false;
709 if (data.EventName == "control")
710 { 701 {
711 if (m_ControlEventsInQueue > 0) 702 m_CurrentResult = null;
712 m_ControlEventsInQueue--;
713 } 703 }
714 if (data.EventName == "collision") 704 return 0;
715 m_CollisionInQueue = false; 705 }
706
707 if (data.EventName == "timer")
708 m_TimerQueued = false;
709 if (data.EventName == "control")
710 {
711 if (m_ControlEventsInQueue > 0)
712 m_ControlEventsInQueue--;
716 } 713 }
714 if (data.EventName == "collision")
715 m_CollisionInQueue = false;
716 }
717
718 lock(m_Script)
719 {
717 720
718// m_log.DebugFormat("[XEngine]: Processing event {0} for {1}", data.EventName, this); 721// m_log.DebugFormat("[XEngine]: Processing event {0} for {1}", data.EventName, this);
719 722
@@ -870,6 +873,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
870 new Object[0], new DetectParams[0])); 873 new Object[0], new DetectParams[0]));
871 } 874 }
872 875
876 [DebuggerNonUserCode] //Stops the VS debugger from farting in this function
873 public void ApiResetScript() 877 public void ApiResetScript()
874 { 878 {
875 // bool running = Running; 879 // bool running = Running;
@@ -901,10 +905,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
901 905
902 public Dictionary<string, object> GetVars() 906 public Dictionary<string, object> GetVars()
903 { 907 {
904 if (m_Script != null) 908 return m_Script.GetVars();
905 return m_Script.GetVars();
906 else
907 return new Dictionary<string, object>();
908 } 909 }
909 910
910 public void SetVars(Dictionary<string, object> vars) 911 public void SetVars(Dictionary<string, object> vars)
diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
index d848b2a..9e6752c 100644
--- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
@@ -83,19 +83,19 @@ namespace OpenSim.Region.ScriptEngine.Shared
83 83
84 public override string ToString() 84 public override string ToString()
85 { 85 {
86 string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000}>", x, y, z); 86 string s=String.Format("<{0:0.000000}, {1:0.000000}, {2:0.000000}>", x, y, z);
87 return s; 87 return s;
88 } 88 }
89 89
90 public static explicit operator LSLString(Vector3 vec) 90 public static explicit operator LSLString(Vector3 vec)
91 { 91 {
92 string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000}>", vec.x, vec.y, vec.z); 92 string s=String.Format("<{0:0.000000}, {1:0.000000}, {2:0.000000}>", vec.x, vec.y, vec.z);
93 return new LSLString(s); 93 return new LSLString(s);
94 } 94 }
95 95
96 public static explicit operator string(Vector3 vec) 96 public static explicit operator string(Vector3 vec)
97 { 97 {
98 string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000}>", vec.x, vec.y, vec.z); 98 string s=String.Format("<{0:0.000000}, {1:0.000000}, {2:0.000000}>", vec.x, vec.y, vec.z);
99 return s; 99 return s;
100 } 100 }
101 101
@@ -342,19 +342,19 @@ namespace OpenSim.Region.ScriptEngine.Shared
342 342
343 public override string ToString() 343 public override string ToString()
344 { 344 {
345 string st=String.Format(Culture.FormatProvider, "<{0:0.000000},{1:0.000000},{2:0.000000},{3:0.000000}>", x, y, z, s); 345 string st=String.Format(Culture.FormatProvider, "<{0:0.000000}, {1:0.000000}, {2:0.000000}, {3:0.000000}>", x, y, z, s);
346 return st; 346 return st;
347 } 347 }
348 348
349 public static explicit operator string(Quaternion r) 349 public static explicit operator string(Quaternion r)
350 { 350 {
351 string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000},{3:0.000000}>", r.x, r.y, r.z, r.s); 351 string s=String.Format("<{0:0.000000}, {1:0.000000}, {2:0.000000}, {3:0.000000}>", r.x, r.y, r.z, r.s);
352 return s; 352 return s;
353 } 353 }
354 354
355 public static explicit operator LSLString(Quaternion r) 355 public static explicit operator LSLString(Quaternion r)
356 { 356 {
357 string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000},{3:0.000000}>", r.x, r.y, r.z, r.s); 357 string s=String.Format("<{0:0.000000}, {1:0.000000}, {2:0.000000}, {3:0.000000}>", r.x, r.y, r.z, r.s);
358 return new LSLString(s); 358 return new LSLString(s);
359 } 359 }
360 360
@@ -459,6 +459,8 @@ namespace OpenSim.Region.ScriptEngine.Shared
459 size += 64; 459 size += 64;
460 else if (o is int) 460 else if (o is int)
461 size += 4; 461 size += 4;
462 else if (o is uint)
463 size += 4;
462 else if (o is string) 464 else if (o is string)
463 size += ((string)o).Length; 465 size += ((string)o).Length;
464 else if (o is float) 466 else if (o is float)
@@ -613,24 +615,16 @@ namespace OpenSim.Region.ScriptEngine.Shared
613 615
614 public static bool operator ==(list a, list b) 616 public static bool operator ==(list a, list b)
615 { 617 {
616 int la = -1; 618 int la = a.Length;
617 int lb = -1; 619 int lb = b.Length;
618 try { la = a.Length; }
619 catch (NullReferenceException) { }
620 try { lb = b.Length; }
621 catch (NullReferenceException) { }
622 620
623 return la == lb; 621 return la == lb;
624 } 622 }
625 623
626 public static bool operator !=(list a, list b) 624 public static bool operator !=(list a, list b)
627 { 625 {
628 int la = -1; 626 int la = a.Length;
629 int lb = -1; 627 int lb = b.Length;
630 try { la = a.Length; }
631 catch (NullReferenceException) { }
632 try {lb = b.Length;}
633 catch (NullReferenceException) { }
634 628
635 return la != lb; 629 return la != lb;
636 } 630 }
@@ -1064,7 +1058,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
1064 { 1058 {
1065 list ret = new list(); 1059 list ret = new list();
1066 double entry; 1060 double entry;
1067 for (int i = 0; i < src.Data.Length - 1; i++) 1061 for (int i = 0; i < src.Data.Length; i++)
1068 { 1062 {
1069 if (double.TryParse(src.Data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry)) 1063 if (double.TryParse(src.Data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry))
1070 { 1064 {
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index f11987e..084ef48 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Diagnostics; //for [DebuggerNonUserCode]
31using System.Globalization; 32using System.Globalization;
32using System.IO; 33using System.IO;
33using System.Reflection; 34using System.Reflection;
@@ -109,6 +110,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
109 private Dictionary<UUID, IScriptInstance> m_Scripts = 110 private Dictionary<UUID, IScriptInstance> m_Scripts =
110 new Dictionary<UUID, IScriptInstance>(); 111 new Dictionary<UUID, IScriptInstance>();
111 112
113 private OpenMetaverse.ReaderWriterLockSlim m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
114
112 // Maps the asset ID to the assembly 115 // Maps the asset ID to the assembly
113 116
114 private Dictionary<UUID, string> m_Assemblies = 117 private Dictionary<UUID, string> m_Assemblies =
@@ -131,6 +134,71 @@ namespace OpenSim.Region.ScriptEngine.XEngine
131 IWorkItemResult m_CurrentCompile = null; 134 IWorkItemResult m_CurrentCompile = null;
132 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>(); 135 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>();
133 136
137 private void lockScriptsForRead(bool locked)
138 {
139 if (locked)
140 {
141 if (m_scriptsLock.RecursiveReadCount > 0)
142 {
143 m_log.Error("[XEngine.m_Scripts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
144 m_scriptsLock.ExitReadLock();
145 }
146 if (m_scriptsLock.RecursiveWriteCount > 0)
147 {
148 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
149 m_scriptsLock.ExitWriteLock();
150 }
151
152 while (!m_scriptsLock.TryEnterReadLock(60000))
153 {
154 m_log.Error("[XEngine.m_Scripts] Thread lock detected while trying to aquire READ lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
155 if (m_scriptsLock.IsWriteLockHeld)
156 {
157 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
158 }
159 }
160 }
161 else
162 {
163 if (m_scriptsLock.RecursiveReadCount > 0)
164 {
165 m_scriptsLock.ExitReadLock();
166 }
167 }
168 }
169 private void lockScriptsForWrite(bool locked)
170 {
171 if (locked)
172 {
173 if (m_scriptsLock.RecursiveReadCount > 0)
174 {
175 m_log.Error("[XEngine.m_Scripts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
176 m_scriptsLock.ExitReadLock();
177 }
178 if (m_scriptsLock.RecursiveWriteCount > 0)
179 {
180 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
181 m_scriptsLock.ExitWriteLock();
182 }
183
184 while (!m_scriptsLock.TryEnterWriteLock(60000))
185 {
186 m_log.Error("[XEngine.m_Scripts] Thread lock detected while trying to aquire WRITE lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
187 if (m_scriptsLock.IsWriteLockHeld)
188 {
189 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
190 }
191 }
192 }
193 else
194 {
195 if (m_scriptsLock.RecursiveWriteCount > 0)
196 {
197 m_scriptsLock.ExitWriteLock();
198 }
199 }
200 }
201
134 public string ScriptEngineName 202 public string ScriptEngineName
135 { 203 {
136 get { return "XEngine"; } 204 get { return "XEngine"; }
@@ -501,44 +569,37 @@ namespace OpenSim.Region.ScriptEngine.XEngine
501 { 569 {
502 if (!m_Enabled) 570 if (!m_Enabled)
503 return; 571 return;
504 572 lockScriptsForRead(true);
505 lock (m_Scripts) 573 foreach (IScriptInstance instance in m_Scripts.Values)
506 { 574 {
507 m_log.InfoFormat( 575 // Force a final state save
508 "[XEngine]: Shutting down {0} scripts in {1}", m_Scripts.Count, m_Scene.RegionInfo.RegionName); 576 //
509 577 if (m_Assemblies.ContainsKey(instance.AssetID))
510 foreach (IScriptInstance instance in m_Scripts.Values)
511 { 578 {
512 // Force a final state save 579 string assembly = m_Assemblies[instance.AssetID];
513 // 580 instance.SaveState(assembly);
514 if (m_Assemblies.ContainsKey(instance.AssetID)) 581 }
515 {
516 string assembly = m_Assemblies[instance.AssetID];
517 instance.SaveState(assembly);
518 }
519 582
520 // Clear the event queue and abort the instance thread 583 // Clear the event queue and abort the instance thread
521 // 584 //
522 instance.ClearQueue(); 585 instance.ClearQueue();
523 instance.Stop(0); 586 instance.Stop(0);
524 587
525 // Release events, timer, etc 588 // Release events, timer, etc
526 // 589 //
527 instance.DestroyScriptInstance(); 590 instance.DestroyScriptInstance();
528 591
529 // Unload scripts and app domains. 592 // Unload scripts and app domains
530 // Must be done explicitly because they have infinite 593 // Must be done explicitly because they have infinite
531 // lifetime. 594 // lifetime
532 // However, don't bother to do this if the simulator is shutting 595 //
533 // down since it takes a long time with many scripts. 596 if (!m_SimulatorShuttingDown)
534 if (!m_SimulatorShuttingDown) 597 {
598 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
599 if (m_DomainScripts[instance.AppDomain].Count == 0)
535 { 600 {
536 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 601 m_DomainScripts.Remove(instance.AppDomain);
537 if (m_DomainScripts[instance.AppDomain].Count == 0) 602 UnloadAppDomain(instance.AppDomain);
538 {
539 m_DomainScripts.Remove(instance.AppDomain);
540 UnloadAppDomain(instance.AppDomain);
541 }
542 } 603 }
543 } 604 }
544 605
@@ -547,6 +608,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
547 m_Assemblies.Clear(); 608 m_Assemblies.Clear();
548 m_DomainScripts.Clear(); 609 m_DomainScripts.Clear();
549 } 610 }
611 lockScriptsForRead(false);
612 lockScriptsForWrite(true);
613 m_Scripts.Clear();
614 lockScriptsForWrite(false);
615 m_PrimObjects.Clear();
616 m_Assemblies.Clear();
617 m_DomainScripts.Clear();
618
550 lock (m_ScriptEngines) 619 lock (m_ScriptEngines)
551 { 620 {
552 m_ScriptEngines.Remove(this); 621 m_ScriptEngines.Remove(this);
@@ -611,22 +680,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
611 680
612 List<IScriptInstance> instances = new List<IScriptInstance>(); 681 List<IScriptInstance> instances = new List<IScriptInstance>();
613 682
614 lock (m_Scripts) 683 lockScriptsForRead(true);
615 { 684 foreach (IScriptInstance instance in m_Scripts.Values)
616 foreach (IScriptInstance instance in m_Scripts.Values)
617 instances.Add(instance); 685 instances.Add(instance);
618 } 686 lockScriptsForRead(false);
619 687
620 foreach (IScriptInstance i in instances) 688 foreach (IScriptInstance i in instances)
621 { 689 {
622 string assembly = String.Empty; 690 string assembly = String.Empty;
623 691
624 lock (m_Scripts) 692
625 {
626 if (!m_Assemblies.ContainsKey(i.AssetID)) 693 if (!m_Assemblies.ContainsKey(i.AssetID))
627 continue; 694 continue;
628 assembly = m_Assemblies[i.AssetID]; 695 assembly = m_Assemblies[i.AssetID];
629 } 696
630 697
631 i.SaveState(assembly); 698 i.SaveState(assembly);
632 } 699 }
@@ -960,92 +1027,95 @@ namespace OpenSim.Region.ScriptEngine.XEngine
960 } 1027 }
961 1028
962 ScriptInstance instance = null; 1029 ScriptInstance instance = null;
963 lock (m_Scripts) 1030 // Create the object record
1031 lockScriptsForRead(true);
1032 if ((!m_Scripts.ContainsKey(itemID)) ||
1033 (m_Scripts[itemID].AssetID != assetID))
964 { 1034 {
965 // Create the object record 1035 lockScriptsForRead(false);
966 1036
967 if ((!m_Scripts.ContainsKey(itemID)) || 1037 UUID appDomain = assetID;
968 (m_Scripts[itemID].AssetID != assetID))
969 {
970 UUID appDomain = assetID;
971 1038
972 if (part.ParentGroup.IsAttachment) 1039 if (part.ParentGroup.IsAttachment)
973 appDomain = part.ParentGroup.RootPart.UUID; 1040 appDomain = part.ParentGroup.RootPart.UUID;
974 1041
975 if (!m_AppDomains.ContainsKey(appDomain)) 1042 if (!m_AppDomains.ContainsKey(appDomain))
1043 {
1044 try
976 { 1045 {
977 try 1046 AppDomainSetup appSetup = new AppDomainSetup();
978 { 1047 appSetup.PrivateBinPath = Path.Combine(
979 AppDomainSetup appSetup = new AppDomainSetup(); 1048 m_ScriptEnginesPath,
980 appSetup.PrivateBinPath = Path.Combine( 1049 m_Scene.RegionInfo.RegionID.ToString());
981 m_ScriptEnginesPath, 1050
982 m_Scene.RegionInfo.RegionID.ToString()); 1051 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
983 1052 Evidence evidence = new Evidence(baseEvidence);
984 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 1053
985 Evidence evidence = new Evidence(baseEvidence); 1054 AppDomain sandbox;
986 1055 if (m_AppDomainLoading)
987 AppDomain sandbox; 1056 sandbox = AppDomain.CreateDomain(
988 if (m_AppDomainLoading) 1057 m_Scene.RegionInfo.RegionID.ToString(),
989 sandbox = AppDomain.CreateDomain( 1058 evidence, appSetup);
990 m_Scene.RegionInfo.RegionID.ToString(), 1059 else
991 evidence, appSetup); 1060 sandbox = AppDomain.CurrentDomain;
992 else 1061
993 sandbox = AppDomain.CurrentDomain; 1062 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
994 1063 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
995 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); 1064 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
996 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); 1065 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
997 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet"); 1066 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
998 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet); 1067 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
999 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement); 1068 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1000 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup; 1069
1001 //sandbox.SetAppDomainPolicy(sandboxPolicy); 1070 m_AppDomains[appDomain] = sandbox;
1002 1071
1003 m_AppDomains[appDomain] = sandbox; 1072 m_AppDomains[appDomain].AssemblyResolve +=
1004 1073 new ResolveEventHandler(
1005 m_AppDomains[appDomain].AssemblyResolve += 1074 AssemblyResolver.OnAssemblyResolve);
1006 new ResolveEventHandler( 1075 m_DomainScripts[appDomain] = new List<UUID>();
1007 AssemblyResolver.OnAssemblyResolve); 1076 }
1008 m_DomainScripts[appDomain] = new List<UUID>(); 1077 catch (Exception e)
1009 } 1078 {
1010 catch (Exception e) 1079 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
1080 m_ScriptErrorMessage += "Exception creating app domain:\n";
1081 m_ScriptFailCount++;
1082 lock (m_AddingAssemblies)
1011 { 1083 {
1012 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); 1084 m_AddingAssemblies[assembly]--;
1013 m_ScriptErrorMessage += "Exception creating app domain:\n";
1014 m_ScriptFailCount++;
1015 lock (m_AddingAssemblies)
1016 {
1017 m_AddingAssemblies[assembly]--;
1018 }
1019 return false;
1020 } 1085 }
1086 return false;
1021 } 1087 }
1022 m_DomainScripts[appDomain].Add(itemID); 1088 }
1023 1089 m_DomainScripts[appDomain].Add(itemID);
1024 instance = new ScriptInstance(this, part, 1090
1025 itemID, assetID, assembly, 1091 instance = new ScriptInstance(this, part,
1026 m_AppDomains[appDomain], 1092 itemID, assetID, assembly,
1027 part.ParentGroup.RootPart.Name, 1093 m_AppDomains[appDomain],
1028 item.Name, startParam, postOnRez, 1094 part.ParentGroup.RootPart.Name,
1029 stateSource, m_MaxScriptQueue); 1095 item.Name, startParam, postOnRez,
1030 1096 stateSource, m_MaxScriptQueue);
1031 m_log.DebugFormat( 1097
1032 "[XEngine] Loaded script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", 1098 m_log.DebugFormat(
1033 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, 1099 "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1100 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
1034 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); 1101 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1035 1102
1036 if (presence != null) 1103 if (presence != null)
1037 { 1104 {
1038 ShowScriptSaveResponse(item.OwnerID, 1105 ShowScriptSaveResponse(item.OwnerID,
1039 assetID, "Compile successful", true); 1106 assetID, "Compile successful", true);
1040 }
1041
1042 instance.AppDomain = appDomain;
1043 instance.LineMap = linemap;
1044
1045 m_Scripts[itemID] = instance;
1046 } 1107 }
1047 }
1048 1108
1109 instance.AppDomain = appDomain;
1110 instance.LineMap = linemap;
1111 lockScriptsForWrite(true);
1112 m_Scripts[itemID] = instance;
1113 lockScriptsForWrite(false);
1114 }
1115 else
1116 {
1117 lockScriptsForRead(false);
1118 }
1049 lock (m_PrimObjects) 1119 lock (m_PrimObjects)
1050 { 1120 {
1051 if (!m_PrimObjects.ContainsKey(localID)) 1121 if (!m_PrimObjects.ContainsKey(localID))
@@ -1064,9 +1134,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1064 m_AddingAssemblies[assembly]--; 1134 m_AddingAssemblies[assembly]--;
1065 } 1135 }
1066 1136
1067 if (instance != null) 1137 if (instance!=null)
1068 instance.Init(); 1138 instance.Init();
1069 1139
1070 return true; 1140 return true;
1071 } 1141 }
1072 1142
@@ -1079,20 +1149,31 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1079 m_CompileDict.Remove(itemID); 1149 m_CompileDict.Remove(itemID);
1080 } 1150 }
1081 1151
1082 IScriptInstance instance = null; 1152 lockScriptsForRead(true);
1083 1153 // Do we even have it?
1084 lock (m_Scripts) 1154 if (!m_Scripts.ContainsKey(itemID))
1085 { 1155 {
1086 // Do we even have it? 1156 // Do we even have it?
1087 if (!m_Scripts.ContainsKey(itemID)) 1157 if (!m_Scripts.ContainsKey(itemID))
1088 return; 1158 return;
1089 1159
1090 instance = m_Scripts[itemID]; 1160 lockScriptsForRead(false);
1161 lockScriptsForWrite(true);
1091 m_Scripts.Remove(itemID); 1162 m_Scripts.Remove(itemID);
1163 lockScriptsForWrite(false);
1164
1165 return;
1092 } 1166 }
1167
1093 1168
1169 IScriptInstance instance=m_Scripts[itemID];
1170 lockScriptsForRead(false);
1171 lockScriptsForWrite(true);
1172 m_Scripts.Remove(itemID);
1173 lockScriptsForWrite(false);
1094 instance.ClearQueue(); 1174 instance.ClearQueue();
1095 instance.Stop(0); 1175 instance.Stop(0);
1176
1096// bool objectRemoved = false; 1177// bool objectRemoved = false;
1097 1178
1098 lock (m_PrimObjects) 1179 lock (m_PrimObjects)
@@ -1128,11 +1209,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1128 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 1209 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
1129 if (handlerObjectRemoved != null) 1210 if (handlerObjectRemoved != null)
1130 { 1211 {
1131 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID); 1212 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
1132 handlerObjectRemoved(part.UUID); 1213 handlerObjectRemoved(part.UUID);
1133 } 1214 }
1134 1215
1135 1216 CleanAssemblies();
1217
1136 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 1218 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
1137 if (handlerScriptRemoved != null) 1219 if (handlerScriptRemoved != null)
1138 handlerScriptRemoved(itemID); 1220 handlerScriptRemoved(itemID);
@@ -1274,7 +1356,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1274 return false; 1356 return false;
1275 1357
1276 uuids = m_PrimObjects[localID]; 1358 uuids = m_PrimObjects[localID];
1277 } 1359
1278 1360
1279 foreach (UUID itemID in uuids) 1361 foreach (UUID itemID in uuids)
1280 { 1362 {
@@ -1292,6 +1374,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1292 result = true; 1374 result = true;
1293 } 1375 }
1294 } 1376 }
1377 }
1295 1378
1296 return result; 1379 return result;
1297 } 1380 }
@@ -1391,12 +1474,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1391 private IScriptInstance GetInstance(UUID itemID) 1474 private IScriptInstance GetInstance(UUID itemID)
1392 { 1475 {
1393 IScriptInstance instance; 1476 IScriptInstance instance;
1394 lock (m_Scripts) 1477 lockScriptsForRead(true);
1478 if (!m_Scripts.ContainsKey(itemID))
1395 { 1479 {
1396 if (!m_Scripts.ContainsKey(itemID)) 1480 lockScriptsForRead(false);
1397 return null; 1481 return null;
1398 instance = m_Scripts[itemID];
1399 } 1482 }
1483 instance = m_Scripts[itemID];
1484 lockScriptsForRead(false);
1400 return instance; 1485 return instance;
1401 } 1486 }
1402 1487
@@ -1420,6 +1505,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1420 return false; 1505 return false;
1421 } 1506 }
1422 1507
1508 [DebuggerNonUserCode]
1423 public void ApiResetScript(UUID itemID) 1509 public void ApiResetScript(UUID itemID)
1424 { 1510 {
1425 IScriptInstance instance = GetInstance(itemID); 1511 IScriptInstance instance = GetInstance(itemID);
@@ -1471,6 +1557,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1471 return UUID.Zero; 1557 return UUID.Zero;
1472 } 1558 }
1473 1559
1560 [DebuggerNonUserCode]
1474 public void SetState(UUID itemID, string newState) 1561 public void SetState(UUID itemID, string newState)
1475 { 1562 {
1476 IScriptInstance instance = GetInstance(itemID); 1563 IScriptInstance instance = GetInstance(itemID);
@@ -1493,11 +1580,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1493 1580
1494 List<IScriptInstance> instances = new List<IScriptInstance>(); 1581 List<IScriptInstance> instances = new List<IScriptInstance>();
1495 1582
1496 lock (m_Scripts) 1583 lockScriptsForRead(true);
1497 { 1584 foreach (IScriptInstance instance in m_Scripts.Values)
1498 foreach (IScriptInstance instance in m_Scripts.Values)
1499 instances.Add(instance); 1585 instances.Add(instance);
1500 } 1586 lockScriptsForRead(false);
1501 1587
1502 foreach (IScriptInstance i in instances) 1588 foreach (IScriptInstance i in instances)
1503 { 1589 {
@@ -1874,5 +1960,17 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1874 if (instance != null) 1960 if (instance != null)
1875 instance.Resume(); 1961 instance.Resume();
1876 } 1962 }
1963
1964 public bool HasScript(UUID itemID, out bool running)
1965 {
1966 running = true;
1967
1968 IScriptInstance instance = GetInstance(itemID);
1969 if (instance == null)
1970 return false;
1971
1972 running = instance.Running;
1973 return true;
1974 }
1877 } 1975 }
1878} \ No newline at end of file 1976}
diff --git a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs
index 1d1f9ef..ded335d5 100644
--- a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs
+++ b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs
@@ -100,6 +100,11 @@ namespace OpenSim.Server.Handlers.Simulation
100 DoAgentDelete(request, responsedata, agentID, action, regionID); 100 DoAgentDelete(request, responsedata, agentID, action, regionID);
101 return responsedata; 101 return responsedata;
102 } 102 }
103 else if (method.Equals("DELETECHILD"))
104 {
105 DoChildAgentDelete(request, responsedata, agentID, action, regionID);
106 return responsedata;
107 }
103 else if (method.Equals("QUERYACCESS")) 108 else if (method.Equals("QUERYACCESS"))
104 { 109 {
105 DoQueryAccess(request, responsedata, agentID, regionID); 110 DoQueryAccess(request, responsedata, agentID, regionID);
@@ -205,6 +210,24 @@ namespace OpenSim.Server.Handlers.Simulation
205 } 210 }
206 } 211 }
207 212
213 protected void DoChildAgentDelete(Hashtable request, Hashtable responsedata, UUID id, string action, UUID regionID)
214 {
215 m_log.Debug(" >>> DoChildAgentDelete action:" + action + "; RegionID:" + regionID);
216
217 GridRegion destination = new GridRegion();
218 destination.RegionID = regionID;
219
220 if (action.Equals("release"))
221 ReleaseAgent(regionID, id);
222 else
223 m_SimulationService.CloseChildAgent(destination, id);
224
225 responsedata["int_response_code"] = HttpStatusCode.OK;
226 responsedata["str_response_string"] = "OpenSim agent " + id.ToString();
227
228 m_log.Debug("[AGENT HANDLER]: Child Agent Released/Deleted.");
229 }
230
208 protected void DoAgentDelete(Hashtable request, Hashtable responsedata, UUID id, string action, UUID regionID) 231 protected void DoAgentDelete(Hashtable request, Hashtable responsedata, UUID id, string action, UUID regionID)
209 { 232 {
210 m_log.Debug(" >>> DoDelete action:" + action + "; RegionID:" + regionID); 233 m_log.Debug(" >>> DoDelete action:" + action + "; RegionID:" + regionID);
diff --git a/OpenSim/Services/AssetService/AssetService.cs b/OpenSim/Services/AssetService/AssetService.cs
index 4f4cbf6..d4bfe8f 100644
--- a/OpenSim/Services/AssetService/AssetService.cs
+++ b/OpenSim/Services/AssetService/AssetService.cs
@@ -168,7 +168,10 @@ namespace OpenSim.Services.AssetService
168 { 168 {
169// m_log.DebugFormat( 169// m_log.DebugFormat(
170// "[ASSET SERVICE]: Storing asset {0} {1}, bytes {2}", asset.Name, asset.FullID, asset.Data.Length); 170// "[ASSET SERVICE]: Storing asset {0} {1}, bytes {2}", asset.Name, asset.FullID, asset.Data.Length);
171 m_Database.StoreAsset(asset); 171 if (!m_Database.StoreAsset(asset))
172 {
173 return UUID.Zero.ToString();
174 }
172 } 175 }
173// else 176// else
174// { 177// {
diff --git a/OpenSim/Services/AuthenticationService/AuthenticationServiceBase.cs b/OpenSim/Services/AuthenticationService/AuthenticationServiceBase.cs
index 229f557..e42f9a0 100644
--- a/OpenSim/Services/AuthenticationService/AuthenticationServiceBase.cs
+++ b/OpenSim/Services/AuthenticationService/AuthenticationServiceBase.cs
@@ -30,10 +30,11 @@ using OpenMetaverse;
30using log4net; 30using log4net;
31using Nini.Config; 31using Nini.Config;
32using System.Reflection; 32using System.Reflection;
33using OpenSim.Server.Base;
34using OpenSim.Services.Interfaces;
33using OpenSim.Data; 35using OpenSim.Data;
34using OpenSim.Framework; 36using OpenSim.Framework;
35using OpenSim.Services.Base; 37using OpenSim.Services.Base;
36using OpenSim.Services.Interfaces;
37 38
38namespace OpenSim.Services.AuthenticationService 39namespace OpenSim.Services.AuthenticationService
39{ 40{
@@ -50,6 +51,12 @@ namespace OpenSim.Services.AuthenticationService
50 MethodBase.GetCurrentMethod().DeclaringType); 51 MethodBase.GetCurrentMethod().DeclaringType);
51 52
52 protected IAuthenticationData m_Database; 53 protected IAuthenticationData m_Database;
54 protected IUserAccountService m_UserAccountService = null;
55
56 public AuthenticationServiceBase(IConfigSource config, IUserAccountService acct) : this(config)
57 {
58 m_UserAccountService = acct;
59 }
53 60
54 public AuthenticationServiceBase(IConfigSource config) : base(config) 61 public AuthenticationServiceBase(IConfigSource config) : base(config)
55 { 62 {
diff --git a/OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs b/OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs
index 14d96cb..d5a6521 100644
--- a/OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs
+++ b/OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs
@@ -51,6 +51,12 @@ namespace OpenSim.Services.AuthenticationService
51 LogManager.GetLogger( 51 LogManager.GetLogger(
52 MethodBase.GetCurrentMethod().DeclaringType); 52 MethodBase.GetCurrentMethod().DeclaringType);
53 53
54 public PasswordAuthenticationService(IConfigSource config, IUserAccountService userService) :
55 base(config, userService)
56 {
57 m_log.Debug("[AUTH SERVICE]: Started with User Account access");
58 }
59
54 public PasswordAuthenticationService(IConfigSource config) : 60 public PasswordAuthenticationService(IConfigSource config) :
55 base(config) 61 base(config)
56 { 62 {
@@ -58,32 +64,65 @@ namespace OpenSim.Services.AuthenticationService
58 64
59 public string Authenticate(UUID principalID, string password, int lifetime) 65 public string Authenticate(UUID principalID, string password, int lifetime)
60 { 66 {
67 m_log.DebugFormat("[AUTH SERVICE]: Authenticating for {0}, user account service present: {1}", principalID, m_UserAccountService != null);
61 AuthenticationData data = m_Database.Get(principalID); 68 AuthenticationData data = m_Database.Get(principalID);
69 UserAccount user = null;
70 if (m_UserAccountService != null)
71 user = m_UserAccountService.GetUserAccount(UUID.Zero, principalID);
62 72
63 if (data == null) 73 if (data == null || data.Data == null)
64 { 74 {
65 m_log.DebugFormat("[AUTH SERVICE]: PrincipalID {0} not found", principalID); 75 m_log.DebugFormat("[AUTH SERVICE]: PrincipalID {0} or its data not found", principalID);
66 return String.Empty; 76 return String.Empty;
67 } 77 }
68 else if (data.Data == null) 78
79 if (!data.Data.ContainsKey("passwordHash") ||
80 !data.Data.ContainsKey("passwordSalt"))
69 { 81 {
70 m_log.DebugFormat("[AUTH SERVICE]: PrincipalID {0} data not found", principalID);
71 return String.Empty; 82 return String.Empty;
72 } 83 }
73 else if (!data.Data.ContainsKey("passwordHash") || !data.Data.ContainsKey("passwordSalt")) 84
85 string hashed = Util.Md5Hash(password + ":" +
86 data.Data["passwordSalt"].ToString());
87
88 m_log.DebugFormat("[PASS AUTH]: got {0}; hashed = {1}; stored = {2}", password, hashed, data.Data["passwordHash"].ToString());
89
90 if (data.Data["passwordHash"].ToString() == hashed)
91 {
92 return GetToken(principalID, lifetime);
93 }
94
95 if (user == null)
74 { 96 {
75 m_log.DebugFormat( 97 m_log.DebugFormat("[PASS AUTH]: No user record for {0}", principalID);
76 "[AUTH SERVICE]: PrincipalID {0} data didn't contain either passwordHash or passwordSalt", principalID);
77 return String.Empty; 98 return String.Empty;
78 } 99 }
79 else 100
101 int impersonateFlag = 1 << 6;
102
103 if ((user.UserFlags & impersonateFlag) == 0)
104 return String.Empty;
105
106 List<UserAccount> accounts = m_UserAccountService.GetUserAccountsWhere(UUID.Zero, "UserLevel >= 200");
107 if (accounts == null || accounts.Count == 0)
108 return String.Empty;
109
110 foreach (UserAccount a in accounts)
80 { 111 {
81 string hashed = Util.Md5Hash(password + ":" + data.Data["passwordSalt"].ToString()); 112 data = m_Database.Get(a.PrincipalID);
113 if (data == null || data.Data == null ||
114 !data.Data.ContainsKey("passwordHash") ||
115 !data.Data.ContainsKey("passwordSalt"))
116 {
117 continue;
118 }
82 119
83 //m_log.DebugFormat("[PASS AUTH]: got {0}; hashed = {1}; stored = {2}", password, hashed, data.Data["passwordHash"].ToString()); 120 hashed = Util.Md5Hash(password + ":" +
121 data.Data["passwordSalt"].ToString());
84 122
85 if (data.Data["passwordHash"].ToString() == hashed) 123 if (data.Data["passwordHash"].ToString() == hashed)
86 { 124 {
125 m_log.DebugFormat("[PASS AUTH]: {0} {1} impersonating {2}, proceeding with login", a.FirstName, a.LastName, principalID);
87 return GetToken(principalID, lifetime); 126 return GetToken(principalID, lifetime);
88 } 127 }
89 else 128 else
@@ -94,6 +133,9 @@ namespace OpenSim.Services.AuthenticationService
94 return String.Empty; 133 return String.Empty;
95 } 134 }
96 } 135 }
136
137 m_log.DebugFormat("[PASS AUTH]: Impersonation of {0} failed", principalID);
138 return String.Empty;
97 } 139 }
98 } 140 }
99} \ No newline at end of file 141}
diff --git a/OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs b/OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs
index 2344c0e..d02ff9b 100644
--- a/OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs
+++ b/OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs
@@ -49,6 +49,11 @@ namespace OpenSim.Services.AuthenticationService
49 private static readonly ILog m_log = 49 private static readonly ILog m_log =
50 LogManager.GetLogger( 50 LogManager.GetLogger(
51 MethodBase.GetCurrentMethod().DeclaringType); 51 MethodBase.GetCurrentMethod().DeclaringType);
52
53 public WebkeyAuthenticationService(IConfigSource config, IUserAccountService userService) :
54 base(config, userService)
55 {
56 }
52 57
53 public WebkeyAuthenticationService(IConfigSource config) : 58 public WebkeyAuthenticationService(IConfigSource config) :
54 base(config) 59 base(config)
diff --git a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs
index e4c3eaf..2882906 100644
--- a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs
@@ -30,6 +30,7 @@ using System;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.IO; 31using System.IO;
32using System.Reflection; 32using System.Reflection;
33using System.Timers;
33using Nini.Config; 34using Nini.Config;
34using OpenSim.Framework; 35using OpenSim.Framework;
35using OpenSim.Framework.Console; 36using OpenSim.Framework.Console;
@@ -47,13 +48,15 @@ namespace OpenSim.Services.Connectors
47 48
48 private string m_ServerURI = String.Empty; 49 private string m_ServerURI = String.Empty;
49 private IImprovedAssetCache m_Cache = null; 50 private IImprovedAssetCache m_Cache = null;
50 51 private int m_retryCounter;
52 private Dictionary<int, List<AssetBase>> m_retryQueue = new Dictionary<int, List<AssetBase>>();
53 private Timer m_retryTimer;
51 private delegate void AssetRetrievedEx(AssetBase asset); 54 private delegate void AssetRetrievedEx(AssetBase asset);
52 55
53 // Keeps track of concurrent requests for the same asset, so that it's only loaded once. 56 // Keeps track of concurrent requests for the same asset, so that it's only loaded once.
54 // Maps: Asset ID -> Handlers which will be called when the asset has been loaded 57 // Maps: Asset ID -> Handlers which will be called when the asset has been loaded
55 private Dictionary<string, AssetRetrievedEx> m_AssetHandlers = new Dictionary<string, AssetRetrievedEx>(); 58 private Dictionary<string, AssetRetrievedEx> m_AssetHandlers = new Dictionary<string, AssetRetrievedEx>();
56 59 private Dictionary<string, string> m_UriMap = new Dictionary<string, string>();
57 60
58 public AssetServicesConnector() 61 public AssetServicesConnector()
59 { 62 {
@@ -81,13 +84,91 @@ namespace OpenSim.Services.Connectors
81 string serviceURI = assetConfig.GetString("AssetServerURI", 84 string serviceURI = assetConfig.GetString("AssetServerURI",
82 String.Empty); 85 String.Empty);
83 86
87 m_ServerURI = serviceURI;
88
84 if (serviceURI == String.Empty) 89 if (serviceURI == String.Empty)
85 { 90 {
86 m_log.Error("[ASSET CONNECTOR]: No Server URI named in section AssetService"); 91 m_log.Error("[ASSET CONNECTOR]: No Server URI named in section AssetService");
87 throw new Exception("Asset connector init error"); 92 throw new Exception("Asset connector init error");
88 } 93 }
89 94
90 m_ServerURI = serviceURI; 95
96 m_retryTimer = new Timer();
97 m_retryTimer.Elapsed += new ElapsedEventHandler(retryCheck);
98 m_retryTimer.Interval = 60000;
99
100 Uri serverUri = new Uri(m_ServerURI);
101
102 string groupHost = serverUri.Host;
103
104 for (int i = 0 ; i < 256 ; i++)
105 {
106 string prefix = i.ToString("x2");
107 groupHost = assetConfig.GetString("AssetServerHost_"+prefix, groupHost);
108
109 m_UriMap[prefix] = groupHost;
110 //m_log.DebugFormat("[ASSET]: Using {0} for prefix {1}", groupHost, prefix);
111 }
112 }
113
114 private string MapServer(string id)
115 {
116 UriBuilder serverUri = new UriBuilder(m_ServerURI);
117
118 string prefix = id.Substring(0, 2).ToLower();
119
120 string host = m_UriMap[prefix];
121
122 serverUri.Host = host;
123
124 // m_log.DebugFormat("[ASSET]: Using {0} for host name for prefix {1}", host, prefix);
125
126 return serverUri.Uri.AbsoluteUri;
127 }
128
129 protected void retryCheck(object source, ElapsedEventArgs e)
130 {
131 m_retryCounter++;
132 if (m_retryCounter > 60) m_retryCounter -= 60;
133 List<int> keys = new List<int>();
134 foreach (int a in m_retryQueue.Keys)
135 {
136 keys.Add(a);
137 }
138 foreach (int a in keys)
139 {
140 //We exponentially fall back on frequency until we reach one attempt per hour
141 //The net result is that we end up in the queue for roughly 24 hours..
142 //24 hours worth of assets could be a lot, so the hope is that the region admin
143 //will have gotten the asset connector back online quickly!
144
145 int timefactor = a ^ 2;
146 if (timefactor > 60)
147 {
148 timefactor = 60;
149 }
150
151 //First, find out if we care about this timefactor
152 if (timefactor % a == 0)
153 {
154 //Yes, we do!
155 List<AssetBase> retrylist = m_retryQueue[a];
156 m_retryQueue.Remove(a);
157
158 foreach(AssetBase ass in retrylist)
159 {
160 Store(ass); //Store my ass. This function will put it back in the dictionary if it fails
161 }
162 }
163 }
164
165 if (m_retryQueue.Count == 0)
166 {
167 //It might only be one tick per minute, but I have
168 //repented and abandoned my wasteful ways
169 m_retryCounter = 0;
170 m_retryTimer.Stop();
171 }
91 } 172 }
92 173
93 protected void SetCache(IImprovedAssetCache cache) 174 protected void SetCache(IImprovedAssetCache cache)
@@ -97,15 +178,13 @@ namespace OpenSim.Services.Connectors
97 178
98 public AssetBase Get(string id) 179 public AssetBase Get(string id)
99 { 180 {
100// m_log.DebugFormat("[ASSET SERVICE CONNECTOR]: Synchronous get request for {0}", id); 181 string uri = MapServer(id) + "/assets/" + id;
101
102 string uri = m_ServerURI + "/assets/" + id;
103 182
104 AssetBase asset = null; 183 AssetBase asset = null;
105 if (m_Cache != null) 184 if (m_Cache != null)
106 asset = m_Cache.Get(id); 185 asset = m_Cache.Get(id);
107 186
108 if (asset == null) 187 if (asset == null || asset.Data == null || asset.Data.Length == 0)
109 { 188 {
110 asset = SynchronousRestObjectRequester. 189 asset = SynchronousRestObjectRequester.
111 MakeRequest<int, AssetBase>("GET", uri, 0); 190 MakeRequest<int, AssetBase>("GET", uri, 0);
@@ -136,7 +215,7 @@ namespace OpenSim.Services.Connectors
136 return fullAsset.Metadata; 215 return fullAsset.Metadata;
137 } 216 }
138 217
139 string uri = m_ServerURI + "/assets/" + id + "/metadata"; 218 string uri = MapServer(id) + "/assets/" + id + "/metadata";
140 219
141 AssetMetadata asset = SynchronousRestObjectRequester. 220 AssetMetadata asset = SynchronousRestObjectRequester.
142 MakeRequest<int, AssetMetadata>("GET", uri, 0); 221 MakeRequest<int, AssetMetadata>("GET", uri, 0);
@@ -153,7 +232,7 @@ namespace OpenSim.Services.Connectors
153 return fullAsset.Data; 232 return fullAsset.Data;
154 } 233 }
155 234
156 RestClient rc = new RestClient(m_ServerURI); 235 RestClient rc = new RestClient(MapServer(id));
157 rc.AddResourcePath("assets"); 236 rc.AddResourcePath("assets");
158 rc.AddResourcePath(id); 237 rc.AddResourcePath(id);
159 rc.AddResourcePath("data"); 238 rc.AddResourcePath("data");
@@ -178,15 +257,13 @@ namespace OpenSim.Services.Connectors
178 257
179 public bool Get(string id, Object sender, AssetRetrieved handler) 258 public bool Get(string id, Object sender, AssetRetrieved handler)
180 { 259 {
181// m_log.DebugFormat("[ASSET SERVICE CONNECTOR]: Potentially asynchronous get request for {0}", id); 260 string uri = MapServer(id) + "/assets/" + id;
182
183 string uri = m_ServerURI + "/assets/" + id;
184 261
185 AssetBase asset = null; 262 AssetBase asset = null;
186 if (m_Cache != null) 263 if (m_Cache != null)
187 asset = m_Cache.Get(id); 264 asset = m_Cache.Get(id);
188 265
189 if (asset == null) 266 if (asset == null || asset.Data == null || asset.Data.Length == 0)
190 { 267 {
191 lock (m_AssetHandlers) 268 lock (m_AssetHandlers)
192 { 269 {
@@ -246,38 +323,95 @@ namespace OpenSim.Services.Connectors
246 323
247 public string Store(AssetBase asset) 324 public string Store(AssetBase asset)
248 { 325 {
249 if (asset.Temporary || asset.Local) 326 // Have to assign the asset ID here. This isn't likely to
327 // trigger since current callers don't pass emtpy IDs
328 // We need the asset ID to route the request to the proper
329 // cluster member, so we can't have the server assign one.
330 if (asset.ID == string.Empty)
250 { 331 {
251 if (m_Cache != null) 332 if (asset.FullID == UUID.Zero)
252 m_Cache.Cache(asset); 333 {
334 asset.FullID = UUID.Random();
335 }
336 asset.ID = asset.FullID.ToString();
337 }
338 else if (asset.FullID == UUID.Zero)
339 {
340 UUID uuid = UUID.Zero;
341 if (UUID.TryParse(asset.ID, out uuid))
342 {
343 asset.FullID = uuid;
344 }
345 else
346 {
347 asset.FullID = UUID.Random();
348 }
349 }
253 350
351 if (m_Cache != null)
352 m_Cache.Cache(asset);
353 if (asset.Temporary || asset.Local)
354 {
254 return asset.ID; 355 return asset.ID;
255 } 356 }
256 357
257 string uri = m_ServerURI + "/assets/"; 358 string uri = MapServer(asset.FullID.ToString()) + "/assets/";
258 359
259 string newID = string.Empty; 360 string newID = string.Empty;
260 try 361 try
261 { 362 {
262 newID = SynchronousRestObjectRequester. 363 newID = SynchronousRestObjectRequester.
263 MakeRequest<AssetBase, string>("POST", uri, asset); 364 MakeRequest<AssetBase, string>("POST", uri, asset, 25);
365 if (newID == null || newID == "")
366 {
367 newID = UUID.Zero.ToString();
368 }
264 } 369 }
265 catch (Exception e) 370 catch (Exception e)
266 { 371 {
267 m_log.WarnFormat("[ASSET CONNECTOR]: Unable to send asset {0} to asset server. Reason: {1}", asset.ID, e.Message); 372 newID = UUID.Zero.ToString();
268 } 373 }
269 374
270 if (newID != String.Empty) 375 if (newID == UUID.Zero.ToString())
271 { 376 {
272 // Placing this here, so that this work with old asset servers that don't send any reply back 377 //The asset upload failed, put it in a queue for later
273 // SynchronousRestObjectRequester returns somethins that is not an empty string 378 asset.UploadAttempts++;
274 if (newID != null) 379 if (asset.UploadAttempts > 30)
275 asset.ID = newID; 380 {
381 //By this stage we've been in the queue for a good few hours;
382 //We're going to drop the asset.
383 m_log.ErrorFormat("[Assets] Dropping asset {0} - Upload has been in the queue for too long.", asset.ID.ToString());
384 }
385 else
386 {
387 if (!m_retryQueue.ContainsKey(asset.UploadAttempts))
388 {
389 m_retryQueue.Add(asset.UploadAttempts, new List<AssetBase>());
390 }
391 List<AssetBase> m_queue = m_retryQueue[asset.UploadAttempts];
392 m_queue.Add(asset);
393 m_log.WarnFormat("[Assets] Upload failed: {0} - Requeuing asset for another run.", asset.ID.ToString());
394 m_retryTimer.Start();
395 }
396 }
397 else
398 {
399 if (asset.UploadAttempts > 0)
400 {
401 m_log.InfoFormat("[Assets] Upload of {0} succeeded after {1} failed attempts", asset.ID.ToString(), asset.UploadAttempts.ToString());
402 }
403 if (newID != String.Empty)
404 {
405 // Placing this here, so that this work with old asset servers that don't send any reply back
406 // SynchronousRestObjectRequester returns somethins that is not an empty string
407 if (newID != null)
408 asset.ID = newID;
276 409
277 if (m_Cache != null) 410 if (m_Cache != null)
278 m_Cache.Cache(asset); 411 m_Cache.Cache(asset);
412 }
279 } 413 }
280 return newID; 414 return asset.ID;
281 } 415 }
282 416
283 public bool UpdateContent(string id, byte[] data) 417 public bool UpdateContent(string id, byte[] data)
@@ -298,7 +432,7 @@ namespace OpenSim.Services.Connectors
298 } 432 }
299 asset.Data = data; 433 asset.Data = data;
300 434
301 string uri = m_ServerURI + "/assets/" + id; 435 string uri = MapServer(id) + "/assets/" + id;
302 436
303 if (SynchronousRestObjectRequester. 437 if (SynchronousRestObjectRequester.
304 MakeRequest<AssetBase, bool>("POST", uri, asset)) 438 MakeRequest<AssetBase, bool>("POST", uri, asset))
@@ -313,7 +447,7 @@ namespace OpenSim.Services.Connectors
313 447
314 public bool Delete(string id) 448 public bool Delete(string id)
315 { 449 {
316 string uri = m_ServerURI + "/assets/" + id; 450 string uri = MapServer(id) + "/assets/" + id;
317 451
318 if (SynchronousRestObjectRequester. 452 if (SynchronousRestObjectRequester.
319 MakeRequest<int, bool>("DELETE", uri, 0)) 453 MakeRequest<int, bool>("DELETE", uri, 0))
@@ -326,4 +460,4 @@ namespace OpenSim.Services.Connectors
326 return false; 460 return false;
327 } 461 }
328 } 462 }
329} \ No newline at end of file 463}
diff --git a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs
index 0430ef6..bc0bc54 100644
--- a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs
@@ -158,17 +158,10 @@ namespace OpenSim.Services.Connectors.Hypergrid
158 try 158 try
159 { 159 {
160 WebClient c = new WebClient(); 160 WebClient c = new WebClient();
161 //m_log.Debug("JPEG: " + imageURL);
161 string name = regionID.ToString(); 162 string name = regionID.ToString();
162 filename = Path.Combine(storagePath, name + ".jpg"); 163 filename = Path.Combine(storagePath, name + ".jpg");
163 m_log.DebugFormat("[GATEKEEPER SERVICE CONNECTOR]: Map image at {0}, cached at {1}", imageURL, filename); 164 c.DownloadFile(imageURL, filename);
164 if (!File.Exists(filename))
165 {
166 m_log.DebugFormat("[GATEKEEPER SERVICE CONNECTOR]: downloading...");
167 c.DownloadFile(imageURL, filename);
168 }
169 else
170 m_log.DebugFormat("[GATEKEEPER SERVICE CONNECTOR]: using cached image");
171
172 bitmap = new Bitmap(filename); 165 bitmap = new Bitmap(filename);
173 //m_log.Debug("Size: " + m.PhysicalDimension.Height + "-" + m.PhysicalDimension.Width); 166 //m_log.Debug("Size: " + m.PhysicalDimension.Height + "-" + m.PhysicalDimension.Width);
174 byte[] imageData = OpenJPEG.EncodeFromImage(bitmap, true); 167 byte[] imageData = OpenJPEG.EncodeFromImage(bitmap, true);
@@ -179,11 +172,10 @@ namespace OpenSim.Services.Connectors.Hypergrid
179 172
180 ass.Data = imageData; 173 ass.Data = imageData;
181 174
182 mapTile = ass.FullID;
183
184 // finally
185 m_AssetService.Store(ass); 175 m_AssetService.Store(ass);
186 176
177 // finally
178 mapTile = ass.FullID;
187 } 179 }
188 catch // LEGIT: Catching problems caused by OpenJPEG p/invoke 180 catch // LEGIT: Catching problems caused by OpenJPEG p/invoke
189 { 181 {
diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs
index 5b27cf6..d617aee 100644
--- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs
@@ -98,8 +98,6 @@ namespace OpenSim.Services.Connectors.Hypergrid
98 throw new Exception("UserAgent connector init error"); 98 throw new Exception("UserAgent connector init error");
99 } 99 }
100 m_ServerURL = serviceURI; 100 m_ServerURL = serviceURI;
101 if (!m_ServerURL.EndsWith("/"))
102 m_ServerURL += "/";
103 101
104 m_log.DebugFormat("[USER AGENT CONNECTOR]: UserAgentServiceConnector started for {0}", m_ServerURL); 102 m_log.DebugFormat("[USER AGENT CONNECTOR]: UserAgentServiceConnector started for {0}", m_ServerURL);
105 } 103 }
diff --git a/OpenSim/Services/Connectors/Land/LandServiceConnector.cs b/OpenSim/Services/Connectors/Land/LandServiceConnector.cs
index 30a73a4..833e22a 100644
--- a/OpenSim/Services/Connectors/Land/LandServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Land/LandServiceConnector.cs
@@ -130,4 +130,4 @@ namespace OpenSim.Services.Connectors
130 return landData; 130 return landData;
131 } 131 }
132 } 132 }
133} \ No newline at end of file 133}
diff --git a/OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs b/OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs
index 7238afc..e16dc36 100644
--- a/OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs
@@ -299,6 +299,17 @@ namespace OpenSim.Services.Connectors
299 { 299 {
300 pinfo = new PresenceInfo((Dictionary<string, object>)replyData["result"]); 300 pinfo = new PresenceInfo((Dictionary<string, object>)replyData["result"]);
301 } 301 }
302 else
303 {
304 if (replyData["result"].ToString() == "null")
305 return null;
306
307 m_log.DebugFormat("[PRESENCE CONNECTOR]: Invalid reply (result not dictionary) received from presence server when querying for sessionID {0}", sessionID.ToString());
308 }
309 }
310 else
311 {
312 m_log.DebugFormat("[PRESENCE CONNECTOR]: Invalid reply received from presence server when querying for sessionID {0}", sessionID.ToString());
302 } 313 }
303 314
304 return pinfo; 315 return pinfo;
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
index 67a65ff..0e4d794 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
@@ -28,6 +28,8 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Collections.Specialized; 30using System.Collections.Specialized;
31using System.Drawing;
32using System.Drawing.Imaging;
31using System.IO; 33using System.IO;
32using System.Net; 34using System.Net;
33using System.Reflection; 35using System.Reflection;
@@ -100,6 +102,15 @@ namespace OpenSim.Services.Connectors.SimianGrid
100 102
101 public string RegisterRegion(UUID scopeID, GridRegion regionInfo) 103 public string RegisterRegion(UUID scopeID, GridRegion regionInfo)
102 { 104 {
105 IPEndPoint ext = regionInfo.ExternalEndPoint;
106 if (ext == null) return "Region registration for " + regionInfo.RegionName + " failed: Could not resolve EndPoint";
107 // Generate and upload our map tile in PNG format to the SimianGrid AddMapTile service
108// Scene scene;
109// if (m_scenes.TryGetValue(regionInfo.RegionID, out scene))
110// UploadMapTile(scene);
111// else
112// m_log.Warn("Registering region " + regionInfo.RegionName + " (" + regionInfo.RegionID + ") that we are not tracking");
113
103 Vector3d minPosition = new Vector3d(regionInfo.RegionLocX, regionInfo.RegionLocY, 0.0); 114 Vector3d minPosition = new Vector3d(regionInfo.RegionLocX, regionInfo.RegionLocY, 0.0);
104 Vector3d maxPosition = minPosition + new Vector3d(Constants.RegionSize, Constants.RegionSize, 4096.0); 115 Vector3d maxPosition = minPosition + new Vector3d(Constants.RegionSize, Constants.RegionSize, 4096.0);
105 116
@@ -108,7 +119,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
108 { "ServerURI", OSD.FromString(regionInfo.ServerURI) }, 119 { "ServerURI", OSD.FromString(regionInfo.ServerURI) },
109 { "InternalAddress", OSD.FromString(regionInfo.InternalEndPoint.Address.ToString()) }, 120 { "InternalAddress", OSD.FromString(regionInfo.InternalEndPoint.Address.ToString()) },
110 { "InternalPort", OSD.FromInteger(regionInfo.InternalEndPoint.Port) }, 121 { "InternalPort", OSD.FromInteger(regionInfo.InternalEndPoint.Port) },
111 { "ExternalAddress", OSD.FromString(regionInfo.ExternalEndPoint.Address.ToString()) }, 122 { "ExternalAddress", OSD.FromString(ext.Address.ToString()) },
112 { "ExternalPort", OSD.FromInteger(regionInfo.ExternalEndPoint.Port) }, 123 { "ExternalPort", OSD.FromInteger(regionInfo.ExternalEndPoint.Port) },
113 { "MapTexture", OSD.FromUUID(regionInfo.TerrainImage) }, 124 { "MapTexture", OSD.FromUUID(regionInfo.TerrainImage) },
114 { "Access", OSD.FromInteger(regionInfo.Access) }, 125 { "Access", OSD.FromInteger(regionInfo.Access) },
@@ -399,6 +410,83 @@ namespace OpenSim.Services.Connectors.SimianGrid
399 410
400 #endregion IGridService 411 #endregion IGridService
401 412
413 private void UploadMapTile(IScene scene)
414 {
415 string errorMessage = null;
416
417 // Create a PNG map tile and upload it to the AddMapTile API
418 byte[] pngData = Utils.EmptyBytes;
419 IMapImageGenerator tileGenerator = scene.RequestModuleInterface<IMapImageGenerator>();
420 if (tileGenerator == null)
421 {
422 m_log.Warn("[SIMIAN GRID CONNECTOR]: Cannot upload PNG map tile without an IMapImageGenerator");
423 return;
424 }
425
426 using (Image mapTile = tileGenerator.CreateMapTile())
427 {
428 using (MemoryStream stream = new MemoryStream())
429 {
430 mapTile.Save(stream, ImageFormat.Png);
431 pngData = stream.ToArray();
432 }
433 }
434
435 List<MultipartForm.Element> postParameters = new List<MultipartForm.Element>()
436 {
437 new MultipartForm.Parameter("X", scene.RegionInfo.RegionLocX.ToString()),
438 new MultipartForm.Parameter("Y", scene.RegionInfo.RegionLocY.ToString()),
439 new MultipartForm.File("Tile", "tile.png", "image/png", pngData)
440 };
441
442 // Make the remote storage request
443 try
444 {
445 HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_ServerURI);
446
447 HttpWebResponse response = MultipartForm.Post(request, postParameters);
448 using (Stream responseStream = response.GetResponseStream())
449 {
450 string responseStr = null;
451
452 try
453 {
454 responseStr = responseStream.GetStreamString();
455 OSD responseOSD = OSDParser.Deserialize(responseStr);
456 if (responseOSD.Type == OSDType.Map)
457 {
458 OSDMap responseMap = (OSDMap)responseOSD;
459 if (responseMap["Success"].AsBoolean())
460 m_log.Info("[SIMIAN GRID CONNECTOR]: Uploaded " + pngData.Length + " byte PNG map tile to AddMapTile");
461 else
462 errorMessage = "Upload failed: " + responseMap["Message"].AsString();
463 }
464 else
465 {
466 errorMessage = "Response format was invalid:\n" + responseStr;
467 }
468 }
469 catch (Exception ex)
470 {
471 if (!String.IsNullOrEmpty(responseStr))
472 errorMessage = "Failed to parse the response:\n" + responseStr;
473 else
474 errorMessage = "Failed to retrieve the response: " + ex.Message;
475 }
476 }
477 }
478 catch (WebException ex)
479 {
480 errorMessage = ex.Message;
481 }
482
483 if (!String.IsNullOrEmpty(errorMessage))
484 {
485 m_log.WarnFormat("[SIMIAN GRID CONNECTOR]: Failed to store {0} byte PNG map tile for {1}: {2}",
486 pngData.Length, scene.RegionInfo.RegionName, errorMessage.Replace('\n', ' '));
487 }
488 }
489
402 private GridRegion GetNearestRegion(Vector3d position, bool onlyEnabled) 490 private GridRegion GetNearestRegion(Vector3d position, bool onlyEnabled)
403 { 491 {
404 NameValueCollection requestArgs = new NameValueCollection 492 NameValueCollection requestArgs = new NameValueCollection
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs
index 4350749..f38ebe8 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs
@@ -191,6 +191,11 @@ namespace OpenSim.Services.Connectors.SimianGrid
191 return accounts; 191 return accounts;
192 } 192 }
193 193
194 public List<UserAccount> GetUserAccountsWhere(UUID scopeID, string query)
195 {
196 return null;
197 }
198
194 public bool StoreUserAccount(UserAccount data) 199 public bool StoreUserAccount(UserAccount data)
195 { 200 {
196// m_log.InfoFormat("[SIMIAN ACCOUNT CONNECTOR]: Storing user account for " + data.Name); 201// m_log.InfoFormat("[SIMIAN ACCOUNT CONNECTOR]: Storing user account for " + data.Name);
diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
index c45f456..24a23dd 100644
--- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
@@ -337,6 +337,10 @@ namespace OpenSim.Services.Connectors.Simulation
337 return false; 337 return false;
338 } 338 }
339 339
340 OSDMap resp = (OSDMap)result["_Result"];
341 success = resp["success"].AsBoolean();
342 reason = resp["reason"].AsString();
343
340 return success; 344 return success;
341 } 345 }
342 catch (Exception e) 346 catch (Exception e)
@@ -365,9 +369,7 @@ namespace OpenSim.Services.Connectors.Simulation
365 return true; 369 return true;
366 } 370 }
367 371
368 /// <summary> 372 private bool CloseAgent(GridRegion destination, UUID id, bool ChildOnly)
369 /// </summary>
370 public bool CloseAgent(GridRegion destination, UUID id)
371 { 373 {
372// m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: CloseAgent start"); 374// m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: CloseAgent start");
373 375
@@ -385,6 +387,16 @@ namespace OpenSim.Services.Connectors.Simulation
385 return true; 387 return true;
386 } 388 }
387 389
390 public bool CloseChildAgent(GridRegion destination, UUID id)
391 {
392 return CloseAgent(destination, id, true);
393 }
394
395 public bool CloseAgent(GridRegion destination, UUID id)
396 {
397 return CloseAgent(destination, id, false);
398 }
399
388 #endregion Agents 400 #endregion Agents
389 401
390 #region Objects 402 #region Objects
diff --git a/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs b/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs
index f6835b9..60f3abe 100644
--- a/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs
+++ b/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs
@@ -186,6 +186,11 @@ namespace OpenSim.Services.Connectors
186 return accounts; 186 return accounts;
187 } 187 }
188 188
189 public List<UserAccount> GetUserAccountsWhere(UUID scopeID, string where)
190 {
191 return null; // Not implemented for regions
192 }
193
189 public virtual bool StoreUserAccount(UserAccount data) 194 public virtual bool StoreUserAccount(UserAccount data)
190 { 195 {
191 Dictionary<string, object> sendData = new Dictionary<string, object>(); 196 Dictionary<string, object> sendData = new Dictionary<string, object>();
diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs
index 78eab3d..46d68c2 100644
--- a/OpenSim/Services/GridService/HypergridLinker.cs
+++ b/OpenSim/Services/GridService/HypergridLinker.cs
@@ -176,7 +176,6 @@ namespace OpenSim.Services.GridService
176 176
177 #region Link Region 177 #region Link Region
178 178
179 // from map search
180 public GridRegion LinkRegion(UUID scopeID, string regionDescriptor) 179 public GridRegion LinkRegion(UUID scopeID, string regionDescriptor)
181 { 180 {
182 string reason = string.Empty; 181 string reason = string.Empty;
@@ -186,7 +185,7 @@ namespace OpenSim.Services.GridService
186 185
187 private static Random random = new Random(); 186 private static Random random = new Random();
188 187
189 // From the command line link-region (obsolete) and the map 188 // From the command line link-region
190 public GridRegion TryLinkRegionToCoords(UUID scopeID, string mapName, int xloc, int yloc, out string reason) 189 public GridRegion TryLinkRegionToCoords(UUID scopeID, string mapName, int xloc, int yloc, out string reason)
191 { 190 {
192 return TryLinkRegionToCoords(scopeID, mapName, xloc, yloc, UUID.Zero, out reason); 191 return TryLinkRegionToCoords(scopeID, mapName, xloc, yloc, UUID.Zero, out reason);
@@ -195,54 +194,19 @@ namespace OpenSim.Services.GridService
195 public GridRegion TryLinkRegionToCoords(UUID scopeID, string mapName, int xloc, int yloc, UUID ownerID, out string reason) 194 public GridRegion TryLinkRegionToCoords(UUID scopeID, string mapName, int xloc, int yloc, UUID ownerID, out string reason)
196 { 195 {
197 reason = string.Empty; 196 reason = string.Empty;
198 GridRegion regInfo = null; 197 uint port = 0;
199 198 string[] parts = mapName.Split(new char[] {':'});
200 if (!mapName.StartsWith("http")) 199 string regionName = String.Empty;
200 if (parts.Length > 1)
201 { 201 {
202 string host = "127.0.0.1"; 202 regionName = mapName.Substring(parts[0].Length + 1);
203 string portstr; 203 regionName = regionName.Trim(new char[] {'"'});
204 string regionName = "";
205 uint port = 0;
206 string[] parts = mapName.Split(new char[] { ':' });
207 if (parts.Length >= 1)
208 {
209 host = parts[0];
210 }
211 if (parts.Length >= 2)
212 {
213 portstr = parts[1];
214 //m_log.Debug("-- port = " + portstr);
215 if (!UInt32.TryParse(portstr, out port))
216 regionName = parts[1];
217 }
218 // always take the last one
219 if (parts.Length >= 3)
220 {
221 regionName = parts[2];
222 }
223
224
225 bool success = TryCreateLink(scopeID, xloc, yloc, regionName, port, host, ownerID, out regInfo, out reason);
226 if (success)
227 {
228 regInfo.RegionName = mapName;
229 return regInfo;
230 }
231 } 204 }
232 else 205 GridRegion regInfo;
206 if (TryCreateLink(scopeID, xloc, yloc, regionName, 0, null, parts[0], ownerID, out regInfo, out reason))
233 { 207 {
234 string[] parts = mapName.Split(new char[] {' '}); 208 regInfo.RegionName = mapName;
235 string regionName = String.Empty; 209 return regInfo;
236 if (parts.Length > 1)
237 {
238 regionName = mapName.Substring(parts[0].Length + 1);
239 regionName = regionName.Trim(new char[] {'"'});
240 }
241 if (TryCreateLink(scopeID, xloc, yloc, regionName, 0, null, parts[0], ownerID, out regInfo, out reason))
242 {
243 regInfo.RegionName = mapName;
244 return regInfo;
245 }
246 } 210 }
247 211
248 return null; 212 return null;
@@ -255,7 +219,7 @@ namespace OpenSim.Services.GridService
255 219
256 public bool TryCreateLink(UUID scopeID, int xloc, int yloc, string remoteRegionName, uint externalPort, string externalHostName, string serverURI, UUID ownerID, out GridRegion regInfo, out string reason) 220 public bool TryCreateLink(UUID scopeID, int xloc, int yloc, string remoteRegionName, uint externalPort, string externalHostName, string serverURI, UUID ownerID, out GridRegion regInfo, out string reason)
257 { 221 {
258 m_log.DebugFormat("[HYPERGRID LINKER]: Link to {0} {1}, in {2}-{3}", 222 m_log.DebugFormat("[HYPERGRID LINKER]: Link to {0}:{1}, in {2}-{3}",
259 ((serverURI == null) ? (externalHostName + ":" + externalPort) : serverURI), 223 ((serverURI == null) ? (externalHostName + ":" + externalPort) : serverURI),
260 remoteRegionName, xloc / Constants.RegionSize, yloc / Constants.RegionSize); 224 remoteRegionName, xloc / Constants.RegionSize, yloc / Constants.RegionSize);
261 225
@@ -378,7 +342,7 @@ namespace OpenSim.Services.GridService
378 regInfo.RegionSecret = handle.ToString(); 342 regInfo.RegionSecret = handle.ToString();
379 343
380 AddHyperlinkRegion(regInfo, handle); 344 AddHyperlinkRegion(regInfo, handle);
381 m_log.InfoFormat("[HYPERGRID LINKER]: Successfully linked to region {0} with image {1}", regInfo.RegionName, regInfo.TerrainImage); 345 m_log.Info("[HYPERGRID LINKER]: Successfully linked to region_uuid " + regInfo.RegionID);
382 return true; 346 return true;
383 } 347 }
384 348
diff --git a/OpenSim/Services/HypergridService/UserAccountCache.cs b/OpenSim/Services/HypergridService/UserAccountCache.cs
index 65f9dd5..e0a3e61 100644
--- a/OpenSim/Services/HypergridService/UserAccountCache.cs
+++ b/OpenSim/Services/HypergridService/UserAccountCache.cs
@@ -90,6 +90,11 @@ namespace OpenSim.Services.HypergridService
90 return null; 90 return null;
91 } 91 }
92 92
93 public List<UserAccount> GetUserAccountsWhere(UUID scopeID, string query)
94 {
95 return null;
96 }
97
93 public List<UserAccount> GetUserAccounts(UUID scopeID, string query) 98 public List<UserAccount> GetUserAccounts(UUID scopeID, string query)
94 { 99 {
95 return null; 100 return null;
diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs
index f681df4..1a839f3 100644
--- a/OpenSim/Services/HypergridService/UserAgentService.cs
+++ b/OpenSim/Services/HypergridService/UserAgentService.cs
@@ -309,13 +309,11 @@ namespace OpenSim.Services.HypergridService
309 309
310 if (m_TravelingAgents.ContainsKey(sessionID)) 310 if (m_TravelingAgents.ContainsKey(sessionID))
311 { 311 {
312 bool result = m_TravelingAgents[sessionID].ClientIPAddress == reportedIP || 312 m_log.DebugFormat("[USER AGENT SERVICE]: Comparing with login IP {0} and MyIP {1}",
313 m_TravelingAgents[sessionID].MyIpAddress == reportedIP; // NATed 313 m_TravelingAgents[sessionID].ClientIPAddress, m_TravelingAgents[sessionID].MyIpAddress);
314
315 m_log.DebugFormat("[USER AGENT SERVICE]: Comparing {0} with login IP {1} and MyIP {1}; result is {3}",
316 reportedIP, m_TravelingAgents[sessionID].ClientIPAddress, m_TravelingAgents[sessionID].MyIpAddress, result);
317 314
318 return result; 315 return m_TravelingAgents[sessionID].ClientIPAddress == reportedIP ||
316 m_TravelingAgents[sessionID].MyIpAddress == reportedIP; // NATed
319 } 317 }
320 318
321 return false; 319 return false;
diff --git a/OpenSim/Services/Interfaces/IAttachmentsService.cs b/OpenSim/Services/Interfaces/IAttachmentsService.cs
new file mode 100644
index 0000000..bdde369
--- /dev/null
+++ b/OpenSim/Services/Interfaces/IAttachmentsService.cs
@@ -0,0 +1,17 @@
1////////////////////////////////////////////////////////////////
2//
3// (c) 2009, 2010 Careminster Limited and Melanie Thielker
4//
5// All rights reserved
6//
7using System;
8using Nini.Config;
9
10namespace OpenSim.Services.Interfaces
11{
12 public interface IAttachmentsService
13 {
14 string Get(string id);
15 void Store(string id, string data);
16 }
17}
diff --git a/OpenSim/Services/Interfaces/IGridService.cs b/OpenSim/Services/Interfaces/IGridService.cs
index d809996..cdcb961 100644
--- a/OpenSim/Services/Interfaces/IGridService.cs
+++ b/OpenSim/Services/Interfaces/IGridService.cs
@@ -324,9 +324,13 @@ namespace OpenSim.Services.Interfaces
324 } 324 }
325 catch (SocketException e) 325 catch (SocketException e)
326 { 326 {
327 throw new Exception( 327 /*throw new Exception(
328 "Unable to resolve local hostname " + m_externalHostName + " innerException of type '" + 328 "Unable to resolve local hostname " + m_externalHostName + " innerException of type '" +
329 e + "' attached to this exception", e); 329 e + "' attached to this exception", e);*/
330 // Don't throw a fatal exception here, instead, return Null and handle it in the caller.
331 // Reason is, on systems such as OSgrid it has occured that known hostnames stop
332 // resolving and thus make surrounding regions crash out with this exception.
333 return null;
330 } 334 }
331 335
332 return new IPEndPoint(ia, m_internalEndPoint.Port); 336 return new IPEndPoint(ia, m_internalEndPoint.Port);
@@ -385,6 +389,12 @@ namespace OpenSim.Services.Interfaces
385 if (kvp.ContainsKey("regionName")) 389 if (kvp.ContainsKey("regionName"))
386 RegionName = (string)kvp["regionName"]; 390 RegionName = (string)kvp["regionName"];
387 391
392 if (kvp.ContainsKey("access"))
393 {
394 byte access = Convert.ToByte((string)kvp["access"]);
395 Maturity = (int)Util.ConvertAccessLevelToMaturity(access);
396 }
397
388 if (kvp.ContainsKey("serverIP")) 398 if (kvp.ContainsKey("serverIP"))
389 { 399 {
390 //int port = 0; 400 //int port = 0;
diff --git a/OpenSim/Services/Interfaces/ISimulationService.cs b/OpenSim/Services/Interfaces/ISimulationService.cs
index 5f9ce6d..ae6bd72 100644
--- a/OpenSim/Services/Interfaces/ISimulationService.cs
+++ b/OpenSim/Services/Interfaces/ISimulationService.cs
@@ -80,6 +80,14 @@ namespace OpenSim.Services.Interfaces
80 bool ReleaseAgent(UUID originRegion, UUID id, string uri); 80 bool ReleaseAgent(UUID originRegion, UUID id, string uri);
81 81
82 /// <summary> 82 /// <summary>
83 /// Close child agent.
84 /// </summary>
85 /// <param name="regionHandle"></param>
86 /// <param name="id"></param>
87 /// <returns></returns>
88 bool CloseChildAgent(GridRegion destination, UUID id);
89
90 /// <summary>
83 /// Close agent. 91 /// Close agent.
84 /// </summary> 92 /// </summary>
85 /// <param name="regionHandle"></param> 93 /// <param name="regionHandle"></param>
diff --git a/OpenSim/Services/Interfaces/IUserAccountService.cs b/OpenSim/Services/Interfaces/IUserAccountService.cs
index 1b85980..6d5d2a0 100644
--- a/OpenSim/Services/Interfaces/IUserAccountService.cs
+++ b/OpenSim/Services/Interfaces/IUserAccountService.cs
@@ -91,6 +91,7 @@ namespace OpenSim.Services.Interfaces
91 public int UserLevel; 91 public int UserLevel;
92 public int UserFlags; 92 public int UserFlags;
93 public string UserTitle; 93 public string UserTitle;
94 public string UserCountry;
94 public Boolean LocalToGrid = true; 95 public Boolean LocalToGrid = true;
95 96
96 public Dictionary<string, object> ServiceURLs; 97 public Dictionary<string, object> ServiceURLs;
@@ -120,6 +121,8 @@ namespace OpenSim.Services.Interfaces
120 UserFlags = Convert.ToInt32(kvp["UserFlags"].ToString()); 121 UserFlags = Convert.ToInt32(kvp["UserFlags"].ToString());
121 if (kvp.ContainsKey("UserTitle")) 122 if (kvp.ContainsKey("UserTitle"))
122 UserTitle = kvp["UserTitle"].ToString(); 123 UserTitle = kvp["UserTitle"].ToString();
124 if (kvp.ContainsKey("UserCountry"))
125 UserCountry = kvp["UserCountry"].ToString();
123 if (kvp.ContainsKey("LocalToGrid")) 126 if (kvp.ContainsKey("LocalToGrid"))
124 Boolean.TryParse(kvp["LocalToGrid"].ToString(), out LocalToGrid); 127 Boolean.TryParse(kvp["LocalToGrid"].ToString(), out LocalToGrid);
125 128
@@ -155,6 +158,7 @@ namespace OpenSim.Services.Interfaces
155 result["UserLevel"] = UserLevel.ToString(); 158 result["UserLevel"] = UserLevel.ToString();
156 result["UserFlags"] = UserFlags.ToString(); 159 result["UserFlags"] = UserFlags.ToString();
157 result["UserTitle"] = UserTitle; 160 result["UserTitle"] = UserTitle;
161 result["UserCountry"] = UserCountry;
158 result["LocalToGrid"] = LocalToGrid.ToString(); 162 result["LocalToGrid"] = LocalToGrid.ToString();
159 163
160 string str = string.Empty; 164 string str = string.Empty;
@@ -182,6 +186,7 @@ namespace OpenSim.Services.Interfaces
182 /// <param name="query"></param> 186 /// <param name="query"></param>
183 /// <returns></returns> 187 /// <returns></returns>
184 List<UserAccount> GetUserAccounts(UUID scopeID, string query); 188 List<UserAccount> GetUserAccounts(UUID scopeID, string query);
189 List<UserAccount> GetUserAccountsWhere(UUID scopeID, string where);
185 190
186 /// <summary> 191 /// <summary>
187 /// Store the data given, wich replaces the stored data, therefore must be complete. 192 /// Store the data given, wich replaces the stored data, therefore must be complete.
diff --git a/OpenSim/Services/LLLoginService/LLLoginResponse.cs b/OpenSim/Services/LLLoginService/LLLoginResponse.cs
index 1a874c8..de05f28 100644
--- a/OpenSim/Services/LLLoginService/LLLoginResponse.cs
+++ b/OpenSim/Services/LLLoginService/LLLoginResponse.cs
@@ -55,6 +55,7 @@ namespace OpenSim.Services.LLLoginService
55 public static LLFailedLoginResponse InventoryProblem; 55 public static LLFailedLoginResponse InventoryProblem;
56 public static LLFailedLoginResponse DeadRegionProblem; 56 public static LLFailedLoginResponse DeadRegionProblem;
57 public static LLFailedLoginResponse LoginBlockedProblem; 57 public static LLFailedLoginResponse LoginBlockedProblem;
58 public static LLFailedLoginResponse UnverifiedAccountProblem;
58 public static LLFailedLoginResponse AlreadyLoggedInProblem; 59 public static LLFailedLoginResponse AlreadyLoggedInProblem;
59 public static LLFailedLoginResponse InternalError; 60 public static LLFailedLoginResponse InternalError;
60 61
@@ -75,6 +76,10 @@ namespace OpenSim.Services.LLLoginService
75 LoginBlockedProblem = new LLFailedLoginResponse("presence", 76 LoginBlockedProblem = new LLFailedLoginResponse("presence",
76 "Logins are currently restricted. Please try again later.", 77 "Logins are currently restricted. Please try again later.",
77 "false"); 78 "false");
79 UnverifiedAccountProblem = new LLFailedLoginResponse("presence",
80 "Your account has not yet been verified. Please check " +
81 "your email and click the provided link.",
82 "false");
78 AlreadyLoggedInProblem = new LLFailedLoginResponse("presence", 83 AlreadyLoggedInProblem = new LLFailedLoginResponse("presence",
79 "You appear to be already logged in. " + 84 "You appear to be already logged in. " +
80 "If this is not the case please wait for your session to timeout. " + 85 "If this is not the case please wait for your session to timeout. " +
@@ -327,6 +332,7 @@ namespace OpenSim.Services.LLLoginService
327 private void FillOutRegionData(GridRegion destination) 332 private void FillOutRegionData(GridRegion destination)
328 { 333 {
329 IPEndPoint endPoint = destination.ExternalEndPoint; 334 IPEndPoint endPoint = destination.ExternalEndPoint;
335 if (endPoint == null) return;
330 SimAddress = endPoint.Address.ToString(); 336 SimAddress = endPoint.Address.ToString();
331 SimPort = (uint)endPoint.Port; 337 SimPort = (uint)endPoint.Port;
332 RegionX = (uint)destination.RegionLocX; 338 RegionX = (uint)destination.RegionLocX;
diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs
index 02b5cc1..035980d 100644
--- a/OpenSim/Services/LLLoginService/LLLoginService.cs
+++ b/OpenSim/Services/LLLoginService/LLLoginService.cs
@@ -132,7 +132,8 @@ namespace OpenSim.Services.LLLoginService
132 Object[] args = new Object[] { config }; 132 Object[] args = new Object[] { config };
133 m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(accountService, args); 133 m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(accountService, args);
134 m_GridUserService = ServerUtils.LoadPlugin<IGridUserService>(gridUserService, args); 134 m_GridUserService = ServerUtils.LoadPlugin<IGridUserService>(gridUserService, args);
135 m_AuthenticationService = ServerUtils.LoadPlugin<IAuthenticationService>(authService, args); 135 Object[] authArgs = new Object[] { config, m_UserAccountService };
136 m_AuthenticationService = ServerUtils.LoadPlugin<IAuthenticationService>(authService, authArgs);
136 m_InventoryService = ServerUtils.LoadPlugin<IInventoryService>(invService, args); 137 m_InventoryService = ServerUtils.LoadPlugin<IInventoryService>(invService, args);
137 138
138 if (gridService != string.Empty) 139 if (gridService != string.Empty)
@@ -275,6 +276,12 @@ namespace OpenSim.Services.LLLoginService
275 return LLFailedLoginResponse.UserProblem; 276 return LLFailedLoginResponse.UserProblem;
276 } 277 }
277 278
279 if (account.UserLevel < 0)
280 {
281 m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: Unverified account");
282 return LLFailedLoginResponse.UnverifiedAccountProblem;
283 }
284
278 if (account.UserLevel < m_MinLoginLevel) 285 if (account.UserLevel < m_MinLoginLevel)
279 { 286 {
280 m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: login is blocked for user level {0}", account.UserLevel); 287 m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: login is blocked for user level {0}", account.UserLevel);
diff --git a/OpenSim/Services/UserAccountService/UserAccountService.cs b/OpenSim/Services/UserAccountService/UserAccountService.cs
index 4a29690..ad06300 100644
--- a/OpenSim/Services/UserAccountService/UserAccountService.cs
+++ b/OpenSim/Services/UserAccountService/UserAccountService.cs
@@ -170,6 +170,10 @@ namespace OpenSim.Services.UserAccountService
170 Int32.TryParse(d.Data["UserLevel"], out u.UserLevel); 170 Int32.TryParse(d.Data["UserLevel"], out u.UserLevel);
171 if (d.Data.ContainsKey("UserFlags") && d.Data["UserFlags"] != null) 171 if (d.Data.ContainsKey("UserFlags") && d.Data["UserFlags"] != null)
172 Int32.TryParse(d.Data["UserFlags"], out u.UserFlags); 172 Int32.TryParse(d.Data["UserFlags"], out u.UserFlags);
173 if (d.Data.ContainsKey("UserCountry") && d.Data["UserCountry"] != null)
174 u.UserCountry = d.Data["UserCountry"].ToString();
175 else
176 u.UserTitle = string.Empty;
173 177
174 if (d.Data.ContainsKey("ServiceURLs") && d.Data["ServiceURLs"] != null) 178 if (d.Data.ContainsKey("ServiceURLs") && d.Data["ServiceURLs"] != null)
175 { 179 {
@@ -291,7 +295,22 @@ namespace OpenSim.Services.UserAccountService
291 295
292 public List<UserAccount> GetUserAccounts(UUID scopeID, string query) 296 public List<UserAccount> GetUserAccounts(UUID scopeID, string query)
293 { 297 {
294 UserAccountData[] d = m_Database.GetUsers(scopeID, query); 298 UserAccountData[] d = m_Database.GetUsers(scopeID, query.Trim());
299
300 if (d == null)
301 return new List<UserAccount>();
302
303 List<UserAccount> ret = new List<UserAccount>();
304
305 foreach (UserAccountData data in d)
306 ret.Add(MakeUserAccount(data));
307
308 return ret;
309 }
310
311 public List<UserAccount> GetUserAccountsWhere(UUID scopeID, string where)
312 {
313 UserAccountData[] d = m_Database.GetUsersWhere(scopeID, where);
295 314
296 if (d == null) 315 if (d == null)
297 return new List<UserAccount>(); 316 return new List<UserAccount>();
diff --git a/OpenSim/Tests/Common/Mock/MockAssetDataPlugin.cs b/OpenSim/Tests/Common/Mock/MockAssetDataPlugin.cs
index 4a15cf2..5bab62c 100644
--- a/OpenSim/Tests/Common/Mock/MockAssetDataPlugin.cs
+++ b/OpenSim/Tests/Common/Mock/MockAssetDataPlugin.cs
@@ -54,9 +54,10 @@ namespace OpenSim.Tests.Common.Mock
54 return assets.Find(x=>x.FullID == uuid); 54 return assets.Find(x=>x.FullID == uuid);
55 } 55 }
56 56
57 public void StoreAsset(AssetBase asset) 57 public bool StoreAsset(AssetBase asset)
58 { 58 {
59 assets.Add(asset); 59 assets.Add(asset);
60 return true;
60 } 61 }
61 62
62 public List<AssetMetadata> FetchAssetMetadataSet(int start, int count) { return new List<AssetMetadata>(count); } 63 public List<AssetMetadata> FetchAssetMetadataSet(int start, int count) { return new List<AssetMetadata>(count); }
diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs
index ab89fe0..b06bff6 100644
--- a/OpenSim/Tests/Common/Mock/TestClient.cs
+++ b/OpenSim/Tests/Common/Mock/TestClient.cs
@@ -71,7 +71,7 @@ namespace OpenSim.Tests.Common.Mock
71 public event MoneyTransferRequest OnMoneyTransferRequest; 71 public event MoneyTransferRequest OnMoneyTransferRequest;
72 public event ParcelBuy OnParcelBuy; 72 public event ParcelBuy OnParcelBuy;
73 public event Action<IClientAPI> OnConnectionClosed; 73 public event Action<IClientAPI> OnConnectionClosed;
74 74 public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy;
75 public event ImprovedInstantMessage OnInstantMessage; 75 public event ImprovedInstantMessage OnInstantMessage;
76 public event ChatMessage OnChatFromClient; 76 public event ChatMessage OnChatFromClient;
77 public event TextureRequest OnRequestTexture; 77 public event TextureRequest OnRequestTexture;
@@ -276,7 +276,7 @@ namespace OpenSim.Tests.Common.Mock
276 public event ClassifiedInfoRequest OnClassifiedInfoRequest; 276 public event ClassifiedInfoRequest OnClassifiedInfoRequest;
277 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate; 277 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate;
278 public event ClassifiedDelete OnClassifiedDelete; 278 public event ClassifiedDelete OnClassifiedDelete;
279 public event ClassifiedDelete OnClassifiedGodDelete; 279 public event ClassifiedGodDelete OnClassifiedGodDelete;
280 280
281 public event EventNotificationAddRequest OnEventNotificationAddRequest; 281 public event EventNotificationAddRequest OnEventNotificationAddRequest;
282 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest; 282 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest;
@@ -315,6 +315,7 @@ namespace OpenSim.Tests.Common.Mock
315 public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest; 315 public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest;
316 public event SimWideDeletesDelegate OnSimWideDeletes; 316 public event SimWideDeletesDelegate OnSimWideDeletes;
317 public event SendPostcard OnSendPostcard; 317 public event SendPostcard OnSendPostcard;
318 public event ChangeInventoryItemFlags OnChangeInventoryItemFlags;
318 public event MuteListEntryUpdate OnUpdateMuteListEntry; 319 public event MuteListEntryUpdate OnUpdateMuteListEntry;
319 public event MuteListEntryRemove OnRemoveMuteListEntry; 320 public event MuteListEntryRemove OnRemoveMuteListEntry;
320 public event GodlikeMessage onGodlikeMessage; 321 public event GodlikeMessage onGodlikeMessage;
@@ -907,6 +908,10 @@ namespace OpenSim.Tests.Common.Mock
907 908
908 public void Close() 909 public void Close()
909 { 910 {
911 Close(true);
912 }
913 public void Close(bool sendStop)
914 {
910 m_scene.RemoveClient(AgentId, true); 915 m_scene.RemoveClient(AgentId, true);
911 } 916 }
912 917