aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/Scene.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/Scene.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs670
1 files changed, 431 insertions, 239 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 05ce00a..2066536 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -80,6 +80,11 @@ namespace OpenSim.Region.Framework.Scenes
80 public SynchronizeSceneHandler SynchronizeScene; 80 public SynchronizeSceneHandler SynchronizeScene;
81 81
82 /// <summary> 82 /// <summary>
83 /// Used to prevent simultaneous calls to RemoveClient() for the same agent from interfering with each other.
84 /// </summary>
85 private object m_removeClientLock = new object();
86
87 /// <summary>
83 /// Statistical information for this scene. 88 /// Statistical information for this scene.
84 /// </summary> 89 /// </summary>
85 public SimStatsReporter StatsReporter { get; private set; } 90 public SimStatsReporter StatsReporter { get; private set; }
@@ -103,8 +108,31 @@ namespace OpenSim.Region.Framework.Scenes
103 /// </summary> 108 /// </summary>
104 public bool CollidablePrims { get; private set; } 109 public bool CollidablePrims { get; private set; }
105 110
111 /// <summary>
112 /// Minimum value of the size of a non-physical prim in each axis
113 /// </summary>
114 public float m_minNonphys = 0.001f;
115
116 /// <summary>
117 /// Maximum value of the size of a non-physical prim in each axis
118 /// </summary>
106 public float m_maxNonphys = 256; 119 public float m_maxNonphys = 256;
120
121 /// <summary>
122 /// Minimum value of the size of a physical prim in each axis
123 /// </summary>
124 public float m_minPhys = 0.01f;
125
126 /// <summary>
127 /// Maximum value of the size of a physical prim in each axis
128 /// </summary>
107 public float m_maxPhys = 10; 129 public float m_maxPhys = 10;
130
131 /// <summary>
132 /// Max prims an object will hold
133 /// </summary>
134 public int m_linksetCapacity = 0;
135
108 public bool m_clampPrimSize; 136 public bool m_clampPrimSize;
109 public bool m_trustBinaries; 137 public bool m_trustBinaries;
110 public bool m_allowScriptCrossings; 138 public bool m_allowScriptCrossings;
@@ -285,6 +313,31 @@ namespace OpenSim.Region.Framework.Scenes
285 } 313 }
286 private volatile bool m_shuttingDown; 314 private volatile bool m_shuttingDown;
287 315
316 /// <summary>
317 /// Is the scene active?
318 /// </summary>
319 /// <remarks>
320 /// If false, maintenance and update loops are not being run. Updates can still be triggered manually if
321 /// the scene is not active.
322 /// </remarks>
323 public bool Active
324 {
325 get { return m_active; }
326 set
327 {
328 if (value)
329 {
330 if (!m_active)
331 Start();
332 }
333 else
334 {
335 m_active = false;
336 }
337 }
338 }
339 private volatile bool m_active;
340
288// private int m_lastUpdate; 341// private int m_lastUpdate;
289 private bool m_firstHeartbeat = true; 342 private bool m_firstHeartbeat = true;
290 343
@@ -746,12 +799,24 @@ namespace OpenSim.Region.Framework.Scenes
746 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true); 799 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true);
747 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true); 800 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
748 801
749 m_maxNonphys = startupConfig.GetFloat("NonphysicalPrimMax", m_maxNonphys); 802 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys);
803 if (RegionInfo.NonphysPrimMin > 0)
804 {
805 m_minNonphys = RegionInfo.NonphysPrimMin;
806 }
807
808 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys);
750 if (RegionInfo.NonphysPrimMax > 0) 809 if (RegionInfo.NonphysPrimMax > 0)
751 { 810 {
752 m_maxNonphys = RegionInfo.NonphysPrimMax; 811 m_maxNonphys = RegionInfo.NonphysPrimMax;
753 } 812 }
754 813
814 m_minPhys = startupConfig.GetFloat("PhysicalPrimMin", m_minPhys);
815 if (RegionInfo.PhysPrimMin > 0)
816 {
817 m_minPhys = RegionInfo.PhysPrimMin;
818 }
819
755 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys); 820 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys);
756 821
757 if (RegionInfo.PhysPrimMax > 0) 822 if (RegionInfo.PhysPrimMax > 0)
@@ -759,6 +824,12 @@ namespace OpenSim.Region.Framework.Scenes
759 m_maxPhys = RegionInfo.PhysPrimMax; 824 m_maxPhys = RegionInfo.PhysPrimMax;
760 } 825 }
761 826
827 m_linksetCapacity = startupConfig.GetInt("LinksetPrims", m_linksetCapacity);
828 if (RegionInfo.LinksetCapacity > 0)
829 {
830 m_linksetCapacity = RegionInfo.LinksetCapacity;
831 }
832
762 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest"); 833 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest");
763 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false); 834 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false);
764 835
@@ -784,13 +855,6 @@ namespace OpenSim.Region.Framework.Scenes
784 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 855 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
785 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine); 856 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
786 857
787 IConfig packetConfig = m_config.Configs["PacketPool"];
788 if (packetConfig != null)
789 {
790 PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true);
791 PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true);
792 }
793
794 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 858 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
795 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion); 859 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
796 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false); 860 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
@@ -854,6 +918,8 @@ namespace OpenSim.Region.Framework.Scenes
854 } 918 }
855 919
856 // FIXME: Ultimately this should be in a module. 920 // FIXME: Ultimately this should be in a module.
921 SendPeriodicAppearanceUpdates = true;
922
857 IConfig appearanceConfig = m_config.Configs["Appearance"]; 923 IConfig appearanceConfig = m_config.Configs["Appearance"];
858 if (appearanceConfig != null) 924 if (appearanceConfig != null)
859 { 925 {
@@ -1151,6 +1217,14 @@ namespace OpenSim.Region.Framework.Scenes
1151 1217
1152 public void SetSceneCoreDebug(Dictionary<string, string> options) 1218 public void SetSceneCoreDebug(Dictionary<string, string> options)
1153 { 1219 {
1220 if (options.ContainsKey("active"))
1221 {
1222 bool active;
1223
1224 if (bool.TryParse(options["active"], out active))
1225 Active = active;
1226 }
1227
1154 if (options.ContainsKey("scripting")) 1228 if (options.ContainsKey("scripting"))
1155 { 1229 {
1156 bool enableScripts = true; 1230 bool enableScripts = true;
@@ -1226,6 +1300,12 @@ namespace OpenSim.Region.Framework.Scenes
1226 // This is the method that shuts down the scene. 1300 // This is the method that shuts down the scene.
1227 public override void Close() 1301 public override void Close()
1228 { 1302 {
1303 if (m_shuttingDown)
1304 {
1305 m_log.WarnFormat("[SCENE]: Ignoring close request because already closing {0}", Name);
1306 return;
1307 }
1308
1229 m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName); 1309 m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName);
1230 1310
1231 StatsReporter.Close(); 1311 StatsReporter.Close();
@@ -1269,6 +1349,14 @@ namespace OpenSim.Region.Framework.Scenes
1269 1349
1270 m_sceneGraph.Close(); 1350 m_sceneGraph.Close();
1271 1351
1352 if (!GridService.DeregisterRegion(RegionInfo.RegionID))
1353 m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name);
1354
1355 base.Close();
1356
1357 // XEngine currently listens to the EventManager.OnShutdown event to trigger script stop and persistence.
1358 // Therefore. we must dispose of the PhysicsScene after this to prevent a window where script code can
1359 // attempt to reference a null or disposed physics scene.
1272 if (PhysicsScene != null) 1360 if (PhysicsScene != null)
1273 { 1361 {
1274 PhysicsScene phys = PhysicsScene; 1362 PhysicsScene phys = PhysicsScene;
@@ -1277,12 +1365,6 @@ namespace OpenSim.Region.Framework.Scenes
1277 phys.Dispose(); 1365 phys.Dispose();
1278 phys = null; 1366 phys = null;
1279 } 1367 }
1280
1281 if (!GridService.DeregisterRegion(RegionInfo.RegionID))
1282 m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name);
1283
1284 // call the base class Close method.
1285 base.Close();
1286 } 1368 }
1287 1369
1288 /// <summary> 1370 /// <summary>
@@ -1290,6 +1372,8 @@ namespace OpenSim.Region.Framework.Scenes
1290 /// </summary> 1372 /// </summary>
1291 public void Start() 1373 public void Start()
1292 { 1374 {
1375 m_active = true;
1376
1293// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); 1377// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName);
1294 1378
1295 //m_heartbeatTimer.Enabled = true; 1379 //m_heartbeatTimer.Enabled = true;
@@ -1346,7 +1430,7 @@ namespace OpenSim.Region.Framework.Scenes
1346 #region Update Methods 1430 #region Update Methods
1347 1431
1348 /// <summary> 1432 /// <summary>
1349 /// Performs per-frame updates regularly 1433 /// Activate the various loops necessary to continually update the scene.
1350 /// </summary> 1434 /// </summary>
1351 private void Heartbeat() 1435 private void Heartbeat()
1352 { 1436 {
@@ -1403,7 +1487,7 @@ namespace OpenSim.Region.Framework.Scenes
1403 List<Vector3> coarseLocations; 1487 List<Vector3> coarseLocations;
1404 List<UUID> avatarUUIDs; 1488 List<UUID> avatarUUIDs;
1405 1489
1406 while (!m_shuttingDown && (endRun == null || MaintenanceRun < endRun)) 1490 while (!m_shuttingDown && ((endRun == null && Active) || MaintenanceRun < endRun))
1407 { 1491 {
1408 runtc = Util.EnvironmentTickCount(); 1492 runtc = Util.EnvironmentTickCount();
1409 ++MaintenanceRun; 1493 ++MaintenanceRun;
@@ -1465,7 +1549,7 @@ namespace OpenSim.Region.Framework.Scenes
1465 int sleepMS; 1549 int sleepMS;
1466 int framestart; 1550 int framestart;
1467 1551
1468 while (!m_shuttingDown && (endFrame == null || Frame < endFrame)) 1552 while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame))
1469 { 1553 {
1470 framestart = Util.EnvironmentTickCount(); 1554 framestart = Util.EnvironmentTickCount();
1471 ++Frame; 1555 ++Frame;
@@ -2185,10 +2269,14 @@ namespace OpenSim.Region.Framework.Scenes
2185 public bool AddRestoredSceneObject( 2269 public bool AddRestoredSceneObject(
2186 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 2270 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
2187 { 2271 {
2188 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 2272 if (m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates))
2189 if (result) 2273 {
2190 sceneObject.IsDeleted = false; 2274 sceneObject.IsDeleted = false;
2191 return result; 2275 EventManager.TriggerObjectAddedToScene(sceneObject);
2276 return true;
2277 }
2278
2279 return false;
2192 } 2280 }
2193 2281
2194 /// <summary> 2282 /// <summary>
@@ -2829,77 +2917,89 @@ namespace OpenSim.Region.Framework.Scenes
2829 2917
2830 public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) 2918 public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type)
2831 { 2919 {
2920 ScenePresence sp;
2921 bool vialogin;
2922
2832 // Validation occurs in LLUDPServer 2923 // Validation occurs in LLUDPServer
2924 //
2925 // XXX: A race condition exists here where two simultaneous calls to AddNewClient can interfere with
2926 // each other. In practice, this does not currently occur in the code.
2833 AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); 2927 AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode);
2834 2928
2835 bool vialogin 2929 // We lock here on AgentCircuitData to prevent a race condition between the thread adding a new connection
2836 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 2930 // and a simultaneous one that removes it (as can happen if the client is closed at a particular point
2837 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 2931 // whilst connecting).
2838 2932 //
2839 CheckHeartbeat(); 2933 // It would be easier to lock across all NewUserConnection(), AddNewClient() and
2840 2934 // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service
2841 ScenePresence sp = GetScenePresence(client.AgentId); 2935 // response in some module listening to AddNewClient()) from holding up unrelated agent calls.
2842 2936 //
2843 // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this 2937 // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all
2844 // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause 2938 // AddNewClient() operations (though not other ops).
2845 // other problems, and possible the code calling AddNewClient() should ensure that no client is already 2939 // In the future this can be relieved once locking per agent (not necessarily on AgentCircuitData) is improved.
2846 // connected. 2940 lock (aCircuit)
2847 if (sp == null) 2941 {
2848 { 2942 vialogin
2849 m_log.DebugFormat( 2943 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0
2850 "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", 2944 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2851 client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); 2945
2852 2946 CheckHeartbeat();
2853 m_clientManager.Add(client); 2947
2854 SubscribeToClientEvents(client); 2948 sp = GetScenePresence(client.AgentId);
2855
2856 sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type);
2857 m_eventManager.TriggerOnNewPresence(sp);
2858
2859 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags;
2860 2949
2861 // The first agent upon login is a root agent by design. 2950 // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this
2862 // For this agent we will have to rez the attachments. 2951 // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause
2863 // All other AddNewClient calls find aCircuit.child to be true. 2952 // other problems, and possible the code calling AddNewClient() should ensure that no client is already
2864 if (aCircuit.child == false) 2953 // connected.
2954 if (sp == null)
2865 { 2955 {
2866 // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to 2956 m_log.DebugFormat(
2867 // start the scripts again (since this is done in RezAttachments()). 2957 "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}",
2868 // XXX: This is convoluted. 2958 client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos);
2869 sp.IsChildAgent = false; 2959
2870 2960 m_clientManager.Add(client);
2871 if (AttachmentsModule != null) 2961 SubscribeToClientEvents(client);
2872 Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); }); 2962
2963 sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type);
2964 m_eventManager.TriggerOnNewPresence(sp);
2965
2966 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags;
2967
2968 // The first agent upon login is a root agent by design.
2969 // For this agent we will have to rez the attachments.
2970 // All other AddNewClient calls find aCircuit.child to be true.
2971 if (aCircuit.child == false)
2972 {
2973 // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to
2974 // start the scripts again (since this is done in RezAttachments()).
2975 // XXX: This is convoluted.
2976 sp.IsChildAgent = false;
2977
2978 if (AttachmentsModule != null)
2979 Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); });
2980 }
2873 } 2981 }
2874 } 2982 else
2875 else 2983 {
2876 { 2984 m_log.WarnFormat(
2877 m_log.WarnFormat( 2985 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence",
2878 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", 2986 sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName);
2879 sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); 2987 }
2880 } 2988
2989 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the
2990 // client is for a root or child agent.
2991 client.SceneAgent = sp;
2881 2992
2882 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the 2993 // Cache the user's name
2883 // client is for a root or child agent. 2994 CacheUserName(sp, aCircuit);
2884 client.SceneAgent = sp; 2995
2996 EventManager.TriggerOnNewClient(client);
2997 if (vialogin)
2998 EventManager.TriggerOnClientLogin(client);
2999 }
2885 3000
2886 m_LastLogin = Util.EnvironmentTickCount(); 3001 m_LastLogin = Util.EnvironmentTickCount();
2887 3002
2888 // Cache the user's name
2889 CacheUserName(sp, aCircuit);
2890
2891 EventManager.TriggerOnNewClient(client);
2892 if (vialogin)
2893 {
2894 EventManager.TriggerOnClientLogin(client);
2895 // Send initial parcel data
2896/* this is done on TriggerOnNewClient by landmanegement respective event handler
2897 Vector3 pos = sp.AbsolutePosition;
2898 ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y);
2899 land.SendLandUpdateToClient(client);
2900*/
2901 }
2902
2903 return sp; 3003 return sp;
2904 } 3004 }
2905 3005
@@ -3439,110 +3539,132 @@ namespace OpenSim.Region.Framework.Scenes
3439 { 3539 {
3440// CheckHeartbeat(); 3540// CheckHeartbeat();
3441 bool isChildAgent = false; 3541 bool isChildAgent = false;
3442 ScenePresence avatar = GetScenePresence(agentID); 3542 AgentCircuitData acd;
3443
3444 if (avatar == null)
3445 {
3446 m_log.WarnFormat(
3447 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID);
3448 3543
3449 return; 3544 lock (m_removeClientLock)
3450 }
3451
3452 try
3453 { 3545 {
3454 isChildAgent = avatar.IsChildAgent; 3546 acd = m_authenticateHandler.GetAgentCircuitData(agentID);
3455 3547
3456 m_log.DebugFormat( 3548 if (acd == null)
3457 "[SCENE]: Removing {0} agent {1} {2} from {3}",
3458 (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName);
3459
3460 // Don't do this to root agents, it's not nice for the viewer
3461 if (closeChildAgents && isChildAgent)
3462 { 3549 {
3463 // Tell a single agent to disconnect from the region. 3550 m_log.ErrorFormat("[SCENE]: No agent circuit found for {0}, aborting Scene.RemoveClient", agentID);
3464 IEventQueue eq = RequestModuleInterface<IEventQueue>(); 3551 return;
3465 if (eq != null)
3466 {
3467 eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID);
3468 }
3469 else
3470 {
3471 avatar.ControllingClient.SendShutdownConnectionNotice();
3472 }
3473 } 3552 }
3474 3553 else
3475 // Only applies to root agents.
3476 if (avatar.ParentID != 0)
3477 { 3554 {
3478 avatar.StandUp(); 3555 // We remove the acd up here to avoid later race conditions if two RemoveClient() calls occurred
3556 // simultaneously.
3557 // We also need to remove by agent ID since NPCs will have no circuit code.
3558 m_authenticateHandler.RemoveCircuit(agentID);
3479 } 3559 }
3560 }
3480 3561
3481 m_sceneGraph.removeUserCount(!isChildAgent); 3562 lock (acd)
3482 3563 {
3483 // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop 3564 ScenePresence avatar = GetScenePresence(agentID);
3484 // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI 3565
3485 if (closeChildAgents && CapsModule != null) 3566 if (avatar == null)
3486 CapsModule.RemoveCaps(agentID);
3487
3488 // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever
3489 // this method is doing is HORRIBLE!!!
3490 avatar.Scene.NeedSceneCacheClear(avatar.UUID);
3491
3492 if (closeChildAgents && !isChildAgent)
3493 { 3567 {
3494 List<ulong> regions = avatar.KnownRegionHandles; 3568 m_log.WarnFormat(
3495 regions.Remove(RegionInfo.RegionHandle); 3569 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID);
3496 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3570
3571 return;
3497 } 3572 }
3498 3573
3499 m_eventManager.TriggerClientClosed(agentID, this); 3574 try
3500 m_eventManager.TriggerOnRemovePresence(agentID);
3501
3502 if (!isChildAgent)
3503 { 3575 {
3504 if (AttachmentsModule != null) 3576 isChildAgent = avatar.IsChildAgent;
3577
3578 m_log.DebugFormat(
3579 "[SCENE]: Removing {0} agent {1} {2} from {3}",
3580 (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName);
3581
3582 // Don't do this to root agents, it's not nice for the viewer
3583 if (closeChildAgents && isChildAgent)
3584 {
3585 // Tell a single agent to disconnect from the region.
3586 IEventQueue eq = RequestModuleInterface<IEventQueue>();
3587 if (eq != null)
3588 {
3589 eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID);
3590 }
3591 else
3592 {
3593 avatar.ControllingClient.SendShutdownConnectionNotice();
3594 }
3595 }
3596
3597 // Only applies to root agents.
3598 if (avatar.ParentID != 0)
3505 { 3599 {
3506 AttachmentsModule.DeRezAttachments(avatar); 3600 avatar.StandUp();
3507 } 3601 }
3508 3602
3509 ForEachClient( 3603 m_sceneGraph.removeUserCount(!isChildAgent);
3510 delegate(IClientAPI client) 3604
3605 // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop
3606 // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI
3607 if (closeChildAgents && CapsModule != null)
3608 CapsModule.RemoveCaps(agentID);
3609
3610// // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever
3611// // this method is doing is HORRIBLE!!!
3612 // Commented pending deletion since this method no longer appears to do anything at all
3613// avatar.Scene.NeedSceneCacheClear(avatar.UUID);
3614
3615 if (closeChildAgents && !isChildAgent)
3616 {
3617 List<ulong> regions = avatar.KnownRegionHandles;
3618 regions.Remove(RegionInfo.RegionHandle);
3619 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3620 }
3621
3622 m_eventManager.TriggerClientClosed(agentID, this);
3623 m_eventManager.TriggerOnRemovePresence(agentID);
3624
3625 if (!isChildAgent)
3626 {
3627 if (AttachmentsModule != null)
3511 { 3628 {
3512 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway 3629 AttachmentsModule.DeRezAttachments(avatar);
3513 try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); } 3630 }
3514 catch (NullReferenceException) { }
3515 });
3516 }
3517
3518 // It's possible for child agents to have transactions if changes are being made cross-border.
3519 if (AgentTransactionsModule != null)
3520 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID);
3521 3631
3522 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3632 ForEachClient(
3523 m_log.Debug("[Scene] The avatar has left the building"); 3633 delegate(IClientAPI client)
3524 } 3634 {
3525 catch (Exception e) 3635 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway
3526 { 3636 try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); }
3527 m_log.Error( 3637 catch (NullReferenceException) { }
3528 string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e); 3638 });
3529 } 3639 }
3530 finally
3531 {
3532 try
3533 {
3534 // Always clean these structures up so that any failure above doesn't cause them to remain in the
3535 // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering
3536 // the same cleanup exception continually.
3537 m_sceneGraph.RemoveScenePresence(agentID);
3538 m_clientManager.Remove(agentID);
3539 3640
3540 avatar.Close(); 3641 // It's possible for child agents to have transactions if changes are being made cross-border.
3642 if (AgentTransactionsModule != null)
3643 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID);
3644 m_log.Debug("[Scene] The avatar has left the building");
3541 } 3645 }
3542 catch (Exception e) 3646 catch (Exception e)
3543 { 3647 {
3544 m_log.Error( 3648 m_log.Error(
3545 string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e); 3649 string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e);
3650 }
3651 finally
3652 {
3653 try
3654 {
3655 // Always clean these structures up so that any failure above doesn't cause them to remain in the
3656 // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering
3657 // the same cleanup exception continually.
3658 m_sceneGraph.RemoveScenePresence(agentID);
3659 m_clientManager.Remove(agentID);
3660
3661 avatar.Close();
3662 }
3663 catch (Exception e)
3664 {
3665 m_log.Error(
3666 string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e);
3667 }
3546 } 3668 }
3547 } 3669 }
3548 3670
@@ -3601,11 +3723,9 @@ namespace OpenSim.Region.Framework.Scenes
3601 3723
3602 /// <summary> 3724 /// <summary>
3603 /// Do the work necessary to initiate a new user connection for a particular scene. 3725 /// Do the work necessary to initiate a new user connection for a particular scene.
3604 /// At the moment, this consists of setting up the caps infrastructure
3605 /// The return bool should allow for connections to be refused, but as not all calling paths
3606 /// take proper notice of it let, we allowed banned users in still.
3607 /// </summary> 3726 /// </summary>
3608 /// <param name="agent">CircuitData of the agent who is connecting</param> 3727 /// <param name="agent">CircuitData of the agent who is connecting</param>
3728 /// <param name="teleportFlags"></param>
3609 /// <param name="reason">Outputs the reason for the false response on this string</param> 3729 /// <param name="reason">Outputs the reason for the false response on this string</param>
3610 /// <returns>True if the region accepts this agent. False if it does not. False will 3730 /// <returns>True if the region accepts this agent. False if it does not. False will
3611 /// also return a reason.</returns> 3731 /// also return a reason.</returns>
@@ -3616,10 +3736,20 @@ namespace OpenSim.Region.Framework.Scenes
3616 3736
3617 /// <summary> 3737 /// <summary>
3618 /// Do the work necessary to initiate a new user connection for a particular scene. 3738 /// Do the work necessary to initiate a new user connection for a particular scene.
3619 /// At the moment, this consists of setting up the caps infrastructure 3739 /// </summary>
3740 /// <remarks>
3741 /// The return bool should allow for connections to be refused, but as not all calling paths
3742 /// take proper notice of it yet, we still allowed banned users in.
3743 ///
3744 /// At the moment this method consists of setting up the caps infrastructure
3620 /// The return bool should allow for connections to be refused, but as not all calling paths 3745 /// The return bool should allow for connections to be refused, but as not all calling paths
3621 /// take proper notice of it let, we allowed banned users in still. 3746 /// take proper notice of it let, we allowed banned users in still.
3622 /// </summary> 3747 ///
3748 /// This method is called by the login service (in the case of login) or another simulator (in the case of region
3749 /// cross or teleport) to initiate the connection. It is not triggered by the viewer itself - the connection
3750 /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of
3751 /// the LLUDP stack).
3752 /// </remarks>
3623 /// <param name="agent">CircuitData of the agent who is connecting</param> 3753 /// <param name="agent">CircuitData of the agent who is connecting</param>
3624 /// <param name="reason">Outputs the reason for the false response on this string</param> 3754 /// <param name="reason">Outputs the reason for the false response on this string</param>
3625 /// <param name="requirePresenceLookup">True for normal presence. False for NPC 3755 /// <param name="requirePresenceLookup">True for normal presence. False for NPC
@@ -3718,83 +3848,86 @@ namespace OpenSim.Region.Framework.Scenes
3718 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", 3848 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.",
3719 sp.Name, sp.UUID, RegionInfo.RegionName); 3849 sp.Name, sp.UUID, RegionInfo.RegionName);
3720 3850
3721 sp.ControllingClient.Close(); 3851 sp.ControllingClient.Close(true, true);
3722 sp = null; 3852 sp = null;
3723 } 3853 }
3724 3854
3725 3855 lock (agent)
3726 //On login test land permisions
3727 if (vialogin)
3728 { 3856 {
3729 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>(); 3857 //On login test land permisions
3730 if (cache != null) 3858 if (vialogin)
3731 cache.Remove(agent.firstname + " " + agent.lastname);
3732 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3733 { 3859 {
3734 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString()); 3860 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3735 return false; 3861 if (cache != null)
3862 cache.Remove(agent.firstname + " " + agent.lastname);
3863 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3864 {
3865 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3866 return false;
3867 }
3736 } 3868 }
3737 }
3738 3869
3739 if (sp == null) // We don't have an [child] agent here already 3870 if (sp == null) // We don't have an [child] agent here already
3740 {
3741 if (requirePresenceLookup)
3742 { 3871 {
3743 try 3872 if (requirePresenceLookup)
3744 { 3873 {
3745 if (!VerifyUserPresence(agent, out reason)) 3874 try
3875 {
3876 if (!VerifyUserPresence(agent, out reason))
3877 return false;
3878 } catch (Exception e)
3879 {
3880 m_log.ErrorFormat(
3881 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace);
3746 return false; 3882 return false;
3747 } catch (Exception e) 3883 }
3884 }
3885
3886 try
3887 {
3888 // Always check estate if this is a login. Always
3889 // check if banned regions are to be blacked out.
3890 if (vialogin || (!m_seeIntoBannedRegion))
3891 {
3892 if (!AuthorizeUser(agent, out reason))
3893 return false;
3894 }
3895 }
3896 catch (Exception e)
3748 { 3897 {
3749 m_log.ErrorFormat( 3898 m_log.ErrorFormat(
3750 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); 3899 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace);
3751 return false; 3900 return false;
3752 } 3901 }
3753 }
3754 3902
3755 try 3903 m_log.InfoFormat(
3756 { 3904 "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})",
3757 // Always check estate if this is a login. Always 3905 RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname,
3758 // check if banned regions are to be blacked out. 3906 agent.AgentID, agent.circuitcode);
3759 if (vialogin || (!m_seeIntoBannedRegion)) 3907
3908 if (CapsModule != null)
3760 { 3909 {
3761 if (!AuthorizeUser(agent, out reason)) 3910 CapsModule.SetAgentCapsSeeds(agent);
3762 return false; 3911 CapsModule.CreateCaps(agent.AgentID);
3763 } 3912 }
3764 } 3913 }
3765 catch (Exception e) 3914 else
3766 { 3915 {
3767 m_log.ErrorFormat( 3916 // Let the SP know how we got here. This has a lot of interesting
3768 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); 3917 // uses down the line.
3769 return false; 3918 sp.TeleportFlags = (TPFlags)teleportFlags;
3770 }
3771 3919
3772 m_log.InfoFormat( 3920 if (sp.IsChildAgent)
3773 "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", 3921 {
3774 RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, 3922 m_log.DebugFormat(
3775 agent.AgentID, agent.circuitcode); 3923 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
3776 3924 agent.AgentID, RegionInfo.RegionName);
3777 if (CapsModule != null)
3778 {
3779 CapsModule.SetAgentCapsSeeds(agent);
3780 CapsModule.CreateCaps(agent.AgentID);
3781 }
3782 } else
3783 {
3784 // Let the SP know how we got here. This has a lot of interesting
3785 // uses down the line.
3786 sp.TeleportFlags = (TPFlags)teleportFlags;
3787 3925
3788 if (sp.IsChildAgent) 3926 sp.AdjustKnownSeeds();
3789 {
3790 m_log.DebugFormat(
3791 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
3792 agent.AgentID, RegionInfo.RegionName);
3793 3927
3794 sp.AdjustKnownSeeds(); 3928 if (CapsModule != null)
3795 3929 CapsModule.SetAgentCapsSeeds(agent);
3796 if (CapsModule != null) 3930 }
3797 CapsModule.SetAgentCapsSeeds(agent);
3798 } 3931 }
3799 } 3932 }
3800 3933
@@ -4225,8 +4358,9 @@ namespace OpenSim.Region.Framework.Scenes
4225 return false; 4358 return false;
4226 } 4359 }
4227 4360
4228 // We have to wait until the viewer contacts this region after receiving EAC. 4361 // We have to wait until the viewer contacts this region
4229 // That calls AddNewClient, which finally creates the ScenePresence 4362 // after receiving the EnableSimulator HTTP Event Queue message. This triggers the viewer to send
4363 // a UseCircuitCode packet which in turn calls AddNewClient which finally creates the ScenePresence.
4230 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); 4364 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID);
4231 4365
4232 if (childAgentUpdate != null) 4366 if (childAgentUpdate != null)
@@ -4321,15 +4455,18 @@ namespace OpenSim.Region.Framework.Scenes
4321 /// Tell a single agent to disconnect from the region. 4455 /// Tell a single agent to disconnect from the region.
4322 /// </summary> 4456 /// </summary>
4323 /// <param name="agentID"></param> 4457 /// <param name="agentID"></param>
4324 /// <param name="childOnly"></param> 4458 /// <param name="force">
4325 public bool IncomingCloseAgent(UUID agentID, bool childOnly) 4459 /// Force the agent to close even if it might be in the middle of some other operation. You do not want to
4460 /// force unless you are absolutely sure that the agent is dead and a normal close is not working.
4461 /// </param>
4462 public bool IncomingCloseAgent(UUID agentID, bool force)
4326 { 4463 {
4327 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 4464 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
4328 4465
4329 ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); 4466 ScenePresence presence = m_sceneGraph.GetScenePresence(agentID);
4330 if (presence != null) 4467 if (presence != null)
4331 { 4468 {
4332 presence.ControllingClient.Close(false); 4469 presence.ControllingClient.Close(force, force);
4333 return true; 4470 return true;
4334 } 4471 }
4335 4472
@@ -4535,6 +4672,16 @@ namespace OpenSim.Region.Framework.Scenes
4535 return LandChannel.GetLandObject(x, y).LandData; 4672 return LandChannel.GetLandObject(x, y).LandData;
4536 } 4673 }
4537 4674
4675 /// <summary>
4676 /// Get LandData by position.
4677 /// </summary>
4678 /// <param name="pos"></param>
4679 /// <returns></returns>
4680 public LandData GetLandData(Vector3 pos)
4681 {
4682 return GetLandData(pos.X, pos.Y);
4683 }
4684
4538 public LandData GetLandData(uint x, uint y) 4685 public LandData GetLandData(uint x, uint y)
4539 { 4686 {
4540 m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y); 4687 m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y);
@@ -4765,13 +4912,24 @@ namespace OpenSim.Region.Framework.Scenes
4765 /// Get a group via its UUID 4912 /// Get a group via its UUID
4766 /// </summary> 4913 /// </summary>
4767 /// <param name="fullID"></param> 4914 /// <param name="fullID"></param>
4768 /// <returns>null if no group with that name exists</returns> 4915 /// <returns>null if no group with that id exists</returns>
4769 public SceneObjectGroup GetSceneObjectGroup(UUID fullID) 4916 public SceneObjectGroup GetSceneObjectGroup(UUID fullID)
4770 { 4917 {
4771 return m_sceneGraph.GetSceneObjectGroup(fullID); 4918 return m_sceneGraph.GetSceneObjectGroup(fullID);
4772 } 4919 }
4773 4920
4774 /// <summary> 4921 /// <summary>
4922 /// Get a group via its local ID
4923 /// </summary>
4924 /// <remarks>This will only return a group if the local ID matches a root part</remarks>
4925 /// <param name="localID"></param>
4926 /// <returns>null if no group with that id exists</returns>
4927 public SceneObjectGroup GetSceneObjectGroup(uint localID)
4928 {
4929 return m_sceneGraph.GetSceneObjectGroup(localID);
4930 }
4931
4932 /// <summary>
4775 /// Get a group by name from the scene (will return the first 4933 /// Get a group by name from the scene (will return the first
4776 /// found, if there are more than one prim with the same name) 4934 /// found, if there are more than one prim with the same name)
4777 /// </summary> 4935 /// </summary>
@@ -4783,6 +4941,18 @@ namespace OpenSim.Region.Framework.Scenes
4783 } 4941 }
4784 4942
4785 /// <summary> 4943 /// <summary>
4944 /// Attempt to get the SOG via its UUID
4945 /// </summary>
4946 /// <param name="fullID"></param>
4947 /// <param name="sog"></param>
4948 /// <returns></returns>
4949 public bool TryGetSceneObjectGroup(UUID fullID, out SceneObjectGroup sog)
4950 {
4951 sog = GetSceneObjectGroup(fullID);
4952 return sog != null;
4953 }
4954
4955 /// <summary>
4786 /// Get a prim by name from the scene (will return the first 4956 /// Get a prim by name from the scene (will return the first
4787 /// found, if there are more than one prim with the same name) 4957 /// found, if there are more than one prim with the same name)
4788 /// </summary> 4958 /// </summary>
@@ -4814,6 +4984,18 @@ namespace OpenSim.Region.Framework.Scenes
4814 } 4984 }
4815 4985
4816 /// <summary> 4986 /// <summary>
4987 /// Attempt to get a prim via its UUID
4988 /// </summary>
4989 /// <param name="fullID"></param>
4990 /// <param name="sop"></param>
4991 /// <returns></returns>
4992 public bool TryGetSceneObjectPart(UUID fullID, out SceneObjectPart sop)
4993 {
4994 sop = GetSceneObjectPart(fullID);
4995 return sop != null;
4996 }
4997
4998 /// <summary>
4817 /// Get a scene object group that contains the prim with the given local id 4999 /// Get a scene object group that contains the prim with the given local id
4818 /// </summary> 5000 /// </summary>
4819 /// <param name="localID"></param> 5001 /// <param name="localID"></param>
@@ -4907,14 +5089,15 @@ namespace OpenSim.Region.Framework.Scenes
4907 client.SendRegionHandle(regionID, handle); 5089 client.SendRegionHandle(regionID, handle);
4908 } 5090 }
4909 5091
4910 public bool NeedSceneCacheClear(UUID agentID) 5092// Commented pending deletion since this method no longer appears to do anything at all
4911 { 5093// public bool NeedSceneCacheClear(UUID agentID)
4912 IInventoryTransferModule inv = RequestModuleInterface<IInventoryTransferModule>(); 5094// {
4913 if (inv == null) 5095// IInventoryTransferModule inv = RequestModuleInterface<IInventoryTransferModule>();
4914 return true; 5096// if (inv == null)
4915 5097// return true;
4916 return inv.NeedSceneCacheClear(agentID, this); 5098//
4917 } 5099// return inv.NeedSceneCacheClear(agentID, this);
5100// }
4918 5101
4919 public void CleanTempObjects() 5102 public void CleanTempObjects()
4920 { 5103 {
@@ -5868,6 +6051,9 @@ Environment.Exit(1);
5868 6051
5869 public string GetExtraSetting(string name) 6052 public string GetExtraSetting(string name)
5870 { 6053 {
6054 if (m_extraSettings == null)
6055 return String.Empty;
6056
5871 string val; 6057 string val;
5872 6058
5873 if (!m_extraSettings.TryGetValue(name, out val)) 6059 if (!m_extraSettings.TryGetValue(name, out val))
@@ -5878,6 +6064,9 @@ Environment.Exit(1);
5878 6064
5879 public void StoreExtraSetting(string name, string val) 6065 public void StoreExtraSetting(string name, string val)
5880 { 6066 {
6067 if (m_extraSettings == null)
6068 return;
6069
5881 string oldVal; 6070 string oldVal;
5882 6071
5883 if (m_extraSettings.TryGetValue(name, out oldVal)) 6072 if (m_extraSettings.TryGetValue(name, out oldVal))
@@ -5895,6 +6084,9 @@ Environment.Exit(1);
5895 6084
5896 public void RemoveExtraSetting(string name) 6085 public void RemoveExtraSetting(string name)
5897 { 6086 {
6087 if (m_extraSettings == null)
6088 return;
6089
5898 if (!m_extraSettings.ContainsKey(name)) 6090 if (!m_extraSettings.ContainsKey(name))
5899 return; 6091 return;
5900 6092