aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim')
-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.migrations8
-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.cs136
-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.cs302
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs71
-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.cs505
-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.cs589
-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.cs2905
-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, 18310 insertions, 3212 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 3275146..48ef447 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 }
@@ -1793,7 +1819,7 @@ namespace OpenSim.Data.MySQL
1793 cmd.Parameters.AddWithValue("Media", null == s.Media ? null : s.Media.ToXml()); 1819 cmd.Parameters.AddWithValue("Media", null == s.Media ? null : s.Media.ToXml());
1794 } 1820 }
1795 1821
1796 public void StorePrimInventory(UUID primID, ICollection<TaskInventoryItem> items) 1822 public virtual void StorePrimInventory(UUID primID, ICollection<TaskInventoryItem> items)
1797 { 1823 {
1798 lock (m_dbLock) 1824 lock (m_dbLock)
1799 { 1825 {
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 642e3b7..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` (
@@ -863,9 +863,3 @@ BEGIN;
863ALTER TABLE `regionsettings` ADD COLUMN `parcel_tile_ID` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'; 863ALTER TABLE `regionsettings` ADD COLUMN `parcel_tile_ID` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000';
864COMMIT; 864COMMIT;
865 865
866:VERSION 41 #---------------- Timed bans/access
867
868BEGIN;
869ALTER TABLE `landaccesslist` ADD COLUMN `Expires` INTEGER NOT NULL DEFAULT 0;
870COMMIT;
871
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 dd3e656..c4c61ff 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 58a80ef..27fadfa 100644
--- a/OpenSim/Framework/LandData.cs
+++ b/OpenSim/Framework/LandData.cs
@@ -67,7 +67,7 @@ namespace OpenSim.Framework
67 67
68 private uint _flags = (uint) ParcelFlags.AllowFly | (uint) ParcelFlags.AllowLandmark | 68 private uint _flags = (uint) ParcelFlags.AllowFly | (uint) ParcelFlags.AllowLandmark |
69 (uint) ParcelFlags.AllowAPrimitiveEntry | 69 (uint) ParcelFlags.AllowAPrimitiveEntry |
70 (uint) ParcelFlags.AllowDeedToGroup | (uint) ParcelFlags.AllowTerraform | 70 (uint) ParcelFlags.AllowDeedToGroup |
71 (uint) ParcelFlags.CreateObjects | (uint) ParcelFlags.AllowOtherScripts | 71 (uint) ParcelFlags.CreateObjects | (uint) ParcelFlags.AllowOtherScripts |
72 (uint) ParcelFlags.SoundLocal; 72 (uint) ParcelFlags.SoundLocal;
73 73
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 e2664dd..b88895f 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;
@@ -644,6 +646,9 @@ namespace OpenSim.Framework
644 string location = String.Format("{0},{1}", m_regionLocX, m_regionLocY); 646 string location = String.Format("{0},{1}", m_regionLocX, m_regionLocY);
645 config.Set("Location", location); 647 config.Set("Location", location);
646 648
649 if (DataStore != String.Empty)
650 config.Set("Datastore", DataStore);
651
647 config.Set("InternalAddress", m_internalEndPoint.Address.ToString()); 652 config.Set("InternalAddress", m_internalEndPoint.Address.ToString());
648 config.Set("InternalPort", m_internalEndPoint.Port); 653 config.Set("InternalPort", m_internalEndPoint.Port);
649 654
@@ -829,6 +834,9 @@ namespace OpenSim.Framework
829 case "sim_location_y": 834 case "sim_location_y":
830 m_regionLocY = (uint) configuration_result; 835 m_regionLocY = (uint) configuration_result;
831 break; 836 break;
837 case "datastore":
838 DataStore = (string) configuration_result;
839 break;
832 case "internal_ip_address": 840 case "internal_ip_address":
833 IPAddress address = (IPAddress) configuration_result; 841 IPAddress address = (IPAddress) configuration_result;
834 m_internalEndPoint = new IPEndPoint(address, 0); 842 m_internalEndPoint = new IPEndPoint(address, 0);
@@ -979,6 +987,11 @@ namespace OpenSim.Framework
979 return regionInfo; 987 return regionInfo;
980 } 988 }
981 989
990 public int getInternalEndPointPort()
991 {
992 return m_internalEndPoint.Port;
993 }
994
982 public Dictionary<string, object> ToKeyValuePairs() 995 public Dictionary<string, object> ToKeyValuePairs()
983 { 996 {
984 Dictionary<string, object> kvp = new Dictionary<string, object>(); 997 Dictionary<string, object> kvp = new Dictionary<string, object>();
@@ -997,4 +1010,4 @@ namespace OpenSim.Framework
997 return kvp; 1010 return kvp;
998 } 1011 }
999 } 1012 }
1000} \ No newline at end of file 1013}
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 cdd4957..8c0a7e9 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..fe75271 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -367,6 +367,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
367 367
368 originalPositions[objectGroup.UUID] = objectGroup.AbsolutePosition; 368 originalPositions[objectGroup.UUID] = objectGroup.AbsolutePosition;
369 369
370 // Restore attachment data after trip through the sim
371 if (objectGroup.RootPart.AttachPoint > 0)
372 inventoryStoredPosition = objectGroup.RootPart.AttachOffset;
373 objectGroup.RootPart.Shape.State = objectGroup.RootPart.AttachPoint;
374
370 objectGroup.AbsolutePosition = inventoryStoredPosition; 375 objectGroup.AbsolutePosition = inventoryStoredPosition;
371 376
372 // Make sure all bits but the ones we want are clear 377 // Make sure all bits but the ones we want are clear
@@ -476,8 +481,17 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
476 IClientAPI remoteClient) 481 IClientAPI remoteClient)
477 { 482 {
478 uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move) | 7; 483 uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move) | 7;
484 // For the porposes of inventory, an object is modify if the prims
485 // are modify. This allows renaming an object that contains no
486 // mod items.
479 foreach (SceneObjectGroup grp in objsForEffectivePermissions) 487 foreach (SceneObjectGroup grp in objsForEffectivePermissions)
480 effectivePerms &= grp.GetEffectivePermissions(); 488 {
489 uint groupPerms = grp.GetEffectivePermissions(true);
490 if ((grp.RootPart.BaseMask & (uint)PermissionMask.Modify) != 0)
491 groupPerms |= (uint)PermissionMask.Modify;
492
493 effectivePerms &= groupPerms;
494 }
481 effectivePerms |= (uint)PermissionMask.Move; 495 effectivePerms |= (uint)PermissionMask.Move;
482 496
483 if (remoteClient != null && (remoteClient.AgentId != so.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions()) 497 if (remoteClient != null && (remoteClient.AgentId != so.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions())
@@ -644,7 +658,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
644 if (so.RootPart.FromFolderID != UUID.Zero) 658 if (so.RootPart.FromFolderID != UUID.Zero)
645 { 659 {
646 InventoryFolderBase f = new InventoryFolderBase(so.RootPart.FromFolderID, userID); 660 InventoryFolderBase f = new InventoryFolderBase(so.RootPart.FromFolderID, userID);
647 folder = m_Scene.InventoryService.GetFolder(f); 661 if (f != null)
662 folder = m_Scene.InventoryService.GetFolder(f);
648 } 663 }
649 } 664 }
650 665
@@ -674,15 +689,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
674 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) 689 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
675 { 690 {
676// m_log.DebugFormat("[INVENTORY ACCESS MODULE]: RezObject for {0}, item {1}", remoteClient.Name, itemID); 691// m_log.DebugFormat("[INVENTORY ACCESS MODULE]: RezObject for {0}, item {1}", remoteClient.Name, itemID);
677
678 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); 692 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId);
679 item = m_Scene.InventoryService.GetItem(item); 693 item = m_Scene.InventoryService.GetItem(item);
680 694
681 if (item == null) 695 if (item == null)
682 { 696 {
683 m_log.WarnFormat(
684 "[InventoryAccessModule]: Could not find item {0} for {1} in RezObject()",
685 itemID, remoteClient.Name);
686 697
687 return null; 698 return null;
688 } 699 }
@@ -734,6 +745,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
734 if (e == null || attachment) // Single 745 if (e == null || attachment) // Single
735 { 746 {
736 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 747 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
748 if (!attachment)
749 {
750 g.RootPart.AttachPoint = g.RootPart.Shape.State;
751 g.RootPart.AttachOffset = g.AbsolutePosition;
752 }
737 753
738 objlist.Add(g); 754 objlist.Add(g);
739 veclist.Add(new Vector3(0, 0, 0)); 755 veclist.Add(new Vector3(0, 0, 0));
@@ -763,6 +779,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
763 foreach (XmlNode n in groups) 779 foreach (XmlNode n in groups)
764 { 780 {
765 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml); 781 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml);
782 g.RootPart.AttachPoint = g.RootPart.Shape.State;
783 g.RootPart.AttachOffset = g.AbsolutePosition;
766 784
767 objlist.Add(g); 785 objlist.Add(g);
768 XmlElement el = (XmlElement)n; 786 XmlElement el = (XmlElement)n;
@@ -782,12 +800,35 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
782 } 800 }
783 } 801 }
784 802
803 int primcount = 0;
804 foreach (SceneObjectGroup g in objlist)
805 primcount += g.PrimCount;
806
807 if (!m_Scene.Permissions.CanRezObject(
808 primcount, remoteClient.AgentId, pos)
809 && !attachment)
810 {
811 // The client operates in no fail mode. It will
812 // have already removed the item from the folder
813 // if it's no copy.
814 // Put it back if it's not an attachment
815 //
816 if (item != null)
817 {
818 if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!attachment))
819 remoteClient.SendBulkUpdateInventory(item);
820 }
821
822 return null;
823 }
824
785 if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, attachment)) 825 if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, attachment))
786 return null; 826 return null;
787 827
788 for (int i = 0; i < objlist.Count; i++) 828 for (int i = 0; i < objlist.Count; i++)
789 { 829 {
790 group = objlist[i]; 830 group = objlist[i];
831 SceneObjectPart rootPart = group.RootPart;
791 832
792// Vector3 storedPosition = group.AbsolutePosition; 833// Vector3 storedPosition = group.AbsolutePosition;
793 if (group.UUID == UUID.Zero) 834 if (group.UUID == UUID.Zero)
@@ -842,8 +883,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
842 883
843 if (!attachment) 884 if (!attachment)
844 { 885 {
845 SceneObjectPart rootPart = group.RootPart;
846
847 if (rootPart.Shape.PCode == (byte)PCode.Prim) 886 if (rootPart.Shape.PCode == (byte)PCode.Prim)
848 group.ClearPartAttachmentData(); 887 group.ClearPartAttachmentData();
849 888
@@ -853,12 +892,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
853 892
854 rootPart.ScheduleFullUpdate(); 893 rootPart.ScheduleFullUpdate();
855 } 894 }
856
857// m_log.DebugFormat(
858// "[InventoryAccessModule]: Rezzed {0} {1} {2} for {3}",
859// group.Name, group.LocalId, group.UUID, remoteClient.Name);
860 } 895 }
861 896
897 group.SetGroup(remoteClient.ActiveGroupId, remoteClient);
898
862 if (item != null) 899 if (item != null)
863 DoPostRezWhenFromItem(item, attachment); 900 DoPostRezWhenFromItem(item, attachment);
864 901
@@ -898,25 +935,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
898 } 935 }
899 } 936 }
900 937
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++) 938 for (int i = 0; i < objlist.Count; i++)
921 { 939 {
922 SceneObjectGroup so = objlist[i]; 940 SceneObjectGroup so = objlist[i];
@@ -932,14 +950,18 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
932 { 950 {
933 rootPart.Name = item.Name; 951 rootPart.Name = item.Name;
934 rootPart.Description = item.Description; 952 rootPart.Description = item.Description;
935 rootPart.ObjectSaleType = item.SaleType; 953 if ((item.Flags & (uint)InventoryItemFlags.ObjectSlamSale) != 0)
936 rootPart.SalePrice = item.SalePrice; 954 {
955 rootPart.ObjectSaleType = item.SaleType;
956 rootPart.SalePrice = item.SalePrice;
957 }
937 } 958 }
938 959
939 rootPart.FromFolderID = item.Folder; 960 rootPart.FromFolderID = item.Folder;
940 961
941 if ((rootPart.OwnerID != item.Owner) || 962 if ((rootPart.OwnerID != item.Owner) ||
942 (item.CurrentPermissions & 16) != 0) 963 (item.CurrentPermissions & 16) != 0 ||
964 (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0)
943 { 965 {
944 //Need to kill the for sale here 966 //Need to kill the for sale here
945 rootPart.ObjectSaleType = 0; 967 rootPart.ObjectSaleType = 0;
@@ -949,31 +971,43 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
949 { 971 {
950 foreach (SceneObjectPart part in so.Parts) 972 foreach (SceneObjectPart part in so.Parts)
951 { 973 {
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 974 part.GroupMask = 0; // DO NOT propagate here
975
976 part.LastOwnerID = part.OwnerID;
977 part.OwnerID = item.Owner;
978 part.Inventory.ChangeInventoryOwner(item.Owner);
958 } 979 }
959 980
960 so.ApplyNextOwnerPermissions(); 981 so.ApplyNextOwnerPermissions();
982
983 // In case the user has changed flags on a received item
984 // we have to apply those changes after the slam. Else we
985 // get a net loss of permissions
986 foreach (SceneObjectPart part in so.Parts)
987 {
988 if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0)
989 {
990 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
991 part.EveryoneMask = item.EveryOnePermissions & part.BaseMask;
992 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
993 part.NextOwnerMask = item.NextPermissions & part.BaseMask;
994 }
995 }
961 } 996 }
962 } 997 }
963 998 else
964 foreach (SceneObjectPart part in so.Parts)
965 { 999 {
966 part.FromUserInventoryItemID = fromUserInventoryItemId; 1000 foreach (SceneObjectPart part in so.Parts)
967
968 if ((part.OwnerID != item.Owner) ||
969 (item.CurrentPermissions & 16) != 0)
970 { 1001 {
971 part.Inventory.ChangeInventoryOwner(item.Owner); 1002 part.FromUserInventoryItemID = fromUserInventoryItemId;
972 part.GroupMask = 0; // DO NOT propagate here 1003
1004 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
1005 part.EveryoneMask = item.EveryOnePermissions;
1006 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
1007 part.NextOwnerMask = item.NextPermissions;
1008 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
1009 part.GroupMask = item.GroupPermissions;
973 } 1010 }
974
975 part.EveryoneMask = item.EveryOnePermissions;
976 part.NextOwnerMask = item.NextPermissions;
977 } 1011 }
978 1012
979 rootPart.TrimPermissions(); 1013 rootPart.TrimPermissions();
@@ -1111,4 +1145,4 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
1111 1145
1112 #endregion 1146 #endregion
1113 } 1147 }
1114} \ No newline at end of file 1148}
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 1c503aa..0f83d82 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>
@@ -204,6 +205,8 @@ namespace OpenSim.Region.CoreModules.World.Land
204 client.OnParcelInfoRequest += ClientOnParcelInfoRequest; 205 client.OnParcelInfoRequest += ClientOnParcelInfoRequest;
205 client.OnParcelDeedToGroup += ClientOnParcelDeedToGroup; 206 client.OnParcelDeedToGroup += ClientOnParcelDeedToGroup;
206 client.OnPreAgentUpdate += ClientOnPreAgentUpdate; 207 client.OnPreAgentUpdate += ClientOnPreAgentUpdate;
208 client.OnParcelEjectUser += ClientOnParcelEjectUser;
209 client.OnParcelFreezeUser += ClientOnParcelFreezeUser;
207 210
208 EntityBase presenceEntity; 211 EntityBase presenceEntity;
209 if (m_scene.Entities.TryGetValue(client.AgentId, out presenceEntity) && presenceEntity is ScenePresence) 212 if (m_scene.Entities.TryGetValue(client.AgentId, out presenceEntity) && presenceEntity is ScenePresence)
@@ -215,36 +218,6 @@ namespace OpenSim.Region.CoreModules.World.Land
215 218
216 void ClientOnPreAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) 219 void ClientOnPreAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
217 { 220 {
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 } 221 }
249 222
250 public void Close() 223 public void Close()
@@ -363,10 +336,16 @@ namespace OpenSim.Region.CoreModules.World.Land
363 private void ForceAvatarToPosition(ScenePresence avatar, Vector3? position) 336 private void ForceAvatarToPosition(ScenePresence avatar, Vector3? position)
364 { 337 {
365 if (m_scene.Permissions.IsGod(avatar.UUID)) return; 338 if (m_scene.Permissions.IsGod(avatar.UUID)) return;
366 if (position.HasValue) 339
367 { 340 if (!position.HasValue)
368 forcedPosition[avatar.ControllingClient.AgentId] = (Vector3)position; 341 return;
369 } 342
343 bool isFlying = avatar.PhysicsActor.Flying;
344 avatar.RemoveFromPhysicalScene();
345
346 avatar.AbsolutePosition = (Vector3)position;
347
348 avatar.AddToPhysicalScene(isFlying);
370 } 349 }
371 350
372 public void SendYouAreRestrictedNotice(ScenePresence avatar) 351 public void SendYouAreRestrictedNotice(ScenePresence avatar)
@@ -386,29 +365,7 @@ namespace OpenSim.Region.CoreModules.World.Land
386 } 365 }
387 366
388 if (parcelAvatarIsEntering != null) 367 if (parcelAvatarIsEntering != null)
389 { 368 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 } 369 }
413 } 370 }
414 371
@@ -512,6 +469,7 @@ namespace OpenSim.Region.CoreModules.World.Land
512 //when we are finally in a safe place, lets release the forced position lock 469 //when we are finally in a safe place, lets release the forced position lock
513 forcedPosition.Remove(clientAvatar.ControllingClient.AgentId); 470 forcedPosition.Remove(clientAvatar.ControllingClient.AgentId);
514 } 471 }
472 EnforceBans(parcel, clientAvatar);
515 } 473 }
516 } 474 }
517 475
@@ -720,7 +678,7 @@ namespace OpenSim.Region.CoreModules.World.Land
720 int x; 678 int x;
721 int y; 679 int y;
722 680
723 if (x_float >= Constants.RegionSize || x_float < 0 || y_float >= Constants.RegionSize || y_float < 0) 681 if (x_float > Constants.RegionSize || x_float < 0 || y_float > Constants.RegionSize || y_float < 0)
724 return null; 682 return null;
725 683
726 try 684 try
@@ -770,14 +728,13 @@ namespace OpenSim.Region.CoreModules.World.Land
770 { 728 {
771 try 729 try
772 { 730 {
773 return m_landList[m_landIDList[x / 4, y / 4]]; 731 //if (m_landList.ContainsKey(m_landIDList[x / 4, y / 4]))
732 return m_landList[m_landIDList[x / 4, y / 4]];
733 //else
734 // return null;
774 } 735 }
775 catch (IndexOutOfRangeException) 736 catch (IndexOutOfRangeException)
776 { 737 {
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; 738 return null;
782 } 739 }
783 } 740 }
@@ -1060,6 +1017,10 @@ namespace OpenSim.Region.CoreModules.World.Land
1060 //Owner Flag 1017 //Owner Flag
1061 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER); 1018 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER);
1062 } 1019 }
1020 else if (currentParcelBlock.LandData.IsGroupOwned && remote_client.IsGroupMember(currentParcelBlock.LandData.GroupID))
1021 {
1022 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_GROUP);
1023 }
1063 else if (currentParcelBlock.LandData.SalePrice > 0 && 1024 else if (currentParcelBlock.LandData.SalePrice > 0 &&
1064 (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero || 1025 (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero ||
1065 currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId)) 1026 currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId))
@@ -1360,18 +1321,31 @@ namespace OpenSim.Region.CoreModules.World.Land
1360 1321
1361 public void EventManagerOnIncomingLandDataFromStorage(List<LandData> data) 1322 public void EventManagerOnIncomingLandDataFromStorage(List<LandData> data)
1362 { 1323 {
1363 for (int i = 0; i < data.Count; i++) 1324 lock (m_landList)
1364 { 1325 {
1365 IncomingLandObjectFromStorage(data[i]); 1326 //Remove all the land objects in the sim and then process our new data
1327 foreach (int n in m_landList.Keys)
1328 {
1329 m_scene.EventManager.TriggerLandObjectRemoved(m_landList[n].LandData.GlobalID);
1330 }
1331 m_landIDList.Initialize();
1332 m_landList.Clear();
1333
1334 for (int i = 0; i < data.Count; i++)
1335 {
1336 IncomingLandObjectFromStorage(data[i]);
1337 }
1366 } 1338 }
1367 } 1339 }
1368 1340
1369 public void IncomingLandObjectFromStorage(LandData data) 1341 public void IncomingLandObjectFromStorage(LandData data)
1370 { 1342 {
1343
1371 ILandObject new_land = new LandObject(data.OwnerID, data.IsGroupOwned, m_scene); 1344 ILandObject new_land = new LandObject(data.OwnerID, data.IsGroupOwned, m_scene);
1372 new_land.LandData = data.Copy(); 1345 new_land.LandData = data.Copy();
1373 new_land.SetLandBitmapFromByteArray(); 1346 new_land.SetLandBitmapFromByteArray();
1374 AddLandObject(new_land); 1347 AddLandObject(new_land);
1348 new_land.SendLandUpdateToAvatarsOverMe();
1375 } 1349 }
1376 1350
1377 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient) 1351 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient)
@@ -1649,6 +1623,168 @@ namespace OpenSim.Region.CoreModules.World.Land
1649 1623
1650 UpdateLandObject(localID, land.LandData); 1624 UpdateLandObject(localID, land.LandData);
1651 } 1625 }
1626
1627 public void ClientOnParcelGodMark(IClientAPI client, UUID god, int landID)
1628 {
1629 ILandObject land = null;
1630 List<ILandObject> Land = ((Scene)client.Scene).LandChannel.AllParcels();
1631 foreach (ILandObject landObject in Land)
1632 {
1633 if (landObject.LandData.LocalID == landID)
1634 {
1635 land = landObject;
1636 }
1637 }
1638 land.DeedToGroup(DefaultGodParcelGroup);
1639 land.LandData.Name = DefaultGodParcelName;
1640 land.SendLandUpdateToAvatarsOverMe();
1641 }
1642
1643 private void ClientOnSimWideDeletes(IClientAPI client, UUID agentID, int flags, UUID targetID)
1644 {
1645 ScenePresence SP;
1646 ((Scene)client.Scene).TryGetScenePresence(client.AgentId, out SP);
1647 List<SceneObjectGroup> returns = new List<SceneObjectGroup>();
1648 if (SP.UserLevel != 0)
1649 {
1650 if (flags == 0) //All parcels, scripted or not
1651 {
1652 ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e)
1653 {
1654 if (e.OwnerID == targetID)
1655 {
1656 returns.Add(e);
1657 }
1658 }
1659 );
1660 }
1661 if (flags == 4) //All parcels, scripted object
1662 {
1663 ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e)
1664 {
1665 if (e.OwnerID == targetID)
1666 {
1667 if (e.scriptScore >= 0.01)
1668 {
1669 returns.Add(e);
1670 }
1671 }
1672 }
1673 );
1674 }
1675 if (flags == 4) //not target parcel, scripted object
1676 {
1677 ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e)
1678 {
1679 if (e.OwnerID == targetID)
1680 {
1681 ILandObject landobject = ((Scene)client.Scene).LandChannel.GetLandObject(e.AbsolutePosition.X, e.AbsolutePosition.Y);
1682 if (landobject.LandData.OwnerID != e.OwnerID)
1683 {
1684 if (e.scriptScore >= 0.01)
1685 {
1686 returns.Add(e);
1687 }
1688 }
1689 }
1690 }
1691 );
1692 }
1693 foreach (SceneObjectGroup ol in returns)
1694 {
1695 ReturnObject(ol, client);
1696 }
1697 }
1698 }
1699 public void ReturnObject(SceneObjectGroup obj, IClientAPI client)
1700 {
1701 SceneObjectGroup[] objs = new SceneObjectGroup[1];
1702 objs[0] = obj;
1703 ((Scene)client.Scene).returnObjects(objs, client.AgentId);
1704 }
1705
1706 Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>();
1707
1708 public void ClientOnParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
1709 {
1710 ScenePresence targetAvatar = null;
1711 ((Scene)client.Scene).TryGetScenePresence(target, out targetAvatar);
1712 ScenePresence parcelManager = null;
1713 ((Scene)client.Scene).TryGetScenePresence(client.AgentId, out parcelManager);
1714 System.Threading.Timer Timer;
1715
1716 if (targetAvatar.UserLevel == 0)
1717 {
1718 ILandObject land = ((Scene)client.Scene).LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y);
1719 if (!((Scene)client.Scene).Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze))
1720 return;
1721 if (flags == 0)
1722 {
1723 targetAvatar.AllowMovement = false;
1724 targetAvatar.ControllingClient.SendAlertMessage(parcelManager.Firstname + " " + parcelManager.Lastname + " has frozen you for 30 seconds. You cannot move or interact with the world.");
1725 parcelManager.ControllingClient.SendAlertMessage("Avatar Frozen.");
1726 System.Threading.TimerCallback timeCB = new System.Threading.TimerCallback(OnEndParcelFrozen);
1727 Timer = new System.Threading.Timer(timeCB, targetAvatar, 30000, 0);
1728 Timers.Add(targetAvatar.UUID, Timer);
1729 }
1730 else
1731 {
1732 targetAvatar.AllowMovement = true;
1733 targetAvatar.ControllingClient.SendAlertMessage(parcelManager.Firstname + " " + parcelManager.Lastname + " has unfrozen you.");
1734 parcelManager.ControllingClient.SendAlertMessage("Avatar Unfrozen.");
1735 Timers.TryGetValue(targetAvatar.UUID, out Timer);
1736 Timers.Remove(targetAvatar.UUID);
1737 Timer.Dispose();
1738 }
1739 }
1740 }
1741 private void OnEndParcelFrozen(object avatar)
1742 {
1743 ScenePresence targetAvatar = (ScenePresence)avatar;
1744 targetAvatar.AllowMovement = true;
1745 System.Threading.Timer Timer;
1746 Timers.TryGetValue(targetAvatar.UUID, out Timer);
1747 Timers.Remove(targetAvatar.UUID);
1748 targetAvatar.ControllingClient.SendAgentAlertMessage("The freeze has worn off; you may go about your business.", false);
1749 }
1750
1751
1752 public void ClientOnParcelEjectUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
1753 {
1754 ScenePresence targetAvatar = null;
1755 ScenePresence parcelManager = null;
1756
1757 // Must have presences
1758 if (!m_scene.TryGetScenePresence(target, out targetAvatar) ||
1759 !m_scene.TryGetScenePresence(client.AgentId, out parcelManager))
1760 return;
1761
1762 // Cannot eject estate managers or gods
1763 if (m_scene.Permissions.IsAdministrator(target))
1764 return;
1765
1766 // Check if you even have permission to do this
1767 ILandObject land = m_scene.LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y);
1768 if (!m_scene.Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze) &&
1769 !m_scene.Permissions.IsAdministrator(client.AgentId))
1770 return;
1771
1772 Vector3 pos = m_scene.GetNearestAllowedPosition(targetAvatar, land);
1773
1774 targetAvatar.TeleportWithMomentum(pos);
1775 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1776 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected.");
1777
1778 if ((flags & 1) != 0) // Ban TODO: Remove magic number
1779 {
1780 LandAccessEntry entry = new LandAccessEntry();
1781 entry.AgentID = targetAvatar.UUID;
1782 entry.Flags = AccessList.Ban;
1783 entry.Expires = 0; // Perm
1784
1785 land.LandData.ParcelAccessList.Add(entry);
1786 }
1787 }
1652 1788
1653 protected void InstallInterfaces() 1789 protected void InstallInterfaces()
1654 { 1790 {
@@ -1711,5 +1847,27 @@ namespace OpenSim.Region.CoreModules.World.Land
1711 1847
1712 MainConsole.Instance.Output(report.ToString()); 1848 MainConsole.Instance.Output(report.ToString());
1713 } 1849 }
1850
1851 public void EnforceBans(ILandObject land, ScenePresence avatar)
1852 {
1853 if (avatar.AbsolutePosition.Z > LandChannel.BAN_LINE_SAFETY_HIEGHT)
1854 return;
1855
1856 if (land.IsEitherBannedOrRestricted(avatar.UUID))
1857 {
1858 if (land.ContainsPoint(Convert.ToInt32(avatar.lastKnownAllowedPosition.X), Convert.ToInt32(avatar.lastKnownAllowedPosition.Y)))
1859 {
1860 Vector3? pos = m_scene.GetNearestAllowedPosition(avatar);
1861 if (pos == null)
1862 m_scene.TeleportClientHome(avatar.UUID, avatar.ControllingClient);
1863 else
1864 ForceAvatarToPosition(avatar, (Vector3)pos);
1865 }
1866 else
1867 {
1868 ForceAvatarToPosition(avatar, avatar.lastKnownAllowedPosition);
1869 }
1870 }
1871 }
1714 } 1872 }
1715} 1873}
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index 3b4336f..debf6d2 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,6 +434,37 @@ 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 ExpireAccessList(); 470 ExpireAccessList();
@@ -468,9 +517,13 @@ namespace OpenSim.Region.CoreModules.World.Land
468 return false; 517 return false;
469 }) == -1) 518 }) == -1)
470 { 519 {
471 return true; 520 if (!HasGroupAccess(avatar))
521 {
522 return true;
523 }
472 } 524 }
473 } 525 }
526
474 return false; 527 return false;
475 } 528 }
476 529
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 d31d380..57db4d6 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;
@@ -797,6 +801,26 @@ namespace OpenSim.Region.Framework.Scenes
797 } 801 }
798 } 802 }
799 } 803 }
804 public void TriggerTerrainUpdate()
805 {
806 OnTerrainUpdateDelegate handlerTerrainUpdate = OnTerrainUpdate;
807 if (handlerTerrainUpdate != null)
808 {
809 foreach (OnTerrainUpdateDelegate d in handlerTerrainUpdate.GetInvocationList())
810 {
811 try
812 {
813 d();
814 }
815 catch (Exception e)
816 {
817 m_log.ErrorFormat(
818 "[EVENT MANAGER]: Delegate for TriggerTerrainUpdate failed - continuing. {0} {1}",
819 e.Message, e.StackTrace);
820 }
821 }
822 }
823 }
800 824
801 public void TriggerTerrainTick() 825 public void TriggerTerrainTick()
802 { 826 {
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 186e01c..03ddbc5 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();
@@ -1390,12 +1436,16 @@ namespace OpenSim.Region.Framework.Scenes
1390 maintc = Util.EnvironmentTickCountSubtract(maintc); 1436 maintc = Util.EnvironmentTickCountSubtract(maintc);
1391 maintc = (int)(MinFrameTime * 1000) - maintc; 1437 maintc = (int)(MinFrameTime * 1000) - maintc;
1392 1438
1439
1440 m_lastUpdate = Util.EnvironmentTickCount();
1441 m_firstHeartbeat = false;
1442
1393 if (maintc > 0) 1443 if (maintc > 0)
1394 Thread.Sleep(maintc); 1444 Thread.Sleep(maintc);
1395 1445
1396 // Tell the watchdog that this thread is still alive 1446 // Tell the watchdog that this thread is still alive
1397 Watchdog.UpdateThread(); 1447 Watchdog.UpdateThread();
1398 } 1448 }
1399 1449
1400 public void AddGroupTarget(SceneObjectGroup grp) 1450 public void AddGroupTarget(SceneObjectGroup grp)
1401 { 1451 {
@@ -1411,9 +1461,9 @@ namespace OpenSim.Region.Framework.Scenes
1411 1461
1412 private void CheckAtTargets() 1462 private void CheckAtTargets()
1413 { 1463 {
1414 Dictionary<UUID, SceneObjectGroup>.ValueCollection objs; 1464 List<SceneObjectGroup> objs = new List<SceneObjectGroup>();
1415 lock (m_groupsWithTargets) 1465 lock (m_groupsWithTargets)
1416 objs = m_groupsWithTargets.Values; 1466 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values);
1417 1467
1418 foreach (SceneObjectGroup entry in objs) 1468 foreach (SceneObjectGroup entry in objs)
1419 entry.checkAtTargets(); 1469 entry.checkAtTargets();
@@ -1495,7 +1545,7 @@ namespace OpenSim.Region.Framework.Scenes
1495 msg.fromAgentName = "Server"; 1545 msg.fromAgentName = "Server";
1496 msg.dialog = (byte)19; // Object msg 1546 msg.dialog = (byte)19; // Object msg
1497 msg.fromGroup = false; 1547 msg.fromGroup = false;
1498 msg.offline = (byte)0; 1548 msg.offline = (byte)1;
1499 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID; 1549 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID;
1500 msg.Position = Vector3.Zero; 1550 msg.Position = Vector3.Zero;
1501 msg.RegionID = RegionInfo.RegionID.Guid; 1551 msg.RegionID = RegionInfo.RegionID.Guid;
@@ -1726,14 +1776,24 @@ namespace OpenSim.Region.Framework.Scenes
1726 /// <returns></returns> 1776 /// <returns></returns>
1727 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 1777 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
1728 { 1778 {
1779
1780 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
1781 Vector3 wpos = Vector3.Zero;
1782 // Check for water surface intersection from above
1783 if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) )
1784 {
1785 float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
1786 wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
1787 wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y));
1788 wpos.Z = wheight;
1789 }
1790
1729 Vector3 pos = Vector3.Zero; 1791 Vector3 pos = Vector3.Zero;
1730 if (RayEndIsIntersection == (byte)1) 1792 if (RayEndIsIntersection == (byte)1)
1731 { 1793 {
1732 pos = RayEnd; 1794 pos = RayEnd;
1733 return pos;
1734 } 1795 }
1735 1796 else if (RayTargetID != UUID.Zero)
1736 if (RayTargetID != UUID.Zero)
1737 { 1797 {
1738 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 1798 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
1739 1799
@@ -1755,7 +1815,7 @@ namespace OpenSim.Region.Framework.Scenes
1755 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 1815 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
1756 1816
1757 // Un-comment out the following line to Get Raytrace results printed to the console. 1817 // Un-comment out the following line to Get Raytrace results printed to the console.
1758 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 1818 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1759 float ScaleOffset = 0.5f; 1819 float ScaleOffset = 0.5f;
1760 1820
1761 // If we hit something 1821 // If we hit something
@@ -1778,13 +1838,10 @@ namespace OpenSim.Region.Framework.Scenes
1778 //pos.Z -= 0.25F; 1838 //pos.Z -= 0.25F;
1779 1839
1780 } 1840 }
1781
1782 return pos;
1783 } 1841 }
1784 else 1842 else
1785 { 1843 {
1786 // We don't have a target here, so we're going to raytrace all the objects in the scene. 1844 // We don't have a target here, so we're going to raytrace all the objects in the scene.
1787
1788 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 1845 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
1789 1846
1790 // Un-comment the following line to print the raytrace results to the console. 1847 // Un-comment the following line to print the raytrace results to the console.
@@ -1793,13 +1850,12 @@ namespace OpenSim.Region.Framework.Scenes
1793 if (ei.HitTF) 1850 if (ei.HitTF)
1794 { 1851 {
1795 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 1852 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1796 } else 1853 }
1854 else
1797 { 1855 {
1798 // fall back to our stupid functionality 1856 // fall back to our stupid functionality
1799 pos = RayEnd; 1857 pos = RayEnd;
1800 } 1858 }
1801
1802 return pos;
1803 } 1859 }
1804 } 1860 }
1805 else 1861 else
@@ -1810,8 +1866,12 @@ namespace OpenSim.Region.Framework.Scenes
1810 //increase height so its above the ground. 1866 //increase height so its above the ground.
1811 //should be getting the normal of the ground at the rez point and using that? 1867 //should be getting the normal of the ground at the rez point and using that?
1812 pos.Z += scale.Z / 2f; 1868 pos.Z += scale.Z / 2f;
1813 return pos; 1869// return pos;
1814 } 1870 }
1871
1872 // check against posible water intercept
1873 if (wpos.Z > pos.Z) pos = wpos;
1874 return pos;
1815 } 1875 }
1816 1876
1817 1877
@@ -1895,7 +1955,10 @@ namespace OpenSim.Region.Framework.Scenes
1895 public bool AddRestoredSceneObject( 1955 public bool AddRestoredSceneObject(
1896 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 1956 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
1897 { 1957 {
1898 return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 1958 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates);
1959 if (result)
1960 sceneObject.IsDeleted = false;
1961 return result;
1899 } 1962 }
1900 1963
1901 /// <summary> 1964 /// <summary>
@@ -1987,6 +2050,15 @@ namespace OpenSim.Region.Framework.Scenes
1987 /// </summary> 2050 /// </summary>
1988 public void DeleteAllSceneObjects() 2051 public void DeleteAllSceneObjects()
1989 { 2052 {
2053 DeleteAllSceneObjects(false);
2054 }
2055
2056 /// <summary>
2057 /// Delete every object from the scene. This does not include attachments worn by avatars.
2058 /// </summary>
2059 public void DeleteAllSceneObjects(bool exceptNoCopy)
2060 {
2061 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
1990 lock (Entities) 2062 lock (Entities)
1991 { 2063 {
1992 EntityBase[] entities = Entities.GetEntities(); 2064 EntityBase[] entities = Entities.GetEntities();
@@ -1995,11 +2067,24 @@ namespace OpenSim.Region.Framework.Scenes
1995 if (e is SceneObjectGroup) 2067 if (e is SceneObjectGroup)
1996 { 2068 {
1997 SceneObjectGroup sog = (SceneObjectGroup)e; 2069 SceneObjectGroup sog = (SceneObjectGroup)e;
1998 if (!sog.IsAttachment) 2070 if (sog != null && !sog.IsAttachment)
1999 DeleteSceneObject((SceneObjectGroup)e, false); 2071 {
2072 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2073 {
2074 DeleteSceneObject((SceneObjectGroup)e, false);
2075 }
2076 else
2077 {
2078 toReturn.Add((SceneObjectGroup)e);
2079 }
2080 }
2000 } 2081 }
2001 } 2082 }
2002 } 2083 }
2084 if (toReturn.Count > 0)
2085 {
2086 returnObjects(toReturn.ToArray(), UUID.Zero);
2087 }
2003 } 2088 }
2004 2089
2005 /// <summary> 2090 /// <summary>
@@ -2047,6 +2132,8 @@ namespace OpenSim.Region.Framework.Scenes
2047 } 2132 }
2048 2133
2049 group.DeleteGroupFromScene(silent); 2134 group.DeleteGroupFromScene(silent);
2135 if (!silent)
2136 SendKillObject(new List<uint>() { group.LocalId });
2050 2137
2051// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2138// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2052 } 2139 }
@@ -2401,10 +2488,17 @@ namespace OpenSim.Region.Framework.Scenes
2401 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2488 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2402 public bool AddSceneObject(SceneObjectGroup sceneObject) 2489 public bool AddSceneObject(SceneObjectGroup sceneObject)
2403 { 2490 {
2491 if (sceneObject.OwnerID == UUID.Zero)
2492 {
2493 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2494 return false;
2495 }
2496
2404 // If the user is banned, we won't let any of their objects 2497 // If the user is banned, we won't let any of their objects
2405 // enter. Period. 2498 // enter. Period.
2406 // 2499 //
2407 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID)) 2500 int flags = GetUserFlags(sceneObject.OwnerID);
2501 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2408 { 2502 {
2409 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID); 2503 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID);
2410 2504
@@ -2450,12 +2544,23 @@ namespace OpenSim.Region.Framework.Scenes
2450 } 2544 }
2451 else 2545 else
2452 { 2546 {
2547 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2453 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2548 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2454 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 2549 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2455 } 2550 }
2551 if (sceneObject.OwnerID == UUID.Zero)
2552 {
2553 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
2554 return false;
2555 }
2456 } 2556 }
2457 else 2557 else
2458 { 2558 {
2559 if (sceneObject.OwnerID == UUID.Zero)
2560 {
2561 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
2562 return false;
2563 }
2459 AddRestoredSceneObject(sceneObject, true, false); 2564 AddRestoredSceneObject(sceneObject, true, false);
2460 2565
2461 if (!Permissions.CanObjectEntry(sceneObject.UUID, 2566 if (!Permissions.CanObjectEntry(sceneObject.UUID,
@@ -2484,6 +2589,24 @@ namespace OpenSim.Region.Framework.Scenes
2484 return 2; // StateSource.PrimCrossing 2589 return 2; // StateSource.PrimCrossing
2485 } 2590 }
2486 2591
2592 public int GetUserFlags(UUID user)
2593 {
2594 //Unfortunately the SP approach means that the value is cached until region is restarted
2595 /*
2596 ScenePresence sp;
2597 if (TryGetScenePresence(user, out sp))
2598 {
2599 return sp.UserFlags;
2600 }
2601 else
2602 {
2603 */
2604 UserAccount uac = UserAccountService.GetUserAccount(RegionInfo.ScopeID, user);
2605 if (uac == null)
2606 return 0;
2607 return uac.UserFlags;
2608 //}
2609 }
2487 #endregion 2610 #endregion
2488 2611
2489 #region Add/Remove Avatar Methods 2612 #region Add/Remove Avatar Methods
@@ -2498,6 +2621,7 @@ namespace OpenSim.Region.Framework.Scenes
2498 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 2621 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2499 2622
2500 CheckHeartbeat(); 2623 CheckHeartbeat();
2624 ScenePresence presence;
2501 2625
2502 ScenePresence sp = GetScenePresence(client.AgentId); 2626 ScenePresence sp = GetScenePresence(client.AgentId);
2503 2627
@@ -2546,7 +2670,13 @@ namespace OpenSim.Region.Framework.Scenes
2546 2670
2547 EventManager.TriggerOnNewClient(client); 2671 EventManager.TriggerOnNewClient(client);
2548 if (vialogin) 2672 if (vialogin)
2673 {
2549 EventManager.TriggerOnClientLogin(client); 2674 EventManager.TriggerOnClientLogin(client);
2675 // Send initial parcel data
2676 Vector3 pos = sp.AbsolutePosition;
2677 ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y);
2678 land.SendLandUpdateToClient(client);
2679 }
2550 2680
2551 return sp; 2681 return sp;
2552 } 2682 }
@@ -2636,19 +2766,12 @@ namespace OpenSim.Region.Framework.Scenes
2636 // and the scene presence and the client, if they exist 2766 // and the scene presence and the client, if they exist
2637 try 2767 try
2638 { 2768 {
2639 // We need to wait for the client to make UDP contact first. 2769 ScenePresence sp = GetScenePresence(agentID);
2640 // It's the UDP contact that creates the scene presence 2770 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2641 ScenePresence sp = WaitGetScenePresence(agentID); 2771
2642 if (sp != null) 2772 if (sp != null)
2643 {
2644 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2645
2646 sp.ControllingClient.Close(); 2773 sp.ControllingClient.Close();
2647 } 2774
2648 else
2649 {
2650 m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID);
2651 }
2652 // BANG! SLASH! 2775 // BANG! SLASH!
2653 m_authenticateHandler.RemoveCircuit(agentID); 2776 m_authenticateHandler.RemoveCircuit(agentID);
2654 2777
@@ -2749,6 +2872,7 @@ namespace OpenSim.Region.Framework.Scenes
2749 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory; 2872 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory;
2750 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 2873 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
2751 client.OnCopyInventoryItem += CopyInventoryItem; 2874 client.OnCopyInventoryItem += CopyInventoryItem;
2875 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
2752 client.OnMoveInventoryItem += MoveInventoryItem; 2876 client.OnMoveInventoryItem += MoveInventoryItem;
2753 client.OnRemoveInventoryItem += RemoveInventoryItem; 2877 client.OnRemoveInventoryItem += RemoveInventoryItem;
2754 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 2878 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -2924,15 +3048,16 @@ namespace OpenSim.Region.Framework.Scenes
2924 /// </summary> 3048 /// </summary>
2925 /// <param name="agentId">The avatar's Unique ID</param> 3049 /// <param name="agentId">The avatar's Unique ID</param>
2926 /// <param name="client">The IClientAPI for the client</param> 3050 /// <param name="client">The IClientAPI for the client</param>
2927 public virtual void TeleportClientHome(UUID agentId, IClientAPI client) 3051 public virtual bool TeleportClientHome(UUID agentId, IClientAPI client)
2928 { 3052 {
2929 if (m_teleportModule != null) 3053 if (m_teleportModule != null)
2930 m_teleportModule.TeleportHome(agentId, client); 3054 return m_teleportModule.TeleportHome(agentId, client);
2931 else 3055 else
2932 { 3056 {
2933 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); 3057 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active");
2934 client.SendTeleportFailed("Unable to perform teleports on this simulator."); 3058 client.SendTeleportFailed("Unable to perform teleports on this simulator.");
2935 } 3059 }
3060 return false;
2936 } 3061 }
2937 3062
2938 /// <summary> 3063 /// <summary>
@@ -3042,6 +3167,16 @@ namespace OpenSim.Region.Framework.Scenes
3042 /// <param name="flags"></param> 3167 /// <param name="flags"></param>
3043 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) 3168 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
3044 { 3169 {
3170 //Add half the avatar's height so that the user doesn't fall through prims
3171 ScenePresence presence;
3172 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3173 {
3174 if (presence.Appearance != null)
3175 {
3176 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3177 }
3178 }
3179
3045 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) 3180 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
3046 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. 3181 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
3047 m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); 3182 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
@@ -3110,8 +3245,9 @@ namespace OpenSim.Region.Framework.Scenes
3110 regions.Remove(RegionInfo.RegionHandle); 3245 regions.Remove(RegionInfo.RegionHandle);
3111 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3246 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3112 } 3247 }
3113 3248 m_log.Debug("[Scene] Beginning ClientClosed");
3114 m_eventManager.TriggerClientClosed(agentID, this); 3249 m_eventManager.TriggerClientClosed(agentID, this);
3250 m_log.Debug("[Scene] Finished ClientClosed");
3115 } 3251 }
3116 catch (NullReferenceException) 3252 catch (NullReferenceException)
3117 { 3253 {
@@ -3173,9 +3309,10 @@ namespace OpenSim.Region.Framework.Scenes
3173 { 3309 {
3174 m_log.ErrorFormat("[SCENE] Scene.cs:RemoveClient exception {0}{1}", e.Message, e.StackTrace); 3310 m_log.ErrorFormat("[SCENE] Scene.cs:RemoveClient exception {0}{1}", e.Message, e.StackTrace);
3175 } 3311 }
3176 3312 m_log.Debug("[Scene] Done. Firing RemoveCircuit");
3177 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3313 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3178// CleanDroppedAttachments(); 3314// CleanDroppedAttachments();
3315 m_log.Debug("[Scene] The avatar has left the building");
3179 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 3316 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
3180 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); 3317 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
3181 } 3318 }
@@ -3294,13 +3431,16 @@ namespace OpenSim.Region.Framework.Scenes
3294 sp = null; 3431 sp = null;
3295 } 3432 }
3296 3433
3297 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3298 3434
3299 //On login test land permisions 3435 //On login test land permisions
3300 if (vialogin) 3436 if (vialogin)
3301 { 3437 {
3302 if (land != null && !TestLandRestrictions(agent, land, out reason)) 3438 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3439 if (cache != null)
3440 cache.Remove(agent.firstname + " " + agent.lastname);
3441 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3303 { 3442 {
3443 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3304 return false; 3444 return false;
3305 } 3445 }
3306 } 3446 }
@@ -3324,8 +3464,13 @@ namespace OpenSim.Region.Framework.Scenes
3324 3464
3325 try 3465 try
3326 { 3466 {
3327 if (!AuthorizeUser(agent, out reason)) 3467 // Always check estate if this is a login. Always
3328 return false; 3468 // check if banned regions are to be blacked out.
3469 if (vialogin || (!m_seeIntoBannedRegion))
3470 {
3471 if (!AuthorizeUser(agent, out reason))
3472 return false;
3473 }
3329 } 3474 }
3330 catch (Exception e) 3475 catch (Exception e)
3331 { 3476 {
@@ -3428,6 +3573,8 @@ namespace OpenSim.Region.Framework.Scenes
3428 } 3573 }
3429 } 3574 }
3430 // Honor parcel landing type and position. 3575 // Honor parcel landing type and position.
3576 /*
3577 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3431 if (land != null) 3578 if (land != null)
3432 { 3579 {
3433 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3580 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3435,26 +3582,34 @@ namespace OpenSim.Region.Framework.Scenes
3435 agent.startpos = land.LandData.UserLocation; 3582 agent.startpos = land.LandData.UserLocation;
3436 } 3583 }
3437 } 3584 }
3585 */// This is now handled properly in ScenePresence.MakeRootAgent
3438 } 3586 }
3439 3587
3440 return true; 3588 return true;
3441 } 3589 }
3442 3590
3443 private bool TestLandRestrictions(AgentCircuitData agent, ILandObject land, out string reason) 3591 public bool TestLandRestrictions(UUID agentID, out string reason, ref float posX, ref float posY)
3444 { 3592 {
3445 3593 reason = String.Empty;
3446 bool banned = land.IsBannedFromLand(agent.AgentID); 3594 if (Permissions.IsGod(agentID))
3447 bool restricted = land.IsRestrictedFromLand(agent.AgentID); 3595 return true;
3596
3597 ILandObject land = LandChannel.GetLandObject(posX, posY);
3598 if (land == null)
3599 return false;
3600
3601 bool banned = land.IsBannedFromLand(agentID);
3602 bool restricted = land.IsRestrictedFromLand(agentID);
3448 3603
3449 if (banned || restricted) 3604 if (banned || restricted)
3450 { 3605 {
3451 ILandObject nearestParcel = GetNearestAllowedParcel(agent.AgentID, agent.startpos.X, agent.startpos.Y); 3606 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY);
3452 if (nearestParcel != null) 3607 if (nearestParcel != null)
3453 { 3608 {
3454 //Move agent to nearest allowed 3609 //Move agent to nearest allowed
3455 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); 3610 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel);
3456 agent.startpos.X = newPosition.X; 3611 posX = newPosition.X;
3457 agent.startpos.Y = newPosition.Y; 3612 posY = newPosition.Y;
3458 } 3613 }
3459 else 3614 else
3460 { 3615 {
@@ -3516,7 +3671,7 @@ namespace OpenSim.Region.Framework.Scenes
3516 3671
3517 if (!m_strictAccessControl) return true; 3672 if (!m_strictAccessControl) return true;
3518 if (Permissions.IsGod(agent.AgentID)) return true; 3673 if (Permissions.IsGod(agent.AgentID)) return true;
3519 3674
3520 if (AuthorizationService != null) 3675 if (AuthorizationService != null)
3521 { 3676 {
3522 if (!AuthorizationService.IsAuthorizedForRegion( 3677 if (!AuthorizationService.IsAuthorizedForRegion(
@@ -3524,14 +3679,14 @@ namespace OpenSim.Region.Framework.Scenes
3524 { 3679 {
3525 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region", 3680 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region",
3526 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3681 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
3527 3682
3528 return false; 3683 return false;
3529 } 3684 }
3530 } 3685 }
3531 3686
3532 if (m_regInfo.EstateSettings != null) 3687 if (m_regInfo.EstateSettings != null)
3533 { 3688 {
3534 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID)) 3689 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID,0))
3535 { 3690 {
3536 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 3691 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
3537 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3692 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
@@ -3723,6 +3878,13 @@ namespace OpenSim.Region.Framework.Scenes
3723 3878
3724 // We have to wait until the viewer contacts this region after receiving EAC. 3879 // We have to wait until the viewer contacts this region after receiving EAC.
3725 // That calls AddNewClient, which finally creates the ScenePresence 3880 // That calls AddNewClient, which finally creates the ScenePresence
3881 int flags = GetUserFlags(cAgentData.AgentID);
3882 if (m_regInfo.EstateSettings.IsBanned(cAgentData.AgentID, flags))
3883 {
3884 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
3885 return false;
3886 }
3887
3726 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 3888 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
3727 if (nearestParcel == null) 3889 if (nearestParcel == null)
3728 { 3890 {
@@ -3804,12 +3966,22 @@ namespace OpenSim.Region.Framework.Scenes
3804 return false; 3966 return false;
3805 } 3967 }
3806 3968
3969 public bool IncomingCloseAgent(UUID agentID)
3970 {
3971 return IncomingCloseAgent(agentID, false);
3972 }
3973
3974 public bool IncomingCloseChildAgent(UUID agentID)
3975 {
3976 return IncomingCloseAgent(agentID, true);
3977 }
3978
3807 /// <summary> 3979 /// <summary>
3808 /// Tell a single agent to disconnect from the region. 3980 /// Tell a single agent to disconnect from the region.
3809 /// </summary> 3981 /// </summary>
3810 /// <param name="regionHandle"></param>
3811 /// <param name="agentID"></param> 3982 /// <param name="agentID"></param>
3812 public bool IncomingCloseAgent(UUID agentID) 3983 /// <param name="childOnly"></param>
3984 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
3813 { 3985 {
3814 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 3986 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
3815 3987
@@ -3821,7 +3993,7 @@ namespace OpenSim.Region.Framework.Scenes
3821 { 3993 {
3822 m_sceneGraph.removeUserCount(false); 3994 m_sceneGraph.removeUserCount(false);
3823 } 3995 }
3824 else 3996 else if (!childOnly)
3825 { 3997 {
3826 m_sceneGraph.removeUserCount(true); 3998 m_sceneGraph.removeUserCount(true);
3827 } 3999 }
@@ -3837,9 +4009,12 @@ namespace OpenSim.Region.Framework.Scenes
3837 } 4009 }
3838 else 4010 else
3839 presence.ControllingClient.SendShutdownConnectionNotice(); 4011 presence.ControllingClient.SendShutdownConnectionNotice();
4012 presence.ControllingClient.Close(false);
4013 }
4014 else if (!childOnly)
4015 {
4016 presence.ControllingClient.Close(true);
3840 } 4017 }
3841
3842 presence.ControllingClient.Close();
3843 return true; 4018 return true;
3844 } 4019 }
3845 4020
@@ -4432,34 +4607,78 @@ namespace OpenSim.Region.Framework.Scenes
4432 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID); 4607 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID);
4433 } 4608 }
4434 4609
4435 public int GetHealth() 4610 public int GetHealth(out int flags, out string message)
4436 { 4611 {
4437 // Returns: 4612 // Returns:
4438 // 1 = sim is up and accepting http requests. The heartbeat has 4613 // 1 = sim is up and accepting http requests. The heartbeat has
4439 // stopped and the sim is probably locked up, but a remote 4614 // stopped and the sim is probably locked up, but a remote
4440 // admin restart may succeed 4615 // admin restart may succeed
4441 // 4616 //
4442 // 2 = Sim is up and the heartbeat is running. The sim is likely 4617 // 2 = Sim is up and the heartbeat is running. The sim is likely
4443 // usable for people within and logins _may_ work 4618 // usable for people within
4619 //
4620 // 3 = Sim is up and one packet thread is running. Sim is
4621 // unstable and will not accept new logins
4622 //
4623 // 4 = Sim is up and both packet threads are running. Sim is
4624 // likely usable
4444 // 4625 //
4445 // 3 = We have seen a new user enter within the past 4 minutes 4626 // 5 = We have seen a new user enter within the past 4 minutes
4446 // which can be seen as positive confirmation of sim health 4627 // which can be seen as positive confirmation of sim health
4447 // 4628 //
4629
4630 flags = 0;
4631 message = String.Empty;
4632
4633 CheckHeartbeat();
4634
4635 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
4636 {
4637 // We're still starting
4638 // 0 means "in startup", it can't happen another way, since
4639 // to get here, we must be able to accept http connections
4640 return 0;
4641 }
4642
4448 int health=1; // Start at 1, means we're up 4643 int health=1; // Start at 1, means we're up
4449 4644
4450 if ((Util.EnvironmentTickCountSubtract(m_lastUpdate)) < 1000) 4645 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) < 1000)
4646 {
4647 health+=1;
4648 flags |= 1;
4649 }
4650
4651 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 1000)
4652 {
4451 health+=1; 4653 health+=1;
4654 flags |= 2;
4655 }
4656
4657 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 1000)
4658 {
4659 health+=1;
4660 flags |= 4;
4661 }
4452 else 4662 else
4663 {
4664int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
4665System.Diagnostics.Process proc = new System.Diagnostics.Process();
4666proc.EnableRaisingEvents=false;
4667proc.StartInfo.FileName = "/bin/kill";
4668proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
4669proc.Start();
4670proc.WaitForExit();
4671Thread.Sleep(1000);
4672Environment.Exit(1);
4673 }
4674
4675 if (flags != 7)
4453 return health; 4676 return health;
4454 4677
4455 // A login in the last 4 mins? We can't be doing too badly 4678 // A login in the last 4 mins? We can't be doing too badly
4456 // 4679 //
4457 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 4680 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
4458 health++; 4681 health++;
4459 else
4460 return health;
4461
4462 CheckHeartbeat();
4463 4682
4464 return health; 4683 return health;
4465 } 4684 }
@@ -4652,7 +4871,7 @@ namespace OpenSim.Region.Framework.Scenes
4652 if (m_firstHeartbeat) 4871 if (m_firstHeartbeat)
4653 return; 4872 return;
4654 4873
4655 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 2000) 4874 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 5000)
4656 StartTimer(); 4875 StartTimer();
4657 } 4876 }
4658 4877
@@ -4666,9 +4885,14 @@ namespace OpenSim.Region.Framework.Scenes
4666 get { return m_allowScriptCrossings; } 4885 get { return m_allowScriptCrossings; }
4667 } 4886 }
4668 4887
4669 public Vector3? GetNearestAllowedPosition(ScenePresence avatar) 4888 public Vector3 GetNearestAllowedPosition(ScenePresence avatar)
4889 {
4890 return GetNearestAllowedPosition(avatar, null);
4891 }
4892
4893 public Vector3 GetNearestAllowedPosition(ScenePresence avatar, ILandObject excludeParcel)
4670 { 4894 {
4671 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); 4895 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, excludeParcel);
4672 4896
4673 if (nearestParcel != null) 4897 if (nearestParcel != null)
4674 { 4898 {
@@ -4727,13 +4951,18 @@ namespace OpenSim.Region.Framework.Scenes
4727 4951
4728 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y) 4952 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y)
4729 { 4953 {
4954 return GetNearestAllowedParcel(avatarId, x, y, null);
4955 }
4956
4957 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y, ILandObject excludeParcel)
4958 {
4730 List<ILandObject> all = AllParcels(); 4959 List<ILandObject> all = AllParcels();
4731 float minParcelDistance = float.MaxValue; 4960 float minParcelDistance = float.MaxValue;
4732 ILandObject nearestParcel = null; 4961 ILandObject nearestParcel = null;
4733 4962
4734 foreach (var parcel in all) 4963 foreach (var parcel in all)
4735 { 4964 {
4736 if (!parcel.IsEitherBannedOrRestricted(avatarId)) 4965 if (!parcel.IsEitherBannedOrRestricted(avatarId) && parcel != excludeParcel)
4737 { 4966 {
4738 float parcelDistance = GetParcelDistancefromPoint(parcel, x, y); 4967 float parcelDistance = GetParcelDistancefromPoint(parcel, x, y);
4739 if (parcelDistance < minParcelDistance) 4968 if (parcelDistance < minParcelDistance)
@@ -4975,7 +5204,55 @@ namespace OpenSim.Region.Framework.Scenes
4975 mapModule.GenerateMaptile(); 5204 mapModule.GenerateMaptile();
4976 } 5205 }
4977 5206
4978 private void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e) 5207// public void CleanDroppedAttachments()
5208// {
5209// List<SceneObjectGroup> objectsToDelete =
5210// new List<SceneObjectGroup>();
5211//
5212// lock (m_cleaningAttachments)
5213// {
5214// ForEachSOG(delegate (SceneObjectGroup grp)
5215// {
5216// if (grp.RootPart.Shape.PCode == 0 && grp.RootPart.Shape.State != 0 && (!objectsToDelete.Contains(grp)))
5217// {
5218// UUID agentID = grp.OwnerID;
5219// if (agentID == UUID.Zero)
5220// {
5221// objectsToDelete.Add(grp);
5222// return;
5223// }
5224//
5225// ScenePresence sp = GetScenePresence(agentID);
5226// if (sp == null)
5227// {
5228// objectsToDelete.Add(grp);
5229// return;
5230// }
5231// }
5232// });
5233// }
5234//
5235// foreach (SceneObjectGroup grp in objectsToDelete)
5236// {
5237// m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
5238// DeleteSceneObject(grp, true);
5239// }
5240// }
5241
5242 public void ThreadAlive(int threadCode)
5243 {
5244 switch(threadCode)
5245 {
5246 case 1: // Incoming
5247 m_lastIncoming = Util.EnvironmentTickCount();
5248 break;
5249 case 2: // Incoming
5250 m_lastOutgoing = Util.EnvironmentTickCount();
5251 break;
5252 }
5253 }
5254
5255 public void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e)
4979 { 5256 {
4980 RegenerateMaptile(); 5257 RegenerateMaptile();
4981 5258
@@ -4994,6 +5271,14 @@ namespace OpenSim.Region.Framework.Scenes
4994 // child agent creation, thereby emulating the SL behavior. 5271 // child agent creation, thereby emulating the SL behavior.
4995 public bool QueryAccess(UUID agentID, Vector3 position, out string reason) 5272 public bool QueryAccess(UUID agentID, Vector3 position, out string reason)
4996 { 5273 {
5274 reason = "You are banned from the region";
5275
5276 if (Permissions.IsGod(agentID))
5277 {
5278 reason = String.Empty;
5279 return true;
5280 }
5281
4997 int num = m_sceneGraph.GetNumberOfScenePresences(); 5282 int num = m_sceneGraph.GetNumberOfScenePresences();
4998 5283
4999 if (num >= RegionInfo.RegionSettings.AgentLimit) 5284 if (num >= RegionInfo.RegionSettings.AgentLimit)
@@ -5005,6 +5290,41 @@ namespace OpenSim.Region.Framework.Scenes
5005 } 5290 }
5006 } 5291 }
5007 5292
5293 ScenePresence presence = GetScenePresence(agentID);
5294 IClientAPI client = null;
5295 AgentCircuitData aCircuit = null;
5296
5297 if (presence != null)
5298 {
5299 client = presence.ControllingClient;
5300 if (client != null)
5301 aCircuit = client.RequestClientInfo();
5302 }
5303
5304 // We may be called before there is a presence or a client.
5305 // Fake AgentCircuitData to keep IAuthorizationModule smiling
5306 if (client == null)
5307 {
5308 aCircuit = new AgentCircuitData();
5309 aCircuit.AgentID = agentID;
5310 aCircuit.firstname = String.Empty;
5311 aCircuit.lastname = String.Empty;
5312 }
5313
5314 try
5315 {
5316 if (!AuthorizeUser(aCircuit, out reason))
5317 {
5318 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5319 return false;
5320 }
5321 }
5322 catch (Exception e)
5323 {
5324 m_log.DebugFormat("[SCENE]: Exception authorizing agent: {0} "+ e.StackTrace, e.Message);
5325 return false;
5326 }
5327
5008 if (position == Vector3.Zero) // Teleport 5328 if (position == Vector3.Zero) // Teleport
5009 { 5329 {
5010 if (!RegionInfo.EstateSettings.AllowDirectTeleport) 5330 if (!RegionInfo.EstateSettings.AllowDirectTeleport)
@@ -5033,13 +5353,46 @@ namespace OpenSim.Region.Framework.Scenes
5033 } 5353 }
5034 } 5354 }
5035 } 5355 }
5356
5357 float posX = 128.0f;
5358 float posY = 128.0f;
5359
5360 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY))
5361 {
5362 // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID);
5363 return false;
5364 }
5365 }
5366 else // Walking
5367 {
5368 ILandObject land = LandChannel.GetLandObject(position.X, position.Y);
5369 if (land == null)
5370 return false;
5371
5372 bool banned = land.IsBannedFromLand(agentID);
5373 bool restricted = land.IsRestrictedFromLand(agentID);
5374
5375 if (banned || restricted)
5376 return false;
5036 } 5377 }
5037 5378
5038 reason = String.Empty; 5379 reason = String.Empty;
5039 return true; 5380 return true;
5040 } 5381 }
5041 5382
5042 /// <summary> 5383 public void StartTimerWatchdog()
5384 {
5385 m_timerWatchdog.Interval = 1000;
5386 m_timerWatchdog.Elapsed += TimerWatchdog;
5387 m_timerWatchdog.AutoReset = true;
5388 m_timerWatchdog.Start();
5389 }
5390
5391 public void TimerWatchdog(object sender, ElapsedEventArgs e)
5392 {
5393 CheckHeartbeat();
5394 }
5395
5043 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the 5396 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the
5044 /// autopilot that moves an avatar to a sit target!. 5397 /// autopilot that moves an avatar to a sit target!.
5045 /// </summary> 5398 /// </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 7d801b5..17563bd 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();
@@ -354,6 +396,11 @@ namespace OpenSim.Region.Framework.Scenes
354 /// </returns> 396 /// </returns>
355 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 397 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
356 { 398 {
399 if (sceneObject == null)
400 {
401 m_log.ErrorFormat("[SCENEGRAPH]: Tried to add null scene object");
402 return false;
403 }
357 if (sceneObject.UUID == UUID.Zero) 404 if (sceneObject.UUID == UUID.Zero)
358 { 405 {
359 m_log.ErrorFormat( 406 m_log.ErrorFormat(
@@ -488,6 +535,30 @@ namespace OpenSim.Region.Framework.Scenes
488 m_updateList[obj.UUID] = obj; 535 m_updateList[obj.UUID] = obj;
489 } 536 }
490 537
538 public void FireAttachToBackup(SceneObjectGroup obj)
539 {
540 if (OnAttachToBackup != null)
541 {
542 OnAttachToBackup(obj);
543 }
544 }
545
546 public void FireDetachFromBackup(SceneObjectGroup obj)
547 {
548 if (OnDetachFromBackup != null)
549 {
550 OnDetachFromBackup(obj);
551 }
552 }
553
554 public void FireChangeBackup(SceneObjectGroup obj)
555 {
556 if (OnChangeBackup != null)
557 {
558 OnChangeBackup(obj);
559 }
560 }
561
491 /// <summary> 562 /// <summary>
492 /// Process all pending updates 563 /// Process all pending updates
493 /// </summary> 564 /// </summary>
@@ -605,7 +676,8 @@ namespace OpenSim.Region.Framework.Scenes
605 676
606 Entities[presence.UUID] = presence; 677 Entities[presence.UUID] = presence;
607 678
608 lock (m_presenceLock) 679 m_scenePresencesLock.EnterWriteLock();
680 try
609 { 681 {
610 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 682 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
611 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 683 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -629,6 +701,10 @@ namespace OpenSim.Region.Framework.Scenes
629 m_scenePresenceMap = newmap; 701 m_scenePresenceMap = newmap;
630 m_scenePresenceArray = newlist; 702 m_scenePresenceArray = newlist;
631 } 703 }
704 finally
705 {
706 m_scenePresencesLock.ExitWriteLock();
707 }
632 } 708 }
633 709
634 /// <summary> 710 /// <summary>
@@ -643,7 +719,8 @@ namespace OpenSim.Region.Framework.Scenes
643 agentID); 719 agentID);
644 } 720 }
645 721
646 lock (m_presenceLock) 722 m_scenePresencesLock.EnterWriteLock();
723 try
647 { 724 {
648 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 725 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
649 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 726 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -665,6 +742,10 @@ namespace OpenSim.Region.Framework.Scenes
665 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 742 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
666 } 743 }
667 } 744 }
745 finally
746 {
747 m_scenePresencesLock.ExitWriteLock();
748 }
668 } 749 }
669 750
670 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 751 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1380,8 +1461,13 @@ namespace OpenSim.Region.Framework.Scenes
1380 { 1461 {
1381 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1462 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1382 { 1463 {
1383 if (m_parentScene.AttachmentsModule != null) 1464 // Set the new attachment point data in the object
1384 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1465 byte attachmentPoint = group.GetAttachmentPoint();
1466 group.UpdateGroupPosition(pos);
1467 group.IsAttachment = false;
1468 group.AbsolutePosition = group.RootPart.AttachedPos;
1469 group.AttachmentPoint = attachmentPoint;
1470 group.HasGroupChanged = true;
1385 } 1471 }
1386 else 1472 else
1387 { 1473 {
@@ -1653,8 +1739,11 @@ namespace OpenSim.Region.Framework.Scenes
1653 return; 1739 return;
1654 1740
1655 Monitor.Enter(m_updateLock); 1741 Monitor.Enter(m_updateLock);
1742
1656 try 1743 try
1657 { 1744 {
1745 parentGroup.areUpdatesSuspended = true;
1746
1658 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1747 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1659 1748
1660 // We do this in reverse to get the link order of the prims correct 1749 // We do this in reverse to get the link order of the prims correct
@@ -1665,9 +1754,13 @@ namespace OpenSim.Region.Framework.Scenes
1665 // Make sure no child prim is set for sale 1754 // Make sure no child prim is set for sale
1666 // So that, on delink, no prims are unwittingly 1755 // So that, on delink, no prims are unwittingly
1667 // left for sale and sold off 1756 // left for sale and sold off
1668 child.RootPart.ObjectSaleType = 0; 1757
1669 child.RootPart.SalePrice = 10; 1758 if (child != null)
1670 childGroups.Add(child); 1759 {
1760 child.RootPart.ObjectSaleType = 0;
1761 child.RootPart.SalePrice = 10;
1762 childGroups.Add(child);
1763 }
1671 } 1764 }
1672 1765
1673 foreach (SceneObjectGroup child in childGroups) 1766 foreach (SceneObjectGroup child in childGroups)
@@ -1686,12 +1779,19 @@ namespace OpenSim.Region.Framework.Scenes
1686 // occur on link to invoke this elsewhere (such as object selection) 1779 // occur on link to invoke this elsewhere (such as object selection)
1687 parentGroup.RootPart.CreateSelected = true; 1780 parentGroup.RootPart.CreateSelected = true;
1688 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1781 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1689 parentGroup.HasGroupChanged = true;
1690 parentGroup.ScheduleGroupForFullUpdate();
1691
1692 } 1782 }
1693 finally 1783 finally
1694 { 1784 {
1785 lock (SceneObjectGroupsByLocalPartID)
1786 {
1787 foreach (SceneObjectPart part in parentGroup.Parts)
1788 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1789 }
1790
1791 parentGroup.areUpdatesSuspended = false;
1792 parentGroup.HasGroupChanged = true;
1793 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1794 parentGroup.ScheduleGroupForFullUpdate();
1695 Monitor.Exit(m_updateLock); 1795 Monitor.Exit(m_updateLock);
1696 } 1796 }
1697 } 1797 }
@@ -1728,21 +1828,24 @@ namespace OpenSim.Region.Framework.Scenes
1728 1828
1729 SceneObjectGroup group = part.ParentGroup; 1829 SceneObjectGroup group = part.ParentGroup;
1730 if (!affectedGroups.Contains(group)) 1830 if (!affectedGroups.Contains(group))
1831 {
1832 group.areUpdatesSuspended = true;
1731 affectedGroups.Add(group); 1833 affectedGroups.Add(group);
1834 }
1732 } 1835 }
1733 } 1836 }
1734 } 1837 }
1735 1838
1736 foreach (SceneObjectPart child in childParts) 1839 if (childParts.Count > 0)
1737 { 1840 {
1738 // Unlink all child parts from their groups 1841 foreach (SceneObjectPart child in childParts)
1739 // 1842 {
1740 child.ParentGroup.DelinkFromGroup(child, true); 1843 // Unlink all child parts from their groups
1741 1844 //
1742 // These are not in affected groups and will not be 1845 child.ParentGroup.DelinkFromGroup(child, true);
1743 // handled further. Do the honors here. 1846 child.ParentGroup.HasGroupChanged = true;
1744 child.ParentGroup.HasGroupChanged = true; 1847 child.ParentGroup.ScheduleGroupForFullUpdate();
1745 child.ParentGroup.ScheduleGroupForFullUpdate(); 1848 }
1746 } 1849 }
1747 1850
1748 foreach (SceneObjectPart root in rootParts) 1851 foreach (SceneObjectPart root in rootParts)
@@ -1752,56 +1855,68 @@ namespace OpenSim.Region.Framework.Scenes
1752 // However, editing linked parts and unlinking may be different 1855 // However, editing linked parts and unlinking may be different
1753 // 1856 //
1754 SceneObjectGroup group = root.ParentGroup; 1857 SceneObjectGroup group = root.ParentGroup;
1858 group.areUpdatesSuspended = true;
1755 1859
1756 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1860 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1757 int numChildren = newSet.Count; 1861 int numChildren = newSet.Count;
1758 1862
1863 if (numChildren == 1)
1864 break;
1865
1759 // If there are prims left in a link set, but the root is 1866 // If there are prims left in a link set, but the root is
1760 // slated for unlink, we need to do this 1867 // slated for unlink, we need to do this
1868 // Unlink the remaining set
1761 // 1869 //
1762 if (numChildren != 1) 1870 bool sendEventsToRemainder = true;
1763 { 1871 if (numChildren > 1)
1764 // Unlink the remaining set 1872 sendEventsToRemainder = false;
1765 //
1766 bool sendEventsToRemainder = true;
1767 if (numChildren > 1)
1768 sendEventsToRemainder = false;
1769 1873
1770 foreach (SceneObjectPart p in newSet) 1874 foreach (SceneObjectPart p in newSet)
1875 {
1876 if (p != group.RootPart)
1771 { 1877 {
1772 if (p != group.RootPart) 1878 group.DelinkFromGroup(p, sendEventsToRemainder);
1773 group.DelinkFromGroup(p, sendEventsToRemainder); 1879 if (numChildren > 2)
1880 {
1881 p.ParentGroup.areUpdatesSuspended = true;
1882 }
1883 else
1884 {
1885 p.ParentGroup.HasGroupChanged = true;
1886 p.ParentGroup.ScheduleGroupForFullUpdate();
1887 }
1774 } 1888 }
1889 }
1890
1891 // If there is more than one prim remaining, we
1892 // need to re-link
1893 //
1894 if (numChildren > 2)
1895 {
1896 // Remove old root
1897 //
1898 if (newSet.Contains(root))
1899 newSet.Remove(root);
1775 1900
1776 // If there is more than one prim remaining, we 1901 // Preserve link ordering
1777 // need to re-link
1778 // 1902 //
1779 if (numChildren > 2) 1903 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1780 { 1904 {
1781 // Remove old root 1905 return a.LinkNum.CompareTo(b.LinkNum);
1782 // 1906 });
1783 if (newSet.Contains(root))
1784 newSet.Remove(root);
1785
1786 // Preserve link ordering
1787 //
1788 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1789 {
1790 return a.LinkNum.CompareTo(b.LinkNum);
1791 });
1792 1907
1793 // Determine new root 1908 // Determine new root
1794 // 1909 //
1795 SceneObjectPart newRoot = newSet[0]; 1910 SceneObjectPart newRoot = newSet[0];
1796 newSet.RemoveAt(0); 1911 newSet.RemoveAt(0);
1797 1912
1798 foreach (SceneObjectPart newChild in newSet) 1913 foreach (SceneObjectPart newChild in newSet)
1799 newChild.ClearUpdateSchedule(); 1914 newChild.ClearUpdateSchedule();
1800 1915
1801 LinkObjects(newRoot, newSet); 1916 newRoot.ParentGroup.areUpdatesSuspended = true;
1802 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1917 LinkObjects(newRoot, newSet);
1803 affectedGroups.Add(newRoot.ParentGroup); 1918 if (!affectedGroups.Contains(newRoot.ParentGroup))
1804 } 1919 affectedGroups.Add(newRoot.ParentGroup);
1805 } 1920 }
1806 } 1921 }
1807 1922
@@ -1809,8 +1924,14 @@ namespace OpenSim.Region.Framework.Scenes
1809 // 1924 //
1810 foreach (SceneObjectGroup g in affectedGroups) 1925 foreach (SceneObjectGroup g in affectedGroups)
1811 { 1926 {
1927 // Child prims that have been unlinked and deleted will
1928 // return unless the root is deleted. This will remove them
1929 // from the database. They will be rewritten immediately,
1930 // minus the rows for the unlinked child prims.
1931 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1812 g.TriggerScriptChangedEvent(Changed.LINK); 1932 g.TriggerScriptChangedEvent(Changed.LINK);
1813 g.HasGroupChanged = true; // Persist 1933 g.HasGroupChanged = true; // Persist
1934 g.areUpdatesSuspended = false;
1814 g.ScheduleGroupForFullUpdate(); 1935 g.ScheduleGroupForFullUpdate();
1815 } 1936 }
1816 } 1937 }
@@ -1912,9 +2033,6 @@ namespace OpenSim.Region.Framework.Scenes
1912 child.ApplyNextOwnerPermissions(); 2033 child.ApplyNextOwnerPermissions();
1913 } 2034 }
1914 } 2035 }
1915
1916 copy.RootPart.ObjectSaleType = 0;
1917 copy.RootPart.SalePrice = 10;
1918 } 2036 }
1919 2037
1920 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2038 // 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..6485710 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
@@ -1956,6 +2351,11 @@ namespace OpenSim.Region.Framework.Scenes
1956 /// <param name="objectGroup">The group of prims which should be linked to this group</param> 2351 /// <param name="objectGroup">The group of prims which should be linked to this group</param>
1957 public void LinkToGroup(SceneObjectGroup objectGroup) 2352 public void LinkToGroup(SceneObjectGroup objectGroup)
1958 { 2353 {
2354 LinkToGroup(objectGroup, false);
2355 }
2356
2357 public void LinkToGroup(SceneObjectGroup objectGroup, bool insert)
2358 {
1959// m_log.DebugFormat( 2359// m_log.DebugFormat(
1960// "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}", 2360// "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}",
1961// objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID); 2361// objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID);
@@ -1985,7 +2385,20 @@ namespace OpenSim.Region.Framework.Scenes
1985 2385
1986 lock (m_parts.SyncRoot) 2386 lock (m_parts.SyncRoot)
1987 { 2387 {
1988 int linkNum = PrimCount + 1; 2388 int linkNum;
2389 if (insert)
2390 {
2391 linkNum = 2;
2392 foreach (SceneObjectPart part in Parts)
2393 {
2394 if (part.LinkNum > 1)
2395 part.LinkNum++;
2396 }
2397 }
2398 else
2399 {
2400 linkNum = PrimCount + 1;
2401 }
1989 2402
1990 m_parts.Add(linkPart.UUID, linkPart); 2403 m_parts.Add(linkPart.UUID, linkPart);
1991 2404
@@ -2013,7 +2426,7 @@ namespace OpenSim.Region.Framework.Scenes
2013 objectGroup.IsDeleted = true; 2426 objectGroup.IsDeleted = true;
2014 2427
2015 objectGroup.m_parts.Clear(); 2428 objectGroup.m_parts.Clear();
2016 2429
2017 // Can't do this yet since backup still makes use of the root part without any synchronization 2430 // Can't do this yet since backup still makes use of the root part without any synchronization
2018// objectGroup.m_rootPart = null; 2431// objectGroup.m_rootPart = null;
2019 2432
@@ -2147,6 +2560,7 @@ namespace OpenSim.Region.Framework.Scenes
2147 /// <param name="objectGroup"></param> 2560 /// <param name="objectGroup"></param>
2148 public virtual void DetachFromBackup() 2561 public virtual void DetachFromBackup()
2149 { 2562 {
2563 m_scene.SceneGraph.FireDetachFromBackup(this);
2150 if (m_isBackedUp && Scene != null) 2564 if (m_isBackedUp && Scene != null)
2151 m_scene.EventManager.OnBackup -= ProcessBackup; 2565 m_scene.EventManager.OnBackup -= ProcessBackup;
2152 2566
@@ -2165,7 +2579,8 @@ namespace OpenSim.Region.Framework.Scenes
2165 2579
2166 axPos *= parentRot; 2580 axPos *= parentRot;
2167 part.OffsetPosition = axPos; 2581 part.OffsetPosition = axPos;
2168 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 2582 Vector3 newPos = oldGroupPosition + part.OffsetPosition;
2583 part.GroupPosition = newPos;
2169 part.OffsetPosition = Vector3.Zero; 2584 part.OffsetPosition = Vector3.Zero;
2170 part.RotationOffset = worldRot; 2585 part.RotationOffset = worldRot;
2171 2586
@@ -2176,7 +2591,7 @@ namespace OpenSim.Region.Framework.Scenes
2176 2591
2177 part.LinkNum = linkNum; 2592 part.LinkNum = linkNum;
2178 2593
2179 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 2594 part.OffsetPosition = newPos - AbsolutePosition;
2180 2595
2181 Quaternion rootRotation = m_rootPart.RotationOffset; 2596 Quaternion rootRotation = m_rootPart.RotationOffset;
2182 2597
@@ -2186,7 +2601,7 @@ namespace OpenSim.Region.Framework.Scenes
2186 2601
2187 parentRot = m_rootPart.RotationOffset; 2602 parentRot = m_rootPart.RotationOffset;
2188 oldRot = part.RotationOffset; 2603 oldRot = part.RotationOffset;
2189 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 2604 Quaternion newRot = Quaternion.Inverse(parentRot) * worldRot;
2190 part.RotationOffset = newRot; 2605 part.RotationOffset = newRot;
2191 } 2606 }
2192 2607
@@ -2433,8 +2848,12 @@ namespace OpenSim.Region.Framework.Scenes
2433 } 2848 }
2434 } 2849 }
2435 2850
2851 RootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
2436 for (int i = 0; i < parts.Length; i++) 2852 for (int i = 0; i < parts.Length; i++)
2437 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect); 2853 {
2854 if (parts[i] != RootPart)
2855 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
2856 }
2438 } 2857 }
2439 } 2858 }
2440 2859
@@ -2447,6 +2866,17 @@ namespace OpenSim.Region.Framework.Scenes
2447 } 2866 }
2448 } 2867 }
2449 2868
2869
2870
2871 /// <summary>
2872 /// Gets the number of parts
2873 /// </summary>
2874 /// <returns></returns>
2875 public int GetPartCount()
2876 {
2877 return Parts.Count();
2878 }
2879
2450 /// <summary> 2880 /// <summary>
2451 /// Update the texture entry for this part 2881 /// Update the texture entry for this part
2452 /// </summary> 2882 /// </summary>
@@ -2508,7 +2938,6 @@ namespace OpenSim.Region.Framework.Scenes
2508 { 2938 {
2509// m_log.DebugFormat( 2939// m_log.DebugFormat(
2510// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale); 2940// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale);
2511
2512 RootPart.StoreUndoState(true); 2941 RootPart.StoreUndoState(true);
2513 2942
2514 scale.X = Math.Min(scale.X, Scene.m_maxNonphys); 2943 scale.X = Math.Min(scale.X, Scene.m_maxNonphys);
@@ -2609,7 +3038,6 @@ namespace OpenSim.Region.Framework.Scenes
2609 prevScale.X *= x; 3038 prevScale.X *= x;
2610 prevScale.Y *= y; 3039 prevScale.Y *= y;
2611 prevScale.Z *= z; 3040 prevScale.Z *= z;
2612
2613// RootPart.IgnoreUndoUpdate = true; 3041// RootPart.IgnoreUndoUpdate = true;
2614 RootPart.Resize(prevScale); 3042 RootPart.Resize(prevScale);
2615// RootPart.IgnoreUndoUpdate = false; 3043// RootPart.IgnoreUndoUpdate = false;
@@ -2640,7 +3068,9 @@ namespace OpenSim.Region.Framework.Scenes
2640 } 3068 }
2641 3069
2642// obPart.IgnoreUndoUpdate = false; 3070// obPart.IgnoreUndoUpdate = false;
2643// obPart.StoreUndoState(); 3071 HasGroupChanged = true;
3072 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
3073 ScheduleGroupForTerseUpdate();
2644 } 3074 }
2645 3075
2646// m_log.DebugFormat( 3076// m_log.DebugFormat(
@@ -2700,9 +3130,9 @@ namespace OpenSim.Region.Framework.Scenes
2700 { 3130 {
2701 SceneObjectPart part = GetChildPart(localID); 3131 SceneObjectPart part = GetChildPart(localID);
2702 3132
2703// SceneObjectPart[] parts = m_parts.GetArray(); 3133 SceneObjectPart[] parts = m_parts.GetArray();
2704// for (int i = 0; i < parts.Length; i++) 3134 for (int i = 0; i < parts.Length; i++)
2705// parts[i].StoreUndoState(); 3135 parts[i].StoreUndoState();
2706 3136
2707 if (part != null) 3137 if (part != null)
2708 { 3138 {
@@ -2758,10 +3188,27 @@ namespace OpenSim.Region.Framework.Scenes
2758 obPart.OffsetPosition = obPart.OffsetPosition + diff; 3188 obPart.OffsetPosition = obPart.OffsetPosition + diff;
2759 } 3189 }
2760 3190
2761 AbsolutePosition = newPos; 3191 //We have to set undoing here because otherwise an undo state will be saved
3192 if (!m_rootPart.Undoing)
3193 {
3194 m_rootPart.Undoing = true;
3195 AbsolutePosition = newPos;
3196 m_rootPart.Undoing = false;
3197 }
3198 else
3199 {
3200 AbsolutePosition = newPos;
3201 }
2762 3202
2763 HasGroupChanged = true; 3203 HasGroupChanged = true;
2764 ScheduleGroupForTerseUpdate(); 3204 if (m_rootPart.Undoing)
3205 {
3206 ScheduleGroupForFullUpdate();
3207 }
3208 else
3209 {
3210 ScheduleGroupForTerseUpdate();
3211 }
2765 } 3212 }
2766 3213
2767 #endregion 3214 #endregion
@@ -2838,10 +3285,7 @@ namespace OpenSim.Region.Framework.Scenes
2838 public void UpdateSingleRotation(Quaternion rot, uint localID) 3285 public void UpdateSingleRotation(Quaternion rot, uint localID)
2839 { 3286 {
2840 SceneObjectPart part = GetChildPart(localID); 3287 SceneObjectPart part = GetChildPart(localID);
2841
2842 SceneObjectPart[] parts = m_parts.GetArray(); 3288 SceneObjectPart[] parts = m_parts.GetArray();
2843 for (int i = 0; i < parts.Length; i++)
2844 parts[i].StoreUndoState();
2845 3289
2846 if (part != null) 3290 if (part != null)
2847 { 3291 {
@@ -2879,7 +3323,16 @@ namespace OpenSim.Region.Framework.Scenes
2879 if (part.UUID == m_rootPart.UUID) 3323 if (part.UUID == m_rootPart.UUID)
2880 { 3324 {
2881 UpdateRootRotation(rot); 3325 UpdateRootRotation(rot);
2882 AbsolutePosition = pos; 3326 if (!m_rootPart.Undoing)
3327 {
3328 m_rootPart.Undoing = true;
3329 AbsolutePosition = pos;
3330 m_rootPart.Undoing = false;
3331 }
3332 else
3333 {
3334 AbsolutePosition = pos;
3335 }
2883 } 3336 }
2884 else 3337 else
2885 { 3338 {
@@ -2903,9 +3356,10 @@ namespace OpenSim.Region.Framework.Scenes
2903 3356
2904 Quaternion axRot = rot; 3357 Quaternion axRot = rot;
2905 Quaternion oldParentRot = m_rootPart.RotationOffset; 3358 Quaternion oldParentRot = m_rootPart.RotationOffset;
2906
2907 m_rootPart.StoreUndoState(); 3359 m_rootPart.StoreUndoState();
2908 m_rootPart.UpdateRotation(rot); 3360
3361 //Don't use UpdateRotation because it schedules an update prematurely
3362 m_rootPart.RotationOffset = rot;
2909 if (m_rootPart.PhysActor != null) 3363 if (m_rootPart.PhysActor != null)
2910 { 3364 {
2911 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset; 3365 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset;
@@ -2919,15 +3373,17 @@ namespace OpenSim.Region.Framework.Scenes
2919 if (prim.UUID != m_rootPart.UUID) 3373 if (prim.UUID != m_rootPart.UUID)
2920 { 3374 {
2921 prim.IgnoreUndoUpdate = true; 3375 prim.IgnoreUndoUpdate = true;
3376
3377 Quaternion NewRot = oldParentRot * prim.RotationOffset;
3378 NewRot = Quaternion.Inverse(axRot) * NewRot;
3379 prim.RotationOffset = NewRot;
3380
2922 Vector3 axPos = prim.OffsetPosition; 3381 Vector3 axPos = prim.OffsetPosition;
3382
2923 axPos *= oldParentRot; 3383 axPos *= oldParentRot;
2924 axPos *= Quaternion.Inverse(axRot); 3384 axPos *= Quaternion.Inverse(axRot);
2925 prim.OffsetPosition = axPos; 3385 prim.OffsetPosition = axPos;
2926 Quaternion primsRot = prim.RotationOffset; 3386
2927 Quaternion newRot = oldParentRot * primsRot;
2928 newRot = Quaternion.Inverse(axRot) * newRot;
2929 prim.RotationOffset = newRot;
2930 prim.ScheduleTerseUpdate();
2931 prim.IgnoreUndoUpdate = false; 3387 prim.IgnoreUndoUpdate = false;
2932 } 3388 }
2933 } 3389 }
@@ -2941,8 +3397,8 @@ namespace OpenSim.Region.Framework.Scenes
2941//// childpart.StoreUndoState(); 3397//// childpart.StoreUndoState();
2942// } 3398// }
2943// } 3399// }
2944 3400 HasGroupChanged = true;
2945 m_rootPart.ScheduleTerseUpdate(); 3401 ScheduleGroupForFullUpdate();
2946 3402
2947// m_log.DebugFormat( 3403// m_log.DebugFormat(
2948// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}", 3404// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}",
@@ -3170,7 +3626,6 @@ namespace OpenSim.Region.Framework.Scenes
3170 public float GetMass() 3626 public float GetMass()
3171 { 3627 {
3172 float retmass = 0f; 3628 float retmass = 0f;
3173
3174 SceneObjectPart[] parts = m_parts.GetArray(); 3629 SceneObjectPart[] parts = m_parts.GetArray();
3175 for (int i = 0; i < parts.Length; i++) 3630 for (int i = 0; i < parts.Length; i++)
3176 retmass += parts[i].GetMass(); 3631 retmass += parts[i].GetMass();
@@ -3266,6 +3721,14 @@ namespace OpenSim.Region.Framework.Scenes
3266 SetFromItemID(uuid); 3721 SetFromItemID(uuid);
3267 } 3722 }
3268 3723
3724 public void ResetOwnerChangeFlag()
3725 {
3726 ForEachPart(delegate(SceneObjectPart part)
3727 {
3728 part.ResetOwnerChangeFlag();
3729 });
3730 }
3731
3269 #endregion 3732 #endregion
3270 } 3733 }
3271} 3734}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 27bcc09..0d14963 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
@@ -1027,10 +1058,7 @@ namespace OpenSim.Region.Framework.Scenes
1027 { 1058 {
1028 get 1059 get
1029 { 1060 {
1030 if (ParentGroup.IsAttachment) 1061 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1031 return GroupPosition;
1032
1033 return m_offsetPosition + m_groupPosition;
1034 } 1062 }
1035 } 1063 }
1036 1064
@@ -1200,6 +1228,13 @@ namespace OpenSim.Region.Framework.Scenes
1200 _flags = value; 1228 _flags = value;
1201 } 1229 }
1202 } 1230 }
1231
1232 [XmlIgnore]
1233 public bool IsOccupied // KF If an av is sittingon this prim
1234 {
1235 get { return m_occupied; }
1236 set { m_occupied = value; }
1237 }
1203 1238
1204 /// <summary> 1239 /// <summary>
1205 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero 1240 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero
@@ -1259,6 +1294,19 @@ namespace OpenSim.Region.Framework.Scenes
1259 set { m_collisionSoundVolume = value; } 1294 set { m_collisionSoundVolume = value; }
1260 } 1295 }
1261 1296
1297 public float Buoyancy
1298 {
1299 get { return m_buoyancy; }
1300 set
1301 {
1302 m_buoyancy = value;
1303 if (PhysActor != null)
1304 {
1305 PhysActor.Buoyancy = value;
1306 }
1307 }
1308 }
1309
1262 #endregion Public Properties with only Get 1310 #endregion Public Properties with only Get
1263 1311
1264 private uint ApplyMask(uint val, bool set, uint mask) 1312 private uint ApplyMask(uint val, bool set, uint mask)
@@ -1583,6 +1631,9 @@ namespace OpenSim.Region.Framework.Scenes
1583 1631
1584 // Move afterwards ResetIDs as it clears the localID 1632 // Move afterwards ResetIDs as it clears the localID
1585 dupe.LocalId = localID; 1633 dupe.LocalId = localID;
1634 if(dupe.PhysActor != null)
1635 dupe.PhysActor.LocalID = localID;
1636
1586 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 1637 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1587 dupe.LastOwnerID = OwnerID; 1638 dupe.LastOwnerID = OwnerID;
1588 1639
@@ -2588,17 +2639,18 @@ namespace OpenSim.Region.Framework.Scenes
2588 //Trys to fetch sound id from prim's inventory. 2639 //Trys to fetch sound id from prim's inventory.
2589 //Prim's inventory doesn't support non script items yet 2640 //Prim's inventory doesn't support non script items yet
2590 2641
2591 lock (TaskInventory) 2642 TaskInventory.LockItemsForRead(true);
2643
2644 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2592 { 2645 {
2593 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2646 if (item.Value.Name == sound)
2594 { 2647 {
2595 if (item.Value.Name == sound) 2648 soundID = item.Value.ItemID;
2596 { 2649 break;
2597 soundID = item.Value.ItemID;
2598 break;
2599 }
2600 } 2650 }
2601 } 2651 }
2652
2653 TaskInventory.LockItemsForRead(false);
2602 } 2654 }
2603 2655
2604 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp) 2656 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp)
@@ -2919,8 +2971,8 @@ namespace OpenSim.Region.Framework.Scenes
2919 { 2971 {
2920 const float ROTATION_TOLERANCE = 0.01f; 2972 const float ROTATION_TOLERANCE = 0.01f;
2921 const float VELOCITY_TOLERANCE = 0.001f; 2973 const float VELOCITY_TOLERANCE = 0.001f;
2922 const float POSITION_TOLERANCE = 0.05f; 2974 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2923 const int TIME_MS_TOLERANCE = 3000; 2975 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2924 2976
2925 switch (UpdateFlag) 2977 switch (UpdateFlag)
2926 { 2978 {
@@ -2982,17 +3034,16 @@ namespace OpenSim.Region.Framework.Scenes
2982 if (!UUID.TryParse(sound, out soundID)) 3034 if (!UUID.TryParse(sound, out soundID))
2983 { 3035 {
2984 // search sound file from inventory 3036 // search sound file from inventory
2985 lock (TaskInventory) 3037 TaskInventory.LockItemsForRead(true);
3038 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2986 { 3039 {
2987 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3040 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
2988 { 3041 {
2989 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3042 soundID = item.Value.ItemID;
2990 { 3043 break;
2991 soundID = item.Value.ItemID;
2992 break;
2993 }
2994 } 3044 }
2995 } 3045 }
3046 TaskInventory.LockItemsForRead(false);
2996 } 3047 }
2997 3048
2998 if (soundID == UUID.Zero) 3049 if (soundID == UUID.Zero)
@@ -3459,10 +3510,10 @@ namespace OpenSim.Region.Framework.Scenes
3459 // TODO: May need to fix for group comparison 3510 // TODO: May need to fix for group comparison
3460 if (last.Compare(this)) 3511 if (last.Compare(this))
3461 { 3512 {
3462 // m_log.DebugFormat( 3513 // m_log.DebugFormat(
3463 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}", 3514 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3464 // Name, LocalId, m_undo.Count); 3515 // Name, LocalId, m_undo.Count);
3465 3516
3466 return; 3517 return;
3467 } 3518 }
3468 } 3519 }
@@ -3475,29 +3526,29 @@ namespace OpenSim.Region.Framework.Scenes
3475 if (ParentGroup.GetSceneMaxUndo() > 0) 3526 if (ParentGroup.GetSceneMaxUndo() > 0)
3476 { 3527 {
3477 UndoState nUndo = new UndoState(this, forGroup); 3528 UndoState nUndo = new UndoState(this, forGroup);
3478 3529
3479 m_undo.Push(nUndo); 3530 m_undo.Push(nUndo);
3480 3531
3481 if (m_redo.Count > 0) 3532 if (m_redo.Count > 0)
3482 m_redo.Clear(); 3533 m_redo.Clear();
3483 3534
3484 // m_log.DebugFormat( 3535 // m_log.DebugFormat(
3485 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}", 3536 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3486 // Name, LocalId, forGroup, m_undo.Count); 3537 // Name, LocalId, forGroup, m_undo.Count);
3487 } 3538 }
3488 } 3539 }
3489 } 3540 }
3490 } 3541 }
3491// else 3542 // else
3492// { 3543 // {
3493// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId); 3544 // m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3494// } 3545 // }
3495 } 3546 }
3496// else 3547 // else
3497// { 3548 // {
3498// m_log.DebugFormat( 3549 // m_log.DebugFormat(
3499// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId); 3550 // "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3500// } 3551 // }
3501 } 3552 }
3502 3553
3503 /// <summary> 3554 /// <summary>
@@ -4228,6 +4279,9 @@ namespace OpenSim.Region.Framework.Scenes
4228 bool wasPhantom = ((Flags & PrimFlags.Phantom) != 0); 4279 bool wasPhantom = ((Flags & PrimFlags.Phantom) != 0);
4229 bool wasVD = VolumeDetectActive; 4280 bool wasVD = VolumeDetectActive;
4230 4281
4282// m_log.DebugFormat("[SOP]: Old states: phys: {0} temp: {1} phan: {2} vd: {3}", wasUsingPhysics, wasTemporary, wasPhantom, wasVD);
4283// m_log.DebugFormat("[SOP]: New states: phys: {0} temp: {1} phan: {2} vd: {3}", UsePhysics, SetTemporary, SetPhantom, SetVD);
4284
4231 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) 4285 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
4232 return; 4286 return;
4233 4287
@@ -4257,6 +4311,11 @@ namespace OpenSim.Region.Framework.Scenes
4257 SetPhantom = false; 4311 SetPhantom = false;
4258 } 4312 }
4259 } 4313 }
4314 else if (wasVD)
4315 {
4316 // Correspondingly, if VD is turned off, also turn off phantom
4317 SetPhantom = false;
4318 }
4260 4319
4261 if (UsePhysics && IsJoint()) 4320 if (UsePhysics && IsJoint())
4262 { 4321 {
@@ -4755,5 +4814,17 @@ namespace OpenSim.Region.Framework.Scenes
4755 Color color = Color; 4814 Color color = Color;
4756 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 4815 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4757 } 4816 }
4817
4818 public void ResetOwnerChangeFlag()
4819 {
4820 List<UUID> inv = Inventory.GetInventoryList();
4821
4822 foreach (UUID itemID in inv)
4823 {
4824 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
4825 item.OwnerChanged = false;
4826 Inventory.UpdateInventoryItem(item, false, false);
4827 }
4828 }
4758 } 4829 }
4759} 4830}
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 11f927c..8fe3199 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 81bf9ed..7f5372c 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 0bdd84a..b0b1b16 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;
554
555 int numPis = (int)(Math.PI / angle);
556 double remainder = angle - Math.PI * numPis;
557 if (numPis % 2 == 1)
558 return Math.PI - angle;
559 return remainder;
560 }
478 561
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. 562 public LSL_Vector llRot2Euler(LSL_Rotation q1)
480 double m = LSL_Vector.Mag(v); // Just in case v isn't normalized, need magnitude for Asin() operation later. 563 {
481 if (m == 0.0) return new LSL_Vector(); 564 m_host.AddScriptLPS(1);
482 double x = Math.Atan2(-v.y, v.z); 565 LSL_Vector eul = new LSL_Vector();
483 double sin = v.x / m;
484 if (sin < -0.999999 || sin > 0.999999) x = 0.0; // Force X rotation to 0 at the singularities.
485 double y = Math.Asin(sin);
486 // Rotate X axis unit vector by r and unwind the X and Y rotations leaving only the Z rotation
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)));
488 double z = Math.Atan2(v.y, v.x);
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();
@@ -2028,11 +2223,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2028 } 2223 }
2029 else 2224 else
2030 { 2225 {
2031 if (m_host.IsRoot) 2226 if (part.IsRoot)
2032 { 2227 {
2033 return new LSL_Vector(m_host.AttachedPos.X, 2228 return new LSL_Vector(part.AttachedPos.X,
2034 m_host.AttachedPos.Y, 2229 part.AttachedPos.Y,
2035 m_host.AttachedPos.Z); 2230 part.AttachedPos.Z);
2036 } 2231 }
2037 else 2232 else
2038 { 2233 {
@@ -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;
@@ -2771,64 +2971,69 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2771 { 2971 {
2772 m_host.AddScriptLPS(1); 2972 m_host.AddScriptLPS(1);
2773 2973
2774 if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s)) 2974 Util.FireAndForget(delegate (object x)
2775 return; 2975 {
2776 float dist = (float)llVecDist(llGetPos(), pos); 2976 if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s))
2977 return;
2978 float dist = (float)llVecDist(llGetPos(), pos);
2777 2979
2778 if (dist > m_ScriptDistanceFactor * 10.0f) 2980 if (dist > m_ScriptDistanceFactor * 10.0f)
2779 return; 2981 return;
2780 2982
2781 TaskInventoryDictionary partInventory = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 2983 //Clone is thread-safe
2984 TaskInventoryDictionary partInventory = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
2782 2985
2783 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in partInventory) 2986 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in partInventory)
2784 {
2785 if (inv.Value.Name == inventory)
2786 { 2987 {
2787 // make sure we're an object. 2988 if (inv.Value.Name == inventory)
2788 if (inv.Value.InvType != (int)InventoryType.Object)
2789 { 2989 {
2790 llSay(0, "Unable to create requested object. Object is missing from database."); 2990 // make sure we're an object.
2791 return; 2991 if (inv.Value.InvType != (int)InventoryType.Object)
2792 } 2992 {
2993 llSay(0, "Unable to create requested object. Object is missing from database.");
2994 return;
2995 }
2793 2996
2794 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z); 2997 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
2795 Vector3 llvel = new Vector3((float)vel.x, (float)vel.y, (float)vel.z); 2998 Vector3 llvel = new Vector3((float)vel.x, (float)vel.y, (float)vel.z);
2796 2999
2797 // need the magnitude later 3000 // need the magnitude later
2798 float velmag = (float)Util.GetMagnitude(llvel); 3001 // float velmag = (float)Util.GetMagnitude(llvel);
2799 3002
2800 SceneObjectGroup new_group = World.RezObject(m_host, inv.Value, llpos, Rot2Quaternion(rot), llvel, param); 3003 SceneObjectGroup new_group = World.RezObject(m_host, inv.Value, llpos, Rot2Quaternion(rot), llvel, param);
2801 3004
2802 // If either of these are null, then there was an unknown error. 3005 // If either of these are null, then there was an unknown error.
2803 if (new_group == null) 3006 if (new_group == null)
2804 continue; 3007 continue;
2805 3008
2806 // objects rezzed with this method are die_at_edge by default. 3009 // objects rezzed with this method are die_at_edge by default.
2807 new_group.RootPart.SetDieAtEdge(true); 3010 new_group.RootPart.SetDieAtEdge(true);
2808 3011
2809 new_group.ResumeScripts(); 3012 new_group.ResumeScripts();
2810 3013
2811 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams( 3014 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
2812 "object_rez", new Object[] { 3015 "object_rez", new Object[] {
2813 new LSL_String( 3016 new LSL_String(
2814 new_group.RootPart.UUID.ToString()) }, 3017 new_group.RootPart.UUID.ToString()) },
2815 new DetectParams[0])); 3018 new DetectParams[0]));
2816 3019
2817 float groupmass = new_group.GetMass(); 3020 float groupmass = new_group.GetMass();
2818 3021
2819 if (new_group.RootPart.PhysActor != null && new_group.RootPart.PhysActor.IsPhysical && llvel != Vector3.Zero) 3022 if (new_group.RootPart.PhysActor != null && new_group.RootPart.PhysActor.IsPhysical && llvel != Vector3.Zero)
2820 { 3023 {
2821 //Recoil. 3024 //Recoil.
2822 llApplyImpulse(new LSL_Vector(llvel.X * groupmass, llvel.Y * groupmass, llvel.Z * groupmass), 0); 3025 llApplyImpulse(new LSL_Vector(llvel.X * groupmass, llvel.Y * groupmass, llvel.Z * groupmass), 0);
3026 }
3027 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
3028 return;
2823 } 3029 }
2824 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
2825 ScriptSleep((int)((groupmass * velmag) / 10));
2826 ScriptSleep(100);
2827 return;
2828 } 3030 }
2829 }
2830 3031
2831 llSay(0, "Could not find object " + inventory); 3032 llSay(0, "Could not find object " + inventory);
3033 });
3034
3035 //ScriptSleep((int)((groupmass * velmag) / 10));
3036 ScriptSleep(100);
2832 } 3037 }
2833 3038
2834 public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param) 3039 public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
@@ -2839,34 +3044,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2839 public void llLookAt(LSL_Vector target, double strength, double damping) 3044 public void llLookAt(LSL_Vector target, double strength, double damping)
2840 { 3045 {
2841 m_host.AddScriptLPS(1); 3046 m_host.AddScriptLPS(1);
2842 // Determine where we are looking from
2843 LSL_Vector from = llGetPos();
2844 3047
2845 // Work out the normalised vector from the source to the target 3048 // Get the normalized vector to the target
2846 LSL_Vector delta = llVecNorm(target - from); 3049 LSL_Vector d1 = llVecNorm(target - llGetPos());
2847 LSL_Vector angle = new LSL_Vector(0,0,0);
2848 3050
2849 // Calculate the yaw 3051 // Get the bearing (yaw)
2850 // subtracting PI_BY_TWO is required to compensate for the odd SL co-ordinate system 3052 LSL_Vector a1 = new LSL_Vector(0,0,0);
2851 angle.x = llAtan2(delta.z, delta.y) - ScriptBaseClass.PI_BY_TWO; 3053 a1.z = llAtan2(d1.y, d1.x);
2852 3054
2853 // Calculate pitch 3055 // Get the elevation (pitch)
2854 angle.y = llAtan2(delta.x, llSqrt((delta.y * delta.y) + (delta.z * delta.z))); 3056 LSL_Vector a2 = new LSL_Vector(0,0,0);
3057 a2.y= -llAtan2(d1.z, llSqrt((d1.x * d1.x) + (d1.y * d1.y)));
2855 3058
2856 // we need to convert from a vector describing 3059 LSL_Rotation r1 = llEuler2Rot(a1);
2857 // the angles of rotation in radians into rotation value 3060 LSL_Rotation r2 = llEuler2Rot(a2);
3061 LSL_Rotation r3 = new LSL_Rotation(0.000000, 0.707107, 0.000000, 0.707107);
2858 3062
2859 LSL_Rotation rot = llEuler2Rot(angle); 3063 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 { 3064 {
2865 llSetRot(rot); 3065 // Do nothing if either value is 0 (this has been checked in SL)
3066 if (strength <= 0.0 || damping <= 0.0)
3067 return;
3068
3069 llSetRot(r3 * r2 * r1);
2866 } 3070 }
2867 else 3071 else
2868 { 3072 {
2869 m_host.StartLookAt(Rot2Quaternion(rot), (float)strength, (float)damping); 3073 if (strength == 0)
3074 {
3075 llSetRot(r3 * r2 * r1);
3076 return;
3077 }
3078
3079 m_host.StartLookAt(Rot2Quaternion(r3 * r2 * r1), (float)strength, (float)damping);
2870 } 3080 }
2871 } 3081 }
2872 3082
@@ -2916,13 +3126,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2916 { 3126 {
2917 TaskInventoryItem item; 3127 TaskInventoryItem item;
2918 3128
2919 lock (m_host.TaskInventory) 3129 m_host.TaskInventory.LockItemsForRead(true);
3130 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2920 { 3131 {
2921 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3132 m_host.TaskInventory.LockItemsForRead(false);
2922 return; 3133 return;
2923 else 3134 }
2924 item = m_host.TaskInventory[InventorySelf()]; 3135 else
3136 {
3137 item = m_host.TaskInventory[InventorySelf()];
2925 } 3138 }
3139 m_host.TaskInventory.LockItemsForRead(false);
2926 3140
2927 if (item.PermsGranter != UUID.Zero) 3141 if (item.PermsGranter != UUID.Zero)
2928 { 3142 {
@@ -2944,13 +3158,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2944 { 3158 {
2945 TaskInventoryItem item; 3159 TaskInventoryItem item;
2946 3160
3161 m_host.TaskInventory.LockItemsForRead(true);
2947 lock (m_host.TaskInventory) 3162 lock (m_host.TaskInventory)
2948 { 3163 {
3164
2949 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3165 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3166 {
3167 m_host.TaskInventory.LockItemsForRead(false);
2950 return; 3168 return;
3169 }
2951 else 3170 else
3171 {
2952 item = m_host.TaskInventory[InventorySelf()]; 3172 item = m_host.TaskInventory[InventorySelf()];
3173 }
2953 } 3174 }
3175 m_host.TaskInventory.LockItemsForRead(false);
2954 3176
2955 m_host.AddScriptLPS(1); 3177 m_host.AddScriptLPS(1);
2956 3178
@@ -2982,19 +3204,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2982 { 3204 {
2983 m_host.AddScriptLPS(1); 3205 m_host.AddScriptLPS(1);
2984 3206
2985// if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
2986// return;
2987
2988 TaskInventoryItem item; 3207 TaskInventoryItem item;
2989 3208
2990 lock (m_host.TaskInventory) 3209 m_host.TaskInventory.LockItemsForRead(true);
3210
3211 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2991 { 3212 {
2992 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3213 m_host.TaskInventory.LockItemsForRead(false);
2993 return; 3214 return;
2994 else 3215 }
2995 item = m_host.TaskInventory[InventorySelf()]; 3216 else
3217 {
3218 item = m_host.TaskInventory[InventorySelf()];
2996 } 3219 }
2997 3220
3221 m_host.TaskInventory.LockItemsForRead(false);
3222
2998 if (item.PermsGranter != m_host.OwnerID) 3223 if (item.PermsGranter != m_host.OwnerID)
2999 return; 3224 return;
3000 3225
@@ -3019,13 +3244,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3019 3244
3020 TaskInventoryItem item; 3245 TaskInventoryItem item;
3021 3246
3022 lock (m_host.TaskInventory) 3247 m_host.TaskInventory.LockItemsForRead(true);
3248
3249 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3023 { 3250 {
3024 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3251 m_host.TaskInventory.LockItemsForRead(false);
3025 return; 3252 return;
3026 else
3027 item = m_host.TaskInventory[InventorySelf()];
3028 } 3253 }
3254 else
3255 {
3256 item = m_host.TaskInventory[InventorySelf()];
3257 }
3258 m_host.TaskInventory.LockItemsForRead(false);
3259
3029 3260
3030 if (item.PermsGranter != m_host.OwnerID) 3261 if (item.PermsGranter != m_host.OwnerID)
3031 return; 3262 return;
@@ -3072,6 +3303,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3072 3303
3073 public void llInstantMessage(string user, string message) 3304 public void llInstantMessage(string user, string message)
3074 { 3305 {
3306 UUID result;
3307 if (!UUID.TryParse(user, out result))
3308 {
3309 ShoutError("An invalid key was passed to llInstantMessage");
3310 ScriptSleep(2000);
3311 return;
3312 }
3313
3314
3075 m_host.AddScriptLPS(1); 3315 m_host.AddScriptLPS(1);
3076 3316
3077 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. 3317 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
@@ -3086,14 +3326,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3086 UUID friendTransactionID = UUID.Random(); 3326 UUID friendTransactionID = UUID.Random();
3087 3327
3088 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); 3328 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
3089 3329
3090 GridInstantMessage msg = new GridInstantMessage(); 3330 GridInstantMessage msg = new GridInstantMessage();
3091 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; 3331 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid;
3092 msg.toAgentID = new Guid(user); // toAgentID.Guid; 3332 msg.toAgentID = new Guid(user); // toAgentID.Guid;
3093 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here 3333 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); 3334// 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()); 3335// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString());
3096 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; 3336// DateTime dt = DateTime.UtcNow;
3337//
3338// // Ticks from UtcNow, but make it look like local. Evil, huh?
3339// dt = DateTime.SpecifyKind(dt, DateTimeKind.Local);
3340//
3341// try
3342// {
3343// // Convert that to the PST timezone
3344// TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
3345// dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo);
3346// }
3347// catch
3348// {
3349// // No logging here, as it could be VERY spammy
3350// }
3351//
3352// // And make it look local again to fool the unix time util
3353// dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
3354
3355 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
3356
3097 //if (client != null) 3357 //if (client != null)
3098 //{ 3358 //{
3099 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName; 3359 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
@@ -3107,12 +3367,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3107 msg.message = message.Substring(0, 1024); 3367 msg.message = message.Substring(0, 1024);
3108 else 3368 else
3109 msg.message = message; 3369 msg.message = message;
3110 msg.dialog = (byte)19; // messgage from script ??? // dialog; 3370 msg.dialog = (byte)19; // MessageFromObject
3111 msg.fromGroup = false;// fromGroup; 3371 msg.fromGroup = false;// fromGroup;
3112 msg.offline = (byte)0; //offline; 3372 msg.offline = (byte)0; //offline;
3113 msg.ParentEstateID = 0; //ParentEstateID; 3373 msg.ParentEstateID = World.RegionInfo.EstateSettings.EstateID;
3114 msg.Position = new Vector3(m_host.AbsolutePosition); 3374 msg.Position = new Vector3(m_host.AbsolutePosition);
3115 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; 3375 msg.RegionID = World.RegionInfo.RegionID.Guid;
3116 msg.binaryBucket 3376 msg.binaryBucket
3117 = Util.StringToBytes256( 3377 = Util.StringToBytes256(
3118 "{0}/{1}/{2}/{3}", 3378 "{0}/{1}/{2}/{3}",
@@ -3140,7 +3400,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3140 } 3400 }
3141 3401
3142 emailModule.SendEmail(m_host.UUID, address, subject, message); 3402 emailModule.SendEmail(m_host.UUID, address, subject, message);
3143 ScriptSleep(20000); 3403 ScriptSleep(15000);
3144 } 3404 }
3145 3405
3146 public void llGetNextEmail(string address, string subject) 3406 public void llGetNextEmail(string address, string subject)
@@ -3279,14 +3539,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3279 3539
3280 TaskInventoryItem item; 3540 TaskInventoryItem item;
3281 3541
3282 lock (m_host.TaskInventory) 3542 m_host.TaskInventory.LockItemsForRead(true);
3543 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3283 { 3544 {
3284 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3545 m_host.TaskInventory.LockItemsForRead(false);
3285 return; 3546 return;
3286 else
3287 item = m_host.TaskInventory[InventorySelf()];
3288 } 3547 }
3289 3548 else
3549 {
3550 item = m_host.TaskInventory[InventorySelf()];
3551 }
3552 m_host.TaskInventory.LockItemsForRead(false);
3290 if (item.PermsGranter == UUID.Zero) 3553 if (item.PermsGranter == UUID.Zero)
3291 return; 3554 return;
3292 3555
@@ -3316,13 +3579,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3316 3579
3317 TaskInventoryItem item; 3580 TaskInventoryItem item;
3318 3581
3319 lock (m_host.TaskInventory) 3582 m_host.TaskInventory.LockItemsForRead(true);
3583 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3320 { 3584 {
3321 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3585 m_host.TaskInventory.LockItemsForRead(false);
3322 return; 3586 return;
3323 else 3587 }
3324 item = m_host.TaskInventory[InventorySelf()]; 3588 else
3589 {
3590 item = m_host.TaskInventory[InventorySelf()];
3325 } 3591 }
3592 m_host.TaskInventory.LockItemsForRead(false);
3593
3326 3594
3327 if (item.PermsGranter == UUID.Zero) 3595 if (item.PermsGranter == UUID.Zero)
3328 return; 3596 return;
@@ -3389,10 +3657,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3389 3657
3390 TaskInventoryItem item; 3658 TaskInventoryItem item;
3391 3659
3392 lock (m_host.TaskInventory) 3660
3661 m_host.TaskInventory.LockItemsForRead(true);
3662 if (!m_host.TaskInventory.ContainsKey(invItemID))
3663 {
3664 m_host.TaskInventory.LockItemsForRead(false);
3665 return;
3666 }
3667 else
3393 { 3668 {
3394 item = m_host.TaskInventory[invItemID]; 3669 item = m_host.TaskInventory[invItemID];
3395 } 3670 }
3671 m_host.TaskInventory.LockItemsForRead(false);
3396 3672
3397 if (agentID == UUID.Zero || perm == 0) // Releasing permissions 3673 if (agentID == UUID.Zero || perm == 0) // Releasing permissions
3398 { 3674 {
@@ -3420,15 +3696,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3420 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | 3696 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
3421 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3697 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3422 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3698 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3699 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3423 ScriptBaseClass.PERMISSION_ATTACH; 3700 ScriptBaseClass.PERMISSION_ATTACH;
3424 3701
3425 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3702 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3426 { 3703 {
3427 lock (m_host.TaskInventory) 3704 m_host.TaskInventory.LockItemsForWrite(true);
3428 { 3705 m_host.TaskInventory[invItemID].PermsGranter = agentID;
3429 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3706 m_host.TaskInventory[invItemID].PermsMask = perm;
3430 m_host.TaskInventory[invItemID].PermsMask = perm; 3707 m_host.TaskInventory.LockItemsForWrite(false);
3431 }
3432 3708
3433 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3709 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3434 "run_time_permissions", new Object[] { 3710 "run_time_permissions", new Object[] {
@@ -3438,28 +3714,44 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3438 return; 3714 return;
3439 } 3715 }
3440 } 3716 }
3441 else if (m_host.SitTargetAvatar == agentID) // Sitting avatar 3717 else
3442 { 3718 {
3443 // When agent is sitting, certain permissions are implicit if requested from sitting agent 3719 bool sitting = false;
3444 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3720 if (m_host.SitTargetAvatar == agentID)
3445 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3721 {
3446 ScriptBaseClass.PERMISSION_TRACK_CAMERA | 3722 sitting = true;
3447 ScriptBaseClass.PERMISSION_TAKE_CONTROLS; 3723 }
3724 else
3725 {
3726 foreach (SceneObjectPart p in m_host.ParentGroup.Parts)
3727 {
3728 if (p.SitTargetAvatar == agentID)
3729 sitting = true;
3730 }
3731 }
3448 3732
3449 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3733 if (sitting)
3450 { 3734 {
3451 lock (m_host.TaskInventory) 3735 // When agent is sitting, certain permissions are implicit if requested from sitting agent
3736 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3737 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3738 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3739 ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
3740
3741 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3452 { 3742 {
3743 m_host.TaskInventory.LockItemsForWrite(true);
3453 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3744 m_host.TaskInventory[invItemID].PermsGranter = agentID;
3454 m_host.TaskInventory[invItemID].PermsMask = perm; 3745 m_host.TaskInventory[invItemID].PermsMask = perm;
3455 } 3746 m_host.TaskInventory.LockItemsForWrite(false);
3456 3747
3457 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3748 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3458 "run_time_permissions", new Object[] { 3749 "run_time_permissions", new Object[] {
3459 new LSL_Integer(perm) }, 3750 new LSL_Integer(perm) },
3460 new DetectParams[0])); 3751 new DetectParams[0]));
3461 3752
3462 return; 3753 return;
3754 }
3463 } 3755 }
3464 } 3756 }
3465 3757
@@ -3473,11 +3765,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3473 3765
3474 if (!m_waitingForScriptAnswer) 3766 if (!m_waitingForScriptAnswer)
3475 { 3767 {
3476 lock (m_host.TaskInventory) 3768 m_host.TaskInventory.LockItemsForWrite(true);
3477 { 3769 m_host.TaskInventory[invItemID].PermsGranter = agentID;
3478 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3770 m_host.TaskInventory[invItemID].PermsMask = 0;
3479 m_host.TaskInventory[invItemID].PermsMask = 0; 3771 m_host.TaskInventory.LockItemsForWrite(false);
3480 }
3481 3772
3482 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; 3773 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
3483 m_waitingForScriptAnswer=true; 3774 m_waitingForScriptAnswer=true;
@@ -3512,10 +3803,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3512 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) 3803 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
3513 llReleaseControls(); 3804 llReleaseControls();
3514 3805
3515 lock (m_host.TaskInventory) 3806
3516 { 3807 m_host.TaskInventory.LockItemsForWrite(true);
3517 m_host.TaskInventory[invItemID].PermsMask = answer; 3808 m_host.TaskInventory[invItemID].PermsMask = answer;
3518 } 3809 m_host.TaskInventory.LockItemsForWrite(false);
3810
3519 3811
3520 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3812 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3521 "run_time_permissions", new Object[] { 3813 "run_time_permissions", new Object[] {
@@ -3527,16 +3819,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3527 { 3819 {
3528 m_host.AddScriptLPS(1); 3820 m_host.AddScriptLPS(1);
3529 3821
3530 lock (m_host.TaskInventory) 3822 m_host.TaskInventory.LockItemsForRead(true);
3823
3824 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3531 { 3825 {
3532 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 3826 if (item.Type == 10 && item.ItemID == m_itemID)
3533 { 3827 {
3534 if (item.Type == 10 && item.ItemID == m_itemID) 3828 m_host.TaskInventory.LockItemsForRead(false);
3535 { 3829 return item.PermsGranter.ToString();
3536 return item.PermsGranter.ToString();
3537 }
3538 } 3830 }
3539 } 3831 }
3832 m_host.TaskInventory.LockItemsForRead(false);
3540 3833
3541 return UUID.Zero.ToString(); 3834 return UUID.Zero.ToString();
3542 } 3835 }
@@ -3545,19 +3838,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3545 { 3838 {
3546 m_host.AddScriptLPS(1); 3839 m_host.AddScriptLPS(1);
3547 3840
3548 lock (m_host.TaskInventory) 3841 m_host.TaskInventory.LockItemsForRead(true);
3842
3843 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3549 { 3844 {
3550 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 3845 if (item.Type == 10 && item.ItemID == m_itemID)
3551 { 3846 {
3552 if (item.Type == 10 && item.ItemID == m_itemID) 3847 int perms = item.PermsMask;
3553 { 3848 if (m_automaticLinkPermission)
3554 int perms = item.PermsMask; 3849 perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS;
3555 if (m_automaticLinkPermission) 3850 m_host.TaskInventory.LockItemsForRead(false);
3556 perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS; 3851 return perms;
3557 return perms;
3558 }
3559 } 3852 }
3560 } 3853 }
3854 m_host.TaskInventory.LockItemsForRead(false);
3561 3855
3562 return 0; 3856 return 0;
3563 } 3857 }
@@ -3579,9 +3873,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3579 public void llSetLinkColor(int linknumber, LSL_Vector color, int face) 3873 public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
3580 { 3874 {
3581 List<SceneObjectPart> parts = GetLinkParts(linknumber); 3875 List<SceneObjectPart> parts = GetLinkParts(linknumber);
3582 3876 if (parts.Count > 0)
3583 foreach (SceneObjectPart part in parts) 3877 {
3584 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); 3878 try
3879 {
3880 parts[0].ParentGroup.areUpdatesSuspended = true;
3881 foreach (SceneObjectPart part in parts)
3882 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face);
3883 }
3884 finally
3885 {
3886 parts[0].ParentGroup.areUpdatesSuspended = false;
3887 }
3888 }
3585 } 3889 }
3586 3890
3587 public void llCreateLink(string target, int parent) 3891 public void llCreateLink(string target, int parent)
@@ -3594,11 +3898,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3594 return; 3898 return;
3595 3899
3596 TaskInventoryItem item; 3900 TaskInventoryItem item;
3597 lock (m_host.TaskInventory) 3901 m_host.TaskInventory.LockItemsForRead(true);
3598 { 3902 item = m_host.TaskInventory[invItemID];
3599 item = m_host.TaskInventory[invItemID]; 3903 m_host.TaskInventory.LockItemsForRead(false);
3600 } 3904
3601
3602 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 3905 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
3603 && !m_automaticLinkPermission) 3906 && !m_automaticLinkPermission)
3604 { 3907 {
@@ -3615,11 +3918,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3615 3918
3616 if (targetPart.ParentGroup.AttachmentPoint != 0) 3919 if (targetPart.ParentGroup.AttachmentPoint != 0)
3617 return; // Fail silently if attached 3920 return; // Fail silently if attached
3921
3922 if (targetPart.ParentGroup.RootPart.OwnerID != m_host.ParentGroup.RootPart.OwnerID)
3923 return;
3924
3618 SceneObjectGroup parentPrim = null, childPrim = null; 3925 SceneObjectGroup parentPrim = null, childPrim = null;
3619 3926
3620 if (targetPart != null) 3927 if (targetPart != null)
3621 { 3928 {
3622 if (parent != 0) { 3929 if (parent != 0)
3930 {
3623 parentPrim = m_host.ParentGroup; 3931 parentPrim = m_host.ParentGroup;
3624 childPrim = targetPart.ParentGroup; 3932 childPrim = targetPart.ParentGroup;
3625 } 3933 }
@@ -3631,7 +3939,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3631 3939
3632 // Required for linking 3940 // Required for linking
3633 childPrim.RootPart.ClearUpdateSchedule(); 3941 childPrim.RootPart.ClearUpdateSchedule();
3634 parentPrim.LinkToGroup(childPrim); 3942 parentPrim.LinkToGroup(childPrim, true);
3635 } 3943 }
3636 3944
3637 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 3945 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
@@ -3650,16 +3958,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3650 m_host.AddScriptLPS(1); 3958 m_host.AddScriptLPS(1);
3651 UUID invItemID = InventorySelf(); 3959 UUID invItemID = InventorySelf();
3652 3960
3653 lock (m_host.TaskInventory) 3961 m_host.TaskInventory.LockItemsForRead(true);
3654 {
3655 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 3962 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
3656 && !m_automaticLinkPermission) 3963 && !m_automaticLinkPermission)
3657 { 3964 {
3658 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!"); 3965 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
3966 m_host.TaskInventory.LockItemsForRead(false);
3659 return; 3967 return;
3660 } 3968 }
3661 } 3969 m_host.TaskInventory.LockItemsForRead(false);
3662 3970
3663 if (linknum < ScriptBaseClass.LINK_THIS) 3971 if (linknum < ScriptBaseClass.LINK_THIS)
3664 return; 3972 return;
3665 3973
@@ -3698,10 +4006,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3698 // Restructuring Multiple Prims. 4006 // Restructuring Multiple Prims.
3699 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts); 4007 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
3700 parts.Remove(parentPrim.RootPart); 4008 parts.Remove(parentPrim.RootPart);
3701 foreach (SceneObjectPart part in parts) 4009 if (parts.Count > 0)
3702 { 4010 {
3703 parentPrim.DelinkFromGroup(part.LocalId, true); 4011 try
4012 {
4013 parts[0].ParentGroup.areUpdatesSuspended = true;
4014 foreach (SceneObjectPart part in parts)
4015 {
4016 parentPrim.DelinkFromGroup(part.LocalId, true);
4017 }
4018 }
4019 finally
4020 {
4021 parts[0].ParentGroup.areUpdatesSuspended = false;
4022 }
3704 } 4023 }
4024
3705 parentPrim.HasGroupChanged = true; 4025 parentPrim.HasGroupChanged = true;
3706 parentPrim.ScheduleGroupForFullUpdate(); 4026 parentPrim.ScheduleGroupForFullUpdate();
3707 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 4027 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
@@ -3710,12 +4030,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3710 { 4030 {
3711 SceneObjectPart newRoot = parts[0]; 4031 SceneObjectPart newRoot = parts[0];
3712 parts.Remove(newRoot); 4032 parts.Remove(newRoot);
3713 foreach (SceneObjectPart part in parts) 4033
4034 try
3714 { 4035 {
3715 // Required for linking 4036 parts[0].ParentGroup.areUpdatesSuspended = true;
3716 part.ClearUpdateSchedule(); 4037 foreach (SceneObjectPart part in parts)
3717 newRoot.ParentGroup.LinkToGroup(part.ParentGroup); 4038 {
4039 part.ClearUpdateSchedule();
4040 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
4041 }
3718 } 4042 }
4043 finally
4044 {
4045 parts[0].ParentGroup.areUpdatesSuspended = false;
4046 }
4047
4048
3719 newRoot.ParentGroup.HasGroupChanged = true; 4049 newRoot.ParentGroup.HasGroupChanged = true;
3720 newRoot.ParentGroup.ScheduleGroupForFullUpdate(); 4050 newRoot.ParentGroup.ScheduleGroupForFullUpdate();
3721 } 4051 }
@@ -3735,6 +4065,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3735 public void llBreakAllLinks() 4065 public void llBreakAllLinks()
3736 { 4066 {
3737 m_host.AddScriptLPS(1); 4067 m_host.AddScriptLPS(1);
4068
4069 UUID invItemID = InventorySelf();
4070
4071 TaskInventoryItem item;
4072 m_host.TaskInventory.LockItemsForRead(true);
4073 item = m_host.TaskInventory[invItemID];
4074 m_host.TaskInventory.LockItemsForRead(false);
4075
4076 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4077 && !m_automaticLinkPermission)
4078 {
4079 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
4080 return;
4081 }
4082
3738 SceneObjectGroup parentPrim = m_host.ParentGroup; 4083 SceneObjectGroup parentPrim = m_host.ParentGroup;
3739 if (parentPrim.AttachmentPoint != 0) 4084 if (parentPrim.AttachmentPoint != 0)
3740 return; // Fail silently if attached 4085 return; // Fail silently if attached
@@ -3754,25 +4099,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3754 public LSL_String llGetLinkKey(int linknum) 4099 public LSL_String llGetLinkKey(int linknum)
3755 { 4100 {
3756 m_host.AddScriptLPS(1); 4101 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); 4102 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
3777 if (part != null) 4103 if (part != null)
3778 { 4104 {
@@ -3780,6 +4106,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3780 } 4106 }
3781 else 4107 else
3782 { 4108 {
4109 if (linknum > m_host.ParentGroup.PrimCount || (linknum == 1 && m_host.ParentGroup.PrimCount == 1))
4110 {
4111 linknum -= (m_host.ParentGroup.PrimCount) + 1;
4112
4113 if (linknum < 0)
4114 return UUID.Zero.ToString();
4115
4116 List<ScenePresence> avatars = GetLinkAvatars(ScriptBaseClass.LINK_SET);
4117 if (avatars.Count > linknum)
4118 {
4119 return avatars[linknum].UUID.ToString();
4120 }
4121 }
3783 return UUID.Zero.ToString(); 4122 return UUID.Zero.ToString();
3784 } 4123 }
3785 } 4124 }
@@ -3878,17 +4217,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3878 m_host.AddScriptLPS(1); 4217 m_host.AddScriptLPS(1);
3879 int count = 0; 4218 int count = 0;
3880 4219
3881 lock (m_host.TaskInventory) 4220 m_host.TaskInventory.LockItemsForRead(true);
4221 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3882 { 4222 {
3883 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4223 if (inv.Value.Type == type || type == -1)
3884 { 4224 {
3885 if (inv.Value.Type == type || type == -1) 4225 count = count + 1;
3886 {
3887 count = count + 1;
3888 }
3889 } 4226 }
3890 } 4227 }
3891 4228
4229 m_host.TaskInventory.LockItemsForRead(false);
3892 return count; 4230 return count;
3893 } 4231 }
3894 4232
@@ -3897,16 +4235,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3897 m_host.AddScriptLPS(1); 4235 m_host.AddScriptLPS(1);
3898 ArrayList keys = new ArrayList(); 4236 ArrayList keys = new ArrayList();
3899 4237
3900 lock (m_host.TaskInventory) 4238 m_host.TaskInventory.LockItemsForRead(true);
4239 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3901 { 4240 {
3902 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4241 if (inv.Value.Type == type || type == -1)
3903 { 4242 {
3904 if (inv.Value.Type == type || type == -1) 4243 keys.Add(inv.Value.Name);
3905 {
3906 keys.Add(inv.Value.Name);
3907 }
3908 } 4244 }
3909 } 4245 }
4246 m_host.TaskInventory.LockItemsForRead(false);
3910 4247
3911 if (keys.Count == 0) 4248 if (keys.Count == 0)
3912 { 4249 {
@@ -3943,25 +4280,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3943 } 4280 }
3944 4281
3945 // move the first object found with this inventory name 4282 // move the first object found with this inventory name
3946 lock (m_host.TaskInventory) 4283 m_host.TaskInventory.LockItemsForRead(true);
4284 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3947 { 4285 {
3948 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4286 if (inv.Value.Name == inventory)
3949 { 4287 {
3950 if (inv.Value.Name == inventory) 4288 found = true;
3951 { 4289 objId = inv.Key;
3952 found = true; 4290 assetType = inv.Value.Type;
3953 objId = inv.Key; 4291 objName = inv.Value.Name;
3954 assetType = inv.Value.Type; 4292 break;
3955 objName = inv.Value.Name;
3956 break;
3957 }
3958 } 4293 }
3959 } 4294 }
4295 m_host.TaskInventory.LockItemsForRead(false);
3960 4296
3961 if (!found) 4297 if (!found)
3962 { 4298 {
3963 llSay(0, String.Format("Could not find object '{0}'", inventory)); 4299 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)); 4300 return;
4301// throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
3965 } 4302 }
3966 4303
3967 // check if destination is an object 4304 // check if destination is an object
@@ -3987,48 +4324,68 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3987 return; 4324 return;
3988 } 4325 }
3989 } 4326 }
4327
3990 // destination is an avatar 4328 // destination is an avatar
3991 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId); 4329 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId);
3992 4330
3993 if (agentItem == null) 4331 if (agentItem == null)
3994 return; 4332 return;
3995 4333
3996 byte[] bucket = new byte[17]; 4334 byte[] bucket = new byte[1];
3997 bucket[0] = (byte)assetType; 4335 bucket[0] = (byte)assetType;
3998 byte[] objBytes = agentItem.ID.GetBytes(); 4336 //byte[] objBytes = agentItem.ID.GetBytes();
3999 Array.Copy(objBytes, 0, bucket, 1, 16); 4337 //Array.Copy(objBytes, 0, bucket, 1, 16);
4000 4338
4001 GridInstantMessage msg = new GridInstantMessage(World, 4339 GridInstantMessage msg = new GridInstantMessage(World,
4002 m_host.UUID, m_host.Name+", an object owned by "+ 4340 m_host.OwnerID, m_host.Name, destId,
4003 resolveName(m_host.OwnerID)+",", destId,
4004 (byte)InstantMessageDialog.TaskInventoryOffered, 4341 (byte)InstantMessageDialog.TaskInventoryOffered,
4005 false, objName+"\n"+m_host.Name+" is located at "+ 4342 false, objName+". "+m_host.Name+" is located at "+
4006 World.RegionInfo.RegionName+" "+ 4343 World.RegionInfo.RegionName+" "+
4007 m_host.AbsolutePosition.ToString(), 4344 m_host.AbsolutePosition.ToString(),
4008 agentItem.ID, true, m_host.AbsolutePosition, 4345 agentItem.ID, true, m_host.AbsolutePosition,
4009 bucket); 4346 bucket);
4010 if (m_TransferModule != null) 4347
4011 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 4348 ScenePresence sp;
4349
4350 if (World.TryGetScenePresence(destId, out sp))
4351 {
4352 sp.ControllingClient.SendInstantMessage(msg);
4353 }
4354 else
4355 {
4356 if (m_TransferModule != null)
4357 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
4358 }
4359
4360 //This delay should only occur when giving inventory to avatars.
4012 ScriptSleep(3000); 4361 ScriptSleep(3000);
4013 } 4362 }
4014 } 4363 }
4015 4364
4365 [DebuggerNonUserCode]
4016 public void llRemoveInventory(string name) 4366 public void llRemoveInventory(string name)
4017 { 4367 {
4018 m_host.AddScriptLPS(1); 4368 m_host.AddScriptLPS(1);
4019 4369
4020 lock (m_host.TaskInventory) 4370 List<TaskInventoryItem> inv;
4371 try
4021 { 4372 {
4022 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4373 m_host.TaskInventory.LockItemsForRead(true);
4374 inv = new List<TaskInventoryItem>(m_host.TaskInventory.Values);
4375 }
4376 finally
4377 {
4378 m_host.TaskInventory.LockItemsForRead(false);
4379 }
4380 foreach (TaskInventoryItem item in inv)
4381 {
4382 if (item.Name == name)
4023 { 4383 {
4024 if (item.Name == name) 4384 if (item.ItemID == m_itemID)
4025 { 4385 throw new ScriptDeleteException();
4026 if (item.ItemID == m_itemID) 4386 else
4027 throw new ScriptDeleteException(); 4387 m_host.Inventory.RemoveInventoryItem(item.ItemID);
4028 else 4388 return;
4029 m_host.Inventory.RemoveInventoryItem(item.ItemID);
4030 return;
4031 }
4032 } 4389 }
4033 } 4390 }
4034 } 4391 }
@@ -4063,112 +4420,122 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4063 { 4420 {
4064 m_host.AddScriptLPS(1); 4421 m_host.AddScriptLPS(1);
4065 4422
4066 UUID uuid = (UUID)id; 4423 UUID uuid;
4067 PresenceInfo pinfo = null; 4424 if (UUID.TryParse(id, out uuid))
4068 UserAccount account;
4069
4070 UserInfoCacheEntry ce;
4071 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4072 { 4425 {
4073 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); 4426 PresenceInfo pinfo = null;
4074 if (account == null) 4427 UserAccount account;
4428
4429 UserInfoCacheEntry ce;
4430 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4075 { 4431 {
4076 m_userInfoCache[uuid] = null; // Cache negative 4432 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
4077 return UUID.Zero.ToString(); 4433 if (account == null)
4078 } 4434 {
4435 m_userInfoCache[uuid] = null; // Cache negative
4436 return UUID.Zero.ToString();
4437 }
4079 4438
4080 4439
4081 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); 4440 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4082 if (pinfos != null && pinfos.Length > 0) 4441 if (pinfos != null && pinfos.Length > 0)
4083 {
4084 foreach (PresenceInfo p in pinfos)
4085 { 4442 {
4086 if (p.RegionID != UUID.Zero) 4443 foreach (PresenceInfo p in pinfos)
4087 { 4444 {
4088 pinfo = p; 4445 if (p.RegionID != UUID.Zero)
4446 {
4447 pinfo = p;
4448 }
4089 } 4449 }
4090 } 4450 }
4091 }
4092 4451
4093 ce = new UserInfoCacheEntry(); 4452 ce = new UserInfoCacheEntry();
4094 ce.time = Util.EnvironmentTickCount(); 4453 ce.time = Util.EnvironmentTickCount();
4095 ce.account = account; 4454 ce.account = account;
4096 ce.pinfo = pinfo; 4455 ce.pinfo = pinfo;
4097 } 4456 m_userInfoCache[uuid] = ce;
4098 else 4457 }
4099 { 4458 else
4100 if (ce == null) 4459 {
4101 return UUID.Zero.ToString(); 4460 if (ce == null)
4461 return UUID.Zero.ToString();
4102 4462
4103 account = ce.account; 4463 account = ce.account;
4104 pinfo = ce.pinfo; 4464 pinfo = ce.pinfo;
4105 } 4465 }
4106 4466
4107 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000) 4467 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 { 4468 {
4112 foreach (PresenceInfo p in pinfos) 4469 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4470 if (pinfos != null && pinfos.Length > 0)
4113 { 4471 {
4114 if (p.RegionID != UUID.Zero) 4472 foreach (PresenceInfo p in pinfos)
4115 { 4473 {
4116 pinfo = p; 4474 if (p.RegionID != UUID.Zero)
4475 {
4476 pinfo = p;
4477 }
4117 } 4478 }
4118 } 4479 }
4119 } 4480 else
4120 else 4481 pinfo = null;
4121 pinfo = null;
4122 4482
4123 ce.time = Util.EnvironmentTickCount(); 4483 ce.time = Util.EnvironmentTickCount();
4124 ce.pinfo = pinfo; 4484 ce.pinfo = pinfo;
4125 } 4485 }
4126 4486
4127 string reply = String.Empty; 4487 string reply = String.Empty;
4128 4488
4129 switch (data) 4489 switch (data)
4130 { 4490 {
4131 case 1: // DATA_ONLINE (0|1) 4491 case 1: // DATA_ONLINE (0|1)
4132 if (pinfo != null && pinfo.RegionID != UUID.Zero) 4492 if (pinfo != null && pinfo.RegionID != UUID.Zero)
4133 reply = "1"; 4493 reply = "1";
4134 else 4494 else
4135 reply = "0"; 4495 reply = "0";
4136 break; 4496 break;
4137 case 2: // DATA_NAME (First Last) 4497 case 2: // DATA_NAME (First Last)
4138 reply = account.FirstName + " " + account.LastName; 4498 reply = account.FirstName + " " + account.LastName;
4139 break; 4499 break;
4140 case 3: // DATA_BORN (YYYY-MM-DD) 4500 case 3: // DATA_BORN (YYYY-MM-DD)
4141 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); 4501 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
4142 born = born.AddSeconds(account.Created); 4502 born = born.AddSeconds(account.Created);
4143 reply = born.ToString("yyyy-MM-dd"); 4503 reply = born.ToString("yyyy-MM-dd");
4144 break; 4504 break;
4145 case 4: // DATA_RATING (0,0,0,0,0,0) 4505 case 4: // DATA_RATING (0,0,0,0,0,0)
4146 reply = "0,0,0,0,0,0"; 4506 reply = "0,0,0,0,0,0";
4147 break; 4507 break;
4148 case 8: // DATA_PAYINFO (0|1|2|3) 4508 case 8: // DATA_PAYINFO (0|1|2|3)
4149 reply = "0"; 4509 reply = "0";
4150 break; 4510 break;
4151 default: 4511 default:
4152 return UUID.Zero.ToString(); // Raise no event 4512 return UUID.Zero.ToString(); // Raise no event
4153 } 4513 }
4154 4514
4155 UUID rq = UUID.Random(); 4515 UUID rq = UUID.Random();
4156 4516
4157 UUID tid = AsyncCommands. 4517 UUID tid = AsyncCommands.
4158 DataserverPlugin.RegisterRequest(m_localID, 4518 DataserverPlugin.RegisterRequest(m_localID,
4159 m_itemID, rq.ToString()); 4519 m_itemID, rq.ToString());
4160 4520
4161 AsyncCommands. 4521 AsyncCommands.
4162 DataserverPlugin.DataserverReply(rq.ToString(), reply); 4522 DataserverPlugin.DataserverReply(rq.ToString(), reply);
4163 4523
4164 ScriptSleep(100); 4524 ScriptSleep(100);
4165 return tid.ToString(); 4525 return tid.ToString();
4526 }
4527 else
4528 {
4529 ShoutError("Invalid UUID passed to llRequestAgentData.");
4530 }
4531 return "";
4166 } 4532 }
4167 4533
4168 public LSL_String llRequestInventoryData(string name) 4534 public LSL_String llRequestInventoryData(string name)
4169 { 4535 {
4170 m_host.AddScriptLPS(1); 4536 m_host.AddScriptLPS(1);
4171 4537
4538 //Clone is thread safe
4172 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 4539 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
4173 4540
4174 foreach (TaskInventoryItem item in itemDictionary.Values) 4541 foreach (TaskInventoryItem item in itemDictionary.Values)
@@ -4222,6 +4589,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4222 ScenePresence presence = World.GetScenePresence(agentId); 4589 ScenePresence presence = World.GetScenePresence(agentId);
4223 if (presence != null) 4590 if (presence != null)
4224 { 4591 {
4592 // agent must not be a god
4593 if (presence.UserLevel >= 200) return;
4594
4225 // agent must be over the owners land 4595 // agent must be over the owners land
4226 if (m_host.OwnerID == World.LandChannel.GetLandObject( 4596 if (m_host.OwnerID == World.LandChannel.GetLandObject(
4227 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) 4597 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
@@ -4244,7 +4614,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4244 UUID av = new UUID(); 4614 UUID av = new UUID();
4245 if (!UUID.TryParse(agent,out av)) 4615 if (!UUID.TryParse(agent,out av))
4246 { 4616 {
4247 LSLError("First parameter to llDialog needs to be a key"); 4617 //LSLError("First parameter to llDialog needs to be a key");
4248 return; 4618 return;
4249 } 4619 }
4250 4620
@@ -4281,17 +4651,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4281 UUID soundId = UUID.Zero; 4651 UUID soundId = UUID.Zero;
4282 if (!UUID.TryParse(impact_sound, out soundId)) 4652 if (!UUID.TryParse(impact_sound, out soundId))
4283 { 4653 {
4284 lock (m_host.TaskInventory) 4654 m_host.TaskInventory.LockItemsForRead(true);
4655 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
4285 { 4656 {
4286 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4657 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound)
4287 { 4658 {
4288 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound) 4659 soundId = item.AssetID;
4289 { 4660 break;
4290 soundId = item.AssetID;
4291 break;
4292 }
4293 } 4661 }
4294 } 4662 }
4663 m_host.TaskInventory.LockItemsForRead(false);
4295 } 4664 }
4296 m_host.CollisionSound = soundId; 4665 m_host.CollisionSound = soundId;
4297 m_host.CollisionSoundVolume = (float)impact_volume; 4666 m_host.CollisionSoundVolume = (float)impact_volume;
@@ -4331,6 +4700,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4331 UUID partItemID; 4700 UUID partItemID;
4332 foreach (SceneObjectPart part in parts) 4701 foreach (SceneObjectPart part in parts)
4333 { 4702 {
4703 //Clone is thread safe
4334 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); 4704 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
4335 4705
4336 foreach (TaskInventoryItem item in itemsDictionary.Values) 4706 foreach (TaskInventoryItem item in itemsDictionary.Values)
@@ -4545,17 +4915,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4545 4915
4546 m_host.AddScriptLPS(1); 4916 m_host.AddScriptLPS(1);
4547 4917
4548 lock (m_host.TaskInventory) 4918 m_host.TaskInventory.LockItemsForRead(true);
4919 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
4549 { 4920 {
4550 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4921 if (item.Type == 10 && item.ItemID == m_itemID)
4551 { 4922 {
4552 if (item.Type == 10 && item.ItemID == m_itemID) 4923 result = item.Name!=null?item.Name:String.Empty;
4553 { 4924 break;
4554 result = item.Name != null ? item.Name : String.Empty;
4555 break;
4556 }
4557 } 4925 }
4558 } 4926 }
4927 m_host.TaskInventory.LockItemsForRead(false);
4559 4928
4560 return result; 4929 return result;
4561 } 4930 }
@@ -4728,23 +5097,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4728 { 5097 {
4729 m_host.AddScriptLPS(1); 5098 m_host.AddScriptLPS(1);
4730 5099
4731 lock (m_host.TaskInventory) 5100 m_host.TaskInventory.LockItemsForRead(true);
5101 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
4732 { 5102 {
4733 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 5103 if (inv.Value.Name == name)
4734 { 5104 {
4735 if (inv.Value.Name == name) 5105 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
4736 { 5106 {
4737 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) 5107 m_host.TaskInventory.LockItemsForRead(false);
4738 { 5108 return inv.Value.AssetID.ToString();
4739 return inv.Value.AssetID.ToString(); 5109 }
4740 } 5110 else
4741 else 5111 {
4742 { 5112 m_host.TaskInventory.LockItemsForRead(false);
4743 return UUID.Zero.ToString(); 5113 return UUID.Zero.ToString();
4744 }
4745 } 5114 }
4746 } 5115 }
4747 } 5116 }
5117 m_host.TaskInventory.LockItemsForRead(false);
4748 5118
4749 return UUID.Zero.ToString(); 5119 return UUID.Zero.ToString();
4750 } 5120 }
@@ -4897,14 +5267,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4897 { 5267 {
4898 m_host.AddScriptLPS(1); 5268 m_host.AddScriptLPS(1);
4899 5269
4900 if (src == null) 5270 return src.Length;
4901 {
4902 return 0;
4903 }
4904 else
4905 {
4906 return src.Length;
4907 }
4908 } 5271 }
4909 5272
4910 public LSL_Integer llList2Integer(LSL_List src, int index) 5273 public LSL_Integer llList2Integer(LSL_List src, int index)
@@ -4950,7 +5313,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4950 else if (src.Data[index] is LSL_Float) 5313 else if (src.Data[index] is LSL_Float)
4951 return Convert.ToDouble(((LSL_Float) src.Data[index]).value); 5314 return Convert.ToDouble(((LSL_Float) src.Data[index]).value);
4952 else if (src.Data[index] is LSL_String) 5315 else if (src.Data[index] is LSL_String)
4953 return Convert.ToDouble(((LSL_String) src.Data[index]).m_string); 5316 {
5317 string str = ((LSL_String) src.Data[index]).m_string;
5318 Match m = Regex.Match(str, "^\\s*(-?\\+?[,0-9]+\\.?[0-9]*)");
5319 if (m != Match.Empty)
5320 {
5321 str = m.Value;
5322 double d = 0.0;
5323 if (!Double.TryParse(str, out d))
5324 return 0.0;
5325
5326 return d;
5327 }
5328 return 0.0;
5329 }
4954 return Convert.ToDouble(src.Data[index]); 5330 return Convert.ToDouble(src.Data[index]);
4955 } 5331 }
4956 catch (FormatException) 5332 catch (FormatException)
@@ -5223,7 +5599,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5223 } 5599 }
5224 } 5600 }
5225 } 5601 }
5226 else { 5602 else
5603 {
5227 object[] array = new object[src.Length]; 5604 object[] array = new object[src.Length];
5228 Array.Copy(src.Data, 0, array, 0, src.Length); 5605 Array.Copy(src.Data, 0, array, 0, src.Length);
5229 result = new LSL_List(array); 5606 result = new LSL_List(array);
@@ -5672,10 +6049,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5672 m_host.AddScriptLPS(1); 6049 m_host.AddScriptLPS(1);
5673 6050
5674 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6051 List<SceneObjectPart> parts = GetLinkParts(linknumber);
5675 6052 if (parts.Count > 0)
5676 foreach (var part in parts)
5677 { 6053 {
5678 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); 6054 try
6055 {
6056 parts[0].ParentGroup.areUpdatesSuspended = true;
6057 foreach (var part in parts)
6058 {
6059 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6060 }
6061 }
6062 finally
6063 {
6064 parts[0].ParentGroup.areUpdatesSuspended = false;
6065 }
5679 } 6066 }
5680 } 6067 }
5681 6068
@@ -5727,13 +6114,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5727 6114
5728 if (m_host.OwnerID == land.LandData.OwnerID) 6115 if (m_host.OwnerID == land.LandData.OwnerID)
5729 { 6116 {
5730 World.TeleportClientHome(agentID, presence.ControllingClient); 6117 Vector3 pos = World.GetNearestAllowedPosition(presence, land);
6118 presence.TeleportWithMomentum(pos);
6119 presence.ControllingClient.SendAlertMessage("You have been ejected from this land");
5731 } 6120 }
5732 } 6121 }
5733 } 6122 }
5734 ScriptSleep(5000); 6123 ScriptSleep(5000);
5735 } 6124 }
5736 6125
6126 public LSL_List llParseString2List(string str, LSL_List separators, LSL_List in_spacers)
6127 {
6128 return ParseString2List(str, separators, in_spacers, false);
6129 }
6130
5737 public LSL_Integer llOverMyLand(string id) 6131 public LSL_Integer llOverMyLand(string id)
5738 { 6132 {
5739 m_host.AddScriptLPS(1); 6133 m_host.AddScriptLPS(1);
@@ -5798,8 +6192,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5798 UUID agentId = new UUID(); 6192 UUID agentId = new UUID();
5799 if (!UUID.TryParse(agent, out agentId)) 6193 if (!UUID.TryParse(agent, out agentId))
5800 return new LSL_Integer(0); 6194 return new LSL_Integer(0);
6195 if (agentId == m_host.GroupID)
6196 return new LSL_Integer(1);
5801 ScenePresence presence = World.GetScenePresence(agentId); 6197 ScenePresence presence = World.GetScenePresence(agentId);
5802 if (presence == null || presence.IsChildAgent) // Return flase for child agents 6198 if (presence == null || presence.IsChildAgent) // Return false for child agents
5803 return new LSL_Integer(0); 6199 return new LSL_Integer(0);
5804 IClientAPI client = presence.ControllingClient; 6200 IClientAPI client = presence.ControllingClient;
5805 if (m_host.GroupID == client.ActiveGroupId) 6201 if (m_host.GroupID == client.ActiveGroupId)
@@ -5934,7 +6330,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5934 return m_host.ParentGroup.AttachmentPoint; 6330 return m_host.ParentGroup.AttachmentPoint;
5935 } 6331 }
5936 6332
5937 public LSL_Integer llGetFreeMemory() 6333 public virtual LSL_Integer llGetFreeMemory()
5938 { 6334 {
5939 m_host.AddScriptLPS(1); 6335 m_host.AddScriptLPS(1);
5940 // Make scripts designed for LSO happy 6336 // Make scripts designed for LSO happy
@@ -6051,7 +6447,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6051 SetParticleSystem(m_host, rules); 6447 SetParticleSystem(m_host, rules);
6052 } 6448 }
6053 6449
6054 private void SetParticleSystem(SceneObjectPart part, LSL_List rules) { 6450 private void SetParticleSystem(SceneObjectPart part, LSL_List rules)
6451 {
6055 6452
6056 6453
6057 if (rules.Length == 0) 6454 if (rules.Length == 0)
@@ -6245,14 +6642,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6245 6642
6246 protected UUID GetTaskInventoryItem(string name) 6643 protected UUID GetTaskInventoryItem(string name)
6247 { 6644 {
6248 lock (m_host.TaskInventory) 6645 m_host.TaskInventory.LockItemsForRead(true);
6646 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6249 { 6647 {
6250 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 6648 if (inv.Value.Name == name)
6251 { 6649 {
6252 if (inv.Value.Name == name) 6650 m_host.TaskInventory.LockItemsForRead(false);
6253 return inv.Key; 6651 return inv.Key;
6254 } 6652 }
6255 } 6653 }
6654 m_host.TaskInventory.LockItemsForRead(false);
6256 6655
6257 return UUID.Zero; 6656 return UUID.Zero;
6258 } 6657 }
@@ -6290,16 +6689,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6290 if (folderID == UUID.Zero) 6689 if (folderID == UUID.Zero)
6291 return; 6690 return;
6292 6691
6293 byte[] bucket = new byte[17]; 6692 byte[] bucket = new byte[1];
6294 bucket[0] = (byte)AssetType.Folder; 6693 bucket[0] = (byte)AssetType.Folder;
6295 byte[] objBytes = folderID.GetBytes(); 6694 //byte[] objBytes = folderID.GetBytes();
6296 Array.Copy(objBytes, 0, bucket, 1, 16); 6695 //Array.Copy(objBytes, 0, bucket, 1, 16);
6297 6696
6298 GridInstantMessage msg = new GridInstantMessage(World, 6697 GridInstantMessage msg = new GridInstantMessage(World,
6299 m_host.UUID, m_host.Name+", an object owned by "+ 6698 m_host.OwnerID, m_host.Name, destID,
6300 resolveName(m_host.OwnerID)+",", destID, 6699 (byte)InstantMessageDialog.TaskInventoryOffered,
6301 (byte)InstantMessageDialog.InventoryOffered, 6700 false, category+". "+m_host.Name+" is located at "+
6302 false, category+"\n"+m_host.Name+" is located at "+
6303 World.RegionInfo.RegionName+" "+ 6701 World.RegionInfo.RegionName+" "+
6304 m_host.AbsolutePosition.ToString(), 6702 m_host.AbsolutePosition.ToString(),
6305 folderID, true, m_host.AbsolutePosition, 6703 folderID, true, m_host.AbsolutePosition,
@@ -6515,13 +6913,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6515 UUID av = new UUID(); 6913 UUID av = new UUID();
6516 if (!UUID.TryParse(avatar,out av)) 6914 if (!UUID.TryParse(avatar,out av))
6517 { 6915 {
6518 LSLError("First parameter to llDialog needs to be a key"); 6916 //LSLError("First parameter to llDialog needs to be a key");
6519 return; 6917 return;
6520 } 6918 }
6521 if (buttons.Length < 1) 6919 if (buttons.Length < 1)
6522 { 6920 {
6523 LSLError("No less than 1 button can be shown"); 6921 buttons.Add("OK");
6524 return;
6525 } 6922 }
6526 if (buttons.Length > 12) 6923 if (buttons.Length > 12)
6527 { 6924 {
@@ -6538,7 +6935,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6538 } 6935 }
6539 if (buttons.Data[i].ToString().Length > 24) 6936 if (buttons.Data[i].ToString().Length > 24)
6540 { 6937 {
6541 LSLError("button label cannot be longer than 24 characters"); 6938 llWhisper(ScriptBaseClass.DEBUG_CHANNEL, "button label cannot be longer than 24 characters");
6542 return; 6939 return;
6543 } 6940 }
6544 buts[i] = buttons.Data[i].ToString(); 6941 buts[i] = buttons.Data[i].ToString();
@@ -6597,22 +6994,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6597 } 6994 }
6598 6995
6599 // copy the first script found with this inventory name 6996 // copy the first script found with this inventory name
6600 lock (m_host.TaskInventory) 6997 TaskInventoryItem scriptItem = null;
6998 m_host.TaskInventory.LockItemsForRead(true);
6999 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6601 { 7000 {
6602 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 7001 if (inv.Value.Name == name)
6603 { 7002 {
6604 if (inv.Value.Name == name) 7003 // make sure the object is a script
7004 if (10 == inv.Value.Type)
6605 { 7005 {
6606 // make sure the object is a script 7006 found = true;
6607 if (10 == inv.Value.Type) 7007 srcId = inv.Key;
6608 { 7008 scriptItem = inv.Value;
6609 found = true; 7009 break;
6610 srcId = inv.Key;
6611 break;
6612 }
6613 } 7010 }
6614 } 7011 }
6615 } 7012 }
7013 m_host.TaskInventory.LockItemsForRead(false);
6616 7014
6617 if (!found) 7015 if (!found)
6618 { 7016 {
@@ -6620,9 +7018,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6620 return; 7018 return;
6621 } 7019 }
6622 7020
6623 // the rest of the permission checks are done in RezScript, so check the pin there as well 7021 SceneObjectPart dest = World.GetSceneObjectPart(destId);
6624 World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param); 7022 if (dest != null)
7023 {
7024 if ((scriptItem.BasePermissions & (uint)PermissionMask.Transfer) != 0 || dest.ParentGroup.RootPart.OwnerID == m_host.ParentGroup.RootPart.OwnerID)
7025 {
7026 // the rest of the permission checks are done in RezScript, so check the pin there as well
7027 World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param);
6625 7028
7029 if ((scriptItem.BasePermissions & (uint)PermissionMask.Copy) == 0)
7030 m_host.Inventory.RemoveInventoryItem(srcId);
7031 }
7032 }
6626 // this will cause the delay even if the script pin or permissions were wrong - seems ok 7033 // this will cause the delay even if the script pin or permissions were wrong - seems ok
6627 ScriptSleep(3000); 7034 ScriptSleep(3000);
6628 } 7035 }
@@ -6685,19 +7092,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6685 public LSL_String llMD5String(string src, int nonce) 7092 public LSL_String llMD5String(string src, int nonce)
6686 { 7093 {
6687 m_host.AddScriptLPS(1); 7094 m_host.AddScriptLPS(1);
6688 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString())); 7095 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString()), Encoding.UTF8);
6689 } 7096 }
6690 7097
6691 public LSL_String llSHA1String(string src) 7098 public LSL_String llSHA1String(string src)
6692 { 7099 {
6693 m_host.AddScriptLPS(1); 7100 m_host.AddScriptLPS(1);
6694 return Util.SHA1Hash(src).ToLower(); 7101 return Util.SHA1Hash(src, Encoding.UTF8).ToLower();
6695 } 7102 }
6696 7103
6697 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) 7104 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve)
6698 { 7105 {
6699 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7106 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6700 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7107 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7108 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7109 return shapeBlock;
6701 7110
6702 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && 7111 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
6703 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && 7112 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
@@ -6802,6 +7211,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6802 // Prim type box, cylinder and prism. 7211 // Prim type box, cylinder and prism.
6803 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) 7212 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)
6804 { 7213 {
7214 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7215 return;
7216
6805 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7217 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6806 ObjectShapePacket.ObjectDataBlock shapeBlock; 7218 ObjectShapePacket.ObjectDataBlock shapeBlock;
6807 7219
@@ -6855,6 +7267,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6855 // Prim type sphere. 7267 // Prim type sphere.
6856 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve) 7268 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve)
6857 { 7269 {
7270 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7271 return;
7272
6858 ObjectShapePacket.ObjectDataBlock shapeBlock; 7273 ObjectShapePacket.ObjectDataBlock shapeBlock;
6859 7274
6860 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); 7275 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@@ -6896,6 +7311,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6896 // Prim type torus, tube and ring. 7311 // Prim type torus, tube and ring.
6897 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) 7312 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)
6898 { 7313 {
7314 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7315 return;
7316
6899 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7317 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6900 ObjectShapePacket.ObjectDataBlock shapeBlock; 7318 ObjectShapePacket.ObjectDataBlock shapeBlock;
6901 7319
@@ -7031,6 +7449,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7031 // Prim type sculpt. 7449 // Prim type sculpt.
7032 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve) 7450 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve)
7033 { 7451 {
7452 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7453 return;
7454
7034 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7455 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7035 UUID sculptId; 7456 UUID sculptId;
7036 7457
@@ -7047,13 +7468,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7047 shapeBlock.PathScaleX = 100; 7468 shapeBlock.PathScaleX = 100;
7048 shapeBlock.PathScaleY = 150; 7469 shapeBlock.PathScaleY = 150;
7049 7470
7050 if (type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_CYLINDER && 7471 if ((type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_CYLINDER) == 0 &&
7051 type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_PLANE && 7472 (type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_PLANE) == 0 &&
7052 type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE && 7473 (type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE) == 0 &&
7053 type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS) 7474 (type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS) == 0)
7054 { 7475 {
7055 // default 7476 // default
7056 type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE; 7477 type = type | (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
7057 } 7478 }
7058 7479
7059 part.Shape.SetSculptProperties((byte)type, sculptId); 7480 part.Shape.SetSculptProperties((byte)type, sculptId);
@@ -7069,32 +7490,87 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7069 ScriptSleep(200); 7490 ScriptSleep(200);
7070 } 7491 }
7071 7492
7072 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) 7493 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
7073 { 7494 {
7074 m_host.AddScriptLPS(1); 7495 m_host.AddScriptLPS(1);
7075 7496
7076 setLinkPrimParams(linknumber, rules); 7497 setLinkPrimParams(linknumber, rules);
7077
7078 ScriptSleep(200);
7079 } 7498 }
7080 7499
7081 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) 7500 private void setLinkPrimParams(int linknumber, LSL_List rules)
7082 { 7501 {
7083 m_host.AddScriptLPS(1); 7502 List<SceneObjectPart> parts = GetLinkParts(linknumber);
7503 List<ScenePresence> avatars = GetLinkAvatars(linknumber);
7504 if (parts.Count>0)
7505 {
7506 try
7507 {
7508 parts[0].ParentGroup.areUpdatesSuspended = true;
7509 foreach (SceneObjectPart part in parts)
7510 SetPrimParams(part, rules);
7511 }
7512 finally
7513 {
7514 parts[0].ParentGroup.areUpdatesSuspended = false;
7515 }
7516 }
7517 if (avatars.Count > 0)
7518 {
7519 foreach (ScenePresence avatar in avatars)
7520 SetPrimParams(avatar, rules);
7521 }
7522 }
7084 7523
7085 setLinkPrimParams(linknumber, rules); 7524 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
7525 {
7526 llSetLinkPrimitiveParamsFast(linknumber, rules);
7527 ScriptSleep(200);
7086 } 7528 }
7087 7529
7088 protected void setLinkPrimParams(int linknumber, LSL_List rules) 7530 protected void SetPrimParams(ScenePresence av, LSL_List rules)
7089 { 7531 {
7090 List<SceneObjectPart> parts = GetLinkParts(linknumber); 7532 //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset.
7533 //We only support PRIM_POSITION and PRIM_ROTATION
7091 7534
7092 foreach (SceneObjectPart part in parts) 7535 int idx = 0;
7093 SetPrimParams(part, rules); 7536
7537 while (idx < rules.Length)
7538 {
7539 int code = rules.GetLSLIntegerItem(idx++);
7540
7541 int remain = rules.Length - idx;
7542
7543
7544
7545 switch (code)
7546 {
7547 case (int)ScriptBaseClass.PRIM_POSITION:
7548 if (remain < 1)
7549 return;
7550 LSL_Vector v;
7551 v = rules.GetVector3Item(idx++);
7552 av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
7553 av.SendAvatarDataToAllAgents();
7554
7555 break;
7556
7557 case (int)ScriptBaseClass.PRIM_ROTATION:
7558 if (remain < 1)
7559 return;
7560 LSL_Rotation r;
7561 r = rules.GetQuaternionItem(idx++);
7562 av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
7563 av.SendAvatarDataToAllAgents();
7564 break;
7565 }
7566 }
7094 } 7567 }
7095 7568
7096 protected void SetPrimParams(SceneObjectPart part, LSL_List rules) 7569 protected void SetPrimParams(SceneObjectPart part, LSL_List rules)
7097 { 7570 {
7571 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7572 return;
7573
7098 int idx = 0; 7574 int idx = 0;
7099 7575
7100 bool positionChanged = false; 7576 bool positionChanged = false;
@@ -7122,6 +7598,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7122 currentPosition = GetSetPosTarget(part, v, currentPosition); 7598 currentPosition = GetSetPosTarget(part, v, currentPosition);
7123 7599
7124 break; 7600 break;
7601 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
7602 if (remain < 1)
7603 return;
7604
7605 v=rules.GetVector3Item(idx++);
7606 positionChanged = true;
7607 currentPosition = GetSetPosTarget(part, v, currentPosition);
7608
7609 break;
7125 case (int)ScriptBaseClass.PRIM_SIZE: 7610 case (int)ScriptBaseClass.PRIM_SIZE:
7126 if (remain < 1) 7611 if (remain < 1)
7127 return; 7612 return;
@@ -7499,6 +7984,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7499 } 7984 }
7500 } 7985 }
7501 } 7986 }
7987
7988 if (positionChanged)
7989 {
7990 if (part.ParentGroup.RootPart == part)
7991 {
7992 SceneObjectGroup parent = part.ParentGroup;
7993 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
7994 }
7995 else
7996 {
7997 part.OffsetPosition = new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z);
7998 SceneObjectGroup parent = part.ParentGroup;
7999 parent.HasGroupChanged = true;
8000 parent.ScheduleGroupForTerseUpdate();
8001 }
8002 }
7502 } 8003 }
7503 8004
7504 public LSL_String llStringToBase64(string str) 8005 public LSL_String llStringToBase64(string str)
@@ -7659,13 +8160,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7659 public LSL_Integer llGetNumberOfPrims() 8160 public LSL_Integer llGetNumberOfPrims()
7660 { 8161 {
7661 m_host.AddScriptLPS(1); 8162 m_host.AddScriptLPS(1);
7662 int avatarCount = 0; 8163 int avatarCount = m_host.ParentGroup.GetLinkedAvatars().Count;
7663 World.ForEachRootScenePresence(delegate(ScenePresence presence) 8164
7664 {
7665 if (presence.ParentID != 0 && m_host.ParentGroup.HasChildPrim(presence.ParentID))
7666 avatarCount++;
7667 });
7668
7669 return m_host.ParentGroup.PrimCount + avatarCount; 8165 return m_host.ParentGroup.PrimCount + avatarCount;
7670 } 8166 }
7671 8167
@@ -7681,55 +8177,98 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7681 m_host.AddScriptLPS(1); 8177 m_host.AddScriptLPS(1);
7682 UUID objID = UUID.Zero; 8178 UUID objID = UUID.Zero;
7683 LSL_List result = new LSL_List(); 8179 LSL_List result = new LSL_List();
8180
8181 // If the ID is not valid, return null result
7684 if (!UUID.TryParse(obj, out objID)) 8182 if (!UUID.TryParse(obj, out objID))
7685 { 8183 {
7686 result.Add(new LSL_Vector()); 8184 result.Add(new LSL_Vector());
7687 result.Add(new LSL_Vector()); 8185 result.Add(new LSL_Vector());
7688 return result; 8186 return result;
7689 } 8187 }
8188
8189 // Check if this is an attached prim. If so, replace
8190 // the UUID with the avatar UUID and report it's bounding box
8191 SceneObjectPart part = World.GetSceneObjectPart(objID);
8192 if (part != null && part.ParentGroup.IsAttachment)
8193 objID = part.ParentGroup.AttachedAvatar;
8194
8195 // Find out if this is an avatar ID. If so, return it's box
7690 ScenePresence presence = World.GetScenePresence(objID); 8196 ScenePresence presence = World.GetScenePresence(objID);
7691 if (presence != null) 8197 if (presence != null)
7692 { 8198 {
7693 if (presence.ParentID == 0) // not sat on an object 8199 // As per LSL Wiki, there is no difference between sitting
8200 // and standing avatar since server 1.36
8201 LSL_Vector lower;
8202 LSL_Vector upper;
8203 if (presence.Animator.Animations.DefaultAnimation.AnimID
8204 == AnimationSet.Animations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
7694 { 8205 {
7695 LSL_Vector lower; 8206 // This is for ground sitting avatars
7696 LSL_Vector upper; 8207 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7697 if (presence.Animator.Animations.DefaultAnimation.AnimID 8208 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7698 == AnimationSet.Animations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) 8209 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7699 {
7700 // This is for ground sitting avatars
7701 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7702 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7703 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7704 }
7705 else
7706 {
7707 // This is for standing/flying avatars
7708 float height = presence.Appearance.AvatarHeight / 2.0f;
7709 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7710 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7711 }
7712 result.Add(lower);
7713 result.Add(upper);
7714 return result;
7715 } 8210 }
7716 else 8211 else
7717 { 8212 {
7718 // sitting on an object so we need the bounding box of that 8213 // This is for standing/flying avatars
7719 // which should include the avatar so set the UUID to the 8214 float height = presence.Appearance.AvatarHeight / 2.0f;
7720 // UUID of the object the avatar is sat on and allow it to fall through 8215 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7721 // to processing an object 8216 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7722 SceneObjectPart p = World.GetSceneObjectPart(presence.ParentID);
7723 objID = p.UUID;
7724 } 8217 }
8218
8219 // Adjust to the documented error offsets (see LSL Wiki)
8220 lower += new LSL_Vector(0.05f, 0.05f, 0.05f);
8221 upper -= new LSL_Vector(0.05f, 0.05f, 0.05f);
8222
8223 if (lower.x > upper.x)
8224 lower.x = upper.x;
8225 if (lower.y > upper.y)
8226 lower.y = upper.y;
8227 if (lower.z > upper.z)
8228 lower.z = upper.z;
8229
8230 result.Add(lower);
8231 result.Add(upper);
8232 return result;
7725 } 8233 }
7726 SceneObjectPart part = World.GetSceneObjectPart(objID); 8234
8235 part = World.GetSceneObjectPart(objID);
7727 // Currently only works for single prims without a sitting avatar 8236 // Currently only works for single prims without a sitting avatar
7728 if (part != null) 8237 if (part != null)
7729 { 8238 {
7730 Vector3 halfSize = part.Scale / 2.0f; 8239 float minX;
7731 LSL_Vector lower = new LSL_Vector(halfSize.X * -1.0f, halfSize.Y * -1.0f, halfSize.Z * -1.0f); 8240 float maxX;
7732 LSL_Vector upper = new LSL_Vector(halfSize.X, halfSize.Y, halfSize.Z); 8241 float minY;
8242 float maxY;
8243 float minZ;
8244 float maxZ;
8245
8246 // This BBox is in sim coordinates, with the offset being
8247 // a contained point.
8248 Vector3[] offsets = Scene.GetCombinedBoundingBox(new List<SceneObjectGroup> { part.ParentGroup },
8249 out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
8250
8251 minX -= offsets[0].X;
8252 maxX -= offsets[0].X;
8253 minY -= offsets[0].Y;
8254 maxY -= offsets[0].Y;
8255 minZ -= offsets[0].Z;
8256 maxZ -= offsets[0].Z;
8257
8258 LSL_Vector lower;
8259 LSL_Vector upper;
8260
8261 // Adjust to the documented error offsets (see LSL Wiki)
8262 lower = new LSL_Vector(minX + 0.05f, minY + 0.05f, minZ + 0.05f);
8263 upper = new LSL_Vector(maxX - 0.05f, maxY - 0.05f, maxZ - 0.05f);
8264
8265 if (lower.x > upper.x)
8266 lower.x = upper.x;
8267 if (lower.y > upper.y)
8268 lower.y = upper.y;
8269 if (lower.z > upper.z)
8270 lower.z = upper.z;
8271
7733 result.Add(lower); 8272 result.Add(lower);
7734 result.Add(upper); 8273 result.Add(upper);
7735 return result; 8274 return result;
@@ -7809,13 +8348,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7809 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X, 8348 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X,
7810 part.AbsolutePosition.Y, 8349 part.AbsolutePosition.Y,
7811 part.AbsolutePosition.Z); 8350 part.AbsolutePosition.Z);
7812 // For some reason, the part.AbsolutePosition.* values do not change if the
7813 // linkset is rotated; they always reflect the child prim's world position
7814 // as though the linkset is unrotated. This is incompatible behavior with SL's
7815 // implementation, so will break scripts imported from there (not to mention it
7816 // makes it more difficult to determine a child prim's actual inworld position).
7817 if (part.ParentID != 0)
7818 v = ((v - llGetRootPosition()) * llGetRootRotation()) + llGetRootPosition();
7819 res.Add(v); 8351 res.Add(v);
7820 break; 8352 break;
7821 8353
@@ -7986,56 +8518,92 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7986 case (int)ScriptBaseClass.PRIM_BUMP_SHINY: 8518 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
7987 if (remain < 1) 8519 if (remain < 1)
7988 return res; 8520 return res;
7989 8521 face = (int)rules.GetLSLIntegerItem(idx++);
7990 face=(int)rules.GetLSLIntegerItem(idx++);
7991 8522
7992 tex = part.Shape.Textures; 8523 tex = part.Shape.Textures;
8524 int shiny;
7993 if (face == ScriptBaseClass.ALL_SIDES) 8525 if (face == ScriptBaseClass.ALL_SIDES)
7994 { 8526 {
7995 for (face = 0; face < GetNumberOfSides(part); face++) 8527 for (face = 0; face < GetNumberOfSides(part); face++)
7996 { 8528 {
7997 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8529 Shininess shinyness = tex.GetFace((uint)face).Shiny;
7998 // Convert Shininess to PRIM_SHINY_* 8530 if (shinyness == Shininess.High)
7999 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8531 {
8000 // PRIM_BUMP_* 8532 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8001 res.Add(new LSL_Integer((int)texface.Bump)); 8533 }
8534 else if (shinyness == Shininess.Medium)
8535 {
8536 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8537 }
8538 else if (shinyness == Shininess.Low)
8539 {
8540 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8541 }
8542 else
8543 {
8544 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8545 }
8546 res.Add(new LSL_Integer(shiny));
8547 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8002 } 8548 }
8003 } 8549 }
8004 else 8550 else
8005 { 8551 {
8006 if (face >= 0 && face < GetNumberOfSides(part)) 8552 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8553 if (shinyness == Shininess.High)
8007 { 8554 {
8008 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8555 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8009 // Convert Shininess to PRIM_SHINY_* 8556 }
8010 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8557 else if (shinyness == Shininess.Medium)
8011 // PRIM_BUMP_* 8558 {
8012 res.Add(new LSL_Integer((int)texface.Bump)); 8559 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8560 }
8561 else if (shinyness == Shininess.Low)
8562 {
8563 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8013 } 8564 }
8565 else
8566 {
8567 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8568 }
8569 res.Add(new LSL_Integer(shiny));
8570 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8014 } 8571 }
8015 break; 8572 break;
8016 8573
8017 case (int)ScriptBaseClass.PRIM_FULLBRIGHT: 8574 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
8018 if (remain < 1) 8575 if (remain < 1)
8019 return res; 8576 return res;
8020 8577 face = (int)rules.GetLSLIntegerItem(idx++);
8021 face=(int)rules.GetLSLIntegerItem(idx++);
8022 8578
8023 tex = part.Shape.Textures; 8579 tex = part.Shape.Textures;
8580 int fullbright;
8024 if (face == ScriptBaseClass.ALL_SIDES) 8581 if (face == ScriptBaseClass.ALL_SIDES)
8025 { 8582 {
8026 for (face = 0; face < GetNumberOfSides(part); face++) 8583 for (face = 0; face < GetNumberOfSides(part); face++)
8027 { 8584 {
8028 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8585 if (tex.GetFace((uint)face).Fullbright == true)
8029 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 8586 {
8587 fullbright = ScriptBaseClass.TRUE;
8588 }
8589 else
8590 {
8591 fullbright = ScriptBaseClass.FALSE;
8592 }
8593 res.Add(new LSL_Integer(fullbright));
8030 } 8594 }
8031 } 8595 }
8032 else 8596 else
8033 { 8597 {
8034 if (face >= 0 && face < GetNumberOfSides(part)) 8598 if (tex.GetFace((uint)face).Fullbright == true)
8035 { 8599 {
8036 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8600 fullbright = ScriptBaseClass.TRUE;
8037 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0));
8038 } 8601 }
8602 else
8603 {
8604 fullbright = ScriptBaseClass.FALSE;
8605 }
8606 res.Add(new LSL_Integer(fullbright));
8039 } 8607 }
8040 break; 8608 break;
8041 8609
@@ -8057,27 +8625,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8057 break; 8625 break;
8058 8626
8059 case (int)ScriptBaseClass.PRIM_TEXGEN: 8627 case (int)ScriptBaseClass.PRIM_TEXGEN:
8628 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
8060 if (remain < 1) 8629 if (remain < 1)
8061 return res; 8630 return res;
8062 8631 face = (int)rules.GetLSLIntegerItem(idx++);
8063 face=(int)rules.GetLSLIntegerItem(idx++);
8064 8632
8065 tex = part.Shape.Textures; 8633 tex = part.Shape.Textures;
8066 if (face == ScriptBaseClass.ALL_SIDES) 8634 if (face == ScriptBaseClass.ALL_SIDES)
8067 { 8635 {
8068 for (face = 0; face < GetNumberOfSides(part); face++) 8636 for (face = 0; face < GetNumberOfSides(part); face++)
8069 { 8637 {
8070 MappingType texgen = tex.GetFace((uint)face).TexMapType; 8638 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8071 // Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc. 8639 {
8072 res.Add(new LSL_Integer((uint)texgen >> 1)); 8640 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8641 }
8642 else
8643 {
8644 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8645 }
8073 } 8646 }
8074 } 8647 }
8075 else 8648 else
8076 { 8649 {
8077 if (face >= 0 && face < GetNumberOfSides(part)) 8650 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8078 { 8651 {
8079 MappingType texgen = tex.GetFace((uint)face).TexMapType; 8652 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8080 res.Add(new LSL_Integer((uint)texgen >> 1)); 8653 }
8654 else
8655 {
8656 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8081 } 8657 }
8082 } 8658 }
8083 break; 8659 break;
@@ -8100,28 +8676,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8100 case (int)ScriptBaseClass.PRIM_GLOW: 8676 case (int)ScriptBaseClass.PRIM_GLOW:
8101 if (remain < 1) 8677 if (remain < 1)
8102 return res; 8678 return res;
8103 8679 face = (int)rules.GetLSLIntegerItem(idx++);
8104 face=(int)rules.GetLSLIntegerItem(idx++);
8105 8680
8106 tex = part.Shape.Textures; 8681 tex = part.Shape.Textures;
8682 float primglow;
8107 if (face == ScriptBaseClass.ALL_SIDES) 8683 if (face == ScriptBaseClass.ALL_SIDES)
8108 { 8684 {
8109 for (face = 0; face < GetNumberOfSides(part); face++) 8685 for (face = 0; face < GetNumberOfSides(part); face++)
8110 { 8686 {
8111 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8687 primglow = tex.GetFace((uint)face).Glow;
8112 res.Add(new LSL_Float(texface.Glow)); 8688 res.Add(new LSL_Float(primglow));
8113 } 8689 }
8114 } 8690 }
8115 else 8691 else
8116 { 8692 {
8117 if (face >= 0 && face < GetNumberOfSides(part)) 8693 primglow = tex.GetFace((uint)face).Glow;
8118 { 8694 res.Add(new LSL_Float(primglow));
8119 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
8120 res.Add(new LSL_Float(texface.Glow));
8121 }
8122 } 8695 }
8123 break; 8696 break;
8124
8125 case (int)ScriptBaseClass.PRIM_TEXT: 8697 case (int)ScriptBaseClass.PRIM_TEXT:
8126 Color4 textColor = part.GetTextColor(); 8698 Color4 textColor = part.GetTextColor();
8127 res.Add(new LSL_String(part.Text)); 8699 res.Add(new LSL_String(part.Text));
@@ -8673,8 +9245,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8673 // The function returns an ordered list 9245 // The function returns an ordered list
8674 // representing the tokens found in the supplied 9246 // representing the tokens found in the supplied
8675 // sources string. If two successive tokenizers 9247 // sources string. If two successive tokenizers
8676 // are encountered, then a NULL entry is added 9248 // are encountered, then a null-string entry is
8677 // to the list. 9249 // added to the list.
8678 // 9250 //
8679 // It is a precondition that the source and 9251 // It is a precondition that the source and
8680 // toekizer lisst are non-null. If they are null, 9252 // toekizer lisst are non-null. If they are null,
@@ -8682,7 +9254,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8682 // while their lengths are being determined. 9254 // while their lengths are being determined.
8683 // 9255 //
8684 // A small amount of working memoryis required 9256 // A small amount of working memoryis required
8685 // of approximately 8*#tokenizers. 9257 // of approximately 8*#tokenizers + 8*srcstrlen.
8686 // 9258 //
8687 // There are many ways in which this function 9259 // There are many ways in which this function
8688 // can be implemented, this implementation is 9260 // can be implemented, this implementation is
@@ -8698,155 +9270,124 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8698 // and eliminates redundant tokenizers as soon 9270 // and eliminates redundant tokenizers as soon
8699 // as is possible. 9271 // as is possible.
8700 // 9272 //
8701 // The implementation tries to avoid any copying 9273 // The implementation tries to minimize temporary
8702 // of arrays or other objects. 9274 // garbage generation.
8703 // </remarks> 9275 // </remarks>
8704 9276
8705 private LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls) 9277 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8706 { 9278 {
8707 int beginning = 0; 9279 return ParseString2List(src, separators, spacers, true);
8708 int srclen = src.Length; 9280 }
8709 int seplen = separators.Length;
8710 object[] separray = separators.Data;
8711 int spclen = spacers.Length;
8712 object[] spcarray = spacers.Data;
8713 int mlen = seplen+spclen;
8714
8715 int[] offset = new int[mlen+1];
8716 bool[] active = new bool[mlen];
8717
8718 int best;
8719 int j;
8720
8721 // Initial capacity reduces resize cost
8722 9281
8723 LSL_List tokens = new LSL_List(); 9282 private LSL_List ParseString2List(string src, LSL_List separators, LSL_List spacers, bool keepNulls)
9283 {
9284 int srclen = src.Length;
9285 int seplen = separators.Length;
9286 object[] separray = separators.Data;
9287 int spclen = spacers.Length;
9288 object[] spcarray = spacers.Data;
9289 int dellen = 0;
9290 string[] delarray = new string[seplen+spclen];
8724 9291
8725 // All entries are initially valid 9292 int outlen = 0;
9293 string[] outarray = new string[srclen*2+1];
8726 9294
8727 for (int i = 0; i < mlen; i++) 9295 int i, j;
8728 active[i] = true; 9296 string d;
8729 9297
8730 offset[mlen] = srclen; 9298 m_host.AddScriptLPS(1);
8731 9299
8732 while (beginning < srclen) 9300 /*
9301 * Convert separator and spacer lists to C# strings.
9302 * Also filter out null strings so we don't hang.
9303 */
9304 for (i = 0; i < seplen; i ++)
8733 { 9305 {
9306 d = separray[i].ToString();
9307 if (d.Length > 0)
9308 {
9309 delarray[dellen++] = d;
9310 }
9311 }
9312 seplen = dellen;
8734 9313
8735 best = mlen; // as bad as it gets 9314 for (i = 0; i < spclen; i ++)
9315 {
9316 d = spcarray[i].ToString();
9317 if (d.Length > 0)
9318 {
9319 delarray[dellen++] = d;
9320 }
9321 }
8736 9322
8737 // Scan for separators 9323 /*
9324 * Scan through source string from beginning to end.
9325 */
9326 for (i = 0;;)
9327 {
8738 9328
8739 for (j = 0; j < seplen; j++) 9329 /*
9330 * Find earliest delimeter in src starting at i (if any).
9331 */
9332 int earliestDel = -1;
9333 int earliestSrc = srclen;
9334 string earliestStr = null;
9335 for (j = 0; j < dellen; j ++)
8740 { 9336 {
8741 if (separray[j].ToString() == String.Empty) 9337 d = delarray[j];
8742 active[j] = false; 9338 if (d != null)
8743
8744 if (active[j])
8745 { 9339 {
8746 // scan all of the markers 9340 int index = src.IndexOf(d, i);
8747 if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1) 9341 if (index < 0)
8748 { 9342 {
8749 // not present at all 9343 delarray[j] = null; // delim nowhere in src, don't check it anymore
8750 active[j] = false;
8751 } 9344 }
8752 else 9345 else if (index < earliestSrc)
8753 { 9346 {
8754 // present and correct 9347 earliestSrc = index; // where delimeter starts in source string
8755 if (offset[j] < offset[best]) 9348 earliestDel = j; // where delimeter is in delarray[]
8756 { 9349 earliestStr = d; // the delimeter string from delarray[]
8757 // closest so far 9350 if (index == i) break; // can't do any better than found at beg of string
8758 best = j;
8759 if (offset[best] == beginning)
8760 break;
8761 }
8762 } 9351 }
8763 } 9352 }
8764 } 9353 }
8765 9354
8766 // Scan for spacers 9355 /*
8767 9356 * Output source string starting at i through start of earliest delimeter.
8768 if (offset[best] != beginning) 9357 */
9358 if (keepNulls || (earliestSrc > i))
8769 { 9359 {
8770 for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) 9360 outarray[outlen++] = src.Substring(i, earliestSrc - i);
8771 {
8772 if (spcarray[j-seplen].ToString() == String.Empty)
8773 active[j] = false;
8774
8775 if (active[j])
8776 {
8777 // scan all of the markers
8778 if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1)
8779 {
8780 // not present at all
8781 active[j] = false;
8782 }
8783 else
8784 {
8785 // present and correct
8786 if (offset[j] < offset[best])
8787 {
8788 // closest so far
8789 best = j;
8790 }
8791 }
8792 }
8793 }
8794 } 9361 }
8795 9362
8796 // This is the normal exit from the scanning loop 9363 /*
9364 * If no delimeter found at or after i, we're done scanning.
9365 */
9366 if (earliestDel < 0) break;
8797 9367
8798 if (best == mlen) 9368 /*
9369 * If delimeter was a spacer, output the spacer.
9370 */
9371 if (earliestDel >= seplen)
8799 { 9372 {
8800 // no markers were found on this pass 9373 outarray[outlen++] = earliestStr;
8801 // so we're pretty much done
8802 if ((keepNulls) || ((!keepNulls) && (srclen - beginning) > 0))
8803 tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning)));
8804 break;
8805 } 9374 }
8806 9375
8807 // Otherwise we just add the newly delimited token 9376 /*
8808 // and recalculate where the search should continue. 9377 * Look at rest of src string following delimeter.
8809 if ((keepNulls) || ((!keepNulls) && (offset[best] - beginning) > 0)) 9378 */
8810 tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning))); 9379 i = earliestSrc + earliestStr.Length;
8811
8812 if (best < seplen)
8813 {
8814 beginning = offset[best] + (separray[best].ToString()).Length;
8815 }
8816 else
8817 {
8818 beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
8819 string str = spcarray[best - seplen].ToString();
8820 if ((keepNulls) || ((!keepNulls) && (str.Length > 0)))
8821 tokens.Add(new LSL_String(str));
8822 }
8823 } 9380 }
8824 9381
8825 // This an awkward an not very intuitive boundary case. If the 9382 /*
8826 // last substring is a tokenizer, then there is an implied trailing 9383 * Make up an exact-sized output array suitable for an LSL_List object.
8827 // null list entry. Hopefully the single comparison will not be too 9384 */
8828 // arduous. Alternatively the 'break' could be replced with a return 9385 object[] outlist = new object[outlen];
8829 // but that's shabby programming. 9386 for (i = 0; i < outlen; i ++)
8830
8831 if ((beginning == srclen) && (keepNulls))
8832 { 9387 {
8833 if (srclen != 0) 9388 outlist[i] = new LSL_String(outarray[i]);
8834 tokens.Add(new LSL_String(""));
8835 } 9389 }
8836 9390 return new LSL_List(outlist);
8837 return tokens;
8838 }
8839
8840 public LSL_List llParseString2List(string src, LSL_List separators, LSL_List spacers)
8841 {
8842 m_host.AddScriptLPS(1);
8843 return this.ParseString(src, separators, spacers, false);
8844 }
8845
8846 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8847 {
8848 m_host.AddScriptLPS(1);
8849 return this.ParseString(src, separators, spacers, true);
8850 } 9391 }
8851 9392
8852 public LSL_Integer llGetObjectPermMask(int mask) 9393 public LSL_Integer llGetObjectPermMask(int mask)
@@ -8923,28 +9464,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8923 { 9464 {
8924 m_host.AddScriptLPS(1); 9465 m_host.AddScriptLPS(1);
8925 9466
8926 lock (m_host.TaskInventory) 9467 m_host.TaskInventory.LockItemsForRead(true);
9468 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
8927 { 9469 {
8928 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9470 if (inv.Value.Name == item)
8929 { 9471 {
8930 if (inv.Value.Name == item) 9472 m_host.TaskInventory.LockItemsForRead(false);
9473 switch (mask)
8931 { 9474 {
8932 switch (mask) 9475 case 0:
8933 { 9476 return (int)inv.Value.BasePermissions;
8934 case 0: 9477 case 1:
8935 return (int)inv.Value.BasePermissions; 9478 return (int)inv.Value.CurrentPermissions;
8936 case 1: 9479 case 2:
8937 return (int)inv.Value.CurrentPermissions; 9480 return (int)inv.Value.GroupPermissions;
8938 case 2: 9481 case 3:
8939 return (int)inv.Value.GroupPermissions; 9482 return (int)inv.Value.EveryonePermissions;
8940 case 3: 9483 case 4:
8941 return (int)inv.Value.EveryonePermissions; 9484 return (int)inv.Value.NextPermissions;
8942 case 4:
8943 return (int)inv.Value.NextPermissions;
8944 }
8945 } 9485 }
8946 } 9486 }
8947 } 9487 }
9488 m_host.TaskInventory.LockItemsForRead(false);
8948 9489
8949 return -1; 9490 return -1;
8950 } 9491 }
@@ -8991,16 +9532,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8991 { 9532 {
8992 m_host.AddScriptLPS(1); 9533 m_host.AddScriptLPS(1);
8993 9534
8994 lock (m_host.TaskInventory) 9535 m_host.TaskInventory.LockItemsForRead(true);
9536 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
8995 { 9537 {
8996 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9538 if (inv.Value.Name == item)
8997 { 9539 {
8998 if (inv.Value.Name == item) 9540 m_host.TaskInventory.LockItemsForRead(false);
8999 { 9541 return inv.Value.CreatorID.ToString();
9000 return inv.Value.CreatorID.ToString();
9001 }
9002 } 9542 }
9003 } 9543 }
9544 m_host.TaskInventory.LockItemsForRead(false);
9004 9545
9005 llSay(0, "No item name '" + item + "'"); 9546 llSay(0, "No item name '" + item + "'");
9006 9547
@@ -9148,7 +9689,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9148 } 9689 }
9149 9690
9150 /// <summary> 9691 /// <summary>
9151 /// illListReplaceList removes the sub-list defined by the inclusive indices 9692 /// llListReplaceList removes the sub-list defined by the inclusive indices
9152 /// start and end and inserts the src list in its place. The inclusive 9693 /// start and end and inserts the src list in its place. The inclusive
9153 /// nature of the indices means that at least one element must be deleted 9694 /// nature of the indices means that at least one element must be deleted
9154 /// if the indices are within the bounds of the existing list. I.e. 2,2 9695 /// if the indices are within the bounds of the existing list. I.e. 2,2
@@ -9205,16 +9746,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9205 // based upon end. Note that if end exceeds the upper 9746 // based upon end. Note that if end exceeds the upper
9206 // bound in this case, the entire destination list 9747 // bound in this case, the entire destination list
9207 // is removed. 9748 // is removed.
9208 else 9749 else if (start == 0)
9209 { 9750 {
9210 if (end + 1 < dest.Length) 9751 if (end + 1 < dest.Length)
9211 {
9212 return src + dest.GetSublist(end + 1, -1); 9752 return src + dest.GetSublist(end + 1, -1);
9213 }
9214 else 9753 else
9215 {
9216 return src; 9754 return src;
9217 } 9755 }
9756 else // Start < 0
9757 {
9758 if (end + 1 < dest.Length)
9759 return dest.GetSublist(end + 1, -1);
9760 else
9761 return new LSL_List();
9218 } 9762 }
9219 } 9763 }
9220 // Finally, if start > end, we strip away a prefix and 9764 // Finally, if start > end, we strip away a prefix and
@@ -9265,17 +9809,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9265 int width = 0; 9809 int width = 0;
9266 int height = 0; 9810 int height = 0;
9267 9811
9268 ParcelMediaCommandEnum? commandToSend = null; 9812 uint commandToSend = 0;
9269 float time = 0.0f; // default is from start 9813 float time = 0.0f; // default is from start
9270 9814
9271 ScenePresence presence = null; 9815 ScenePresence presence = null;
9272 9816
9273 for (int i = 0; i < commandList.Data.Length; i++) 9817 for (int i = 0; i < commandList.Data.Length; i++)
9274 { 9818 {
9275 ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i]; 9819 uint command = (uint)(commandList.GetLSLIntegerItem(i));
9276 switch (command) 9820 switch (command)
9277 { 9821 {
9278 case ParcelMediaCommandEnum.Agent: 9822 case (uint)ParcelMediaCommandEnum.Agent:
9279 // we send only to one agent 9823 // we send only to one agent
9280 if ((i + 1) < commandList.Length) 9824 if ((i + 1) < commandList.Length)
9281 { 9825 {
@@ -9292,25 +9836,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9292 } 9836 }
9293 break; 9837 break;
9294 9838
9295 case ParcelMediaCommandEnum.Loop: 9839 case (uint)ParcelMediaCommandEnum.Loop:
9296 loop = 1; 9840 loop = 1;
9297 commandToSend = command; 9841 commandToSend = command;
9298 update = true; //need to send the media update packet to set looping 9842 update = true; //need to send the media update packet to set looping
9299 break; 9843 break;
9300 9844
9301 case ParcelMediaCommandEnum.Play: 9845 case (uint)ParcelMediaCommandEnum.Play:
9302 loop = 0; 9846 loop = 0;
9303 commandToSend = command; 9847 commandToSend = command;
9304 update = true; //need to send the media update packet to make sure it doesn't loop 9848 update = true; //need to send the media update packet to make sure it doesn't loop
9305 break; 9849 break;
9306 9850
9307 case ParcelMediaCommandEnum.Pause: 9851 case (uint)ParcelMediaCommandEnum.Pause:
9308 case ParcelMediaCommandEnum.Stop: 9852 case (uint)ParcelMediaCommandEnum.Stop:
9309 case ParcelMediaCommandEnum.Unload: 9853 case (uint)ParcelMediaCommandEnum.Unload:
9310 commandToSend = command; 9854 commandToSend = command;
9311 break; 9855 break;
9312 9856
9313 case ParcelMediaCommandEnum.Url: 9857 case (uint)ParcelMediaCommandEnum.Url:
9314 if ((i + 1) < commandList.Length) 9858 if ((i + 1) < commandList.Length)
9315 { 9859 {
9316 if (commandList.Data[i + 1] is LSL_String) 9860 if (commandList.Data[i + 1] is LSL_String)
@@ -9323,7 +9867,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9323 } 9867 }
9324 break; 9868 break;
9325 9869
9326 case ParcelMediaCommandEnum.Texture: 9870 case (uint)ParcelMediaCommandEnum.Texture:
9327 if ((i + 1) < commandList.Length) 9871 if ((i + 1) < commandList.Length)
9328 { 9872 {
9329 if (commandList.Data[i + 1] is LSL_String) 9873 if (commandList.Data[i + 1] is LSL_String)
@@ -9336,7 +9880,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9336 } 9880 }
9337 break; 9881 break;
9338 9882
9339 case ParcelMediaCommandEnum.Time: 9883 case (uint)ParcelMediaCommandEnum.Time:
9340 if ((i + 1) < commandList.Length) 9884 if ((i + 1) < commandList.Length)
9341 { 9885 {
9342 if (commandList.Data[i + 1] is LSL_Float) 9886 if (commandList.Data[i + 1] is LSL_Float)
@@ -9348,7 +9892,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9348 } 9892 }
9349 break; 9893 break;
9350 9894
9351 case ParcelMediaCommandEnum.AutoAlign: 9895 case (uint)ParcelMediaCommandEnum.AutoAlign:
9352 if ((i + 1) < commandList.Length) 9896 if ((i + 1) < commandList.Length)
9353 { 9897 {
9354 if (commandList.Data[i + 1] is LSL_Integer) 9898 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9362,7 +9906,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9362 } 9906 }
9363 break; 9907 break;
9364 9908
9365 case ParcelMediaCommandEnum.Type: 9909 case (uint)ParcelMediaCommandEnum.Type:
9366 if ((i + 1) < commandList.Length) 9910 if ((i + 1) < commandList.Length)
9367 { 9911 {
9368 if (commandList.Data[i + 1] is LSL_String) 9912 if (commandList.Data[i + 1] is LSL_String)
@@ -9375,7 +9919,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9375 } 9919 }
9376 break; 9920 break;
9377 9921
9378 case ParcelMediaCommandEnum.Desc: 9922 case (uint)ParcelMediaCommandEnum.Desc:
9379 if ((i + 1) < commandList.Length) 9923 if ((i + 1) < commandList.Length)
9380 { 9924 {
9381 if (commandList.Data[i + 1] is LSL_String) 9925 if (commandList.Data[i + 1] is LSL_String)
@@ -9388,7 +9932,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9388 } 9932 }
9389 break; 9933 break;
9390 9934
9391 case ParcelMediaCommandEnum.Size: 9935 case (uint)ParcelMediaCommandEnum.Size:
9392 if ((i + 2) < commandList.Length) 9936 if ((i + 2) < commandList.Length)
9393 { 9937 {
9394 if (commandList.Data[i + 1] is LSL_Integer) 9938 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9458,7 +10002,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9458 } 10002 }
9459 } 10003 }
9460 10004
9461 if (commandToSend != null) 10005 if (commandToSend != 0)
9462 { 10006 {
9463 // the commandList contained a start/stop/... command, too 10007 // the commandList contained a start/stop/... command, too
9464 if (presence == null) 10008 if (presence == null)
@@ -9495,7 +10039,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9495 10039
9496 if (aList.Data[i] != null) 10040 if (aList.Data[i] != null)
9497 { 10041 {
9498 switch ((ParcelMediaCommandEnum) aList.Data[i]) 10042 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString()))
9499 { 10043 {
9500 case ParcelMediaCommandEnum.Url: 10044 case ParcelMediaCommandEnum.Url:
9501 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL)); 10045 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL));
@@ -9538,16 +10082,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9538 { 10082 {
9539 m_host.AddScriptLPS(1); 10083 m_host.AddScriptLPS(1);
9540 10084
9541 lock (m_host.TaskInventory) 10085 m_host.TaskInventory.LockItemsForRead(true);
10086 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9542 { 10087 {
9543 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 10088 if (inv.Value.Name == name)
9544 { 10089 {
9545 if (inv.Value.Name == name) 10090 m_host.TaskInventory.LockItemsForRead(false);
9546 { 10091 return inv.Value.Type;
9547 return inv.Value.Type;
9548 }
9549 } 10092 }
9550 } 10093 }
10094 m_host.TaskInventory.LockItemsForRead(false);
9551 10095
9552 return -1; 10096 return -1;
9553 } 10097 }
@@ -9558,15 +10102,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9558 10102
9559 if (quick_pay_buttons.Data.Length < 4) 10103 if (quick_pay_buttons.Data.Length < 4)
9560 { 10104 {
9561 LSLError("List must have at least 4 elements"); 10105 int x;
9562 return; 10106 for (x=quick_pay_buttons.Data.Length; x<= 4; x++)
10107 {
10108 quick_pay_buttons.Add(ScriptBaseClass.PAY_HIDE);
10109 }
9563 } 10110 }
9564 m_host.ParentGroup.RootPart.PayPrice[0]=price; 10111 int[] nPrice = new int[5];
9565 10112 nPrice[0] = price;
9566 m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; 10113 nPrice[1] = quick_pay_buttons.GetLSLIntegerItem(0);
9567 m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; 10114 nPrice[2] = quick_pay_buttons.GetLSLIntegerItem(1);
9568 m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; 10115 nPrice[3] = quick_pay_buttons.GetLSLIntegerItem(2);
9569 m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; 10116 nPrice[4] = quick_pay_buttons.GetLSLIntegerItem(3);
10117 m_host.ParentGroup.RootPart.PayPrice = nPrice;
9570 m_host.ParentGroup.HasGroupChanged = true; 10118 m_host.ParentGroup.HasGroupChanged = true;
9571 } 10119 }
9572 10120
@@ -9578,17 +10126,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9578 if (invItemID == UUID.Zero) 10126 if (invItemID == UUID.Zero)
9579 return new LSL_Vector(); 10127 return new LSL_Vector();
9580 10128
9581 lock (m_host.TaskInventory) 10129 m_host.TaskInventory.LockItemsForRead(true);
10130 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
9582 { 10131 {
9583 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) 10132 m_host.TaskInventory.LockItemsForRead(false);
9584 return new LSL_Vector(); 10133 return new LSL_Vector();
10134 }
9585 10135
9586 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) 10136 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
9587 { 10137 {
9588 ShoutError("No permissions to track the camera"); 10138 ShoutError("No permissions to track the camera");
9589 return new LSL_Vector(); 10139 m_host.TaskInventory.LockItemsForRead(false);
9590 } 10140 return new LSL_Vector();
9591 } 10141 }
10142 m_host.TaskInventory.LockItemsForRead(false);
9592 10143
9593 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10144 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
9594 if (presence != null) 10145 if (presence != null)
@@ -9606,17 +10157,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9606 if (invItemID == UUID.Zero) 10157 if (invItemID == UUID.Zero)
9607 return new LSL_Rotation(); 10158 return new LSL_Rotation();
9608 10159
9609 lock (m_host.TaskInventory) 10160 m_host.TaskInventory.LockItemsForRead(true);
10161 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
9610 { 10162 {
9611 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) 10163 m_host.TaskInventory.LockItemsForRead(false);
9612 return new LSL_Rotation(); 10164 return new LSL_Rotation();
9613
9614 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
9615 {
9616 ShoutError("No permissions to track the camera");
9617 return new LSL_Rotation();
9618 }
9619 } 10165 }
10166 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
10167 {
10168 ShoutError("No permissions to track the camera");
10169 m_host.TaskInventory.LockItemsForRead(false);
10170 return new LSL_Rotation();
10171 }
10172 m_host.TaskInventory.LockItemsForRead(false);
9620 10173
9621 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10174 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
9622 if (presence != null) 10175 if (presence != null)
@@ -9678,8 +10231,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9678 { 10231 {
9679 m_host.AddScriptLPS(1); 10232 m_host.AddScriptLPS(1);
9680 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, 0); 10233 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, 0);
9681 if (detectedParams == null) return; // only works on the first detected avatar 10234 if (detectedParams == null)
9682 10235 {
10236 if (m_host.ParentGroup.IsAttachment == true)
10237 {
10238 detectedParams = new DetectParams();
10239 detectedParams.Key = m_host.OwnerID;
10240 }
10241 else
10242 {
10243 return;
10244 }
10245 }
10246
9683 ScenePresence avatar = World.GetScenePresence(detectedParams.Key); 10247 ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
9684 if (avatar != null) 10248 if (avatar != null)
9685 { 10249 {
@@ -9687,6 +10251,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9687 new Vector3((float)pos.x, (float)pos.y, (float)pos.z), 10251 new Vector3((float)pos.x, (float)pos.y, (float)pos.z),
9688 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z)); 10252 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z));
9689 } 10253 }
10254
9690 ScriptSleep(1000); 10255 ScriptSleep(1000);
9691 } 10256 }
9692 10257
@@ -9798,14 +10363,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9798 if (objectID == UUID.Zero) return; 10363 if (objectID == UUID.Zero) return;
9799 10364
9800 UUID agentID; 10365 UUID agentID;
9801 lock (m_host.TaskInventory) 10366 m_host.TaskInventory.LockItemsForRead(true);
9802 { 10367 // we need the permission first, to know which avatar we want to set the camera for
9803 // we need the permission first, to know which avatar we want to set the camera for 10368 agentID = m_host.TaskInventory[invItemID].PermsGranter;
9804 agentID = m_host.TaskInventory[invItemID].PermsGranter;
9805 10369
9806 if (agentID == UUID.Zero) return; 10370 if (agentID == UUID.Zero)
9807 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return; 10371 {
10372 m_host.TaskInventory.LockItemsForRead(false);
10373 return;
10374 }
10375 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0)
10376 {
10377 m_host.TaskInventory.LockItemsForRead(false);
10378 return;
9808 } 10379 }
10380 m_host.TaskInventory.LockItemsForRead(false);
9809 10381
9810 ScenePresence presence = World.GetScenePresence(agentID); 10382 ScenePresence presence = World.GetScenePresence(agentID);
9811 10383
@@ -9814,12 +10386,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9814 10386
9815 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>(); 10387 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
9816 object[] data = rules.Data; 10388 object[] data = rules.Data;
9817 for (int i = 0; i < data.Length; ++i) { 10389 for (int i = 0; i < data.Length; ++i)
10390 {
9818 int type = Convert.ToInt32(data[i++].ToString()); 10391 int type = Convert.ToInt32(data[i++].ToString());
9819 if (i >= data.Length) break; // odd number of entries => ignore the last 10392 if (i >= data.Length) break; // odd number of entries => ignore the last
9820 10393
9821 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3) 10394 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
9822 switch (type) { 10395 switch (type)
10396 {
9823 case ScriptBaseClass.CAMERA_FOCUS: 10397 case ScriptBaseClass.CAMERA_FOCUS:
9824 case ScriptBaseClass.CAMERA_FOCUS_OFFSET: 10398 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
9825 case ScriptBaseClass.CAMERA_POSITION: 10399 case ScriptBaseClass.CAMERA_POSITION:
@@ -9855,12 +10429,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9855 10429
9856 // we need the permission first, to know which avatar we want to clear the camera for 10430 // we need the permission first, to know which avatar we want to clear the camera for
9857 UUID agentID; 10431 UUID agentID;
9858 lock (m_host.TaskInventory) 10432 m_host.TaskInventory.LockItemsForRead(true);
10433 agentID = m_host.TaskInventory[invItemID].PermsGranter;
10434 if (agentID == UUID.Zero)
9859 { 10435 {
9860 agentID = m_host.TaskInventory[invItemID].PermsGranter; 10436 m_host.TaskInventory.LockItemsForRead(false);
9861 if (agentID == UUID.Zero) return; 10437 return;
9862 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return;
9863 } 10438 }
10439 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0)
10440 {
10441 m_host.TaskInventory.LockItemsForRead(false);
10442 return;
10443 }
10444 m_host.TaskInventory.LockItemsForRead(false);
9864 10445
9865 ScenePresence presence = World.GetScenePresence(agentID); 10446 ScenePresence presence = World.GetScenePresence(agentID);
9866 10447
@@ -9927,19 +10508,65 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9927 public LSL_String llXorBase64StringsCorrect(string str1, string str2) 10508 public LSL_String llXorBase64StringsCorrect(string str1, string str2)
9928 { 10509 {
9929 m_host.AddScriptLPS(1); 10510 m_host.AddScriptLPS(1);
9930 string ret = String.Empty; 10511
9931 string src1 = llBase64ToString(str1); 10512 if (str1 == String.Empty)
9932 string src2 = llBase64ToString(str2); 10513 return String.Empty;
9933 int c = 0; 10514 if (str2 == String.Empty)
9934 for (int i = 0; i < src1.Length; i++) 10515 return str1;
10516
10517 int len = str2.Length;
10518 if ((len % 4) != 0) // LL is EVIL!!!!
9935 { 10519 {
9936 ret += (char) (src1[i] ^ src2[c]); 10520 while (str2.EndsWith("="))
10521 str2 = str2.Substring(0, str2.Length - 1);
10522
10523 len = str2.Length;
10524 int mod = len % 4;
10525
10526 if (mod == 1)
10527 str2 = str2.Substring(0, str2.Length - 1);
10528 else if (mod == 2)
10529 str2 += "==";
10530 else if (mod == 3)
10531 str2 += "=";
10532 }
9937 10533
9938 c++; 10534 byte[] data1;
9939 if (c >= src2.Length) 10535 byte[] data2;
9940 c = 0; 10536 try
10537 {
10538 data1 = Convert.FromBase64String(str1);
10539 data2 = Convert.FromBase64String(str2);
10540 }
10541 catch (Exception)
10542 {
10543 return new LSL_String(String.Empty);
9941 } 10544 }
9942 return llStringToBase64(ret); 10545
10546 byte[] d2 = new Byte[data1.Length];
10547 int pos = 0;
10548
10549 if (data1.Length <= data2.Length)
10550 {
10551 Array.Copy(data2, 0, d2, 0, data1.Length);
10552 }
10553 else
10554 {
10555 while (pos < data1.Length)
10556 {
10557 len = data1.Length - pos;
10558 if (len > data2.Length)
10559 len = data2.Length;
10560
10561 Array.Copy(data2, 0, d2, pos, len);
10562 pos += len;
10563 }
10564 }
10565
10566 for (pos = 0 ; pos < data1.Length ; pos++ )
10567 data1[pos] ^= d2[pos];
10568
10569 return Convert.ToBase64String(data1);
9943 } 10570 }
9944 10571
9945 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body) 10572 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
@@ -9996,12 +10623,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9996 Regex r = new Regex(authregex); 10623 Regex r = new Regex(authregex);
9997 int[] gnums = r.GetGroupNumbers(); 10624 int[] gnums = r.GetGroupNumbers();
9998 Match m = r.Match(url); 10625 Match m = r.Match(url);
9999 if (m.Success) { 10626 if (m.Success)
10000 for (int i = 1; i < gnums.Length; i++) { 10627 {
10628 for (int i = 1; i < gnums.Length; i++)
10629 {
10001 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]]; 10630 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]];
10002 //CaptureCollection cc = g.Captures; 10631 //CaptureCollection cc = g.Captures;
10003 } 10632 }
10004 if (m.Groups.Count == 5) { 10633 if (m.Groups.Count == 5)
10634 {
10005 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString()))); 10635 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString())));
10006 url = m.Groups[1].ToString() + m.Groups[4].ToString(); 10636 url = m.Groups[1].ToString() + m.Groups[4].ToString();
10007 } 10637 }
@@ -10287,15 +10917,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10287 10917
10288 internal UUID ScriptByName(string name) 10918 internal UUID ScriptByName(string name)
10289 { 10919 {
10290 lock (m_host.TaskInventory) 10920 m_host.TaskInventory.LockItemsForRead(true);
10921
10922 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
10291 { 10923 {
10292 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 10924 if (item.Type == 10 && item.Name == name)
10293 { 10925 {
10294 if (item.Type == 10 && item.Name == name) 10926 m_host.TaskInventory.LockItemsForRead(false);
10295 return item.ItemID; 10927 return item.ItemID;
10296 } 10928 }
10297 } 10929 }
10298 10930
10931 m_host.TaskInventory.LockItemsForRead(false);
10932
10299 return UUID.Zero; 10933 return UUID.Zero;
10300 } 10934 }
10301 10935
@@ -10336,6 +10970,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10336 { 10970 {
10337 m_host.AddScriptLPS(1); 10971 m_host.AddScriptLPS(1);
10338 10972
10973 //Clone is thread safe
10339 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 10974 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10340 10975
10341 UUID assetID = UUID.Zero; 10976 UUID assetID = UUID.Zero;
@@ -10398,6 +11033,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10398 { 11033 {
10399 m_host.AddScriptLPS(1); 11034 m_host.AddScriptLPS(1);
10400 11035
11036 //Clone is thread safe
10401 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 11037 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10402 11038
10403 UUID assetID = UUID.Zero; 11039 UUID assetID = UUID.Zero;
@@ -10478,15 +11114,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10478 return GetLinkPrimitiveParams(obj, rules); 11114 return GetLinkPrimitiveParams(obj, rules);
10479 } 11115 }
10480 11116
10481 public void print(string str) 11117 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
10482 { 11118 {
10483 // yes, this is a real LSL function. See: http://wiki.secondlife.com/wiki/Print 11119 List<SceneObjectPart> parts = GetLinkParts(link);
10484 IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_itemID, "OSSL"); 11120 if (parts.Count < 1)
10485 if (ossl != null) 11121 return 0;
10486 { 11122
10487 ossl.CheckThreatLevel(ThreatLevel.High, "print"); 11123 return GetNumberOfSides(parts[0]);
10488 m_log.Info("LSL print():" + str);
10489 }
10490 } 11124 }
10491 11125
10492 private string Name2Username(string name) 11126 private string Name2Username(string name)
@@ -10532,153 +11166,392 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10532 return rq.ToString(); 11166 return rq.ToString();
10533 } 11167 }
10534 11168
11169 private void SayShoutTimerElapsed(Object sender, ElapsedEventArgs args)
11170 {
11171 m_SayShoutCount = 0;
11172 }
11173
11174 private struct Tri
11175 {
11176 public Vector3 p1;
11177 public Vector3 p2;
11178 public Vector3 p3;
11179 }
11180
11181 private bool InBoundingBox(ScenePresence avatar, Vector3 point)
11182 {
11183 float height = avatar.Appearance.AvatarHeight;
11184 Vector3 b1 = avatar.AbsolutePosition + new Vector3(-0.22f, -0.22f, -height/2);
11185 Vector3 b2 = avatar.AbsolutePosition + new Vector3(0.22f, 0.22f, height/2);
11186
11187 if (point.X > b1.X && point.X < b2.X &&
11188 point.Y > b1.Y && point.Y < b2.Y &&
11189 point.Z > b1.Z && point.Z < b2.Z)
11190 return true;
11191 return false;
11192 }
11193
11194 private ContactResult[] AvatarIntersection(Vector3 rayStart, Vector3 rayEnd)
11195 {
11196 List<ContactResult> contacts = new List<ContactResult>();
11197
11198 Vector3 ab = rayEnd - rayStart;
11199
11200 World.ForEachScenePresence(delegate(ScenePresence sp)
11201 {
11202 Vector3 ac = sp.AbsolutePosition - rayStart;
11203 Vector3 bc = sp.AbsolutePosition - rayEnd;
11204
11205 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11206
11207 if (d > 1.5)
11208 return;
11209
11210 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
11211
11212 if (d2 > 0)
11213 return;
11214
11215 double dp = Math.Sqrt(Vector3.Mag(ac) * Vector3.Mag(ac) - d * d);
11216 Vector3 p = rayStart + Vector3.Divide(Vector3.Multiply(ab, (float)dp), (float)Vector3.Mag(ab));
11217
11218 if (!InBoundingBox(sp, p))
11219 return;
11220
11221 ContactResult result = new ContactResult ();
11222 result.ConsumerID = sp.LocalId;
11223 result.Depth = Vector3.Distance(rayStart, p);
11224 result.Normal = Vector3.Zero;
11225 result.Pos = p;
11226
11227 contacts.Add(result);
11228 });
11229
11230 return contacts.ToArray();
11231 }
11232
11233 private ContactResult[] ObjectIntersection(Vector3 rayStart, Vector3 rayEnd, bool includePhysical, bool includeNonPhysical, bool includePhantom)
11234 {
11235 Ray ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart));
11236 List<ContactResult> contacts = new List<ContactResult>();
11237
11238 Vector3 ab = rayEnd - rayStart;
11239
11240 World.ForEachSOG(delegate(SceneObjectGroup group)
11241 {
11242 if (m_host.ParentGroup == group)
11243 return;
11244
11245 if (group.IsAttachment)
11246 return;
11247
11248 if (group.RootPart.PhysActor == null)
11249 {
11250 if (!includePhantom)
11251 return;
11252 }
11253 else
11254 {
11255 if (group.RootPart.PhysActor.IsPhysical)
11256 {
11257 if (!includePhysical)
11258 return;
11259 }
11260 else
11261 {
11262 if (!includeNonPhysical)
11263 return;
11264 }
11265 }
11266
11267 // Find the radius ouside of which we don't even need to hit test
11268 float minX;
11269 float maxX;
11270 float minY;
11271 float maxY;
11272 float minZ;
11273 float maxZ;
11274
11275 float radius = 0.0f;
11276
11277 group.GetAxisAlignedBoundingBoxRaw(out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
11278
11279 if (Math.Abs(minX) > radius)
11280 radius = Math.Abs(minX);
11281 if (Math.Abs(minY) > radius)
11282 radius = Math.Abs(minY);
11283 if (Math.Abs(minZ) > radius)
11284 radius = Math.Abs(minZ);
11285 if (Math.Abs(maxX) > radius)
11286 radius = Math.Abs(maxX);
11287 if (Math.Abs(maxY) > radius)
11288 radius = Math.Abs(maxY);
11289 if (Math.Abs(maxZ) > radius)
11290 radius = Math.Abs(maxZ);
11291
11292 Vector3 ac = group.AbsolutePosition - rayStart;
11293 Vector3 bc = group.AbsolutePosition - rayEnd;
11294
11295 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11296
11297 // Too far off ray, don't bother
11298 if (d > radius)
11299 return;
11300
11301 // Behind ray, drop
11302 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
11303 if (d2 > 0)
11304 return;
11305
11306 EntityIntersection intersection = group.TestIntersection(ray, true, false);
11307 // Miss.
11308 if (!intersection.HitTF)
11309 return;
11310
11311 ContactResult result = new ContactResult ();
11312 result.ConsumerID = group.LocalId;
11313 result.Depth = intersection.distance;
11314 result.Normal = intersection.normal;
11315 result.Pos = intersection.ipoint;
11316
11317 contacts.Add(result);
11318 });
11319
11320 return contacts.ToArray();
11321 }
11322
11323 private ContactResult? GroundIntersection(Vector3 rayStart, Vector3 rayEnd)
11324 {
11325 double[,] heightfield = World.Heightmap.GetDoubles();
11326 List<ContactResult> contacts = new List<ContactResult>();
11327
11328 double min = 2048.0;
11329 double max = 0.0;
11330
11331 // Find the min and max of the heightfield
11332 for (int x = 0 ; x < World.Heightmap.Width ; x++)
11333 {
11334 for (int y = 0 ; y < World.Heightmap.Height ; y++)
11335 {
11336 if (heightfield[x, y] > max)
11337 max = heightfield[x, y];
11338 if (heightfield[x, y] < min)
11339 min = heightfield[x, y];
11340 }
11341 }
11342
11343
11344 // A ray extends past rayEnd, but doesn't go back before
11345 // rayStart. If the start is above the highest point of the ground
11346 // and the ray goes up, we can't hit the ground. Ever.
11347 if (rayStart.Z > max && rayEnd.Z >= rayStart.Z)
11348 return null;
11349
11350 // Same for going down
11351 if (rayStart.Z < min && rayEnd.Z <= rayStart.Z)
11352 return null;
11353
11354 List<Tri> trilist = new List<Tri>();
11355
11356 // Create our triangle list
11357 for (int x = 1 ; x < World.Heightmap.Width ; x++)
11358 {
11359 for (int y = 1 ; y < World.Heightmap.Height ; y++)
11360 {
11361 Tri t1 = new Tri();
11362 Tri t2 = new Tri();
11363
11364 Vector3 p1 = new Vector3(x-1, y-1, (float)heightfield[x-1, y-1]);
11365 Vector3 p2 = new Vector3(x, y-1, (float)heightfield[x, y-1]);
11366 Vector3 p3 = new Vector3(x, y, (float)heightfield[x, y]);
11367 Vector3 p4 = new Vector3(x-1, y, (float)heightfield[x-1, y]);
11368
11369 t1.p1 = p1;
11370 t1.p2 = p2;
11371 t1.p3 = p3;
11372
11373 t2.p1 = p3;
11374 t2.p2 = p4;
11375 t2.p3 = p1;
11376
11377 trilist.Add(t1);
11378 trilist.Add(t2);
11379 }
11380 }
11381
11382 // Ray direction
11383 Vector3 rayDirection = rayEnd - rayStart;
11384
11385 foreach (Tri t in trilist)
11386 {
11387 // Compute triangle plane normal and edges
11388 Vector3 u = t.p2 - t.p1;
11389 Vector3 v = t.p3 - t.p1;
11390 Vector3 n = Vector3.Cross(u, v);
11391
11392 if (n == Vector3.Zero)
11393 continue;
11394
11395 Vector3 w0 = rayStart - t.p1;
11396 double a = -Vector3.Dot(n, w0);
11397 double b = Vector3.Dot(n, rayDirection);
11398
11399 // Not intersecting the plane, or in plane (same thing)
11400 // Ignoring this MAY cause the ground to not be detected
11401 // sometimes
11402 if (Math.Abs(b) < 0.000001)
11403 continue;
11404
11405 double r = a / b;
11406
11407 // ray points away from plane
11408 if (r < 0.0)
11409 continue;
11410
11411 Vector3 ip = rayStart + Vector3.Multiply(rayDirection, (float)r);
11412
11413 float uu = Vector3.Dot(u, u);
11414 float uv = Vector3.Dot(u, v);
11415 float vv = Vector3.Dot(v, v);
11416 Vector3 w = ip - t.p1;
11417 float wu = Vector3.Dot(w, u);
11418 float wv = Vector3.Dot(w, v);
11419 float d = uv * uv - uu * vv;
11420
11421 float cs = (uv * wv - vv * wu) / d;
11422 if (cs < 0 || cs > 1.0)
11423 continue;
11424 float ct = (uv * wu - uu * wv) / d;
11425 if (ct < 0 || (cs + ct) > 1.0)
11426 continue;
11427
11428 // Add contact point
11429 ContactResult result = new ContactResult ();
11430 result.ConsumerID = 0;
11431 result.Depth = Vector3.Distance(rayStart, ip);
11432 result.Normal = n;
11433 result.Pos = ip;
11434
11435 contacts.Add(result);
11436 }
11437
11438 if (contacts.Count == 0)
11439 return null;
11440
11441 contacts.Sort(delegate(ContactResult a, ContactResult b)
11442 {
11443 return (int)(a.Depth - b.Depth);
11444 });
11445
11446 return contacts[0];
11447 }
11448
10535 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) 11449 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
10536 { 11450 {
11451 LSL_List list = new LSL_List();
11452
10537 m_host.AddScriptLPS(1); 11453 m_host.AddScriptLPS(1);
10538 11454
10539 Vector3 dir = new Vector3((float)(end-start).x, (float)(end-start).y, (float)(end-start).z); 11455 Vector3 rayStart = new Vector3((float)start.x, (float)start.y, (float)start.z);
10540 Vector3 startvector = new Vector3((float)start.x, (float)start.y, (float)start.z); 11456 Vector3 rayEnd = new Vector3((float)end.x, (float)end.y, (float)end.z);
10541 Vector3 endvector = new Vector3((float)end.x, (float)end.y, (float)end.z); 11457 Vector3 dir = rayEnd - rayStart;
10542 11458
10543 int count = 0; 11459 int count = 1;
10544// int detectPhantom = 0; 11460 bool detectPhantom = false;
10545 int dataFlags = 0; 11461 int dataFlags = 0;
10546 int rejectTypes = 0; 11462 int rejectTypes = 0;
10547 11463
10548 for (int i = 0; i < options.Length; i += 2) 11464 for (int i = 0; i < options.Length; i += 2)
10549 { 11465 {
10550 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS) 11466 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS)
10551 {
10552 count = options.GetLSLIntegerItem(i + 1); 11467 count = options.GetLSLIntegerItem(i + 1);
10553 } 11468 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM)
10554// else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM) 11469 detectPhantom = (options.GetLSLIntegerItem(i + 1) > 0);
10555// {
10556// detectPhantom = options.GetLSLIntegerItem(i + 1);
10557// }
10558 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS) 11470 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS)
10559 {
10560 dataFlags = options.GetLSLIntegerItem(i + 1); 11471 dataFlags = options.GetLSLIntegerItem(i + 1);
10561 }
10562 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES) 11472 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES)
10563 {
10564 rejectTypes = options.GetLSLIntegerItem(i + 1); 11473 rejectTypes = options.GetLSLIntegerItem(i + 1);
10565 }
10566 } 11474 }
10567 11475
10568 LSL_List list = new LSL_List(); 11476 if (count > 16)
10569 List<ContactResult> results = World.PhysicsScene.RaycastWorld(startvector, dir, dir.Length(), count); 11477 count = 16;
10570
10571 double distance = Util.GetDistanceTo(startvector, endvector);
10572 11478
10573 if (distance == 0) 11479 List<ContactResult> results = new List<ContactResult>();
10574 distance = 0.001;
10575
10576 Vector3 posToCheck = startvector;
10577 ITerrainChannel channel = World.RequestModuleInterface<ITerrainChannel>();
10578 11480
10579 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND); 11481 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND);
10580 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS); 11482 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS);
10581 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL); 11483 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL);
10582 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); 11484 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL);
10583 11485
10584 for (float i = 0; i <= distance; i += 0.1f) 11486 if (checkTerrain)
10585 { 11487 {
10586 posToCheck = startvector + (dir * (i / (float)distance)); 11488 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
11489 if (groundContact != null)
11490 results.Add((ContactResult)groundContact);
11491 }
10587 11492
10588 if (checkTerrain && channel[(int)(posToCheck.X + startvector.X), (int)(posToCheck.Y + startvector.Y)] < posToCheck.Z) 11493 if (checkAgents)
10589 { 11494 {
10590 ContactResult result = new ContactResult(); 11495 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
10591 result.ConsumerID = 0; 11496 foreach (ContactResult r in agentHits)
10592 result.Depth = 0; 11497 results.Add(r);
10593 result.Normal = Vector3.Zero; 11498 }
10594 result.Pos = posToCheck;
10595 results.Add(result);
10596 checkTerrain = false;
10597 }
10598 11499
10599 if (checkAgents) 11500 if (checkPhysical || checkNonPhysical)
10600 { 11501 {
10601 World.ForEachRootScenePresence(delegate(ScenePresence sp) 11502 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom);
10602 { 11503 foreach (ContactResult r in objectHits)
10603 if (sp.AbsolutePosition.ApproxEquals(posToCheck, sp.PhysicsActor.Size.X)) 11504 results.Add(r);
10604 {
10605 ContactResult result = new ContactResult ();
10606 result.ConsumerID = sp.LocalId;
10607 result.Depth = 0;
10608 result.Normal = Vector3.Zero;
10609 result.Pos = posToCheck;
10610 results.Add(result);
10611 }
10612 });
10613 }
10614 } 11505 }
10615 11506
10616 int refcount = 0; 11507 results.Sort(delegate(ContactResult a, ContactResult b)
11508 {
11509 return (int)(a.Depth - b.Depth);
11510 });
11511
11512 int values = 0;
10617 foreach (ContactResult result in results) 11513 foreach (ContactResult result in results)
10618 { 11514 {
10619 if ((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) 11515 UUID itemID = UUID.Zero;
10620 == ScriptBaseClass.RC_REJECT_LAND && result.ConsumerID == 0) 11516 int linkNum = 0;
10621 continue;
10622
10623 ISceneEntity entity = World.GetSceneObjectPart(result.ConsumerID);
10624
10625 if (entity == null && (rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) != ScriptBaseClass.RC_REJECT_AGENTS)
10626 entity = World.GetScenePresence(result.ConsumerID); //Only check if we should be looking for agents
10627 11517
10628 if (entity == null) 11518 SceneObjectPart part = World.GetSceneObjectPart(result.ConsumerID);
11519 // It's a prim!
11520 if (part != null)
10629 { 11521 {
10630 list.Add(UUID.Zero); 11522 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY)
10631 11523 itemID = part.ParentGroup.UUID;
10632 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) 11524 else
10633 list.Add(0); 11525 itemID = part.UUID;
10634
10635 list.Add(result.Pos);
10636
10637 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
10638 list.Add(result.Normal);
10639 11526
10640 continue; //Can't find it, so add UUID.Zero 11527 linkNum = part.LinkNum;
10641 } 11528 }
10642 11529 else
10643 /*if (detectPhantom == 0 && intersection.obj is ISceneChildEntity &&
10644 ((ISceneChildEntity)intersection.obj).PhysActor == null)
10645 continue;*/ //Can't do this ATM, physics engine knows only of non phantom objects
10646
10647 if (entity is SceneObjectPart)
10648 { 11530 {
10649 if (((SceneObjectPart)entity).PhysActor != null && ((SceneObjectPart)entity).PhysActor.IsPhysical) 11531 ScenePresence sp = World.GetScenePresence(result.ConsumerID);
10650 { 11532 /// It it a boy? a girl?
10651 if (!checkPhysical) 11533 if (sp != null)
10652 continue; 11534 itemID = sp.UUID;
10653 }
10654 else
10655 {
10656 if (!checkNonPhysical)
10657 continue;
10658 }
10659 } 11535 }
10660 11536
10661 refcount++; 11537 list.Add(new LSL_String(itemID.ToString()));
10662 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY && entity is SceneObjectPart) 11538 list.Add(new LSL_String(result.Pos.ToString()));
10663 list.Add(((SceneObjectPart)entity).ParentGroup.UUID);
10664 else
10665 list.Add(entity.UUID);
10666 11539
10667 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) 11540 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
10668 { 11541 list.Add(new LSL_Integer(linkNum));
10669 if (entity is SceneObjectPart)
10670 list.Add(((SceneObjectPart)entity).LinkNum);
10671 else
10672 list.Add(0);
10673 }
10674 11542
10675 list.Add(result.Pos);
10676 11543
10677 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) 11544 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
10678 list.Add(result.Normal); 11545 list.Add(new LSL_Vector(result.Normal.X, result.Normal.Y, result.Normal.Z));
11546
11547 values++;
11548 count--;
11549
11550 if (count == 0)
11551 break;
10679 } 11552 }
10680 11553
10681 list.Add(refcount); //The status code, either the # of contacts, RCERR_SIM_PERF_LOW, or RCERR_CAST_TIME_EXCEEDED 11554 list.Add(new LSL_Integer(values));
10682 11555
10683 return list; 11556 return list;
10684 } 11557 }
@@ -10718,7 +11591,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10718 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD: 11591 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD:
10719 if (!isAccount) return 0; 11592 if (!isAccount) return 0;
10720 if (estate.HasAccess(id)) return 1; 11593 if (estate.HasAccess(id)) return 1;
10721 if (estate.IsBanned(id)) 11594 if (estate.IsBanned(id, World.GetUserFlags(id)))
10722 estate.RemoveBan(id); 11595 estate.RemoveBan(id);
10723 estate.AddEstateUser(id); 11596 estate.AddEstateUser(id);
10724 break; 11597 break;
@@ -10737,14 +11610,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10737 break; 11610 break;
10738 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD: 11611 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD:
10739 if (!isAccount) return 0; 11612 if (!isAccount) return 0;
10740 if (estate.IsBanned(id)) return 1; 11613 if (estate.IsBanned(id, World.GetUserFlags(id))) return 1;
10741 EstateBan ban = new EstateBan(); 11614 EstateBan ban = new EstateBan();
10742 ban.EstateID = estate.EstateID; 11615 ban.EstateID = estate.EstateID;
10743 ban.BannedUserID = id; 11616 ban.BannedUserID = id;
10744 estate.AddBan(ban); 11617 estate.AddBan(ban);
10745 break; 11618 break;
10746 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE: 11619 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE:
10747 if (!isAccount || !estate.IsBanned(id)) return 0; 11620 if (!isAccount || !estate.IsBanned(id, World.GetUserFlags(id))) return 0;
10748 estate.RemoveBan(id); 11621 estate.RemoveBan(id);
10749 break; 11622 break;
10750 default: return 0; 11623 default: return 0;
@@ -10770,22 +11643,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10770 NotImplemented("llGetSPMaxMemory"); 11643 NotImplemented("llGetSPMaxMemory");
10771 } 11644 }
10772 11645
10773 public void llGetUsedMemory() 11646 public virtual LSL_Integer llGetUsedMemory()
10774 { 11647 {
10775 m_host.AddScriptLPS(1); 11648 m_host.AddScriptLPS(1);
10776 NotImplemented("llGetUsedMemory"); 11649 NotImplemented("llGetUsedMemory");
11650 return 0;
10777 } 11651 }
10778 11652
10779 public void llScriptProfiler(LSL_Integer flags) 11653 public void llScriptProfiler(LSL_Integer flags)
10780 { 11654 {
10781 m_host.AddScriptLPS(1); 11655 m_host.AddScriptLPS(1);
10782 NotImplemented("llScriptProfiler"); 11656 //NotImplemented("llScriptProfiler");
10783 } 11657 }
10784 11658
10785 public void llSetSoundQueueing(int queue) 11659 public void llSetSoundQueueing(int queue)
10786 { 11660 {
10787 m_host.AddScriptLPS(1); 11661 m_host.AddScriptLPS(1);
10788 NotImplemented("llSetSoundQueueing");
10789 } 11662 }
10790 11663
10791 public void llCollisionSprite(string impact_sprite) 11664 public void llCollisionSprite(string impact_sprite)
@@ -10797,7 +11670,133 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10797 public void llGodLikeRezObject(string inventory, LSL_Vector pos) 11670 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
10798 { 11671 {
10799 m_host.AddScriptLPS(1); 11672 m_host.AddScriptLPS(1);
10800 NotImplemented("llGodLikeRezObject"); 11673
11674 if (!World.Permissions.IsGod(m_host.OwnerID))
11675 NotImplemented("llGodLikeRezObject");
11676
11677 AssetBase rezAsset = World.AssetService.Get(inventory);
11678 if (rezAsset == null)
11679 {
11680 llSay(0, "Asset not found");
11681 return;
11682 }
11683
11684 SceneObjectGroup group = null;
11685
11686 try
11687 {
11688 string xmlData = Utils.BytesToString(rezAsset.Data);
11689 group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
11690 }
11691 catch
11692 {
11693 llSay(0, "Asset not found");
11694 return;
11695 }
11696
11697 if (group == null)
11698 {
11699 llSay(0, "Asset not found");
11700 return;
11701 }
11702
11703 group.RootPart.AttachPoint = group.RootPart.Shape.State;
11704 group.RootPart.AttachOffset = group.AbsolutePosition;
11705
11706 group.ResetIDs();
11707
11708 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
11709 World.AddNewSceneObject(group, true, llpos, Quaternion.Identity, Vector3.Zero);
11710 group.CreateScriptInstances(0, true, World.DefaultScriptEngine, 3);
11711 group.ScheduleGroupForFullUpdate();
11712
11713 // objects rezzed with this method are die_at_edge by default.
11714 group.RootPart.SetDieAtEdge(true);
11715
11716 group.ResumeScripts();
11717
11718 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
11719 "object_rez", new Object[] {
11720 new LSL_String(
11721 group.RootPart.UUID.ToString()) },
11722 new DetectParams[0]));
11723 }
11724
11725 public LSL_String llTransferLindenDollars(string destination, int amount)
11726 {
11727 UUID txn = UUID.Random();
11728
11729 Util.FireAndForget(delegate(object x)
11730 {
11731 int replycode = 0;
11732 string replydata = destination + "," + amount.ToString();
11733
11734 try
11735 {
11736 UUID invItemID=InventorySelf();
11737 if (invItemID == UUID.Zero)
11738 {
11739 replydata = "SERVICE_ERROR";
11740 return;
11741 }
11742
11743 m_host.AddScriptLPS(1);
11744
11745 m_host.TaskInventory.LockItemsForRead(true);
11746 TaskInventoryItem item = m_host.TaskInventory[invItemID];
11747 m_host.TaskInventory.LockItemsForRead(false);
11748
11749 if (item.PermsGranter == UUID.Zero)
11750 {
11751 replydata = "MISSING_PERMISSION_DEBIT";
11752 return;
11753 }
11754
11755 if ((item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
11756 {
11757 replydata = "MISSING_PERMISSION_DEBIT";
11758 return;
11759 }
11760
11761 UUID toID = new UUID();
11762
11763 if (!UUID.TryParse(destination, out toID))
11764 {
11765 replydata = "INVALID_AGENT";
11766 return;
11767 }
11768
11769 IMoneyModule money = World.RequestModuleInterface<IMoneyModule>();
11770
11771 if (money == null)
11772 {
11773 replydata = "TRANSFERS_DISABLED";
11774 return;
11775 }
11776
11777 bool result = money.ObjectGiveMoney(
11778 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
11779
11780 if (result)
11781 {
11782 replycode = 1;
11783 return;
11784 }
11785
11786 replydata = "LINDENDOLLAR_INSUFFICIENTFUNDS";
11787 }
11788 finally
11789 {
11790 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
11791 "transaction_result", new Object[] {
11792 new LSL_String(txn.ToString()),
11793 new LSL_Integer(replycode),
11794 new LSL_String(replydata) },
11795 new DetectParams[0]));
11796 }
11797 });
11798
11799 return txn.ToString();
10801 } 11800 }
10802 11801
10803 #endregion 11802 #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 6106a65..f2d4399 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();
@@ -201,6 +202,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
201 void llGiveInventory(string destination, string inventory); 202 void llGiveInventory(string destination, string inventory);
202 void llGiveInventoryList(string destination, string category, LSL_List inventory); 203 void llGiveInventoryList(string destination, string category, LSL_List inventory);
203 LSL_Integer llGiveMoney(string destination, int amount); 204 LSL_Integer llGiveMoney(string destination, int amount);
205 LSL_String llTransferLindenDollars(string destination, int amount);
204 void llGodLikeRezObject(string inventory, LSL_Vector pos); 206 void llGodLikeRezObject(string inventory, LSL_Vector pos);
205 LSL_Float llGround(LSL_Vector offset); 207 LSL_Float llGround(LSL_Vector offset);
206 LSL_Vector llGroundContour(LSL_Vector offset); 208 LSL_Vector llGroundContour(LSL_Vector offset);
@@ -408,7 +410,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
408 LSL_Vector llWind(LSL_Vector offset); 410 LSL_Vector llWind(LSL_Vector offset);
409 LSL_String llXorBase64Strings(string str1, string str2); 411 LSL_String llXorBase64Strings(string str1, string str2);
410 LSL_String llXorBase64StringsCorrect(string str1, string str2); 412 LSL_String llXorBase64StringsCorrect(string str1, string str2);
411 void print(string str); 413 LSL_Integer llGetLinkNumberOfSides(LSL_Integer link);
412 414
413 void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); 415 void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
414 LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules); 416 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 83550a5..fad6c35 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();
@@ -849,6 +861,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
849 return m_LSL_Functions.llGiveMoney(destination, amount); 861 return m_LSL_Functions.llGiveMoney(destination, amount);
850 } 862 }
851 863
864 public LSL_String llTransferLindenDollars(string destination, int amount)
865 {
866 return m_LSL_Functions.llTransferLindenDollars(destination, amount);
867 }
868
852 public void llGodLikeRezObject(string inventory, LSL_Vector pos) 869 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
853 { 870 {
854 m_LSL_Functions.llGodLikeRezObject(inventory, pos); 871 m_LSL_Functions.llGodLikeRezObject(inventory, pos);
@@ -1893,9 +1910,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1893 return m_LSL_Functions.llClearPrimMedia(face); 1910 return m_LSL_Functions.llClearPrimMedia(face);
1894 } 1911 }
1895 1912
1896 public void print(string str) 1913 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
1897 { 1914 {
1898 m_LSL_Functions.print(str); 1915 return m_LSL_Functions.llGetLinkNumberOfSides(link);
1899 } 1916 }
1900 } 1917 }
1901} 1918}
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 4d3d257..c32dbf5 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