aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/Scene.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/Scene.cs')
-rwxr-xr-x[-rw-r--r--]OpenSim/Region/Framework/Scenes/Scene.cs2597
1 files changed, 1521 insertions, 1076 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index f87d469..2fe6e22 100644..100755
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -6,7 +6,7 @@
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright 7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD 9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the 12 * * Neither the name of the OpenSimulator Project nor the
@@ -39,18 +39,19 @@ using Nini.Config;
39using OpenMetaverse; 39using OpenMetaverse;
40using OpenMetaverse.Packets; 40using OpenMetaverse.Packets;
41using OpenMetaverse.Imaging; 41using OpenMetaverse.Imaging;
42using OpenMetaverse.StructuredData;
42using OpenSim.Framework; 43using OpenSim.Framework;
43using OpenSim.Framework.Monitoring; 44using OpenSim.Framework.Monitoring;
44using OpenSim.Services.Interfaces; 45using OpenSim.Services.Interfaces;
45using OpenSim.Framework.Communications;
46using OpenSim.Framework.Console; 46using OpenSim.Framework.Console;
47using OpenSim.Region.Framework.Interfaces; 47using OpenSim.Region.Framework.Interfaces;
48using OpenSim.Region.Framework.Scenes.Scripting; 48using OpenSim.Region.Framework.Scenes.Scripting;
49using OpenSim.Region.Framework.Scenes.Serialization; 49using OpenSim.Region.Framework.Scenes.Serialization;
50using OpenSim.Region.Physics.Manager; 50using OpenSim.Region.PhysicsModules.SharedBase;
51using Timer=System.Timers.Timer; 51using Timer = System.Timers.Timer;
52using TPFlags = OpenSim.Framework.Constants.TeleportFlags; 52using TPFlags = OpenSim.Framework.Constants.TeleportFlags;
53using GridRegion = OpenSim.Services.Interfaces.GridRegion; 53using GridRegion = OpenSim.Services.Interfaces.GridRegion;
54using PermissionMask = OpenSim.Framework.PermissionMask;
54 55
55namespace OpenSim.Region.Framework.Scenes 56namespace OpenSim.Region.Framework.Scenes
56{ 57{
@@ -60,6 +61,8 @@ namespace OpenSim.Region.Framework.Scenes
60 { 61 {
61 private const long DEFAULT_MIN_TIME_FOR_PERSISTENCE = 60L; 62 private const long DEFAULT_MIN_TIME_FOR_PERSISTENCE = 60L;
62 private const long DEFAULT_MAX_TIME_FOR_PERSISTENCE = 600L; 63 private const long DEFAULT_MAX_TIME_FOR_PERSISTENCE = 600L;
64
65 public const int m_defaultNumberFramesStored = 10;
63 66
64 public delegate void SynchronizeSceneHandler(Scene scene); 67 public delegate void SynchronizeSceneHandler(Scene scene);
65 68
@@ -102,15 +105,37 @@ namespace OpenSim.Region.Framework.Scenes
102 /// <summary> 105 /// <summary>
103 /// If false then physical objects are disabled, though collisions will continue as normal. 106 /// If false then physical objects are disabled, though collisions will continue as normal.
104 /// </summary> 107 /// </summary>
105 public bool PhysicsEnabled { get; set; } 108 public bool PhysicsEnabled
109 {
110 get
111 {
112 return m_physicsEnabled;
113 }
114
115 set
116 {
117 m_physicsEnabled = value;
118
119 if (PhysicsScene != null)
120 {
121 IPhysicsParameters physScene = PhysicsScene as IPhysicsParameters;
122
123 if (physScene != null)
124 physScene.SetPhysicsParameter(
125 "Active", m_physicsEnabled.ToString(), PhysParameterEntry.APPLY_TO_NONE);
126 }
127 }
128 }
129
130 private bool m_physicsEnabled;
106 131
107 /// <summary> 132 /// <summary>
108 /// If false then scripts are not enabled on the smiulator 133 /// If false then scripts are not enabled on the smiulator
109 /// </summary> 134 /// </summary>
110 public bool ScriptsEnabled 135 public bool ScriptsEnabled
111 { 136 {
112 get { return m_scripts_enabled; } 137 get { return m_scripts_enabled; }
113 set 138 set
114 { 139 {
115 if (m_scripts_enabled != value) 140 if (m_scripts_enabled != value)
116 { 141 {
@@ -128,7 +153,7 @@ namespace OpenSim.Region.Framework.Scenes
128 else 153 else
129 { 154 {
130 m_log.Info("Starting all Scripts in Scene"); 155 m_log.Info("Starting all Scripts in Scene");
131 156
132 EntityBase[] entities = Entities.GetEntities(); 157 EntityBase[] entities = Entities.GetEntities();
133 foreach (EntityBase ent in entities) 158 foreach (EntityBase ent in entities)
134 { 159 {
@@ -150,7 +175,7 @@ namespace OpenSim.Region.Framework.Scenes
150 public SynchronizeSceneHandler SynchronizeScene; 175 public SynchronizeSceneHandler SynchronizeScene;
151 176
152 /// <summary> 177 /// <summary>
153 /// Used to prevent simultaneous calls to RemoveClient() for the same agent from interfering with each other. 178 /// Used to prevent simultaneous calls to code that adds and removes agents.
154 /// </summary> 179 /// </summary>
155 private object m_removeClientLock = new object(); 180 private object m_removeClientLock = new object();
156 181
@@ -159,11 +184,6 @@ namespace OpenSim.Region.Framework.Scenes
159 /// </summary> 184 /// </summary>
160 public SimStatsReporter StatsReporter { get; private set; } 185 public SimStatsReporter StatsReporter { get; private set; }
161 186
162 public List<Border> NorthBorders = new List<Border>();
163 public List<Border> EastBorders = new List<Border>();
164 public List<Border> SouthBorders = new List<Border>();
165 public List<Border> WestBorders = new List<Border>();
166
167 /// <summary> 187 /// <summary>
168 /// Controls whether physics can be applied to prims. Even if false, prims still have entries in a 188 /// Controls whether physics can be applied to prims. Even if false, prims still have entries in a
169 /// PhysicsScene in order to perform collision detection 189 /// PhysicsScene in order to perform collision detection
@@ -196,7 +216,7 @@ namespace OpenSim.Region.Framework.Scenes
196 /// <summary> 216 /// <summary>
197 /// Maximum value of the size of a physical prim in each axis 217 /// Maximum value of the size of a physical prim in each axis
198 /// </summary> 218 /// </summary>
199 public float m_maxPhys = 10; 219 public float m_maxPhys = 64;
200 220
201 /// <summary> 221 /// <summary>
202 /// Max prims an object will hold 222 /// Max prims an object will hold
@@ -205,7 +225,13 @@ namespace OpenSim.Region.Framework.Scenes
205 225
206 public bool m_clampPrimSize; 226 public bool m_clampPrimSize;
207 public bool m_trustBinaries; 227 public bool m_trustBinaries;
208 public bool m_allowScriptCrossings; 228 public bool m_allowScriptCrossings = true;
229
230 /// <summary>
231 /// Can avatars cross from and to this region?
232 /// </summary>
233 public bool AllowAvatarCrossing { get; set; }
234
209 public bool m_useFlySlow; 235 public bool m_useFlySlow;
210 public bool m_useTrashOnDelete = true; 236 public bool m_useTrashOnDelete = true;
211 237
@@ -214,21 +240,58 @@ namespace OpenSim.Region.Framework.Scenes
214 /// </summary> 240 /// </summary>
215 public bool SendPeriodicAppearanceUpdates { get; set; } 241 public bool SendPeriodicAppearanceUpdates { get; set; }
216 242
243 /// <summary>
244 /// How much a root agent has to change position before updates are sent to viewers.
245 /// </summary>
246 public float RootPositionUpdateTolerance { get; set; }
247
248 /// <summary>
249 /// How much a root agent has to rotate before updates are sent to viewers.
250 /// </summary>
251 public float RootRotationUpdateTolerance { get; set; }
252
253 /// <summary>
254 /// How much a root agent has to change velocity before updates are sent to viewers.
255 /// </summary>
256 public float RootVelocityUpdateTolerance { get; set; }
257
258 /// <summary>
259 /// If greater than 1, we only send terse updates to other root agents on every n updates.
260 /// </summary>
261 public int RootTerseUpdatePeriod { get; set; }
262
263 /// <summary>
264 /// If greater than 1, we only send terse updates to child agents on every n updates.
265 /// </summary>
266 public int ChildTerseUpdatePeriod { get; set; }
267
217 protected float m_defaultDrawDistance = 255.0f; 268 protected float m_defaultDrawDistance = 255.0f;
218 public float DefaultDrawDistance 269 public float DefaultDrawDistance
219 { 270 {
220 get { return m_defaultDrawDistance; } 271 // get { return m_defaultDrawDistance; }
272 get
273 {
274 if (RegionInfo != null)
275 {
276 float largestDimension = Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY);
277 m_defaultDrawDistance = Math.Max(m_defaultDrawDistance, largestDimension);
278
279 }
280 return m_defaultDrawDistance;
281 }
221 } 282 }
222 283
223 private List<string> m_AllowedViewers = new List<string>(); 284 private List<string> m_AllowedViewers = new List<string>();
224 private List<string> m_BannedViewers = new List<string>(); 285 private List<string> m_BannedViewers = new List<string>();
225 286
226 // TODO: need to figure out how allow client agents but deny 287 // TODO: need to figure out how allow client agents but deny
227 // root agents when ACL denies access to root agent 288 // root agents when ACL denies access to root agent
228 public bool m_strictAccessControl = true; 289 public bool m_strictAccessControl = true;
229 290
230 public int MaxUndoCount { get; set; } 291 public int MaxUndoCount { get; set; }
231 292
293 public bool SeeIntoRegion { get; set; }
294
232 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; 295 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet;
233 public bool LoginLock = false; 296 public bool LoginLock = false;
234 297
@@ -262,6 +325,7 @@ namespace OpenSim.Region.Framework.Scenes
262 protected IUserAccountService m_UserAccountService; 325 protected IUserAccountService m_UserAccountService;
263 protected IAvatarService m_AvatarService; 326 protected IAvatarService m_AvatarService;
264 protected IGridUserService m_GridUserService; 327 protected IGridUserService m_GridUserService;
328 protected IAgentPreferencesService m_AgentPreferencesService;
265 329
266 protected IXMLRPC m_xmlrpcModule; 330 protected IXMLRPC m_xmlrpcModule;
267 protected IWorldComm m_worldCommModule; 331 protected IWorldComm m_worldCommModule;
@@ -275,6 +339,17 @@ namespace OpenSim.Region.Framework.Scenes
275 private Dictionary<string, string> m_extraSettings; 339 private Dictionary<string, string> m_extraSettings;
276 340
277 /// <summary> 341 /// <summary>
342 /// If true then the next time the scene loop is activated, updates will be performed by firing of a timer
343 /// rather than on a single thread that sleeps.
344 /// </summary>
345 public bool UpdateOnTimer { get; set; }
346
347 /// <summary>
348 /// Only used if we are updating scene on a timer rather than sleeping a thread.
349 /// </summary>
350 private Timer m_sceneUpdateTimer;
351
352 /// <summary>
278 /// Current scene frame number 353 /// Current scene frame number
279 /// </summary> 354 /// </summary>
280 public uint Frame 355 public uint Frame
@@ -289,30 +364,59 @@ namespace OpenSim.Region.Framework.Scenes
289 public uint MaintenanceRun { get; private set; } 364 public uint MaintenanceRun { get; private set; }
290 365
291 /// <summary> 366 /// <summary>
292 /// The minimum length of time in seconds that will be taken for a scene frame. If the frame takes less time then we 367 /// The minimum length of time in milliseconds that will be taken for a scene frame. If the frame takes less time then we
293 /// will sleep for the remaining period. 368 /// will sleep for the remaining period.
294 /// </summary> 369 /// </summary>
295 /// <remarks> 370 /// <remarks>
296 /// One can tweak this number to experiment. One current effect of reducing it is to make avatar animations 371 /// One can tweak this number to experiment. One current effect of reducing it is to make avatar animations
297 /// occur too quickly (viewer 1) or with even more slide (viewer 2). 372 /// occur too quickly (viewer 1) or with even more slide (viewer 2).
298 /// </remarks> 373 /// </remarks>
299 public float MinFrameTime { get; private set; } 374 public int MinFrameTicks
375 {
376 get { return m_minFrameTicks; }
377 private set
378 {
379 m_minFrameTicks = value;
380 MinFrameSeconds = (float)m_minFrameTicks / 1000;
381 }
382 }
383 private int m_minFrameTicks;
384
385 public int FrameTimeWarnPercent { get; private set; }
386 public int FrameTimeCritPercent { get; private set; }
387
388 // Normalize the frame related stats to nominal 55fps for viewer and scripts option
389 // see SimStatsReporter.cs
390 public bool Normalized55FPS { get; private set; }
391
392 /// <summary>
393 /// The minimum length of time in seconds that will be taken for a scene frame.
394 /// </summary>
395 /// <remarks>
396 /// Always derived from MinFrameTicks.
397 /// </remarks>
398 public float MinFrameSeconds { get; private set; }
300 399
301 /// <summary> 400 /// <summary>
302 /// The minimum length of time in seconds that will be taken for a maintenance run. 401 /// The minimum length of time in milliseconds that will be taken for a scene frame. If the frame takes less time then we
402 /// will sleep for the remaining period.
303 /// </summary> 403 /// </summary>
304 public float MinMaintenanceTime { get; private set; } 404 /// <remarks>
405 /// One can tweak this number to experiment. One current effect of reducing it is to make avatar animations
406 /// occur too quickly (viewer 1) or with even more slide (viewer 2).
407 /// </remarks>
408 public int MinMaintenanceTicks { get; set; }
305 409
306 private int m_update_physics = 1; 410 private int m_update_physics = 1;
307 private int m_update_entitymovement = 1; 411 private int m_update_entitymovement = 1;
308 private int m_update_objects = 1; 412 private int m_update_objects = 1;
309 private int m_update_temp_cleaning = 1000;
310 private int m_update_presences = 1; // Update scene presence movements 413 private int m_update_presences = 1; // Update scene presence movements
311 private int m_update_events = 1; 414 private int m_update_events = 1;
312 private int m_update_backup = 200; 415 private int m_update_backup = 200;
313 private int m_update_terrain = 50; 416 private int m_update_terrain = 50;
314// private int m_update_land = 1; 417 // private int m_update_land = 1;
315 private int m_update_coarse_locations = 50; 418 private int m_update_coarse_locations = 50;
419 private int m_update_temp_cleaning = 180;
316 420
317 private int agentMS; 421 private int agentMS;
318 private int frameMS; 422 private int frameMS;
@@ -326,6 +430,17 @@ namespace OpenSim.Region.Framework.Scenes
326 private int landMS; 430 private int landMS;
327 private int spareMS; 431 private int spareMS;
328 432
433 // A temporary configuration flag to enable using FireAndForget to process
434 // collisions from the physics engine. There is a problem with collisions
435 // stopping sometimes and MB's suspicion is some race condition passing
436 // collisions from the physics engine callback to the script engine.
437 // This causes the collision events to be passed with a FireAndForget
438 // call which should eliminate that linkage. Testers can turn this on
439 // and see if collisions stop. If they don't, the problem is somewhere else.
440 // This feature defaults to 'off' so, by default, the simulator operation
441 // is not changed.
442 public bool ShouldUseFireAndForgetForCollisions = false;
443
329 /// <summary> 444 /// <summary>
330 /// Tick at which the last frame was processed. 445 /// Tick at which the last frame was processed.
331 /// </summary> 446 /// </summary>
@@ -337,16 +452,28 @@ namespace OpenSim.Region.Framework.Scenes
337 private int m_lastMaintenanceTick; 452 private int m_lastMaintenanceTick;
338 453
339 /// <summary> 454 /// <summary>
455 /// Total script execution time (in Stopwatch Ticks) since the last frame
456 /// </summary>
457 private long m_scriptExecutionTime = 0;
458
459 /// <summary>
340 /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched 460 /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched
341 /// asynchronously from the update loop. 461 /// asynchronously from the update loop.
342 /// </summary> 462 /// </summary>
343 private bool m_cleaningTemps = false; 463 private bool m_cleaningTemps = false;
344 464
345// private Object m_heartbeatLock = new Object(); 465 /// <summary>
466 /// Used to control main scene thread looping time when not updating via timer.
467 /// </summary>
468 private ManualResetEvent m_updateWaitEvent = new ManualResetEvent(false);
469
470 /// <summary>
471 /// Used to control maintenance thread runs.
472 /// </summary>
473 private ManualResetEvent m_maintenanceWaitEvent = new ManualResetEvent(false);
346 474
347 // TODO: Possibly stop other classes being able to manipulate this directly. 475 // TODO: Possibly stop other classes being able to manipulate this directly.
348 private SceneGraph m_sceneGraph; 476 private SceneGraph m_sceneGraph;
349 private volatile int m_bordersLocked;
350 private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing 477 private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing
351 private volatile bool m_backingup; 478 private volatile bool m_backingup;
352 private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>(); 479 private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>();
@@ -354,6 +481,12 @@ namespace OpenSim.Region.Framework.Scenes
354 481
355 private string m_defaultScriptEngine; 482 private string m_defaultScriptEngine;
356 483
484 private int m_unixStartTime;
485 public int UnixStartTime
486 {
487 get { return m_unixStartTime; }
488 }
489
357 /// <summary> 490 /// <summary>
358 /// Tick at which the last login occurred. 491 /// Tick at which the last login occurred.
359 /// </summary> 492 /// </summary>
@@ -377,7 +510,8 @@ namespace OpenSim.Region.Framework.Scenes
377 /// Is the scene active? 510 /// Is the scene active?
378 /// </summary> 511 /// </summary>
379 /// <remarks> 512 /// <remarks>
380 /// If false, maintenance and update loops are not being run. Updates can still be triggered manually if 513 /// If false, maintenance and update loops are not being run, though after setting to false update may still
514 /// be active for a period (and IsRunning will still be true). Updates can still be triggered manually if
381 /// the scene is not active. 515 /// the scene is not active.
382 /// </remarks> 516 /// </remarks>
383 public bool Active 517 public bool Active
@@ -388,24 +522,23 @@ namespace OpenSim.Region.Framework.Scenes
388 if (value) 522 if (value)
389 { 523 {
390 if (!m_active) 524 if (!m_active)
391 Start(); 525 Start(false);
392 } 526 }
393 else 527 else
394 { 528 {
529 // This appears assymetric with Start() above but is not - setting m_active = false stops the loops
530 // XXX: Possibly this should be in an explicit Stop() method for symmetry.
395 m_active = false; 531 m_active = false;
396 } 532 }
397 } 533 }
398 } 534 }
399 private volatile bool m_active; 535 private volatile bool m_active;
400 536
401// private int m_lastUpdate; 537 /// <summary>
402// private bool m_firstHeartbeat = true; 538 /// If true then updates are running. This may be true for a short period after a scene is de-activated.
403 539 /// </summary>
404 private UpdatePrioritizationSchemes m_priorityScheme = UpdatePrioritizationSchemes.Time; 540 public bool IsRunning { get { return m_isRunning; } }
405 private bool m_reprioritizationEnabled = true; 541 private volatile bool m_isRunning;
406 private double m_reprioritizationInterval = 5000.0;
407 private double m_rootReprioritizationDistance = 10.0;
408 private double m_childReprioritizationDistance = 20.0;
409 542
410 private Timer m_mapGenerationTimer = new Timer(); 543 private Timer m_mapGenerationTimer = new Timer();
411 private bool m_generateMaptiles; 544 private bool m_generateMaptiles;
@@ -421,23 +554,18 @@ namespace OpenSim.Region.Framework.Scenes
421 set { m_splitRegionID = value; } 554 set { m_splitRegionID = value; }
422 } 555 }
423 556
424 public bool BordersLocked
425 {
426 get { return m_bordersLocked == 1; }
427 set
428 {
429 if (value == true)
430 m_bordersLocked = 1;
431 else
432 m_bordersLocked = 0;
433 }
434 }
435
436 public new float TimeDilation 557 public new float TimeDilation
437 { 558 {
438 get { return m_sceneGraph.PhysicsScene.TimeDilation; } 559 get { return m_sceneGraph.PhysicsScene.TimeDilation; }
439 } 560 }
440 561
562 public void setThreadCount(int inUseThreads)
563 {
564 // Just pass the thread count information on its way as the Scene
565 // does not require the value for anything at this time
566 StatsReporter.SetThreadCount(inUseThreads);
567 }
568
441 public SceneCommunicationService SceneGridService 569 public SceneCommunicationService SceneGridService
442 { 570 {
443 get { return m_sceneGridService; } 571 get { return m_sceneGridService; }
@@ -496,7 +624,7 @@ namespace OpenSim.Region.Framework.Scenes
496 return m_AssetService; 624 return m_AssetService;
497 } 625 }
498 } 626 }
499 627
500 public IAuthorizationService AuthorizationService 628 public IAuthorizationService AuthorizationService
501 { 629 {
502 get 630 get
@@ -624,6 +752,16 @@ namespace OpenSim.Region.Framework.Scenes
624 } 752 }
625 } 753 }
626 754
755 public IAgentPreferencesService AgentPreferencesService
756 {
757 get
758 {
759 if (m_AgentPreferencesService == null)
760 m_AgentPreferencesService = RequestModuleInterface<IAgentPreferencesService>();
761 return m_AgentPreferencesService;
762 }
763 }
764
627 public IAttachmentsModule AttachmentsModule { get; set; } 765 public IAttachmentsModule AttachmentsModule { get; set; }
628 public IEntityTransferModule EntityTransferModule { get; private set; } 766 public IEntityTransferModule EntityTransferModule { get; private set; }
629 public IAgentAssetTransactions AgentTransactionsModule { get; private set; } 767 public IAgentAssetTransactions AgentTransactionsModule { get; private set; }
@@ -633,7 +771,7 @@ namespace OpenSim.Region.Framework.Scenes
633 { 771 {
634 get { return m_AvatarFactory; } 772 get { return m_AvatarFactory; }
635 } 773 }
636 774
637 public ICapabilitiesModule CapsModule 775 public ICapabilitiesModule CapsModule
638 { 776 {
639 get { return m_capsModule; } 777 get { return m_capsModule; }
@@ -650,11 +788,11 @@ namespace OpenSim.Region.Framework.Scenes
650 public int MonitorLandTime { get { return landMS; } } 788 public int MonitorLandTime { get { return landMS; } }
651 public int MonitorLastFrameTick { get { return m_lastFrameTick; } } 789 public int MonitorLastFrameTick { get { return m_lastFrameTick; } }
652 790
653 public UpdatePrioritizationSchemes UpdatePrioritizationScheme { get { return m_priorityScheme; } } 791 public UpdatePrioritizationSchemes UpdatePrioritizationScheme { get; set; }
654 public bool IsReprioritizationEnabled { get { return m_reprioritizationEnabled; } } 792 public bool IsReprioritizationEnabled { get; set; }
655 public double ReprioritizationInterval { get { return m_reprioritizationInterval; } } 793 public double ReprioritizationInterval { get; set; }
656 public double RootReprioritizationDistance { get { return m_rootReprioritizationDistance; } } 794 public double RootReprioritizationDistance { get; set; }
657 public double ChildReprioritizationDistance { get { return m_childReprioritizationDistance; } } 795 public double ChildReprioritizationDistance { get; set; }
658 796
659 public AgentCircuitManager AuthenticateHandler 797 public AgentCircuitManager AuthenticateHandler
660 { 798 {
@@ -699,43 +837,46 @@ namespace OpenSim.Region.Framework.Scenes
699 get { return m_sceneGraph.Entities; } 837 get { return m_sceneGraph.Entities; }
700 } 838 }
701 839
702 840
703 // used in sequence see: SpawnPoint() 841 // used in sequence see: SpawnPoint()
704 private int m_SpawnPoint; 842 private int m_SpawnPoint;
705 // can be closest/random/sequence 843 // can be closest/random/sequence
706 public string SpawnPointRouting 844 public string SpawnPointRouting
707 { 845 {
708 get; private set; 846 get;
847 private set;
709 } 848 }
710 // allow landmarks to pass 849 // allow landmarks to pass
711 public bool TelehubAllowLandmarks 850 public bool TelehubAllowLandmarks
712 { 851 {
713 get; private set; 852 get;
853 private set;
714 } 854 }
715 855
716 #endregion Properties 856 #endregion Properties
717 857
718 #region Constructors 858 #region Constructors
719 859
720 public Scene(RegionInfo regInfo, AgentCircuitManager authen, 860 public Scene(RegionInfo regInfo, AgentCircuitManager authen,
721 SceneCommunicationService sceneGridService,
722 ISimulationDataService simDataService, IEstateDataService estateDataService, 861 ISimulationDataService simDataService, IEstateDataService estateDataService,
723 bool dumpAssetsToFile,
724 IConfigSource config, string simulatorVersion) 862 IConfigSource config, string simulatorVersion)
725 : this(regInfo) 863 : this(regInfo)
726 { 864 {
727 m_config = config; 865 m_config = config;
728 MinFrameTime = 0.089f; 866 MinFrameTicks = 89;
729 MinMaintenanceTime = 1; 867 FrameTimeWarnPercent = 60;
868 FrameTimeCritPercent = 40;
869 Normalized55FPS = true;
870 MinMaintenanceTicks = 1000;
871 SeeIntoRegion = true;
730 872
731 Random random = new Random(); 873 Random random = new Random();
732 874
733 m_lastAllocatedLocalId = (uint)(random.NextDouble() * (double)(uint.MaxValue / 2)) + (uint)(uint.MaxValue / 4); 875 m_lastAllocatedLocalId = (uint)(random.NextDouble() * (double)(uint.MaxValue / 2)) + (uint)(uint.MaxValue / 4);
734 m_authenticateHandler = authen; 876 m_authenticateHandler = authen;
735 m_sceneGridService = sceneGridService; 877 m_sceneGridService = new SceneCommunicationService();
736 m_SimulationDataService = simDataService; 878 m_SimulationDataService = simDataService;
737 m_EstateDataService = estateDataService; 879 m_EstateDataService = estateDataService;
738 m_regionHandle = RegionInfo.RegionHandle;
739 880
740 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this); 881 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
741 m_asyncSceneObjectDeleter.Enabled = true; 882 m_asyncSceneObjectDeleter.Enabled = true;
@@ -794,25 +935,8 @@ namespace OpenSim.Region.Framework.Scenes
794 EventManager.OnLandObjectRemoved += 935 EventManager.OnLandObjectRemoved +=
795 new EventManager.LandObjectRemoved(simDataService.RemoveLandObject); 936 new EventManager.LandObjectRemoved(simDataService.RemoveLandObject);
796 937
797 m_sceneGraph = new SceneGraph(this);
798
799 // If the scene graph has an Unrecoverable error, restart this sim.
800 // Currently the only thing that causes it to happen is two kinds of specific
801 // Physics based crashes.
802 //
803 // Out of memory
804 // Operating system has killed the plugin
805 m_sceneGraph.UnRecoverableError
806 += () =>
807 {
808 m_log.ErrorFormat("[SCENE]: Restarting region {0} due to unrecoverable physics crash", Name);
809 RestartNow();
810 };
811
812 RegisterDefaultSceneEvents(); 938 RegisterDefaultSceneEvents();
813 939
814 DumpAssetsToFile = dumpAssetsToFile;
815
816 // XXX: Don't set the public property since we don't want to activate here. This needs to be handled 940 // XXX: Don't set the public property since we don't want to activate here. This needs to be handled
817 // better in the future. 941 // better in the future.
818 m_scripts_enabled = !RegionInfo.RegionSettings.DisableScripts; 942 m_scripts_enabled = !RegionInfo.RegionSettings.DisableScripts;
@@ -835,10 +959,12 @@ namespace OpenSim.Region.Framework.Scenes
835 UseBackup = startupConfig.GetBoolean("UseSceneBackup", UseBackup); 959 UseBackup = startupConfig.GetBoolean("UseSceneBackup", UseBackup);
836 if (!UseBackup) 960 if (!UseBackup)
837 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName); 961 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName);
838 962
839 //Animation states 963 //Animation states
840 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); 964 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
841 965
966 SeeIntoRegion = startupConfig.GetBoolean("see_into_region", SeeIntoRegion);
967
842 MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20); 968 MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20);
843 969
844 PhysicalPrims = startupConfig.GetBoolean("physical_prim", PhysicalPrims); 970 PhysicalPrims = startupConfig.GetBoolean("physical_prim", PhysicalPrims);
@@ -887,10 +1013,10 @@ namespace OpenSim.Region.Framework.Scenes
887 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries); 1013 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries);
888 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings); 1014 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings);
889 m_dontPersistBefore = 1015 m_dontPersistBefore =
890 startupConfig.GetLong("MinimumTimeBeforePersistenceConsidered", DEFAULT_MIN_TIME_FOR_PERSISTENCE); 1016 startupConfig.GetLong("MinimumTimeBeforePersistenceConsidered", DEFAULT_MIN_TIME_FOR_PERSISTENCE);
891 m_dontPersistBefore *= 10000000; 1017 m_dontPersistBefore *= 10000000;
892 m_persistAfter = 1018 m_persistAfter =
893 startupConfig.GetLong("MaximumTimeBeforePersistenceConsidered", DEFAULT_MAX_TIME_FOR_PERSISTENCE); 1019 startupConfig.GetLong("MaximumTimeBeforePersistenceConsidered", DEFAULT_MAX_TIME_FOR_PERSISTENCE);
894 m_persistAfter *= 10000000; 1020 m_persistAfter *= 10000000;
895 1021
896 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 1022 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
@@ -900,10 +1026,15 @@ namespace OpenSim.Region.Framework.Scenes
900 1026
901 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 1027 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
902 1028
903 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true); 1029 string[] possibleMapConfigSections = new string[] { "Map", "Startup" };
1030
1031 m_generateMaptiles
1032 = Util.GetConfigVarFromSections<bool>(config, "GenerateMaptiles", possibleMapConfigSections, true);
1033
904 if (m_generateMaptiles) 1034 if (m_generateMaptiles)
905 { 1035 {
906 int maptileRefresh = startupConfig.GetInt("MaptileRefresh", 0); 1036 int maptileRefresh = Util.GetConfigVarFromSections<int>(config, "MaptileRefresh", possibleMapConfigSections, 0);
1037 m_log.InfoFormat("[SCENE]: Region {0}, WORLD MAP refresh time set to {1} seconds", RegionInfo.RegionName, maptileRefresh);
907 if (maptileRefresh != 0) 1038 if (maptileRefresh != 0)
908 { 1039 {
909 m_mapGenerationTimer.Interval = maptileRefresh * 1000; 1040 m_mapGenerationTimer.Interval = maptileRefresh * 1000;
@@ -914,16 +1045,29 @@ namespace OpenSim.Region.Framework.Scenes
914 } 1045 }
915 else 1046 else
916 { 1047 {
917 string tile = startupConfig.GetString("MaptileStaticUUID", UUID.Zero.ToString()); 1048 string tile
1049 = Util.GetConfigVarFromSections<string>(
1050 config, "MaptileStaticUUID", possibleMapConfigSections, UUID.Zero.ToString());
1051
918 UUID tileID; 1052 UUID tileID;
919 1053
920 if (UUID.TryParse(tile, out tileID)) 1054 if (tile != UUID.Zero.ToString() && UUID.TryParse(tile, out tileID))
921 { 1055 {
922 RegionInfo.RegionSettings.TerrainImageID = tileID; 1056 RegionInfo.RegionSettings.TerrainImageID = tileID;
923 } 1057 }
1058 else
1059 {
1060 RegionInfo.RegionSettings.TerrainImageID = RegionInfo.MaptileStaticUUID;
1061 m_log.InfoFormat("[SCENE]: Region {0}, maptile set to {1}", RegionInfo.RegionName, RegionInfo.MaptileStaticUUID.ToString());
1062 }
924 } 1063 }
925 1064
926 string grant = startupConfig.GetString("AllowedClients", String.Empty); 1065 string[] possibleAccessControlConfigSections = new string[] { "Startup", "AccessControl"};
1066
1067 string grant
1068 = Util.GetConfigVarFromSections<string>(
1069 config, "AllowedClients", possibleAccessControlConfigSections, string.Empty);
1070
927 if (grant.Length > 0) 1071 if (grant.Length > 0)
928 { 1072 {
929 foreach (string viewer in grant.Split('|')) 1073 foreach (string viewer in grant.Split('|'))
@@ -932,7 +1076,14 @@ namespace OpenSim.Region.Framework.Scenes
932 } 1076 }
933 } 1077 }
934 1078
935 grant = startupConfig.GetString("BannedClients", String.Empty); 1079 grant
1080 = Util.GetConfigVarFromSections<string>(
1081 config, "DeniedClients", possibleAccessControlConfigSections, String.Empty);
1082 // Deal with the mess of someone having used a different word at some point
1083 if (grant == String.Empty)
1084 grant = Util.GetConfigVarFromSections<string>(
1085 config, "BannedClients", possibleAccessControlConfigSections, String.Empty);
1086
936 if (grant.Length > 0) 1087 if (grant.Length > 0)
937 { 1088 {
938 foreach (string viewer in grant.Split('|')) 1089 foreach (string viewer in grant.Split('|'))
@@ -941,21 +1092,32 @@ namespace OpenSim.Region.Framework.Scenes
941 } 1092 }
942 } 1093 }
943 1094
944 MinFrameTime = startupConfig.GetFloat( "MinFrameTime", MinFrameTime); 1095 if (startupConfig.Contains("MinFrameTime"))
945 m_update_backup = startupConfig.GetInt( "UpdateStorageEveryNFrames", m_update_backup); 1096 MinFrameTicks = (int)(startupConfig.GetFloat("MinFrameTime") * 1000);
946 m_update_coarse_locations = startupConfig.GetInt( "UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations); 1097 FrameTimeWarnPercent = startupConfig.GetInt( "FrameTimeWarnPercent", FrameTimeWarnPercent);
947 m_update_entitymovement = startupConfig.GetInt( "UpdateEntityMovementEveryNFrames", m_update_entitymovement); 1098 FrameTimeCritPercent = startupConfig.GetInt( "FrameTimeCritPercent", FrameTimeCritPercent);
948 m_update_events = startupConfig.GetInt( "UpdateEventsEveryNFrames", m_update_events); 1099 Normalized55FPS = startupConfig.GetBoolean( "Normalized55FPS", Normalized55FPS);
949 m_update_objects = startupConfig.GetInt( "UpdateObjectsEveryNFrames", m_update_objects); 1100
950 m_update_physics = startupConfig.GetInt( "UpdatePhysicsEveryNFrames", m_update_physics); 1101 m_update_backup = startupConfig.GetInt("UpdateStorageEveryNFrames", m_update_backup);
951 m_update_presences = startupConfig.GetInt( "UpdateAgentsEveryNFrames", m_update_presences); 1102 m_update_coarse_locations = startupConfig.GetInt("UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations);
952 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain); 1103 m_update_entitymovement = startupConfig.GetInt("UpdateEntityMovementEveryNFrames", m_update_entitymovement);
953 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning); 1104 m_update_events = startupConfig.GetInt("UpdateEventsEveryNFrames", m_update_events);
1105 m_update_objects = startupConfig.GetInt("UpdateObjectsEveryNFrames", m_update_objects);
1106 m_update_physics = startupConfig.GetInt("UpdatePhysicsEveryNFrames", m_update_physics);
1107 m_update_presences = startupConfig.GetInt("UpdateAgentsEveryNFrames", m_update_presences);
1108 m_update_terrain = startupConfig.GetInt("UpdateTerrainEveryNFrames", m_update_terrain);
1109 m_update_temp_cleaning = startupConfig.GetInt("UpdateTempCleaningEveryNSeconds", m_update_temp_cleaning);
1110
1111 if (startupConfig.Contains("ShouldUseFireAndForgetForCollisions"))
1112 {
1113 ShouldUseFireAndForgetForCollisions = startupConfig.GetBoolean("ShouldUseFireAndForgetForCollisions", false);
1114 }
954 } 1115 }
955 1116
1117
956 // FIXME: Ultimately this should be in a module. 1118 // FIXME: Ultimately this should be in a module.
957 SendPeriodicAppearanceUpdates = true; 1119 SendPeriodicAppearanceUpdates = false;
958 1120
959 IConfig appearanceConfig = m_config.Configs["Appearance"]; 1121 IConfig appearanceConfig = m_config.Configs["Appearance"];
960 if (appearanceConfig != null) 1122 if (appearanceConfig != null)
961 { 1123 {
@@ -965,6 +1127,12 @@ namespace OpenSim.Region.Framework.Scenes
965 1127
966 #endregion Region Config 1128 #endregion Region Config
967 1129
1130 IConfig entityTransferConfig = m_config.Configs["EntityTransfer"];
1131 if (entityTransferConfig != null)
1132 {
1133 AllowAvatarCrossing = entityTransferConfig.GetBoolean("AllowAvatarCrossing", AllowAvatarCrossing);
1134 }
1135
968 #region Interest Management 1136 #region Interest Management
969 1137
970 IConfig interestConfig = m_config.Configs["InterestManagement"]; 1138 IConfig interestConfig = m_config.Configs["InterestManagement"];
@@ -974,59 +1142,109 @@ namespace OpenSim.Region.Framework.Scenes
974 1142
975 try 1143 try
976 { 1144 {
977 m_priorityScheme = (UpdatePrioritizationSchemes)Enum.Parse(typeof(UpdatePrioritizationSchemes), update_prioritization_scheme, true); 1145 UpdatePrioritizationScheme = (UpdatePrioritizationSchemes)Enum.Parse(typeof(UpdatePrioritizationSchemes), update_prioritization_scheme, true);
978 } 1146 }
979 catch (Exception) 1147 catch (Exception)
980 { 1148 {
981 m_log.Warn("[PRIORITIZER]: UpdatePrioritizationScheme was not recognized, setting to default prioritizer Time"); 1149 m_log.Warn("[PRIORITIZER]: UpdatePrioritizationScheme was not recognized, setting to default prioritizer Time");
982 m_priorityScheme = UpdatePrioritizationSchemes.Time; 1150 UpdatePrioritizationScheme = UpdatePrioritizationSchemes.Time;
983 } 1151 }
984 1152
985 m_reprioritizationEnabled = interestConfig.GetBoolean("ReprioritizationEnabled", true); 1153 IsReprioritizationEnabled
986 m_reprioritizationInterval = interestConfig.GetDouble("ReprioritizationInterval", 5000.0); 1154 = interestConfig.GetBoolean("ReprioritizationEnabled", IsReprioritizationEnabled);
987 m_rootReprioritizationDistance = interestConfig.GetDouble("RootReprioritizationDistance", 10.0); 1155 ReprioritizationInterval
988 m_childReprioritizationDistance = interestConfig.GetDouble("ChildReprioritizationDistance", 20.0); 1156 = interestConfig.GetDouble("ReprioritizationInterval", ReprioritizationInterval);
1157 RootReprioritizationDistance
1158 = interestConfig.GetDouble("RootReprioritizationDistance", RootReprioritizationDistance);
1159 ChildReprioritizationDistance
1160 = interestConfig.GetDouble("ChildReprioritizationDistance", ChildReprioritizationDistance);
1161
1162 RootTerseUpdatePeriod = interestConfig.GetInt("RootTerseUpdatePeriod", RootTerseUpdatePeriod);
1163 ChildTerseUpdatePeriod = interestConfig.GetInt("ChildTerseUpdatePeriod", ChildTerseUpdatePeriod);
1164
1165 RootPositionUpdateTolerance
1166 = interestConfig.GetFloat("RootPositionUpdateTolerance", RootPositionUpdateTolerance);
1167 RootRotationUpdateTolerance
1168 = interestConfig.GetFloat("RootRotationUpdateTolerance", RootRotationUpdateTolerance);
1169 RootVelocityUpdateTolerance
1170 = interestConfig.GetFloat("RootVelocityUpdateTolerance", RootVelocityUpdateTolerance);
989 } 1171 }
990 1172
991 m_log.DebugFormat("[SCENE]: Using the {0} prioritization scheme", m_priorityScheme); 1173 m_log.DebugFormat("[SCENE]: Using the {0} prioritization scheme", UpdatePrioritizationScheme);
992 1174
993 #endregion Interest Management 1175 #endregion Interest Management
994 1176
995 StatsReporter = new SimStatsReporter(this); 1177 // The timer used by the Stopwatch class depends on the system hardware and operating system; inform
1178 // if the timer is based on a high-resolution performance counter or based on the system timer;
1179 // the performance counter will provide a more precise time than the system timer
1180 if (Stopwatch.IsHighResolution)
1181 m_log.InfoFormat("[SCENE]: Using high-resolution performance counter for statistics.");
1182 else
1183 m_log.InfoFormat("[SCENE]: Using system timer for statistics.");
1184
1185 // Acquire the statistics section of the OpenSim.ini file located
1186 // in the bin directory
1187 IConfig statisticsConfig = m_config.Configs["Statistics"];
1188
1189 // Confirm that the statistics section existed in the configuration
1190 // file
1191 if (statisticsConfig != null)
1192 {
1193 // Create the StatsReporter using the number of frames to store
1194 // for the frame time statistics, or 10 frames if the config
1195 // file doesn't contain a value
1196 StatsReporter = new SimStatsReporter(this,
1197 statisticsConfig.GetInt("NumberOfFrames",
1198 m_defaultNumberFramesStored));
1199 }
1200 else
1201 {
1202 // Create a StatsReporter with the current scene and a default
1203 // 10 frames stored for the frame time statistics
1204 StatsReporter = new SimStatsReporter(this);
1205 }
1206
996 StatsReporter.OnSendStatsResult += SendSimStatsPackets; 1207 StatsReporter.OnSendStatsResult += SendSimStatsPackets;
997 StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats; 1208 StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats;
1209
998 } 1210 }
999 1211
1000 public Scene(RegionInfo regInfo) : base(regInfo) 1212 public Scene(RegionInfo regInfo)
1213 : base(regInfo)
1001 { 1214 {
1215 m_sceneGraph = new SceneGraph(this);
1216
1217 // If the scene graph has an Unrecoverable error, restart this sim.
1218 // Currently the only thing that causes it to happen is two kinds of specific
1219 // Physics based crashes.
1220 //
1221 // Out of memory
1222 // Operating system has killed the plugin
1223 m_sceneGraph.UnRecoverableError
1224 += () =>
1225 {
1226 m_log.ErrorFormat("[SCENE]: Restarting region {0} due to unrecoverable physics crash", Name);
1227 RestartNow();
1228 };
1229
1002 PhysicalPrims = true; 1230 PhysicalPrims = true;
1003 CollidablePrims = true; 1231 CollidablePrims = true;
1004 PhysicsEnabled = true; 1232 PhysicsEnabled = true;
1005 1233
1234 AllowAvatarCrossing = true;
1235
1006 PeriodicBackup = true; 1236 PeriodicBackup = true;
1007 UseBackup = true; 1237 UseBackup = true;
1008 1238
1009 BordersLocked = true; 1239 IsReprioritizationEnabled = true;
1010 Border northBorder = new Border(); 1240 UpdatePrioritizationScheme = UpdatePrioritizationSchemes.Time;
1011 northBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, (int)Constants.RegionSize); //<--- 1241 ReprioritizationInterval = 5000;
1012 northBorder.CrossDirection = Cardinals.N;
1013 NorthBorders.Add(northBorder);
1014
1015 Border southBorder = new Border();
1016 southBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue,0); //--->
1017 southBorder.CrossDirection = Cardinals.S;
1018 SouthBorders.Add(southBorder);
1019 1242
1020 Border eastBorder = new Border(); 1243 RootRotationUpdateTolerance = 0.1f;
1021 eastBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, (int)Constants.RegionSize); //<--- 1244 RootVelocityUpdateTolerance = 0.001f;
1022 eastBorder.CrossDirection = Cardinals.E; 1245 RootPositionUpdateTolerance = 0.05f;
1023 EastBorders.Add(eastBorder); 1246 RootReprioritizationDistance = 10.0;
1024 1247 ChildReprioritizationDistance = 20.0;
1025 Border westBorder = new Border();
1026 westBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue,0); //--->
1027 westBorder.CrossDirection = Cardinals.W;
1028 WestBorders.Add(westBorder);
1029 BordersLocked = false;
1030 1248
1031 m_eventManager = new EventManager(); 1249 m_eventManager = new EventManager();
1032 1250
@@ -1046,13 +1264,44 @@ namespace OpenSim.Region.Framework.Scenes
1046 get { return m_sceneGraph; } 1264 get { return m_sceneGraph; }
1047 } 1265 }
1048 1266
1049 protected virtual void RegisterDefaultSceneEvents() 1267 /// <summary>
1268 /// Called by the module loader when all modules are loaded, after each module's
1269 /// RegionLoaded hook is called. This is the earliest time where RequestModuleInterface
1270 /// may be used.
1271 /// </summary>
1272 public void AllModulesLoaded()
1050 { 1273 {
1051 IDialogModule dm = RequestModuleInterface<IDialogModule>(); 1274 IDialogModule dm = RequestModuleInterface<IDialogModule>();
1052 1275
1053 if (dm != null) 1276 if (dm != null)
1054 m_eventManager.OnPermissionError += dm.SendAlertToUser; 1277 m_eventManager.OnPermissionError += dm.SendAlertToUser;
1055 1278
1279 ISimulatorFeaturesModule fm = RequestModuleInterface<ISimulatorFeaturesModule>();
1280 if (fm != null)
1281 {
1282 OSD openSimExtras;
1283 OSDMap openSimExtrasMap;
1284
1285 if (!fm.TryGetFeature("OpenSimExtras", out openSimExtras))
1286 openSimExtras = new OSDMap();
1287
1288 float FrameTime = MinFrameTicks / 1000.0f;
1289 float statisticsFPSfactor = 1.0f;
1290 if(Normalized55FPS)
1291 statisticsFPSfactor = 55.0f * FrameTime;
1292
1293 openSimExtrasMap = (OSDMap)openSimExtras;
1294 openSimExtrasMap["SimulatorFPS"] = OSD.FromReal(1.0f / FrameTime);
1295 openSimExtrasMap["SimulatorFPSFactor"] = OSD.FromReal(statisticsFPSfactor);
1296 openSimExtrasMap["SimulatorFPSWarnPercent"] = OSD.FromInteger(FrameTimeWarnPercent);
1297 openSimExtrasMap["SimulatorFPSCritPercent"] = OSD.FromInteger(FrameTimeCritPercent);
1298
1299 fm.AddFeature("OpenSimExtras", openSimExtrasMap);
1300 }
1301 }
1302
1303 protected virtual void RegisterDefaultSceneEvents()
1304 {
1056 m_eventManager.OnSignificantClientMovement += HandleOnSignificantClientMovement; 1305 m_eventManager.OnSignificantClientMovement += HandleOnSignificantClientMovement;
1057 } 1306 }
1058 1307
@@ -1074,17 +1323,22 @@ namespace OpenSim.Region.Framework.Scenes
1074 /// <returns>True after all operations complete, throws exceptions otherwise.</returns> 1323 /// <returns>True after all operations complete, throws exceptions otherwise.</returns>
1075 public override void OtherRegionUp(GridRegion otherRegion) 1324 public override void OtherRegionUp(GridRegion otherRegion)
1076 { 1325 {
1077 uint xcell = (uint)((int)otherRegion.RegionLocX / (int)Constants.RegionSize);
1078 uint ycell = (uint)((int)otherRegion.RegionLocY / (int)Constants.RegionSize);
1079 //m_log.InfoFormat("[SCENE]: (on region {0}): Region {1} up in coords {2}-{3}",
1080 // RegionInfo.RegionName, otherRegion.RegionName, xcell, ycell);
1081
1082 if (RegionInfo.RegionHandle != otherRegion.RegionHandle) 1326 if (RegionInfo.RegionHandle != otherRegion.RegionHandle)
1083 { 1327 {
1084 // If these are cast to INT because long + negative values + abs returns invalid data 1328 //// If these are cast to INT because long + negative values + abs returns invalid data
1085 int resultX = Math.Abs((int)xcell - (int)RegionInfo.RegionLocX); 1329 //int resultX = Math.Abs((int)xcell - (int)RegionInfo.RegionLocX);
1086 int resultY = Math.Abs((int)ycell - (int)RegionInfo.RegionLocY); 1330 //int resultY = Math.Abs((int)ycell - (int)RegionInfo.RegionLocY);
1087 if (resultX <= 1 && resultY <= 1) 1331 //if (resultX <= 1 && resultY <= 1)
1332 float dist = (float)Math.Max(DefaultDrawDistance,
1333 (float)Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY));
1334 uint newRegionX, newRegionY, thisRegionX, thisRegionY;
1335 Util.RegionHandleToRegionLoc(otherRegion.RegionHandle, out newRegionX, out newRegionY);
1336 Util.RegionHandleToRegionLoc(RegionInfo.RegionHandle, out thisRegionX, out thisRegionY);
1337
1338 //m_log.InfoFormat("[SCENE]: (on region {0}): Region {1} up in coords {2}-{3}",
1339 // RegionInfo.RegionName, otherRegion.RegionName, newRegionX, newRegionY);
1340
1341 if (!Util.IsOutsideView(dist, thisRegionX, newRegionX, thisRegionY, newRegionY))
1088 { 1342 {
1089 // Let the grid service module know, so this can be cached 1343 // Let the grid service module know, so this can be cached
1090 m_eventManager.TriggerOnRegionUp(otherRegion); 1344 m_eventManager.TriggerOnRegionUp(otherRegion);
@@ -1147,46 +1401,6 @@ namespace OpenSim.Region.Framework.Scenes
1147 return found; 1401 return found;
1148 } 1402 }
1149 1403
1150 /// <summary>
1151 /// Checks whether this region has a neighbour in the given direction.
1152 /// </summary>
1153 /// <param name="car"></param>
1154 /// <param name="fix"></param>
1155 /// <returns>
1156 /// An integer which represents a compass point. N == 1, going clockwise until we reach NW == 8.
1157 /// Returns a positive integer if there is a region in that direction, a negative integer if not.
1158 /// </returns>
1159 public int HaveNeighbor(Cardinals car, ref int[] fix)
1160 {
1161 uint neighbourx = RegionInfo.RegionLocX;
1162 uint neighboury = RegionInfo.RegionLocY;
1163
1164 int dir = (int)car;
1165
1166 if (dir > 1 && dir < 5) //Heading East
1167 neighbourx++;
1168 else if (dir > 5) // Heading West
1169 neighbourx--;
1170
1171 if (dir < 3 || dir == 8) // Heading North
1172 neighboury++;
1173 else if (dir > 3 && dir < 7) // Heading Sout
1174 neighboury--;
1175
1176 int x = (int)(neighbourx * Constants.RegionSize);
1177 int y = (int)(neighboury * Constants.RegionSize);
1178 GridRegion neighbourRegion = GridService.GetRegionByPosition(RegionInfo.ScopeID, x, y);
1179
1180 if (neighbourRegion == null)
1181 {
1182 fix[0] = (int)(RegionInfo.RegionLocX - neighbourx);
1183 fix[1] = (int)(RegionInfo.RegionLocY - neighboury);
1184 return dir * (-1);
1185 }
1186 else
1187 return dir;
1188 }
1189
1190 // Alias IncomingHelloNeighbour OtherRegionUp, for now 1404 // Alias IncomingHelloNeighbour OtherRegionUp, for now
1191 public GridRegion IncomingHelloNeighbour(RegionInfo neighbour) 1405 public GridRegion IncomingHelloNeighbour(RegionInfo neighbour)
1192 { 1406 {
@@ -1270,14 +1484,14 @@ namespace OpenSim.Region.Framework.Scenes
1270 1484
1271 // Kick all ROOT agents with the message, 'The simulator is going down' 1485 // Kick all ROOT agents with the message, 'The simulator is going down'
1272 ForEachScenePresence(delegate(ScenePresence avatar) 1486 ForEachScenePresence(delegate(ScenePresence avatar)
1273 { 1487 {
1274 avatar.RemoveNeighbourRegion(RegionInfo.RegionHandle); 1488 avatar.RemoveNeighbourRegion(RegionInfo.RegionHandle);
1275 1489
1276 if (!avatar.IsChildAgent) 1490 if (!avatar.IsChildAgent)
1277 avatar.ControllingClient.Kick("The simulator is going down."); 1491 avatar.ControllingClient.Kick("The simulator is going down.");
1278 1492
1279 avatar.ControllingClient.SendShutdownConnectionNotice(); 1493 avatar.ControllingClient.SendShutdownConnectionNotice();
1280 }); 1494 });
1281 1495
1282 // Stop updating the scene objects and agents. 1496 // Stop updating the scene objects and agents.
1283 m_shuttingDown = true; 1497 m_shuttingDown = true;
@@ -1288,20 +1502,11 @@ namespace OpenSim.Region.Framework.Scenes
1288 Thread.Sleep(500); 1502 Thread.Sleep(500);
1289 1503
1290 // Stop all client threads. 1504 // Stop all client threads.
1291 ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(); }); 1505 ForEachScenePresence(delegate(ScenePresence avatar) { CloseAgent(avatar.UUID, false); });
1292 1506
1293 m_log.Debug("[SCENE]: Persisting changed objects"); 1507 m_log.Debug("[SCENE]: Persisting changed objects");
1294 EventManager.TriggerSceneShuttingDown(this); 1508 EventManager.TriggerSceneShuttingDown(this);
1295 1509 Backup(false);
1296 EntityBase[] entities = GetEntities();
1297 foreach (EntityBase entity in entities)
1298 {
1299 if (!entity.IsDeleted && entity is SceneObjectGroup && ((SceneObjectGroup)entity).HasGroupChanged)
1300 {
1301 ((SceneObjectGroup)entity).ProcessBackup(SimulationDataService, false);
1302 }
1303 }
1304
1305 m_sceneGraph.Close(); 1510 m_sceneGraph.Close();
1306 1511
1307 if (!GridService.DeregisterRegion(RegionInfo.RegionID)) 1512 if (!GridService.DeregisterRegion(RegionInfo.RegionID))
@@ -1322,28 +1527,38 @@ namespace OpenSim.Region.Framework.Scenes
1322 } 1527 }
1323 } 1528 }
1324 1529
1530 public override void Start()
1531 {
1532 Start(true);
1533 }
1534
1325 /// <summary> 1535 /// <summary>
1326 /// Start the scene 1536 /// Start the scene
1327 /// </summary> 1537 /// </summary>
1328 public void Start() 1538 /// <param name='startScripts'>
1539 /// Start the scripts within the scene.
1540 /// </param>
1541 public void Start(bool startScripts)
1329 { 1542 {
1543 if (IsRunning)
1544 return;
1545
1546 m_isRunning = true;
1330 m_active = true; 1547 m_active = true;
1331 1548
1549 m_unixStartTime = Util.UnixTimeSinceEpoch();
1332// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); 1550// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName);
1333
1334 //m_heartbeatTimer.Enabled = true;
1335 //m_heartbeatTimer.Interval = (int)(m_timespan * 1000);
1336 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
1337 if (m_heartbeatThread != null) 1551 if (m_heartbeatThread != null)
1338 { 1552 {
1339 m_heartbeatThread.Abort(); 1553 m_heartbeatThread.Abort();
1340 m_heartbeatThread = null; 1554 m_heartbeatThread = null;
1341 } 1555 }
1342// m_lastUpdate = Util.EnvironmentTickCount();
1343 1556
1344 m_heartbeatThread 1557 m_heartbeatThread
1345 = Watchdog.StartThread( 1558 = WorkManager.StartThread(
1346 Heartbeat, string.Format("Heartbeat ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, false); 1559 Heartbeat, string.Format("Heartbeat-({0})", RegionInfo.RegionName.Replace(" ", "_")), ThreadPriority.Normal, false, false);
1560
1561 StartScripts();
1347 } 1562 }
1348 1563
1349 /// <summary> 1564 /// <summary>
@@ -1374,15 +1589,6 @@ namespace OpenSim.Region.Framework.Scenes
1374 /// </summary> 1589 /// </summary>
1375 private void Heartbeat() 1590 private void Heartbeat()
1376 { 1591 {
1377// if (!Monitor.TryEnter(m_heartbeatLock))
1378// {
1379// Watchdog.RemoveThread();
1380// return;
1381// }
1382
1383// try
1384// {
1385
1386 m_eventManager.TriggerOnRegionStarted(this); 1592 m_eventManager.TriggerOnRegionStarted(this);
1387 1593
1388 // The first frame can take a very long time due to physics actors being added on startup. Therefore, 1594 // The first frame can take a very long time due to physics actors being added on startup. Therefore,
@@ -1390,22 +1596,49 @@ namespace OpenSim.Region.Framework.Scenes
1390 // alarms for scenes with many objects. 1596 // alarms for scenes with many objects.
1391 Update(1); 1597 Update(1);
1392 1598
1393 Watchdog.StartThread( 1599 WorkManager.StartThread(
1394 Maintenance, string.Format("Maintenance ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, true); 1600 Maintenance, string.Format("Maintenance ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, true);
1395 1601
1396 Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true; 1602 Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true;
1397 Update(-1); 1603 m_lastFrameTick = Util.EnvironmentTickCount();
1398 1604
1399// m_lastUpdate = Util.EnvironmentTickCount(); 1605 if (UpdateOnTimer)
1400// m_firstHeartbeat = false; 1606 {
1401// } 1607 m_sceneUpdateTimer = new Timer(MinFrameTicks);
1402// finally 1608 m_sceneUpdateTimer.AutoReset = true;
1403// { 1609 m_sceneUpdateTimer.Elapsed += Update;
1404// Monitor.Pulse(m_heartbeatLock); 1610 m_sceneUpdateTimer.Start();
1405// Monitor.Exit(m_heartbeatLock); 1611 }
1406// } 1612 else
1613 {
1614 Thread.CurrentThread.Priority = ThreadPriority.Highest;
1615 Update(-1);
1616 Watchdog.RemoveThread();
1617 m_isRunning = false;
1618 }
1619 }
1407 1620
1408 Watchdog.RemoveThread(); 1621 private volatile bool m_isTimerUpdateRunning;
1622
1623 private void Update(object sender, ElapsedEventArgs e)
1624 {
1625 if (m_isTimerUpdateRunning)
1626 return;
1627
1628 m_isTimerUpdateRunning = true;
1629
1630 // If the last frame did not complete on time, then immediately start the next update on the same thread
1631 // and ignore further timed updates until we have a frame that had spare time.
1632 while (!Update(1) && Active) { }
1633
1634 if (!Active || m_shuttingDown)
1635 {
1636 m_sceneUpdateTimer.Stop();
1637 m_sceneUpdateTimer = null;
1638 m_isRunning = false;
1639 }
1640
1641 m_isTimerUpdateRunning = false;
1409 } 1642 }
1410 1643
1411 private void Maintenance() 1644 private void Maintenance()
@@ -1418,7 +1651,7 @@ namespace OpenSim.Region.Framework.Scenes
1418 public void DoMaintenance(int runs) 1651 public void DoMaintenance(int runs)
1419 { 1652 {
1420 long? endRun = null; 1653 long? endRun = null;
1421 int runtc; 1654 int runtc, tmpMS;
1422 int previousMaintenanceTick; 1655 int previousMaintenanceTick;
1423 1656
1424 if (runs >= 0) 1657 if (runs >= 0)
@@ -1432,6 +1665,8 @@ namespace OpenSim.Region.Framework.Scenes
1432 runtc = Util.EnvironmentTickCount(); 1665 runtc = Util.EnvironmentTickCount();
1433 ++MaintenanceRun; 1666 ++MaintenanceRun;
1434 1667
1668 // m_log.DebugFormat("[SCENE]: Maintenance run {0} in {1}", MaintenanceRun, Name);
1669
1435 // Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client) 1670 // Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client)
1436 if (MaintenanceRun % (m_update_coarse_locations / 10) == 0) 1671 if (MaintenanceRun % (m_update_coarse_locations / 10) == 0)
1437 { 1672 {
@@ -1445,7 +1680,7 @@ namespace OpenSim.Region.Framework.Scenes
1445 1680
1446 if (SendPeriodicAppearanceUpdates && MaintenanceRun % 60 == 0) 1681 if (SendPeriodicAppearanceUpdates && MaintenanceRun % 60 == 0)
1447 { 1682 {
1448// m_log.DebugFormat("[SCENE]: Sending periodic appearance updates"); 1683 // m_log.DebugFormat("[SCENE]: Sending periodic appearance updates");
1449 1684
1450 if (AvatarFactory != null) 1685 if (AvatarFactory != null)
1451 { 1686 {
@@ -1453,29 +1688,44 @@ namespace OpenSim.Region.Framework.Scenes
1453 } 1688 }
1454 } 1689 }
1455 1690
1691 // Delete temp-on-rez stuff
1692 if (MaintenanceRun % m_update_temp_cleaning == 0 && !m_cleaningTemps)
1693 {
1694 // m_log.DebugFormat("[SCENE]: Running temp-on-rez cleaning in {0}", Name);
1695 tmpMS = Util.EnvironmentTickCount();
1696 m_cleaningTemps = true;
1697
1698 WorkManager.RunInThread(
1699 delegate { CleanTempObjects(); m_cleaningTemps = false; },
1700 null,
1701 string.Format("CleanTempObjects ({0})", Name));
1702
1703 tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpMS);
1704 }
1705
1456 Watchdog.UpdateThread(); 1706 Watchdog.UpdateThread();
1457 1707
1458 previousMaintenanceTick = m_lastMaintenanceTick; 1708 previousMaintenanceTick = m_lastMaintenanceTick;
1459 m_lastMaintenanceTick = Util.EnvironmentTickCount(); 1709 m_lastMaintenanceTick = Util.EnvironmentTickCount();
1460 runtc = Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, runtc); 1710 runtc = Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, runtc);
1461 runtc = (int)(MinMaintenanceTime * 1000) - runtc; 1711 runtc = MinMaintenanceTicks - runtc;
1462 1712
1463 if (runtc > 0) 1713 if (runtc > 0)
1464 Thread.Sleep(runtc); 1714 m_maintenanceWaitEvent.WaitOne(runtc);
1465 1715
1466 // Optionally warn if a frame takes double the amount of time that it should. 1716 // Optionally warn if a frame takes double the amount of time that it should.
1467 if (DebugUpdates 1717 if (DebugUpdates
1468 && Util.EnvironmentTickCountSubtract( 1718 && Util.EnvironmentTickCountSubtract(
1469 m_lastMaintenanceTick, previousMaintenanceTick) > (int)(MinMaintenanceTime * 1000 * 2)) 1719 m_lastMaintenanceTick, previousMaintenanceTick) > MinMaintenanceTicks * 2)
1470 m_log.WarnFormat( 1720 m_log.WarnFormat(
1471 "[SCENE]: Maintenance took {0} ms (desired max {1} ms) in {2}", 1721 "[SCENE]: Maintenance took {0} ms (desired max {1} ms) in {2}",
1472 Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, previousMaintenanceTick), 1722 Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, previousMaintenanceTick),
1473 MinMaintenanceTime * 1000, 1723 MinMaintenanceTicks,
1474 RegionInfo.RegionName); 1724 RegionInfo.RegionName);
1475 } 1725 }
1476 } 1726 }
1477 1727
1478 public override void Update(int frames) 1728 public override bool Update(int frames)
1479 { 1729 {
1480 long? endFrame = null; 1730 long? endFrame = null;
1481 1731
@@ -1484,101 +1734,159 @@ namespace OpenSim.Region.Framework.Scenes
1484 1734
1485 float physicsFPS = 0f; 1735 float physicsFPS = 0f;
1486 int previousFrameTick, tmpMS; 1736 int previousFrameTick, tmpMS;
1487 int maintc = Util.EnvironmentTickCount(); 1737
1738 // These variables will be used to save the precise frame time using the
1739 // Stopwatch class of Microsoft SDK; the times are recorded at the start
1740 // and end of a particular section of code, and then used to calculate
1741 // the frame times, which are the sums of the sections for each given name
1742 double preciseTotalFrameTime = 0.0;
1743 double preciseSimFrameTime = 0.0;
1744 double precisePhysicsFrameTime = 0.0;
1745 Stopwatch totalFrameStopwatch = new Stopwatch();
1746 Stopwatch simFrameStopwatch = new Stopwatch();
1747 Stopwatch physicsFrameStopwatch = new Stopwatch();
1748
1749 // Begin the stopwatch to keep track of the time that the frame
1750 // started running to determine how long the frame took to complete
1751 totalFrameStopwatch.Start();
1488 1752
1489 while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame)) 1753 while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame))
1490 { 1754 {
1491 ++Frame; 1755 ++Frame;
1492 1756
1493// m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName); 1757 // m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName);
1494 1758
1495 agentMS = tempOnRezMS = eventMS = backupMS = terrainMS = landMS = spareMS = 0; 1759 agentMS = eventMS = backupMS = terrainMS = landMS = spareMS = 0;
1496 1760
1497 try 1761 try
1498 { 1762 {
1763 EventManager.TriggerRegionHeartbeatStart(this);
1764
1499 // Apply taints in terrain module to terrain in physics scene 1765 // Apply taints in terrain module to terrain in physics scene
1500 if (Frame % m_update_terrain == 0) 1766 if (Frame % m_update_terrain == 0)
1501 { 1767 {
1768 // At several points inside the code there was a need to
1769 // create a more precise measurement of time elapsed.
1770 // This led to the addition of variables that have a
1771 // similar function and thus remain tightly connected to
1772 // their original counterparts. However, the original
1773 // code is not receiving comments from our group because
1774 // we don't feel right modifying the code to that degree
1775 // at this point in time, the precise values all begin
1776 // with the keyword precise
1502 tmpMS = Util.EnvironmentTickCount(); 1777 tmpMS = Util.EnvironmentTickCount();
1778 simFrameStopwatch.Start();
1503 UpdateTerrain(); 1779 UpdateTerrain();
1780
1781 // Get the simulation frame time that the avatar force
1782 // input took
1783 simFrameStopwatch.Stop();
1784 preciseSimFrameTime =
1785 simFrameStopwatch.Elapsed.TotalMilliseconds;
1504 terrainMS = Util.EnvironmentTickCountSubtract(tmpMS); 1786 terrainMS = Util.EnvironmentTickCountSubtract(tmpMS);
1505 } 1787 }
1506 1788
1789 // At several points inside the code there was a need to
1790 // create a more precise measurement of time elapsed. This
1791 // led to the addition of variables that have a similar
1792 // function and thus remain tightly connected to their
1793 // original counterparts. However, the original code is
1794 // not receiving comments from our group because we don't
1795 // feel right modifying the code to that degree at this
1796 // point in time, the precise values all begin with the
1797 // keyword precise
1798
1507 tmpMS = Util.EnvironmentTickCount(); 1799 tmpMS = Util.EnvironmentTickCount();
1800
1801 // Begin the stopwatch to track the time to prepare physics
1802 physicsFrameStopwatch.Start();
1508 if (PhysicsEnabled && Frame % m_update_physics == 0) 1803 if (PhysicsEnabled && Frame % m_update_physics == 0)
1509 m_sceneGraph.UpdatePreparePhysics(); 1804 m_sceneGraph.UpdatePreparePhysics();
1805
1806 // Get the time it took to prepare the physics, this
1807 // would report the most precise time that physics was
1808 // running on the machine and should the physics not be
1809 // enabled will report the time it took to check if physics
1810 // was enabled
1811 physicsFrameStopwatch.Stop();
1812 precisePhysicsFrameTime = physicsFrameStopwatch.Elapsed.TotalMilliseconds;
1510 physicsMS2 = Util.EnvironmentTickCountSubtract(tmpMS); 1813 physicsMS2 = Util.EnvironmentTickCountSubtract(tmpMS);
1511 1814
1512 // Apply any pending avatar force input to the avatar's velocity 1815 // Apply any pending avatar force input to the avatar's velocity
1513 tmpMS = Util.EnvironmentTickCount(); 1816 tmpMS = Util.EnvironmentTickCount();
1817 simFrameStopwatch.Restart();
1514 if (Frame % m_update_entitymovement == 0) 1818 if (Frame % m_update_entitymovement == 0)
1515 m_sceneGraph.UpdateScenePresenceMovement(); 1819 m_sceneGraph.UpdateScenePresenceMovement();
1820
1821 // Get the simulation frame time that the avatar force input
1822 // took
1823 simFrameStopwatch.Stop();
1824 preciseSimFrameTime +=
1825 simFrameStopwatch.Elapsed.TotalMilliseconds;
1516 agentMS = Util.EnvironmentTickCountSubtract(tmpMS); 1826 agentMS = Util.EnvironmentTickCountSubtract(tmpMS);
1517 1827
1518 // Perform the main physics update. This will do the actual work of moving objects and avatars according to their 1828 // Perform the main physics update. This will do the actual work of moving objects and avatars according to their
1519 // velocity 1829 // velocity
1520 tmpMS = Util.EnvironmentTickCount(); 1830 tmpMS = Util.EnvironmentTickCount();
1831 physicsFrameStopwatch.Restart();
1521 if (Frame % m_update_physics == 0) 1832 if (Frame % m_update_physics == 0)
1522 { 1833 {
1523 if (PhysicsEnabled) 1834 if (PhysicsEnabled)
1524 physicsFPS = m_sceneGraph.UpdatePhysics(MinFrameTime); 1835 physicsFPS = m_sceneGraph.UpdatePhysics(MinFrameSeconds);
1525 1836
1526 if (SynchronizeScene != null) 1837 if (SynchronizeScene != null)
1527 SynchronizeScene(this); 1838 SynchronizeScene(this);
1528 } 1839 }
1840
1841 // Add the main physics update time to the prepare physics time
1842 physicsFrameStopwatch.Stop();
1843 precisePhysicsFrameTime += physicsFrameStopwatch.Elapsed.TotalMilliseconds;
1529 physicsMS = Util.EnvironmentTickCountSubtract(tmpMS); 1844 physicsMS = Util.EnvironmentTickCountSubtract(tmpMS);
1530 1845
1846 // Start the stopwatch for the remainder of the simulation
1847 simFrameStopwatch.Restart();
1531 tmpMS = Util.EnvironmentTickCount(); 1848 tmpMS = Util.EnvironmentTickCount();
1532 1849
1533 // Check if any objects have reached their targets 1850 // Check if any objects have reached their targets
1534 CheckAtTargets(); 1851 CheckAtTargets();
1535 1852
1536 // Update SceneObjectGroups that have scheduled themselves for updates 1853 // Update SceneObjectGroups that have scheduled themselves for updates
1537 // Objects queue their updates onto all scene presences 1854 // Objects queue their updates onto all scene presences
1538 if (Frame % m_update_objects == 0) 1855 if (Frame % m_update_objects == 0)
1539 m_sceneGraph.UpdateObjectGroups(); 1856 m_sceneGraph.UpdateObjectGroups();
1540 1857
1541 // Run through all ScenePresences looking for updates 1858 // Run through all ScenePresences looking for updates
1542 // Presence updates and queued object updates for each presence are sent to clients 1859 // Presence updates and queued object updates for each presence are sent to clients
1543 if (Frame % m_update_presences == 0) 1860 if (Frame % m_update_presences == 0)
1544 m_sceneGraph.UpdatePresences(); 1861 m_sceneGraph.UpdatePresences();
1545 1862
1546 agentMS += Util.EnvironmentTickCountSubtract(tmpMS); 1863 agentMS += Util.EnvironmentTickCountSubtract(tmpMS);
1547 1864
1548 // Delete temp-on-rez stuff
1549 if (Frame % m_update_temp_cleaning == 0 && !m_cleaningTemps)
1550 {
1551 tmpMS = Util.EnvironmentTickCount();
1552 m_cleaningTemps = true;
1553 Util.FireAndForget(delegate { CleanTempObjects(); m_cleaningTemps = false; });
1554 tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpMS);
1555 }
1556
1557 if (Frame % m_update_events == 0) 1865 if (Frame % m_update_events == 0)
1558 { 1866 {
1559 tmpMS = Util.EnvironmentTickCount(); 1867 tmpMS = Util.EnvironmentTickCount();
1560 UpdateEvents(); 1868 UpdateEvents();
1561 eventMS = Util.EnvironmentTickCountSubtract(tmpMS); 1869 eventMS = Util.EnvironmentTickCountSubtract(tmpMS);
1562 } 1870 }
1563 1871
1564 if (PeriodicBackup && Frame % m_update_backup == 0) 1872 if (PeriodicBackup && Frame % m_update_backup == 0)
1565 { 1873 {
1566 tmpMS = Util.EnvironmentTickCount(); 1874 tmpMS = Util.EnvironmentTickCount();
1567 UpdateStorageBackup(); 1875 UpdateStorageBackup();
1568 backupMS = Util.EnvironmentTickCountSubtract(tmpMS); 1876 backupMS = Util.EnvironmentTickCountSubtract(tmpMS);
1569 } 1877 }
1570 1878
1571 //if (Frame % m_update_land == 0) 1879 //if (Frame % m_update_land == 0)
1572 //{ 1880 //{
1573 // int ldMS = Util.EnvironmentTickCount(); 1881 // int ldMS = Util.EnvironmentTickCount();
1574 // UpdateLand(); 1882 // UpdateLand();
1575 // landMS = Util.EnvironmentTickCountSubtract(ldMS); 1883 // landMS = Util.EnvironmentTickCountSubtract(ldMS);
1576 //} 1884 //}
1577 1885
1578 if (!LoginsEnabled && Frame == 20) 1886 if (!LoginsEnabled && Frame == 20)
1579 { 1887 {
1580 // m_log.DebugFormat("{0} {1} {2}", LoginsDisabled, m_sceneGraph.GetActiveScriptsCount(), LoginLock); 1888 // m_log.DebugFormat("{0} {1} {2}", LoginsDisabled, m_sceneGraph.GetActiveScriptsCount(), LoginLock);
1581 1889
1582 // In 99.9% of cases it is a bad idea to manually force garbage collection. However, 1890 // In 99.9% of cases it is a bad idea to manually force garbage collection. However,
1583 // this is a rare case where we know we have just went through a long cycle of heap 1891 // this is a rare case where we know we have just went through a long cycle of heap
1584 // allocations, and there is no more work to be done until someone logs in 1892 // allocations, and there is no more work to be done until someone logs in
@@ -1593,7 +1901,7 @@ namespace OpenSim.Region.Framework.Scenes
1593 } 1901 }
1594 1902
1595 m_sceneGridService.InformNeighborsThatRegionisUp( 1903 m_sceneGridService.InformNeighborsThatRegionisUp(
1596 RequestModuleInterface<INeighbourService>(), RegionInfo); 1904 RequestModuleInterface<INeighbourService>(), RegionInfo);
1597 1905
1598 // Region ready should always be set 1906 // Region ready should always be set
1599 Ready = true; 1907 Ready = true;
@@ -1604,7 +1912,7 @@ namespace OpenSim.Region.Framework.Scenes
1604 if (m_sceneGraph.GetActiveScriptsCount() == 0) 1912 if (m_sceneGraph.GetActiveScriptsCount() == 0)
1605 { 1913 {
1606 // In this case, we leave it to the IRegionReadyModule to enable logins 1914 // In this case, we leave it to the IRegionReadyModule to enable logins
1607 1915
1608 // LoginLock can currently only be set by a region module implementation. 1916 // LoginLock can currently only be set by a region module implementation.
1609 // If somehow this hasn't been done then the quickest way to bugfix is to see the 1917 // If somehow this hasn't been done then the quickest way to bugfix is to see the
1610 // NullReferenceException 1918 // NullReferenceException
@@ -1620,26 +1928,42 @@ namespace OpenSim.Region.Framework.Scenes
1620 "[SCENE]: Failed on region {0} with exception {1}{2}", 1928 "[SCENE]: Failed on region {0} with exception {1}{2}",
1621 RegionInfo.RegionName, e.Message, e.StackTrace); 1929 RegionInfo.RegionName, e.Message, e.StackTrace);
1622 } 1930 }
1623 1931
1624 EventManager.TriggerRegionHeartbeatEnd(this); 1932 EventManager.TriggerRegionHeartbeatEnd(this);
1933 otherMS = eventMS + backupMS + terrainMS + landMS;
1625 1934
1626 Watchdog.UpdateThread(); 1935 // Get the elapsed time for the simulation frame
1936 simFrameStopwatch.Stop();
1937 preciseSimFrameTime +=
1938 simFrameStopwatch.Elapsed.TotalMilliseconds;
1627 1939
1628 previousFrameTick = m_lastFrameTick; 1940 if (!UpdateOnTimer)
1629 m_lastFrameTick = Util.EnvironmentTickCount(); 1941 {
1630 tmpMS = Util.EnvironmentTickCountSubtract(m_lastFrameTick, maintc); 1942 Watchdog.UpdateThread();
1631 tmpMS = (int)(MinFrameTime * 1000) - tmpMS;
1632 1943
1633 if (tmpMS > 0) 1944 spareMS = MinFrameTicks - Util.EnvironmentTickCountSubtract(m_lastFrameTick);
1945
1946 if (spareMS > 0)
1947 m_updateWaitEvent.WaitOne(spareMS);
1948 else
1949 spareMS = 0;
1950 }
1951 else
1634 { 1952 {
1635 Thread.Sleep(tmpMS); 1953 spareMS = Math.Max(0, MinFrameTicks - physicsMS2 - agentMS - physicsMS - otherMS);
1636 spareMS += tmpMS;
1637 } 1954 }
1638 1955
1639 frameMS = Util.EnvironmentTickCountSubtract(maintc); 1956 // Get the total frame time
1640 maintc = Util.EnvironmentTickCount(); 1957 totalFrameStopwatch.Stop();
1958 preciseTotalFrameTime =
1959 totalFrameStopwatch.Elapsed.TotalMilliseconds;
1641 1960
1642 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS; 1961 // Restart the stopwatch for the total time of the next frame
1962 totalFrameStopwatch.Restart();
1963
1964 previousFrameTick = m_lastFrameTick;
1965 frameMS = Util.EnvironmentTickCountSubtract(m_lastFrameTick);
1966 m_lastFrameTick = Util.EnvironmentTickCount();
1643 1967
1644 // if (Frame%m_update_avatars == 0) 1968 // if (Frame%m_update_avatars == 0)
1645 // UpdateInWorldTime(); 1969 // UpdateInWorldTime();
@@ -1653,18 +1977,53 @@ namespace OpenSim.Region.Framework.Scenes
1653 StatsReporter.addOtherMS(otherMS); 1977 StatsReporter.addOtherMS(otherMS);
1654 StatsReporter.AddSpareMS(spareMS); 1978 StatsReporter.AddSpareMS(spareMS);
1655 StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS()); 1979 StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS());
1980 StatsReporter.AddScriptMS((int) GetAndResetScriptExecutionTime());
1981
1982 // Send the correct time values to the stats reporter for the
1983 // frame times
1984 StatsReporter.addFrameTimeMilliseconds(preciseTotalFrameTime,
1985 preciseSimFrameTime, precisePhysicsFrameTime, 0.0);
1986
1987 // Send the correct number of frames that the physics library
1988 // has processed to the stats reporter
1989 StatsReporter.addPhysicsFrame(1);
1656 1990
1657 // Optionally warn if a frame takes double the amount of time that it should. 1991 // Optionally warn if a frame takes double the amount of time that it should.
1658 if (DebugUpdates 1992 if (DebugUpdates
1659 && Util.EnvironmentTickCountSubtract( 1993 && Util.EnvironmentTickCountSubtract(
1660 m_lastFrameTick, previousFrameTick) > (int)(MinFrameTime * 1000 * 2)) 1994 m_lastFrameTick, previousFrameTick) > MinFrameTicks * 2)
1661 m_log.WarnFormat( 1995 m_log.WarnFormat(
1662 "[SCENE]: Frame took {0} ms (desired max {1} ms) in {2}", 1996 "[SCENE]: Frame took {0} ms (desired max {1} ms) in {2}",
1663 Util.EnvironmentTickCountSubtract(m_lastFrameTick, previousFrameTick), 1997 Util.EnvironmentTickCountSubtract(m_lastFrameTick, previousFrameTick),
1664 MinFrameTime * 1000, 1998 MinFrameTicks,
1665 RegionInfo.RegionName); 1999 RegionInfo.RegionName);
1666 } 2000 }
1667 } 2001
2002 // Finished updating scene frame, so stop the total frame's Stopwatch
2003 totalFrameStopwatch.Stop();
2004
2005 return spareMS >= 0;
2006 }
2007
2008 /// <summary>
2009 /// Adds the execution time of one script to the total scripts execution time for this region.
2010 /// </summary>
2011 /// <param name="ticks">Elapsed Stopwatch ticks</param>
2012 public void AddScriptExecutionTime(long ticks)
2013 {
2014 Interlocked.Add(ref m_scriptExecutionTime, ticks);
2015 }
2016
2017 /// <summary>
2018 /// Returns the total execution time of all the scripts in the region since the last frame
2019 /// (in milliseconds), and clears the value in preparation for the next frame.
2020 /// </summary>
2021 /// <returns>Time in milliseconds</returns>
2022 private long GetAndResetScriptExecutionTime()
2023 {
2024 long ticks = Interlocked.Exchange(ref m_scriptExecutionTime, 0);
2025 return (ticks * 1000) / Stopwatch.Frequency;
2026 }
1668 2027
1669 public void AddGroupTarget(SceneObjectGroup grp) 2028 public void AddGroupTarget(SceneObjectGroup grp)
1670 { 2029 {
@@ -1723,7 +2082,7 @@ namespace OpenSim.Region.Framework.Scenes
1723 if (!m_backingup) 2082 if (!m_backingup)
1724 { 2083 {
1725 m_backingup = true; 2084 m_backingup = true;
1726 Util.FireAndForget(BackupWaitCallback); 2085 WorkManager.RunInThread(o => Backup(false), null, string.Format("BackupWaitCallback ({0})", Name));
1727 } 2086 }
1728 } 2087 }
1729 2088
@@ -1736,16 +2095,12 @@ namespace OpenSim.Region.Framework.Scenes
1736 } 2095 }
1737 2096
1738 /// <summary> 2097 /// <summary>
1739 /// Wrapper for Backup() that can be called with Util.FireAndForget() 2098 /// Backup the scene.
1740 /// </summary>
1741 private void BackupWaitCallback(object o)
1742 {
1743 Backup(false);
1744 }
1745
1746 /// <summary>
1747 /// Backup the scene. This acts as the main method of the backup thread.
1748 /// </summary> 2099 /// </summary>
2100 /// <remarks>
2101 /// This acts as the main method of the backup thread. In a regression test whether the backup thread is not
2102 /// running independently this can be invoked directly.
2103 /// </remarks>
1749 /// <param name="forced"> 2104 /// <param name="forced">
1750 /// If true, then any changes that have not yet been persisted are persisted. If false, 2105 /// If true, then any changes that have not yet been persisted are persisted. If false,
1751 /// then the persistence decision is left to the backup code (in some situations, such as object persistence, 2106 /// then the persistence decision is left to the backup code (in some situations, such as object persistence,
@@ -1784,7 +2139,7 @@ namespace OpenSim.Region.Framework.Scenes
1784 2139
1785 IMessageTransferModule tr = RequestModuleInterface<IMessageTransferModule>(); 2140 IMessageTransferModule tr = RequestModuleInterface<IMessageTransferModule>();
1786 if (tr != null) 2141 if (tr != null)
1787 tr.SendInstantMessage(msg, delegate(bool success) {}); 2142 tr.SendInstantMessage(msg, delegate(bool success) { });
1788 } 2143 }
1789 m_returns.Clear(); 2144 m_returns.Clear();
1790 } 2145 }
@@ -1798,6 +2153,7 @@ namespace OpenSim.Region.Framework.Scenes
1798 { 2153 {
1799 if (group != null) 2154 if (group != null)
1800 { 2155 {
2156 group.HasGroupChanged = true;
1801 group.ProcessBackup(SimulationDataService, true); 2157 group.ProcessBackup(SimulationDataService, true);
1802 } 2158 }
1803 } 2159 }
@@ -1866,7 +2222,7 @@ namespace OpenSim.Region.Framework.Scenes
1866 { 2222 {
1867 try 2223 try
1868 { 2224 {
1869 double[,] map = SimulationDataService.LoadTerrain(RegionInfo.RegionID); 2225 TerrainData map = SimulationDataService.LoadTerrain(RegionInfo.RegionID, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ);
1870 if (map == null) 2226 if (map == null)
1871 { 2227 {
1872 // This should be in the Terrain module, but it isn't because 2228 // This should be in the Terrain module, but it isn't because
@@ -1877,7 +2233,7 @@ namespace OpenSim.Region.Framework.Scenes
1877 m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain); 2233 m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain);
1878 2234
1879 m_log.InfoFormat("[TERRAIN]: No default terrain. Generating a new terrain {0}.", m_InitialTerrain); 2235 m_log.InfoFormat("[TERRAIN]: No default terrain. Generating a new terrain {0}.", m_InitialTerrain);
1880 Heightmap = new TerrainChannel(m_InitialTerrain); 2236 Heightmap = new TerrainChannel(m_InitialTerrain, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ);
1881 2237
1882 SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); 2238 SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID);
1883 } 2239 }
@@ -1891,9 +2247,9 @@ namespace OpenSim.Region.Framework.Scenes
1891 m_log.WarnFormat( 2247 m_log.WarnFormat(
1892 "[TERRAIN]: Scene.cs: LoadWorldMap() - Regenerating as failed with exception {0}{1}", 2248 "[TERRAIN]: Scene.cs: LoadWorldMap() - Regenerating as failed with exception {0}{1}",
1893 e.Message, e.StackTrace); 2249 e.Message, e.StackTrace);
1894 2250
1895 // Non standard region size. If there's an old terrain in the database, it might read past the buffer 2251 // Non standard region size. If there's an old terrain in the database, it might read past the buffer
1896 #pragma warning disable 0162 2252#pragma warning disable 0162
1897 if ((int)Constants.RegionSize != 256) 2253 if ((int)Constants.RegionSize != 256)
1898 { 2254 {
1899 Heightmap = new TerrainChannel(); 2255 Heightmap = new TerrainChannel();
@@ -1921,10 +2277,16 @@ namespace OpenSim.Region.Framework.Scenes
1921 //// stored in the GridService, because that's what the world map module uses 2277 //// stored in the GridService, because that's what the world map module uses
1922 //// to send the map image UUIDs (of other regions) to the viewer... 2278 //// to send the map image UUIDs (of other regions) to the viewer...
1923 if (m_generateMaptiles) 2279 if (m_generateMaptiles)
1924 RegenerateMaptile(); 2280 RegenerateMaptile();
1925 2281
1926 GridRegion region = new GridRegion(RegionInfo); 2282 GridRegion region = new GridRegion(RegionInfo);
1927 string error = GridService.RegisterRegion(RegionInfo.ScopeID, region); 2283 string error = GridService.RegisterRegion(RegionInfo.ScopeID, region);
2284 // m_log.DebugFormat("[SCENE]: RegisterRegionWithGrid. name={0},id={1},loc=<{2},{3}>,size=<{4},{5}>",
2285 // m_regionName,
2286 // RegionInfo.RegionID,
2287 // RegionInfo.RegionLocX, RegionInfo.RegionLocY,
2288 // RegionInfo.RegionSizeX, RegionInfo.RegionSizeY);
2289
1928 if (error != String.Empty) 2290 if (error != String.Empty)
1929 throw new Exception(error); 2291 throw new Exception(error);
1930 } 2292 }
@@ -1985,13 +2347,26 @@ namespace OpenSim.Region.Framework.Scenes
1985 rootPart.TrimPermissions(); 2347 rootPart.TrimPermissions();
1986 2348
1987 // Don't do this here - it will get done later on when sculpt data is loaded. 2349 // Don't do this here - it will get done later on when sculpt data is loaded.
1988// group.CheckSculptAndLoad(); 2350 // group.CheckSculptAndLoad();
1989 } 2351 }
1990 2352
1991 LoadingPrims = false; 2353 LoadingPrims = false;
1992 EventManager.TriggerPrimsLoaded(this); 2354 EventManager.TriggerPrimsLoaded(this);
1993 } 2355 }
1994 2356
2357 public bool SupportsRayCastFiltered()
2358 {
2359 if (PhysicsScene == null)
2360 return false;
2361 return PhysicsScene.SupportsRaycastWorldFiltered();
2362 }
2363
2364 public object RayCastFiltered(Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags filter)
2365 {
2366 if (PhysicsScene == null)
2367 return null;
2368 return PhysicsScene.RaycastWorld(position, direction, length, Count, filter);
2369 }
1995 2370
1996 /// <summary> 2371 /// <summary>
1997 /// Gets a new rez location based on the raycast and the size of the object that is being rezzed. 2372 /// Gets a new rez location based on the raycast and the size of the object that is being rezzed.
@@ -2020,8 +2395,8 @@ namespace OpenSim.Region.Framework.Scenes
2020 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 2395 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
2021 2396
2022 Vector3 direction = Vector3.Normalize(RayEnd - RayStart); 2397 Vector3 direction = Vector3.Normalize(RayEnd - RayStart);
2023 Vector3 AXOrigin = new Vector3(RayStart.X, RayStart.Y, RayStart.Z); 2398 Vector3 AXOrigin = RayStart;
2024 Vector3 AXdirection = new Vector3(direction.X, direction.Y, direction.Z); 2399 Vector3 AXdirection = direction;
2025 2400
2026 if (target != null) 2401 if (target != null)
2027 { 2402 {
@@ -2037,19 +2412,19 @@ namespace OpenSim.Region.Framework.Scenes
2037 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 2412 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
2038 2413
2039 // Un-comment out the following line to Get Raytrace results printed to the console. 2414 // Un-comment out the following line to Get Raytrace results printed to the console.
2040 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 2415 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
2041 float ScaleOffset = 0.5f; 2416 float ScaleOffset = 0.5f;
2042 2417
2043 // If we hit something 2418 // If we hit something
2044 if (ei.HitTF) 2419 if (ei.HitTF)
2045 { 2420 {
2046 Vector3 scaleComponent = new Vector3(ei.AAfaceNormal.X, ei.AAfaceNormal.Y, ei.AAfaceNormal.Z); 2421 Vector3 scaleComponent = ei.AAfaceNormal;
2047 if (scaleComponent.X != 0) ScaleOffset = scale.X; 2422 if (scaleComponent.X != 0) ScaleOffset = scale.X;
2048 if (scaleComponent.Y != 0) ScaleOffset = scale.Y; 2423 if (scaleComponent.Y != 0) ScaleOffset = scale.Y;
2049 if (scaleComponent.Z != 0) ScaleOffset = scale.Z; 2424 if (scaleComponent.Z != 0) ScaleOffset = scale.Z;
2050 ScaleOffset = Math.Abs(ScaleOffset); 2425 ScaleOffset = Math.Abs(ScaleOffset);
2051 Vector3 intersectionpoint = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 2426 Vector3 intersectionpoint = ei.ipoint;
2052 Vector3 normal = new Vector3(ei.normal.X, ei.normal.Y, ei.normal.Z); 2427 Vector3 normal = ei.normal;
2053 // Set the position to the intersection point 2428 // Set the position to the intersection point
2054 Vector3 offset = (normal * (ScaleOffset / 2f)); 2429 Vector3 offset = (normal * (ScaleOffset / 2f));
2055 pos = (intersectionpoint + offset); 2430 pos = (intersectionpoint + offset);
@@ -2058,7 +2433,7 @@ namespace OpenSim.Region.Framework.Scenes
2058 //And in cases when we weren't rezzing from inventory we were re-adding the 0.25 straight after calling this method 2433 //And in cases when we weren't rezzing from inventory we were re-adding the 0.25 straight after calling this method
2059 // Un-offset the prim (it gets offset later by the consumer method) 2434 // Un-offset the prim (it gets offset later by the consumer method)
2060 //pos.Z -= 0.25F; 2435 //pos.Z -= 0.25F;
2061 2436
2062 } 2437 }
2063 2438
2064 return pos; 2439 return pos;
@@ -2074,8 +2449,9 @@ namespace OpenSim.Region.Framework.Scenes
2074 2449
2075 if (ei.HitTF) 2450 if (ei.HitTF)
2076 { 2451 {
2077 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 2452 pos = ei.ipoint;
2078 } else 2453 }
2454 else
2079 { 2455 {
2080 // fall back to our stupid functionality 2456 // fall back to our stupid functionality
2081 pos = RayEnd; 2457 pos = RayEnd;
@@ -2137,7 +2513,7 @@ namespace OpenSim.Region.Framework.Scenes
2137 // "[SCENE]: Scene.AddNewPrim() pcode {0} called for {1} in {2}", shape.PCode, ownerID, RegionInfo.RegionName); 2513 // "[SCENE]: Scene.AddNewPrim() pcode {0} called for {1} in {2}", shape.PCode, ownerID, RegionInfo.RegionName);
2138 2514
2139 SceneObjectGroup sceneObject = null; 2515 SceneObjectGroup sceneObject = null;
2140 2516
2141 // If an entity creator has been registered for this prim type then use that 2517 // If an entity creator has been registered for this prim type then use that
2142 if (m_entityCreators.ContainsKey((PCode)shape.PCode)) 2518 if (m_entityCreators.ContainsKey((PCode)shape.PCode))
2143 { 2519 {
@@ -2158,7 +2534,7 @@ namespace OpenSim.Region.Framework.Scenes
2158 2534
2159 return sceneObject; 2535 return sceneObject;
2160 } 2536 }
2161 2537
2162 /// <summary> 2538 /// <summary>
2163 /// Add an object into the scene that has come from storage 2539 /// Add an object into the scene that has come from storage
2164 /// </summary> 2540 /// </summary>
@@ -2191,7 +2567,7 @@ namespace OpenSim.Region.Framework.Scenes
2191 return false; 2567 return false;
2192 2568
2193 } 2569 }
2194 2570
2195 /// <summary> 2571 /// <summary>
2196 /// Add an object into the scene that has come from storage 2572 /// Add an object into the scene that has come from storage
2197 /// </summary> 2573 /// </summary>
@@ -2227,7 +2603,7 @@ namespace OpenSim.Region.Framework.Scenes
2227 { 2603 {
2228 return AddNewSceneObject(sceneObject, attachToBackup, true); 2604 return AddNewSceneObject(sceneObject, attachToBackup, true);
2229 } 2605 }
2230 2606
2231 /// <summary> 2607 /// <summary>
2232 /// Add a newly created object to the scene 2608 /// Add a newly created object to the scene
2233 /// </summary> 2609 /// </summary>
@@ -2242,16 +2618,16 @@ namespace OpenSim.Region.Framework.Scenes
2242 /// </param> 2618 /// </param>
2243 /// <returns>true if the object was added. false if not</returns> 2619 /// <returns>true if the object was added. false if not</returns>
2244 public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 2620 public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
2245 { 2621 {
2246 if (m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates)) 2622 if (m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates))
2247 { 2623 {
2248 EventManager.TriggerObjectAddedToScene(sceneObject); 2624 EventManager.TriggerObjectAddedToScene(sceneObject);
2249 return true; 2625 return true;
2250 } 2626 }
2251 2627
2252 return false; 2628 return false;
2253 } 2629 }
2254 2630
2255 /// <summary> 2631 /// <summary>
2256 /// Add a newly created object to the scene. 2632 /// Add a newly created object to the scene.
2257 /// </summary> 2633 /// </summary>
@@ -2268,7 +2644,7 @@ namespace OpenSim.Region.Framework.Scenes
2268 SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel) 2644 SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel)
2269 { 2645 {
2270 if (m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, pos, rot, vel)) 2646 if (m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, pos, rot, vel))
2271 { 2647 {
2272 EventManager.TriggerObjectAddedToScene(sceneObject); 2648 EventManager.TriggerObjectAddedToScene(sceneObject);
2273 return true; 2649 return true;
2274 } 2650 }
@@ -2316,8 +2692,8 @@ namespace OpenSim.Region.Framework.Scenes
2316 /// <param name="silent">Suppress broadcasting changes to other clients.</param> 2692 /// <param name="silent">Suppress broadcasting changes to other clients.</param>
2317 /// <param name="removeScripts">If true, then scripts are removed. If false, then they are only stopped.</para> 2693 /// <param name="removeScripts">If true, then scripts are removed. If false, then they are only stopped.</para>
2318 public void DeleteSceneObject(SceneObjectGroup group, bool silent, bool removeScripts) 2694 public void DeleteSceneObject(SceneObjectGroup group, bool silent, bool removeScripts)
2319 { 2695 {
2320// m_log.DebugFormat("[SCENE]: Deleting scene object {0} {1}", group.Name, group.UUID); 2696 // m_log.DebugFormat("[SCENE]: Deleting scene object {0} {1}", group.Name, group.UUID);
2321 2697
2322 if (removeScripts) 2698 if (removeScripts)
2323 group.RemoveScriptInstances(true); 2699 group.RemoveScriptInstances(true);
@@ -2328,6 +2704,12 @@ namespace OpenSim.Region.Framework.Scenes
2328 2704
2329 foreach (SceneObjectPart part in partList) 2705 foreach (SceneObjectPart part in partList)
2330 { 2706 {
2707 if (part.KeyframeMotion != null)
2708 {
2709 part.KeyframeMotion.Delete();
2710 part.KeyframeMotion = null;
2711 }
2712
2331 if (part.IsJoint() && ((part.Flags & PrimFlags.Physics) != 0)) 2713 if (part.IsJoint() && ((part.Flags & PrimFlags.Physics) != 0))
2332 { 2714 {
2333 PhysicsScene.RequestJointDeletion(part.Name); // FIXME: what if the name changed? 2715 PhysicsScene.RequestJointDeletion(part.Name); // FIXME: what if the name changed?
@@ -2346,7 +2728,7 @@ namespace OpenSim.Region.Framework.Scenes
2346 2728
2347 group.DeleteGroupFromScene(silent); 2729 group.DeleteGroupFromScene(silent);
2348 2730
2349// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2731 // m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2350 } 2732 }
2351 2733
2352 /// <summary> 2734 /// <summary>
@@ -2362,17 +2744,16 @@ namespace OpenSim.Region.Framework.Scenes
2362 { 2744 {
2363 if (!softDelete) 2745 if (!softDelete)
2364 { 2746 {
2365 // Force a database update so that the scene object group ID is accurate. It's possible that the 2747 // If the group contains prims whose SceneGroupID is incorrect then force a
2366 // group has recently been delinked from another group but that this change has not been persisted 2748 // database update, because RemoveObject() works by searching on the SceneGroupID.
2367 // to the DB.
2368 // This is an expensive thing to do so only do it if absolutely necessary. 2749 // This is an expensive thing to do so only do it if absolutely necessary.
2369 if (so.HasGroupChangedDueToDelink) 2750 if (so.GroupContainsForeignPrims)
2370 ForceSceneObjectBackup(so); 2751 ForceSceneObjectBackup(so);
2371 2752
2372 so.DetachFromBackup(); 2753 so.DetachFromBackup();
2373 SimulationDataService.RemoveObject(so.UUID, RegionInfo.RegionID); 2754 SimulationDataService.RemoveObject(so.UUID, RegionInfo.RegionID);
2374 } 2755 }
2375 2756
2376 // We need to keep track of this state in case this group is still queued for further backup. 2757 // We need to keep track of this state in case this group is still queued for further backup.
2377 so.IsDeleted = true; 2758 so.IsDeleted = true;
2378 2759
@@ -2431,186 +2812,35 @@ namespace OpenSim.Region.Framework.Scenes
2431 EntityTransferModule.Cross(grp, attemptedPosition, silent); 2812 EntityTransferModule.Cross(grp, attemptedPosition, silent);
2432 } 2813 }
2433 2814
2434 public Border GetCrossedBorder(Vector3 position, Cardinals gridline) 2815 // Simple test to see if a position is in the current region.
2816 // This test is mostly used to see if a region crossing is necessary.
2817 // Assuming the position is relative to the region so anything outside its bounds.
2818 // Return 'true' if position inside region.
2819 public bool PositionIsInCurrentRegion(Vector3 pos)
2435 { 2820 {
2436 if (BordersLocked) 2821 bool ret = false;
2437 { 2822 int xx = (int)Math.Floor(pos.X);
2438 switch (gridline) 2823 int yy = (int)Math.Floor(pos.Y);
2439 { 2824 if (xx < 0 || yy < 0)
2440 case Cardinals.N: 2825 return false;
2441 lock (NorthBorders)
2442 {
2443 foreach (Border b in NorthBorders)
2444 {
2445 if (b.TestCross(position))
2446 return b;
2447 }
2448 }
2449 break;
2450 case Cardinals.S:
2451 lock (SouthBorders)
2452 {
2453 foreach (Border b in SouthBorders)
2454 {
2455 if (b.TestCross(position))
2456 return b;
2457 }
2458 }
2459
2460 break;
2461 case Cardinals.E:
2462 lock (EastBorders)
2463 {
2464 foreach (Border b in EastBorders)
2465 {
2466 if (b.TestCross(position))
2467 return b;
2468 }
2469 }
2470
2471 break;
2472 case Cardinals.W:
2473
2474 lock (WestBorders)
2475 {
2476 foreach (Border b in WestBorders)
2477 {
2478 if (b.TestCross(position))
2479 return b;
2480 }
2481 }
2482 break;
2483 2826
2484 } 2827 IRegionCombinerModule regionCombinerModule = RequestModuleInterface<IRegionCombinerModule>();
2828 if (regionCombinerModule == null)
2829 {
2830 // Regular region. Just check for region size
2831 if (xx < RegionInfo.RegionSizeX && yy < RegionInfo.RegionSizeY)
2832 ret = true;
2485 } 2833 }
2486 else 2834 else
2487 { 2835 {
2488 switch (gridline) 2836 // We're in a mega-region so see if we are still in that larger region
2489 { 2837 ret = regionCombinerModule.PositionIsInMegaregion(this.RegionInfo.RegionID, xx, yy);
2490 case Cardinals.N:
2491 foreach (Border b in NorthBorders)
2492 {
2493 if (b.TestCross(position))
2494 return b;
2495 }
2496
2497 break;
2498 case Cardinals.S:
2499 foreach (Border b in SouthBorders)
2500 {
2501 if (b.TestCross(position))
2502 return b;
2503 }
2504 break;
2505 case Cardinals.E:
2506 foreach (Border b in EastBorders)
2507 {
2508 if (b.TestCross(position))
2509 return b;
2510 }
2511
2512 break;
2513 case Cardinals.W:
2514 foreach (Border b in WestBorders)
2515 {
2516 if (b.TestCross(position))
2517 return b;
2518 }
2519 break;
2520
2521 }
2522 } 2838 }
2523
2524 2839
2525 return null; 2840 return ret;
2526 }
2527 2841
2528 public bool TestBorderCross(Vector3 position, Cardinals border)
2529 {
2530 if (BordersLocked)
2531 {
2532 switch (border)
2533 {
2534 case Cardinals.N:
2535 lock (NorthBorders)
2536 {
2537 foreach (Border b in NorthBorders)
2538 {
2539 if (b.TestCross(position))
2540 return true;
2541 }
2542 }
2543 break;
2544 case Cardinals.E:
2545 lock (EastBorders)
2546 {
2547 foreach (Border b in EastBorders)
2548 {
2549 if (b.TestCross(position))
2550 return true;
2551 }
2552 }
2553 break;
2554 case Cardinals.S:
2555 lock (SouthBorders)
2556 {
2557 foreach (Border b in SouthBorders)
2558 {
2559 if (b.TestCross(position))
2560 return true;
2561 }
2562 }
2563 break;
2564 case Cardinals.W:
2565 lock (WestBorders)
2566 {
2567 foreach (Border b in WestBorders)
2568 {
2569 if (b.TestCross(position))
2570 return true;
2571 }
2572 }
2573 break;
2574 }
2575 }
2576 else
2577 {
2578 switch (border)
2579 {
2580 case Cardinals.N:
2581 foreach (Border b in NorthBorders)
2582 {
2583 if (b.TestCross(position))
2584 return true;
2585 }
2586 break;
2587 case Cardinals.E:
2588 foreach (Border b in EastBorders)
2589 {
2590 if (b.TestCross(position))
2591 return true;
2592 }
2593 break;
2594 case Cardinals.S:
2595 foreach (Border b in SouthBorders)
2596 {
2597 if (b.TestCross(position))
2598 return true;
2599 }
2600 break;
2601 case Cardinals.W:
2602 foreach (Border b in WestBorders)
2603 {
2604 if (b.TestCross(position))
2605 return true;
2606 }
2607 break;
2608 }
2609 }
2610 return false;
2611 } 2842 }
2612 2843
2613
2614 /// <summary> 2844 /// <summary>
2615 /// Called when objects or attachments cross the border, or teleport, between regions. 2845 /// Called when objects or attachments cross the border, or teleport, between regions.
2616 /// </summary> 2846 /// </summary>
@@ -2632,45 +2862,8 @@ namespace OpenSim.Region.Framework.Scenes
2632 return false; 2862 return false;
2633 } 2863 }
2634 2864
2635 // If the user is banned, we won't let any of their objects 2865 if (!EntityTransferModule.HandleIncomingSceneObject(newObject, newPosition))
2636 // enter. Period.
2637 //
2638 if (RegionInfo.EstateSettings.IsBanned(newObject.OwnerID))
2639 {
2640 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", newObject.OwnerID);
2641 return false;
2642 }
2643
2644 if (newPosition != Vector3.Zero)
2645 newObject.RootPart.GroupPosition = newPosition;
2646
2647 if (!AddSceneObject(newObject))
2648 {
2649 m_log.DebugFormat(
2650 "[INTERREGION]: Problem adding scene object {0} in {1} ", newObject.UUID, RegionInfo.RegionName);
2651 return false; 2866 return false;
2652 }
2653
2654 if (!newObject.IsAttachment)
2655 {
2656 // FIXME: It would be better to never add the scene object at all rather than add it and then delete
2657 // it
2658 if (!Permissions.CanObjectEntry(newObject.UUID, true, newObject.AbsolutePosition))
2659 {
2660 // Deny non attachments based on parcel settings
2661 //
2662 m_log.Info("[INTERREGION]: Denied prim crossing because of parcel settings");
2663
2664 DeleteSceneObject(newObject, false);
2665
2666 return false;
2667 }
2668
2669 // For attachments, we need to wait until the agent is root
2670 // before we restart the scripts, or else some functions won't work.
2671 newObject.RootPart.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, GetStateSource(newObject));
2672 newObject.ResumeScripts();
2673 }
2674 2867
2675 // Do this as late as possible so that listeners have full access to the incoming object 2868 // Do this as late as possible so that listeners have full access to the incoming object
2676 EventManager.TriggerOnIncomingSceneObject(newObject); 2869 EventManager.TriggerOnIncomingSceneObject(newObject);
@@ -2697,7 +2890,7 @@ namespace OpenSim.Region.Framework.Scenes
2697 { 2890 {
2698 sceneObject.RootPart.AddFlag(PrimFlags.TemporaryOnRez); 2891 sceneObject.RootPart.AddFlag(PrimFlags.TemporaryOnRez);
2699 sceneObject.RootPart.AddFlag(PrimFlags.Phantom); 2892 sceneObject.RootPart.AddFlag(PrimFlags.Phantom);
2700 2893
2701 // Don't sent a full update here because this will cause full updates to be sent twice for 2894 // Don't sent a full update here because this will cause full updates to be sent twice for
2702 // attachments on region crossings, resulting in viewer glitches. 2895 // attachments on region crossings, resulting in viewer glitches.
2703 AddRestoredSceneObject(sceneObject, false, false, false); 2896 AddRestoredSceneObject(sceneObject, false, false, false);
@@ -2712,15 +2905,18 @@ namespace OpenSim.Region.Framework.Scenes
2712 { 2905 {
2713 SceneObjectGroup grp = sceneObject; 2906 SceneObjectGroup grp = sceneObject;
2714 2907
2715// m_log.DebugFormat( 2908 // m_log.DebugFormat(
2716// "[ATTACHMENT]: Received attachment {0}, inworld asset id {1}", grp.FromItemID, grp.UUID); 2909 // "[ATTACHMENT]: Received attachment {0}, inworld asset id {1}", grp.FromItemID, grp.UUID);
2717// m_log.DebugFormat( 2910 // m_log.DebugFormat(
2718// "[ATTACHMENT]: Attach to avatar {0} at position {1}", sp.UUID, grp.AbsolutePosition); 2911 // "[ATTACHMENT]: Attach to avatar {0} at position {1}", sp.UUID, grp.AbsolutePosition);
2719 2912
2720 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2913 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2721 2914
2915 // We must currently not resume scripts at this stage since AttachmentsModule does not have the
2916 // information that this is due to a teleport/border cross rather than an ordinary attachment.
2917 // We currently do this in Scene.MakeRootAgent() instead.
2722 if (AttachmentsModule != null) 2918 if (AttachmentsModule != null)
2723 AttachmentsModule.AttachObject(sp, grp, 0, false, false); 2919 AttachmentsModule.AttachObject(sp, grp, 0, false, false, true);
2724 } 2920 }
2725 else 2921 else
2726 { 2922 {
@@ -2736,28 +2932,22 @@ namespace OpenSim.Region.Framework.Scenes
2736 return true; 2932 return true;
2737 } 2933 }
2738 2934
2739 private int GetStateSource(SceneObjectGroup sog)
2740 {
2741 ScenePresence sp = GetScenePresence(sog.OwnerID);
2742
2743 if (sp != null)
2744 return sp.GetStateSource();
2745
2746 return 2; // StateSource.PrimCrossing
2747 }
2748
2749 #endregion 2935 #endregion
2750 2936
2751 #region Add/Remove Avatar Methods 2937 #region Add/Remove Avatar Methods
2752 2938
2753 public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) 2939 public override ISceneAgent AddNewAgent(IClientAPI client, PresenceType type)
2754 { 2940 {
2755 ScenePresence sp; 2941 ScenePresence sp;
2756 bool vialogin; 2942 bool vialogin;
2943 bool reallyNew = true;
2944
2945 // Update the number of users attempting to login
2946 StatsReporter.UpdateUsersLoggingIn(true);
2757 2947
2758 // Validation occurs in LLUDPServer 2948 // Validation occurs in LLUDPServer
2759 // 2949 //
2760 // XXX: A race condition exists here where two simultaneous calls to AddNewClient can interfere with 2950 // XXX: A race condition exists here where two simultaneous calls to AddNewAgent can interfere with
2761 // each other. In practice, this does not currently occur in the code. 2951 // each other. In practice, this does not currently occur in the code.
2762 AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); 2952 AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode);
2763 2953
@@ -2765,9 +2955,9 @@ namespace OpenSim.Region.Framework.Scenes
2765 // and a simultaneous one that removes it (as can happen if the client is closed at a particular point 2955 // and a simultaneous one that removes it (as can happen if the client is closed at a particular point
2766 // whilst connecting). 2956 // whilst connecting).
2767 // 2957 //
2768 // It would be easier to lock across all NewUserConnection(), AddNewClient() and 2958 // It would be easier to lock across all NewUserConnection(), AddNewAgent() and
2769 // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service 2959 // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service
2770 // response in some module listening to AddNewClient()) from holding up unrelated agent calls. 2960 // response in some module listening to AddNewAgent()) from holding up unrelated agent calls.
2771 // 2961 //
2772 // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all 2962 // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all
2773 // AddNewClient() operations (though not other ops). 2963 // AddNewClient() operations (though not other ops).
@@ -2777,68 +2967,90 @@ namespace OpenSim.Region.Framework.Scenes
2777 vialogin 2967 vialogin
2778 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 2968 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0
2779 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 2969 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2780 2970
2781 // CheckHeartbeat(); 2971 // CheckHeartbeat();
2782 2972
2783 sp = GetScenePresence(client.AgentId); 2973 sp = GetScenePresence(client.AgentId);
2784 2974
2785 // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this 2975 // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this
2786 // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause 2976 // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause
2787 // other problems, and possible the code calling AddNewClient() should ensure that no client is already 2977 // other problems, and possibly the code calling AddNewAgent() should ensure that no client is already
2788 // connected. 2978 // connected.
2789 if (sp == null) 2979 if (sp == null)
2790 { 2980 {
2791 m_log.DebugFormat( 2981 m_log.DebugFormat(
2792 "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", 2982 "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}",
2793 client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); 2983 client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos);
2794 2984
2985 sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type);
2986
2987 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the
2988 // client is for a root or child agent.
2989 // We must also set this before adding the client to the client manager so that an exception later on
2990 // does not leave a client manager entry without the scene agent set, which will cause other code
2991 // to fail since any entry in the client manager should have a ScenePresence
2992 //
2993 // XXX: This may be better set for a new client before that client is added to the client manager.
2994 // But need to know what happens in the case where a ScenePresence is already present (and if this
2995 // actually occurs).
2996 client.SceneAgent = sp;
2997
2795 m_clientManager.Add(client); 2998 m_clientManager.Add(client);
2796 SubscribeToClientEvents(client); 2999 SubscribeToClientEvents(client);
2797
2798 sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type);
2799 m_eventManager.TriggerOnNewPresence(sp); 3000 m_eventManager.TriggerOnNewPresence(sp);
2800 3001
2801 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; 3002 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags;
2802
2803 // The first agent upon login is a root agent by design.
2804 // For this agent we will have to rez the attachments.
2805 // All other AddNewClient calls find aCircuit.child to be true.
2806 if (aCircuit.child == false)
2807 {
2808 // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to
2809 // start the scripts again (since this is done in RezAttachments()).
2810 // XXX: This is convoluted.
2811 sp.IsChildAgent = false;
2812
2813 if (AttachmentsModule != null)
2814 Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); });
2815 }
2816 } 3003 }
2817 else 3004 else
2818 { 3005 {
3006 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the
3007 // client is for a root or child agent.
3008 // XXX: This may be better set for a new client before that client is added to the client manager.
3009 // But need to know what happens in the case where a ScenePresence is already present (and if this
3010 // actually occurs).
3011 client.SceneAgent = sp;
3012
2819 m_log.WarnFormat( 3013 m_log.WarnFormat(
2820 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", 3014 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence",
2821 sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); 3015 sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName);
3016
3017 reallyNew = false;
2822 } 3018 }
2823
2824 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the
2825 // client is for a root or child agent.
2826 client.SceneAgent = sp;
2827 3019
2828 // Cache the user's name 3020 // This is currently also being done earlier in NewUserConnection for real users to see if this
3021 // resolves problems where HG agents are occasionally seen by others as "Unknown user" in chat and other
3022 // places. However, we still need to do it here for NPCs.
2829 CacheUserName(sp, aCircuit); 3023 CacheUserName(sp, aCircuit);
2830 3024
2831 EventManager.TriggerOnNewClient(client); 3025 if (reallyNew)
3026 EventManager.TriggerOnNewClient(client);
3027
2832 if (vialogin) 3028 if (vialogin)
2833 EventManager.TriggerOnClientLogin(client); 3029 EventManager.TriggerOnClientLogin(client);
2834 } 3030 }
2835 3031
3032 // User has logged into the scene so update the list of users logging
3033 // in
3034 StatsReporter.UpdateUsersLoggingIn(false);
3035
2836 m_LastLogin = Util.EnvironmentTickCount(); 3036 m_LastLogin = Util.EnvironmentTickCount();
2837 3037
2838 return sp; 3038 return sp;
2839 } 3039 }
2840 3040
2841 /// <summary> 3041 /// <summary>
3042 /// Returns the Home URI of the agent, or null if unknown.
3043 /// </summary>
3044 public string GetAgentHomeURI(UUID agentID)
3045 {
3046 AgentCircuitData circuit = AuthenticateHandler.GetAgentCircuitData(agentID);
3047 if (circuit != null && circuit.ServiceURLs != null && circuit.ServiceURLs.ContainsKey("HomeURI"))
3048 return circuit.ServiceURLs["HomeURI"].ToString();
3049 else
3050 return null;
3051 }
3052
3053 /// <summary>
2842 /// Cache the user name for later use. 3054 /// Cache the user name for later use.
2843 /// </summary> 3055 /// </summary>
2844 /// <param name="sp"></param> 3056 /// <param name="sp"></param>
@@ -2849,7 +3061,7 @@ namespace OpenSim.Region.Framework.Scenes
2849 { 3061 {
2850 string first = aCircuit.firstname, last = aCircuit.lastname; 3062 string first = aCircuit.firstname, last = aCircuit.lastname;
2851 3063
2852 if (sp.PresenceType == PresenceType.Npc) 3064 if (sp != null && sp.PresenceType == PresenceType.Npc)
2853 { 3065 {
2854 UserManagementModule.AddUser(aCircuit.AgentID, first, last); 3066 UserManagementModule.AddUser(aCircuit.AgentID, first, last);
2855 } 3067 }
@@ -2878,7 +3090,7 @@ namespace OpenSim.Region.Framework.Scenes
2878 private bool VerifyClient(AgentCircuitData aCircuit, System.Net.IPEndPoint ep, out bool vialogin) 3090 private bool VerifyClient(AgentCircuitData aCircuit, System.Net.IPEndPoint ep, out bool vialogin)
2879 { 3091 {
2880 vialogin = false; 3092 vialogin = false;
2881 3093
2882 // Do the verification here 3094 // Do the verification here
2883 if ((aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0) 3095 if ((aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0)
2884 { 3096 {
@@ -2929,7 +3141,7 @@ namespace OpenSim.Region.Framework.Scenes
2929 { 3141 {
2930 PresenceService.LogoutAgent(sp.ControllingClient.SessionId); 3142 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2931 3143
2932 sp.ControllingClient.Close(); 3144 CloseAgent(sp.UUID, false);
2933 } 3145 }
2934 else 3146 else
2935 { 3147 {
@@ -2973,7 +3185,7 @@ namespace OpenSim.Region.Framework.Scenes
2973 { 3185 {
2974 client.OnRegionHandShakeReply += SendLayerData; 3186 client.OnRegionHandShakeReply += SendLayerData;
2975 } 3187 }
2976 3188
2977 public virtual void SubscribeToClientPrimEvents(IClientAPI client) 3189 public virtual void SubscribeToClientPrimEvents(IClientAPI client)
2978 { 3190 {
2979 client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition; 3191 client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition;
@@ -2983,7 +3195,7 @@ namespace OpenSim.Region.Framework.Scenes
2983 client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation; 3195 client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation;
2984 client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation; 3196 client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation;
2985 client.OnUpdatePrimSingleRotationPosition += m_sceneGraph.UpdatePrimSingleRotationPosition; 3197 client.OnUpdatePrimSingleRotationPosition += m_sceneGraph.UpdatePrimSingleRotationPosition;
2986 3198
2987 client.OnUpdatePrimScale += m_sceneGraph.UpdatePrimScale; 3199 client.OnUpdatePrimScale += m_sceneGraph.UpdatePrimScale;
2988 client.OnUpdatePrimGroupScale += m_sceneGraph.UpdatePrimGroupScale; 3200 client.OnUpdatePrimGroupScale += m_sceneGraph.UpdatePrimGroupScale;
2989 client.OnUpdateExtraParams += m_sceneGraph.UpdateExtraParam; 3201 client.OnUpdateExtraParams += m_sceneGraph.UpdateExtraParam;
@@ -2996,7 +3208,7 @@ namespace OpenSim.Region.Framework.Scenes
2996 client.OnSpinStart += m_sceneGraph.SpinStart; 3208 client.OnSpinStart += m_sceneGraph.SpinStart;
2997 client.OnSpinUpdate += m_sceneGraph.SpinObject; 3209 client.OnSpinUpdate += m_sceneGraph.SpinObject;
2998 client.OnDeRezObject += DeRezObjects; 3210 client.OnDeRezObject += DeRezObjects;
2999 3211
3000 client.OnObjectName += m_sceneGraph.PrimName; 3212 client.OnObjectName += m_sceneGraph.PrimName;
3001 client.OnObjectClickAction += m_sceneGraph.PrimClickAction; 3213 client.OnObjectClickAction += m_sceneGraph.PrimClickAction;
3002 client.OnObjectMaterial += m_sceneGraph.PrimMaterial; 3214 client.OnObjectMaterial += m_sceneGraph.PrimMaterial;
@@ -3008,7 +3220,7 @@ namespace OpenSim.Region.Framework.Scenes
3008 client.OnRequestObjectPropertiesFamily += m_sceneGraph.RequestObjectPropertiesFamily; 3220 client.OnRequestObjectPropertiesFamily += m_sceneGraph.RequestObjectPropertiesFamily;
3009 client.OnObjectPermissions += HandleObjectPermissionsUpdate; 3221 client.OnObjectPermissions += HandleObjectPermissionsUpdate;
3010 client.OnGrabObject += ProcessObjectGrab; 3222 client.OnGrabObject += ProcessObjectGrab;
3011 client.OnGrabUpdate += ProcessObjectGrabUpdate; 3223 client.OnGrabUpdate += ProcessObjectGrabUpdate;
3012 client.OnDeGrabObject += ProcessObjectDeGrab; 3224 client.OnDeGrabObject += ProcessObjectDeGrab;
3013 client.OnUndo += m_sceneGraph.HandleUndo; 3225 client.OnUndo += m_sceneGraph.HandleUndo;
3014 client.OnRedo += m_sceneGraph.HandleRedo; 3226 client.OnRedo += m_sceneGraph.HandleRedo;
@@ -3068,10 +3280,8 @@ namespace OpenSim.Region.Framework.Scenes
3068 { 3280 {
3069 //client.OnNameFromUUIDRequest += HandleUUIDNameRequest; 3281 //client.OnNameFromUUIDRequest += HandleUUIDNameRequest;
3070 client.OnMoneyTransferRequest += ProcessMoneyTransferRequest; 3282 client.OnMoneyTransferRequest += ProcessMoneyTransferRequest;
3071 client.OnSetStartLocationRequest += SetHomeRezPoint;
3072 client.OnRegionHandleRequest += RegionHandleRequest;
3073 } 3283 }
3074 3284
3075 public virtual void SubscribeToClientNetworkEvents(IClientAPI client) 3285 public virtual void SubscribeToClientNetworkEvents(IClientAPI client)
3076 { 3286 {
3077 client.OnNetworkStatsUpdate += StatsReporter.AddPacketsStats; 3287 client.OnNetworkStatsUpdate += StatsReporter.AddPacketsStats;
@@ -3193,8 +3403,6 @@ namespace OpenSim.Region.Framework.Scenes
3193 { 3403 {
3194 //client.OnNameFromUUIDRequest -= HandleUUIDNameRequest; 3404 //client.OnNameFromUUIDRequest -= HandleUUIDNameRequest;
3195 client.OnMoneyTransferRequest -= ProcessMoneyTransferRequest; 3405 client.OnMoneyTransferRequest -= ProcessMoneyTransferRequest;
3196 client.OnSetStartLocationRequest -= SetHomeRezPoint;
3197 client.OnRegionHandleRequest -= RegionHandleRequest;
3198 } 3406 }
3199 3407
3200 public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client) 3408 public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client)
@@ -3208,17 +3416,18 @@ namespace OpenSim.Region.Framework.Scenes
3208 /// </summary> 3416 /// </summary>
3209 /// <param name="agentId">The avatar's Unique ID</param> 3417 /// <param name="agentId">The avatar's Unique ID</param>
3210 /// <param name="client">The IClientAPI for the client</param> 3418 /// <param name="client">The IClientAPI for the client</param>
3211 public virtual void TeleportClientHome(UUID agentId, IClientAPI client) 3419 public virtual bool TeleportClientHome(UUID agentId, IClientAPI client)
3212 { 3420 {
3213 if (EntityTransferModule != null) 3421 if (EntityTransferModule != null)
3214 { 3422 {
3215 EntityTransferModule.TeleportHome(agentId, client); 3423 return EntityTransferModule.TeleportHome(agentId, client);
3216 } 3424 }
3217 else 3425 else
3218 { 3426 {
3219 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); 3427 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active");
3220 client.SendTeleportFailed("Unable to perform teleports on this simulator."); 3428 client.SendTeleportFailed("Unable to perform teleports on this simulator.");
3221 } 3429 }
3430 return false;
3222 } 3431 }
3223 3432
3224 /// <summary> 3433 /// <summary>
@@ -3264,8 +3473,8 @@ namespace OpenSim.Region.Framework.Scenes
3264 if (target != null && target2 != null) 3473 if (target != null && target2 != null)
3265 { 3474 {
3266 Vector3 direction = Vector3.Normalize(RayEnd - RayStart); 3475 Vector3 direction = Vector3.Normalize(RayEnd - RayStart);
3267 Vector3 AXOrigin = new Vector3(RayStart.X, RayStart.Y, RayStart.Z); 3476 Vector3 AXOrigin = RayStart;
3268 Vector3 AXdirection = new Vector3(direction.X, direction.Y, direction.Z); 3477 Vector3 AXdirection = direction;
3269 3478
3270 pos = target2.AbsolutePosition; 3479 pos = target2.AbsolutePosition;
3271 //m_log.Info("[OBJECT_REZ]: TargetPos: " + pos.ToString() + ", RayStart: " + RayStart.ToString() + ", RayEnd: " + RayEnd.ToString() + ", Volume: " + Util.GetDistanceTo(RayStart,RayEnd).ToString() + ", mag1: " + Util.GetMagnitude(RayStart).ToString() + ", mag2: " + Util.GetMagnitude(RayEnd).ToString()); 3480 //m_log.Info("[OBJECT_REZ]: TargetPos: " + pos.ToString() + ", RayStart: " + RayStart.ToString() + ", RayEnd: " + RayEnd.ToString() + ", Volume: " + Util.GetDistanceTo(RayStart,RayEnd).ToString() + ", mag1: " + Util.GetMagnitude(RayStart).ToString() + ", mag2: " + Util.GetMagnitude(RayEnd).ToString());
@@ -3286,13 +3495,13 @@ namespace OpenSim.Region.Framework.Scenes
3286 if (ei.HitTF) 3495 if (ei.HitTF)
3287 { 3496 {
3288 Vector3 scale = target.Scale; 3497 Vector3 scale = target.Scale;
3289 Vector3 scaleComponent = new Vector3(ei.AAfaceNormal.X, ei.AAfaceNormal.Y, ei.AAfaceNormal.Z); 3498 Vector3 scaleComponent = ei.AAfaceNormal;
3290 if (scaleComponent.X != 0) ScaleOffset = scale.X; 3499 if (scaleComponent.X != 0) ScaleOffset = scale.X;
3291 if (scaleComponent.Y != 0) ScaleOffset = scale.Y; 3500 if (scaleComponent.Y != 0) ScaleOffset = scale.Y;
3292 if (scaleComponent.Z != 0) ScaleOffset = scale.Z; 3501 if (scaleComponent.Z != 0) ScaleOffset = scale.Z;
3293 ScaleOffset = Math.Abs(ScaleOffset); 3502 ScaleOffset = Math.Abs(ScaleOffset);
3294 Vector3 intersectionpoint = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 3503 Vector3 intersectionpoint = ei.ipoint;
3295 Vector3 normal = new Vector3(ei.normal.X, ei.normal.Y, ei.normal.Z); 3504 Vector3 normal = ei.normal;
3296 Vector3 offset = normal * (ScaleOffset / 2f); 3505 Vector3 offset = normal * (ScaleOffset / 2f);
3297 pos = intersectionpoint + offset; 3506 pos = intersectionpoint + offset;
3298 3507
@@ -3312,6 +3521,7 @@ namespace OpenSim.Region.Framework.Scenes
3312 { 3521 {
3313 copy = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, Quaternion.Identity); 3522 copy = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, Quaternion.Identity);
3314 } 3523 }
3524
3315 if (copy != null) 3525 if (copy != null)
3316 EventManager.TriggerObjectAddedToScene(copy); 3526 EventManager.TriggerObjectAddedToScene(copy);
3317 } 3527 }
@@ -3319,24 +3529,7 @@ namespace OpenSim.Region.Framework.Scenes
3319 } 3529 }
3320 3530
3321 /// <summary> 3531 /// <summary>
3322 /// Sets the Home Point. The LoginService uses this to know where to put a user when they log-in 3532 /// Get the avatar appearance for the given client.
3323 /// </summary>
3324 /// <param name="remoteClient"></param>
3325 /// <param name="regionHandle"></param>
3326 /// <param name="position"></param>
3327 /// <param name="lookAt"></param>
3328 /// <param name="flags"></param>
3329 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
3330 {
3331 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
3332 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
3333 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
3334 else
3335 m_dialogModule.SendAlertToUser(remoteClient, "Set Home request Failed.");
3336 }
3337
3338 /// <summary>
3339 /// Get the avatar apperance for the given client.
3340 /// </summary> 3533 /// </summary>
3341 /// <param name="client"></param> 3534 /// <param name="client"></param>
3342 /// <param name="appearance"></param> 3535 /// <param name="appearance"></param>
@@ -3359,93 +3552,93 @@ namespace OpenSim.Region.Framework.Scenes
3359 } 3552 }
3360 } 3553 }
3361 3554
3362 public override void RemoveClient(UUID agentID, bool closeChildAgents) 3555 /// <summary>
3556 /// Remove the given client from the scene.
3557 /// </summary>
3558 /// <remarks>
3559 /// Only clientstack code should call this directly. All other code should call IncomingCloseAgent() instead
3560 /// to properly operate the state machine and avoid race conditions with other close requests (such as directly
3561 /// from viewers).
3562 /// </remarks>
3563 /// <param name='agentID'>ID of agent to close</param>
3564 /// <param name='closeChildAgents'>
3565 /// Close the neighbour child agents associated with this client.
3566 /// </param>
3567 public void RemoveClient(UUID agentID, bool closeChildAgents)
3363 { 3568 {
3364// CheckHeartbeat(); 3569 AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID);
3365 bool isChildAgent = false;
3366 AgentCircuitData acd;
3367 3570
3368 lock (m_removeClientLock) 3571 // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which
3572 // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not
3573 // However, will keep for now just in case.
3574 if (acd == null)
3369 { 3575 {
3370 acd = m_authenticateHandler.GetAgentCircuitData(agentID); 3576 m_log.ErrorFormat(
3577 "[SCENE]: No agent circuit found for {0} in {1}, aborting Scene.RemoveClient", agentID, Name);
3371 3578
3372 if (acd == null) 3579 return;
3373 {
3374 m_log.ErrorFormat("[SCENE]: No agent circuit found for {0}, aborting Scene.RemoveClient", agentID);
3375 return;
3376 }
3377 else
3378 {
3379 // We remove the acd up here to avoid later race conditions if two RemoveClient() calls occurred
3380 // simultaneously.
3381 // We also need to remove by agent ID since NPCs will have no circuit code.
3382 m_authenticateHandler.RemoveCircuit(agentID);
3383 }
3384 } 3580 }
3385 3581
3582 // TODO: Can we now remove this lock?
3386 lock (acd) 3583 lock (acd)
3387 { 3584 {
3585 bool isChildAgent = false;
3586
3388 ScenePresence avatar = GetScenePresence(agentID); 3587 ScenePresence avatar = GetScenePresence(agentID);
3389 3588
3589 // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which
3590 // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not
3591 // However, will keep for now just in case.
3390 if (avatar == null) 3592 if (avatar == null)
3391 { 3593 {
3392 m_log.WarnFormat( 3594 m_log.ErrorFormat(
3393 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); 3595 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID);
3394 3596 m_authenticateHandler.RemoveCircuit(agentID);
3597
3395 return; 3598 return;
3396 } 3599 }
3397 3600
3398 try 3601 try
3399 { 3602 {
3400 isChildAgent = avatar.IsChildAgent; 3603 isChildAgent = avatar.IsChildAgent;
3401 3604
3402 m_log.DebugFormat( 3605 m_log.DebugFormat(
3403 "[SCENE]: Removing {0} agent {1} {2} from {3}", 3606 "[SCENE]: Removing {0} agent {1} {2} from {3}",
3404 (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName); 3607 isChildAgent ? "child" : "root", avatar.Name, agentID, Name);
3405 3608
3406 // Don't do this to root agents, it's not nice for the viewer 3609 // Don't do this to root agents, it's not nice for the viewer
3407 if (closeChildAgents && isChildAgent) 3610 if (closeChildAgents && isChildAgent)
3408 { 3611 {
3409 // Tell a single agent to disconnect from the region. 3612 // Tell a single agent to disconnect from the region.
3410 IEventQueue eq = RequestModuleInterface<IEventQueue>(); 3613 // Let's do this via UDP
3411 if (eq != null) 3614 avatar.ControllingClient.SendShutdownConnectionNotice();
3412 {
3413 eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID);
3414 }
3415 else
3416 {
3417 avatar.ControllingClient.SendShutdownConnectionNotice();
3418 }
3419 } 3615 }
3420 3616
3421 // Only applies to root agents. 3617 // Only applies to root agents.
3422 if (avatar.ParentID != 0) 3618 if (avatar.ParentID != 0)
3423 { 3619 {
3424 avatar.StandUp(); 3620 avatar.StandUp();
3425 } 3621 }
3426 3622
3427 m_sceneGraph.removeUserCount(!isChildAgent); 3623 m_sceneGraph.removeUserCount(!isChildAgent);
3428 3624
3429 // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop 3625 // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop
3430 // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI 3626 // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI
3431 if (closeChildAgents && CapsModule != null) 3627 if (closeChildAgents && CapsModule != null)
3432 CapsModule.RemoveCaps(agentID); 3628 CapsModule.RemoveCaps(agentID);
3433 3629
3434// // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever
3435// // this method is doing is HORRIBLE!!!
3436 // Commented pending deletion since this method no longer appears to do anything at all
3437// avatar.Scene.NeedSceneCacheClear(avatar.UUID);
3438
3439 if (closeChildAgents && !isChildAgent) 3630 if (closeChildAgents && !isChildAgent)
3440 { 3631 {
3441 List<ulong> regions = avatar.KnownRegionHandles; 3632 List<ulong> regions = avatar.KnownRegionHandles;
3442 regions.Remove(RegionInfo.RegionHandle); 3633 regions.Remove(RegionInfo.RegionHandle);
3443 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3634
3635 // This ends up being done asynchronously so that a logout isn't held up where there are many present but unresponsive neighbours.
3636 m_sceneGridService.SendCloseChildAgentConnections(agentID, acd.SessionID.ToString(), regions);
3444 } 3637 }
3445 3638
3446 m_eventManager.TriggerClientClosed(agentID, this); 3639 m_eventManager.TriggerClientClosed(agentID, this);
3447 m_eventManager.TriggerOnRemovePresence(agentID); 3640 m_eventManager.TriggerOnRemovePresence(agentID);
3448 3641
3449 if (!isChildAgent) 3642 if (!isChildAgent)
3450 { 3643 {
3451 if (AttachmentsModule != null) 3644 if (AttachmentsModule != null)
@@ -3457,11 +3650,11 @@ namespace OpenSim.Region.Framework.Scenes
3457 delegate(IClientAPI client) 3650 delegate(IClientAPI client)
3458 { 3651 {
3459 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway 3652 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway
3460 try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); } 3653 try { client.SendKillObject(new List<uint> { avatar.LocalId }); }
3461 catch (NullReferenceException) { } 3654 catch (NullReferenceException) { }
3462 }); 3655 });
3463 } 3656 }
3464 3657
3465 // It's possible for child agents to have transactions if changes are being made cross-border. 3658 // It's possible for child agents to have transactions if changes are being made cross-border.
3466 if (AgentTransactionsModule != null) 3659 if (AgentTransactionsModule != null)
3467 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); 3660 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID);
@@ -3478,9 +3671,10 @@ namespace OpenSim.Region.Framework.Scenes
3478 // Always clean these structures up so that any failure above doesn't cause them to remain in the 3671 // Always clean these structures up so that any failure above doesn't cause them to remain in the
3479 // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering 3672 // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering
3480 // the same cleanup exception continually. 3673 // the same cleanup exception continually.
3674 m_authenticateHandler.RemoveCircuit(agentID);
3481 m_sceneGraph.RemoveScenePresence(agentID); 3675 m_sceneGraph.RemoveScenePresence(agentID);
3482 m_clientManager.Remove(agentID); 3676 m_clientManager.Remove(agentID);
3483 3677
3484 avatar.Close(); 3678 avatar.Close();
3485 } 3679 }
3486 catch (Exception e) 3680 catch (Exception e)
@@ -3537,7 +3731,8 @@ namespace OpenSim.Region.Framework.Scenes
3537 } 3731 }
3538 deleteIDs.Add(localID); 3732 deleteIDs.Add(localID);
3539 } 3733 }
3540 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, deleteIDs); }); 3734
3735 ForEachClient(c => c.SendKillObject(deleteIDs));
3541 } 3736 }
3542 3737
3543 #endregion 3738 #endregion
@@ -3549,12 +3744,13 @@ namespace OpenSim.Region.Framework.Scenes
3549 /// </summary> 3744 /// </summary>
3550 /// <param name="agent">CircuitData of the agent who is connecting</param> 3745 /// <param name="agent">CircuitData of the agent who is connecting</param>
3551 /// <param name="teleportFlags"></param> 3746 /// <param name="teleportFlags"></param>
3747 /// <param name="source">Source region (may be null)</param>
3552 /// <param name="reason">Outputs the reason for the false response on this string</param> 3748 /// <param name="reason">Outputs the reason for the false response on this string</param>
3553 /// <returns>True if the region accepts this agent. False if it does not. False will 3749 /// <returns>True if the region accepts this agent. False if it does not. False will
3554 /// also return a reason.</returns> 3750 /// also return a reason.</returns>
3555 public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, out string reason) 3751 public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, GridRegion source, out string reason)
3556 { 3752 {
3557 return NewUserConnection(agent, teleportFlags, out reason, true); 3753 return NewUserConnection(agent, teleportFlags, source, out reason, true);
3558 } 3754 }
3559 3755
3560 /// <summary> 3756 /// <summary>
@@ -3573,13 +3769,14 @@ namespace OpenSim.Region.Framework.Scenes
3573 /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of 3769 /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of
3574 /// the LLUDP stack). 3770 /// the LLUDP stack).
3575 /// </remarks> 3771 /// </remarks>
3576 /// <param name="agent">CircuitData of the agent who is connecting</param> 3772 /// <param name="acd">CircuitData of the agent who is connecting</param>
3773 /// <param name="source">Source region (may be null)</param>
3577 /// <param name="reason">Outputs the reason for the false response on this string</param> 3774 /// <param name="reason">Outputs the reason for the false response on this string</param>
3578 /// <param name="requirePresenceLookup">True for normal presence. False for NPC 3775 /// <param name="requirePresenceLookup">True for normal presence. False for NPC
3579 /// or other applications where a full grid/Hypergrid presence may not be required.</param> 3776 /// or other applications where a full grid/Hypergrid presence may not be required.</param>
3580 /// <returns>True if the region accepts this agent. False if it does not. False will 3777 /// <returns>True if the region accepts this agent. False if it does not. False will
3581 /// also return a reason.</returns> 3778 /// also return a reason.</returns>
3582 public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, out string reason, bool requirePresenceLookup) 3779 public bool NewUserConnection(AgentCircuitData acd, uint teleportFlags, GridRegion source, out string reason, bool requirePresenceLookup)
3583 { 3780 {
3584 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 || 3781 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 ||
3585 (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0); 3782 (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0);
@@ -3596,18 +3793,20 @@ namespace OpenSim.Region.Framework.Scenes
3596 // TeleportFlags.ViaLandmark | TeleportFlags.ViaLocation | TeleportFlags.ViaLandmark | TeleportFlags.Default - Regular Teleport 3793 // TeleportFlags.ViaLandmark | TeleportFlags.ViaLocation | TeleportFlags.ViaLandmark | TeleportFlags.Default - Regular Teleport
3597 3794
3598 // Don't disable this log message - it's too helpful 3795 // Don't disable this log message - it's too helpful
3796 string curViewer = Util.GetViewerName(acd);
3599 m_log.DebugFormat( 3797 m_log.DebugFormat(
3600 "[SCENE]: Region {0} told of incoming {1} agent {2} {3} {4} (circuit code {5}, IP {6}, viewer {7}, teleportflags ({8}), position {9})", 3798 "[SCENE]: Region {0} told of incoming {1} agent {2} {3} {4} (circuit code {5}, IP {6}, viewer {7}, teleportflags ({8}), position {9}. {10}",
3601 RegionInfo.RegionName, 3799 RegionInfo.RegionName,
3602 (agent.child ? "child" : "root"), 3800 (acd.child ? "child" : "root"),
3603 agent.firstname, 3801 acd.firstname,
3604 agent.lastname, 3802 acd.lastname,
3605 agent.AgentID, 3803 acd.AgentID,
3606 agent.circuitcode, 3804 acd.circuitcode,
3607 agent.IPAddress, 3805 acd.IPAddress,
3608 agent.Viewer, 3806 curViewer,
3609 ((TPFlags)teleportFlags).ToString(), 3807 ((TPFlags)teleportFlags).ToString(),
3610 agent.startpos 3808 acd.startpos,
3809 (source == null) ? "" : string.Format("From region {0} ({1}){2}", source.RegionName, source.RegionID, (source.RawServerURI == null) ? "" : " @ " + source.ServerURI)
3611 ); 3810 );
3612 3811
3613 if (!LoginsEnabled) 3812 if (!LoginsEnabled)
@@ -3625,7 +3824,7 @@ namespace OpenSim.Region.Framework.Scenes
3625 { 3824 {
3626 foreach (string viewer in m_AllowedViewers) 3825 foreach (string viewer in m_AllowedViewers)
3627 { 3826 {
3628 if (viewer == agent.Viewer.Substring(0, viewer.Length).Trim().ToLower()) 3827 if (viewer == curViewer.Substring(0, Math.Min(viewer.Length, curViewer.Length)).Trim().ToLower())
3629 { 3828 {
3630 ViewerDenied = false; 3829 ViewerDenied = false;
3631 break; 3830 break;
@@ -3642,7 +3841,7 @@ namespace OpenSim.Region.Framework.Scenes
3642 { 3841 {
3643 foreach (string viewer in m_BannedViewers) 3842 foreach (string viewer in m_BannedViewers)
3644 { 3843 {
3645 if (viewer == agent.Viewer.Substring(0, viewer.Length).Trim().ToLower()) 3844 if (viewer == curViewer.Substring(0, Math.Min(viewer.Length, curViewer.Length)).Trim().ToLower())
3646 { 3845 {
3647 ViewerDenied = true; 3846 ViewerDenied = true;
3648 break; 3847 break;
@@ -3654,81 +3853,178 @@ namespace OpenSim.Region.Framework.Scenes
3654 { 3853 {
3655 m_log.DebugFormat( 3854 m_log.DebugFormat(
3656 "[SCENE]: Access denied for {0} {1} using {2}", 3855 "[SCENE]: Access denied for {0} {1} using {2}",
3657 agent.firstname, agent.lastname, agent.Viewer); 3856 acd.firstname, acd.lastname, curViewer);
3658 reason = "Access denied, your viewer is banned by the region owner"; 3857 reason = "Access denied, your viewer is banned by the region owner";
3659 return false; 3858 return false;
3660 } 3859 }
3661 3860
3662 ILandObject land; 3861 ILandObject land;
3862 ScenePresence sp;
3663 3863
3664 lock (agent) 3864 lock (m_removeClientLock)
3665 { 3865 {
3666 ScenePresence sp = GetScenePresence(agent.AgentID); 3866 sp = GetScenePresence(acd.AgentID);
3667 3867
3668 if (sp != null && !sp.IsChildAgent) 3868 // We need to ensure that we are not already removing the scene presence before we ask it not to be
3869 // closed.
3870 if (sp != null && sp.IsChildAgent
3871 && (sp.LifecycleState == ScenePresenceState.Running
3872 || sp.LifecycleState == ScenePresenceState.PreRemove))
3873 {
3874 m_log.DebugFormat(
3875 "[SCENE]: Reusing existing child scene presence for {0}, state {1} in {2}",
3876 sp.Name, sp.LifecycleState, Name);
3877
3878 // In the case where, for example, an A B C D region layout, an avatar may
3879 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. When C
3880 // renews the lease on the child agent at B, we must make sure that the close from A does not succeed.
3881 //
3882 // XXX: In the end, this should not be necessary if child agents are closed without delay on
3883 // teleport, since realistically, the close request should always be processed before any other
3884 // region tried to re-establish a child agent. This is much simpler since the logic below is
3885 // vulnerable to an issue when a viewer quits a region without sending a proper logout but then
3886 // re-establishes the connection on a relogin. This could wrongly set the DoNotCloseAfterTeleport
3887 // flag when no teleport had taken place (and hence no close was going to come).
3888// if (!acd.ChildrenCapSeeds.ContainsKey(RegionInfo.RegionHandle))
3889// {
3890// m_log.DebugFormat(
3891// "[SCENE]: Setting DoNotCloseAfterTeleport for child scene presence {0} in {1} because source will attempt close.",
3892// sp.Name, Name);
3893//
3894// sp.DoNotCloseAfterTeleport = true;
3895// }
3896// else if (EntityTransferModule.IsInTransit(sp.UUID))
3897
3898 sp.LifecycleState = ScenePresenceState.Running;
3899
3900 if (EntityTransferModule.IsInTransit(sp.UUID))
3901 {
3902 sp.DoNotCloseAfterTeleport = true;
3903
3904 m_log.DebugFormat(
3905 "[SCENE]: Set DoNotCloseAfterTeleport for child scene presence {0} in {1} because this region will attempt end-of-teleport close from a previous close.",
3906 sp.Name, Name);
3907 }
3908 }
3909 }
3910
3911 // Need to poll here in case we are currently deleting an sp. Letting threads run over each other will
3912 // allow unpredictable things to happen.
3913 if (sp != null)
3914 {
3915 const int polls = 10;
3916 const int pollInterval = 1000;
3917 int pollsLeft = polls;
3918
3919 while (sp.LifecycleState == ScenePresenceState.Removing && pollsLeft-- > 0)
3920 Thread.Sleep(pollInterval);
3921
3922 if (sp.LifecycleState == ScenePresenceState.Removing)
3669 { 3923 {
3670 // We have a zombie from a crashed session.
3671 // Or the same user is trying to be root twice here, won't work.
3672 // Kill it.
3673 m_log.WarnFormat( 3924 m_log.WarnFormat(
3674 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", 3925 "[SCENE]: Agent {0} in {1} was still being removed after {2}s. Aborting NewUserConnection.",
3675 sp.Name, sp.UUID, RegionInfo.RegionName); 3926 sp.Name, Name, polls * pollInterval / 1000);
3676 3927
3677 sp.ControllingClient.Close(true); 3928 return false;
3678 sp = null; 3929 }
3679 } 3930 else if (polls != pollsLeft)
3680 3931 {
3681 land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y); 3932 m_log.DebugFormat(
3682 3933 "[SCENE]: NewUserConnection for agent {0} in {1} had to wait {2}s for in-progress removal to complete on an old presence.",
3683 //On login test land permisions 3934 sp.Name, Name, polls * pollInterval / 1000);
3935 }
3936 }
3937
3938 // TODO: can we remove this lock?
3939 lock (acd)
3940 {
3941 if (sp != null && !sp.IsChildAgent)
3942 {
3943 // We have a root agent. Is it in transit?
3944 if (!EntityTransferModule.IsInTransit(sp.UUID))
3945 {
3946 // We have a zombie from a crashed session.
3947 // Or the same user is trying to be root twice here, won't work.
3948 // Kill it.
3949 m_log.WarnFormat(
3950 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.",
3951 sp.Name, sp.UUID, RegionInfo.RegionName);
3952
3953 if (sp.ControllingClient != null)
3954 CloseAgent(sp.UUID, true);
3955
3956 sp = null;
3957 }
3958 //else
3959 // m_log.WarnFormat("[SCENE]: Existing root scene presence for {0} {1} in {2}, but agent is in trasit", sp.Name, sp.UUID, RegionInfo.RegionName);
3960 }
3961
3962 // Optimistic: add or update the circuit data with the new agent circuit data and teleport flags.
3963 // We need the circuit data here for some of the subsequent checks. (groups, for example)
3964 // If the checks fail, we remove the circuit.
3965 acd.teleportFlags = teleportFlags;
3966 m_authenticateHandler.AddNewCircuit(acd.circuitcode, acd);
3967
3968 land = LandChannel.GetLandObject(acd.startpos.X, acd.startpos.Y);
3969
3970 // On login test land permisions
3684 if (vialogin) 3971 if (vialogin)
3685 { 3972 {
3686 if (land != null && !TestLandRestrictions(agent, land, out reason)) 3973 if (land != null && !TestLandRestrictions(acd.AgentID, out reason, ref acd.startpos.X, ref acd.startpos.Y))
3687 { 3974 {
3975 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3688 return false; 3976 return false;
3689 } 3977 }
3690 } 3978 }
3691 3979
3692 if (sp == null) // We don't have an [child] agent here already 3980 if (sp == null) // We don't have an [child] agent here already
3693 { 3981 {
3694 if (requirePresenceLookup) 3982 if (requirePresenceLookup)
3695 { 3983 {
3696 try 3984 try
3697 { 3985 {
3698 if (!VerifyUserPresence(agent, out reason)) 3986 if (!VerifyUserPresence(acd, out reason))
3987 {
3988 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3699 return false; 3989 return false;
3990 }
3700 } 3991 }
3701 catch (Exception e) 3992 catch (Exception e)
3702 { 3993 {
3703 m_log.ErrorFormat( 3994 m_log.ErrorFormat(
3704 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); 3995 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace);
3705 3996
3997 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3706 return false; 3998 return false;
3707 } 3999 }
3708 } 4000 }
3709 4001
3710 try 4002 try
3711 { 4003 {
3712 if (!AuthorizeUser(agent, out reason)) 4004 if (!AuthorizeUser(acd, (vialogin ? false : SeeIntoRegion), out reason))
4005 {
4006 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3713 return false; 4007 return false;
4008 }
3714 } 4009 }
3715 catch (Exception e) 4010 catch (Exception e)
3716 { 4011 {
3717 m_log.ErrorFormat( 4012 m_log.ErrorFormat(
3718 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); 4013 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace);
3719 4014
4015 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3720 return false; 4016 return false;
3721 } 4017 }
3722 4018
3723 m_log.InfoFormat( 4019 m_log.InfoFormat(
3724 "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", 4020 "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})",
3725 RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, 4021 Name, (acd.child ? "child" : "root"), acd.firstname, acd.lastname,
3726 agent.AgentID, agent.circuitcode); 4022 acd.AgentID, acd.circuitcode);
3727 4023
3728 if (CapsModule != null) 4024 if (CapsModule != null)
3729 { 4025 {
3730 CapsModule.SetAgentCapsSeeds(agent); 4026 CapsModule.SetAgentCapsSeeds(acd);
3731 CapsModule.CreateCaps(agent.AgentID); 4027 CapsModule.CreateCaps(acd.AgentID);
3732 } 4028 }
3733 } 4029 }
3734 else 4030 else
@@ -3736,83 +4032,42 @@ namespace OpenSim.Region.Framework.Scenes
3736 // Let the SP know how we got here. This has a lot of interesting 4032 // Let the SP know how we got here. This has a lot of interesting
3737 // uses down the line. 4033 // uses down the line.
3738 sp.TeleportFlags = (TPFlags)teleportFlags; 4034 sp.TeleportFlags = (TPFlags)teleportFlags;
3739 4035
3740 if (sp.IsChildAgent) 4036 if (sp.IsChildAgent)
3741 { 4037 {
3742 m_log.DebugFormat( 4038 m_log.DebugFormat(
3743 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", 4039 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
3744 agent.AgentID, RegionInfo.RegionName); 4040 acd.AgentID, RegionInfo.RegionName);
3745 4041
3746 sp.AdjustKnownSeeds(); 4042 sp.AdjustKnownSeeds();
3747 4043
3748 if (CapsModule != null) 4044 if (CapsModule != null)
3749 CapsModule.SetAgentCapsSeeds(agent); 4045 {
4046 CapsModule.SetAgentCapsSeeds(acd);
4047 CapsModule.CreateCaps(acd.AgentID);
4048 }
3750 } 4049 }
3751 } 4050 }
3752 }
3753 4051
3754 // In all cases, add or update the circuit data with the new agent circuit data and teleport flags 4052 // Try caching an incoming user name much earlier on to see if this helps with an issue
3755 agent.teleportFlags = teleportFlags; 4053 // where HG users are occasionally seen by others as "Unknown User" because their UUIDName
3756 m_authenticateHandler.AddNewCircuit(agent.circuitcode, agent); 4054 // request for the HG avatar appears to trigger before the user name is cached.
4055 CacheUserName(null, acd);
4056 }
3757 4057
3758 if (vialogin) 4058 if (vialogin)
3759 { 4059 {
3760// CleanDroppedAttachments(); 4060// CleanDroppedAttachments();
3761 4061
3762 if (TestBorderCross(agent.startpos, Cardinals.E)) 4062 // Make sure avatar position is in the region (why it wouldn't be is a mystery but do sanity checking)
3763 { 4063 if (acd.startpos.X < 0) acd.startpos.X = 1f;
3764 Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.E); 4064 if (acd.startpos.X >= RegionInfo.RegionSizeX) acd.startpos.X = RegionInfo.RegionSizeX - 1f;
3765 agent.startpos.X = crossedBorder.BorderLine.Z - 1; 4065 if (acd.startpos.Y < 0) acd.startpos.Y = 1f;
3766 } 4066 if (acd.startpos.Y >= RegionInfo.RegionSizeY) acd.startpos.Y = RegionInfo.RegionSizeY - 1f;
3767
3768 if (TestBorderCross(agent.startpos, Cardinals.N))
3769 {
3770 Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.N);
3771 agent.startpos.Y = crossedBorder.BorderLine.Z - 1;
3772 }
3773 4067
3774 //Mitigate http://opensimulator.org/mantis/view.php?id=3522 4068// m_log.DebugFormat(
3775 // Check if start position is outside of region 4069// "[SCENE]: Found telehub object {0} for new user connection {1} to {2}",
3776 // If it is, check the Z start position also.. if not, leave it alone. 4070// RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
3777 if (BordersLocked)
3778 {
3779 lock (EastBorders)
3780 {
3781 if (agent.startpos.X > EastBorders[0].BorderLine.Z)
3782 {
3783 m_log.Warn("FIX AGENT POSITION");
3784 agent.startpos.X = EastBorders[0].BorderLine.Z * 0.5f;
3785 if (agent.startpos.Z > 720)
3786 agent.startpos.Z = 720;
3787 }
3788 }
3789 lock (NorthBorders)
3790 {
3791 if (agent.startpos.Y > NorthBorders[0].BorderLine.Z)
3792 {
3793 m_log.Warn("FIX Agent POSITION");
3794 agent.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f;
3795 if (agent.startpos.Z > 720)
3796 agent.startpos.Z = 720;
3797 }
3798 }
3799 } else
3800 {
3801 if (agent.startpos.X > EastBorders[0].BorderLine.Z)
3802 {
3803 m_log.Warn("FIX AGENT POSITION");
3804 agent.startpos.X = EastBorders[0].BorderLine.Z * 0.5f;
3805 if (agent.startpos.Z > 720)
3806 agent.startpos.Z = 720;
3807 }
3808 if (agent.startpos.Y > NorthBorders[0].BorderLine.Z)
3809 {
3810 m_log.Warn("FIX Agent POSITION");
3811 agent.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f;
3812 if (agent.startpos.Z > 720)
3813 agent.startpos.Z = 720;
3814 }
3815 }
3816 4071
3817 // Honor Estate teleport routing via Telehubs excluding ViaHome and GodLike TeleportFlags 4072 // Honor Estate teleport routing via Telehubs excluding ViaHome and GodLike TeleportFlags
3818 if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && 4073 if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero &&
@@ -3820,26 +4075,49 @@ namespace OpenSim.Region.Framework.Scenes
3820 !viahome && !godlike) 4075 !viahome && !godlike)
3821 { 4076 {
3822 SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject); 4077 SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject);
3823 // Can have multiple SpawnPoints 4078
3824 List<SpawnPoint> spawnpoints = RegionInfo.RegionSettings.SpawnPoints(); 4079 if (telehub != null)
3825 if (spawnpoints.Count > 1)
3826 { 4080 {
3827 // We have multiple SpawnPoints, Route the agent to a random or sequential one 4081 // Can have multiple SpawnPoints
3828 if (SpawnPointRouting == "random") 4082 List<SpawnPoint> spawnpoints = RegionInfo.RegionSettings.SpawnPoints();
3829 agent.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation( 4083 if (spawnpoints.Count > 1)
3830 telehub.AbsolutePosition, 4084 {
3831 telehub.GroupRotation 4085 // We have multiple SpawnPoints, Route the agent to a random or sequential one
3832 ); 4086 if (SpawnPointRouting == "random")
4087 acd.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation(
4088 telehub.AbsolutePosition,
4089 telehub.GroupRotation
4090 );
4091 else
4092 acd.startpos = spawnpoints[SpawnPoint()].GetLocation(
4093 telehub.AbsolutePosition,
4094 telehub.GroupRotation
4095 );
4096 }
4097 else if (spawnpoints.Count == 1)
4098 {
4099 // We have a single SpawnPoint and will route the agent to it
4100 acd.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation);
4101 }
3833 else 4102 else
3834 agent.startpos = spawnpoints[SpawnPoint()].GetLocation( 4103 {
3835 telehub.AbsolutePosition, 4104 m_log.DebugFormat(
3836 telehub.GroupRotation 4105 "[SCENE]: No spawnpoints defined for telehub {0} for {1} in {2}. Continuing.",
3837 ); 4106 RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
4107 }
3838 } 4108 }
3839 else 4109 else
3840 { 4110 {
3841 // We have a single SpawnPoint and will route the agent to it 4111 m_log.DebugFormat(
3842 agent.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); 4112 "[SCENE]: No telehub {0} found to direct {1} in {2}. Continuing.",
4113 RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
4114 }
4115
4116 // Final permissions check; this time we don't allow changing the position
4117 if (!IsPositionAllowed(acd.AgentID, acd.startpos, ref reason))
4118 {
4119 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
4120 return false;
3843 } 4121 }
3844 4122
3845 return true; 4123 return true;
@@ -3850,7 +4128,14 @@ namespace OpenSim.Region.Framework.Scenes
3850 { 4128 {
3851 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 4129 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
3852 { 4130 {
3853 agent.startpos = land.LandData.UserLocation; 4131 acd.startpos = land.LandData.UserLocation;
4132
4133 // Final permissions check; this time we don't allow changing the position
4134 if (!IsPositionAllowed(acd.AgentID, acd.startpos, ref reason))
4135 {
4136 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
4137 return false;
4138 }
3854 } 4139 }
3855 } 4140 }
3856 } 4141 }
@@ -3858,20 +4143,52 @@ namespace OpenSim.Region.Framework.Scenes
3858 return true; 4143 return true;
3859 } 4144 }
3860 4145
3861 private bool TestLandRestrictions(AgentCircuitData agent, ILandObject land, out string reason) 4146 private bool IsPositionAllowed(UUID agentID, Vector3 pos, ref string reason)
3862 { 4147 {
3863 bool banned = land.IsBannedFromLand(agent.AgentID); 4148 ILandObject land = LandChannel.GetLandObject(pos);
3864 bool restricted = land.IsRestrictedFromLand(agent.AgentID); 4149 if (land == null)
4150 return true;
4151
4152 if (land.IsBannedFromLand(agentID) || land.IsRestrictedFromLand(agentID))
4153 {
4154 reason = "You are banned from the region.";
4155 return false;
4156 }
4157
4158 return true;
4159 }
4160
4161 public bool TestLandRestrictions(UUID agentID, out string reason, ref float posX, ref float posY)
4162 {
4163 if (posX < 0)
4164 posX = 0;
4165 else if (posX >= (float)RegionInfo.RegionSizeX)
4166 posX = (float)RegionInfo.RegionSizeX - 0.001f;
4167 if (posY < 0)
4168 posY = 0;
4169 else if (posY >= (float)RegionInfo.RegionSizeY)
4170 posY = (float)RegionInfo.RegionSizeY - 0.001f;
4171
4172 reason = String.Empty;
4173 if (Permissions.IsGod(agentID))
4174 return true;
4175
4176 ILandObject land = LandChannel.GetLandObject(posX, posY);
4177 if (land == null)
4178 return false;
4179
4180 bool banned = land.IsBannedFromLand(agentID);
4181 bool restricted = land.IsRestrictedFromLand(agentID);
3865 4182
3866 if (banned || restricted) 4183 if (banned || restricted)
3867 { 4184 {
3868 ILandObject nearestParcel = GetNearestAllowedParcel(agent.AgentID, agent.startpos.X, agent.startpos.Y); 4185 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY);
3869 if (nearestParcel != null) 4186 if (nearestParcel != null)
3870 { 4187 {
3871 //Move agent to nearest allowed 4188 //Move agent to nearest allowed
3872 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); 4189 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel);
3873 agent.startpos.X = newPosition.X; 4190 posX = newPosition.X;
3874 agent.startpos.Y = newPosition.Y; 4191 posY = newPosition.Y;
3875 } 4192 }
3876 else 4193 else
3877 { 4194 {
@@ -3882,7 +4199,7 @@ namespace OpenSim.Region.Framework.Scenes
3882 else 4199 else
3883 { 4200 {
3884 reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", 4201 reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.",
3885 RegionInfo.RegionName); 4202 RegionInfo.RegionName);
3886 } 4203 }
3887 return false; 4204 return false;
3888 } 4205 }
@@ -3927,86 +4244,93 @@ namespace OpenSim.Region.Framework.Scenes
3927 /// <param name="reason">outputs the reason to this string</param> 4244 /// <param name="reason">outputs the reason to this string</param>
3928 /// <returns>True if the region accepts this agent. False if it does not. False will 4245 /// <returns>True if the region accepts this agent. False if it does not. False will
3929 /// also return a reason.</returns> 4246 /// also return a reason.</returns>
3930 protected virtual bool AuthorizeUser(AgentCircuitData agent, out string reason) 4247 protected virtual bool AuthorizeUser(AgentCircuitData agent, bool bypassAccessControl, out string reason)
3931 { 4248 {
3932 reason = String.Empty; 4249 reason = String.Empty;
3933 4250
3934 if (!m_strictAccessControl) return true; 4251 if (!m_strictAccessControl) return true;
3935 if (Permissions.IsGod(agent.AgentID)) return true; 4252 if (Permissions.IsGod(agent.AgentID)) return true;
3936 4253
3937 if (AuthorizationService != null) 4254 if (AuthorizationService != null)
3938 { 4255 {
3939 if (!AuthorizationService.IsAuthorizedForRegion( 4256 if (!AuthorizationService.IsAuthorizedForRegion(
3940 agent.AgentID.ToString(), agent.firstname, agent.lastname, RegionInfo.RegionID.ToString(), out reason)) 4257 agent.AgentID.ToString(), agent.firstname, agent.lastname, RegionInfo.RegionID.ToString(), out reason))
3941 { 4258 {
3942 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because {4}", 4259 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because: {4}",
3943 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName, reason); 4260 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName, reason);
3944
3945 return false;
3946 }
3947 }
3948 4261
3949 if (RegionInfo.EstateSettings != null)
3950 {
3951 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID))
3952 {
3953 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
3954 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
3955 reason = String.Format("Denied access to region {0}: You have been banned from that region.",
3956 RegionInfo.RegionName);
3957 return false; 4262 return false;
3958 } 4263 }
3959 } 4264 }
3960 else
3961 {
3962 m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!");
3963 }
3964 4265
3965 List<UUID> agentGroups = new List<UUID>(); 4266 // We only test the things below when we want to cut off
3966 4267 // child agents from being present in the scene for which their root
3967 if (m_groupsModule != null) 4268 // agent isn't allowed. Otherwise, we allow child agents. The test for
4269 // the root is done elsewhere (QueryAccess)
4270 if (!bypassAccessControl)
3968 { 4271 {
3969 GroupMembershipData[] GroupMembership = m_groupsModule.GetMembershipData(agent.AgentID); 4272 if (RegionInfo.EstateSettings != null)
3970
3971 if (GroupMembership != null)
3972 { 4273 {
3973 for (int i = 0; i < GroupMembership.Length; i++) 4274 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID))
3974 agentGroups.Add(GroupMembership[i].GroupID); 4275 {
4276 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
4277 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
4278 reason = String.Format("Denied access to region {0}: You have been banned from that region.",
4279 RegionInfo.RegionName);
4280 return false;
4281 }
3975 } 4282 }
3976 else 4283 else
3977 { 4284 {
3978 m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!"); 4285 m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!");
3979 } 4286 }
3980 }
3981 4287
3982 bool groupAccess = false; 4288 List<UUID> agentGroups = new List<UUID>();
3983 UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups;
3984 4289
3985 if (estateGroups != null) 4290 if (m_groupsModule != null)
3986 {
3987 foreach (UUID group in estateGroups)
3988 { 4291 {
3989 if (agentGroups.Contains(group)) 4292 GroupMembershipData[] GroupMembership = m_groupsModule.GetMembershipData(agent.AgentID);
4293
4294 if (GroupMembership != null)
3990 { 4295 {
3991 groupAccess = true; 4296 for (int i = 0; i < GroupMembership.Length; i++)
3992 break; 4297 agentGroups.Add(GroupMembership[i].GroupID);
4298 }
4299 else
4300 {
4301 m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!");
3993 } 4302 }
3994 } 4303 }
3995 }
3996 else
3997 {
3998 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!");
3999 }
4000 4304
4001 if (!RegionInfo.EstateSettings.PublicAccess && 4305 bool groupAccess = false;
4002 !RegionInfo.EstateSettings.HasAccess(agent.AgentID) && 4306 UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups;
4003 !groupAccess) 4307
4004 { 4308 if (estateGroups != null)
4005 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate", 4309 {
4006 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 4310 foreach (UUID group in estateGroups)
4007 reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", 4311 {
4008 RegionInfo.RegionName); 4312 if (agentGroups.Contains(group))
4009 return false; 4313 {
4314 groupAccess = true;
4315 break;
4316 }
4317 }
4318 }
4319 else
4320 {
4321 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!");
4322 }
4323
4324 if (!RegionInfo.EstateSettings.PublicAccess &&
4325 !RegionInfo.EstateSettings.HasAccess(agent.AgentID) &&
4326 !groupAccess)
4327 {
4328 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate",
4329 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
4330 reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.",
4331 RegionInfo.RegionName);
4332 return false;
4333 }
4010 } 4334 }
4011 4335
4012 // TODO: estate/region settings are not properly hooked up 4336 // TODO: estate/region settings are not properly hooked up
@@ -4096,33 +4420,33 @@ namespace OpenSim.Region.Framework.Scenes
4096// } 4420// }
4097// } 4421// }
4098 4422
4099 /// <summary> 4423// /// <summary>
4100 /// Triggered when an agent crosses into this sim. Also happens on initial login. 4424// /// Triggered when an agent crosses into this sim. Also happens on initial login.
4101 /// </summary> 4425// /// </summary>
4102 /// <param name="agentID"></param> 4426// /// <param name="agentID"></param>
4103 /// <param name="position"></param> 4427// /// <param name="position"></param>
4104 /// <param name="isFlying"></param> 4428// /// <param name="isFlying"></param>
4105 public virtual void AgentCrossing(UUID agentID, Vector3 position, bool isFlying) 4429// public virtual void AgentCrossing(UUID agentID, Vector3 position, bool isFlying)
4106 { 4430// {
4107 ScenePresence presence = GetScenePresence(agentID); 4431// ScenePresence presence = GetScenePresence(agentID);
4108 if (presence != null) 4432// if (presence != null)
4109 { 4433// {
4110 try 4434// try
4111 { 4435// {
4112 presence.MakeRootAgent(position, isFlying); 4436// presence.MakeRootAgent(position, isFlying);
4113 } 4437// }
4114 catch (Exception e) 4438// catch (Exception e)
4115 { 4439// {
4116 m_log.ErrorFormat("[SCENE]: Unable to do agent crossing, exception {0}{1}", e.Message, e.StackTrace); 4440// m_log.ErrorFormat("[SCENE]: Unable to do agent crossing, exception {0}{1}", e.Message, e.StackTrace);
4117 } 4441// }
4118 } 4442// }
4119 else 4443// else
4120 { 4444// {
4121 m_log.ErrorFormat( 4445// m_log.ErrorFormat(
4122 "[SCENE]: Could not find presence for agent {0} crossing into scene {1}", 4446// "[SCENE]: Could not find presence for agent {0} crossing into scene {1}",
4123 agentID, RegionInfo.RegionName); 4447// agentID, RegionInfo.RegionName);
4124 } 4448// }
4125 } 4449// }
4126 4450
4127 /// <summary> 4451 /// <summary>
4128 /// We've got an update about an agent that sees into this region, 4452 /// We've got an update about an agent that sees into this region,
@@ -4131,18 +4455,16 @@ namespace OpenSim.Region.Framework.Scenes
4131 /// <param name="cAgentData">Agent that contains all of the relevant things about an agent. 4455 /// <param name="cAgentData">Agent that contains all of the relevant things about an agent.
4132 /// Appearance, animations, position, etc.</param> 4456 /// Appearance, animations, position, etc.</param>
4133 /// <returns>true if we handled it.</returns> 4457 /// <returns>true if we handled it.</returns>
4134 public virtual bool IncomingChildAgentDataUpdate(AgentData cAgentData) 4458 public virtual bool IncomingUpdateChildAgent(AgentData cAgentData)
4135 { 4459 {
4136 m_log.DebugFormat( 4460 m_log.DebugFormat(
4137 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName); 4461 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName);
4138 4462
4139 // XPTO: if this agent is not allowed here as root, always return false
4140
4141 // TODO: This check should probably be in QueryAccess(). 4463 // TODO: This check should probably be in QueryAccess().
4142 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 4464 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, RegionInfo.RegionSizeX / 2, RegionInfo.RegionSizeY / 2);
4143 if (nearestParcel == null) 4465 if (nearestParcel == null)
4144 { 4466 {
4145 m_log.DebugFormat( 4467 m_log.InfoFormat(
4146 "[SCENE]: Denying root agent entry to {0} in {1}: no allowed parcel", 4468 "[SCENE]: Denying root agent entry to {0} in {1}: no allowed parcel",
4147 cAgentData.AgentID, RegionInfo.RegionName); 4469 cAgentData.AgentID, RegionInfo.RegionName);
4148 4470
@@ -4150,13 +4472,44 @@ namespace OpenSim.Region.Framework.Scenes
4150 } 4472 }
4151 4473
4152 // We have to wait until the viewer contacts this region 4474 // We have to wait until the viewer contacts this region
4153 // after receiving the EnableSimulator HTTP Event Queue message. This triggers the viewer to send 4475 // after receiving the EnableSimulator HTTP Event Queue message (for the v1 teleport protocol)
4154 // a UseCircuitCode packet which in turn calls AddNewClient which finally creates the ScenePresence. 4476 // or TeleportFinish (for the v2 teleport protocol). This triggers the viewer to send
4155 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); 4477 // a UseCircuitCode packet which in turn calls AddNewAgent which finally creates the ScenePresence.
4478 ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID);
4156 4479
4157 if (childAgentUpdate != null) 4480 if (sp != null)
4158 { 4481 {
4159 childAgentUpdate.ChildAgentDataUpdate(cAgentData); 4482 if (cAgentData.SessionID != sp.ControllingClient.SessionId)
4483 {
4484 m_log.WarnFormat(
4485 "[SCENE]: Attempt to update agent {0} with invalid session id {1} (possibly from simulator in older version; tell them to update).",
4486 sp.UUID, cAgentData.SessionID);
4487
4488 Console.WriteLine(String.Format("[SCENE]: Attempt to update agent {0} ({1}) with invalid session id {2}",
4489 sp.UUID, sp.ControllingClient.SessionId, cAgentData.SessionID));
4490 }
4491
4492 sp.UpdateChildAgent(cAgentData);
4493
4494 int ntimes = 20;
4495 if (cAgentData.SenderWantsToWaitForRoot)
4496 {
4497 while (sp.IsChildAgent && ntimes-- > 0)
4498 Thread.Sleep(1000);
4499
4500 if (sp.IsChildAgent)
4501 m_log.WarnFormat(
4502 "[SCENE]: Found presence {0} {1} unexpectedly still child in {2}",
4503 sp.Name, sp.UUID, Name);
4504 else
4505 m_log.InfoFormat(
4506 "[SCENE]: Found presence {0} {1} as root in {2} after {3} waits",
4507 sp.Name, sp.UUID, Name, 20 - ntimes);
4508
4509 if (sp.IsChildAgent)
4510 return false;
4511 }
4512
4160 return true; 4513 return true;
4161 } 4514 }
4162 4515
@@ -4169,12 +4522,20 @@ namespace OpenSim.Region.Framework.Scenes
4169 /// </summary> 4522 /// </summary>
4170 /// <param name="cAgentData">AgentPosition that contains agent positional data so we can know what to send</param> 4523 /// <param name="cAgentData">AgentPosition that contains agent positional data so we can know what to send</param>
4171 /// <returns>true if we handled it.</returns> 4524 /// <returns>true if we handled it.</returns>
4172 public virtual bool IncomingChildAgentDataUpdate(AgentPosition cAgentData) 4525 public virtual bool IncomingUpdateChildAgent(AgentPosition cAgentData)
4173 { 4526 {
4174 //m_log.Debug(" XXX Scene IncomingChildAgentDataUpdate POSITION in " + RegionInfo.RegionName); 4527// m_log.DebugFormat(
4528// "[SCENE PRESENCE]: IncomingChildAgentDataUpdate POSITION for {0} in {1}, position {2}",
4529// cAgentData.AgentID, Name, cAgentData.Position);
4530
4175 ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID); 4531 ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID);
4176 if (childAgentUpdate != null) 4532 if (childAgentUpdate != null)
4177 { 4533 {
4534// if (childAgentUpdate.ControllingClient.SessionId != cAgentData.SessionID)
4535// // Only warn for now
4536// m_log.WarnFormat("[SCENE]: Attempt at updating position of agent {0} with invalid session id {1}. Neighbor running older version?",
4537// childAgentUpdate.UUID, cAgentData.SessionID);
4538
4178 // I can't imagine *yet* why we would get an update if the agent is a root agent.. 4539 // I can't imagine *yet* why we would get an update if the agent is a root agent..
4179 // however to avoid a race condition crossing borders.. 4540 // however to avoid a race condition crossing borders..
4180 if (childAgentUpdate.IsChildAgent) 4541 if (childAgentUpdate.IsChildAgent)
@@ -4184,7 +4545,7 @@ namespace OpenSim.Region.Framework.Scenes
4184 uint tRegionX = RegionInfo.RegionLocX; 4545 uint tRegionX = RegionInfo.RegionLocX;
4185 uint tRegionY = RegionInfo.RegionLocY; 4546 uint tRegionY = RegionInfo.RegionLocY;
4186 //Send Data to ScenePresence 4547 //Send Data to ScenePresence
4187 childAgentUpdate.ChildAgentDataUpdate(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY); 4548 childAgentUpdate.UpdateChildAgent(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY);
4188 // Not Implemented: 4549 // Not Implemented:
4189 //TODO: Do we need to pass the message on to one of our neighbors? 4550 //TODO: Do we need to pass the message on to one of our neighbors?
4190 } 4551 }
@@ -4202,7 +4563,7 @@ namespace OpenSim.Region.Framework.Scenes
4202 /// <param name='agentID'></param> 4563 /// <param name='agentID'></param>
4203 protected virtual ScenePresence WaitGetScenePresence(UUID agentID) 4564 protected virtual ScenePresence WaitGetScenePresence(UUID agentID)
4204 { 4565 {
4205 int ntimes = 10; 4566 int ntimes = 20;
4206 ScenePresence sp = null; 4567 ScenePresence sp = null;
4207 while ((sp = GetScenePresence(agentID)) == null && (ntimes-- > 0)) 4568 while ((sp = GetScenePresence(agentID)) == null && (ntimes-- > 0))
4208 Thread.Sleep(1000); 4569 Thread.Sleep(1000);
@@ -4211,28 +4572,92 @@ namespace OpenSim.Region.Framework.Scenes
4211 m_log.WarnFormat( 4572 m_log.WarnFormat(
4212 "[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout", 4573 "[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout",
4213 agentID, RegionInfo.RegionName); 4574 agentID, RegionInfo.RegionName);
4214// else
4215// m_log.DebugFormat(
4216// "[SCENE PRESENCE]: Found presence {0} {1} {2} in {3} after {4} waits",
4217// sp.Name, sp.UUID, sp.IsChildAgent ? "child" : "root", RegionInfo.RegionName, 10 - ntimes);
4218 4575
4219 return sp; 4576 return sp;
4220 } 4577 }
4221 4578
4222 public virtual bool IncomingRetrieveRootAgent(UUID id, out IAgentData agent) 4579 /// <summary>
4580 /// Authenticated close (via network)
4581 /// </summary>
4582 /// <param name="agentID"></param>
4583 /// <param name="force"></param>
4584 /// <param name="auth_token"></param>
4585 /// <returns></returns>
4586 public bool CloseAgent(UUID agentID, bool force, string auth_token)
4223 { 4587 {
4224 agent = null; 4588 //m_log.DebugFormat("[SCENE]: Processing incoming close agent {0} in region {1} with auth_token {2}", agentID, RegionInfo.RegionName, auth_token);
4225 ScenePresence sp = GetScenePresence(id); 4589
4226 if ((sp != null) && (!sp.IsChildAgent)) 4590 // Check that the auth_token is valid
4591 AgentCircuitData acd = AuthenticateHandler.GetAgentCircuitData(agentID);
4592
4593 if (acd == null)
4594 {
4595 m_log.DebugFormat(
4596 "[SCENE]: Request to close agent {0} but no such agent in scene {1}. May have been closed previously.",
4597 agentID, Name);
4598
4599 return false;
4600 }
4601
4602 if (acd.SessionID.ToString() == auth_token)
4603 {
4604 return CloseAgent(agentID, force);
4605 }
4606 else
4227 { 4607 {
4228 sp.IsChildAgent = true; 4608 m_log.WarnFormat(
4229 return sp.CopyAgent(out agent); 4609 "[SCENE]: Request to close agent {0} with invalid authorization token {1} in {2}",
4610 agentID, auth_token, Name);
4230 } 4611 }
4231 4612
4232 return false; 4613 return false;
4233 } 4614 }
4234 4615
4235 /// <summary> 4616 /// <summary>
4617 /// Tell a single client to prepare to close.
4618 /// </summary>
4619 /// <remarks>
4620 /// This should only be called if we may close the client but there will be some delay in so doing. Meant for
4621 /// internal use - other callers should almost certainly called CloseClient().
4622 /// </remarks>
4623 /// <param name="sp"></param>
4624 /// <returns>true if pre-close state notification was successful. false if the agent
4625 /// was not in a state where it could transition to pre-close.</returns>
4626 public bool IncomingPreCloseClient(ScenePresence sp)
4627 {
4628 lock (m_removeClientLock)
4629 {
4630 // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may
4631 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not
4632 // want to obey this close since C may have renewed the child agent lease on B.
4633 if (sp.DoNotCloseAfterTeleport)
4634 {
4635 m_log.DebugFormat(
4636 "[SCENE]: Not pre-closing {0} agent {1} in {2} since another simulator has re-established the child connection",
4637 sp.IsChildAgent ? "child" : "root", sp.Name, Name);
4638
4639 // Need to reset the flag so that a subsequent close after another teleport can succeed.
4640 sp.DoNotCloseAfterTeleport = false;
4641
4642 return false;
4643 }
4644
4645 if (sp.LifecycleState != ScenePresenceState.Running)
4646 {
4647 m_log.DebugFormat(
4648 "[SCENE]: Called IncomingPreCloseAgent() for {0} in {1} but presence is already in state {2}",
4649 sp.Name, Name, sp.LifecycleState);
4650
4651 return false;
4652 }
4653
4654 sp.LifecycleState = ScenePresenceState.PreRemove;
4655
4656 return true;
4657 }
4658 }
4659
4660 /// <summary>
4236 /// Tell a single agent to disconnect from the region. 4661 /// Tell a single agent to disconnect from the region.
4237 /// </summary> 4662 /// </summary>
4238 /// <param name="agentID"></param> 4663 /// <param name="agentID"></param>
@@ -4240,19 +4665,53 @@ namespace OpenSim.Region.Framework.Scenes
4240 /// Force the agent to close even if it might be in the middle of some other operation. You do not want to 4665 /// Force the agent to close even if it might be in the middle of some other operation. You do not want to
4241 /// force unless you are absolutely sure that the agent is dead and a normal close is not working. 4666 /// force unless you are absolutely sure that the agent is dead and a normal close is not working.
4242 /// </param> 4667 /// </param>
4243 public bool IncomingCloseAgent(UUID agentID, bool force) 4668 public override bool CloseAgent(UUID agentID, bool force)
4244 { 4669 {
4245 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 4670 ScenePresence sp;
4246 4671
4247 ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); 4672 lock (m_removeClientLock)
4248 if (presence != null)
4249 { 4673 {
4250 presence.ControllingClient.Close(force); 4674 sp = GetScenePresence(agentID);
4251 return true; 4675
4676 if (sp == null)
4677 {
4678 m_log.DebugFormat(
4679 "[SCENE]: Called CloseClient() with agent ID {0} but no such presence is in {1}",
4680 agentID, Name);
4681
4682 return false;
4683 }
4684
4685 if (sp.LifecycleState != ScenePresenceState.Running && sp.LifecycleState != ScenePresenceState.PreRemove)
4686 {
4687 m_log.DebugFormat(
4688 "[SCENE]: Called CloseClient() for {0} in {1} but presence is already in state {2}",
4689 sp.Name, Name, sp.LifecycleState);
4690
4691 return false;
4692 }
4693
4694 // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may
4695 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not
4696 // want to obey this close since C may have renewed the child agent lease on B.
4697 if (sp.DoNotCloseAfterTeleport)
4698 {
4699 m_log.DebugFormat(
4700 "[SCENE]: Not closing {0} agent {1} in {2} since another simulator has re-established the child connection",
4701 sp.IsChildAgent ? "child" : "root", sp.Name, Name);
4702
4703 // Need to reset the flag so that a subsequent close after another teleport can succeed.
4704 sp.DoNotCloseAfterTeleport = false;
4705
4706 return false;
4707 }
4708
4709 sp.LifecycleState = ScenePresenceState.Removing;
4252 } 4710 }
4253 4711
4254 // Agent not here 4712 sp.ControllingClient.Close(force);
4255 return false; 4713
4714 return true;
4256 } 4715 }
4257 4716
4258 /// <summary> 4717 /// <summary>
@@ -4295,44 +4754,6 @@ namespace OpenSim.Region.Framework.Scenes
4295 ScenePresence sp = GetScenePresence(remoteClient.AgentId); 4754 ScenePresence sp = GetScenePresence(remoteClient.AgentId);
4296 if (sp != null) 4755 if (sp != null)
4297 { 4756 {
4298 uint regionX = RegionInfo.RegionLocX;
4299 uint regionY = RegionInfo.RegionLocY;
4300
4301 Utils.LongToUInts(regionHandle, out regionX, out regionY);
4302
4303 int shiftx = (int) regionX - (int) RegionInfo.RegionLocX * (int)Constants.RegionSize;
4304 int shifty = (int) regionY - (int) RegionInfo.RegionLocY * (int)Constants.RegionSize;
4305
4306 position.X += shiftx;
4307 position.Y += shifty;
4308
4309 bool result = false;
4310
4311 if (TestBorderCross(position,Cardinals.N))
4312 result = true;
4313
4314 if (TestBorderCross(position, Cardinals.S))
4315 result = true;
4316
4317 if (TestBorderCross(position, Cardinals.E))
4318 result = true;
4319
4320 if (TestBorderCross(position, Cardinals.W))
4321 result = true;
4322
4323 // bordercross if position is outside of region
4324
4325 if (!result)
4326 {
4327 regionHandle = RegionInfo.RegionHandle;
4328 }
4329 else
4330 {
4331 // not in this region, undo the shift!
4332 position.X -= shiftx;
4333 position.Y -= shifty;
4334 }
4335
4336 if (EntityTransferModule != null) 4757 if (EntityTransferModule != null)
4337 { 4758 {
4338 EntityTransferModule.Teleport(sp, regionHandle, position, lookAt, teleportFlags); 4759 EntityTransferModule.Teleport(sp, regionHandle, position, lookAt, teleportFlags);
@@ -4473,20 +4894,7 @@ namespace OpenSim.Region.Framework.Scenes
4473 4894
4474 #region Script Engine 4895 #region Script Engine
4475 4896
4476 private List<ScriptEngineInterface> ScriptEngines = new List<ScriptEngineInterface>(); 4897 private bool ScriptDanger(SceneObjectPart part, Vector3 pos)
4477 public bool DumpAssetsToFile;
4478
4479 /// <summary>
4480 ///
4481 /// </summary>
4482 /// <param name="scriptEngine"></param>
4483 public void AddScriptEngine(ScriptEngineInterface scriptEngine)
4484 {
4485 ScriptEngines.Add(scriptEngine);
4486 scriptEngine.InitializeEngine(this);
4487 }
4488
4489 private bool ScriptDanger(SceneObjectPart part,Vector3 pos)
4490 { 4898 {
4491 ILandObject parcel = LandChannel.GetLandObject(pos.X, pos.Y); 4899 ILandObject parcel = LandChannel.GetLandObject(pos.X, pos.Y);
4492 if (part != null) 4900 if (part != null)
@@ -4497,35 +4905,24 @@ namespace OpenSim.Region.Framework.Scenes
4497 { 4905 {
4498 return true; 4906 return true;
4499 } 4907 }
4500 else if ((parcel.LandData.Flags & (uint)ParcelFlags.AllowGroupScripts) != 0) 4908 else if ((part.OwnerID == parcel.LandData.OwnerID) || Permissions.IsGod(part.OwnerID))
4501 { 4909 {
4502 if (part.OwnerID == parcel.LandData.OwnerID 4910 return true;
4503 || (parcel.LandData.IsGroupOwned && part.GroupID == parcel.LandData.GroupID) 4911 }
4504 || Permissions.IsGod(part.OwnerID)) 4912 else if (((parcel.LandData.Flags & (uint)ParcelFlags.AllowGroupScripts) != 0)
4505 { 4913 && (parcel.LandData.GroupID != UUID.Zero) && (parcel.LandData.GroupID == part.GroupID))
4506 return true; 4914 {
4507 } 4915 return true;
4508 else
4509 {
4510 return false;
4511 }
4512 } 4916 }
4513 else 4917 else
4514 { 4918 {
4515 if (part.OwnerID == parcel.LandData.OwnerID) 4919 return false;
4516 {
4517 return true;
4518 }
4519 else
4520 {
4521 return false;
4522 }
4523 } 4920 }
4524 } 4921 }
4525 else 4922 else
4526 { 4923 {
4527 4924
4528 if (pos.X > 0f && pos.X < Constants.RegionSize && pos.Y > 0f && pos.Y < Constants.RegionSize) 4925 if (pos.X > 0f && pos.X < RegionInfo.RegionSizeX && pos.Y > 0f && pos.Y < RegionInfo.RegionSizeY)
4529 { 4926 {
4530 // The only time parcel != null when an object is inside a region is when 4927 // The only time parcel != null when an object is inside a region is when
4531 // there is nothing behind the landchannel. IE, no land plugin loaded. 4928 // there is nothing behind the landchannel. IE, no land plugin loaded.
@@ -4854,21 +5251,6 @@ namespace OpenSim.Region.Framework.Scenes
4854 5251
4855 #endregion 5252 #endregion
4856 5253
4857 public void RegionHandleRequest(IClientAPI client, UUID regionID)
4858 {
4859 ulong handle = 0;
4860 if (regionID == RegionInfo.RegionID)
4861 handle = RegionInfo.RegionHandle;
4862 else
4863 {
4864 GridRegion r = GridService.GetRegionByUUID(UUID.Zero, regionID);
4865 if (r != null)
4866 handle = r.RegionHandle;
4867 }
4868
4869 if (handle != 0)
4870 client.SendRegionHandle(regionID, handle);
4871 }
4872 5254
4873// Commented pending deletion since this method no longer appears to do anything at all 5255// Commented pending deletion since this method no longer appears to do anything at all
4874// public bool NeedSceneCacheClear(UUID agentID) 5256// public bool NeedSceneCacheClear(UUID agentID)
@@ -4920,7 +5302,7 @@ namespace OpenSim.Region.Framework.Scenes
4920 // 3 = We have seen a new user enter within the past 4 minutes 5302 // 3 = We have seen a new user enter within the past 4 minutes
4921 // which can be seen as positive confirmation of sim health 5303 // which can be seen as positive confirmation of sim health
4922 // 5304 //
4923 int health=1; // Start at 1, means we're up 5305 int health = 1; // Start at 1, means we're up
4924 5306
4925 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 1000) 5307 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 1000)
4926 health += 1; 5308 health += 1;
@@ -4967,7 +5349,7 @@ namespace OpenSim.Region.Framework.Scenes
4967 case PhysicsJointType.Ball: 5349 case PhysicsJointType.Ball:
4968 { 5350 {
4969 Vector3 jointAnchor = PhysicsScene.GetJointAnchor(joint); 5351 Vector3 jointAnchor = PhysicsScene.GetJointAnchor(joint);
4970 Vector3 proxyPos = new Vector3(jointAnchor.X, jointAnchor.Y, jointAnchor.Z); 5352 Vector3 proxyPos = jointAnchor;
4971 jointProxyObject.ParentGroup.UpdateGroupPosition(proxyPos); // schedules the entire group for a terse update 5353 jointProxyObject.ParentGroup.UpdateGroupPosition(proxyPos); // schedules the entire group for a terse update
4972 } 5354 }
4973 break; 5355 break;
@@ -4992,7 +5374,7 @@ namespace OpenSim.Region.Framework.Scenes
4992 jointErrorMessage(joint, "joint.TrackedBodyName is null, joint " + joint.ObjectNameInScene); 5374 jointErrorMessage(joint, "joint.TrackedBodyName is null, joint " + joint.ObjectNameInScene);
4993 } 5375 }
4994 5376
4995 Vector3 proxyPos = new Vector3(jointAnchor.X, jointAnchor.Y, jointAnchor.Z); 5377 Vector3 proxyPos = jointAnchor;
4996 Quaternion q = trackedBody.RotationOffset * joint.LocalRotation; 5378 Quaternion q = trackedBody.RotationOffset * joint.LocalRotation;
4997 5379
4998 jointProxyObject.ParentGroup.UpdateGroupPosition(proxyPos); // schedules the entire group for a terse update 5380 jointProxyObject.ParentGroup.UpdateGroupPosition(proxyPos); // schedules the entire group for a terse update
@@ -5081,6 +5463,10 @@ namespace OpenSim.Region.Framework.Scenes
5081 return null; 5463 return null;
5082 } 5464 }
5083 5465
5466 // Get terrain height at the specified <x,y> location.
5467 // Presumes the underlying implementation is a heightmap which is a 1m grid.
5468 // Finds heightmap grid points before and after the point and
5469 // does a linear approximation of the height at this intermediate point.
5084 public float GetGroundHeight(float x, float y) 5470 public float GetGroundHeight(float x, float y)
5085 { 5471 {
5086 if (x < 0) 5472 if (x < 0)
@@ -5093,8 +5479,8 @@ namespace OpenSim.Region.Framework.Scenes
5093 y = Heightmap.Height - 1; 5479 y = Heightmap.Height - 1;
5094 5480
5095 Vector3 p0 = new Vector3(x, y, (float)Heightmap[(int)x, (int)y]); 5481 Vector3 p0 = new Vector3(x, y, (float)Heightmap[(int)x, (int)y]);
5096 Vector3 p1 = new Vector3(p0); 5482 Vector3 p1 = p0;
5097 Vector3 p2 = new Vector3(p0); 5483 Vector3 p2 = p0;
5098 5484
5099 p1.X += 1.0f; 5485 p1.X += 1.0f;
5100 if (p1.X < Heightmap.Width) 5486 if (p1.X < Heightmap.Width)
@@ -5141,9 +5527,14 @@ namespace OpenSim.Region.Framework.Scenes
5141 get { return m_allowScriptCrossings; } 5527 get { return m_allowScriptCrossings; }
5142 } 5528 }
5143 5529
5144 public Vector3? GetNearestAllowedPosition(ScenePresence avatar) 5530 public Vector3 GetNearestAllowedPosition(ScenePresence avatar)
5145 { 5531 {
5146 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); 5532 return GetNearestAllowedPosition(avatar, null);
5533 }
5534
5535 public Vector3 GetNearestAllowedPosition(ScenePresence avatar, ILandObject excludeParcel)
5536 {
5537 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, excludeParcel);
5147 5538
5148 if (nearestParcel != null) 5539 if (nearestParcel != null)
5149 { 5540 {
@@ -5152,10 +5543,7 @@ namespace OpenSim.Region.Framework.Scenes
5152 Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); 5543 Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel);
5153 if (nearestPoint != null) 5544 if (nearestPoint != null)
5154 { 5545 {
5155// m_log.DebugFormat( 5546 m_log.Debug("Found a sane previous position based on velocity, sending them to: " + nearestPoint.ToString());
5156// "[SCENE]: Found a sane previous position based on velocity for {0}, sending them to {1} in {2}",
5157// avatar.Name, nearestPoint, nearestParcel.LandData.Name);
5158
5159 return nearestPoint.Value; 5547 return nearestPoint.Value;
5160 } 5548 }
5161 5549
@@ -5165,24 +5553,27 @@ namespace OpenSim.Region.Framework.Scenes
5165 nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); 5553 nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel);
5166 if (nearestPoint != null) 5554 if (nearestPoint != null)
5167 { 5555 {
5168// m_log.DebugFormat( 5556 m_log.Debug("They had a zero velocity, sending them to: " + nearestPoint.ToString());
5169// "[SCENE]: {0} had a zero velocity, sending them to {1}", avatar.Name, nearestPoint);
5170
5171 return nearestPoint.Value; 5557 return nearestPoint.Value;
5172 } 5558 }
5173 5559
5174 //Ultimate backup if we have no idea where they are 5560 ILandObject dest = LandChannel.GetLandObject(avatar.lastKnownAllowedPosition.X, avatar.lastKnownAllowedPosition.Y);
5175// m_log.DebugFormat( 5561 if (dest != excludeParcel)
5176// "[SCENE]: No idea where {0} is, sending them to {1}", avatar.Name, avatar.lastKnownAllowedPosition); 5562 {
5563 // Ultimate backup if we have no idea where they are and
5564 // the last allowed position was in another parcel
5565 m_log.Debug("Have no idea where they are, sending them to: " + avatar.lastKnownAllowedPosition.ToString());
5566 return avatar.lastKnownAllowedPosition;
5567 }
5177 5568
5178 return avatar.lastKnownAllowedPosition; 5569 // else fall through to region edge
5179 } 5570 }
5180 5571
5181 //Go to the edge, this happens in teleporting to a region with no available parcels 5572 //Go to the edge, this happens in teleporting to a region with no available parcels
5182 Vector3 nearestRegionEdgePoint = GetNearestRegionEdgePosition(avatar); 5573 Vector3 nearestRegionEdgePoint = GetNearestRegionEdgePosition(avatar);
5183 5574
5184 //Debug.WriteLine("They are really in a place they don't belong, sending them to: " + nearestRegionEdgePoint.ToString()); 5575 //m_log.Debug("They are really in a place they don't belong, sending them to: " + nearestRegionEdgePoint.ToString());
5185 5576
5186 return nearestRegionEdgePoint; 5577 return nearestRegionEdgePoint;
5187 } 5578 }
5188 5579
@@ -5196,7 +5587,7 @@ namespace OpenSim.Region.Framework.Scenes
5196 { 5587 {
5197 Vector3 unitDirection = Vector3.Normalize(direction); 5588 Vector3 unitDirection = Vector3.Normalize(direction);
5198 //Making distance to search go through some sane limit of distance 5589 //Making distance to search go through some sane limit of distance
5199 for (float distance = 0; distance < Constants.RegionSize * 2; distance += .5f) 5590 for (float distance = 0; distance < Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY) * 2; distance += .5f)
5200 { 5591 {
5201 Vector3 testPos = Vector3.Add(pos, Vector3.Multiply(unitDirection, distance)); 5592 Vector3 testPos = Vector3.Add(pos, Vector3.Multiply(unitDirection, distance));
5202 if (parcel.ContainsPoint((int)testPos.X, (int)testPos.Y)) 5593 if (parcel.ContainsPoint((int)testPos.X, (int)testPos.Y))
@@ -5209,13 +5600,18 @@ namespace OpenSim.Region.Framework.Scenes
5209 5600
5210 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y) 5601 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y)
5211 { 5602 {
5603 return GetNearestAllowedParcel(avatarId, x, y, null);
5604 }
5605
5606 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y, ILandObject excludeParcel)
5607 {
5212 List<ILandObject> all = AllParcels(); 5608 List<ILandObject> all = AllParcels();
5213 float minParcelDistance = float.MaxValue; 5609 float minParcelDistance = float.MaxValue;
5214 ILandObject nearestParcel = null; 5610 ILandObject nearestParcel = null;
5215 5611
5216 foreach (var parcel in all) 5612 foreach (var parcel in all)
5217 { 5613 {
5218 if (!parcel.IsEitherBannedOrRestricted(avatarId)) 5614 if (!parcel.IsEitherBannedOrRestricted(avatarId) && parcel != excludeParcel)
5219 { 5615 {
5220 float parcelDistance = GetParcelDistancefromPoint(parcel, x, y); 5616 float parcelDistance = GetParcelDistancefromPoint(parcel, x, y);
5221 if (parcelDistance < minParcelDistance) 5617 if (parcelDistance < minParcelDistance)
@@ -5245,9 +5641,9 @@ namespace OpenSim.Region.Framework.Scenes
5245 int count = 0; 5641 int count = 0;
5246 int avgx = 0; 5642 int avgx = 0;
5247 int avgy = 0; 5643 int avgy = 0;
5248 for (int x = 0; x < Constants.RegionSize; x++) 5644 for (int x = 0; x < RegionInfo.RegionSizeX; x++)
5249 { 5645 {
5250 for (int y = 0; y < Constants.RegionSize; y++) 5646 for (int y = 0; y < RegionInfo.RegionSizeY; y++)
5251 { 5647 {
5252 //Just keep a running average as we check if all the points are inside or not 5648 //Just keep a running average as we check if all the points are inside or not
5253 if (parcel.ContainsPoint(x, y)) 5649 if (parcel.ContainsPoint(x, y))
@@ -5271,31 +5667,33 @@ namespace OpenSim.Region.Framework.Scenes
5271 5667
5272 private Vector3 GetNearestRegionEdgePosition(ScenePresence avatar) 5668 private Vector3 GetNearestRegionEdgePosition(ScenePresence avatar)
5273 { 5669 {
5274 float xdistance = avatar.AbsolutePosition.X < Constants.RegionSize / 2 ? avatar.AbsolutePosition.X : Constants.RegionSize - avatar.AbsolutePosition.X; 5670 float xdistance = avatar.AbsolutePosition.X < RegionInfo.RegionSizeX / 2
5275 float ydistance = avatar.AbsolutePosition.Y < Constants.RegionSize / 2 ? avatar.AbsolutePosition.Y : Constants.RegionSize - avatar.AbsolutePosition.Y; 5671 ? avatar.AbsolutePosition.X : RegionInfo.RegionSizeX - avatar.AbsolutePosition.X;
5672 float ydistance = avatar.AbsolutePosition.Y < RegionInfo.RegionSizeY / 2
5673 ? avatar.AbsolutePosition.Y : RegionInfo.RegionSizeY - avatar.AbsolutePosition.Y;
5276 5674
5277 //find out what vertical edge to go to 5675 //find out what vertical edge to go to
5278 if (xdistance < ydistance) 5676 if (xdistance < ydistance)
5279 { 5677 {
5280 if (avatar.AbsolutePosition.X < Constants.RegionSize / 2) 5678 if (avatar.AbsolutePosition.X < RegionInfo.RegionSizeX / 2)
5281 { 5679 {
5282 return GetPositionAtAvatarHeightOrGroundHeight(avatar, 0.0f, avatar.AbsolutePosition.Y); 5680 return GetPositionAtAvatarHeightOrGroundHeight(avatar, 0.0f, avatar.AbsolutePosition.Y);
5283 } 5681 }
5284 else 5682 else
5285 { 5683 {
5286 return GetPositionAtAvatarHeightOrGroundHeight(avatar, Constants.RegionSize, avatar.AbsolutePosition.Y); 5684 return GetPositionAtAvatarHeightOrGroundHeight(avatar, RegionInfo.RegionSizeY, avatar.AbsolutePosition.Y);
5287 } 5685 }
5288 } 5686 }
5289 //find out what horizontal edge to go to 5687 //find out what horizontal edge to go to
5290 else 5688 else
5291 { 5689 {
5292 if (avatar.AbsolutePosition.Y < Constants.RegionSize / 2) 5690 if (avatar.AbsolutePosition.Y < RegionInfo.RegionSizeY / 2)
5293 { 5691 {
5294 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, 0.0f); 5692 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, 0.0f);
5295 } 5693 }
5296 else 5694 else
5297 { 5695 {
5298 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, Constants.RegionSize); 5696 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, RegionInfo.RegionSizeY);
5299 } 5697 }
5300 } 5698 }
5301 } 5699 }
@@ -5336,33 +5734,7 @@ namespace OpenSim.Region.Framework.Scenes
5336 5734
5337 public void TriggerEstateSunUpdate() 5735 public void TriggerEstateSunUpdate()
5338 { 5736 {
5339 float sun; 5737 EventManager.TriggerEstateToolsSunUpdate(RegionInfo.RegionHandle);
5340 if (RegionInfo.RegionSettings.UseEstateSun)
5341 {
5342 sun = (float)RegionInfo.EstateSettings.SunPosition;
5343 if (RegionInfo.EstateSettings.UseGlobalTime)
5344 {
5345 sun = EventManager.GetCurrentTimeAsSunLindenHour() - 6.0f;
5346 }
5347
5348 //
5349 EventManager.TriggerEstateToolsSunUpdate(
5350 RegionInfo.RegionHandle,
5351 RegionInfo.EstateSettings.FixedSun,
5352 RegionInfo.RegionSettings.UseEstateSun,
5353 sun);
5354 }
5355 else
5356 {
5357 // Use the Sun Position from the Region Settings
5358 sun = (float)RegionInfo.RegionSettings.SunPosition - 6.0f;
5359
5360 EventManager.TriggerEstateToolsSunUpdate(
5361 RegionInfo.RegionHandle,
5362 RegionInfo.RegionSettings.FixedSun,
5363 RegionInfo.RegionSettings.UseEstateSun,
5364 sun);
5365 }
5366 } 5738 }
5367 5739
5368 private void HandleReloadEstate(string module, string[] cmd) 5740 private void HandleReloadEstate(string module, string[] cmd)
@@ -5387,15 +5759,15 @@ namespace OpenSim.Region.Framework.Scenes
5387 /// <param name="maxZ"></param> 5759 /// <param name="maxZ"></param>
5388 /// <returns></returns> 5760 /// <returns></returns>
5389 public static Vector3[] GetCombinedBoundingBox( 5761 public static Vector3[] GetCombinedBoundingBox(
5390 List<SceneObjectGroup> objects, 5762 List<SceneObjectGroup> objects,
5391 out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) 5763 out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ)
5392 { 5764 {
5393 minX = 256; 5765 minX = float.MaxValue;
5394 maxX = -256; 5766 maxX = float.MinValue;
5395 minY = 256; 5767 minY = float.MaxValue;
5396 maxY = -256; 5768 maxY = float.MinValue;
5397 minZ = 8192; 5769 minZ = float.MaxValue;
5398 maxZ = -256; 5770 maxZ = float.MinValue;
5399 5771
5400 List<Vector3> offsets = new List<Vector3>(); 5772 List<Vector3> offsets = new List<Vector3>();
5401 5773
@@ -5406,7 +5778,7 @@ namespace OpenSim.Region.Framework.Scenes
5406 Vector3 vec = g.AbsolutePosition; 5778 Vector3 vec = g.AbsolutePosition;
5407 5779
5408 g.GetAxisAlignedBoundingBoxRaw(out ominX, out omaxX, out ominY, out omaxY, out ominZ, out omaxZ); 5780 g.GetAxisAlignedBoundingBoxRaw(out ominX, out omaxX, out ominY, out omaxY, out ominZ, out omaxZ);
5409 5781
5410// m_log.DebugFormat( 5782// m_log.DebugFormat(
5411// "[SCENE]: For {0} found AxisAlignedBoundingBoxRaw {1}, {2}", 5783// "[SCENE]: For {0} found AxisAlignedBoundingBoxRaw {1}, {2}",
5412// g.Name, new Vector3(ominX, ominY, ominZ), new Vector3(omaxX, omaxY, omaxZ)); 5784// g.Name, new Vector3(ominX, ominY, ominZ), new Vector3(omaxX, omaxY, omaxZ));
@@ -5465,7 +5837,7 @@ namespace OpenSim.Region.Framework.Scenes
5465 // so that all simulators can retrieve it 5837 // so that all simulators can retrieve it
5466 string error = GridService.RegisterRegion(RegionInfo.ScopeID, new GridRegion(RegionInfo)); 5838 string error = GridService.RegisterRegion(RegionInfo.ScopeID, new GridRegion(RegionInfo));
5467 if (error != string.Empty) 5839 if (error != string.Empty)
5468 throw new Exception(error); 5840 throw new Exception(error);
5469 } 5841 }
5470 5842
5471 /// <summary> 5843 /// <summary>
@@ -5479,22 +5851,23 @@ namespace OpenSim.Region.Framework.Scenes
5479 /// or corssing the broder walking, but will NOT prevent 5851 /// or corssing the broder walking, but will NOT prevent
5480 /// child agent creation, thereby emulating the SL behavior. 5852 /// child agent creation, thereby emulating the SL behavior.
5481 /// </remarks> 5853 /// </remarks>
5482 /// <param name='agentID'></param> 5854 /// <param name='agentID'>The visitor's User ID</param>
5855 /// <param name="agentHomeURI">The visitor's Home URI (may be null)</param>
5483 /// <param name='position'></param> 5856 /// <param name='position'></param>
5484 /// <param name='reason'></param> 5857 /// <param name='reason'></param>
5485 /// <returns></returns> 5858 /// <returns></returns>
5486 public bool QueryAccess(UUID agentID, Vector3 position, out string reason) 5859 public bool QueryAccess(UUID agentID, string agentHomeURI, bool viaTeleport, Vector3 position, List<UUID> features, out string reason)
5487 { 5860 {
5488 if (EntityTransferModule.IsInTransit(agentID)) 5861 reason = string.Empty;
5489 {
5490 reason = "Agent is still in transit from this region";
5491 5862
5492 m_log.WarnFormat( 5863 if (Permissions.IsGod(agentID))
5493 "[SCENE]: Denying agent {0} entry into {1} since region still has them registered as in transit", 5864 {
5494 agentID, RegionInfo.RegionName); 5865 reason = String.Empty;
5866 return true;
5867 }
5495 5868
5869 if (!AllowAvatarCrossing && !viaTeleport)
5496 return false; 5870 return false;
5497 }
5498 5871
5499 // FIXME: Root agent count is currently known to be inaccurate. This forces a recount before we check. 5872 // FIXME: Root agent count is currently known to be inaccurate. This forces a recount before we check.
5500 // However, the long term fix is to make sure root agent count is always accurate. 5873 // However, the long term fix is to make sure root agent count is always accurate.
@@ -5516,7 +5889,43 @@ namespace OpenSim.Region.Framework.Scenes
5516 } 5889 }
5517 } 5890 }
5518 5891
5519 if (position == Vector3.Zero) // Teleport 5892 ScenePresence presence = GetScenePresence(agentID);
5893 IClientAPI client = null;
5894 AgentCircuitData aCircuit = null;
5895
5896 if (presence != null)
5897 {
5898 client = presence.ControllingClient;
5899 if (client != null)
5900 aCircuit = client.RequestClientInfo();
5901 }
5902
5903 // We may be called before there is a presence or a client.
5904 // Fake AgentCircuitData to keep IAuthorizationModule smiling
5905 if (client == null)
5906 {
5907 aCircuit = new AgentCircuitData();
5908 aCircuit.AgentID = agentID;
5909 aCircuit.firstname = String.Empty;
5910 aCircuit.lastname = String.Empty;
5911 }
5912
5913 try
5914 {
5915 if (!AuthorizeUser(aCircuit, false, out reason))
5916 {
5917 //m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5918 return false;
5919 }
5920 }
5921 catch (Exception e)
5922 {
5923 m_log.DebugFormat("[SCENE]: Exception authorizing agent: {0} " + e.StackTrace, e.Message);
5924 reason = "Error authorizing agent: " + e.Message;
5925 return false;
5926 }
5927
5928 if (viaTeleport)
5520 { 5929 {
5521 if (!RegionInfo.EstateSettings.AllowDirectTeleport) 5930 if (!RegionInfo.EstateSettings.AllowDirectTeleport)
5522 { 5931 {
@@ -5539,11 +5948,47 @@ namespace OpenSim.Region.Framework.Scenes
5539 5948
5540 if (banned) 5949 if (banned)
5541 { 5950 {
5542 reason = "No suitable landing point found"; 5951 if (Permissions.IsAdministrator(agentID) == false || Permissions.IsGridGod(agentID) == false)
5543 return false; 5952 {
5953 reason = "No suitable landing point found";
5954 return false;
5955 }
5956 reason = "Administrative access only";
5957 return true;
5544 } 5958 }
5545 } 5959 }
5546 } 5960 }
5961
5962 float posX = 128.0f;
5963 float posY = 128.0f;
5964
5965 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY))
5966 {
5967 // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID);
5968 reason = "You are banned from the region on all parcels";
5969 return false;
5970 }
5971 }
5972 else // Walking
5973 {
5974 ILandObject land = LandChannel.GetLandObject(position.X, position.Y);
5975 if (land == null)
5976 {
5977 reason = "No parcel found";
5978 return false;
5979 }
5980
5981 bool banned = land.IsBannedFromLand(agentID);
5982 bool restricted = land.IsRestrictedFromLand(agentID);
5983
5984 if (banned || restricted)
5985 {
5986 if (banned)
5987 reason = "You are banned from the parcel";
5988 else
5989 reason = "The parcel is restricted";
5990 return false;
5991 }
5547 } 5992 }
5548 5993
5549 reason = String.Empty; 5994 reason = String.Empty;