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.cs685
1 files changed, 440 insertions, 245 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 649d545..2543333 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();
@@ -1272,6 +1352,14 @@ namespace OpenSim.Region.Framework.Scenes
1272 m_log.Debug("[SCENE]: Graph close"); 1352 m_log.Debug("[SCENE]: Graph close");
1273 m_sceneGraph.Close(); 1353 m_sceneGraph.Close();
1274 1354
1355 if (!GridService.DeregisterRegion(RegionInfo.RegionID))
1356 m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name);
1357
1358 base.Close();
1359
1360 // XEngine currently listens to the EventManager.OnShutdown event to trigger script stop and persistence.
1361 // Therefore. we must dispose of the PhysicsScene after this to prevent a window where script code can
1362 // attempt to reference a null or disposed physics scene.
1275 if (PhysicsScene != null) 1363 if (PhysicsScene != null)
1276 { 1364 {
1277 m_log.Debug("[SCENE]: Dispose Physics"); 1365 m_log.Debug("[SCENE]: Dispose Physics");
@@ -1281,13 +1369,6 @@ namespace OpenSim.Region.Framework.Scenes
1281 phys.Dispose(); 1369 phys.Dispose();
1282 phys = null; 1370 phys = null;
1283 } 1371 }
1284
1285 if (!GridService.DeregisterRegion(RegionInfo.RegionID))
1286 m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name);
1287
1288 // call the base class Close method.
1289 m_log.Debug("[SCENE]: Base close");
1290 base.Close();
1291 } 1372 }
1292 1373
1293 /// <summary> 1374 /// <summary>
@@ -1295,6 +1376,8 @@ namespace OpenSim.Region.Framework.Scenes
1295 /// </summary> 1376 /// </summary>
1296 public void Start() 1377 public void Start()
1297 { 1378 {
1379 m_active = true;
1380
1298// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); 1381// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName);
1299 1382
1300 //m_heartbeatTimer.Enabled = true; 1383 //m_heartbeatTimer.Enabled = true;
@@ -1354,7 +1437,7 @@ namespace OpenSim.Region.Framework.Scenes
1354 #region Update Methods 1437 #region Update Methods
1355 1438
1356 /// <summary> 1439 /// <summary>
1357 /// Performs per-frame updates regularly 1440 /// Activate the various loops necessary to continually update the scene.
1358 /// </summary> 1441 /// </summary>
1359 private void Heartbeat() 1442 private void Heartbeat()
1360 { 1443 {
@@ -1411,7 +1494,7 @@ namespace OpenSim.Region.Framework.Scenes
1411 List<Vector3> coarseLocations; 1494 List<Vector3> coarseLocations;
1412 List<UUID> avatarUUIDs; 1495 List<UUID> avatarUUIDs;
1413 1496
1414 while (!m_shuttingDown && (endRun == null || MaintenanceRun < endRun)) 1497 while (!m_shuttingDown && ((endRun == null && Active) || MaintenanceRun < endRun))
1415 { 1498 {
1416 runtc = Util.EnvironmentTickCount(); 1499 runtc = Util.EnvironmentTickCount();
1417 ++MaintenanceRun; 1500 ++MaintenanceRun;
@@ -1473,7 +1556,7 @@ namespace OpenSim.Region.Framework.Scenes
1473 int sleepMS; 1556 int sleepMS;
1474 int framestart; 1557 int framestart;
1475 1558
1476 while (!m_shuttingDown && (endFrame == null || Frame < endFrame)) 1559 while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame))
1477 { 1560 {
1478 framestart = Util.EnvironmentTickCount(); 1561 framestart = Util.EnvironmentTickCount();
1479 ++Frame; 1562 ++Frame;
@@ -1672,15 +1755,19 @@ namespace OpenSim.Region.Framework.Scenes
1672 1755
1673 private void CheckAtTargets() 1756 private void CheckAtTargets()
1674 { 1757 {
1675 List<SceneObjectGroup> objs = new List<SceneObjectGroup>(); 1758 List<SceneObjectGroup> objs = null;
1759
1676 lock (m_groupsWithTargets) 1760 lock (m_groupsWithTargets)
1677 { 1761 {
1678 foreach (SceneObjectGroup grp in m_groupsWithTargets.Values) 1762 if (m_groupsWithTargets.Count != 0)
1679 objs.Add(grp); 1763 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values);
1680 } 1764 }
1681 1765
1682 foreach (SceneObjectGroup entry in objs) 1766 if (objs != null)
1683 entry.checkAtTargets(); 1767 {
1768 foreach (SceneObjectGroup entry in objs)
1769 entry.checkAtTargets();
1770 }
1684 } 1771 }
1685 1772
1686 /// <summary> 1773 /// <summary>
@@ -2193,10 +2280,14 @@ namespace OpenSim.Region.Framework.Scenes
2193 public bool AddRestoredSceneObject( 2280 public bool AddRestoredSceneObject(
2194 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 2281 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
2195 { 2282 {
2196 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 2283 if (m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates))
2197 if (result) 2284 {
2198 sceneObject.IsDeleted = false; 2285 sceneObject.IsDeleted = false;
2199 return result; 2286 EventManager.TriggerObjectAddedToScene(sceneObject);
2287 return true;
2288 }
2289
2290 return false;
2200 } 2291 }
2201 2292
2202 /// <summary> 2293 /// <summary>
@@ -2837,77 +2928,89 @@ namespace OpenSim.Region.Framework.Scenes
2837 2928
2838 public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) 2929 public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type)
2839 { 2930 {
2931 ScenePresence sp;
2932 bool vialogin;
2933
2840 // Validation occurs in LLUDPServer 2934 // Validation occurs in LLUDPServer
2935 //
2936 // XXX: A race condition exists here where two simultaneous calls to AddNewClient can interfere with
2937 // each other. In practice, this does not currently occur in the code.
2841 AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); 2938 AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode);
2842 2939
2843 bool vialogin 2940 // We lock here on AgentCircuitData to prevent a race condition between the thread adding a new connection
2844 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 2941 // and a simultaneous one that removes it (as can happen if the client is closed at a particular point
2845 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 2942 // whilst connecting).
2846 2943 //
2847 CheckHeartbeat(); 2944 // It would be easier to lock across all NewUserConnection(), AddNewClient() and
2848 2945 // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service
2849 ScenePresence sp = GetScenePresence(client.AgentId); 2946 // response in some module listening to AddNewClient()) from holding up unrelated agent calls.
2850 2947 //
2851 // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this 2948 // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all
2852 // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause 2949 // AddNewClient() operations (though not other ops).
2853 // other problems, and possible the code calling AddNewClient() should ensure that no client is already 2950 // In the future this can be relieved once locking per agent (not necessarily on AgentCircuitData) is improved.
2854 // connected. 2951 lock (aCircuit)
2855 if (sp == null) 2952 {
2856 { 2953 vialogin
2857 m_log.DebugFormat( 2954 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0
2858 "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", 2955 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2859 client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); 2956
2860 2957 CheckHeartbeat();
2861 m_clientManager.Add(client); 2958
2862 SubscribeToClientEvents(client); 2959 sp = GetScenePresence(client.AgentId);
2863
2864 sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type);
2865 m_eventManager.TriggerOnNewPresence(sp);
2866
2867 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags;
2868 2960
2869 // The first agent upon login is a root agent by design. 2961 // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this
2870 // For this agent we will have to rez the attachments. 2962 // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause
2871 // All other AddNewClient calls find aCircuit.child to be true. 2963 // other problems, and possible the code calling AddNewClient() should ensure that no client is already
2872 if (aCircuit.child == false) 2964 // connected.
2965 if (sp == null)
2873 { 2966 {
2874 // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to 2967 m_log.DebugFormat(
2875 // start the scripts again (since this is done in RezAttachments()). 2968 "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}",
2876 // XXX: This is convoluted. 2969 client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos);
2877 sp.IsChildAgent = false; 2970
2878 2971 m_clientManager.Add(client);
2879 if (AttachmentsModule != null) 2972 SubscribeToClientEvents(client);
2880 Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); }); 2973
2974 sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type);
2975 m_eventManager.TriggerOnNewPresence(sp);
2976
2977 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags;
2978
2979 // The first agent upon login is a root agent by design.
2980 // For this agent we will have to rez the attachments.
2981 // All other AddNewClient calls find aCircuit.child to be true.
2982 if (aCircuit.child == false)
2983 {
2984 // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to
2985 // start the scripts again (since this is done in RezAttachments()).
2986 // XXX: This is convoluted.
2987 sp.IsChildAgent = false;
2988
2989 if (AttachmentsModule != null)
2990 Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); });
2991 }
2881 } 2992 }
2882 } 2993 else
2883 else 2994 {
2884 { 2995 m_log.WarnFormat(
2885 m_log.WarnFormat( 2996 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence",
2886 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", 2997 sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName);
2887 sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); 2998 }
2888 } 2999
3000 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the
3001 // client is for a root or child agent.
3002 client.SceneAgent = sp;
2889 3003
2890 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the 3004 // Cache the user's name
2891 // client is for a root or child agent. 3005 CacheUserName(sp, aCircuit);
2892 client.SceneAgent = sp; 3006
3007 EventManager.TriggerOnNewClient(client);
3008 if (vialogin)
3009 EventManager.TriggerOnClientLogin(client);
3010 }
2893 3011
2894 m_LastLogin = Util.EnvironmentTickCount(); 3012 m_LastLogin = Util.EnvironmentTickCount();
2895 3013
2896 // Cache the user's name
2897 CacheUserName(sp, aCircuit);
2898
2899 EventManager.TriggerOnNewClient(client);
2900 if (vialogin)
2901 {
2902 EventManager.TriggerOnClientLogin(client);
2903 // Send initial parcel data
2904/* this is done on TriggerOnNewClient by landmanegement respective event handler
2905 Vector3 pos = sp.AbsolutePosition;
2906 ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y);
2907 land.SendLandUpdateToClient(client);
2908*/
2909 }
2910
2911 return sp; 3014 return sp;
2912 } 3015 }
2913 3016
@@ -3447,110 +3550,132 @@ namespace OpenSim.Region.Framework.Scenes
3447 { 3550 {
3448// CheckHeartbeat(); 3551// CheckHeartbeat();
3449 bool isChildAgent = false; 3552 bool isChildAgent = false;
3450 ScenePresence avatar = GetScenePresence(agentID); 3553 AgentCircuitData acd;
3451 3554
3452 if (avatar == null) 3555 lock (m_removeClientLock)
3453 { 3556 {
3454 m_log.WarnFormat( 3557 acd = m_authenticateHandler.GetAgentCircuitData(agentID);
3455 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID);
3456
3457 return;
3458 }
3459
3460 try
3461 {
3462 isChildAgent = avatar.IsChildAgent;
3463
3464 m_log.DebugFormat(
3465 "[SCENE]: Removing {0} agent {1} {2} from {3}",
3466 (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName);
3467 3558
3468 // Don't do this to root agents, it's not nice for the viewer 3559 if (acd == null)
3469 if (closeChildAgents && isChildAgent)
3470 { 3560 {
3471 // Tell a single agent to disconnect from the region. 3561 m_log.ErrorFormat("[SCENE]: No agent circuit found for {0}, aborting Scene.RemoveClient", agentID);
3472 IEventQueue eq = RequestModuleInterface<IEventQueue>(); 3562 return;
3473 if (eq != null)
3474 {
3475 eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID);
3476 }
3477 else
3478 {
3479 avatar.ControllingClient.SendShutdownConnectionNotice();
3480 }
3481 } 3563 }
3482 3564 else
3483 // Only applies to root agents.
3484 if (avatar.ParentID != 0)
3485 { 3565 {
3486 avatar.StandUp(); 3566 // We remove the acd up here to avoid later race conditions if two RemoveClient() calls occurred
3567 // simultaneously.
3568 // We also need to remove by agent ID since NPCs will have no circuit code.
3569 m_authenticateHandler.RemoveCircuit(agentID);
3487 } 3570 }
3571 }
3488 3572
3489 m_sceneGraph.removeUserCount(!isChildAgent); 3573 lock (acd)
3490 3574 {
3491 // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop 3575 ScenePresence avatar = GetScenePresence(agentID);
3492 // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI 3576
3493 if (closeChildAgents && CapsModule != null) 3577 if (avatar == null)
3494 CapsModule.RemoveCaps(agentID);
3495
3496 // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever
3497 // this method is doing is HORRIBLE!!!
3498 avatar.Scene.NeedSceneCacheClear(avatar.UUID);
3499
3500 if (closeChildAgents && !isChildAgent)
3501 { 3578 {
3502 List<ulong> regions = avatar.KnownRegionHandles; 3579 m_log.WarnFormat(
3503 regions.Remove(RegionInfo.RegionHandle); 3580 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID);
3504 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3581
3582 return;
3505 } 3583 }
3506 3584
3507 m_eventManager.TriggerClientClosed(agentID, this); 3585 try
3508 m_eventManager.TriggerOnRemovePresence(agentID);
3509
3510 if (!isChildAgent)
3511 { 3586 {
3512 if (AttachmentsModule != null) 3587 isChildAgent = avatar.IsChildAgent;
3588
3589 m_log.DebugFormat(
3590 "[SCENE]: Removing {0} agent {1} {2} from {3}",
3591 (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName);
3592
3593 // Don't do this to root agents, it's not nice for the viewer
3594 if (closeChildAgents && isChildAgent)
3513 { 3595 {
3514 AttachmentsModule.DeRezAttachments(avatar); 3596 // Tell a single agent to disconnect from the region.
3597 IEventQueue eq = RequestModuleInterface<IEventQueue>();
3598 if (eq != null)
3599 {
3600 eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID);
3601 }
3602 else
3603 {
3604 avatar.ControllingClient.SendShutdownConnectionNotice();
3605 }
3515 } 3606 }
3516 3607
3517 ForEachClient( 3608 // Only applies to root agents.
3518 delegate(IClientAPI client) 3609 if (avatar.ParentID != 0)
3610 {
3611 avatar.StandUp();
3612 }
3613
3614 m_sceneGraph.removeUserCount(!isChildAgent);
3615
3616 // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop
3617 // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI
3618 if (closeChildAgents && CapsModule != null)
3619 CapsModule.RemoveCaps(agentID);
3620
3621// // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever
3622// // this method is doing is HORRIBLE!!!
3623 // Commented pending deletion since this method no longer appears to do anything at all
3624// avatar.Scene.NeedSceneCacheClear(avatar.UUID);
3625
3626 if (closeChildAgents && !isChildAgent)
3627 {
3628 List<ulong> regions = avatar.KnownRegionHandles;
3629 regions.Remove(RegionInfo.RegionHandle);
3630 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3631 }
3632
3633 m_eventManager.TriggerClientClosed(agentID, this);
3634 m_eventManager.TriggerOnRemovePresence(agentID);
3635
3636 if (!isChildAgent)
3637 {
3638 if (AttachmentsModule != null)
3519 { 3639 {
3520 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway 3640 AttachmentsModule.DeRezAttachments(avatar);
3521 try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); } 3641 }
3522 catch (NullReferenceException) { }
3523 });
3524 }
3525
3526 // It's possible for child agents to have transactions if changes are being made cross-border.
3527 if (AgentTransactionsModule != null)
3528 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID);
3529 3642
3530 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3643 ForEachClient(
3531 m_log.Debug("[Scene] The avatar has left the building"); 3644 delegate(IClientAPI client)
3532 } 3645 {
3533 catch (Exception e) 3646 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway
3534 { 3647 try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); }
3535 m_log.Error( 3648 catch (NullReferenceException) { }
3536 string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e); 3649 });
3537 } 3650 }
3538 finally
3539 {
3540 try
3541 {
3542 // Always clean these structures up so that any failure above doesn't cause them to remain in the
3543 // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering
3544 // the same cleanup exception continually.
3545 m_sceneGraph.RemoveScenePresence(agentID);
3546 m_clientManager.Remove(agentID);
3547 3651
3548 avatar.Close(); 3652 // It's possible for child agents to have transactions if changes are being made cross-border.
3653 if (AgentTransactionsModule != null)
3654 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID);
3655 m_log.Debug("[Scene] The avatar has left the building");
3549 } 3656 }
3550 catch (Exception e) 3657 catch (Exception e)
3551 { 3658 {
3552 m_log.Error( 3659 m_log.Error(
3553 string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e); 3660 string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e);
3661 }
3662 finally
3663 {
3664 try
3665 {
3666 // Always clean these structures up so that any failure above doesn't cause them to remain in the
3667 // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering
3668 // the same cleanup exception continually.
3669 m_sceneGraph.RemoveScenePresence(agentID);
3670 m_clientManager.Remove(agentID);
3671
3672 avatar.Close();
3673 }
3674 catch (Exception e)
3675 {
3676 m_log.Error(
3677 string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e);
3678 }
3554 } 3679 }
3555 } 3680 }
3556 3681
@@ -3609,11 +3734,9 @@ namespace OpenSim.Region.Framework.Scenes
3609 3734
3610 /// <summary> 3735 /// <summary>
3611 /// Do the work necessary to initiate a new user connection for a particular scene. 3736 /// Do the work necessary to initiate a new user connection for a particular scene.
3612 /// At the moment, this consists of setting up the caps infrastructure
3613 /// The return bool should allow for connections to be refused, but as not all calling paths
3614 /// take proper notice of it let, we allowed banned users in still.
3615 /// </summary> 3737 /// </summary>
3616 /// <param name="agent">CircuitData of the agent who is connecting</param> 3738 /// <param name="agent">CircuitData of the agent who is connecting</param>
3739 /// <param name="teleportFlags"></param>
3617 /// <param name="reason">Outputs the reason for the false response on this string</param> 3740 /// <param name="reason">Outputs the reason for the false response on this string</param>
3618 /// <returns>True if the region accepts this agent. False if it does not. False will 3741 /// <returns>True if the region accepts this agent. False if it does not. False will
3619 /// also return a reason.</returns> 3742 /// also return a reason.</returns>
@@ -3624,10 +3747,20 @@ namespace OpenSim.Region.Framework.Scenes
3624 3747
3625 /// <summary> 3748 /// <summary>
3626 /// Do the work necessary to initiate a new user connection for a particular scene. 3749 /// Do the work necessary to initiate a new user connection for a particular scene.
3627 /// At the moment, this consists of setting up the caps infrastructure 3750 /// </summary>
3751 /// <remarks>
3752 /// The return bool should allow for connections to be refused, but as not all calling paths
3753 /// take proper notice of it yet, we still allowed banned users in.
3754 ///
3755 /// At the moment this method consists of setting up the caps infrastructure
3628 /// The return bool should allow for connections to be refused, but as not all calling paths 3756 /// The return bool should allow for connections to be refused, but as not all calling paths
3629 /// take proper notice of it let, we allowed banned users in still. 3757 /// take proper notice of it let, we allowed banned users in still.
3630 /// </summary> 3758 ///
3759 /// This method is called by the login service (in the case of login) or another simulator (in the case of region
3760 /// cross or teleport) to initiate the connection. It is not triggered by the viewer itself - the connection
3761 /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of
3762 /// the LLUDP stack).
3763 /// </remarks>
3631 /// <param name="agent">CircuitData of the agent who is connecting</param> 3764 /// <param name="agent">CircuitData of the agent who is connecting</param>
3632 /// <param name="reason">Outputs the reason for the false response on this string</param> 3765 /// <param name="reason">Outputs the reason for the false response on this string</param>
3633 /// <param name="requirePresenceLookup">True for normal presence. False for NPC 3766 /// <param name="requirePresenceLookup">True for normal presence. False for NPC
@@ -3726,83 +3859,86 @@ namespace OpenSim.Region.Framework.Scenes
3726 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", 3859 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.",
3727 sp.Name, sp.UUID, RegionInfo.RegionName); 3860 sp.Name, sp.UUID, RegionInfo.RegionName);
3728 3861
3729 sp.ControllingClient.Close(); 3862 sp.ControllingClient.Close(true, true);
3730 sp = null; 3863 sp = null;
3731 } 3864 }
3732 3865
3733 3866 lock (agent)
3734 //On login test land permisions
3735 if (vialogin)
3736 { 3867 {
3737 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>(); 3868 //On login test land permisions
3738 if (cache != null) 3869 if (vialogin)
3739 cache.Remove(agent.firstname + " " + agent.lastname);
3740 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3741 { 3870 {
3742 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString()); 3871 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3743 return false; 3872 if (cache != null)
3873 cache.Remove(agent.firstname + " " + agent.lastname);
3874 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3875 {
3876 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3877 return false;
3878 }
3744 } 3879 }
3745 }
3746 3880
3747 if (sp == null) // We don't have an [child] agent here already 3881 if (sp == null) // We don't have an [child] agent here already
3748 {
3749 if (requirePresenceLookup)
3750 { 3882 {
3751 try 3883 if (requirePresenceLookup)
3752 { 3884 {
3753 if (!VerifyUserPresence(agent, out reason)) 3885 try
3886 {
3887 if (!VerifyUserPresence(agent, out reason))
3888 return false;
3889 } catch (Exception e)
3890 {
3891 m_log.ErrorFormat(
3892 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace);
3754 return false; 3893 return false;
3755 } catch (Exception e) 3894 }
3895 }
3896
3897 try
3898 {
3899 // Always check estate if this is a login. Always
3900 // check if banned regions are to be blacked out.
3901 if (vialogin || (!m_seeIntoBannedRegion))
3902 {
3903 if (!AuthorizeUser(agent, out reason))
3904 return false;
3905 }
3906 }
3907 catch (Exception e)
3756 { 3908 {
3757 m_log.ErrorFormat( 3909 m_log.ErrorFormat(
3758 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); 3910 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace);
3759 return false; 3911 return false;
3760 } 3912 }
3761 }
3762 3913
3763 try 3914 m_log.InfoFormat(
3764 { 3915 "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})",
3765 // Always check estate if this is a login. Always 3916 RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname,
3766 // check if banned regions are to be blacked out. 3917 agent.AgentID, agent.circuitcode);
3767 if (vialogin || (!m_seeIntoBannedRegion)) 3918
3919 if (CapsModule != null)
3768 { 3920 {
3769 if (!AuthorizeUser(agent, out reason)) 3921 CapsModule.SetAgentCapsSeeds(agent);
3770 return false; 3922 CapsModule.CreateCaps(agent.AgentID);
3771 } 3923 }
3772 } 3924 }
3773 catch (Exception e) 3925 else
3774 { 3926 {
3775 m_log.ErrorFormat( 3927 // Let the SP know how we got here. This has a lot of interesting
3776 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); 3928 // uses down the line.
3777 return false; 3929 sp.TeleportFlags = (TPFlags)teleportFlags;
3778 }
3779
3780 m_log.InfoFormat(
3781 "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})",
3782 RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname,
3783 agent.AgentID, agent.circuitcode);
3784 3930
3785 if (CapsModule != null) 3931 if (sp.IsChildAgent)
3786 { 3932 {
3787 CapsModule.SetAgentCapsSeeds(agent); 3933 m_log.DebugFormat(
3788 CapsModule.CreateCaps(agent.AgentID); 3934 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
3789 } 3935 agent.AgentID, RegionInfo.RegionName);
3790 } else
3791 {
3792 // Let the SP know how we got here. This has a lot of interesting
3793 // uses down the line.
3794 sp.TeleportFlags = (TPFlags)teleportFlags;
3795 3936
3796 if (sp.IsChildAgent) 3937 sp.AdjustKnownSeeds();
3797 {
3798 m_log.DebugFormat(
3799 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
3800 agent.AgentID, RegionInfo.RegionName);
3801 3938
3802 sp.AdjustKnownSeeds(); 3939 if (CapsModule != null)
3803 3940 CapsModule.SetAgentCapsSeeds(agent);
3804 if (CapsModule != null) 3941 }
3805 CapsModule.SetAgentCapsSeeds(agent);
3806 } 3942 }
3807 } 3943 }
3808 3944
@@ -4233,8 +4369,9 @@ namespace OpenSim.Region.Framework.Scenes
4233 return false; 4369 return false;
4234 } 4370 }
4235 4371
4236 // We have to wait until the viewer contacts this region after receiving EAC. 4372 // We have to wait until the viewer contacts this region
4237 // That calls AddNewClient, which finally creates the ScenePresence 4373 // after receiving the EnableSimulator HTTP Event Queue message. This triggers the viewer to send
4374 // a UseCircuitCode packet which in turn calls AddNewClient which finally creates the ScenePresence.
4238 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); 4375 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID);
4239 4376
4240 if (childAgentUpdate != null) 4377 if (childAgentUpdate != null)
@@ -4329,15 +4466,18 @@ namespace OpenSim.Region.Framework.Scenes
4329 /// Tell a single agent to disconnect from the region. 4466 /// Tell a single agent to disconnect from the region.
4330 /// </summary> 4467 /// </summary>
4331 /// <param name="agentID"></param> 4468 /// <param name="agentID"></param>
4332 /// <param name="childOnly"></param> 4469 /// <param name="force">
4333 public bool IncomingCloseAgent(UUID agentID, bool childOnly) 4470 /// Force the agent to close even if it might be in the middle of some other operation. You do not want to
4471 /// force unless you are absolutely sure that the agent is dead and a normal close is not working.
4472 /// </param>
4473 public bool IncomingCloseAgent(UUID agentID, bool force)
4334 { 4474 {
4335 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 4475 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
4336 4476
4337 ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); 4477 ScenePresence presence = m_sceneGraph.GetScenePresence(agentID);
4338 if (presence != null) 4478 if (presence != null)
4339 { 4479 {
4340 presence.ControllingClient.Close(false); 4480 presence.ControllingClient.Close(force, force);
4341 return true; 4481 return true;
4342 } 4482 }
4343 4483
@@ -4543,6 +4683,16 @@ namespace OpenSim.Region.Framework.Scenes
4543 return LandChannel.GetLandObject(x, y).LandData; 4683 return LandChannel.GetLandObject(x, y).LandData;
4544 } 4684 }
4545 4685
4686 /// <summary>
4687 /// Get LandData by position.
4688 /// </summary>
4689 /// <param name="pos"></param>
4690 /// <returns></returns>
4691 public LandData GetLandData(Vector3 pos)
4692 {
4693 return GetLandData(pos.X, pos.Y);
4694 }
4695
4546 public LandData GetLandData(uint x, uint y) 4696 public LandData GetLandData(uint x, uint y)
4547 { 4697 {
4548 m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y); 4698 m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y);
@@ -4773,13 +4923,24 @@ namespace OpenSim.Region.Framework.Scenes
4773 /// Get a group via its UUID 4923 /// Get a group via its UUID
4774 /// </summary> 4924 /// </summary>
4775 /// <param name="fullID"></param> 4925 /// <param name="fullID"></param>
4776 /// <returns>null if no group with that name exists</returns> 4926 /// <returns>null if no group with that id exists</returns>
4777 public SceneObjectGroup GetSceneObjectGroup(UUID fullID) 4927 public SceneObjectGroup GetSceneObjectGroup(UUID fullID)
4778 { 4928 {
4779 return m_sceneGraph.GetSceneObjectGroup(fullID); 4929 return m_sceneGraph.GetSceneObjectGroup(fullID);
4780 } 4930 }
4781 4931
4782 /// <summary> 4932 /// <summary>
4933 /// Get a group via its local ID
4934 /// </summary>
4935 /// <remarks>This will only return a group if the local ID matches a root part</remarks>
4936 /// <param name="localID"></param>
4937 /// <returns>null if no group with that id exists</returns>
4938 public SceneObjectGroup GetSceneObjectGroup(uint localID)
4939 {
4940 return m_sceneGraph.GetSceneObjectGroup(localID);
4941 }
4942
4943 /// <summary>
4783 /// Get a group by name from the scene (will return the first 4944 /// Get a group by name from the scene (will return the first
4784 /// found, if there are more than one prim with the same name) 4945 /// found, if there are more than one prim with the same name)
4785 /// </summary> 4946 /// </summary>
@@ -4791,6 +4952,18 @@ namespace OpenSim.Region.Framework.Scenes
4791 } 4952 }
4792 4953
4793 /// <summary> 4954 /// <summary>
4955 /// Attempt to get the SOG via its UUID
4956 /// </summary>
4957 /// <param name="fullID"></param>
4958 /// <param name="sog"></param>
4959 /// <returns></returns>
4960 public bool TryGetSceneObjectGroup(UUID fullID, out SceneObjectGroup sog)
4961 {
4962 sog = GetSceneObjectGroup(fullID);
4963 return sog != null;
4964 }
4965
4966 /// <summary>
4794 /// Get a prim by name from the scene (will return the first 4967 /// Get a prim by name from the scene (will return the first
4795 /// found, if there are more than one prim with the same name) 4968 /// found, if there are more than one prim with the same name)
4796 /// </summary> 4969 /// </summary>
@@ -4822,6 +4995,18 @@ namespace OpenSim.Region.Framework.Scenes
4822 } 4995 }
4823 4996
4824 /// <summary> 4997 /// <summary>
4998 /// Attempt to get a prim via its UUID
4999 /// </summary>
5000 /// <param name="fullID"></param>
5001 /// <param name="sop"></param>
5002 /// <returns></returns>
5003 public bool TryGetSceneObjectPart(UUID fullID, out SceneObjectPart sop)
5004 {
5005 sop = GetSceneObjectPart(fullID);
5006 return sop != null;
5007 }
5008
5009 /// <summary>
4825 /// Get a scene object group that contains the prim with the given local id 5010 /// Get a scene object group that contains the prim with the given local id
4826 /// </summary> 5011 /// </summary>
4827 /// <param name="localID"></param> 5012 /// <param name="localID"></param>
@@ -4915,14 +5100,15 @@ namespace OpenSim.Region.Framework.Scenes
4915 client.SendRegionHandle(regionID, handle); 5100 client.SendRegionHandle(regionID, handle);
4916 } 5101 }
4917 5102
4918 public bool NeedSceneCacheClear(UUID agentID) 5103// Commented pending deletion since this method no longer appears to do anything at all
4919 { 5104// public bool NeedSceneCacheClear(UUID agentID)
4920 IInventoryTransferModule inv = RequestModuleInterface<IInventoryTransferModule>(); 5105// {
4921 if (inv == null) 5106// IInventoryTransferModule inv = RequestModuleInterface<IInventoryTransferModule>();
4922 return true; 5107// if (inv == null)
4923 5108// return true;
4924 return inv.NeedSceneCacheClear(agentID, this); 5109//
4925 } 5110// return inv.NeedSceneCacheClear(agentID, this);
5111// }
4926 5112
4927 public void CleanTempObjects() 5113 public void CleanTempObjects()
4928 { 5114 {
@@ -5876,6 +6062,9 @@ Environment.Exit(1);
5876 6062
5877 public string GetExtraSetting(string name) 6063 public string GetExtraSetting(string name)
5878 { 6064 {
6065 if (m_extraSettings == null)
6066 return String.Empty;
6067
5879 string val; 6068 string val;
5880 6069
5881 if (!m_extraSettings.TryGetValue(name, out val)) 6070 if (!m_extraSettings.TryGetValue(name, out val))
@@ -5886,6 +6075,9 @@ Environment.Exit(1);
5886 6075
5887 public void StoreExtraSetting(string name, string val) 6076 public void StoreExtraSetting(string name, string val)
5888 { 6077 {
6078 if (m_extraSettings == null)
6079 return;
6080
5889 string oldVal; 6081 string oldVal;
5890 6082
5891 if (m_extraSettings.TryGetValue(name, out oldVal)) 6083 if (m_extraSettings.TryGetValue(name, out oldVal))
@@ -5903,6 +6095,9 @@ Environment.Exit(1);
5903 6095
5904 public void RemoveExtraSetting(string name) 6096 public void RemoveExtraSetting(string name)
5905 { 6097 {
6098 if (m_extraSettings == null)
6099 return;
6100
5906 if (!m_extraSettings.ContainsKey(name)) 6101 if (!m_extraSettings.ContainsKey(name))
5907 return; 6102 return;
5908 6103