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.cs699
1 files changed, 443 insertions, 256 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 649d545..c99e37e 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;
@@ -149,7 +177,6 @@ namespace OpenSim.Region.Framework.Scenes
149 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>(); 177 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>();
150 protected List<RegionInfo> m_neighbours = new List<RegionInfo>(); 178 protected List<RegionInfo> m_neighbours = new List<RegionInfo>();
151 protected string m_simulatorVersion = "OpenSimulator Server"; 179 protected string m_simulatorVersion = "OpenSimulator Server";
152 protected ModuleLoader m_moduleLoader;
153 protected AgentCircuitManager m_authenticateHandler; 180 protected AgentCircuitManager m_authenticateHandler;
154 protected SceneCommunicationService m_sceneGridService; 181 protected SceneCommunicationService m_sceneGridService;
155 protected ISnmpModule m_snmpService = null; 182 protected ISnmpModule m_snmpService = null;
@@ -285,6 +312,31 @@ namespace OpenSim.Region.Framework.Scenes
285 } 312 }
286 private volatile bool m_shuttingDown; 313 private volatile bool m_shuttingDown;
287 314
315 /// <summary>
316 /// Is the scene active?
317 /// </summary>
318 /// <remarks>
319 /// If false, maintenance and update loops are not being run. Updates can still be triggered manually if
320 /// the scene is not active.
321 /// </remarks>
322 public bool Active
323 {
324 get { return m_active; }
325 set
326 {
327 if (value)
328 {
329 if (!m_active)
330 Start();
331 }
332 else
333 {
334 m_active = false;
335 }
336 }
337 }
338 private volatile bool m_active;
339
288// private int m_lastUpdate; 340// private int m_lastUpdate;
289 private bool m_firstHeartbeat = true; 341 private bool m_firstHeartbeat = true;
290 342
@@ -626,7 +678,7 @@ namespace OpenSim.Region.Framework.Scenes
626 public Scene(RegionInfo regInfo, AgentCircuitManager authen, 678 public Scene(RegionInfo regInfo, AgentCircuitManager authen,
627 SceneCommunicationService sceneGridService, 679 SceneCommunicationService sceneGridService,
628 ISimulationDataService simDataService, IEstateDataService estateDataService, 680 ISimulationDataService simDataService, IEstateDataService estateDataService,
629 ModuleLoader moduleLoader, bool dumpAssetsToFile, 681 bool dumpAssetsToFile,
630 IConfigSource config, string simulatorVersion) 682 IConfigSource config, string simulatorVersion)
631 : this(regInfo) 683 : this(regInfo)
632 { 684 {
@@ -637,7 +689,6 @@ namespace OpenSim.Region.Framework.Scenes
637 Random random = new Random(); 689 Random random = new Random();
638 690
639 m_lastAllocatedLocalId = (uint)(random.NextDouble() * (double)(uint.MaxValue / 2)) + (uint)(uint.MaxValue / 4); 691 m_lastAllocatedLocalId = (uint)(random.NextDouble() * (double)(uint.MaxValue / 2)) + (uint)(uint.MaxValue / 4);
640 m_moduleLoader = moduleLoader;
641 m_authenticateHandler = authen; 692 m_authenticateHandler = authen;
642 m_sceneGridService = sceneGridService; 693 m_sceneGridService = sceneGridService;
643 m_SimulationDataService = simDataService; 694 m_SimulationDataService = simDataService;
@@ -746,12 +797,24 @@ namespace OpenSim.Region.Framework.Scenes
746 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true); 797 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true);
747 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true); 798 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
748 799
749 m_maxNonphys = startupConfig.GetFloat("NonphysicalPrimMax", m_maxNonphys); 800 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys);
801 if (RegionInfo.NonphysPrimMin > 0)
802 {
803 m_minNonphys = RegionInfo.NonphysPrimMin;
804 }
805
806 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys);
750 if (RegionInfo.NonphysPrimMax > 0) 807 if (RegionInfo.NonphysPrimMax > 0)
751 { 808 {
752 m_maxNonphys = RegionInfo.NonphysPrimMax; 809 m_maxNonphys = RegionInfo.NonphysPrimMax;
753 } 810 }
754 811
812 m_minPhys = startupConfig.GetFloat("PhysicalPrimMin", m_minPhys);
813 if (RegionInfo.PhysPrimMin > 0)
814 {
815 m_minPhys = RegionInfo.PhysPrimMin;
816 }
817
755 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys); 818 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys);
756 819
757 if (RegionInfo.PhysPrimMax > 0) 820 if (RegionInfo.PhysPrimMax > 0)
@@ -759,6 +822,12 @@ namespace OpenSim.Region.Framework.Scenes
759 m_maxPhys = RegionInfo.PhysPrimMax; 822 m_maxPhys = RegionInfo.PhysPrimMax;
760 } 823 }
761 824
825 m_linksetCapacity = startupConfig.GetInt("LinksetPrims", m_linksetCapacity);
826 if (RegionInfo.LinksetCapacity > 0)
827 {
828 m_linksetCapacity = RegionInfo.LinksetCapacity;
829 }
830
762 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest"); 831 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest");
763 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false); 832 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false);
764 833
@@ -784,13 +853,6 @@ namespace OpenSim.Region.Framework.Scenes
784 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 853 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
785 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine); 854 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
786 855
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); 856 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
795 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion); 857 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
796 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false); 858 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
@@ -854,6 +916,8 @@ namespace OpenSim.Region.Framework.Scenes
854 } 916 }
855 917
856 // FIXME: Ultimately this should be in a module. 918 // FIXME: Ultimately this should be in a module.
919 SendPeriodicAppearanceUpdates = true;
920
857 IConfig appearanceConfig = m_config.Configs["Appearance"]; 921 IConfig appearanceConfig = m_config.Configs["Appearance"];
858 if (appearanceConfig != null) 922 if (appearanceConfig != null)
859 { 923 {
@@ -1103,15 +1167,9 @@ namespace OpenSim.Region.Framework.Scenes
1103 } 1167 }
1104 } 1168 }
1105 1169
1106 m_log.Error("[REGION]: Closing"); 1170 m_log.InfoFormat("[REGION]: Restarting region {0}", Name);
1107 Close();
1108 1171
1109 if (PhysicsScene != null) 1172 Close();
1110 {
1111 PhysicsScene.Dispose();
1112 }
1113
1114 m_log.Error("[REGION]: Firing Region Restart Message");
1115 1173
1116 base.Restart(); 1174 base.Restart();
1117 } 1175 }
@@ -1151,6 +1209,14 @@ namespace OpenSim.Region.Framework.Scenes
1151 1209
1152 public void SetSceneCoreDebug(Dictionary<string, string> options) 1210 public void SetSceneCoreDebug(Dictionary<string, string> options)
1153 { 1211 {
1212 if (options.ContainsKey("active"))
1213 {
1214 bool active;
1215
1216 if (bool.TryParse(options["active"], out active))
1217 Active = active;
1218 }
1219
1154 if (options.ContainsKey("scripting")) 1220 if (options.ContainsKey("scripting"))
1155 { 1221 {
1156 bool enableScripts = true; 1222 bool enableScripts = true;
@@ -1226,6 +1292,12 @@ namespace OpenSim.Region.Framework.Scenes
1226 // This is the method that shuts down the scene. 1292 // This is the method that shuts down the scene.
1227 public override void Close() 1293 public override void Close()
1228 { 1294 {
1295 if (m_shuttingDown)
1296 {
1297 m_log.WarnFormat("[SCENE]: Ignoring close request because already closing {0}", Name);
1298 return;
1299 }
1300
1229 m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName); 1301 m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName);
1230 1302
1231 StatsReporter.Close(); 1303 StatsReporter.Close();
@@ -1272,6 +1344,14 @@ namespace OpenSim.Region.Framework.Scenes
1272 m_log.Debug("[SCENE]: Graph close"); 1344 m_log.Debug("[SCENE]: Graph close");
1273 m_sceneGraph.Close(); 1345 m_sceneGraph.Close();
1274 1346
1347 if (!GridService.DeregisterRegion(RegionInfo.RegionID))
1348 m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name);
1349
1350 base.Close();
1351
1352 // XEngine currently listens to the EventManager.OnShutdown event to trigger script stop and persistence.
1353 // Therefore. we must dispose of the PhysicsScene after this to prevent a window where script code can
1354 // attempt to reference a null or disposed physics scene.
1275 if (PhysicsScene != null) 1355 if (PhysicsScene != null)
1276 { 1356 {
1277 m_log.Debug("[SCENE]: Dispose Physics"); 1357 m_log.Debug("[SCENE]: Dispose Physics");
@@ -1281,13 +1361,6 @@ namespace OpenSim.Region.Framework.Scenes
1281 phys.Dispose(); 1361 phys.Dispose();
1282 phys = null; 1362 phys = null;
1283 } 1363 }
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 } 1364 }
1292 1365
1293 /// <summary> 1366 /// <summary>
@@ -1295,6 +1368,8 @@ namespace OpenSim.Region.Framework.Scenes
1295 /// </summary> 1368 /// </summary>
1296 public void Start() 1369 public void Start()
1297 { 1370 {
1371 m_active = true;
1372
1298// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); 1373// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName);
1299 1374
1300 //m_heartbeatTimer.Enabled = true; 1375 //m_heartbeatTimer.Enabled = true;
@@ -1354,7 +1429,7 @@ namespace OpenSim.Region.Framework.Scenes
1354 #region Update Methods 1429 #region Update Methods
1355 1430
1356 /// <summary> 1431 /// <summary>
1357 /// Performs per-frame updates regularly 1432 /// Activate the various loops necessary to continually update the scene.
1358 /// </summary> 1433 /// </summary>
1359 private void Heartbeat() 1434 private void Heartbeat()
1360 { 1435 {
@@ -1411,7 +1486,7 @@ namespace OpenSim.Region.Framework.Scenes
1411 List<Vector3> coarseLocations; 1486 List<Vector3> coarseLocations;
1412 List<UUID> avatarUUIDs; 1487 List<UUID> avatarUUIDs;
1413 1488
1414 while (!m_shuttingDown && (endRun == null || MaintenanceRun < endRun)) 1489 while (!m_shuttingDown && ((endRun == null && Active) || MaintenanceRun < endRun))
1415 { 1490 {
1416 runtc = Util.EnvironmentTickCount(); 1491 runtc = Util.EnvironmentTickCount();
1417 ++MaintenanceRun; 1492 ++MaintenanceRun;
@@ -1473,7 +1548,7 @@ namespace OpenSim.Region.Framework.Scenes
1473 int sleepMS; 1548 int sleepMS;
1474 int framestart; 1549 int framestart;
1475 1550
1476 while (!m_shuttingDown && (endFrame == null || Frame < endFrame)) 1551 while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame))
1477 { 1552 {
1478 framestart = Util.EnvironmentTickCount(); 1553 framestart = Util.EnvironmentTickCount();
1479 ++Frame; 1554 ++Frame;
@@ -1672,15 +1747,19 @@ namespace OpenSim.Region.Framework.Scenes
1672 1747
1673 private void CheckAtTargets() 1748 private void CheckAtTargets()
1674 { 1749 {
1675 List<SceneObjectGroup> objs = new List<SceneObjectGroup>(); 1750 List<SceneObjectGroup> objs = null;
1751
1676 lock (m_groupsWithTargets) 1752 lock (m_groupsWithTargets)
1677 { 1753 {
1678 foreach (SceneObjectGroup grp in m_groupsWithTargets.Values) 1754 if (m_groupsWithTargets.Count != 0)
1679 objs.Add(grp); 1755 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values);
1680 } 1756 }
1681 1757
1682 foreach (SceneObjectGroup entry in objs) 1758 if (objs != null)
1683 entry.checkAtTargets(); 1759 {
1760 foreach (SceneObjectGroup entry in objs)
1761 entry.checkAtTargets();
1762 }
1684 } 1763 }
1685 1764
1686 /// <summary> 1765 /// <summary>
@@ -2193,10 +2272,14 @@ namespace OpenSim.Region.Framework.Scenes
2193 public bool AddRestoredSceneObject( 2272 public bool AddRestoredSceneObject(
2194 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 2273 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
2195 { 2274 {
2196 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 2275 if (m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates))
2197 if (result) 2276 {
2198 sceneObject.IsDeleted = false; 2277 sceneObject.IsDeleted = false;
2199 return result; 2278 EventManager.TriggerObjectAddedToScene(sceneObject);
2279 return true;
2280 }
2281
2282 return false;
2200 } 2283 }
2201 2284
2202 /// <summary> 2285 /// <summary>
@@ -2837,77 +2920,89 @@ namespace OpenSim.Region.Framework.Scenes
2837 2920
2838 public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) 2921 public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type)
2839 { 2922 {
2923 ScenePresence sp;
2924 bool vialogin;
2925
2840 // Validation occurs in LLUDPServer 2926 // Validation occurs in LLUDPServer
2927 //
2928 // XXX: A race condition exists here where two simultaneous calls to AddNewClient can interfere with
2929 // each other. In practice, this does not currently occur in the code.
2841 AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); 2930 AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode);
2842 2931
2843 bool vialogin 2932 // 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 2933 // 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; 2934 // whilst connecting).
2846 2935 //
2847 CheckHeartbeat(); 2936 // It would be easier to lock across all NewUserConnection(), AddNewClient() and
2848 2937 // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service
2849 ScenePresence sp = GetScenePresence(client.AgentId); 2938 // response in some module listening to AddNewClient()) from holding up unrelated agent calls.
2850 2939 //
2851 // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this 2940 // 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 2941 // AddNewClient() operations (though not other ops).
2853 // other problems, and possible the code calling AddNewClient() should ensure that no client is already 2942 // In the future this can be relieved once locking per agent (not necessarily on AgentCircuitData) is improved.
2854 // connected. 2943 lock (aCircuit)
2855 if (sp == null) 2944 {
2856 { 2945 vialogin
2857 m_log.DebugFormat( 2946 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0
2858 "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", 2947 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2859 client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); 2948
2860 2949 CheckHeartbeat();
2861 m_clientManager.Add(client); 2950
2862 SubscribeToClientEvents(client); 2951 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 2952
2869 // The first agent upon login is a root agent by design. 2953 // 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. 2954 // 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. 2955 // other problems, and possible the code calling AddNewClient() should ensure that no client is already
2872 if (aCircuit.child == false) 2956 // connected.
2957 if (sp == null)
2873 { 2958 {
2874 // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to 2959 m_log.DebugFormat(
2875 // start the scripts again (since this is done in RezAttachments()). 2960 "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}",
2876 // XXX: This is convoluted. 2961 client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos);
2877 sp.IsChildAgent = false; 2962
2878 2963 m_clientManager.Add(client);
2879 if (AttachmentsModule != null) 2964 SubscribeToClientEvents(client);
2880 Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); }); 2965
2966 sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type);
2967 m_eventManager.TriggerOnNewPresence(sp);
2968
2969 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags;
2970
2971 // The first agent upon login is a root agent by design.
2972 // For this agent we will have to rez the attachments.
2973 // All other AddNewClient calls find aCircuit.child to be true.
2974 if (aCircuit.child == false)
2975 {
2976 // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to
2977 // start the scripts again (since this is done in RezAttachments()).
2978 // XXX: This is convoluted.
2979 sp.IsChildAgent = false;
2980
2981 if (AttachmentsModule != null)
2982 Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); });
2983 }
2881 } 2984 }
2882 } 2985 else
2883 else 2986 {
2884 { 2987 m_log.WarnFormat(
2885 m_log.WarnFormat( 2988 "[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", 2989 sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName);
2887 sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); 2990 }
2888 } 2991
2992 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the
2993 // client is for a root or child agent.
2994 client.SceneAgent = sp;
2889 2995
2890 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the 2996 // Cache the user's name
2891 // client is for a root or child agent. 2997 CacheUserName(sp, aCircuit);
2892 client.SceneAgent = sp; 2998
2999 EventManager.TriggerOnNewClient(client);
3000 if (vialogin)
3001 EventManager.TriggerOnClientLogin(client);
3002 }
2893 3003
2894 m_LastLogin = Util.EnvironmentTickCount(); 3004 m_LastLogin = Util.EnvironmentTickCount();
2895 3005
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; 3006 return sp;
2912 } 3007 }
2913 3008
@@ -3447,110 +3542,132 @@ namespace OpenSim.Region.Framework.Scenes
3447 { 3542 {
3448// CheckHeartbeat(); 3543// CheckHeartbeat();
3449 bool isChildAgent = false; 3544 bool isChildAgent = false;
3450 ScenePresence avatar = GetScenePresence(agentID); 3545 AgentCircuitData acd;
3451
3452 if (avatar == null)
3453 {
3454 m_log.WarnFormat(
3455 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID);
3456 3546
3457 return; 3547 lock (m_removeClientLock)
3458 }
3459
3460 try
3461 { 3548 {
3462 isChildAgent = avatar.IsChildAgent; 3549 acd = m_authenticateHandler.GetAgentCircuitData(agentID);
3463 3550
3464 m_log.DebugFormat( 3551 if (acd == null)
3465 "[SCENE]: Removing {0} agent {1} {2} from {3}",
3466 (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName);
3467
3468 // Don't do this to root agents, it's not nice for the viewer
3469 if (closeChildAgents && isChildAgent)
3470 { 3552 {
3471 // Tell a single agent to disconnect from the region. 3553 m_log.ErrorFormat("[SCENE]: No agent circuit found for {0}, aborting Scene.RemoveClient", agentID);
3472 IEventQueue eq = RequestModuleInterface<IEventQueue>(); 3554 return;
3473 if (eq != null)
3474 {
3475 eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID);
3476 }
3477 else
3478 {
3479 avatar.ControllingClient.SendShutdownConnectionNotice();
3480 }
3481 } 3555 }
3482 3556 else
3483 // Only applies to root agents.
3484 if (avatar.ParentID != 0)
3485 { 3557 {
3486 avatar.StandUp(); 3558 // We remove the acd up here to avoid later race conditions if two RemoveClient() calls occurred
3559 // simultaneously.
3560 // We also need to remove by agent ID since NPCs will have no circuit code.
3561 m_authenticateHandler.RemoveCircuit(agentID);
3487 } 3562 }
3563 }
3488 3564
3489 m_sceneGraph.removeUserCount(!isChildAgent); 3565 lock (acd)
3490 3566 {
3491 // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop 3567 ScenePresence avatar = GetScenePresence(agentID);
3492 // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI 3568
3493 if (closeChildAgents && CapsModule != null) 3569 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 { 3570 {
3502 List<ulong> regions = avatar.KnownRegionHandles; 3571 m_log.WarnFormat(
3503 regions.Remove(RegionInfo.RegionHandle); 3572 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID);
3504 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3573
3574 return;
3505 } 3575 }
3506 3576
3507 m_eventManager.TriggerClientClosed(agentID, this); 3577 try
3508 m_eventManager.TriggerOnRemovePresence(agentID);
3509
3510 if (!isChildAgent)
3511 { 3578 {
3512 if (AttachmentsModule != null) 3579 isChildAgent = avatar.IsChildAgent;
3580
3581 m_log.DebugFormat(
3582 "[SCENE]: Removing {0} agent {1} {2} from {3}",
3583 (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName);
3584
3585 // Don't do this to root agents, it's not nice for the viewer
3586 if (closeChildAgents && isChildAgent)
3513 { 3587 {
3514 AttachmentsModule.DeRezAttachments(avatar); 3588 // Tell a single agent to disconnect from the region.
3589 IEventQueue eq = RequestModuleInterface<IEventQueue>();
3590 if (eq != null)
3591 {
3592 eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID);
3593 }
3594 else
3595 {
3596 avatar.ControllingClient.SendShutdownConnectionNotice();
3597 }
3515 } 3598 }
3516 3599
3517 ForEachClient( 3600 // Only applies to root agents.
3518 delegate(IClientAPI client) 3601 if (avatar.ParentID != 0)
3602 {
3603 avatar.StandUp();
3604 }
3605
3606 m_sceneGraph.removeUserCount(!isChildAgent);
3607
3608 // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop
3609 // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI
3610 if (closeChildAgents && CapsModule != null)
3611 CapsModule.RemoveCaps(agentID);
3612
3613// // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever
3614// // this method is doing is HORRIBLE!!!
3615 // Commented pending deletion since this method no longer appears to do anything at all
3616// avatar.Scene.NeedSceneCacheClear(avatar.UUID);
3617
3618 if (closeChildAgents && !isChildAgent)
3619 {
3620 List<ulong> regions = avatar.KnownRegionHandles;
3621 regions.Remove(RegionInfo.RegionHandle);
3622 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3623 }
3624
3625 m_eventManager.TriggerClientClosed(agentID, this);
3626 m_eventManager.TriggerOnRemovePresence(agentID);
3627
3628 if (!isChildAgent)
3629 {
3630 if (AttachmentsModule != null)
3519 { 3631 {
3520 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway 3632 AttachmentsModule.DeRezAttachments(avatar);
3521 try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); } 3633 }
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 3634
3530 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3635 ForEachClient(
3531 m_log.Debug("[Scene] The avatar has left the building"); 3636 delegate(IClientAPI client)
3532 } 3637 {
3533 catch (Exception e) 3638 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway
3534 { 3639 try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); }
3535 m_log.Error( 3640 catch (NullReferenceException) { }
3536 string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e); 3641 });
3537 } 3642 }
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 3643
3548 avatar.Close(); 3644 // It's possible for child agents to have transactions if changes are being made cross-border.
3645 if (AgentTransactionsModule != null)
3646 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID);
3647 m_log.Debug("[Scene] The avatar has left the building");
3549 } 3648 }
3550 catch (Exception e) 3649 catch (Exception e)
3551 { 3650 {
3552 m_log.Error( 3651 m_log.Error(
3553 string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e); 3652 string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e);
3653 }
3654 finally
3655 {
3656 try
3657 {
3658 // Always clean these structures up so that any failure above doesn't cause them to remain in the
3659 // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering
3660 // the same cleanup exception continually.
3661 m_sceneGraph.RemoveScenePresence(agentID);
3662 m_clientManager.Remove(agentID);
3663
3664 avatar.Close();
3665 }
3666 catch (Exception e)
3667 {
3668 m_log.Error(
3669 string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e);
3670 }
3554 } 3671 }
3555 } 3672 }
3556 3673
@@ -3609,11 +3726,9 @@ namespace OpenSim.Region.Framework.Scenes
3609 3726
3610 /// <summary> 3727 /// <summary>
3611 /// Do the work necessary to initiate a new user connection for a particular scene. 3728 /// 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> 3729 /// </summary>
3616 /// <param name="agent">CircuitData of the agent who is connecting</param> 3730 /// <param name="agent">CircuitData of the agent who is connecting</param>
3731 /// <param name="teleportFlags"></param>
3617 /// <param name="reason">Outputs the reason for the false response on this string</param> 3732 /// <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 3733 /// <returns>True if the region accepts this agent. False if it does not. False will
3619 /// also return a reason.</returns> 3734 /// also return a reason.</returns>
@@ -3624,10 +3739,20 @@ namespace OpenSim.Region.Framework.Scenes
3624 3739
3625 /// <summary> 3740 /// <summary>
3626 /// Do the work necessary to initiate a new user connection for a particular scene. 3741 /// 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 3742 /// </summary>
3743 /// <remarks>
3744 /// The return bool should allow for connections to be refused, but as not all calling paths
3745 /// take proper notice of it yet, we still allowed banned users in.
3746 ///
3747 /// 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 3748 /// 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. 3749 /// take proper notice of it let, we allowed banned users in still.
3630 /// </summary> 3750 ///
3751 /// This method is called by the login service (in the case of login) or another simulator (in the case of region
3752 /// cross or teleport) to initiate the connection. It is not triggered by the viewer itself - the connection
3753 /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of
3754 /// the LLUDP stack).
3755 /// </remarks>
3631 /// <param name="agent">CircuitData of the agent who is connecting</param> 3756 /// <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> 3757 /// <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 3758 /// <param name="requirePresenceLookup">True for normal presence. False for NPC
@@ -3726,83 +3851,86 @@ namespace OpenSim.Region.Framework.Scenes
3726 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", 3851 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.",
3727 sp.Name, sp.UUID, RegionInfo.RegionName); 3852 sp.Name, sp.UUID, RegionInfo.RegionName);
3728 3853
3729 sp.ControllingClient.Close(); 3854 sp.ControllingClient.Close(true, true);
3730 sp = null; 3855 sp = null;
3731 } 3856 }
3732 3857
3733 3858 lock (agent)
3734 //On login test land permisions
3735 if (vialogin)
3736 { 3859 {
3737 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>(); 3860 //On login test land permisions
3738 if (cache != null) 3861 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 { 3862 {
3742 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString()); 3863 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3743 return false; 3864 if (cache != null)
3865 cache.Remove(agent.firstname + " " + agent.lastname);
3866 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3867 {
3868 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3869 return false;
3870 }
3744 } 3871 }
3745 }
3746 3872
3747 if (sp == null) // We don't have an [child] agent here already 3873 if (sp == null) // We don't have an [child] agent here already
3748 {
3749 if (requirePresenceLookup)
3750 { 3874 {
3751 try 3875 if (requirePresenceLookup)
3752 { 3876 {
3753 if (!VerifyUserPresence(agent, out reason)) 3877 try
3878 {
3879 if (!VerifyUserPresence(agent, out reason))
3880 return false;
3881 } catch (Exception e)
3882 {
3883 m_log.ErrorFormat(
3884 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace);
3754 return false; 3885 return false;
3755 } catch (Exception e) 3886 }
3887 }
3888
3889 try
3890 {
3891 // Always check estate if this is a login. Always
3892 // check if banned regions are to be blacked out.
3893 if (vialogin || (!m_seeIntoBannedRegion))
3894 {
3895 if (!AuthorizeUser(agent, out reason))
3896 return false;
3897 }
3898 }
3899 catch (Exception e)
3756 { 3900 {
3757 m_log.ErrorFormat( 3901 m_log.ErrorFormat(
3758 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); 3902 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace);
3759 return false; 3903 return false;
3760 } 3904 }
3761 }
3762 3905
3763 try 3906 m_log.InfoFormat(
3764 { 3907 "[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 3908 RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname,
3766 // check if banned regions are to be blacked out. 3909 agent.AgentID, agent.circuitcode);
3767 if (vialogin || (!m_seeIntoBannedRegion)) 3910
3911 if (CapsModule != null)
3768 { 3912 {
3769 if (!AuthorizeUser(agent, out reason)) 3913 CapsModule.SetAgentCapsSeeds(agent);
3770 return false; 3914 CapsModule.CreateCaps(agent.AgentID);
3771 } 3915 }
3772 } 3916 }
3773 catch (Exception e) 3917 else
3774 { 3918 {
3775 m_log.ErrorFormat( 3919 // 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); 3920 // uses down the line.
3777 return false; 3921 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 3922
3785 if (CapsModule != null) 3923 if (sp.IsChildAgent)
3786 { 3924 {
3787 CapsModule.SetAgentCapsSeeds(agent); 3925 m_log.DebugFormat(
3788 CapsModule.CreateCaps(agent.AgentID); 3926 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
3789 } 3927 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 3928
3796 if (sp.IsChildAgent) 3929 sp.AdjustKnownSeeds();
3797 {
3798 m_log.DebugFormat(
3799 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
3800 agent.AgentID, RegionInfo.RegionName);
3801 3930
3802 sp.AdjustKnownSeeds(); 3931 if (CapsModule != null)
3803 3932 CapsModule.SetAgentCapsSeeds(agent);
3804 if (CapsModule != null) 3933 }
3805 CapsModule.SetAgentCapsSeeds(agent);
3806 } 3934 }
3807 } 3935 }
3808 3936
@@ -4233,8 +4361,9 @@ namespace OpenSim.Region.Framework.Scenes
4233 return false; 4361 return false;
4234 } 4362 }
4235 4363
4236 // We have to wait until the viewer contacts this region after receiving EAC. 4364 // We have to wait until the viewer contacts this region
4237 // That calls AddNewClient, which finally creates the ScenePresence 4365 // after receiving the EnableSimulator HTTP Event Queue message. This triggers the viewer to send
4366 // a UseCircuitCode packet which in turn calls AddNewClient which finally creates the ScenePresence.
4238 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); 4367 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID);
4239 4368
4240 if (childAgentUpdate != null) 4369 if (childAgentUpdate != null)
@@ -4329,15 +4458,18 @@ namespace OpenSim.Region.Framework.Scenes
4329 /// Tell a single agent to disconnect from the region. 4458 /// Tell a single agent to disconnect from the region.
4330 /// </summary> 4459 /// </summary>
4331 /// <param name="agentID"></param> 4460 /// <param name="agentID"></param>
4332 /// <param name="childOnly"></param> 4461 /// <param name="force">
4333 public bool IncomingCloseAgent(UUID agentID, bool childOnly) 4462 /// Force the agent to close even if it might be in the middle of some other operation. You do not want to
4463 /// force unless you are absolutely sure that the agent is dead and a normal close is not working.
4464 /// </param>
4465 public bool IncomingCloseAgent(UUID agentID, bool force)
4334 { 4466 {
4335 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 4467 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
4336 4468
4337 ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); 4469 ScenePresence presence = m_sceneGraph.GetScenePresence(agentID);
4338 if (presence != null) 4470 if (presence != null)
4339 { 4471 {
4340 presence.ControllingClient.Close(false); 4472 presence.ControllingClient.Close(force, force);
4341 return true; 4473 return true;
4342 } 4474 }
4343 4475
@@ -4543,6 +4675,16 @@ namespace OpenSim.Region.Framework.Scenes
4543 return LandChannel.GetLandObject(x, y).LandData; 4675 return LandChannel.GetLandObject(x, y).LandData;
4544 } 4676 }
4545 4677
4678 /// <summary>
4679 /// Get LandData by position.
4680 /// </summary>
4681 /// <param name="pos"></param>
4682 /// <returns></returns>
4683 public LandData GetLandData(Vector3 pos)
4684 {
4685 return GetLandData(pos.X, pos.Y);
4686 }
4687
4546 public LandData GetLandData(uint x, uint y) 4688 public LandData GetLandData(uint x, uint y)
4547 { 4689 {
4548 m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y); 4690 m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y);
@@ -4773,13 +4915,24 @@ namespace OpenSim.Region.Framework.Scenes
4773 /// Get a group via its UUID 4915 /// Get a group via its UUID
4774 /// </summary> 4916 /// </summary>
4775 /// <param name="fullID"></param> 4917 /// <param name="fullID"></param>
4776 /// <returns>null if no group with that name exists</returns> 4918 /// <returns>null if no group with that id exists</returns>
4777 public SceneObjectGroup GetSceneObjectGroup(UUID fullID) 4919 public SceneObjectGroup GetSceneObjectGroup(UUID fullID)
4778 { 4920 {
4779 return m_sceneGraph.GetSceneObjectGroup(fullID); 4921 return m_sceneGraph.GetSceneObjectGroup(fullID);
4780 } 4922 }
4781 4923
4782 /// <summary> 4924 /// <summary>
4925 /// Get a group via its local ID
4926 /// </summary>
4927 /// <remarks>This will only return a group if the local ID matches a root part</remarks>
4928 /// <param name="localID"></param>
4929 /// <returns>null if no group with that id exists</returns>
4930 public SceneObjectGroup GetSceneObjectGroup(uint localID)
4931 {
4932 return m_sceneGraph.GetSceneObjectGroup(localID);
4933 }
4934
4935 /// <summary>
4783 /// Get a group by name from the scene (will return the first 4936 /// 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) 4937 /// found, if there are more than one prim with the same name)
4785 /// </summary> 4938 /// </summary>
@@ -4791,6 +4944,18 @@ namespace OpenSim.Region.Framework.Scenes
4791 } 4944 }
4792 4945
4793 /// <summary> 4946 /// <summary>
4947 /// Attempt to get the SOG via its UUID
4948 /// </summary>
4949 /// <param name="fullID"></param>
4950 /// <param name="sog"></param>
4951 /// <returns></returns>
4952 public bool TryGetSceneObjectGroup(UUID fullID, out SceneObjectGroup sog)
4953 {
4954 sog = GetSceneObjectGroup(fullID);
4955 return sog != null;
4956 }
4957
4958 /// <summary>
4794 /// Get a prim by name from the scene (will return the first 4959 /// 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) 4960 /// found, if there are more than one prim with the same name)
4796 /// </summary> 4961 /// </summary>
@@ -4822,6 +4987,18 @@ namespace OpenSim.Region.Framework.Scenes
4822 } 4987 }
4823 4988
4824 /// <summary> 4989 /// <summary>
4990 /// Attempt to get a prim via its UUID
4991 /// </summary>
4992 /// <param name="fullID"></param>
4993 /// <param name="sop"></param>
4994 /// <returns></returns>
4995 public bool TryGetSceneObjectPart(UUID fullID, out SceneObjectPart sop)
4996 {
4997 sop = GetSceneObjectPart(fullID);
4998 return sop != null;
4999 }
5000
5001 /// <summary>
4825 /// Get a scene object group that contains the prim with the given local id 5002 /// Get a scene object group that contains the prim with the given local id
4826 /// </summary> 5003 /// </summary>
4827 /// <param name="localID"></param> 5004 /// <param name="localID"></param>
@@ -4915,14 +5092,15 @@ namespace OpenSim.Region.Framework.Scenes
4915 client.SendRegionHandle(regionID, handle); 5092 client.SendRegionHandle(regionID, handle);
4916 } 5093 }
4917 5094
4918 public bool NeedSceneCacheClear(UUID agentID) 5095// Commented pending deletion since this method no longer appears to do anything at all
4919 { 5096// public bool NeedSceneCacheClear(UUID agentID)
4920 IInventoryTransferModule inv = RequestModuleInterface<IInventoryTransferModule>(); 5097// {
4921 if (inv == null) 5098// IInventoryTransferModule inv = RequestModuleInterface<IInventoryTransferModule>();
4922 return true; 5099// if (inv == null)
4923 5100// return true;
4924 return inv.NeedSceneCacheClear(agentID, this); 5101//
4925 } 5102// return inv.NeedSceneCacheClear(agentID, this);
5103// }
4926 5104
4927 public void CleanTempObjects() 5105 public void CleanTempObjects()
4928 { 5106 {
@@ -5876,6 +6054,9 @@ Environment.Exit(1);
5876 6054
5877 public string GetExtraSetting(string name) 6055 public string GetExtraSetting(string name)
5878 { 6056 {
6057 if (m_extraSettings == null)
6058 return String.Empty;
6059
5879 string val; 6060 string val;
5880 6061
5881 if (!m_extraSettings.TryGetValue(name, out val)) 6062 if (!m_extraSettings.TryGetValue(name, out val))
@@ -5886,6 +6067,9 @@ Environment.Exit(1);
5886 6067
5887 public void StoreExtraSetting(string name, string val) 6068 public void StoreExtraSetting(string name, string val)
5888 { 6069 {
6070 if (m_extraSettings == null)
6071 return;
6072
5889 string oldVal; 6073 string oldVal;
5890 6074
5891 if (m_extraSettings.TryGetValue(name, out oldVal)) 6075 if (m_extraSettings.TryGetValue(name, out oldVal))
@@ -5903,6 +6087,9 @@ Environment.Exit(1);
5903 6087
5904 public void RemoveExtraSetting(string name) 6088 public void RemoveExtraSetting(string name)
5905 { 6089 {
6090 if (m_extraSettings == null)
6091 return;
6092
5906 if (!m_extraSettings.ContainsKey(name)) 6093 if (!m_extraSettings.ContainsKey(name))
5907 return; 6094 return;
5908 6095