aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/Scene.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs2681
1 files changed, 1543 insertions, 1138 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 2fe6e22..dd23bf6 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -61,15 +61,12 @@ namespace OpenSim.Region.Framework.Scenes
61 { 61 {
62 private const long DEFAULT_MIN_TIME_FOR_PERSISTENCE = 60L; 62 private const long DEFAULT_MIN_TIME_FOR_PERSISTENCE = 60L;
63 private const long DEFAULT_MAX_TIME_FOR_PERSISTENCE = 600L; 63 private const long DEFAULT_MAX_TIME_FOR_PERSISTENCE = 600L;
64 64
65 public const int m_defaultNumberFramesStored = 10;
66 65
67 public delegate void SynchronizeSceneHandler(Scene scene); 66 public delegate void SynchronizeSceneHandler(Scene scene);
68 67
69 #region Fields 68 #region Fields
70 69
71 public bool EmergencyMonitoring = false;
72
73 /// <summary> 70 /// <summary>
74 /// Show debug information about animations. 71 /// Show debug information about animations.
75 /// </summary> 72 /// </summary>
@@ -91,7 +88,7 @@ namespace OpenSim.Region.Framework.Scenes
91 /// </summary> 88 /// </summary>
92 /// <remarks> 89 /// <remarks>
93 /// Even if false, the scene will still be saved on clean shutdown. 90 /// Even if false, the scene will still be saved on clean shutdown.
94 /// FIXME: Currently, setting this to false will mean that objects are not periodically returned from parcels. 91 /// FIXME: Currently, setting this to false will mean that objects are not periodically returned from parcels.
95 /// This needs to be fixed. 92 /// This needs to be fixed.
96 /// </remarks> 93 /// </remarks>
97 public bool PeriodicBackup { get; set; } 94 public bool PeriodicBackup { get; set; }
@@ -105,6 +102,7 @@ namespace OpenSim.Region.Framework.Scenes
105 /// <summary> 102 /// <summary>
106 /// If false then physical objects are disabled, though collisions will continue as normal. 103 /// If false then physical objects are disabled, though collisions will continue as normal.
107 /// </summary> 104 /// </summary>
105
108 public bool PhysicsEnabled 106 public bool PhysicsEnabled
109 { 107 {
110 get 108 get
@@ -174,6 +172,13 @@ namespace OpenSim.Region.Framework.Scenes
174 172
175 public SynchronizeSceneHandler SynchronizeScene; 173 public SynchronizeSceneHandler SynchronizeScene;
176 174
175 public bool ClampNegativeZ
176 {
177 get { return m_clampNegativeZ; }
178 }
179
180 private bool m_clampNegativeZ = false;
181
177 /// <summary> 182 /// <summary>
178 /// Used to prevent simultaneous calls to code that adds and removes agents. 183 /// Used to prevent simultaneous calls to code that adds and removes agents.
179 /// </summary> 184 /// </summary>
@@ -216,7 +221,7 @@ namespace OpenSim.Region.Framework.Scenes
216 /// <summary> 221 /// <summary>
217 /// Maximum value of the size of a physical prim in each axis 222 /// Maximum value of the size of a physical prim in each axis
218 /// </summary> 223 /// </summary>
219 public float m_maxPhys = 64; 224 public float m_maxPhys = 10;
220 225
221 /// <summary> 226 /// <summary>
222 /// Max prims an object will hold 227 /// Max prims an object will hold
@@ -228,57 +233,48 @@ namespace OpenSim.Region.Framework.Scenes
228 public bool m_allowScriptCrossings = true; 233 public bool m_allowScriptCrossings = true;
229 234
230 /// <summary> 235 /// <summary>
231 /// Can avatars cross from and to this region? 236 /// use legacy sittarget offsets to avoid contents breaks
237 /// to compensate for SL bug
232 /// </summary> 238 /// </summary>
233 public bool AllowAvatarCrossing { get; set; } 239 public bool LegacySitOffsets = true;
234
235 public bool m_useFlySlow;
236 public bool m_useTrashOnDelete = true;
237 240
238 /// <summary> 241 /// <summary>
239 /// Temporarily setting to trigger appearance resends at 60 second intervals. 242 /// Can avatars cross from and to this region?
240 /// </summary>
241 public bool SendPeriodicAppearanceUpdates { get; set; }
242
243 /// <summary>
244 /// How much a root agent has to change position before updates are sent to viewers.
245 /// </summary> 243 /// </summary>
246 public float RootPositionUpdateTolerance { get; set; } 244 public bool AllowAvatarCrossing { get; set; }
247 245
248 /// <summary> 246 /// Max prims an Physical object will hold
249 /// How much a root agent has to rotate before updates are sent to viewers.
250 /// </summary> 247 /// </summary>
251 public float RootRotationUpdateTolerance { get; set; } 248 ///
252 249 public int m_linksetPhysCapacity = 0;
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 250
258 /// <summary> 251 /// <summary>
259 /// If greater than 1, we only send terse updates to other root agents on every n updates. 252 /// When placed outside the region's border, do we transfer the objects or
253 /// do we keep simulating them here?
260 /// </summary> 254 /// </summary>
261 public int RootTerseUpdatePeriod { get; set; } 255 public bool DisableObjectTransfer { get; set; }
262 256
263 /// <summary> 257 public bool m_useFlySlow;
264 /// If greater than 1, we only send terse updates to child agents on every n updates. 258 public bool m_useTrashOnDelete = true;
265 /// </summary>
266 public int ChildTerseUpdatePeriod { get; set; }
267 259
268 protected float m_defaultDrawDistance = 255.0f; 260 protected float m_defaultDrawDistance = 255f;
261 protected float m_defaultCullingDrawDistance = 16f;
269 public float DefaultDrawDistance 262 public float DefaultDrawDistance
270 { 263 {
271 // get { return m_defaultDrawDistance; } 264 get { return ObjectsCullingByDistance?m_defaultCullingDrawDistance:m_defaultDrawDistance; }
272 get 265 }
273 {
274 if (RegionInfo != null)
275 {
276 float largestDimension = Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY);
277 m_defaultDrawDistance = Math.Max(m_defaultDrawDistance, largestDimension);
278 266
279 } 267 protected float m_maxDrawDistance = 512.0f;
280 return m_defaultDrawDistance; 268// protected float m_maxDrawDistance = 256.0f;
281 } 269 public float MaxDrawDistance
270 {
271 get { return m_maxDrawDistance; }
272 }
273
274 protected float m_maxRegionViewDistance = 255f;
275 public float MaxRegionViewDistance
276 {
277 get { return m_maxRegionViewDistance; }
282 } 278 }
283 279
284 private List<string> m_AllowedViewers = new List<string>(); 280 private List<string> m_AllowedViewers = new List<string>();
@@ -287,8 +283,8 @@ namespace OpenSim.Region.Framework.Scenes
287 // TODO: need to figure out how allow client agents but deny 283 // TODO: need to figure out how allow client agents but deny
288 // root agents when ACL denies access to root agent 284 // root agents when ACL denies access to root agent
289 public bool m_strictAccessControl = true; 285 public bool m_strictAccessControl = true;
290 286 public bool m_seeIntoBannedRegion = false;
291 public int MaxUndoCount { get; set; } 287 public int MaxUndoCount = 5;
292 288
293 public bool SeeIntoRegion { get; set; } 289 public bool SeeIntoRegion { get; set; }
294 290
@@ -306,11 +302,13 @@ namespace OpenSim.Region.Framework.Scenes
306 302
307 protected int m_splitRegionID; 303 protected int m_splitRegionID;
308 protected Timer m_restartWaitTimer = new Timer(); 304 protected Timer m_restartWaitTimer = new Timer();
305 protected Timer m_timerWatchdog = new Timer();
309 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>(); 306 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>();
310 protected List<RegionInfo> m_neighbours = new List<RegionInfo>(); 307 protected List<RegionInfo> m_neighbours = new List<RegionInfo>();
311 protected string m_simulatorVersion = "OpenSimulator Server"; 308 protected string m_simulatorVersion = "OpenSimulator Server";
312 protected AgentCircuitManager m_authenticateHandler; 309 protected AgentCircuitManager m_authenticateHandler;
313 protected SceneCommunicationService m_sceneGridService; 310 protected SceneCommunicationService m_sceneGridService;
311 protected ISnmpModule m_snmpService = null;
314 312
315 protected ISimulationDataService m_SimulationDataService; 313 protected ISimulationDataService m_SimulationDataService;
316 protected IEstateDataService m_EstateDataService; 314 protected IEstateDataService m_EstateDataService;
@@ -336,18 +334,10 @@ namespace OpenSim.Region.Framework.Scenes
336 protected ICapabilitiesModule m_capsModule; 334 protected ICapabilitiesModule m_capsModule;
337 protected IGroupsModule m_groupsModule; 335 protected IGroupsModule m_groupsModule;
338 336
339 private Dictionary<string, string> m_extraSettings; 337 // The lists of groups to automatically add to logging in users.
340 338 private Dictionary<string, string[]> m_AutoGroups;
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 339
347 /// <summary> 340 private Dictionary<string, string> m_extraSettings;
348 /// Only used if we are updating scene on a timer rather than sleeping a thread.
349 /// </summary>
350 private Timer m_sceneUpdateTimer;
351 341
352 /// <summary> 342 /// <summary>
353 /// Current scene frame number 343 /// Current scene frame number
@@ -359,87 +349,38 @@ namespace OpenSim.Region.Framework.Scenes
359 } 349 }
360 350
361 /// <summary> 351 /// <summary>
362 /// Current maintenance run number 352 /// Frame time
363 /// </summary>
364 public uint MaintenanceRun { get; private set; }
365
366 /// <summary>
367 /// The minimum length of time in milliseconds that will be taken for a scene frame. If the frame takes less time then we
368 /// will sleep for the remaining period.
369 /// </summary>
370 /// <remarks>
371 /// One can tweak this number to experiment. One current effect of reducing it is to make avatar animations
372 /// occur too quickly (viewer 1) or with even more slide (viewer 2).
373 /// </remarks> 353 /// </remarks>
374 public int MinFrameTicks 354 public float FrameTime { get; private set; }
375 { 355 public int FrameTimeWarnPercent { get; private set; }
376 get { return m_minFrameTicks; } 356 public int FrameTimeCritPercent { get; private set; }
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 357
388 // Normalize the frame related stats to nominal 55fps for viewer and scripts option 358 // Normalize the frame related stats to nominal 55fps for viewer and scripts option
389 // see SimStatsReporter.cs 359 // see SimStatsReporter.cs
390 public bool Normalized55FPS { get; private set; } 360 public bool Normalized55FPS { get; private set; }
391 361
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; }
399
400 /// <summary>
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.
403 /// </summary>
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; }
409
410 private int m_update_physics = 1; 362 private int m_update_physics = 1;
411 private int m_update_entitymovement = 1; 363 private int m_update_entitymovement = 1;
412 private int m_update_objects = 1; 364 private int m_update_objects = 1;
413 private int m_update_presences = 1; // Update scene presence movements 365 private int m_update_presences = 1; // Update scene presence movements
414 private int m_update_events = 1; 366 private int m_update_events = 1;
415 private int m_update_backup = 200; 367 private int m_update_backup = 200;
416 private int m_update_terrain = 50; 368
417 // private int m_update_land = 1; 369 private int m_update_terrain = 1000;
418 private int m_update_coarse_locations = 50; 370
371 private int m_update_coarse_locations = 5;
419 private int m_update_temp_cleaning = 180; 372 private int m_update_temp_cleaning = 180;
420 373
421 private int agentMS; 374 private float agentMS;
422 private int frameMS; 375 private float frameMS;
423 private int physicsMS2; 376 private float physicsMS2;
424 private int physicsMS; 377 private float physicsMS;
425 private int otherMS; 378 private float otherMS;
426 private int tempOnRezMS; 379 private float tempOnRezMS;
427 private int eventMS; 380 private float eventMS;
428 private int backupMS; 381 private float backupMS;
429 private int terrainMS; 382 private float terrainMS;
430 private int landMS; 383 private float landMS;
431 private int spareMS;
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 384
444 /// <summary> 385 /// <summary>
445 /// Tick at which the last frame was processed. 386 /// Tick at which the last frame was processed.
@@ -447,11 +388,6 @@ namespace OpenSim.Region.Framework.Scenes
447 private int m_lastFrameTick; 388 private int m_lastFrameTick;
448 389
449 /// <summary> 390 /// <summary>
450 /// Tick at which the last maintenance run occurred.
451 /// </summary>
452 private int m_lastMaintenanceTick;
453
454 /// <summary>
455 /// Total script execution time (in Stopwatch Ticks) since the last frame 391 /// Total script execution time (in Stopwatch Ticks) since the last frame
456 /// </summary> 392 /// </summary>
457 private long m_scriptExecutionTime = 0; 393 private long m_scriptExecutionTime = 0;
@@ -461,23 +397,19 @@ namespace OpenSim.Region.Framework.Scenes
461 /// asynchronously from the update loop. 397 /// asynchronously from the update loop.
462 /// </summary> 398 /// </summary>
463 private bool m_cleaningTemps = false; 399 private bool m_cleaningTemps = false;
400 private bool m_sendingCoarseLocations = false; // same for async course locations sending
464 401
465 /// <summary> 402 /// <summary>
466 /// Used to control main scene thread looping time when not updating via timer. 403 /// Used to control main scene thread looping time when not updating via timer.
467 /// </summary> 404 /// </summary>
468 private ManualResetEvent m_updateWaitEvent = new ManualResetEvent(false); 405 private ManualResetEvent m_updateWaitEvent = new ManualResetEvent(false);
469 406
470 /// <summary>
471 /// Used to control maintenance thread runs.
472 /// </summary>
473 private ManualResetEvent m_maintenanceWaitEvent = new ManualResetEvent(false);
474
475 // TODO: Possibly stop other classes being able to manipulate this directly. 407 // TODO: Possibly stop other classes being able to manipulate this directly.
476 private SceneGraph m_sceneGraph; 408 private SceneGraph m_sceneGraph;
477 private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing 409 private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing
478 private volatile bool m_backingup; 410 private volatile bool m_backingup;
479 private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>(); 411 private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>();
480 private Dictionary<UUID, SceneObjectGroup> m_groupsWithTargets = new Dictionary<UUID, SceneObjectGroup>(); 412 private Dictionary<UUID, int> m_groupsWithTargets = new Dictionary<UUID, int>();
481 413
482 private string m_defaultScriptEngine; 414 private string m_defaultScriptEngine;
483 415
@@ -492,6 +424,11 @@ namespace OpenSim.Region.Framework.Scenes
492 /// </summary> 424 /// </summary>
493 private int m_LastLogin; 425 private int m_LastLogin;
494 426
427 private int m_lastIncoming;
428 private int m_lastOutgoing;
429 private int m_hbRestarts = 0;
430
431
495 /// <summary> 432 /// <summary>
496 /// Thread that runs the scene loop. 433 /// Thread that runs the scene loop.
497 /// </summary> 434 /// </summary>
@@ -510,7 +447,7 @@ namespace OpenSim.Region.Framework.Scenes
510 /// Is the scene active? 447 /// Is the scene active?
511 /// </summary> 448 /// </summary>
512 /// <remarks> 449 /// <remarks>
513 /// If false, maintenance and update loops are not being run, though after setting to false update may still 450 /// If false, update loop is 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 451 /// be active for a period (and IsRunning will still be true). Updates can still be triggered manually if
515 /// the scene is not active. 452 /// the scene is not active.
516 /// </remarks> 453 /// </remarks>
@@ -540,9 +477,21 @@ namespace OpenSim.Region.Framework.Scenes
540 public bool IsRunning { get { return m_isRunning; } } 477 public bool IsRunning { get { return m_isRunning; } }
541 private volatile bool m_isRunning; 478 private volatile bool m_isRunning;
542 479
480 private bool m_firstHeartbeat = true;
481
482// private UpdatePrioritizationSchemes m_priorityScheme = UpdatePrioritizationSchemes.Time;
483// private bool m_reprioritizationEnabled = true;
484// private double m_reprioritizationInterval = 5000.0;
485// private double m_rootReprioritizationDistance = 10.0;
486// private double m_childReprioritizationDistance = 20.0;
487
488
543 private Timer m_mapGenerationTimer = new Timer(); 489 private Timer m_mapGenerationTimer = new Timer();
544 private bool m_generateMaptiles; 490 private bool m_generateMaptiles;
545 491
492 protected int m_lastHealth = -1;
493 protected int m_lastUsers = -1;
494
546 #endregion Fields 495 #endregion Fields
547 496
548 #region Properties 497 #region Properties
@@ -571,6 +520,19 @@ namespace OpenSim.Region.Framework.Scenes
571 get { return m_sceneGridService; } 520 get { return m_sceneGridService; }
572 } 521 }
573 522
523 public ISnmpModule SnmpService
524 {
525 get
526 {
527 if (m_snmpService == null)
528 {
529 m_snmpService = RequestModuleInterface<ISnmpModule>();
530 }
531
532 return m_snmpService;
533 }
534 }
535
574 public ISimulationDataService SimulationDataService 536 public ISimulationDataService SimulationDataService
575 { 537 {
576 get 538 get
@@ -777,22 +739,25 @@ namespace OpenSim.Region.Framework.Scenes
777 get { return m_capsModule; } 739 get { return m_capsModule; }
778 } 740 }
779 741
780 public int MonitorFrameTime { get { return frameMS; } } 742 public int MonitorFrameTime { get { return (int)frameMS; } }
781 public int MonitorPhysicsUpdateTime { get { return physicsMS; } } 743 public int MonitorPhysicsUpdateTime { get { return (int)physicsMS; } }
782 public int MonitorPhysicsSyncTime { get { return physicsMS2; } } 744 public int MonitorPhysicsSyncTime { get { return (int)physicsMS2; } }
783 public int MonitorOtherTime { get { return otherMS; } } 745 public int MonitorOtherTime { get { return (int)otherMS; } }
784 public int MonitorTempOnRezTime { get { return tempOnRezMS; } } 746 public int MonitorTempOnRezTime { get { return (int)tempOnRezMS; } }
785 public int MonitorEventTime { get { return eventMS; } } // This may need to be divided into each event? 747 public int MonitorEventTime { get { return (int)eventMS; } } // This may need to be divided into each event?
786 public int MonitorBackupTime { get { return backupMS; } } 748 public int MonitorBackupTime { get { return (int)backupMS; } }
787 public int MonitorTerrainTime { get { return terrainMS; } } 749 public int MonitorTerrainTime { get { return (int)terrainMS; } }
788 public int MonitorLandTime { get { return landMS; } } 750 public int MonitorLandTime { get { return (int)landMS; } }
789 public int MonitorLastFrameTick { get { return m_lastFrameTick; } } 751 public int MonitorLastFrameTick { get { return m_lastFrameTick; } }
790 752
791 public UpdatePrioritizationSchemes UpdatePrioritizationScheme { get; set; } 753 public UpdatePrioritizationSchemes UpdatePrioritizationScheme { get; set; }
792 public bool IsReprioritizationEnabled { get; set; } 754 public bool IsReprioritizationEnabled { get; set; }
793 public double ReprioritizationInterval { get; set; } 755 public float ReprioritizationInterval { get; set; }
794 public double RootReprioritizationDistance { get; set; } 756 public float ReprioritizationDistance { get; set; }
795 public double ChildReprioritizationDistance { get; set; } 757 private float m_minReprioritizationDistance = 32f;
758 public bool ObjectsCullingByDistance = false;
759
760 private ExpiringCache<UUID, UUID> TeleportTargetsCoolDown = new ExpiringCache<UUID, UUID>();
796 761
797 public AgentCircuitManager AuthenticateHandler 762 public AgentCircuitManager AuthenticateHandler
798 { 763 {
@@ -857,17 +822,16 @@ namespace OpenSim.Region.Framework.Scenes
857 822
858 #region Constructors 823 #region Constructors
859 824
860 public Scene(RegionInfo regInfo, AgentCircuitManager authen, 825 public Scene(RegionInfo regInfo, AgentCircuitManager authen,
861 ISimulationDataService simDataService, IEstateDataService estateDataService, 826 ISimulationDataService simDataService, IEstateDataService estateDataService,
862 IConfigSource config, string simulatorVersion) 827 IConfigSource config, string simulatorVersion)
863 : this(regInfo) 828 : this(regInfo)
864 { 829 {
865 m_config = config; 830 m_config = config;
866 MinFrameTicks = 89; 831 FrameTime = 0.0908f;
867 FrameTimeWarnPercent = 60; 832 FrameTimeWarnPercent = 60;
868 FrameTimeCritPercent = 40; 833 FrameTimeCritPercent = 40;
869 Normalized55FPS = true; 834 Normalized55FPS = true;
870 MinMaintenanceTicks = 1000;
871 SeeIntoRegion = true; 835 SeeIntoRegion = true;
872 836
873 Random random = new Random(); 837 Random random = new Random();
@@ -878,6 +842,9 @@ namespace OpenSim.Region.Framework.Scenes
878 m_SimulationDataService = simDataService; 842 m_SimulationDataService = simDataService;
879 m_EstateDataService = estateDataService; 843 m_EstateDataService = estateDataService;
880 844
845 m_lastIncoming = 0;
846 m_lastOutgoing = 0;
847
881 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this); 848 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
882 m_asyncSceneObjectDeleter.Enabled = true; 849 m_asyncSceneObjectDeleter.Enabled = true;
883 850
@@ -935,9 +902,9 @@ namespace OpenSim.Region.Framework.Scenes
935 EventManager.OnLandObjectRemoved += 902 EventManager.OnLandObjectRemoved +=
936 new EventManager.LandObjectRemoved(simDataService.RemoveLandObject); 903 new EventManager.LandObjectRemoved(simDataService.RemoveLandObject);
937 904
938 RegisterDefaultSceneEvents(); 905 RegisterDefaultSceneEvents();
939 906
940 // XXX: Don't set the public property since we don't want to activate here. This needs to be handled 907 // XXX: Don't set the public property since we don't want to activate here. This needs to be handled
941 // better in the future. 908 // better in the future.
942 m_scripts_enabled = !RegionInfo.RegionSettings.DisableScripts; 909 m_scripts_enabled = !RegionInfo.RegionSettings.DisableScripts;
943 910
@@ -956,6 +923,18 @@ namespace OpenSim.Region.Framework.Scenes
956 StartDisabled = startupConfig.GetBoolean("StartDisabled", false); 923 StartDisabled = startupConfig.GetBoolean("StartDisabled", false);
957 924
958 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance", m_defaultDrawDistance); 925 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance", m_defaultDrawDistance);
926 m_maxDrawDistance = startupConfig.GetFloat("MaxDrawDistance", m_maxDrawDistance);
927 m_maxRegionViewDistance = startupConfig.GetFloat("MaxRegionsViewDistance", m_maxRegionViewDistance);
928
929 // old versions compatibility
930 LegacySitOffsets = startupConfig.GetBoolean("LegacySitOffsets", LegacySitOffsets);
931
932 if (m_defaultDrawDistance > m_maxDrawDistance)
933 m_defaultDrawDistance = m_maxDrawDistance;
934
935 if (m_maxRegionViewDistance > m_maxDrawDistance)
936 m_maxRegionViewDistance = m_maxDrawDistance;
937
959 UseBackup = startupConfig.GetBoolean("UseSceneBackup", UseBackup); 938 UseBackup = startupConfig.GetBoolean("UseSceneBackup", UseBackup);
960 if (!UseBackup) 939 if (!UseBackup)
961 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName); 940 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName);
@@ -967,9 +946,8 @@ namespace OpenSim.Region.Framework.Scenes
967 946
968 MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20); 947 MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20);
969 948
970 PhysicalPrims = startupConfig.GetBoolean("physical_prim", PhysicalPrims); 949 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true);
971 CollidablePrims = startupConfig.GetBoolean("collidable_prim", CollidablePrims); 950 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
972
973 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys); 951 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys);
974 if (RegionInfo.NonphysPrimMin > 0) 952 if (RegionInfo.NonphysPrimMin > 0)
975 { 953 {
@@ -989,11 +967,24 @@ namespace OpenSim.Region.Framework.Scenes
989 } 967 }
990 968
991 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys); 969 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys);
970
992 if (RegionInfo.PhysPrimMax > 0) 971 if (RegionInfo.PhysPrimMax > 0)
993 { 972 {
994 m_maxPhys = RegionInfo.PhysPrimMax; 973 m_maxPhys = RegionInfo.PhysPrimMax;
995 } 974 }
996 975
976 m_linksetCapacity = startupConfig.GetInt("LinksetPrims", m_linksetCapacity);
977 if (RegionInfo.LinksetCapacity > 0)
978 {
979 m_linksetCapacity = RegionInfo.LinksetCapacity;
980 }
981
982 m_linksetPhysCapacity = startupConfig.GetInt("LinksetPhysPrims", m_linksetPhysCapacity);
983
984
985 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest");
986 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false);
987
997 // Here, if clamping is requested in either global or 988 // Here, if clamping is requested in either global or
998 // local config, it will be used 989 // local config, it will be used
999 // 990 //
@@ -1003,13 +994,9 @@ namespace OpenSim.Region.Framework.Scenes
1003 m_clampPrimSize = true; 994 m_clampPrimSize = true;
1004 } 995 }
1005 996
1006 m_linksetCapacity = startupConfig.GetInt("LinksetPrims", m_linksetCapacity); 997 m_clampNegativeZ = startupConfig.GetBoolean("ClampNegativeZ", m_clampNegativeZ);
1007 if (RegionInfo.LinksetCapacity > 0)
1008 {
1009 m_linksetCapacity = RegionInfo.LinksetCapacity;
1010 }
1011 998
1012 m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete", m_useTrashOnDelete); 999 m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete",m_useTrashOnDelete);
1013 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries); 1000 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries);
1014 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings); 1001 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings);
1015 m_dontPersistBefore = 1002 m_dontPersistBefore =
@@ -1020,11 +1007,10 @@ namespace OpenSim.Region.Framework.Scenes
1020 m_persistAfter *= 10000000; 1007 m_persistAfter *= 10000000;
1021 1008
1022 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 1009 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
1023 1010 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
1024 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest");
1025 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false);
1026 1011
1027 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 1012 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
1013 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
1028 1014
1029 string[] possibleMapConfigSections = new string[] { "Map", "Startup" }; 1015 string[] possibleMapConfigSections = new string[] { "Map", "Startup" };
1030 1016
@@ -1070,7 +1056,7 @@ namespace OpenSim.Region.Framework.Scenes
1070 1056
1071 if (grant.Length > 0) 1057 if (grant.Length > 0)
1072 { 1058 {
1073 foreach (string viewer in grant.Split('|')) 1059 foreach (string viewer in grant.Split(','))
1074 { 1060 {
1075 m_AllowedViewers.Add(viewer.Trim().ToLower()); 1061 m_AllowedViewers.Add(viewer.Trim().ToLower());
1076 } 1062 }
@@ -1086,17 +1072,16 @@ namespace OpenSim.Region.Framework.Scenes
1086 1072
1087 if (grant.Length > 0) 1073 if (grant.Length > 0)
1088 { 1074 {
1089 foreach (string viewer in grant.Split('|')) 1075 foreach (string viewer in grant.Split(','))
1090 { 1076 {
1091 m_BannedViewers.Add(viewer.Trim().ToLower()); 1077 m_BannedViewers.Add(viewer.Trim().ToLower());
1092 } 1078 }
1093 } 1079 }
1094 1080
1095 if (startupConfig.Contains("MinFrameTime")) 1081 FrameTime = startupConfig.GetFloat( "FrameTime", FrameTime);
1096 MinFrameTicks = (int)(startupConfig.GetFloat("MinFrameTime") * 1000);
1097 FrameTimeWarnPercent = startupConfig.GetInt( "FrameTimeWarnPercent", FrameTimeWarnPercent); 1082 FrameTimeWarnPercent = startupConfig.GetInt( "FrameTimeWarnPercent", FrameTimeWarnPercent);
1098 FrameTimeCritPercent = startupConfig.GetInt( "FrameTimeCritPercent", FrameTimeCritPercent); 1083 FrameTimeCritPercent = startupConfig.GetInt( "FrameTimeCritPercent", FrameTimeCritPercent);
1099 Normalized55FPS = startupConfig.GetBoolean( "Normalized55FPS", Normalized55FPS); 1084 Normalized55FPS = startupConfig.GetBoolean( "Normalized55FPS", Normalized55FPS);
1100 1085
1101 m_update_backup = startupConfig.GetInt("UpdateStorageEveryNFrames", m_update_backup); 1086 m_update_backup = startupConfig.GetInt("UpdateStorageEveryNFrames", m_update_backup);
1102 m_update_coarse_locations = startupConfig.GetInt("UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations); 1087 m_update_coarse_locations = startupConfig.GetInt("UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations);
@@ -1108,21 +1093,6 @@ namespace OpenSim.Region.Framework.Scenes
1108 m_update_terrain = startupConfig.GetInt("UpdateTerrainEveryNFrames", m_update_terrain); 1093 m_update_terrain = startupConfig.GetInt("UpdateTerrainEveryNFrames", m_update_terrain);
1109 m_update_temp_cleaning = startupConfig.GetInt("UpdateTempCleaningEveryNSeconds", m_update_temp_cleaning); 1094 m_update_temp_cleaning = startupConfig.GetInt("UpdateTempCleaningEveryNSeconds", m_update_temp_cleaning);
1110 1095
1111 if (startupConfig.Contains("ShouldUseFireAndForgetForCollisions"))
1112 {
1113 ShouldUseFireAndForgetForCollisions = startupConfig.GetBoolean("ShouldUseFireAndForgetForCollisions", false);
1114 }
1115 }
1116
1117
1118 // FIXME: Ultimately this should be in a module.
1119 SendPeriodicAppearanceUpdates = false;
1120
1121 IConfig appearanceConfig = m_config.Configs["Appearance"];
1122 if (appearanceConfig != null)
1123 {
1124 SendPeriodicAppearanceUpdates
1125 = appearanceConfig.GetBoolean("ResendAppearanceUpdates", SendPeriodicAppearanceUpdates);
1126 } 1096 }
1127 1097
1128 #endregion Region Config 1098 #endregion Region Config
@@ -1131,6 +1101,7 @@ namespace OpenSim.Region.Framework.Scenes
1131 if (entityTransferConfig != null) 1101 if (entityTransferConfig != null)
1132 { 1102 {
1133 AllowAvatarCrossing = entityTransferConfig.GetBoolean("AllowAvatarCrossing", AllowAvatarCrossing); 1103 AllowAvatarCrossing = entityTransferConfig.GetBoolean("AllowAvatarCrossing", AllowAvatarCrossing);
1104 DisableObjectTransfer = entityTransferConfig.GetBoolean("DisableObjectTransfer", false);
1134 } 1105 }
1135 1106
1136 #region Interest Management 1107 #region Interest Management
@@ -1153,60 +1124,95 @@ namespace OpenSim.Region.Framework.Scenes
1153 IsReprioritizationEnabled 1124 IsReprioritizationEnabled
1154 = interestConfig.GetBoolean("ReprioritizationEnabled", IsReprioritizationEnabled); 1125 = interestConfig.GetBoolean("ReprioritizationEnabled", IsReprioritizationEnabled);
1155 ReprioritizationInterval 1126 ReprioritizationInterval
1156 = interestConfig.GetDouble("ReprioritizationInterval", ReprioritizationInterval); 1127 = interestConfig.GetFloat("ReprioritizationInterval", ReprioritizationInterval);
1157 RootReprioritizationDistance 1128 ReprioritizationDistance
1158 = interestConfig.GetDouble("RootReprioritizationDistance", RootReprioritizationDistance); 1129 = interestConfig.GetFloat("RootReprioritizationDistance", ReprioritizationDistance);
1159 ChildReprioritizationDistance
1160 = interestConfig.GetDouble("ChildReprioritizationDistance", ChildReprioritizationDistance);
1161 1130
1162 RootTerseUpdatePeriod = interestConfig.GetInt("RootTerseUpdatePeriod", RootTerseUpdatePeriod); 1131 if(ReprioritizationDistance < m_minReprioritizationDistance)
1163 ChildTerseUpdatePeriod = interestConfig.GetInt("ChildTerseUpdatePeriod", ChildTerseUpdatePeriod); 1132 ReprioritizationDistance = m_minReprioritizationDistance;
1133
1134 ObjectsCullingByDistance
1135 = interestConfig.GetBoolean("ObjectsCullingByDistance", ObjectsCullingByDistance);
1164 1136
1165 RootPositionUpdateTolerance
1166 = interestConfig.GetFloat("RootPositionUpdateTolerance", RootPositionUpdateTolerance);
1167 RootRotationUpdateTolerance
1168 = interestConfig.GetFloat("RootRotationUpdateTolerance", RootRotationUpdateTolerance);
1169 RootVelocityUpdateTolerance
1170 = interestConfig.GetFloat("RootVelocityUpdateTolerance", RootVelocityUpdateTolerance);
1171 } 1137 }
1172 1138
1173 m_log.DebugFormat("[SCENE]: Using the {0} prioritization scheme", UpdatePrioritizationScheme); 1139 m_log.DebugFormat("[SCENE]: Using the {0} prioritization scheme", UpdatePrioritizationScheme);
1174 1140
1175 #endregion Interest Management 1141 #endregion Interest Management
1176 1142
1177 // The timer used by the Stopwatch class depends on the system hardware and operating system; inform 1143 #region Group
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 1144
1185 // Acquire the statistics section of the OpenSim.ini file located 1145 IConfig groupsConfig = m_config.Configs["Groups"];
1186 // in the bin directory 1146 m_AutoGroups = new Dictionary<string, string[]>();
1187 IConfig statisticsConfig = m_config.Configs["Statistics"]; 1147 if (groupsConfig != null)
1188
1189 // Confirm that the statistics section existed in the configuration
1190 // file
1191 if (statisticsConfig != null)
1192 { 1148 {
1193 // Create the StatsReporter using the number of frames to store 1149 string groups = groupsConfig.GetString("AddDefaultGroup", string.Empty);
1194 // for the frame time statistics, or 10 frames if the config 1150 if (groups.Length > 0)
1195 // file doesn't contain a value 1151 {
1196 StatsReporter = new SimStatsReporter(this, 1152 try
1197 statisticsConfig.GetInt("NumberOfFrames", 1153 {
1198 m_defaultNumberFramesStored)); 1154 m_AutoGroups.Add("local", groups.Split('|'));
1199 } 1155 }
1200 else 1156 catch (ArgumentException)
1201 { 1157 {
1202 // Create a StatsReporter with the current scene and a default 1158 m_log.Warn("[SCENE]: Duplicated AddDefaultGroup option.");
1203 // 10 frames stored for the frame time statistics 1159 }
1204 StatsReporter = new SimStatsReporter(this); 1160 }
1161 string[] keys = groupsConfig.GetKeys();
1162 if (0 < keys.Length)
1163 {
1164 foreach (string k in keys)
1165 {
1166 if (k.StartsWith("AddHGDefaultGroup_"))
1167 {
1168 groups = groupsConfig.GetString(k, string.Empty);
1169 if (groups.Length > 0)
1170 {
1171 try
1172 {
1173 m_AutoGroups.Add(k.Substring(18), groups.Split('|'));
1174 }
1175 catch (ArgumentException)
1176 {
1177 m_log.WarnFormat("[SCENE]: Duplicated {0} option.", k);
1178 }
1179 }
1180 }
1181 }
1182 }
1205 } 1183 }
1206 1184
1185 #endregion Group
1186
1187 StatsReporter = new SimStatsReporter(this);
1188
1207 StatsReporter.OnSendStatsResult += SendSimStatsPackets; 1189 StatsReporter.OnSendStatsResult += SendSimStatsPackets;
1208 StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats; 1190 StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats;
1209 1191
1192 IConfig restartConfig = config.Configs["RestartModule"];
1193 if (restartConfig != null)
1194 {
1195 string markerPath = restartConfig.GetString("MarkerPath", String.Empty);
1196
1197 if (markerPath != String.Empty)
1198 {
1199 string path = Path.Combine(markerPath, RegionInfo.RegionID.ToString() + ".started");
1200 try
1201 {
1202 string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
1203 FileStream fs = File.Create(path);
1204 System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
1205 Byte[] buf = enc.GetBytes(pidstring);
1206 fs.Write(buf, 0, buf.Length);
1207 fs.Close();
1208 }
1209 catch (Exception)
1210 {
1211 }
1212 }
1213 }
1214
1215 StartTimerWatchdog();
1210 } 1216 }
1211 1217
1212 public Scene(RegionInfo regInfo) 1218 public Scene(RegionInfo regInfo)
@@ -1240,15 +1246,12 @@ namespace OpenSim.Region.Framework.Scenes
1240 UpdatePrioritizationScheme = UpdatePrioritizationSchemes.Time; 1246 UpdatePrioritizationScheme = UpdatePrioritizationSchemes.Time;
1241 ReprioritizationInterval = 5000; 1247 ReprioritizationInterval = 5000;
1242 1248
1243 RootRotationUpdateTolerance = 0.1f; 1249 ReprioritizationDistance = m_minReprioritizationDistance;
1244 RootVelocityUpdateTolerance = 0.001f;
1245 RootPositionUpdateTolerance = 0.05f;
1246 RootReprioritizationDistance = 10.0;
1247 ChildReprioritizationDistance = 20.0;
1248 1250
1249 m_eventManager = new EventManager(); 1251 m_eventManager = new EventManager();
1250 1252
1251 m_permissions = new ScenePermissions(this); 1253 m_permissions = new ScenePermissions(this);
1254
1252 } 1255 }
1253 1256
1254 #endregion 1257 #endregion
@@ -1285,7 +1288,6 @@ namespace OpenSim.Region.Framework.Scenes
1285 if (!fm.TryGetFeature("OpenSimExtras", out openSimExtras)) 1288 if (!fm.TryGetFeature("OpenSimExtras", out openSimExtras))
1286 openSimExtras = new OSDMap(); 1289 openSimExtras = new OSDMap();
1287 1290
1288 float FrameTime = MinFrameTicks / 1000.0f;
1289 float statisticsFPSfactor = 1.0f; 1291 float statisticsFPSfactor = 1.0f;
1290 if(Normalized55FPS) 1292 if(Normalized55FPS)
1291 statisticsFPSfactor = 55.0f * FrameTime; 1293 statisticsFPSfactor = 55.0f * FrameTime;
@@ -1302,7 +1304,7 @@ namespace OpenSim.Region.Framework.Scenes
1302 1304
1303 protected virtual void RegisterDefaultSceneEvents() 1305 protected virtual void RegisterDefaultSceneEvents()
1304 { 1306 {
1305 m_eventManager.OnSignificantClientMovement += HandleOnSignificantClientMovement; 1307// m_eventManager.OnSignificantClientMovement += HandleOnSignificantClientMovement;
1306 } 1308 }
1307 1309
1308 public override string GetSimulatorVersion() 1310 public override string GetSimulatorVersion()
@@ -1325,20 +1327,8 @@ namespace OpenSim.Region.Framework.Scenes
1325 { 1327 {
1326 if (RegionInfo.RegionHandle != otherRegion.RegionHandle) 1328 if (RegionInfo.RegionHandle != otherRegion.RegionHandle)
1327 { 1329 {
1328 //// If these are cast to INT because long + negative values + abs returns invalid data
1329 //int resultX = Math.Abs((int)xcell - (int)RegionInfo.RegionLocX);
1330 //int resultY = Math.Abs((int)ycell - (int)RegionInfo.RegionLocY);
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 1330
1341 if (!Util.IsOutsideView(dist, thisRegionX, newRegionX, thisRegionY, newRegionY)) 1331 if (isNeighborRegion(otherRegion))
1342 { 1332 {
1343 // Let the grid service module know, so this can be cached 1333 // Let the grid service module know, so this can be cached
1344 m_eventManager.TriggerOnRegionUp(otherRegion); 1334 m_eventManager.TriggerOnRegionUp(otherRegion);
@@ -1373,6 +1363,21 @@ namespace OpenSim.Region.Framework.Scenes
1373 } 1363 }
1374 } 1364 }
1375 1365
1366 public bool isNeighborRegion(GridRegion otherRegion)
1367 {
1368 int tmp = otherRegion.RegionLocX - (int)RegionInfo.WorldLocX; ;
1369
1370 if (tmp < -otherRegion.RegionSizeX && tmp > RegionInfo.RegionSizeX)
1371 return false;
1372
1373 tmp = otherRegion.RegionLocY - (int)RegionInfo.WorldLocY;
1374
1375 if (tmp < -otherRegion.RegionSizeY && tmp > RegionInfo.RegionSizeY)
1376 return false;
1377
1378 return true;
1379 }
1380
1376 public void AddNeighborRegion(RegionInfo region) 1381 public void AddNeighborRegion(RegionInfo region)
1377 { 1382 {
1378 lock (m_neighbours) 1383 lock (m_neighbours)
@@ -1475,13 +1480,24 @@ namespace OpenSim.Region.Framework.Scenes
1475 return; 1480 return;
1476 } 1481 }
1477 1482
1483 IEtcdModule etcd = RequestModuleInterface<IEtcdModule>();
1484 if (etcd != null)
1485 {
1486 etcd.Delete("Health");
1487 etcd.Delete("HealthFlags");
1488 etcd.Delete("RootAgents");
1489 }
1490
1478 m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName); 1491 m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName);
1479 1492
1480 StatsReporter.Close();
1481 1493
1494 StatsReporter.Close();
1482 m_restartTimer.Stop(); 1495 m_restartTimer.Stop();
1483 m_restartTimer.Close(); 1496 m_restartTimer.Close();
1484 1497
1498 if (!GridService.DeregisterRegion(RegionInfo.RegionID))
1499 m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name);
1500
1485 // Kick all ROOT agents with the message, 'The simulator is going down' 1501 // Kick all ROOT agents with the message, 'The simulator is going down'
1486 ForEachScenePresence(delegate(ScenePresence avatar) 1502 ForEachScenePresence(delegate(ScenePresence avatar)
1487 { 1503 {
@@ -1504,13 +1520,15 @@ namespace OpenSim.Region.Framework.Scenes
1504 // Stop all client threads. 1520 // Stop all client threads.
1505 ForEachScenePresence(delegate(ScenePresence avatar) { CloseAgent(avatar.UUID, false); }); 1521 ForEachScenePresence(delegate(ScenePresence avatar) { CloseAgent(avatar.UUID, false); });
1506 1522
1507 m_log.Debug("[SCENE]: Persisting changed objects"); 1523 m_log.Debug("[SCENE]: TriggerSceneShuttingDown");
1508 EventManager.TriggerSceneShuttingDown(this); 1524 EventManager.TriggerSceneShuttingDown(this);
1509 Backup(false);
1510 m_sceneGraph.Close();
1511 1525
1512 if (!GridService.DeregisterRegion(RegionInfo.RegionID)) 1526 m_log.Debug("[SCENE]: Persisting changed objects");
1513 m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name); 1527 Backup(true);
1528
1529 m_log.Debug("[SCENE]: Closing scene");
1530
1531 m_sceneGraph.Close();
1514 1532
1515 base.Close(); 1533 base.Close();
1516 1534
@@ -1519,6 +1537,7 @@ namespace OpenSim.Region.Framework.Scenes
1519 // attempt to reference a null or disposed physics scene. 1537 // attempt to reference a null or disposed physics scene.
1520 if (PhysicsScene != null) 1538 if (PhysicsScene != null)
1521 { 1539 {
1540 m_log.Debug("[SCENE]: Dispose Physics");
1522 PhysicsScene phys = PhysicsScene; 1541 PhysicsScene phys = PhysicsScene;
1523 // remove the physics engine from both Scene and SceneGraph 1542 // remove the physics engine from both Scene and SceneGraph
1524 PhysicsScene = null; 1543 PhysicsScene = null;
@@ -1537,7 +1556,7 @@ namespace OpenSim.Region.Framework.Scenes
1537 /// </summary> 1556 /// </summary>
1538 /// <param name='startScripts'> 1557 /// <param name='startScripts'>
1539 /// Start the scripts within the scene. 1558 /// Start the scripts within the scene.
1540 /// </param> 1559 /// </param>
1541 public void Start(bool startScripts) 1560 public void Start(bool startScripts)
1542 { 1561 {
1543 if (IsRunning) 1562 if (IsRunning)
@@ -1550,10 +1569,31 @@ namespace OpenSim.Region.Framework.Scenes
1550// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); 1569// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName);
1551 if (m_heartbeatThread != null) 1570 if (m_heartbeatThread != null)
1552 { 1571 {
1572 m_hbRestarts++;
1573 if(m_hbRestarts > 10)
1574 Environment.Exit(1);
1575 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1576
1577//int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
1578//System.Diagnostics.Process proc = new System.Diagnostics.Process();
1579//proc.EnableRaisingEvents=false;
1580//proc.StartInfo.FileName = "/bin/kill";
1581//proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
1582//proc.Start();
1583//proc.WaitForExit();
1584//Thread.Sleep(1000);
1585//Environment.Exit(1);
1553 m_heartbeatThread.Abort(); 1586 m_heartbeatThread.Abort();
1587 Watchdog.AbortThread(m_heartbeatThread.ManagedThreadId);
1554 m_heartbeatThread = null; 1588 m_heartbeatThread = null;
1555 } 1589 }
1556 1590
1591 GC.Collect();
1592 GC.WaitForPendingFinalizers();
1593 GC.Collect();
1594 // tell physics to finish building actor
1595 m_sceneGraph.ProcessPhysicsPreSimulation();
1596
1557 m_heartbeatThread 1597 m_heartbeatThread
1558 = WorkManager.StartThread( 1598 = WorkManager.StartThread(
1559 Heartbeat, string.Format("Heartbeat-({0})", RegionInfo.RegionName.Replace(" ", "_")), ThreadPriority.Normal, false, false); 1599 Heartbeat, string.Format("Heartbeat-({0})", RegionInfo.RegionName.Replace(" ", "_")), ThreadPriority.Normal, false, false);
@@ -1596,136 +1636,13 @@ namespace OpenSim.Region.Framework.Scenes
1596 // alarms for scenes with many objects. 1636 // alarms for scenes with many objects.
1597 Update(1); 1637 Update(1);
1598 1638
1599 WorkManager.StartThread(
1600 Maintenance, string.Format("Maintenance ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, true);
1601
1602 Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true; 1639 Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true;
1603 m_lastFrameTick = Util.EnvironmentTickCount(); 1640 m_lastFrameTick = Util.EnvironmentTickCount();
1604 1641 Update(-1);
1605 if (UpdateOnTimer)
1606 {
1607 m_sceneUpdateTimer = new Timer(MinFrameTicks);
1608 m_sceneUpdateTimer.AutoReset = true;
1609 m_sceneUpdateTimer.Elapsed += Update;
1610 m_sceneUpdateTimer.Start();
1611 }
1612 else
1613 {
1614 Thread.CurrentThread.Priority = ThreadPriority.Highest;
1615 Update(-1);
1616 Watchdog.RemoveThread();
1617 m_isRunning = false;
1618 }
1619 }
1620
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;
1642 }
1643
1644 private void Maintenance()
1645 {
1646 DoMaintenance(-1);
1647
1648 Watchdog.RemoveThread(); 1642 Watchdog.RemoveThread();
1649 } 1643 }
1650 1644
1651 public void DoMaintenance(int runs) 1645 public override void Update(int frames)
1652 {
1653 long? endRun = null;
1654 int runtc, tmpMS;
1655 int previousMaintenanceTick;
1656
1657 if (runs >= 0)
1658 endRun = MaintenanceRun + runs;
1659
1660 List<Vector3> coarseLocations;
1661 List<UUID> avatarUUIDs;
1662
1663 while (!m_shuttingDown && ((endRun == null && Active) || MaintenanceRun < endRun))
1664 {
1665 runtc = Util.EnvironmentTickCount();
1666 ++MaintenanceRun;
1667
1668 // m_log.DebugFormat("[SCENE]: Maintenance run {0} in {1}", MaintenanceRun, Name);
1669
1670 // Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client)
1671 if (MaintenanceRun % (m_update_coarse_locations / 10) == 0)
1672 {
1673 SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60);
1674 // Send coarse locations to clients
1675 ForEachScenePresence(delegate(ScenePresence presence)
1676 {
1677 presence.SendCoarseLocations(coarseLocations, avatarUUIDs);
1678 });
1679 }
1680
1681 if (SendPeriodicAppearanceUpdates && MaintenanceRun % 60 == 0)
1682 {
1683 // m_log.DebugFormat("[SCENE]: Sending periodic appearance updates");
1684
1685 if (AvatarFactory != null)
1686 {
1687 ForEachRootScenePresence(sp => AvatarFactory.SendAppearance(sp.UUID));
1688 }
1689 }
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
1706 Watchdog.UpdateThread();
1707
1708 previousMaintenanceTick = m_lastMaintenanceTick;
1709 m_lastMaintenanceTick = Util.EnvironmentTickCount();
1710 runtc = Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, runtc);
1711 runtc = MinMaintenanceTicks - runtc;
1712
1713 if (runtc > 0)
1714 m_maintenanceWaitEvent.WaitOne(runtc);
1715
1716 // Optionally warn if a frame takes double the amount of time that it should.
1717 if (DebugUpdates
1718 && Util.EnvironmentTickCountSubtract(
1719 m_lastMaintenanceTick, previousMaintenanceTick) > MinMaintenanceTicks * 2)
1720 m_log.WarnFormat(
1721 "[SCENE]: Maintenance took {0} ms (desired max {1} ms) in {2}",
1722 Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, previousMaintenanceTick),
1723 MinMaintenanceTicks,
1724 RegionInfo.RegionName);
1725 }
1726 }
1727
1728 public override bool Update(int frames)
1729 { 1646 {
1730 long? endFrame = null; 1647 long? endFrame = null;
1731 1648
@@ -1733,119 +1650,97 @@ namespace OpenSim.Region.Framework.Scenes
1733 endFrame = Frame + frames; 1650 endFrame = Frame + frames;
1734 1651
1735 float physicsFPS = 0f; 1652 float physicsFPS = 0f;
1736 int previousFrameTick, tmpMS; 1653 float frameTimeMS = FrameTime * 1000.0f;
1737 1654
1738 // These variables will be used to save the precise frame time using the 1655 int previousFrameTick;
1739 // Stopwatch class of Microsoft SDK; the times are recorded at the start 1656
1740 // and end of a particular section of code, and then used to calculate 1657 double tmpMS;
1741 // the frame times, which are the sums of the sections for each given name 1658 double tmpMS2;
1742 double preciseTotalFrameTime = 0.0; 1659 double framestart;
1743 double preciseSimFrameTime = 0.0; 1660 float sleepMS;
1744 double precisePhysicsFrameTime = 0.0; 1661 float sleepError = 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();
1752 1662
1753 while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame)) 1663 while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame))
1754 { 1664 {
1665 framestart = Util.GetTimeStampMS();
1755 ++Frame; 1666 ++Frame;
1756 1667
1757 // m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName); 1668 // m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName);
1758 1669
1759 agentMS = eventMS = backupMS = terrainMS = landMS = spareMS = 0; 1670 agentMS = tempOnRezMS = eventMS = backupMS = terrainMS = landMS = 0f;
1760 1671
1761 try 1672 try
1762 { 1673 {
1763 EventManager.TriggerRegionHeartbeatStart(this); 1674 EventManager.TriggerRegionHeartbeatStart(this);
1764 1675
1765 // Apply taints in terrain module to terrain in physics scene 1676 // Apply taints in terrain module to terrain in physics scene
1677
1678 tmpMS = Util.GetTimeStampMS();
1679
1680 if (Frame % 4 == 0)
1681 {
1682 CheckTerrainUpdates();
1683 }
1684
1766 if (Frame % m_update_terrain == 0) 1685 if (Frame % m_update_terrain == 0)
1767 { 1686 {
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
1777 tmpMS = Util.EnvironmentTickCount();
1778 simFrameStopwatch.Start();
1779 UpdateTerrain(); 1687 UpdateTerrain();
1780
1781 // Get the simulation frame time that the avatar force
1782 // input took
1783 simFrameStopwatch.Stop();
1784 preciseSimFrameTime =
1785 simFrameStopwatch.Elapsed.TotalMilliseconds;
1786 terrainMS = Util.EnvironmentTickCountSubtract(tmpMS);
1787 } 1688 }
1788 1689
1789 // At several points inside the code there was a need to 1690 tmpMS2 = Util.GetTimeStampMS();
1790 // create a more precise measurement of time elapsed. This 1691 terrainMS = (float)(tmpMS2 - tmpMS);
1791 // led to the addition of variables that have a similar 1692 tmpMS = tmpMS2;
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 1693
1799 tmpMS = Util.EnvironmentTickCount();
1800
1801 // Begin the stopwatch to track the time to prepare physics
1802 physicsFrameStopwatch.Start();
1803 if (PhysicsEnabled && Frame % m_update_physics == 0) 1694 if (PhysicsEnabled && Frame % m_update_physics == 0)
1804 m_sceneGraph.UpdatePreparePhysics(); 1695 m_sceneGraph.UpdatePreparePhysics();
1805 1696
1806 // Get the time it took to prepare the physics, this 1697 tmpMS2 = Util.GetTimeStampMS();
1807 // would report the most precise time that physics was 1698 physicsMS2 = (float)(tmpMS2 - tmpMS);
1808 // running on the machine and should the physics not be 1699 tmpMS = tmpMS2;
1809 // enabled will report the time it took to check if physics
1810 // was enabled
1811 physicsFrameStopwatch.Stop();
1812 precisePhysicsFrameTime = physicsFrameStopwatch.Elapsed.TotalMilliseconds;
1813 physicsMS2 = Util.EnvironmentTickCountSubtract(tmpMS);
1814 1700
1701/*
1815 // Apply any pending avatar force input to the avatar's velocity 1702 // Apply any pending avatar force input to the avatar's velocity
1816 tmpMS = Util.EnvironmentTickCount();
1817 simFrameStopwatch.Restart();
1818 if (Frame % m_update_entitymovement == 0) 1703 if (Frame % m_update_entitymovement == 0)
1819 m_sceneGraph.UpdateScenePresenceMovement(); 1704 m_sceneGraph.UpdateScenePresenceMovement();
1705*/
1706 if (Frame % (m_update_coarse_locations) == 0 && !m_sendingCoarseLocations)
1707 {
1708 m_sendingCoarseLocations = true;
1709 WorkManager.RunInThreadPool(
1710 delegate
1711 {
1712 List<Vector3> coarseLocations;
1713 List<UUID> avatarUUIDs;
1714 SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60);
1715 // Send coarse locations to clients
1716 ForEachScenePresence(delegate(ScenePresence presence)
1717 {
1718 presence.SendCoarseLocations(coarseLocations, avatarUUIDs);
1719 });
1720 m_sendingCoarseLocations = false;
1721 }, null, string.Format("SendCoarseLocations ({0})", Name));
1722 }
1820 1723
1821 // Get the simulation frame time that the avatar force input 1724 // Get the simulation frame time that the avatar force input
1822 // took 1725 // took
1823 simFrameStopwatch.Stop(); 1726 tmpMS2 = Util.GetTimeStampMS();
1824 preciseSimFrameTime += 1727 agentMS = (float)(tmpMS2 - tmpMS);
1825 simFrameStopwatch.Elapsed.TotalMilliseconds; 1728 tmpMS = tmpMS2;
1826 agentMS = Util.EnvironmentTickCountSubtract(tmpMS);
1827 1729
1828 // Perform the main physics update. This will do the actual work of moving objects and avatars according to their 1730 // Perform the main physics update. This will do the actual work of moving objects and avatars according to their
1829 // velocity 1731 // velocity
1830 tmpMS = Util.EnvironmentTickCount();
1831 physicsFrameStopwatch.Restart();
1832 if (Frame % m_update_physics == 0) 1732 if (Frame % m_update_physics == 0)
1833 { 1733 {
1834 if (PhysicsEnabled) 1734 if (PhysicsEnabled)
1835 physicsFPS = m_sceneGraph.UpdatePhysics(MinFrameSeconds); 1735 physicsFPS = m_sceneGraph.UpdatePhysics(FrameTime);
1836 1736
1837 if (SynchronizeScene != null) 1737 if (SynchronizeScene != null)
1838 SynchronizeScene(this); 1738 SynchronizeScene(this);
1839 } 1739 }
1840 1740
1841 // Add the main physics update time to the prepare physics time 1741 tmpMS2 = Util.GetTimeStampMS();
1842 physicsFrameStopwatch.Stop(); 1742 physicsMS = (float)(tmpMS2 - tmpMS);
1843 precisePhysicsFrameTime += physicsFrameStopwatch.Elapsed.TotalMilliseconds; 1743 tmpMS = tmpMS2;
1844 physicsMS = Util.EnvironmentTickCountSubtract(tmpMS);
1845
1846 // Start the stopwatch for the remainder of the simulation
1847 simFrameStopwatch.Restart();
1848 tmpMS = Util.EnvironmentTickCount();
1849 1744
1850 // Check if any objects have reached their targets 1745 // Check if any objects have reached their targets
1851 CheckAtTargets(); 1746 CheckAtTargets();
@@ -1860,20 +1755,37 @@ namespace OpenSim.Region.Framework.Scenes
1860 if (Frame % m_update_presences == 0) 1755 if (Frame % m_update_presences == 0)
1861 m_sceneGraph.UpdatePresences(); 1756 m_sceneGraph.UpdatePresences();
1862 1757
1863 agentMS += Util.EnvironmentTickCountSubtract(tmpMS); 1758 tmpMS2 = Util.GetTimeStampMS();
1759 agentMS += (float)(tmpMS2 - tmpMS);
1760 tmpMS = tmpMS2;
1761
1762 // Delete temp-on-rez stuff
1763 if (Frame % m_update_temp_cleaning == 0 && !m_cleaningTemps)
1764 {
1765 m_cleaningTemps = true;
1766 WorkManager.RunInThreadPool(
1767 delegate { CleanTempObjects(); m_cleaningTemps = false; }, null, string.Format("CleanTempObjects ({0})", Name));
1768 tmpMS2 = Util.GetTimeStampMS();
1769 tempOnRezMS = (float)(tmpMS2 - tmpMS); // bad.. counts the FireAndForget, not CleanTempObjects
1770 tmpMS = tmpMS2;
1771 }
1864 1772
1865 if (Frame % m_update_events == 0) 1773 if (Frame % m_update_events == 0)
1866 { 1774 {
1867 tmpMS = Util.EnvironmentTickCount();
1868 UpdateEvents(); 1775 UpdateEvents();
1869 eventMS = Util.EnvironmentTickCountSubtract(tmpMS); 1776
1777 tmpMS2 = Util.GetTimeStampMS();
1778 eventMS = (float)(tmpMS2 - tmpMS);
1779 tmpMS = tmpMS2;
1870 } 1780 }
1871 1781
1872 if (PeriodicBackup && Frame % m_update_backup == 0) 1782 if (PeriodicBackup && Frame % m_update_backup == 0)
1873 { 1783 {
1874 tmpMS = Util.EnvironmentTickCount();
1875 UpdateStorageBackup(); 1784 UpdateStorageBackup();
1876 backupMS = Util.EnvironmentTickCountSubtract(tmpMS); 1785
1786 tmpMS2 = Util.GetTimeStampMS();
1787 backupMS = (float)(tmpMS2 - tmpMS);
1788 tmpMS = tmpMS2;
1877 } 1789 }
1878 1790
1879 //if (Frame % m_update_land == 0) 1791 //if (Frame % m_update_land == 0)
@@ -1885,28 +1797,24 @@ namespace OpenSim.Region.Framework.Scenes
1885 1797
1886 if (!LoginsEnabled && Frame == 20) 1798 if (!LoginsEnabled && Frame == 20)
1887 { 1799 {
1888 // m_log.DebugFormat("{0} {1} {2}", LoginsDisabled, m_sceneGraph.GetActiveScriptsCount(), LoginLock);
1889
1890 // In 99.9% of cases it is a bad idea to manually force garbage collection. However,
1891 // this is a rare case where we know we have just went through a long cycle of heap
1892 // allocations, and there is no more work to be done until someone logs in
1893 GC.Collect(); 1800 GC.Collect();
1894 1801 GC.WaitForPendingFinalizers();
1802 GC.Collect();
1895 if (!LoginLock) 1803 if (!LoginLock)
1896 { 1804 {
1805 m_sceneGridService.InformNeighborsThatRegionisUp(
1806 RequestModuleInterface<INeighbourService>(), RegionInfo);
1807
1897 if (!StartDisabled) 1808 if (!StartDisabled)
1898 { 1809 {
1899 m_log.InfoFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName); 1810 m_log.InfoFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName);
1900 LoginsEnabled = true; 1811 LoginsEnabled = true;
1901 } 1812 }
1902 1813
1903 m_sceneGridService.InformNeighborsThatRegionisUp(
1904 RequestModuleInterface<INeighbourService>(), RegionInfo);
1905
1906 // Region ready should always be set 1814 // Region ready should always be set
1907 Ready = true; 1815 Ready = true;
1908 } 1816 }
1909 else 1817//// else
1910 { 1818 {
1911 // This handles a case of a region having no scripts for the RegionReady module 1819 // This handles a case of a region having no scripts for the RegionReady module
1912 if (m_sceneGraph.GetActiveScriptsCount() == 0) 1820 if (m_sceneGraph.GetActiveScriptsCount() == 0)
@@ -1916,6 +1824,7 @@ namespace OpenSim.Region.Framework.Scenes
1916 // LoginLock can currently only be set by a region module implementation. 1824 // LoginLock can currently only be set by a region module implementation.
1917 // If somehow this hasn't been done then the quickest way to bugfix is to see the 1825 // If somehow this hasn't been done then the quickest way to bugfix is to see the
1918 // NullReferenceException 1826 // NullReferenceException
1827
1919 IRegionReadyModule rrm = RequestModuleInterface<IRegionReadyModule>(); 1828 IRegionReadyModule rrm = RequestModuleInterface<IRegionReadyModule>();
1920 rrm.TriggerRegionReady(this); 1829 rrm.TriggerRegionReady(this);
1921 } 1830 }
@@ -1930,79 +1839,64 @@ namespace OpenSim.Region.Framework.Scenes
1930 } 1839 }
1931 1840
1932 EventManager.TriggerRegionHeartbeatEnd(this); 1841 EventManager.TriggerRegionHeartbeatEnd(this);
1933 otherMS = eventMS + backupMS + terrainMS + landMS; 1842 m_firstHeartbeat = false;
1843 Watchdog.UpdateThread();
1934 1844
1935 // Get the elapsed time for the simulation frame 1845 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS;
1936 simFrameStopwatch.Stop();
1937 preciseSimFrameTime +=
1938 simFrameStopwatch.Elapsed.TotalMilliseconds;
1939 1846
1940 if (!UpdateOnTimer) 1847 tmpMS = Util.GetTimeStampMS();
1941 {
1942 Watchdog.UpdateThread();
1943 1848
1944 spareMS = MinFrameTicks - Util.EnvironmentTickCountSubtract(m_lastFrameTick); 1849 previousFrameTick = m_lastFrameTick;
1850 m_lastFrameTick = (int)(tmpMS + 0.5);
1945 1851
1946 if (spareMS > 0) 1852 // estimate sleep time
1947 m_updateWaitEvent.WaitOne(spareMS); 1853 tmpMS2 = tmpMS - framestart;
1948 else 1854 tmpMS2 = (double)frameTimeMS - tmpMS2 - sleepError;
1949 spareMS = 0; 1855
1950 } 1856 // reuse frameMS as temporary
1857 frameMS = (float)tmpMS2;
1858
1859 // sleep if we can
1860 if (tmpMS2 > 0)
1861 {
1862 Thread.Sleep((int)(tmpMS2 + 0.5));
1863
1864 tmpMS2 = Util.GetTimeStampMS();
1865 sleepMS = (float)(tmpMS2 - tmpMS);
1866 sleepError = sleepMS - frameMS;
1867 Util.Clamp(sleepError, 0.0f, 20f);
1868 frameMS = (float)(tmpMS2 - framestart);
1869 }
1951 else 1870 else
1952 { 1871 {
1953 spareMS = Math.Max(0, MinFrameTicks - physicsMS2 - agentMS - physicsMS - otherMS); 1872 tmpMS2 = Util.GetTimeStampMS();
1954 } 1873 frameMS = (float)(tmpMS2 - framestart);
1874 sleepMS = 0.0f;
1875 sleepError = 0.0f;
1876 }
1955 1877
1956 // Get the total frame time 1878 // script time is not scene frame time, but is displayed per frame
1957 totalFrameStopwatch.Stop(); 1879 float scriptTimeMS = GetAndResetScriptExecutionTime();
1958 preciseTotalFrameTime = 1880 StatsReporter.AddFrameStats(TimeDilation, physicsFPS, agentMS,
1959 totalFrameStopwatch.Elapsed.TotalMilliseconds; 1881 physicsMS + physicsMS2, otherMS , sleepMS, frameMS, scriptTimeMS);
1960 1882
1961 // Restart the stopwatch for the total time of the next frame
1962 totalFrameStopwatch.Restart();
1963 1883
1964 previousFrameTick = m_lastFrameTick;
1965 frameMS = Util.EnvironmentTickCountSubtract(m_lastFrameTick);
1966 m_lastFrameTick = Util.EnvironmentTickCount();
1967 1884
1968 // if (Frame%m_update_avatars == 0) 1885 // if (Frame%m_update_avatars == 0)
1969 // UpdateInWorldTime(); 1886 // UpdateInWorldTime();
1970 StatsReporter.AddPhysicsFPS(physicsFPS); 1887
1971 StatsReporter.AddTimeDilation(TimeDilation); 1888 // Optionally warn if a frame takes double the amount of time that it should.
1972 StatsReporter.AddFPS(1);
1973
1974 StatsReporter.addFrameMS(frameMS);
1975 StatsReporter.addAgentMS(agentMS);
1976 StatsReporter.addPhysicsMS(physicsMS + physicsMS2);
1977 StatsReporter.addOtherMS(otherMS);
1978 StatsReporter.AddSpareMS(spareMS);
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);
1990
1991 // Optionally warn if a frame takes double the amount of time that it should.
1992 if (DebugUpdates 1889 if (DebugUpdates
1993 && Util.EnvironmentTickCountSubtract( 1890 && Util.EnvironmentTickCountSubtract(
1994 m_lastFrameTick, previousFrameTick) > MinFrameTicks * 2) 1891 m_lastFrameTick, previousFrameTick) > (int)(FrameTime * 1000 * 2))
1892
1995 m_log.WarnFormat( 1893 m_log.WarnFormat(
1996 "[SCENE]: Frame took {0} ms (desired max {1} ms) in {2}", 1894 "[SCENE]: Frame took {0} ms (desired max {1} ms) in {2}",
1997 Util.EnvironmentTickCountSubtract(m_lastFrameTick, previousFrameTick), 1895 Util.EnvironmentTickCountSubtract(m_lastFrameTick, previousFrameTick),
1998 MinFrameTicks, 1896 FrameTime * 1000,
1897
1999 RegionInfo.RegionName); 1898 RegionInfo.RegionName);
2000 } 1899 }
2001
2002 // Finished updating scene frame, so stop the total frame's Stopwatch
2003 totalFrameStopwatch.Stop();
2004
2005 return spareMS >= 0;
2006 } 1900 }
2007 1901
2008 /// <summary> 1902 /// <summary>
@@ -2011,24 +1905,28 @@ namespace OpenSim.Region.Framework.Scenes
2011 /// <param name="ticks">Elapsed Stopwatch ticks</param> 1905 /// <param name="ticks">Elapsed Stopwatch ticks</param>
2012 public void AddScriptExecutionTime(long ticks) 1906 public void AddScriptExecutionTime(long ticks)
2013 { 1907 {
1908 StatsReporter.addScriptEvents(1);
2014 Interlocked.Add(ref m_scriptExecutionTime, ticks); 1909 Interlocked.Add(ref m_scriptExecutionTime, ticks);
2015 } 1910 }
2016 1911
2017 /// <summary> 1912 /// <summary>
2018 /// Returns the total execution time of all the scripts in the region since the last frame 1913 /// Returns the total execution time of all the scripts in the region since the last call
2019 /// (in milliseconds), and clears the value in preparation for the next frame. 1914 /// (in milliseconds), and clears the value in preparation for the next call.
2020 /// </summary> 1915 /// </summary>
2021 /// <returns>Time in milliseconds</returns> 1916 /// <returns>Time in milliseconds</returns>
2022 private long GetAndResetScriptExecutionTime() 1917
1918 // Warning: this is now called from StatsReporter, and can't be shared
1919
1920 public long GetAndResetScriptExecutionTime()
2023 { 1921 {
2024 long ticks = Interlocked.Exchange(ref m_scriptExecutionTime, 0); 1922 long ticks = Interlocked.Exchange(ref m_scriptExecutionTime, 0);
2025 return (ticks * 1000) / Stopwatch.Frequency; 1923 return (ticks * 1000L) / Stopwatch.Frequency;
2026 } 1924 }
2027 1925
2028 public void AddGroupTarget(SceneObjectGroup grp) 1926 public void AddGroupTarget(SceneObjectGroup grp)
2029 { 1927 {
2030 lock (m_groupsWithTargets) 1928 lock (m_groupsWithTargets)
2031 m_groupsWithTargets[grp.UUID] = grp; 1929 m_groupsWithTargets[grp.UUID] = 0;
2032 } 1930 }
2033 1931
2034 public void RemoveGroupTarget(SceneObjectGroup grp) 1932 public void RemoveGroupTarget(SceneObjectGroup grp)
@@ -2039,18 +1937,24 @@ namespace OpenSim.Region.Framework.Scenes
2039 1937
2040 private void CheckAtTargets() 1938 private void CheckAtTargets()
2041 { 1939 {
2042 List<SceneObjectGroup> objs = null; 1940 List<UUID> objs = null;
2043 1941
2044 lock (m_groupsWithTargets) 1942 lock (m_groupsWithTargets)
2045 { 1943 {
2046 if (m_groupsWithTargets.Count != 0) 1944 if (m_groupsWithTargets.Count != 0)
2047 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values); 1945 objs = new List<UUID>(m_groupsWithTargets.Keys);
2048 } 1946 }
2049 1947
2050 if (objs != null) 1948 if (objs != null)
2051 { 1949 {
2052 foreach (SceneObjectGroup entry in objs) 1950 foreach (UUID entry in objs)
2053 entry.checkAtTargets(); 1951 {
1952 SceneObjectGroup grp = GetSceneObjectGroup(entry);
1953 if (grp == null)
1954 m_groupsWithTargets.Remove(entry);
1955 else
1956 grp.checkAtTargets();
1957 }
2054 } 1958 }
2055 } 1959 }
2056 1960
@@ -2074,6 +1978,11 @@ namespace OpenSim.Region.Framework.Scenes
2074 EventManager.TriggerTerrainTick(); 1978 EventManager.TriggerTerrainTick();
2075 } 1979 }
2076 1980
1981 private void CheckTerrainUpdates()
1982 {
1983 EventManager.TriggerTerrainCheckUpdates();
1984 }
1985
2077 /// <summary> 1986 /// <summary>
2078 /// Back up queued up changes 1987 /// Back up queued up changes
2079 /// </summary> 1988 /// </summary>
@@ -2081,8 +1990,7 @@ namespace OpenSim.Region.Framework.Scenes
2081 { 1990 {
2082 if (!m_backingup) 1991 if (!m_backingup)
2083 { 1992 {
2084 m_backingup = true; 1993 WorkManager.RunInThreadPool(o => Backup(false), null, string.Format("BackupWorker ({0}", Name), false);
2085 WorkManager.RunInThread(o => Backup(false), null, string.Format("BackupWaitCallback ({0})", Name));
2086 } 1994 }
2087 } 1995 }
2088 1996
@@ -2110,38 +2018,58 @@ namespace OpenSim.Region.Framework.Scenes
2110 { 2018 {
2111 lock (m_returns) 2019 lock (m_returns)
2112 { 2020 {
2113 EventManager.TriggerOnBackup(SimulationDataService, forced); 2021 if(m_backingup)
2114 m_backingup = false; 2022 {
2023 m_log.WarnFormat("[Scene] Backup of {0} already running. New call skipped", RegionInfo.RegionName);
2024 return;
2025 }
2115 2026
2116 foreach (KeyValuePair<UUID, ReturnInfo> ret in m_returns) 2027 m_backingup = true;
2028 try
2117 { 2029 {
2118 UUID transaction = UUID.Random(); 2030 EventManager.TriggerOnBackup(SimulationDataService, forced);
2119 2031
2120 GridInstantMessage msg = new GridInstantMessage(); 2032 if(m_returns.Count == 0)
2121 msg.fromAgentID = new Guid(UUID.Zero.ToString()); // From server 2033 return;
2122 msg.toAgentID = new Guid(ret.Key.ToString());
2123 msg.imSessionID = new Guid(transaction.ToString());
2124 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
2125 msg.fromAgentName = "Server";
2126 msg.dialog = (byte)19; // Object msg
2127 msg.fromGroup = false;
2128 msg.offline = (byte)0;
2129 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID;
2130 msg.Position = Vector3.Zero;
2131 msg.RegionID = RegionInfo.RegionID.Guid;
2132
2133 // We must fill in a null-terminated 'empty' string here since bytes[0] will crash viewer 3.
2134 msg.binaryBucket = Util.StringToBytes256("\0");
2135 if (ret.Value.count > 1)
2136 msg.message = string.Format("Your {0} objects were returned from {1} in region {2} due to {3}", ret.Value.count, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason);
2137 else
2138 msg.message = string.Format("Your object {0} was returned from {1} in region {2} due to {3}", ret.Value.objectName, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason);
2139 2034
2140 IMessageTransferModule tr = RequestModuleInterface<IMessageTransferModule>(); 2035 IMessageTransferModule tr = RequestModuleInterface<IMessageTransferModule>();
2141 if (tr != null) 2036 if (tr == null)
2037 return;
2038
2039 uint unixtime = (uint)Util.UnixTimeSinceEpoch();
2040 uint estateid = RegionInfo.EstateSettings.ParentEstateID;
2041 Guid regionguid = RegionInfo.RegionID.Guid;
2042
2043 foreach (KeyValuePair<UUID, ReturnInfo> ret in m_returns)
2044 {
2045 GridInstantMessage msg = new GridInstantMessage();
2046 msg.fromAgentID = Guid.Empty; // From server
2047 msg.toAgentID = ret.Key.Guid;
2048 msg.imSessionID = Guid.NewGuid();
2049 msg.timestamp = unixtime;
2050 msg.fromAgentName = "Server";
2051 msg.dialog = 19; // Object msg
2052 msg.fromGroup = false;
2053 msg.offline = 1;
2054 msg.ParentEstateID = estateid;
2055 msg.Position = Vector3.Zero;
2056 msg.RegionID = regionguid;
2057
2058 // We must fill in a null-terminated 'empty' string here since bytes[0] will crash viewer 3.
2059 msg.binaryBucket = new Byte[1] {0};
2060 if (ret.Value.count > 1)
2061 msg.message = string.Format("Your {0} objects were returned from {1} in region {2} due to {3}", ret.Value.count, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason);
2062 else
2063 msg.message = string.Format("Your object {0} was returned from {1} in region {2} due to {3}", ret.Value.objectName, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason);
2064
2142 tr.SendInstantMessage(msg, delegate(bool success) { }); 2065 tr.SendInstantMessage(msg, delegate(bool success) { });
2066 }
2067 m_returns.Clear();
2068 }
2069 finally
2070 {
2071 m_backingup = false;
2143 } 2072 }
2144 m_returns.Clear();
2145 } 2073 }
2146 } 2074 }
2147 2075
@@ -2159,7 +2087,7 @@ namespace OpenSim.Region.Framework.Scenes
2159 } 2087 }
2160 2088
2161 /// <summary> 2089 /// <summary>
2162 /// Tell an agent that their object has been returned. 2090 /// Tell an agent that their object has been returned.
2163 /// </summary> 2091 /// </summary>
2164 /// <remarks> 2092 /// <remarks>
2165 /// The actual return is handled by the caller. 2093 /// The actual return is handled by the caller.
@@ -2199,7 +2127,16 @@ namespace OpenSim.Region.Framework.Scenes
2199 /// </summary> 2127 /// </summary>
2200 public void SaveTerrain() 2128 public void SaveTerrain()
2201 { 2129 {
2202 SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); 2130 SimulationDataService.StoreTerrain(Heightmap.GetTerrainData(), RegionInfo.RegionID);
2131 }
2132
2133 /// <summary>
2134 /// Store the terrain in the persistant data store
2135 /// </summary>
2136 public void SaveBakedTerrain()
2137 {
2138 if(Bakedmap != null)
2139 SimulationDataService.StoreBakedTerrain(Bakedmap.GetTerrainData(), RegionInfo.RegionID);
2203 } 2140 }
2204 2141
2205 public void StoreWindlightProfile(RegionLightShareData wl) 2142 public void StoreWindlightProfile(RegionLightShareData wl)
@@ -2222,20 +2159,44 @@ namespace OpenSim.Region.Framework.Scenes
2222 { 2159 {
2223 try 2160 try
2224 { 2161 {
2162 Bakedmap = null;
2163 TerrainData map = SimulationDataService.LoadBakedTerrain(RegionInfo.RegionID, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ);
2164 if (map != null)
2165 {
2166 Bakedmap = new TerrainChannel(map);
2167 }
2168 }
2169 catch (Exception e)
2170 {
2171 m_log.WarnFormat(
2172 "[TERRAIN]: Scene.cs: LoadWorldMap() baked terrain - Failed with exception {0}{1}", e.Message, e.StackTrace);
2173 }
2174
2175 try
2176 {
2225 TerrainData map = SimulationDataService.LoadTerrain(RegionInfo.RegionID, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ); 2177 TerrainData map = SimulationDataService.LoadTerrain(RegionInfo.RegionID, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ);
2226 if (map == null) 2178 if (map == null)
2227 { 2179 {
2228 // This should be in the Terrain module, but it isn't because 2180 if(Bakedmap != null)
2229 // the heightmap is needed _way_ before the modules are initialized... 2181 {
2230 IConfig terrainConfig = m_config.Configs["Terrain"]; 2182 m_log.Warn("[TERRAIN]: terrain not found. Used stored baked terrain.");
2231 String m_InitialTerrain = "pinhead-island"; 2183 Heightmap = Bakedmap.MakeCopy();
2232 if (terrainConfig != null) 2184 SimulationDataService.StoreTerrain(Heightmap.GetTerrainData(), RegionInfo.RegionID);
2233 m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain); 2185 }
2186 else
2187 {
2188 // This should be in the Terrain module, but it isn't because
2189 // the heightmap is needed _way_ before the modules are initialized...
2190 IConfig terrainConfig = m_config.Configs["Terrain"];
2191 String m_InitialTerrain = "pinhead-island";
2192 if (terrainConfig != null)
2193 m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain);
2234 2194
2235 m_log.InfoFormat("[TERRAIN]: No default terrain. Generating a new terrain {0}.", m_InitialTerrain); 2195 m_log.InfoFormat("[TERRAIN]: No default terrain. Generating a new terrain {0}.", m_InitialTerrain);
2236 Heightmap = new TerrainChannel(m_InitialTerrain, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ); 2196 Heightmap = new TerrainChannel(m_InitialTerrain, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ);
2237 2197
2238 SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); 2198 SimulationDataService.StoreTerrain(Heightmap.GetTerrainData(), RegionInfo.RegionID);
2199 }
2239 } 2200 }
2240 else 2201 else
2241 { 2202 {
@@ -2248,13 +2209,12 @@ namespace OpenSim.Region.Framework.Scenes
2248 "[TERRAIN]: Scene.cs: LoadWorldMap() - Regenerating as failed with exception {0}{1}", 2209 "[TERRAIN]: Scene.cs: LoadWorldMap() - Regenerating as failed with exception {0}{1}",
2249 e.Message, e.StackTrace); 2210 e.Message, e.StackTrace);
2250 2211
2251 // Non standard region size. If there's an old terrain in the database, it might read past the buffer
2252#pragma warning disable 0162 2212#pragma warning disable 0162
2253 if ((int)Constants.RegionSize != 256) 2213 if ((int)Constants.RegionSize != 256)
2254 { 2214 {
2255 Heightmap = new TerrainChannel(); 2215 Heightmap = new TerrainChannel();
2256 2216
2257 SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); 2217 SimulationDataService.StoreTerrain(Heightmap.GetTerrainData(), RegionInfo.RegionID);
2258 } 2218 }
2259 } 2219 }
2260 catch (Exception e) 2220 catch (Exception e)
@@ -2262,6 +2222,12 @@ namespace OpenSim.Region.Framework.Scenes
2262 m_log.WarnFormat( 2222 m_log.WarnFormat(
2263 "[TERRAIN]: Scene.cs: LoadWorldMap() - Failed with exception {0}{1}", e.Message, e.StackTrace); 2223 "[TERRAIN]: Scene.cs: LoadWorldMap() - Failed with exception {0}{1}", e.Message, e.StackTrace);
2264 } 2224 }
2225
2226 if(Bakedmap == null && Heightmap != null)
2227 {
2228 Bakedmap = Heightmap.MakeCopy();
2229 SimulationDataService.StoreBakedTerrain(Bakedmap.GetTerrainData(), RegionInfo.RegionID);
2230 }
2265 } 2231 }
2266 2232
2267 /// <summary> 2233 /// <summary>
@@ -2277,12 +2243,12 @@ namespace OpenSim.Region.Framework.Scenes
2277 //// stored in the GridService, because that's what the world map module uses 2243 //// stored in the GridService, because that's what the world map module uses
2278 //// to send the map image UUIDs (of other regions) to the viewer... 2244 //// to send the map image UUIDs (of other regions) to the viewer...
2279 if (m_generateMaptiles) 2245 if (m_generateMaptiles)
2280 RegenerateMaptile(); 2246 RegenerateMaptile();
2281 2247
2282 GridRegion region = new GridRegion(RegionInfo); 2248 GridRegion region = new GridRegion(RegionInfo);
2283 string error = GridService.RegisterRegion(RegionInfo.ScopeID, region); 2249 string error = GridService.RegisterRegion(RegionInfo.ScopeID, region);
2284 // m_log.DebugFormat("[SCENE]: RegisterRegionWithGrid. name={0},id={1},loc=<{2},{3}>,size=<{4},{5}>", 2250 // m_log.DebugFormat("[SCENE]: RegisterRegionWithGrid. name={0},id={1},loc=<{2},{3}>,size=<{4},{5}>",
2285 // m_regionName, 2251 // m_regionName,
2286 // RegionInfo.RegionID, 2252 // RegionInfo.RegionID,
2287 // RegionInfo.RegionLocX, RegionInfo.RegionLocY, 2253 // RegionInfo.RegionLocX, RegionInfo.RegionLocY,
2288 // RegionInfo.RegionSizeX, RegionInfo.RegionSizeY); 2254 // RegionInfo.RegionSizeX, RegionInfo.RegionSizeY);
@@ -2344,7 +2310,9 @@ namespace OpenSim.Region.Framework.Scenes
2344 EventManager.TriggerOnSceneObjectLoaded(group); 2310 EventManager.TriggerOnSceneObjectLoaded(group);
2345 SceneObjectPart rootPart = group.GetPart(group.UUID); 2311 SceneObjectPart rootPart = group.GetPart(group.UUID);
2346 rootPart.Flags &= ~PrimFlags.Scripted; 2312 rootPart.Flags &= ~PrimFlags.Scripted;
2313
2347 rootPart.TrimPermissions(); 2314 rootPart.TrimPermissions();
2315 group.InvalidateDeepEffectivePerms();
2348 2316
2349 // Don't do this here - it will get done later on when sculpt data is loaded. 2317 // Don't do this here - it will get done later on when sculpt data is loaded.
2350 // group.CheckSculptAndLoad(); 2318 // group.CheckSculptAndLoad();
@@ -2383,93 +2351,166 @@ namespace OpenSim.Region.Framework.Scenes
2383 /// <returns></returns> 2351 /// <returns></returns>
2384 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 2352 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
2385 { 2353 {
2386 Vector3 pos = Vector3.Zero;
2387 if (RayEndIsIntersection == (byte)1)
2388 {
2389 pos = RayEnd;
2390 return pos;
2391 }
2392 2354
2393 if (RayTargetID != UUID.Zero) 2355 Vector3 dir = RayEnd - RayStart;
2356
2357 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
2358 Vector3 wpos = Vector3.Zero;
2359 // Check for water surface intersection from above
2360 if ((RayStart.Z > wheight) && (RayEnd.Z < wheight))
2394 { 2361 {
2395 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 2362 float ratio = (wheight - RayStart.Z) / dir.Z;
2363 wpos.X = RayStart.X + (ratio * dir.X);
2364 wpos.Y = RayStart.Y + (ratio * dir.Y);
2365 wpos.Z = wheight;
2366 }
2396 2367
2397 Vector3 direction = Vector3.Normalize(RayEnd - RayStart); 2368 Vector3 pos = Vector3.Zero;
2398 Vector3 AXOrigin = RayStart;
2399 Vector3 AXdirection = direction;
2400 2369
2401 if (target != null) 2370 if (RayEndIsIntersection != (byte)1)
2371 {
2372 float dist = dir.Length();
2373 if (dist != 0)
2402 { 2374 {
2403 pos = target.AbsolutePosition; 2375 Vector3 direction = dir * (1 / dist);
2404 //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());
2405 2376
2406 // TODO: Raytrace better here 2377 dist += 1.0f;
2407 2378
2408 //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection)); 2379 if (SupportsRayCastFiltered())
2409 Ray NewRay = new Ray(AXOrigin, AXdirection); 2380 {
2381 RayFilterFlags rayfilter = RayFilterFlags.BackFaceCull;
2382 rayfilter |= RayFilterFlags.land;
2383 rayfilter |= RayFilterFlags.physical;
2384 rayfilter |= RayFilterFlags.nonphysical;
2385 rayfilter |= RayFilterFlags.LSLPhantom; // ubODE will only see volume detectors
2386
2387 // get some more contacts ???
2388 int physcount = 4;
2389
2390 List<ContactResult> physresults =
2391 (List<ContactResult>)RayCastFiltered(RayStart, direction, dist, physcount, rayfilter);
2392 if (physresults != null && physresults.Count > 0)
2393 {
2394 // look for terrain ?
2395 if(RayTargetID == UUID.Zero)
2396 {
2397 foreach (ContactResult r in physresults)
2398 {
2399 if (r.ConsumerID == 0)
2400 {
2401 pos = r.Normal * scale;
2402 pos *= 0.5f;
2403 pos = r.Pos + pos;
2404
2405 if (wpos.Z > pos.Z) pos = wpos;
2406 return pos;
2407 }
2408 }
2409 }
2410 else
2411 {
2412 foreach (ContactResult r in physresults)
2413 {
2414 SceneObjectPart part = GetSceneObjectPart(r.ConsumerID);
2415 if (part == null)
2416 continue;
2417 if (part.UUID == RayTargetID)
2418 {
2419 pos = r.Normal * scale;
2420 pos *= 0.5f;
2421 pos = r.Pos + pos;
2422
2423 if (wpos.Z > pos.Z) pos = wpos;
2424 return pos;
2425 }
2426 }
2427 }
2428 // else the first we got
2429 pos = physresults[0].Normal * scale;
2430 pos *= 0.5f;
2431 pos = physresults[0].Pos + pos;
2432
2433 if (wpos.Z > pos.Z)
2434 pos = wpos;
2435 return pos;
2436 }
2410 2437
2411 // Ray Trace against target here 2438 }
2412 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 2439 if (RayTargetID != UUID.Zero)
2440 {
2441 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
2413 2442
2414 // Un-comment out the following line to Get Raytrace results printed to the console. 2443 Ray NewRay = new Ray(RayStart, direction);
2415 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
2416 float ScaleOffset = 0.5f;
2417 2444
2418 // If we hit something 2445 if (target != null)
2419 if (ei.HitTF) 2446 {
2420 { 2447 pos = target.AbsolutePosition;
2421 Vector3 scaleComponent = ei.AAfaceNormal;
2422 if (scaleComponent.X != 0) ScaleOffset = scale.X;
2423 if (scaleComponent.Y != 0) ScaleOffset = scale.Y;
2424 if (scaleComponent.Z != 0) ScaleOffset = scale.Z;
2425 ScaleOffset = Math.Abs(ScaleOffset);
2426 Vector3 intersectionpoint = ei.ipoint;
2427 Vector3 normal = ei.normal;
2428 // Set the position to the intersection point
2429 Vector3 offset = (normal * (ScaleOffset / 2f));
2430 pos = (intersectionpoint + offset);
2431
2432 //Seems to make no sense to do this as this call is used for rezzing from inventory as well, and with inventory items their size is not always 0.5f
2433 //And in cases when we weren't rezzing from inventory we were re-adding the 0.25 straight after calling this method
2434 // Un-offset the prim (it gets offset later by the consumer method)
2435 //pos.Z -= 0.25F;
2436 2448
2437 } 2449 // Ray Trace against target here
2450 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
2438 2451
2439 return pos; 2452 // Un-comment out the following line to Get Raytrace results printed to the console.
2440 } 2453 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
2441 else 2454 float ScaleOffset = 0.5f;
2442 {
2443 // We don't have a target here, so we're going to raytrace all the objects in the scene.
2444 2455
2445 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 2456 // If we hit something
2457 if (ei.HitTF)
2458 {
2459 Vector3 scaleComponent = ei.AAfaceNormal;
2460 if (scaleComponent.X != 0) ScaleOffset = scale.X;
2461 if (scaleComponent.Y != 0) ScaleOffset = scale.Y;
2462 if (scaleComponent.Z != 0) ScaleOffset = scale.Z;
2463 ScaleOffset = Math.Abs(ScaleOffset);
2464 Vector3 intersectionpoint = ei.ipoint;
2465 Vector3 normal = ei.normal;
2466 // Set the position to the intersection point
2467 Vector3 offset = (normal * (ScaleOffset / 2f));
2468 pos = (intersectionpoint + offset);
2469
2470 //Seems to make no sense to do this as this call is used for rezzing from inventory as well, and with inventory items their size is not always 0.5f
2471 //And in cases when we weren't rezzing from inventory we were re-adding the 0.25 straight after calling this method
2472 // Un-offset the prim (it gets offset later by the consumer method)
2473 //pos.Z -= 0.25F;
2474
2475 if (wpos.Z > pos.Z) pos = wpos;
2476 return pos;
2477 }
2478 }
2479 else
2480 {
2481 // We don't have a target here, so we're going to raytrace all the objects in the scene.
2482 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(NewRay, true, false);
2446 2483
2447 // Un-comment the following line to print the raytrace results to the console. 2484 // Un-comment the following line to print the raytrace results to the console.
2448 //m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 2485 //m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
2449 2486
2450 if (ei.HitTF) 2487 if (ei.HitTF)
2451 { 2488 {
2452 pos = ei.ipoint; 2489 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
2453 } 2490 }
2454 else 2491 else
2455 { 2492 {
2456 // fall back to our stupid functionality 2493 // fall back to our stupid functionality
2457 pos = RayEnd; 2494 pos = RayEnd;
2458 } 2495 }
2459 2496
2460 return pos; 2497 if (wpos.Z > pos.Z) pos = wpos;
2498 return pos;
2499 }
2500 }
2461 } 2501 }
2462 } 2502 }
2463 else
2464 {
2465 // fall back to our stupid functionality
2466 pos = RayEnd;
2467 2503
2468 //increase height so its above the ground. 2504 // fall back to our stupid functionality
2469 //should be getting the normal of the ground at the rez point and using that? 2505 pos = RayEnd;
2470 pos.Z += scale.Z / 2f; 2506
2471 return pos; 2507 //increase height so its above the ground.
2472 } 2508 //should be getting the normal of the ground at the rez point and using that?
2509 pos.Z += scale.Z / 2f;
2510 // return pos;
2511 // check against posible water intercept
2512 if (wpos.Z > pos.Z) pos = wpos;
2513 return pos;
2473 } 2514 }
2474 2515
2475 2516
@@ -2523,13 +2564,26 @@ namespace OpenSim.Region.Framework.Scenes
2523 { 2564 {
2524 // Otherwise, use this default creation code; 2565 // Otherwise, use this default creation code;
2525 sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape); 2566 sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape);
2526 AddNewSceneObject(sceneObject, true);
2527 sceneObject.SetGroup(groupID, null); 2567 sceneObject.SetGroup(groupID, null);
2568 AddNewSceneObject(sceneObject, true);
2569
2570 if (AgentPreferencesService != null) // This will override the brave new full perm world!
2571 {
2572 AgentPrefs prefs = AgentPreferencesService.GetAgentPreferences(ownerID);
2573 // Only apply user selected prefs if the user set them
2574 if (prefs != null && prefs.PermNextOwner != 0)
2575 {
2576 sceneObject.RootPart.GroupMask = (uint)prefs.PermGroup;
2577 sceneObject.RootPart.EveryoneMask = (uint)prefs.PermEveryone;
2578 sceneObject.RootPart.NextOwnerMask = (uint)prefs.PermNextOwner;
2579 }
2580 }
2528 } 2581 }
2529 2582
2530 if (UserManagementModule != null) 2583 if (UserManagementModule != null)
2531 sceneObject.RootPart.CreatorIdentification = UserManagementModule.GetUserUUI(ownerID); 2584 sceneObject.RootPart.CreatorIdentification = UserManagementModule.GetUserUUI(ownerID);
2532 2585
2586 sceneObject.InvalidateDeepEffectivePerms();;
2533 sceneObject.ScheduleGroupForFullUpdate(); 2587 sceneObject.ScheduleGroupForFullUpdate();
2534 2588
2535 return sceneObject; 2589 return sceneObject;
@@ -2560,12 +2614,12 @@ namespace OpenSim.Region.Framework.Scenes
2560 { 2614 {
2561 if (m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates)) 2615 if (m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates))
2562 { 2616 {
2617 sceneObject.IsDeleted = false;
2563 EventManager.TriggerObjectAddedToScene(sceneObject); 2618 EventManager.TriggerObjectAddedToScene(sceneObject);
2564 return true; 2619 return true;
2565 } 2620 }
2566 2621
2567 return false; 2622 return false;
2568
2569 } 2623 }
2570 2624
2571 /// <summary> 2625 /// <summary>
@@ -2657,6 +2711,15 @@ namespace OpenSim.Region.Framework.Scenes
2657 /// </summary> 2711 /// </summary>
2658 public void DeleteAllSceneObjects() 2712 public void DeleteAllSceneObjects()
2659 { 2713 {
2714 DeleteAllSceneObjects(false);
2715 }
2716
2717 /// <summary>
2718 /// Delete every object from the scene. This does not include attachments worn by avatars.
2719 /// </summary>
2720 public void DeleteAllSceneObjects(bool exceptNoCopy)
2721 {
2722 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
2660 lock (Entities) 2723 lock (Entities)
2661 { 2724 {
2662 EntityBase[] entities = Entities.GetEntities(); 2725 EntityBase[] entities = Entities.GetEntities();
@@ -2665,11 +2728,24 @@ namespace OpenSim.Region.Framework.Scenes
2665 if (e is SceneObjectGroup) 2728 if (e is SceneObjectGroup)
2666 { 2729 {
2667 SceneObjectGroup sog = (SceneObjectGroup)e; 2730 SceneObjectGroup sog = (SceneObjectGroup)e;
2668 if (!sog.IsAttachment) 2731 if (sog != null && !sog.IsAttachment)
2669 DeleteSceneObject((SceneObjectGroup)e, false); 2732 {
2733 if (!exceptNoCopy || ((sog.EffectiveOwnerPerms & (uint)PermissionMask.Copy) != 0))
2734 {
2735 DeleteSceneObject((SceneObjectGroup)e, false);
2736 }
2737 else
2738 {
2739 toReturn.Add((SceneObjectGroup)e);
2740 }
2741 }
2670 } 2742 }
2671 } 2743 }
2672 } 2744 }
2745 if (toReturn.Count > 0)
2746 {
2747 returnObjects(toReturn.ToArray(), null);
2748 }
2673 } 2749 }
2674 2750
2675 /// <summary> 2751 /// <summary>
@@ -2728,7 +2804,11 @@ namespace OpenSim.Region.Framework.Scenes
2728 2804
2729 group.DeleteGroupFromScene(silent); 2805 group.DeleteGroupFromScene(silent);
2730 2806
2731 // m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2807 // use this to mean also full delete
2808 if (removeScripts)
2809 group.Clear();
2810 partList = null;
2811 // m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2732 } 2812 }
2733 2813
2734 /// <summary> 2814 /// <summary>
@@ -2763,6 +2843,13 @@ namespace OpenSim.Region.Framework.Scenes
2763 return false; 2843 return false;
2764 } 2844 }
2765 2845
2846
2847 public void updateScenePartGroup(SceneObjectPart part, SceneObjectGroup grp)
2848 {
2849 m_sceneGraph.updateScenePartGroup(part, grp);
2850 }
2851
2852/* not in use, outdate by async method
2766 /// <summary> 2853 /// <summary>
2767 /// Move the given scene object into a new region depending on which region its absolute position has moved 2854 /// Move the given scene object into a new region depending on which region its absolute position has moved
2768 /// into. 2855 /// into.
@@ -2811,6 +2898,7 @@ namespace OpenSim.Region.Framework.Scenes
2811 if (EntityTransferModule != null) 2898 if (EntityTransferModule != null)
2812 EntityTransferModule.Cross(grp, attemptedPosition, silent); 2899 EntityTransferModule.Cross(grp, attemptedPosition, silent);
2813 } 2900 }
2901*/
2814 2902
2815 // Simple test to see if a position is in the current region. 2903 // 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. 2904 // This test is mostly used to see if a region crossing is necessary.
@@ -2818,27 +2906,15 @@ namespace OpenSim.Region.Framework.Scenes
2818 // Return 'true' if position inside region. 2906 // Return 'true' if position inside region.
2819 public bool PositionIsInCurrentRegion(Vector3 pos) 2907 public bool PositionIsInCurrentRegion(Vector3 pos)
2820 { 2908 {
2821 bool ret = false; 2909 float t = pos.X;
2822 int xx = (int)Math.Floor(pos.X); 2910 if (t < 0 || t >= RegionInfo.RegionSizeX)
2823 int yy = (int)Math.Floor(pos.Y);
2824 if (xx < 0 || yy < 0)
2825 return false; 2911 return false;
2826 2912
2827 IRegionCombinerModule regionCombinerModule = RequestModuleInterface<IRegionCombinerModule>(); 2913 t = pos.Y;
2828 if (regionCombinerModule == null) 2914 if (t < 0 || t >= RegionInfo.RegionSizeY)
2829 { 2915 return false;
2830 // Regular region. Just check for region size
2831 if (xx < RegionInfo.RegionSizeX && yy < RegionInfo.RegionSizeY)
2832 ret = true;
2833 }
2834 else
2835 {
2836 // We're in a mega-region so see if we are still in that larger region
2837 ret = regionCombinerModule.PositionIsInMegaregion(this.RegionInfo.RegionID, xx, yy);
2838 }
2839
2840 return ret;
2841 2916
2917 return true;
2842 } 2918 }
2843 2919
2844 /// <summary> 2920 /// <summary>
@@ -2880,6 +2956,23 @@ namespace OpenSim.Region.Framework.Scenes
2880 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2956 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2881 public bool AddSceneObject(SceneObjectGroup sceneObject) 2957 public bool AddSceneObject(SceneObjectGroup sceneObject)
2882 { 2958 {
2959 if (sceneObject.OwnerID == UUID.Zero)
2960 {
2961 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2962 return false;
2963 }
2964
2965 // If the user is banned, we won't let any of their objects
2966 // enter. Period.
2967 //
2968 int flags = GetUserFlags(sceneObject.OwnerID);
2969 if (RegionInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2970 {
2971 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID);
2972
2973 return false;
2974 }
2975
2883 // Force allocation of new LocalId 2976 // Force allocation of new LocalId
2884 // 2977 //
2885 SceneObjectPart[] parts = sceneObject.Parts; 2978 SceneObjectPart[] parts = sceneObject.Parts;
@@ -2889,9 +2982,9 @@ namespace OpenSim.Region.Framework.Scenes
2889 if (sceneObject.IsAttachmentCheckFull()) // Attachment 2982 if (sceneObject.IsAttachmentCheckFull()) // Attachment
2890 { 2983 {
2891 sceneObject.RootPart.AddFlag(PrimFlags.TemporaryOnRez); 2984 sceneObject.RootPart.AddFlag(PrimFlags.TemporaryOnRez);
2892 sceneObject.RootPart.AddFlag(PrimFlags.Phantom); 2985// sceneObject.RootPart.AddFlag(PrimFlags.Phantom);
2893 2986
2894 // Don't sent a full update here because this will cause full updates to be sent twice for 2987 // Don't sent a full update here because this will cause full updates to be sent twice for
2895 // attachments on region crossings, resulting in viewer glitches. 2988 // attachments on region crossings, resulting in viewer glitches.
2896 AddRestoredSceneObject(sceneObject, false, false, false); 2989 AddRestoredSceneObject(sceneObject, false, false, false);
2897 2990
@@ -2912,7 +3005,7 @@ namespace OpenSim.Region.Framework.Scenes
2912 3005
2913 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 3006 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2914 3007
2915 // We must currently not resume scripts at this stage since AttachmentsModule does not have the 3008 // 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. 3009 // information that this is due to a teleport/border cross rather than an ordinary attachment.
2917 // We currently do this in Scene.MakeRootAgent() instead. 3010 // We currently do this in Scene.MakeRootAgent() instead.
2918 if (AttachmentsModule != null) 3011 if (AttachmentsModule != null)
@@ -2920,18 +3013,60 @@ namespace OpenSim.Region.Framework.Scenes
2920 } 3013 }
2921 else 3014 else
2922 { 3015 {
2923 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 3016 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2924 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 3017// RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
3018// RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
3019 }
3020 if (sceneObject.OwnerID == UUID.Zero)
3021 {
3022 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
3023 return false;
2925 } 3024 }
2926 } 3025 }
2927 else 3026 else
2928 { 3027 {
3028 if (sceneObject.OwnerID == UUID.Zero)
3029 {
3030 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
3031 return false;
3032 }
2929 AddRestoredSceneObject(sceneObject, true, false); 3033 AddRestoredSceneObject(sceneObject, true, false);
2930 } 3034 }
2931 3035
2932 return true; 3036 return true;
2933 } 3037 }
2934 3038
3039 private int GetStateSource(SceneObjectGroup sog)
3040 {
3041 if(!sog.IsAttachmentCheckFull())
3042 return 2; // StateSource.PrimCrossing
3043
3044 ScenePresence sp = GetScenePresence(sog.OwnerID);
3045 if (sp != null)
3046 return sp.GetStateSource();
3047
3048 return 2; // StateSource.PrimCrossing
3049 }
3050
3051 public int GetUserFlags(UUID user)
3052 {
3053 //Unfortunately the SP approach means that the value is cached until region is restarted
3054 /*
3055 ScenePresence sp;
3056 if (TryGetScenePresence(user, out sp))
3057 {
3058 return sp.UserFlags;
3059 }
3060 else
3061 {
3062 */
3063 UserAccount uac = UserAccountService.GetUserAccount(RegionInfo.ScopeID, user);
3064 if (uac == null)
3065 return 0;
3066 return uac.UserFlags;
3067 //}
3068 }
3069
2935 #endregion 3070 #endregion
2936 3071
2937 #region Add/Remove Avatar Methods 3072 #region Add/Remove Avatar Methods
@@ -2968,47 +3103,34 @@ namespace OpenSim.Region.Framework.Scenes
2968 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 3103 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0
2969 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 3104 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2970 3105
2971 // CheckHeartbeat(); 3106 CheckHeartbeat();
2972 3107
2973 sp = GetScenePresence(client.AgentId); 3108 sp = GetScenePresence(client.AgentId);
2974 3109
2975 // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this
2976 // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause
2977 // other problems, and possibly the code calling AddNewAgent() should ensure that no client is already
2978 // connected.
2979 if (sp == null) 3110 if (sp == null)
2980 { 3111 {
2981 m_log.DebugFormat( 3112 m_log.DebugFormat(
2982 "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", 3113 "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}, tpflags: {4}",
2983 client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); 3114 client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos,
2984 3115 ((TPFlags)aCircuit.teleportFlags).ToString());
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 3116
2998 m_clientManager.Add(client); 3117 m_clientManager.Add(client);
2999 SubscribeToClientEvents(client); 3118 SubscribeToClientEvents(client);
3000 m_eventManager.TriggerOnNewPresence(sp); 3119
3120 sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type);
3001 3121
3002 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; 3122 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags;
3123
3124 m_eventManager.TriggerOnNewPresence(sp);
3003 } 3125 }
3004 else 3126 else
3005 { 3127 {
3006 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the 3128 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the
3007 // client is for a root or child agent. 3129 // 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. 3130 // 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 3131 // But need to know what happens in the case where a ScenePresence is already present (and if this
3010 // actually occurs). 3132 // actually occurs).
3011 client.SceneAgent = sp; 3133
3012 3134
3013 m_log.WarnFormat( 3135 m_log.WarnFormat(
3014 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", 3136 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence",
@@ -3016,8 +3138,9 @@ namespace OpenSim.Region.Framework.Scenes
3016 3138
3017 reallyNew = false; 3139 reallyNew = false;
3018 } 3140 }
3141 client.SceneAgent = sp;
3019 3142
3020 // This is currently also being done earlier in NewUserConnection for real users to see if this 3143 // 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 3144 // 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. 3145 // places. However, we still need to do it here for NPCs.
3023 CacheUserName(sp, aCircuit); 3146 CacheUserName(sp, aCircuit);
@@ -3063,7 +3186,7 @@ namespace OpenSim.Region.Framework.Scenes
3063 3186
3064 if (sp != null && sp.PresenceType == PresenceType.Npc) 3187 if (sp != null && sp.PresenceType == PresenceType.Npc)
3065 { 3188 {
3066 UserManagementModule.AddUser(aCircuit.AgentID, first, last); 3189 UserManagementModule.AddUser(aCircuit.AgentID, first, last, true);
3067 } 3190 }
3068 else 3191 else
3069 { 3192 {
@@ -3134,19 +3257,15 @@ namespace OpenSim.Region.Framework.Scenes
3134 // and the scene presence and the client, if they exist 3257 // and the scene presence and the client, if they exist
3135 try 3258 try
3136 { 3259 {
3137 // We need to wait for the client to make UDP contact first.
3138 // It's the UDP contact that creates the scene presence
3139 ScenePresence sp = WaitGetScenePresence(agentID); 3260 ScenePresence sp = WaitGetScenePresence(agentID);
3261
3140 if (sp != null) 3262 if (sp != null)
3141 { 3263 {
3142 PresenceService.LogoutAgent(sp.ControllingClient.SessionId); 3264 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
3143 3265
3144 CloseAgent(sp.UUID, false); 3266 CloseAgent(sp.UUID, false);
3145 } 3267 }
3146 else 3268
3147 {
3148 m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID);
3149 }
3150 // BANG! SLASH! 3269 // BANG! SLASH!
3151 m_authenticateHandler.RemoveCircuit(agentID); 3270 m_authenticateHandler.RemoveCircuit(agentID);
3152 3271
@@ -3183,7 +3302,7 @@ namespace OpenSim.Region.Framework.Scenes
3183 3302
3184 public virtual void SubscribeToClientTerrainEvents(IClientAPI client) 3303 public virtual void SubscribeToClientTerrainEvents(IClientAPI client)
3185 { 3304 {
3186 client.OnRegionHandShakeReply += SendLayerData; 3305// client.OnRegionHandShakeReply += SendLayerData;
3187 } 3306 }
3188 3307
3189 public virtual void SubscribeToClientPrimEvents(IClientAPI client) 3308 public virtual void SubscribeToClientPrimEvents(IClientAPI client)
@@ -3191,6 +3310,8 @@ namespace OpenSim.Region.Framework.Scenes
3191 client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition; 3310 client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition;
3192 client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition; 3311 client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition;
3193 3312
3313 client.onClientChangeObject += m_sceneGraph.ClientChangeObject;
3314
3194 client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation; 3315 client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation;
3195 client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation; 3316 client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation;
3196 client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation; 3317 client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation;
@@ -3204,9 +3325,6 @@ namespace OpenSim.Region.Framework.Scenes
3204 client.OnObjectRequest += RequestPrim; 3325 client.OnObjectRequest += RequestPrim;
3205 client.OnObjectSelect += SelectPrim; 3326 client.OnObjectSelect += SelectPrim;
3206 client.OnObjectDeselect += DeselectPrim; 3327 client.OnObjectDeselect += DeselectPrim;
3207 client.OnGrabUpdate += m_sceneGraph.MoveObject;
3208 client.OnSpinStart += m_sceneGraph.SpinStart;
3209 client.OnSpinUpdate += m_sceneGraph.SpinObject;
3210 client.OnDeRezObject += DeRezObjects; 3328 client.OnDeRezObject += DeRezObjects;
3211 3329
3212 client.OnObjectName += m_sceneGraph.PrimName; 3330 client.OnObjectName += m_sceneGraph.PrimName;
@@ -3222,6 +3340,9 @@ namespace OpenSim.Region.Framework.Scenes
3222 client.OnGrabObject += ProcessObjectGrab; 3340 client.OnGrabObject += ProcessObjectGrab;
3223 client.OnGrabUpdate += ProcessObjectGrabUpdate; 3341 client.OnGrabUpdate += ProcessObjectGrabUpdate;
3224 client.OnDeGrabObject += ProcessObjectDeGrab; 3342 client.OnDeGrabObject += ProcessObjectDeGrab;
3343 client.OnSpinStart += ProcessSpinStart;
3344 client.OnSpinUpdate += ProcessSpinObject;
3345 client.OnSpinStop += ProcessSpinObjectStop;
3225 client.OnUndo += m_sceneGraph.HandleUndo; 3346 client.OnUndo += m_sceneGraph.HandleUndo;
3226 client.OnRedo += m_sceneGraph.HandleRedo; 3347 client.OnRedo += m_sceneGraph.HandleRedo;
3227 client.OnObjectDescription += m_sceneGraph.PrimDescription; 3348 client.OnObjectDescription += m_sceneGraph.PrimDescription;
@@ -3247,6 +3368,7 @@ namespace OpenSim.Region.Framework.Scenes
3247 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory; 3368 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory;
3248 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 3369 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
3249 client.OnCopyInventoryItem += CopyInventoryItem; 3370 client.OnCopyInventoryItem += CopyInventoryItem;
3371 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
3250 client.OnMoveInventoryItem += MoveInventoryItem; 3372 client.OnMoveInventoryItem += MoveInventoryItem;
3251 client.OnRemoveInventoryItem += RemoveInventoryItem; 3373 client.OnRemoveInventoryItem += RemoveInventoryItem;
3252 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 3374 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -3308,7 +3430,7 @@ namespace OpenSim.Region.Framework.Scenes
3308 3430
3309 public virtual void UnSubscribeToClientTerrainEvents(IClientAPI client) 3431 public virtual void UnSubscribeToClientTerrainEvents(IClientAPI client)
3310 { 3432 {
3311 client.OnRegionHandShakeReply -= SendLayerData; 3433// client.OnRegionHandShakeReply -= SendLayerData;
3312 } 3434 }
3313 3435
3314 public virtual void UnSubscribeToClientPrimEvents(IClientAPI client) 3436 public virtual void UnSubscribeToClientPrimEvents(IClientAPI client)
@@ -3316,6 +3438,8 @@ namespace OpenSim.Region.Framework.Scenes
3316 client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition; 3438 client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition;
3317 client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition; 3439 client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition;
3318 3440
3441 client.onClientChangeObject -= m_sceneGraph.ClientChangeObject;
3442
3319 client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation; 3443 client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation;
3320 client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation; 3444 client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation;
3321 client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation; 3445 client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation;
@@ -3329,9 +3453,6 @@ namespace OpenSim.Region.Framework.Scenes
3329 client.OnObjectRequest -= RequestPrim; 3453 client.OnObjectRequest -= RequestPrim;
3330 client.OnObjectSelect -= SelectPrim; 3454 client.OnObjectSelect -= SelectPrim;
3331 client.OnObjectDeselect -= DeselectPrim; 3455 client.OnObjectDeselect -= DeselectPrim;
3332 client.OnGrabUpdate -= m_sceneGraph.MoveObject;
3333 client.OnSpinStart -= m_sceneGraph.SpinStart;
3334 client.OnSpinUpdate -= m_sceneGraph.SpinObject;
3335 client.OnDeRezObject -= DeRezObjects; 3456 client.OnDeRezObject -= DeRezObjects;
3336 client.OnObjectName -= m_sceneGraph.PrimName; 3457 client.OnObjectName -= m_sceneGraph.PrimName;
3337 client.OnObjectClickAction -= m_sceneGraph.PrimClickAction; 3458 client.OnObjectClickAction -= m_sceneGraph.PrimClickAction;
@@ -3344,7 +3465,11 @@ namespace OpenSim.Region.Framework.Scenes
3344 client.OnRequestObjectPropertiesFamily -= m_sceneGraph.RequestObjectPropertiesFamily; 3465 client.OnRequestObjectPropertiesFamily -= m_sceneGraph.RequestObjectPropertiesFamily;
3345 client.OnObjectPermissions -= HandleObjectPermissionsUpdate; 3466 client.OnObjectPermissions -= HandleObjectPermissionsUpdate;
3346 client.OnGrabObject -= ProcessObjectGrab; 3467 client.OnGrabObject -= ProcessObjectGrab;
3468 client.OnGrabUpdate -= ProcessObjectGrabUpdate;
3347 client.OnDeGrabObject -= ProcessObjectDeGrab; 3469 client.OnDeGrabObject -= ProcessObjectDeGrab;
3470 client.OnSpinStart -= ProcessSpinStart;
3471 client.OnSpinUpdate -= ProcessSpinObject;
3472 client.OnSpinStop -= ProcessSpinObjectStop;
3348 client.OnUndo -= m_sceneGraph.HandleUndo; 3473 client.OnUndo -= m_sceneGraph.HandleUndo;
3349 client.OnRedo -= m_sceneGraph.HandleRedo; 3474 client.OnRedo -= m_sceneGraph.HandleRedo;
3350 client.OnObjectDescription -= m_sceneGraph.PrimDescription; 3475 client.OnObjectDescription -= m_sceneGraph.PrimDescription;
@@ -3440,13 +3565,15 @@ namespace OpenSim.Region.Framework.Scenes
3440 /// <param name="GroupID">Group of new object</param> 3565 /// <param name="GroupID">Group of new object</param>
3441 public void DuplicateObject(uint originalPrim, Vector3 offset, uint flags, UUID AgentID, UUID GroupID) 3566 public void DuplicateObject(uint originalPrim, Vector3 offset, uint flags, UUID AgentID, UUID GroupID)
3442 { 3567 {
3443 SceneObjectGroup copy = SceneGraph.DuplicateObject(originalPrim, offset, flags, AgentID, GroupID, Quaternion.Identity); 3568 bool createSelected = (flags & (uint)PrimFlags.CreateSelected) != 0;
3569 SceneObjectGroup copy = SceneGraph.DuplicateObject(originalPrim, offset, AgentID,
3570 GroupID, Quaternion.Identity, createSelected);
3444 if (copy != null) 3571 if (copy != null)
3445 EventManager.TriggerObjectAddedToScene(copy); 3572 EventManager.TriggerObjectAddedToScene(copy);
3446 } 3573 }
3447 3574
3448 /// <summary> 3575 /// <summary>
3449 /// Duplicates object specified by localID at position raycasted against RayTargetObject using 3576 /// Duplicates object specified by localID at position raycasted against RayTargetObject using
3450 /// RayEnd and RayStart to determine what the angle of the ray is 3577 /// RayEnd and RayStart to determine what the angle of the ray is
3451 /// </summary> 3578 /// </summary>
3452 /// <param name="localID">ID of object to duplicate</param> 3579 /// <param name="localID">ID of object to duplicate</param>
@@ -3470,11 +3597,11 @@ namespace OpenSim.Region.Framework.Scenes
3470 SceneObjectPart target = GetSceneObjectPart(localID); 3597 SceneObjectPart target = GetSceneObjectPart(localID);
3471 SceneObjectPart target2 = GetSceneObjectPart(RayTargetObj); 3598 SceneObjectPart target2 = GetSceneObjectPart(RayTargetObj);
3472 3599
3600 bool createSelected = (dupeFlags & (uint)PrimFlags.CreateSelected) != 0;
3601
3473 if (target != null && target2 != null) 3602 if (target != null && target2 != null)
3474 { 3603 {
3475 Vector3 direction = Vector3.Normalize(RayEnd - RayStart); 3604 Vector3 direction = Vector3.Normalize(RayEnd - RayStart);
3476 Vector3 AXOrigin = RayStart;
3477 Vector3 AXdirection = direction;
3478 3605
3479 pos = target2.AbsolutePosition; 3606 pos = target2.AbsolutePosition;
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()); 3607 //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());
@@ -3482,7 +3609,7 @@ namespace OpenSim.Region.Framework.Scenes
3482 // TODO: Raytrace better here 3609 // TODO: Raytrace better here
3483 3610
3484 //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection)); 3611 //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection));
3485 Ray NewRay = new Ray(AXOrigin, AXdirection); 3612 Ray NewRay = new Ray(RayStart,direction);
3486 3613
3487 // Ray Trace against target here 3614 // Ray Trace against target here
3488 EntityIntersection ei = target2.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, CopyCenters); 3615 EntityIntersection ei = target2.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, CopyCenters);
@@ -3513,13 +3640,13 @@ namespace OpenSim.Region.Framework.Scenes
3513 Quaternion worldRot = target2.GetWorldRotation(); 3640 Quaternion worldRot = target2.GetWorldRotation();
3514 3641
3515 // SceneObjectGroup obj = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, worldRot); 3642 // SceneObjectGroup obj = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, worldRot);
3516 copy = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, worldRot); 3643 copy = m_sceneGraph.DuplicateObject(localID, pos, AgentID, GroupID, worldRot, createSelected);
3517 //obj.Rotation = worldRot; 3644 //obj.Rotation = worldRot;
3518 //obj.UpdateGroupRotationR(worldRot); 3645 //obj.UpdateGroupRotationR(worldRot);
3519 } 3646 }
3520 else 3647 else
3521 { 3648 {
3522 copy = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, Quaternion.Identity); 3649 copy = m_sceneGraph.DuplicateObject(localID, pos, AgentID, GroupID, Quaternion.Identity, createSelected);
3523 } 3650 }
3524 3651
3525 if (copy != null) 3652 if (copy != null)
@@ -3553,7 +3680,7 @@ namespace OpenSim.Region.Framework.Scenes
3553 } 3680 }
3554 3681
3555 /// <summary> 3682 /// <summary>
3556 /// Remove the given client from the scene. 3683 /// Remove the given client from the scene.
3557 /// </summary> 3684 /// </summary>
3558 /// <remarks> 3685 /// <remarks>
3559 /// Only clientstack code should call this directly. All other code should call IncomingCloseAgent() instead 3686 /// Only clientstack code should call this directly. All other code should call IncomingCloseAgent() instead
@@ -3564,11 +3691,15 @@ namespace OpenSim.Region.Framework.Scenes
3564 /// <param name='closeChildAgents'> 3691 /// <param name='closeChildAgents'>
3565 /// Close the neighbour child agents associated with this client. 3692 /// Close the neighbour child agents associated with this client.
3566 /// </param> 3693 /// </param>
3694 ///
3695
3696 private object m_removeClientPrivLock = new Object();
3697
3567 public void RemoveClient(UUID agentID, bool closeChildAgents) 3698 public void RemoveClient(UUID agentID, bool closeChildAgents)
3568 { 3699 {
3569 AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID); 3700 AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID);
3570 3701
3571 // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which 3702 // 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 3703 // 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. 3704 // However, will keep for now just in case.
3574 if (acd == null) 3705 if (acd == null)
@@ -3580,13 +3711,13 @@ namespace OpenSim.Region.Framework.Scenes
3580 } 3711 }
3581 3712
3582 // TODO: Can we now remove this lock? 3713 // TODO: Can we now remove this lock?
3583 lock (acd) 3714 lock (m_removeClientPrivLock)
3584 { 3715 {
3585 bool isChildAgent = false; 3716 bool isChildAgent = false;
3586 3717
3587 ScenePresence avatar = GetScenePresence(agentID); 3718 ScenePresence avatar = GetScenePresence(agentID);
3588 3719
3589 // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which 3720 // 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 3721 // 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. 3722 // However, will keep for now just in case.
3592 if (avatar == null) 3723 if (avatar == null)
@@ -3602,7 +3733,7 @@ namespace OpenSim.Region.Framework.Scenes
3602 { 3733 {
3603 isChildAgent = avatar.IsChildAgent; 3734 isChildAgent = avatar.IsChildAgent;
3604 3735
3605 m_log.DebugFormat( 3736 m_log.InfoFormat(
3606 "[SCENE]: Removing {0} agent {1} {2} from {3}", 3737 "[SCENE]: Removing {0} agent {1} {2} from {3}",
3607 isChildAgent ? "child" : "root", avatar.Name, agentID, Name); 3738 isChildAgent ? "child" : "root", avatar.Name, agentID, Name);
3608 3739
@@ -3625,7 +3756,7 @@ namespace OpenSim.Region.Framework.Scenes
3625 // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop 3756 // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop
3626 // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI 3757 // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI
3627 if (closeChildAgents && CapsModule != null) 3758 if (closeChildAgents && CapsModule != null)
3628 CapsModule.RemoveCaps(agentID); 3759 CapsModule.RemoveCaps(agentID, avatar.ControllingClient.CircuitCode);
3629 3760
3630 if (closeChildAgents && !isChildAgent) 3761 if (closeChildAgents && !isChildAgent)
3631 { 3762 {
@@ -3637,13 +3768,17 @@ namespace OpenSim.Region.Framework.Scenes
3637 } 3768 }
3638 3769
3639 m_eventManager.TriggerClientClosed(agentID, this); 3770 m_eventManager.TriggerClientClosed(agentID, this);
3771// m_log.Debug("[Scene]TriggerClientClosed done");
3640 m_eventManager.TriggerOnRemovePresence(agentID); 3772 m_eventManager.TriggerOnRemovePresence(agentID);
3773// m_log.Debug("[Scene]TriggerOnRemovePresence done");
3641 3774
3642 if (!isChildAgent) 3775 if (!isChildAgent)
3643 { 3776 {
3644 if (AttachmentsModule != null) 3777 if (AttachmentsModule != null)
3645 { 3778 {
3779// m_log.Debug("[Scene]DeRezAttachments");
3646 AttachmentsModule.DeRezAttachments(avatar); 3780 AttachmentsModule.DeRezAttachments(avatar);
3781// m_log.Debug("[Scene]DeRezAttachments done");
3647 } 3782 }
3648 3783
3649 ForEachClient( 3784 ForEachClient(
@@ -3657,7 +3792,11 @@ namespace OpenSim.Region.Framework.Scenes
3657 3792
3658 // It's possible for child agents to have transactions if changes are being made cross-border. 3793 // It's possible for child agents to have transactions if changes are being made cross-border.
3659 if (AgentTransactionsModule != null) 3794 if (AgentTransactionsModule != null)
3795 {
3796// m_log.Debug("[Scene]RemoveAgentAssetTransactions");
3660 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); 3797 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID);
3798 }
3799 m_log.Debug("[Scene] The avatar has left the building");
3661 } 3800 }
3662 catch (Exception e) 3801 catch (Exception e)
3663 { 3802 {
@@ -3691,7 +3830,7 @@ namespace OpenSim.Region.Framework.Scenes
3691 3830
3692 /// <summary> 3831 /// <summary>
3693 /// Removes region from an avatar's known region list. This coincides with child agents. For each child agent, there will be a known region entry. 3832 /// Removes region from an avatar's known region list. This coincides with child agents. For each child agent, there will be a known region entry.
3694 /// 3833 ///
3695 /// </summary> 3834 /// </summary>
3696 /// <param name="avatarID"></param> 3835 /// <param name="avatarID"></param>
3697 /// <param name="regionslst"></param> 3836 /// <param name="regionslst"></param>
@@ -3721,15 +3860,9 @@ namespace OpenSim.Region.Framework.Scenes
3721 foreach (uint localID in localIDs) 3860 foreach (uint localID in localIDs)
3722 { 3861 {
3723 SceneObjectPart part = GetSceneObjectPart(localID); 3862 SceneObjectPart part = GetSceneObjectPart(localID);
3724 if (part != null) // It is a prim 3863 if (part != null && part.ParentGroup != null &&
3725 { 3864 part.ParentGroup.RootPart == part)
3726 if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid 3865 deleteIDs.Add(localID);
3727 {
3728 if (part.ParentGroup.RootPart != part) // Child part
3729 continue;
3730 }
3731 }
3732 deleteIDs.Add(localID);
3733 } 3866 }
3734 3867
3735 ForEachClient(c => c.SendKillObject(deleteIDs)); 3868 ForEachClient(c => c.SendKillObject(deleteIDs));
@@ -3746,7 +3879,7 @@ namespace OpenSim.Region.Framework.Scenes
3746 /// <param name="teleportFlags"></param> 3879 /// <param name="teleportFlags"></param>
3747 /// <param name="source">Source region (may be null)</param> 3880 /// <param name="source">Source region (may be null)</param>
3748 /// <param name="reason">Outputs the reason for the false response on this string</param> 3881 /// <param name="reason">Outputs the reason for the false response on this string</param>
3749 /// <returns>True if the region accepts this agent. False if it does not. False will 3882 /// <returns>True if the region accepts this agent. False if it does not. False will
3750 /// also return a reason.</returns> 3883 /// also return a reason.</returns>
3751 public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, GridRegion source, out string reason) 3884 public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, GridRegion source, out string reason)
3752 { 3885 {
@@ -3774,14 +3907,17 @@ namespace OpenSim.Region.Framework.Scenes
3774 /// <param name="reason">Outputs the reason for the false response on this string</param> 3907 /// <param name="reason">Outputs the reason for the false response on this string</param>
3775 /// <param name="requirePresenceLookup">True for normal presence. False for NPC 3908 /// <param name="requirePresenceLookup">True for normal presence. False for NPC
3776 /// or other applications where a full grid/Hypergrid presence may not be required.</param> 3909 /// or other applications where a full grid/Hypergrid presence may not be required.</param>
3777 /// <returns>True if the region accepts this agent. False if it does not. False will 3910 /// <returns>True if the region accepts this agent. False if it does not. False will
3778 /// also return a reason.</returns> 3911 /// also return a reason.</returns>
3912 ///
3913 private object m_newUserConnLock = new object();
3914
3779 public bool NewUserConnection(AgentCircuitData acd, uint teleportFlags, GridRegion source, out string reason, bool requirePresenceLookup) 3915 public bool NewUserConnection(AgentCircuitData acd, uint teleportFlags, GridRegion source, out string reason, bool requirePresenceLookup)
3780 { 3916 {
3781 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 || 3917 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 ||
3782 (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0); 3918 (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0);
3783 bool viahome = ((teleportFlags & (uint)TPFlags.ViaHome) != 0); 3919 bool viahome = ((teleportFlags & (uint)TPFlags.ViaHome) != 0);
3784 bool godlike = ((teleportFlags & (uint)TPFlags.Godlike) != 0); 3920// bool godlike = ((teleportFlags & (uint)TPFlags.Godlike) != 0);
3785 3921
3786 reason = String.Empty; 3922 reason = String.Empty;
3787 3923
@@ -3809,9 +3945,11 @@ namespace OpenSim.Region.Framework.Scenes
3809 (source == null) ? "" : string.Format("From region {0} ({1}){2}", source.RegionName, source.RegionID, (source.RawServerURI == null) ? "" : " @ " + source.ServerURI) 3945 (source == null) ? "" : string.Format("From region {0} ({1}){2}", source.RegionName, source.RegionID, (source.RawServerURI == null) ? "" : " @ " + source.ServerURI)
3810 ); 3946 );
3811 3947
3948// m_log.DebugFormat("NewUserConnection stack {0}", Environment.StackTrace);
3949
3812 if (!LoginsEnabled) 3950 if (!LoginsEnabled)
3813 { 3951 {
3814 reason = "Logins Disabled"; 3952 reason = "Logins to this region are disabled";
3815 return false; 3953 return false;
3816 } 3954 }
3817 3955
@@ -3858,14 +3996,13 @@ namespace OpenSim.Region.Framework.Scenes
3858 return false; 3996 return false;
3859 } 3997 }
3860 3998
3861 ILandObject land;
3862 ScenePresence sp; 3999 ScenePresence sp;
3863 4000
3864 lock (m_removeClientLock) 4001 lock (m_removeClientLock)
3865 { 4002 {
3866 sp = GetScenePresence(acd.AgentID); 4003 sp = GetScenePresence(acd.AgentID);
3867 4004
3868 // We need to ensure that we are not already removing the scene presence before we ask it not to be 4005 // We need to ensure that we are not already removing the scene presence before we ask it not to be
3869 // closed. 4006 // closed.
3870 if (sp != null && sp.IsChildAgent 4007 if (sp != null && sp.IsChildAgent
3871 && (sp.LifecycleState == ScenePresenceState.Running 4008 && (sp.LifecycleState == ScenePresenceState.Running
@@ -3879,16 +4016,16 @@ namespace OpenSim.Region.Framework.Scenes
3879 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. When C 4016 // 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. 4017 // renews the lease on the child agent at B, we must make sure that the close from A does not succeed.
3881 // 4018 //
3882 // XXX: In the end, this should not be necessary if child agents are closed without delay on 4019 // 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 4020 // 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 4021 // 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 4022 // 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 4023 // 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). 4024 // flag when no teleport had taken place (and hence no close was going to come).
3888// if (!acd.ChildrenCapSeeds.ContainsKey(RegionInfo.RegionHandle)) 4025// if (!acd.ChildrenCapSeeds.ContainsKey(RegionInfo.RegionHandle))
3889// { 4026// {
3890// m_log.DebugFormat( 4027// m_log.DebugFormat(
3891// "[SCENE]: Setting DoNotCloseAfterTeleport for child scene presence {0} in {1} because source will attempt close.", 4028// "[SCENE]: Setting DoNotCloseAfterTeleport for child scene presence {0} in {1} because source will attempt close.",
3892// sp.Name, Name); 4029// sp.Name, Name);
3893// 4030//
3894// sp.DoNotCloseAfterTeleport = true; 4031// sp.DoNotCloseAfterTeleport = true;
@@ -3902,7 +4039,7 @@ namespace OpenSim.Region.Framework.Scenes
3902 sp.DoNotCloseAfterTeleport = true; 4039 sp.DoNotCloseAfterTeleport = true;
3903 4040
3904 m_log.DebugFormat( 4041 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.", 4042 "[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); 4043 sp.Name, Name);
3907 } 4044 }
3908 } 4045 }
@@ -3922,7 +4059,7 @@ namespace OpenSim.Region.Framework.Scenes
3922 if (sp.LifecycleState == ScenePresenceState.Removing) 4059 if (sp.LifecycleState == ScenePresenceState.Removing)
3923 { 4060 {
3924 m_log.WarnFormat( 4061 m_log.WarnFormat(
3925 "[SCENE]: Agent {0} in {1} was still being removed after {2}s. Aborting NewUserConnection.", 4062 "[SCENE]: Agent {0} in {1} was still being removed after {2}s. Aborting NewUserConnection.",
3926 sp.Name, Name, polls * pollInterval / 1000); 4063 sp.Name, Name, polls * pollInterval / 1000);
3927 4064
3928 return false; 4065 return false;
@@ -3936,14 +4073,14 @@ namespace OpenSim.Region.Framework.Scenes
3936 } 4073 }
3937 4074
3938 // TODO: can we remove this lock? 4075 // TODO: can we remove this lock?
3939 lock (acd) 4076 lock (m_newUserConnLock)
3940 { 4077 {
3941 if (sp != null && !sp.IsChildAgent) 4078 if (sp != null && !sp.IsChildAgent)
3942 { 4079 {
3943 // We have a root agent. Is it in transit? 4080 // We have a root agent. Is it in transit?
3944 if (!EntityTransferModule.IsInTransit(sp.UUID)) 4081 if (!EntityTransferModule.IsInTransit(sp.UUID))
3945 { 4082 {
3946 // We have a zombie from a crashed session. 4083 // We have a zombie from a crashed session.
3947 // Or the same user is trying to be root twice here, won't work. 4084 // Or the same user is trying to be root twice here, won't work.
3948 // Kill it. 4085 // Kill it.
3949 m_log.WarnFormat( 4086 m_log.WarnFormat(
@@ -3963,20 +4100,21 @@ namespace OpenSim.Region.Framework.Scenes
3963 // We need the circuit data here for some of the subsequent checks. (groups, for example) 4100 // We need the circuit data here for some of the subsequent checks. (groups, for example)
3964 // If the checks fail, we remove the circuit. 4101 // If the checks fail, we remove the circuit.
3965 acd.teleportFlags = teleportFlags; 4102 acd.teleportFlags = teleportFlags;
3966 m_authenticateHandler.AddNewCircuit(acd.circuitcode, acd);
3967
3968 land = LandChannel.GetLandObject(acd.startpos.X, acd.startpos.Y);
3969 4103
3970 // On login test land permisions
3971 if (vialogin) 4104 if (vialogin)
3972 { 4105 {
3973 if (land != null && !TestLandRestrictions(acd.AgentID, out reason, ref acd.startpos.X, ref acd.startpos.Y)) 4106 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3974 { 4107 if (cache != null)
3975 m_authenticateHandler.RemoveCircuit(acd.circuitcode); 4108// cache.Remove(acd.firstname + " " + acd.lastname);
3976 return false; 4109 cache.Remove(acd.AgentID);
3977 } 4110
4111 // Remove any preexisting circuit - we don't want duplicates
4112 // This is a stab at preventing avatar "ghosting"
4113 m_authenticateHandler.RemoveCircuit(acd.AgentID);
3978 } 4114 }
3979 4115
4116 m_authenticateHandler.AddNewCircuit(acd.circuitcode, acd);
4117
3980 if (sp == null) // We don't have an [child] agent here already 4118 if (sp == null) // We don't have an [child] agent here already
3981 { 4119 {
3982 if (requirePresenceLookup) 4120 if (requirePresenceLookup)
@@ -4024,7 +4162,7 @@ namespace OpenSim.Region.Framework.Scenes
4024 if (CapsModule != null) 4162 if (CapsModule != null)
4025 { 4163 {
4026 CapsModule.SetAgentCapsSeeds(acd); 4164 CapsModule.SetAgentCapsSeeds(acd);
4027 CapsModule.CreateCaps(acd.AgentID); 4165 CapsModule.CreateCaps(acd.AgentID, acd.circuitcode);
4028 } 4166 }
4029 } 4167 }
4030 else 4168 else
@@ -4039,13 +4177,13 @@ namespace OpenSim.Region.Framework.Scenes
4039 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", 4177 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
4040 acd.AgentID, RegionInfo.RegionName); 4178 acd.AgentID, RegionInfo.RegionName);
4041 4179
4042 sp.AdjustKnownSeeds();
4043
4044 if (CapsModule != null) 4180 if (CapsModule != null)
4045 { 4181 {
4046 CapsModule.SetAgentCapsSeeds(acd); 4182 CapsModule.SetAgentCapsSeeds(acd);
4047 CapsModule.CreateCaps(acd.AgentID); 4183 CapsModule.CreateCaps(acd.AgentID, acd.circuitcode);
4048 } 4184 }
4185
4186 sp.AdjustKnownSeeds();
4049 } 4187 }
4050 } 4188 }
4051 4189
@@ -4055,88 +4193,48 @@ namespace OpenSim.Region.Framework.Scenes
4055 CacheUserName(null, acd); 4193 CacheUserName(null, acd);
4056 } 4194 }
4057 4195
4058 if (vialogin) 4196 if (CapsModule != null)
4059 { 4197 {
4060// CleanDroppedAttachments(); 4198 CapsModule.ActivateCaps(acd.circuitcode);
4061 4199 }
4062 // Make sure avatar position is in the region (why it wouldn't be is a mystery but do sanity checking)
4063 if (acd.startpos.X < 0) acd.startpos.X = 1f;
4064 if (acd.startpos.X >= RegionInfo.RegionSizeX) acd.startpos.X = RegionInfo.RegionSizeX - 1f;
4065 if (acd.startpos.Y < 0) acd.startpos.Y = 1f;
4066 if (acd.startpos.Y >= RegionInfo.RegionSizeY) acd.startpos.Y = RegionInfo.RegionSizeY - 1f;
4067
4068// m_log.DebugFormat(
4069// "[SCENE]: Found telehub object {0} for new user connection {1} to {2}",
4070// RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
4071
4072 // Honor Estate teleport routing via Telehubs excluding ViaHome and GodLike TeleportFlags
4073 if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero &&
4074 RegionInfo.EstateSettings.AllowDirectTeleport == false &&
4075 !viahome && !godlike)
4076 {
4077 SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject);
4078
4079 if (telehub != null)
4080 {
4081 // Can have multiple SpawnPoints
4082 List<SpawnPoint> spawnpoints = RegionInfo.RegionSettings.SpawnPoints();
4083 if (spawnpoints.Count > 1)
4084 {
4085 // We have multiple SpawnPoints, Route the agent to a random or sequential one
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 }
4102 else
4103 {
4104 m_log.DebugFormat(
4105 "[SCENE]: No spawnpoints defined for telehub {0} for {1} in {2}. Continuing.",
4106 RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
4107 }
4108 }
4109 else
4110 {
4111 m_log.DebugFormat(
4112 "[SCENE]: No telehub {0} found to direct {1} in {2}. Continuing.",
4113 RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
4114 }
4115 4200
4116 // Final permissions check; this time we don't allow changing the position 4201// if (vialogin)
4117 if (!IsPositionAllowed(acd.AgentID, acd.startpos, ref reason)) 4202// {
4118 { 4203// CleanDroppedAttachments();
4119 m_authenticateHandler.RemoveCircuit(acd.circuitcode); 4204// }
4120 return false;
4121 }
4122 4205
4123 return true; 4206 if(teleportFlags != (uint) TPFlags.Default)
4124 } 4207 {
4208 // Make sure root avatar position is in the region
4209 if (acd.startpos.X < 0)
4210 acd.startpos.X = 1f;
4211 else if (acd.startpos.X >= RegionInfo.RegionSizeX)
4212 acd.startpos.X = RegionInfo.RegionSizeX - 1f;
4213 if (acd.startpos.Y < 0)
4214 acd.startpos.Y = 1f;
4215 else if (acd.startpos.Y >= RegionInfo.RegionSizeY)
4216 acd.startpos.Y = RegionInfo.RegionSizeY - 1f;
4217 }
4218 // only check access, actual relocations will happen later on ScenePresence MakeRoot
4219 // allow child agents creation
4220// if(!godlike && teleportFlags != (uint) TPFlags.Default)
4221 if(teleportFlags != (uint) TPFlags.Default)
4222 {
4223 bool checkTeleHub;
4224
4225 // don't check hubs if via home or via lure
4226 if((teleportFlags & (uint) TPFlags.ViaHome) != 0
4227 || (teleportFlags & (uint) TPFlags.ViaLure) != 0)
4228 checkTeleHub = false;
4229 else
4230 checkTeleHub = vialogin
4231 || (TelehubAllowLandmarks == true ? false : ((teleportFlags & (uint)TPFlags.ViaLandmark) != 0 ))
4232 || (teleportFlags & (uint) TPFlags.ViaLocation) != 0;
4125 4233
4126 // Honor parcel landing type and position. 4234 if(!CheckLandPositionAccess(acd.AgentID, true, checkTeleHub, acd.startpos, out reason))
4127 if (land != null)
4128 { 4235 {
4129 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 4236 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
4130 { 4237 return false;
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 }
4139 }
4140 } 4238 }
4141 } 4239 }
4142 4240
@@ -4162,12 +4260,13 @@ namespace OpenSim.Region.Framework.Scenes
4162 { 4260 {
4163 if (posX < 0) 4261 if (posX < 0)
4164 posX = 0; 4262 posX = 0;
4165 else if (posX >= (float)RegionInfo.RegionSizeX) 4263
4166 posX = (float)RegionInfo.RegionSizeX - 0.001f; 4264 else if (posX >= RegionInfo.RegionSizeX)
4265 posX = RegionInfo.RegionSizeX - 0.5f;
4167 if (posY < 0) 4266 if (posY < 0)
4168 posY = 0; 4267 posY = 0;
4169 else if (posY >= (float)RegionInfo.RegionSizeY) 4268 else if (posY >= RegionInfo.RegionSizeY)
4170 posY = (float)RegionInfo.RegionSizeY - 0.001f; 4269 posY = RegionInfo.RegionSizeY - 0.5f;
4171 4270
4172 reason = String.Empty; 4271 reason = String.Empty;
4173 if (Permissions.IsGod(agentID)) 4272 if (Permissions.IsGod(agentID))
@@ -4183,14 +4282,14 @@ namespace OpenSim.Region.Framework.Scenes
4183 if (banned || restricted) 4282 if (banned || restricted)
4184 { 4283 {
4185 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY); 4284 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY);
4285 Vector2? newPosition = null;
4186 if (nearestParcel != null) 4286 if (nearestParcel != null)
4187 { 4287 {
4188 //Move agent to nearest allowed 4288 //Move agent to nearest allowed
4189 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); 4289// Vector2 newPosition = GetParcelSafeCorner(nearestParcel);
4190 posX = newPosition.X; 4290 newPosition = nearestParcel.GetNearestPoint(new Vector3(posX, posY,0));
4191 posY = newPosition.Y;
4192 } 4291 }
4193 else 4292 if(newPosition == null)
4194 { 4293 {
4195 if (banned) 4294 if (banned)
4196 { 4295 {
@@ -4203,6 +4302,11 @@ namespace OpenSim.Region.Framework.Scenes
4203 } 4302 }
4204 return false; 4303 return false;
4205 } 4304 }
4305 else
4306 {
4307 posX = newPosition.Value.X;
4308 posY = newPosition.Value.Y;
4309 }
4206 } 4310 }
4207 reason = ""; 4311 reason = "";
4208 return true; 4312 return true;
@@ -4213,7 +4317,7 @@ namespace OpenSim.Region.Framework.Scenes
4213 /// </summary> 4317 /// </summary>
4214 /// <param name="agent">Circuit Data of the Agent we're verifying</param> 4318 /// <param name="agent">Circuit Data of the Agent we're verifying</param>
4215 /// <param name="reason">Outputs the reason for the false response on this string</param> 4319 /// <param name="reason">Outputs the reason for the false response on this string</param>
4216 /// <returns>True if the user has a session on the grid. False if it does not. False will 4320 /// <returns>True if the user has a session on the grid. False if it does not. False will
4217 /// also return a reason.</returns> 4321 /// also return a reason.</returns>
4218 public virtual bool VerifyUserPresence(AgentCircuitData agent, out string reason) 4322 public virtual bool VerifyUserPresence(AgentCircuitData agent, out string reason)
4219 { 4323 {
@@ -4242,19 +4346,22 @@ namespace OpenSim.Region.Framework.Scenes
4242 /// </summary> 4346 /// </summary>
4243 /// <param name="agent">The circuit data for the agent</param> 4347 /// <param name="agent">The circuit data for the agent</param>
4244 /// <param name="reason">outputs the reason to this string</param> 4348 /// <param name="reason">outputs the reason to this string</param>
4245 /// <returns>True if the region accepts this agent. False if it does not. False will 4349 /// <returns>True if the region accepts this agent. False if it does not. False will
4246 /// also return a reason.</returns> 4350 /// also return a reason.</returns>
4247 protected virtual bool AuthorizeUser(AgentCircuitData agent, bool bypassAccessControl, out string reason) 4351 protected virtual bool AuthorizeUser(AgentCircuitData agent, bool bypassAccessControl, out string reason)
4248 { 4352 {
4249 reason = String.Empty; 4353 reason = String.Empty;
4354 bool isLocal = false;
4250 4355
4251 if (!m_strictAccessControl) return true; 4356 if (!m_strictAccessControl)
4252 if (Permissions.IsGod(agent.AgentID)) return true; 4357 return true;
4358 if (Permissions.IsGod(agent.AgentID))
4359 return true;
4253 4360
4254 if (AuthorizationService != null) 4361 if (AuthorizationService != null)
4255 { 4362 {
4256 if (!AuthorizationService.IsAuthorizedForRegion( 4363 if (!AuthorizationService.IsAuthorizedForRegion(
4257 agent.AgentID.ToString(), agent.firstname, agent.lastname, RegionInfo.RegionID.ToString(), out reason)) 4364 agent.AgentID.ToString(), agent.firstname, agent.lastname, RegionInfo.RegionID.ToString(), out reason, out isLocal))
4258 { 4365 {
4259 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because: {4}", 4366 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because: {4}",
4260 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName, reason); 4367 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName, reason);
@@ -4269,98 +4376,152 @@ namespace OpenSim.Region.Framework.Scenes
4269 // the root is done elsewhere (QueryAccess) 4376 // the root is done elsewhere (QueryAccess)
4270 if (!bypassAccessControl) 4377 if (!bypassAccessControl)
4271 { 4378 {
4272 if (RegionInfo.EstateSettings != null) 4379 if(RegionInfo.EstateSettings == null)
4273 { 4380 {
4274 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID)) 4381 // something is broken? let it get in
4275 { 4382 m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!");
4276 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 4383 return true;
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 }
4282 } 4384 }
4283 else 4385
4386 // check estate ban
4387 int flags = GetUserFlags(agent.AgentID);
4388 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, flags))
4284 { 4389 {
4285 m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!"); 4390 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
4391 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
4392 reason = String.Format("Denied access to region {0}: You have been banned from that region.",
4393 RegionInfo.RegionName);
4394 return false;
4286 } 4395 }
4287 4396
4288 List<UUID> agentGroups = new List<UUID>(); 4397 List<UUID> agentGroups = new List<UUID>();
4398 GroupMembershipData[] GroupMembership = null;
4399 if(m_groupsModule != null)
4400 GroupMembership = m_groupsModule.GetMembershipData(agent.AgentID);
4401
4402 if (null != GroupMembership)
4403 {
4404 for(int i = 0;i < GroupMembership.Length;i++)
4405 agentGroups.Add(GroupMembership[i].GroupID);
4406 // We get called twice, the first time the name is set to a single space.
4407 // The first time is from QueryAccess(), the second from NewUserConnection()
4408// if (" " != agent.Name)
4409 {
4410 string grid = "";
4411 if (isLocal)
4412 {
4413 grid = "local";
4414 m_log.InfoFormat("[CONNECTION BEGIN]: LOCAL agent {0} {1} {2} {3}, checking auto groups.", agent.firstname, agent.lastname, agent.Name, agent.AgentID);
4415 }
4416 else
4417 {
4418 // agent.AgentID could look like this - @grid.com:8002 01234567-89ab-cdef-0123-456789abcdef
4419 // Or agent.lastname could.
4420 string a = agent.AgentID.ToString();
4421 if ("@" == a.Substring(0, 1))
4422 {
4423 grid = a.Split(':')[0].Substring(1);
4424 m_log.InfoFormat("[CONNECTION BEGIN]: HYPERGRID agent {0} from grid {1}, checking auto groups.", agent.AgentID, grid);
4425 }
4426 else
4427 {
4428 a = agent.lastname;
4429 if (String.Empty != a)
4430 {
4431 if ("@" == a.Substring(0, 1))
4432 {
4433 grid = a.Split(':')[0].Substring(1);
4434 m_log.InfoFormat("[CONNECTION BEGIN]: HYPERGRID agent {0} from grid {1}, checking auto groups.", agent.firstname, grid);
4435 }
4436 }
4437 }
4438 }
4439 string[] groupIDs = null;
4440 try
4441 {
4442 groupIDs = m_AutoGroups[grid];
4443 }
4444 catch (KeyNotFoundException)
4445 {
4446 // Do nothing.
4447 }
4448 if (null != groupIDs)
4449 {
4450 foreach(string name in groupIDs)
4451 {
4452 GroupRecord g = m_groupsModule.GetGroupRecord(name);
4453 if (null != g)
4454 {
4455 UUID group = g.GroupID;
4456 if(!agentGroups.Contains(group))
4457 {
4458 m_groupsModule.JoinGroup(agent.AgentID.ToString(), group);
4459 agentGroups.Add(group);
4460 m_log.InfoFormat("[CONNECTION BEGIN]: Automatically added {0} to group {1}.", agent.AgentID, name);
4461 }
4462 }
4463 else
4464 m_log.ErrorFormat("[CONNECTION BEGIN]: Bogus group {0}, not adding {1}.", name, agent.AgentID);
4465 }
4466 }
4467 }
4468 }
4469
4470 // public access
4471 if (RegionInfo.EstateSettings.PublicAccess)
4472 return true;
4473
4474 // in access list / owner / manager
4475 if (RegionInfo.EstateSettings.HasAccess(agent.AgentID))
4476 return true;
4477
4478 // finally test groups
4479 bool groupAccess = false;
4289 4480
4290 if (m_groupsModule != null) 4481 // some say GOTO is ugly
4482 if(m_groupsModule == null) // if no groups refuse
4483 goto Label_GroupsDone;
4484
4485 UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups;
4486
4487 if(estateGroups == null)
4291 { 4488 {
4292 GroupMembershipData[] GroupMembership = m_groupsModule.GetMembershipData(agent.AgentID); 4489 m_log.ErrorFormat("[CONNECTION BEGIN]: Estate GroupMembership is null!");
4490 goto Label_GroupsDone;
4491 }
4293 4492
4294 if (GroupMembership != null) 4493 if(estateGroups.Length == 0)
4295 { 4494 goto Label_GroupsDone;
4296 for (int i = 0; i < GroupMembership.Length; i++) 4495
4297 agentGroups.Add(GroupMembership[i].GroupID); 4496 if(GroupMembership == null)
4298 } 4497 {
4299 else 4498 m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!");
4300 { 4499 goto Label_GroupsDone;
4301 m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!");
4302 }
4303 } 4500 }
4304 4501
4305 bool groupAccess = false; 4502 if(GroupMembership.Length == 0)
4306 UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups; 4503 goto Label_GroupsDone;
4307 4504
4308 if (estateGroups != null) 4505 foreach(UUID group in estateGroups)
4309 { 4506 {
4310 foreach (UUID group in estateGroups) 4507 if(agentGroups.Contains(group))
4311 { 4508 {
4312 if (agentGroups.Contains(group)) 4509 groupAccess = true;
4313 { 4510 break;
4314 groupAccess = true;
4315 break;
4316 }
4317 } 4511 }
4318 } 4512 }
4319 else
4320 {
4321 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!");
4322 }
4323 4513
4324 if (!RegionInfo.EstateSettings.PublicAccess && 4514Label_GroupsDone:
4325 !RegionInfo.EstateSettings.HasAccess(agent.AgentID) && 4515 if (!groupAccess)
4326 !groupAccess)
4327 { 4516 {
4328 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate", 4517 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); 4518 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.", 4519 reason = String.Format("Denied access to private region {0}: You do not have access to that region.",
4331 RegionInfo.RegionName); 4520 RegionInfo.RegionName);
4332 return false; 4521 return false;
4333 } 4522 }
4334 } 4523 }
4335 4524
4336 // TODO: estate/region settings are not properly hooked up
4337 // to ILandObject.isRestrictedFromLand()
4338 // if (null != LandChannel)
4339 // {
4340 // // region seems to have local Id of 1
4341 // ILandObject land = LandChannel.GetLandObject(1);
4342 // if (null != land)
4343 // {
4344 // if (land.isBannedFromLand(agent.AgentID))
4345 // {
4346 // m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user has been banned from land",
4347 // agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
4348 // reason = String.Format("Denied access to private region {0}: You are banned from that region.",
4349 // RegionInfo.RegionName);
4350 // return false;
4351 // }
4352
4353 // if (land.isRestrictedFromLand(agent.AgentID))
4354 // {
4355 // m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region",
4356 // agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
4357 // reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.",
4358 // RegionInfo.RegionName);
4359 // return false;
4360 // }
4361 // }
4362 // }
4363
4364 return true; 4525 return true;
4365 } 4526 }
4366 4527
@@ -4449,7 +4610,7 @@ namespace OpenSim.Region.Framework.Scenes
4449// } 4610// }
4450 4611
4451 /// <summary> 4612 /// <summary>
4452 /// We've got an update about an agent that sees into this region, 4613 /// We've got an update about an agent that sees into this region,
4453 /// send it to ScenePresence for processing It's the full data. 4614 /// send it to ScenePresence for processing It's the full data.
4454 /// </summary> 4615 /// </summary>
4455 /// <param name="cAgentData">Agent that contains all of the relevant things about an agent. 4616 /// <param name="cAgentData">Agent that contains all of the relevant things about an agent.
@@ -4460,8 +4621,25 @@ namespace OpenSim.Region.Framework.Scenes
4460 m_log.DebugFormat( 4621 m_log.DebugFormat(
4461 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName); 4622 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName);
4462 4623
4624 if (!LoginsEnabled)
4625 {
4626// reason = "Logins Disabled";
4627 m_log.DebugFormat(
4628 "[SCENE]: update for {0} in {1} refused: Logins Disabled", cAgentData.AgentID, RegionInfo.RegionName);
4629 return false;
4630 }
4631 // We have to wait until the viewer contacts this region after receiving EAC.
4632 // That calls AddNewClient, which finally creates the ScenePresence
4633 int flags = GetUserFlags(cAgentData.AgentID);
4634 if (RegionInfo.EstateSettings.IsBanned(cAgentData.AgentID, flags))
4635 {
4636 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
4637 return false;
4638 }
4639
4463 // TODO: This check should probably be in QueryAccess(). 4640 // TODO: This check should probably be in QueryAccess().
4464 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, RegionInfo.RegionSizeX / 2, RegionInfo.RegionSizeY / 2); 4641 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID,
4642 (float)RegionInfo.RegionSizeX * 0.5f, (float)RegionInfo.RegionSizeY * 0.5f);
4465 if (nearestParcel == null) 4643 if (nearestParcel == null)
4466 { 4644 {
4467 m_log.InfoFormat( 4645 m_log.InfoFormat(
@@ -4472,20 +4650,26 @@ namespace OpenSim.Region.Framework.Scenes
4472 } 4650 }
4473 4651
4474 // We have to wait until the viewer contacts this region 4652 // We have to wait until the viewer contacts this region
4475 // after receiving the EnableSimulator HTTP Event Queue message (for the v1 teleport protocol) 4653 // after receiving the EnableSimulator HTTP Event Queue message (for the v1 teleport protocol)
4476 // or TeleportFinish (for the v2 teleport protocol). This triggers the viewer to send 4654 // or TeleportFinish (for the v2 teleport protocol). This triggers the viewer to send
4477 // a UseCircuitCode packet which in turn calls AddNewAgent which finally creates the ScenePresence. 4655 // a UseCircuitCode packet which in turn calls AddNewAgent which finally creates the ScenePresence.
4478 ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID); 4656 ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID);
4479 4657
4480 if (sp != null) 4658 if (sp != null)
4481 { 4659 {
4660 if (!sp.IsChildAgent)
4661 {
4662 m_log.WarnFormat("[SCENE]: Ignoring a child update on a root agent {0} {1} in {2}",
4663 sp.Name, sp.UUID, Name);
4664 return false;
4665 }
4482 if (cAgentData.SessionID != sp.ControllingClient.SessionId) 4666 if (cAgentData.SessionID != sp.ControllingClient.SessionId)
4483 { 4667 {
4484 m_log.WarnFormat( 4668 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).", 4669 "[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); 4670 sp.UUID, cAgentData.SessionID);
4487 4671
4488 Console.WriteLine(String.Format("[SCENE]: Attempt to update agent {0} ({1}) with invalid session id {2}", 4672 Console.WriteLine(String.Format("[SCENE]: Attempt to update agent {0} ({1}) with invalid session id {2}",
4489 sp.UUID, sp.ControllingClient.SessionId, cAgentData.SessionID)); 4673 sp.UUID, sp.ControllingClient.SessionId, cAgentData.SessionID));
4490 } 4674 }
4491 4675
@@ -4517,7 +4701,7 @@ namespace OpenSim.Region.Framework.Scenes
4517 } 4701 }
4518 4702
4519 /// <summary> 4703 /// <summary>
4520 /// We've got an update about an agent that sees into this region, 4704 /// We've got an update about an agent that sees into this region,
4521 /// send it to ScenePresence for processing It's only positional data 4705 /// send it to ScenePresence for processing It's only positional data
4522 /// </summary> 4706 /// </summary>
4523 /// <param name="cAgentData">AgentPosition that contains agent positional data so we can know what to send</param> 4707 /// <param name="cAgentData">AgentPosition that contains agent positional data so we can know what to send</param>
@@ -4525,7 +4709,7 @@ namespace OpenSim.Region.Framework.Scenes
4525 public virtual bool IncomingUpdateChildAgent(AgentPosition cAgentData) 4709 public virtual bool IncomingUpdateChildAgent(AgentPosition cAgentData)
4526 { 4710 {
4527// m_log.DebugFormat( 4711// m_log.DebugFormat(
4528// "[SCENE PRESENCE]: IncomingChildAgentDataUpdate POSITION for {0} in {1}, position {2}", 4712// "[SCENE PRESENCE]: IncomingChildAgentDataUpdate POSITION for {0} in {1}, position {2}",
4529// cAgentData.AgentID, Name, cAgentData.Position); 4713// cAgentData.AgentID, Name, cAgentData.Position);
4530 4714
4531 ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID); 4715 ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID);
@@ -4533,7 +4717,7 @@ namespace OpenSim.Region.Framework.Scenes
4533 { 4717 {
4534// if (childAgentUpdate.ControllingClient.SessionId != cAgentData.SessionID) 4718// if (childAgentUpdate.ControllingClient.SessionId != cAgentData.SessionID)
4535// // Only warn for now 4719// // 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?", 4720// 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); 4721// childAgentUpdate.UUID, cAgentData.SessionID);
4538 4722
4539 // I can't imagine *yet* why we would get an update if the agent is a root agent.. 4723 // I can't imagine *yet* why we would get an update if the agent is a root agent..
@@ -4563,10 +4747,10 @@ namespace OpenSim.Region.Framework.Scenes
4563 /// <param name='agentID'></param> 4747 /// <param name='agentID'></param>
4564 protected virtual ScenePresence WaitGetScenePresence(UUID agentID) 4748 protected virtual ScenePresence WaitGetScenePresence(UUID agentID)
4565 { 4749 {
4566 int ntimes = 20; 4750 int ntimes = 120; // 30s
4567 ScenePresence sp = null; 4751 ScenePresence sp = null;
4568 while ((sp = GetScenePresence(agentID)) == null && (ntimes-- > 0)) 4752 while ((sp = GetScenePresence(agentID)) == null && (ntimes-- > 0))
4569 Thread.Sleep(1000); 4753 Thread.Sleep(250);
4570 4754
4571 if (sp == null) 4755 if (sp == null)
4572 m_log.WarnFormat( 4756 m_log.WarnFormat(
@@ -4593,7 +4777,7 @@ namespace OpenSim.Region.Framework.Scenes
4593 if (acd == null) 4777 if (acd == null)
4594 { 4778 {
4595 m_log.DebugFormat( 4779 m_log.DebugFormat(
4596 "[SCENE]: Request to close agent {0} but no such agent in scene {1}. May have been closed previously.", 4780 "[SCENE]: Request to close agent {0} but no such agent in scene {1}. May have been closed previously.",
4597 agentID, Name); 4781 agentID, Name);
4598 4782
4599 return false; 4783 return false;
@@ -4606,13 +4790,23 @@ namespace OpenSim.Region.Framework.Scenes
4606 else 4790 else
4607 { 4791 {
4608 m_log.WarnFormat( 4792 m_log.WarnFormat(
4609 "[SCENE]: Request to close agent {0} with invalid authorization token {1} in {2}", 4793 "[SCENE]: Request to close agent {0} with invalid authorization token {1} in {2}",
4610 agentID, auth_token, Name); 4794 agentID, auth_token, Name);
4611 } 4795 }
4612 4796
4613 return false; 4797 return false;
4614 } 4798 }
4615 4799
4800// public bool IncomingCloseAgent(UUID agentID)
4801// {
4802// return IncomingCloseAgent(agentID, false);
4803// }
4804
4805// public bool IncomingCloseChildAgent(UUID agentID)
4806// {
4807// return IncomingCloseAgent(agentID, true);
4808// }
4809
4616 /// <summary> 4810 /// <summary>
4617 /// Tell a single client to prepare to close. 4811 /// Tell a single client to prepare to close.
4618 /// </summary> 4812 /// </summary>
@@ -4675,8 +4869,22 @@ namespace OpenSim.Region.Framework.Scenes
4675 4869
4676 if (sp == null) 4870 if (sp == null)
4677 { 4871 {
4872 // If there is no scene presence, we may be handling a dead
4873 // client. These can keep an avatar from reentering a region
4874 // and since they don't get cleaned up they will stick
4875 // around until region restart. So, if there is no SP,
4876 // remove the client as well.
4877 IClientAPI client = null;
4878 if (m_clientManager.TryGetValue(agentID, out client))
4879 {
4880 m_clientManager.Remove(agentID);
4881 if (CapsModule != null)
4882 CapsModule.RemoveCaps(agentID, 0);
4883 m_log.DebugFormat( "[SCENE]: Dead client for agent ID {0} was cleaned up in {1}", agentID, Name);
4884 return true;
4885 }
4678 m_log.DebugFormat( 4886 m_log.DebugFormat(
4679 "[SCENE]: Called CloseClient() with agent ID {0} but no such presence is in {1}", 4887 "[SCENE]: Called CloseClient() with agent ID {0} but no such presence is in {1}",
4680 agentID, Name); 4888 agentID, Name);
4681 4889
4682 return false; 4890 return false;
@@ -4709,7 +4917,11 @@ namespace OpenSim.Region.Framework.Scenes
4709 sp.LifecycleState = ScenePresenceState.Removing; 4917 sp.LifecycleState = ScenePresenceState.Removing;
4710 } 4918 }
4711 4919
4712 sp.ControllingClient.Close(force); 4920 if (sp != null)
4921 {
4922 sp.ControllingClient.Close(force, force);
4923 return true;
4924 }
4713 4925
4714 return true; 4926 return true;
4715 } 4927 }
@@ -4728,16 +4940,34 @@ namespace OpenSim.Region.Framework.Scenes
4728 public void RequestTeleportLocation(IClientAPI remoteClient, string regionName, Vector3 position, 4940 public void RequestTeleportLocation(IClientAPI remoteClient, string regionName, Vector3 position,
4729 Vector3 lookat, uint teleportFlags) 4941 Vector3 lookat, uint teleportFlags)
4730 { 4942 {
4731 GridRegion region = GridService.GetRegionByName(RegionInfo.ScopeID, regionName); 4943 if (EntityTransferModule == null)
4944 {
4945 m_log.DebugFormat("[SCENE]: Unable to perform teleports: no AgentTransferModule is active");
4946 return;
4947 }
4732 4948
4733 if (region == null) 4949 ScenePresence sp = GetScenePresence(remoteClient.AgentId);
4950 if (sp == null || sp.IsDeleted || sp.IsInTransit)
4951 return;
4952
4953 ulong regionHandle = 0;
4954 if(regionName == RegionInfo.RegionName)
4955 regionHandle = RegionInfo.RegionHandle;
4956 else
4957 {
4958 GridRegion region = GridService.GetRegionByName(RegionInfo.ScopeID, regionName);
4959 if (region != null)
4960 regionHandle = region.RegionHandle;
4961 }
4962
4963 if(regionHandle == 0)
4734 { 4964 {
4735 // can't find the region: Tell viewer and abort 4965 // can't find the region: Tell viewer and abort
4736 remoteClient.SendTeleportFailed("The region '" + regionName + "' could not be found."); 4966 remoteClient.SendTeleportFailed("The region '" + regionName + "' could not be found.");
4737 return; 4967 return;
4738 } 4968 }
4739 4969
4740 RequestTeleportLocation(remoteClient, region.RegionHandle, position, lookat, teleportFlags); 4970 EntityTransferModule.Teleport(sp, regionHandle, position, lookat, teleportFlags);
4741 } 4971 }
4742 4972
4743 /// <summary> 4973 /// <summary>
@@ -4751,19 +4981,17 @@ namespace OpenSim.Region.Framework.Scenes
4751 public void RequestTeleportLocation(IClientAPI remoteClient, ulong regionHandle, Vector3 position, 4981 public void RequestTeleportLocation(IClientAPI remoteClient, ulong regionHandle, Vector3 position,
4752 Vector3 lookAt, uint teleportFlags) 4982 Vector3 lookAt, uint teleportFlags)
4753 { 4983 {
4754 ScenePresence sp = GetScenePresence(remoteClient.AgentId); 4984 if (EntityTransferModule == null)
4755 if (sp != null)
4756 { 4985 {
4757 if (EntityTransferModule != null) 4986 m_log.DebugFormat("[SCENE]: Unable to perform teleports: no AgentTransferModule is active");
4758 { 4987 return;
4759 EntityTransferModule.Teleport(sp, regionHandle, position, lookAt, teleportFlags);
4760 }
4761 else
4762 {
4763 m_log.DebugFormat("[SCENE]: Unable to perform teleports: no AgentTransferModule is active");
4764 sp.ControllingClient.SendTeleportFailed("Unable to perform teleports on this simulator.");
4765 }
4766 } 4988 }
4989
4990 ScenePresence sp = GetScenePresence(remoteClient.AgentId);
4991 if (sp == null || sp.IsDeleted || sp.IsInTransit)
4992 return;
4993
4994 EntityTransferModule.Teleport(sp, regionHandle, position, lookAt, teleportFlags);
4767 } 4995 }
4768 4996
4769 public bool CrossAgentToNewRegion(ScenePresence agent, bool isFlying) 4997 public bool CrossAgentToNewRegion(ScenePresence agent, bool isFlying)
@@ -4871,7 +5099,10 @@ namespace OpenSim.Region.Framework.Scenes
4871 5099
4872 public LandData GetLandData(float x, float y) 5100 public LandData GetLandData(float x, float y)
4873 { 5101 {
4874 return LandChannel.GetLandObject(x, y).LandData; 5102 ILandObject parcel = LandChannel.GetLandObject(x, y);
5103 if (parcel == null)
5104 return null;
5105 return parcel.LandData;
4875 } 5106 }
4876 5107
4877 /// <summary> 5108 /// <summary>
@@ -4886,72 +5117,69 @@ namespace OpenSim.Region.Framework.Scenes
4886 5117
4887 public LandData GetLandData(uint x, uint y) 5118 public LandData GetLandData(uint x, uint y)
4888 { 5119 {
4889 m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y); 5120// m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y);
4890 return LandChannel.GetLandObject((int)x, (int)y).LandData; 5121 ILandObject parcel = LandChannel.GetLandObject((int)x, (int)y);
5122 if (parcel == null)
5123 return null;
5124 return parcel.LandData;
4891 } 5125 }
4892 5126
4893 #endregion 5127 #endregion
4894 5128
4895 #region Script Engine 5129 #region Script Engine
4896 5130 public bool LSLScriptDanger(SceneObjectPart part, Vector3 pos)
4897 private bool ScriptDanger(SceneObjectPart part, Vector3 pos)
4898 { 5131 {
5132
4899 ILandObject parcel = LandChannel.GetLandObject(pos.X, pos.Y); 5133 ILandObject parcel = LandChannel.GetLandObject(pos.X, pos.Y);
4900 if (part != null) 5134 if (parcel == null)
4901 { 5135 return true;
4902 if (parcel != null) 5136
4903 { 5137 LandData ldata = parcel.LandData;
4904 if ((parcel.LandData.Flags & (uint)ParcelFlags.AllowOtherScripts) != 0) 5138 if (ldata == null)
4905 { 5139 return true;
4906 return true; 5140
4907 } 5141 uint landflags = ldata.Flags;
4908 else if ((part.OwnerID == parcel.LandData.OwnerID) || Permissions.IsGod(part.OwnerID)) 5142
4909 { 5143 uint mask = (uint)(ParcelFlags.CreateObjects | ParcelFlags.AllowAPrimitiveEntry);
4910 return true; 5144 if((landflags & mask) != mask)
4911 } 5145 return true;
4912 else if (((parcel.LandData.Flags & (uint)ParcelFlags.AllowGroupScripts) != 0) 5146
4913 && (parcel.LandData.GroupID != UUID.Zero) && (parcel.LandData.GroupID == part.GroupID)) 5147 if((landflags & (uint)ParcelFlags.AllowOtherScripts) != 0)
4914 { 5148 return false;
4915 return true;
4916 }
4917 else
4918 {
4919 return false;
4920 }
4921 }
4922 else
4923 {
4924 5149
4925 if (pos.X > 0f && pos.X < RegionInfo.RegionSizeX && pos.Y > 0f && pos.Y < RegionInfo.RegionSizeY) 5150 if(part == null)
4926 { 5151 return true;
4927 // The only time parcel != null when an object is inside a region is when 5152 if(part.GroupID == ldata.GroupID && (landflags & (uint)ParcelFlags.AllowGroupScripts) != 0)
4928 // there is nothing behind the landchannel. IE, no land plugin loaded.
4929 return true;
4930 }
4931 else
4932 {
4933 // The object is outside of this region. Stop piping events to it.
4934 return false;
4935 }
4936 }
4937 }
4938 else
4939 {
4940 return false; 5153 return false;
4941 } 5154
5155 return true;
4942 } 5156 }
4943 5157
4944 public bool ScriptDanger(uint localID, Vector3 pos) 5158 private bool ScriptDanger(SceneObjectPart part, Vector3 pos)
4945 { 5159 {
4946 SceneObjectPart part = GetSceneObjectPart(localID); 5160 if (part == null)
4947 if (part != null) 5161 return false;
5162
5163 ILandObject parcel = LandChannel.GetLandObject(pos.X, pos.Y);
5164 if (parcel != null)
4948 { 5165 {
4949 return ScriptDanger(part, pos); 5166 if ((parcel.LandData.Flags & (uint)ParcelFlags.AllowOtherScripts) != 0)
5167 return true;
5168
5169 if ((part.OwnerID == parcel.LandData.OwnerID) || Permissions.IsGod(part.OwnerID))
5170 return true;
5171
5172 if (((parcel.LandData.Flags & (uint)ParcelFlags.AllowGroupScripts) != 0)
5173 && (parcel.LandData.GroupID != UUID.Zero) && (parcel.LandData.GroupID == part.GroupID))
5174 return true;
4950 } 5175 }
4951 else 5176 else
4952 { 5177 {
4953 return false; 5178 if (pos.X > 0f && pos.X < RegionInfo.RegionSizeX && pos.Y > 0f && pos.Y < RegionInfo.RegionSizeY)
5179 return true;
4954 } 5180 }
5181
5182 return false;
4955 } 5183 }
4956 5184
4957 public bool PipeEventsForScript(uint localID) 5185 public bool PipeEventsForScript(uint localID)
@@ -5177,7 +5405,7 @@ namespace OpenSim.Region.Framework.Scenes
5177 /// Get a scene object group that contains the prim with the given local id 5405 /// Get a scene object group that contains the prim with the given local id
5178 /// </summary> 5406 /// </summary>
5179 /// <param name="localID"></param> 5407 /// <param name="localID"></param>
5180 /// <returns>null if no scene object group containing that prim is found</returns> 5408 /// <returns>null if no scene object group containing that prim is found</returns>
5181 public SceneObjectGroup GetGroupByPrim(uint localID) 5409 public SceneObjectGroup GetGroupByPrim(uint localID)
5182 { 5410 {
5183 return m_sceneGraph.GetGroupByPrim(localID); 5411 return m_sceneGraph.GetGroupByPrim(localID);
@@ -5187,7 +5415,7 @@ namespace OpenSim.Region.Framework.Scenes
5187 /// Get a scene object group that contains the prim with the given uuid 5415 /// Get a scene object group that contains the prim with the given uuid
5188 /// </summary> 5416 /// </summary>
5189 /// <param name="fullID"></param> 5417 /// <param name="fullID"></param>
5190 /// <returns>null if no scene object group containing that prim is found</returns> 5418 /// <returns>null if no scene object group containing that prim is found</returns>
5191 public SceneObjectGroup GetGroupByPrim(UUID fullID) 5419 public SceneObjectGroup GetGroupByPrim(UUID fullID)
5192 { 5420 {
5193 return m_sceneGraph.GetGroupByPrim(fullID); 5421 return m_sceneGraph.GetGroupByPrim(fullID);
@@ -5221,7 +5449,12 @@ namespace OpenSim.Region.Framework.Scenes
5221 /// <param name="action"></param> 5449 /// <param name="action"></param>
5222 public void ForEachClient(Action<IClientAPI> action) 5450 public void ForEachClient(Action<IClientAPI> action)
5223 { 5451 {
5224 m_clientManager.ForEachSync(action); 5452 m_clientManager.ForEach(action);
5453 }
5454
5455 public int GetNumberOfClients()
5456 {
5457 return m_clientManager.Count;
5225 } 5458 }
5226 5459
5227 public bool TryGetClient(UUID avatarID, out IClientAPI client) 5460 public bool TryGetClient(UUID avatarID, out IClientAPI client)
@@ -5264,6 +5497,7 @@ namespace OpenSim.Region.Framework.Scenes
5264 5497
5265 public void CleanTempObjects() 5498 public void CleanTempObjects()
5266 { 5499 {
5500 DateTime now = DateTime.UtcNow;
5267 EntityBase[] entities = GetEntities(); 5501 EntityBase[] entities = GetEntities();
5268 foreach (EntityBase obj in entities) 5502 foreach (EntityBase obj in entities)
5269 { 5503 {
@@ -5275,13 +5509,12 @@ namespace OpenSim.Region.Framework.Scenes
5275 { 5509 {
5276 if ((grp.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 5510 if ((grp.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
5277 { 5511 {
5278 if (grp.RootPart.Expires <= DateTime.Now) 5512 if (grp.GetSittingAvatarsCount() == 0 && grp.RootPart.Expires <= now)
5279 DeleteSceneObject(grp, false); 5513 DeleteSceneObject(grp, false);
5280 } 5514 }
5281 } 5515 }
5282 } 5516 }
5283 } 5517 }
5284
5285 } 5518 }
5286 5519
5287 public void DeleteFromStorage(UUID uuid) 5520 public void DeleteFromStorage(UUID uuid)
@@ -5289,7 +5522,7 @@ namespace OpenSim.Region.Framework.Scenes
5289 SimulationDataService.RemoveObject(uuid, RegionInfo.RegionID); 5522 SimulationDataService.RemoveObject(uuid, RegionInfo.RegionID);
5290 } 5523 }
5291 5524
5292 public int GetHealth() 5525 public int GetHealth(out int flags, out string message)
5293 { 5526 {
5294 // Returns: 5527 // Returns:
5295 // 1 = sim is up and accepting http requests. The heartbeat has 5528 // 1 = sim is up and accepting http requests. The heartbeat has
@@ -5297,27 +5530,74 @@ namespace OpenSim.Region.Framework.Scenes
5297 // admin restart may succeed 5530 // admin restart may succeed
5298 // 5531 //
5299 // 2 = Sim is up and the heartbeat is running. The sim is likely 5532 // 2 = Sim is up and the heartbeat is running. The sim is likely
5300 // usable for people within and logins _may_ work 5533 // usable for people within
5534 //
5535 // 3 = Sim is up and one packet thread is running. Sim is
5536 // unstable and will not accept new logins
5301 // 5537 //
5302 // 3 = We have seen a new user enter within the past 4 minutes 5538 // 4 = Sim is up and both packet threads are running. Sim is
5539 // likely usable
5540 //
5541 // 5 = We have seen a new user enter within the past 4 minutes
5303 // which can be seen as positive confirmation of sim health 5542 // which can be seen as positive confirmation of sim health
5304 // 5543 //
5305 int health = 1; // Start at 1, means we're up 5544 int health = 1; // Start at 1, means we're up
5306 5545
5307 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 1000) 5546 flags = 0;
5308 health += 1; 5547 message = String.Empty;
5548
5549 CheckHeartbeat();
5550
5551 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
5552 {
5553 // We're still starting
5554 // 0 means "in startup", it can't happen another way, since
5555 // to get here, we must be able to accept http connections
5556 return 0;
5557 }
5558
5559 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 2000)
5560 {
5561 health+=1;
5562 flags |= 1;
5563 }
5564
5565 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 2000)
5566 {
5567 health+=1;
5568 flags |= 2;
5569 }
5570
5571 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 2000)
5572 {
5573 health+=1;
5574 flags |= 4;
5575 }
5576 /*
5309 else 5577 else
5578 {
5579int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
5580System.Diagnostics.Process proc = new System.Diagnostics.Process();
5581proc.EnableRaisingEvents=false;
5582proc.StartInfo.FileName = "/bin/kill";
5583proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
5584proc.Start();
5585proc.WaitForExit();
5586Thread.Sleep(1000);
5587Environment.Exit(1);
5588 }
5589 */
5590
5591 if (flags != 7)
5310 return health; 5592 return health;
5311 5593
5312 // A login in the last 4 mins? We can't be doing too badly 5594 // A login in the last 4 mins? We can't be doing too badly
5313 // 5595 //
5314 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 5596 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
5315 health++; 5597 health++;
5316 else 5598 else
5317 return health; 5599 return health;
5318 5600
5319// CheckHeartbeat();
5320
5321 return health; 5601 return health;
5322 } 5602 }
5323 5603
@@ -5405,7 +5685,7 @@ namespace OpenSim.Region.Framework.Scenes
5405 bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0); 5685 bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0);
5406 if (wasUsingPhysics) 5686 if (wasUsingPhysics)
5407 { 5687 {
5408 jointProxyObject.UpdatePrimFlags(false, false, true, false); // FIXME: possible deadlock here; check to make sure all the scene alterations set into motion here won't deadlock 5688 jointProxyObject.UpdatePrimFlags(false, false, true, false,false); // FIXME: possible deadlock here; check to make sure all the scene alterations set into motion here won't deadlock
5409 } 5689 }
5410 } 5690 }
5411 5691
@@ -5508,14 +5788,14 @@ namespace OpenSim.Region.Framework.Scenes
5508 return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z; 5788 return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z;
5509 } 5789 }
5510 5790
5511// private void CheckHeartbeat() 5791 private void CheckHeartbeat()
5512// { 5792 {
5513// if (m_firstHeartbeat) 5793 if (m_firstHeartbeat)
5514// return; 5794 return;
5515// 5795
5516// if (Util.EnvironmentTickCountSubtract(m_lastFrameTick) > 2000) 5796 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) > 5000)
5517// StartTimer(); 5797 Start();
5518// } 5798 }
5519 5799
5520 public override ISceneObject DeserializeObject(string representation) 5800 public override ISceneObject DeserializeObject(string representation)
5521 { 5801 {
@@ -5534,27 +5814,26 @@ namespace OpenSim.Region.Framework.Scenes
5534 5814
5535 public Vector3 GetNearestAllowedPosition(ScenePresence avatar, ILandObject excludeParcel) 5815 public Vector3 GetNearestAllowedPosition(ScenePresence avatar, ILandObject excludeParcel)
5536 { 5816 {
5537 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, excludeParcel); 5817 Vector3 pos = avatar.AbsolutePosition;
5818
5819 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, pos.X, pos.Y, excludeParcel);
5538 5820
5539 if (nearestParcel != null) 5821 if (nearestParcel != null)
5540 { 5822 {
5541 Vector3 dir = Vector3.Normalize(Vector3.Multiply(avatar.Velocity, -1)); 5823 Vector2? nearestPoint = null;
5542 //Try to get a location that feels like where they came from 5824 Vector3 dir = -avatar.Velocity;
5543 Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); 5825 float dirlen = dir.Length();
5544 if (nearestPoint != null) 5826 if(dirlen > 1.0f)
5545 { 5827 //Try to get a location that feels like where they came from
5546 m_log.Debug("Found a sane previous position based on velocity, sending them to: " + nearestPoint.ToString()); 5828 nearestPoint = nearestParcel.GetNearestPointAlongDirection(pos, dir);
5547 return nearestPoint.Value; 5829
5548 } 5830 if (nearestPoint == null)
5831 nearestPoint = nearestParcel.GetNearestPoint(pos);
5549 5832
5550 //Sometimes velocity might be zero (local teleport), so try finding point along path from avatar to center of nearest parcel
5551 Vector3 directionToParcelCenter = Vector3.Subtract(GetParcelCenterAtGround(nearestParcel), avatar.AbsolutePosition);
5552 dir = Vector3.Normalize(directionToParcelCenter);
5553 nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel);
5554 if (nearestPoint != null) 5833 if (nearestPoint != null)
5555 { 5834 {
5556 m_log.Debug("They had a zero velocity, sending them to: " + nearestPoint.ToString()); 5835 return GetPositionAtAvatarHeightOrGroundHeight(avatar,
5557 return nearestPoint.Value; 5836 nearestPoint.Value.X, nearestPoint.Value.Y);
5558 } 5837 }
5559 5838
5560 ILandObject dest = LandChannel.GetLandObject(avatar.lastKnownAllowedPosition.X, avatar.lastKnownAllowedPosition.Y); 5839 ILandObject dest = LandChannel.GetLandObject(avatar.lastKnownAllowedPosition.X, avatar.lastKnownAllowedPosition.Y);
@@ -5572,32 +5851,16 @@ namespace OpenSim.Region.Framework.Scenes
5572 //Go to the edge, this happens in teleporting to a region with no available parcels 5851 //Go to the edge, this happens in teleporting to a region with no available parcels
5573 Vector3 nearestRegionEdgePoint = GetNearestRegionEdgePosition(avatar); 5852 Vector3 nearestRegionEdgePoint = GetNearestRegionEdgePosition(avatar);
5574 5853
5575 //m_log.Debug("They are really in a place they don't belong, sending them to: " + nearestRegionEdgePoint.ToString()); 5854 //Debug.WriteLine("They are really in a place they don't belong, sending them to: " + nearestRegionEdgePoint.ToString());
5576
5577 return nearestRegionEdgePoint; 5855 return nearestRegionEdgePoint;
5578 } 5856 }
5579 5857
5580 private Vector3 GetParcelCenterAtGround(ILandObject parcel) 5858 private Vector3 GetParcelCenterAtGround(ILandObject parcel)
5581 { 5859 {
5582 Vector2 center = GetParcelCenter(parcel); 5860 Vector2 center = parcel.CenterPoint;
5583 return GetPositionAtGround(center.X, center.Y); 5861 return GetPositionAtGround(center.X, center.Y);
5584 } 5862 }
5585 5863
5586 private Vector3? GetNearestPointInParcelAlongDirectionFromPoint(Vector3 pos, Vector3 direction, ILandObject parcel)
5587 {
5588 Vector3 unitDirection = Vector3.Normalize(direction);
5589 //Making distance to search go through some sane limit of distance
5590 for (float distance = 0; distance < Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY) * 2; distance += .5f)
5591 {
5592 Vector3 testPos = Vector3.Add(pos, Vector3.Multiply(unitDirection, distance));
5593 if (parcel.ContainsPoint((int)testPos.X, (int)testPos.Y))
5594 {
5595 return testPos;
5596 }
5597 }
5598 return null;
5599 }
5600
5601 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y) 5864 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y)
5602 { 5865 {
5603 return GetNearestAllowedParcel(avatarId, x, y, null); 5866 return GetNearestAllowedParcel(avatarId, x, y, null);
@@ -5605,18 +5868,30 @@ namespace OpenSim.Region.Framework.Scenes
5605 5868
5606 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y, ILandObject excludeParcel) 5869 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y, ILandObject excludeParcel)
5607 { 5870 {
5608 List<ILandObject> all = AllParcels(); 5871 if(LandChannel == null)
5609 float minParcelDistance = float.MaxValue; 5872 return null;
5873
5874 List<ILandObject> all = LandChannel.AllParcels();
5875
5876 if(all == null || all.Count == 0)
5877 return null;
5878
5879 float minParcelDistanceSQ = float.MaxValue;
5610 ILandObject nearestParcel = null; 5880 ILandObject nearestParcel = null;
5881 Vector2 curCenter;
5882 float parcelDistanceSQ;
5611 5883
5612 foreach (var parcel in all) 5884 foreach (var parcel in all)
5613 { 5885 {
5614 if (!parcel.IsEitherBannedOrRestricted(avatarId) && parcel != excludeParcel) 5886 if (parcel != excludeParcel && !parcel.IsEitherBannedOrRestricted(avatarId))
5615 { 5887 {
5616 float parcelDistance = GetParcelDistancefromPoint(parcel, x, y); 5888 curCenter = parcel.CenterPoint;
5617 if (parcelDistance < minParcelDistance) 5889 curCenter.X -= x;
5890 curCenter.Y -= y;
5891 parcelDistanceSQ = curCenter.LengthSquared();
5892 if (parcelDistanceSQ < minParcelDistanceSQ)
5618 { 5893 {
5619 minParcelDistance = parcelDistance; 5894 minParcelDistanceSQ = parcelDistanceSQ;
5620 nearestParcel = parcel; 5895 nearestParcel = parcel;
5621 } 5896 }
5622 } 5897 }
@@ -5625,82 +5900,52 @@ namespace OpenSim.Region.Framework.Scenes
5625 return nearestParcel; 5900 return nearestParcel;
5626 } 5901 }
5627 5902
5628 private List<ILandObject> AllParcels() 5903 private Vector2 GetParcelSafeCorner(ILandObject parcel)
5629 {
5630 return LandChannel.AllParcels();
5631 }
5632
5633 private float GetParcelDistancefromPoint(ILandObject parcel, float x, float y)
5634 { 5904 {
5635 return Vector2.Distance(new Vector2(x, y), GetParcelCenter(parcel)); 5905 Vector2 place = parcel.StartPoint;
5636 } 5906 place.X += 2f;
5637 5907 place.Y += 2f;
5638 //calculate the average center point of a parcel 5908 return place;
5639 private Vector2 GetParcelCenter(ILandObject parcel)
5640 {
5641 int count = 0;
5642 int avgx = 0;
5643 int avgy = 0;
5644 for (int x = 0; x < RegionInfo.RegionSizeX; x++)
5645 {
5646 for (int y = 0; y < RegionInfo.RegionSizeY; y++)
5647 {
5648 //Just keep a running average as we check if all the points are inside or not
5649 if (parcel.ContainsPoint(x, y))
5650 {
5651 if (count == 0)
5652 {
5653 avgx = x;
5654 avgy = y;
5655 }
5656 else
5657 {
5658 avgx = (avgx * count + x) / (count + 1);
5659 avgy = (avgy * count + y) / (count + 1);
5660 }
5661 count += 1;
5662 }
5663 }
5664 }
5665 return new Vector2(avgx, avgy);
5666 } 5909 }
5667 5910
5668 private Vector3 GetNearestRegionEdgePosition(ScenePresence avatar) 5911 private Vector3 GetNearestRegionEdgePosition(ScenePresence avatar)
5669 { 5912 {
5670 float xdistance = avatar.AbsolutePosition.X < RegionInfo.RegionSizeX / 2 5913 float posX = avatar.AbsolutePosition.X;
5671 ? avatar.AbsolutePosition.X : RegionInfo.RegionSizeX - avatar.AbsolutePosition.X; 5914 float posY = avatar.AbsolutePosition.Y;
5672 float ydistance = avatar.AbsolutePosition.Y < RegionInfo.RegionSizeY / 2 5915 float regionSizeX = RegionInfo.RegionSizeX;
5673 ? avatar.AbsolutePosition.Y : RegionInfo.RegionSizeY - avatar.AbsolutePosition.Y; 5916 float halfRegionSizeX = regionSizeX * 0.5f;
5917 float regionSizeY = RegionInfo.RegionSizeY;
5918 float halfRegionSizeY = regionSizeY * 0.5f;
5919
5920 float xdistance = posX < halfRegionSizeX ? posX : regionSizeX - posX;
5921 float ydistance = posY < halfRegionSizeY ? posY : regionSizeY - posY;
5674 5922
5675 //find out what vertical edge to go to 5923 //find out what vertical edge to go to
5676 if (xdistance < ydistance) 5924 if (xdistance < ydistance)
5677 { 5925 {
5678 if (avatar.AbsolutePosition.X < RegionInfo.RegionSizeX / 2) 5926 if (posX < halfRegionSizeX)
5679 { 5927 return GetPositionAtAvatarHeightOrGroundHeight(avatar, 0.5f, posY);
5680 return GetPositionAtAvatarHeightOrGroundHeight(avatar, 0.0f, avatar.AbsolutePosition.Y);
5681 }
5682 else 5928 else
5683 { 5929 return GetPositionAtAvatarHeightOrGroundHeight(avatar, regionSizeX - 0.5f, posY);
5684 return GetPositionAtAvatarHeightOrGroundHeight(avatar, RegionInfo.RegionSizeY, avatar.AbsolutePosition.Y);
5685 }
5686 } 5930 }
5687 //find out what horizontal edge to go to 5931 //find out what horizontal edge to go to
5688 else 5932 else
5689 { 5933 {
5690 if (avatar.AbsolutePosition.Y < RegionInfo.RegionSizeY / 2) 5934 if (posY < halfRegionSizeY)
5691 { 5935 return GetPositionAtAvatarHeightOrGroundHeight(avatar, posX, 0.5f);
5692 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, 0.0f);
5693 }
5694 else 5936 else
5695 { 5937 return GetPositionAtAvatarHeightOrGroundHeight(avatar, posX, regionSizeY - 0.5f);
5696 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, RegionInfo.RegionSizeY);
5697 }
5698 } 5938 }
5699 } 5939 }
5700 5940
5701 private Vector3 GetPositionAtAvatarHeightOrGroundHeight(ScenePresence avatar, float x, float y) 5941 private Vector3 GetPositionAtAvatarHeightOrGroundHeight(ScenePresence avatar, float x, float y)
5702 { 5942 {
5703 Vector3 ground = GetPositionAtGround(x, y); 5943 Vector3 ground = GetPositionAtGround(x, y);
5944 if(avatar.Appearance != null)
5945 ground.Z += avatar.Appearance.AvatarHeight * 0.5f;
5946 else
5947 ground.Z += 0.8f;
5948
5704 if (avatar.AbsolutePosition.Z > ground.Z) 5949 if (avatar.AbsolutePosition.Z > ground.Z)
5705 { 5950 {
5706 ground.Z = avatar.AbsolutePosition.Z; 5951 ground.Z = avatar.AbsolutePosition.Z;
@@ -5780,7 +6025,7 @@ namespace OpenSim.Region.Framework.Scenes
5780 g.GetAxisAlignedBoundingBoxRaw(out ominX, out omaxX, out ominY, out omaxY, out ominZ, out omaxZ); 6025 g.GetAxisAlignedBoundingBoxRaw(out ominX, out omaxX, out ominY, out omaxY, out ominZ, out omaxZ);
5781 6026
5782// m_log.DebugFormat( 6027// m_log.DebugFormat(
5783// "[SCENE]: For {0} found AxisAlignedBoundingBoxRaw {1}, {2}", 6028// "[SCENE]: For {0} found AxisAlignedBoundingBoxRaw {1}, {2}",
5784// g.Name, new Vector3(ominX, ominY, ominZ), new Vector3(omaxX, omaxY, omaxZ)); 6029// g.Name, new Vector3(ominX, ominY, ominZ), new Vector3(omaxX, omaxY, omaxZ));
5785 6030
5786 ominX += vec.X; 6031 ominX += vec.X;
@@ -5829,7 +6074,55 @@ namespace OpenSim.Region.Framework.Scenes
5829 mapModule.GenerateMaptile(); 6074 mapModule.GenerateMaptile();
5830 } 6075 }
5831 6076
5832 private void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e) 6077// public void CleanDroppedAttachments()
6078// {
6079// List<SceneObjectGroup> objectsToDelete =
6080// new List<SceneObjectGroup>();
6081//
6082// lock (m_cleaningAttachments)
6083// {
6084// ForEachSOG(delegate (SceneObjectGroup grp)
6085// {
6086// if (grp.RootPart.Shape.PCode == 0 && grp.RootPart.Shape.State != 0 && (!objectsToDelete.Contains(grp)))
6087// {
6088// UUID agentID = grp.OwnerID;
6089// if (agentID == UUID.Zero)
6090// {
6091// objectsToDelete.Add(grp);
6092// return;
6093// }
6094//
6095// ScenePresence sp = GetScenePresence(agentID);
6096// if (sp == null)
6097// {
6098// objectsToDelete.Add(grp);
6099// return;
6100// }
6101// }
6102// });
6103// }
6104//
6105// foreach (SceneObjectGroup grp in objectsToDelete)
6106// {
6107// m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
6108// DeleteSceneObject(grp, true);
6109// }
6110// }
6111
6112 public void ThreadAlive(int threadCode)
6113 {
6114 switch(threadCode)
6115 {
6116 case 1: // Incoming
6117 m_lastIncoming = Util.EnvironmentTickCount();
6118 break;
6119 case 2: // Incoming
6120 m_lastOutgoing = Util.EnvironmentTickCount();
6121 break;
6122 }
6123 }
6124
6125 public void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e)
5833 { 6126 {
5834 RegenerateMaptile(); 6127 RegenerateMaptile();
5835 6128
@@ -5861,13 +6154,16 @@ namespace OpenSim.Region.Framework.Scenes
5861 reason = string.Empty; 6154 reason = string.Empty;
5862 6155
5863 if (Permissions.IsGod(agentID)) 6156 if (Permissions.IsGod(agentID))
5864 {
5865 reason = String.Empty;
5866 return true; 6157 return true;
5867 }
5868 6158
5869 if (!AllowAvatarCrossing && !viaTeleport) 6159 if (!AllowAvatarCrossing && !viaTeleport)
6160 {
6161 reason = "Region Crossing not allowed";
5870 return false; 6162 return false;
6163 }
6164
6165 bool isAdmin = Permissions.IsAdministrator(agentID);
6166 bool isManager = Permissions.IsEstateManager(agentID);
5871 6167
5872 // FIXME: Root agent count is currently known to be inaccurate. This forces a recount before we check. 6168 // FIXME: Root agent count is currently known to be inaccurate. This forces a recount before we check.
5873 // However, the long term fix is to make sure root agent count is always accurate. 6169 // However, the long term fix is to make sure root agent count is always accurate.
@@ -5877,7 +6173,7 @@ namespace OpenSim.Region.Framework.Scenes
5877 6173
5878 if (num >= RegionInfo.RegionSettings.AgentLimit) 6174 if (num >= RegionInfo.RegionSettings.AgentLimit)
5879 { 6175 {
5880 if (!Permissions.IsAdministrator(agentID)) 6176 if (!(isAdmin || isManager))
5881 { 6177 {
5882 reason = "The region is full"; 6178 reason = "The region is full";
5883 6179
@@ -5915,6 +6211,7 @@ namespace OpenSim.Region.Framework.Scenes
5915 if (!AuthorizeUser(aCircuit, false, out reason)) 6211 if (!AuthorizeUser(aCircuit, false, out reason))
5916 { 6212 {
5917 //m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID); 6213 //m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
6214// reason = "Region authorization fail";
5918 return false; 6215 return false;
5919 } 6216 }
5920 } 6217 }
@@ -5925,52 +6222,101 @@ namespace OpenSim.Region.Framework.Scenes
5925 return false; 6222 return false;
5926 } 6223 }
5927 6224
5928 if (viaTeleport) 6225 // last check aditional land access restrictions and relocations
6226 // if crossing (viaTeleport false) check only the specified parcel
6227 return CheckLandPositionAccess(agentID, viaTeleport, true, position, out reason);
6228 }
6229
6230 // check access to land.
6231 public bool CheckLandPositionAccess(UUID agentID, bool NotCrossing, bool checkTeleHub, Vector3 position, out string reason)
6232 {
6233 reason = string.Empty;
6234
6235 if (Permissions.IsGod(agentID))
6236 return true;
6237
6238 // Permissions.IsAdministrator is the same as IsGod for now
6239// bool isAdmin = Permissions.IsAdministrator(agentID);
6240// if(isAdmin)
6241// return true;
6242
6243 // also honor estate managers access rights
6244 bool isManager = Permissions.IsEstateManager(agentID);
6245 if(isManager)
6246 return true;
6247
6248 if (NotCrossing)
5929 { 6249 {
5930 if (!RegionInfo.EstateSettings.AllowDirectTeleport) 6250 if (!RegionInfo.EstateSettings.AllowDirectTeleport)
5931 { 6251 {
5932 SceneObjectGroup telehub; 6252 SceneObjectGroup telehub;
5933 if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject)) != null) 6253 if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = GetSceneObjectGroup (RegionInfo.RegionSettings.TelehubObject)) != null && checkTeleHub)
5934 { 6254 {
5935 List<SpawnPoint> spawnPoints = RegionInfo.RegionSettings.SpawnPoints();
5936 bool banned = true; 6255 bool banned = true;
5937 foreach (SpawnPoint sp in spawnPoints) 6256 bool validTelehub = false;
6257 List<SpawnPoint> spawnPoints = RegionInfo.RegionSettings.SpawnPoints();
6258 Vector3 spawnPoint;
6259 ILandObject land = null;
6260 Vector3 telehubPosition = telehub.AbsolutePosition;
6261
6262 if(spawnPoints.Count == 0)
5938 { 6263 {
5939 Vector3 spawnPoint = sp.GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); 6264 // will this ever happen?
5940 ILandObject land = LandChannel.GetLandObject(spawnPoint.X, spawnPoint.Y); 6265 // if so use the telehub object position
5941 if (land == null) 6266 spawnPoint = telehubPosition;
5942 continue; 6267 land = LandChannel.GetLandObject(spawnPoint.X, spawnPoint.Y);
5943 if (land.IsEitherBannedOrRestricted(agentID)) 6268 if(land != null && !land.IsEitherBannedOrRestricted(agentID))
5944 continue; 6269 {
5945 banned = false; 6270 banned = false;
5946 break; 6271 validTelehub = true;
6272 }
6273 }
6274 else
6275 {
6276 Quaternion telehubRotation = telehub.GroupRotation;
6277 foreach (SpawnPoint spawn in spawnPoints)
6278 {
6279 spawnPoint = spawn.GetLocation(telehubPosition, telehubRotation);
6280 land = LandChannel.GetLandObject(spawnPoint.X, spawnPoint.Y);
6281 if (land == null)
6282 continue;
6283 validTelehub = true;
6284 if (!land.IsEitherBannedOrRestricted(agentID))
6285 {
6286 banned = false;
6287 break;
6288 }
6289 }
5947 } 6290 }
5948 6291
5949 if (banned) 6292 if(validTelehub)
5950 { 6293 {
5951 if (Permissions.IsAdministrator(agentID) == false || Permissions.IsGridGod(agentID) == false) 6294 if (banned)
5952 { 6295 {
5953 reason = "No suitable landing point found"; 6296 reason = "No suitable landing point found";
5954 return false; 6297 return false;
5955 } 6298 }
5956 reason = "Administrative access only"; 6299 else
5957 return true; 6300 return true;
5958 } 6301 }
6302 // possible broken telehub, fall into normal check
5959 } 6303 }
5960 } 6304 }
5961 6305
5962 float posX = 128.0f; 6306 float posX = position.X;
5963 float posY = 128.0f; 6307 float posY = position.Y;
5964 6308
6309 // allow position relocation
5965 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY)) 6310 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY))
5966 { 6311 {
5967 // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID); 6312 // 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"; 6313 reason = "You dont have access to the region parcels";
5969 return false; 6314 return false;
5970 } 6315 }
5971 } 6316 }
5972 else // Walking 6317 else // check for query region crossing only
5973 { 6318 {
6319 // no relocation allowed on crossings
5974 ILandObject land = LandChannel.GetLandObject(position.X, position.Y); 6320 ILandObject land = LandChannel.GetLandObject(position.X, position.Y);
5975 if (land == null) 6321 if (land == null)
5976 { 6322 {
@@ -5991,11 +6337,48 @@ namespace OpenSim.Region.Framework.Scenes
5991 } 6337 }
5992 } 6338 }
5993 6339
5994 reason = String.Empty;
5995 return true; 6340 return true;
5996 } 6341 }
5997 6342
5998 /// <summary> 6343 public void StartTimerWatchdog()
6344 {
6345 m_timerWatchdog.Interval = 1000;
6346 m_timerWatchdog.Elapsed += TimerWatchdog;
6347 m_timerWatchdog.AutoReset = true;
6348 m_timerWatchdog.Start();
6349 }
6350
6351 public void TimerWatchdog(object sender, ElapsedEventArgs e)
6352 {
6353 CheckHeartbeat();
6354
6355 IEtcdModule etcd = RequestModuleInterface<IEtcdModule>();
6356 int flags;
6357 string message;
6358 if (etcd != null)
6359 {
6360 int health = GetHealth(out flags, out message);
6361 if (health != m_lastHealth)
6362 {
6363 m_lastHealth = health;
6364
6365 etcd.Store("Health", health.ToString(), 300000);
6366 etcd.Store("HealthFlags", flags.ToString(), 300000);
6367 }
6368
6369 int roots = 0;
6370 foreach (ScenePresence sp in GetScenePresences())
6371 if (!sp.IsChildAgent && !sp.IsNPC)
6372 roots++;
6373
6374 if (m_lastUsers != roots)
6375 {
6376 m_lastUsers = roots;
6377 etcd.Store("RootAgents", roots.ToString(), 300000);
6378 }
6379 }
6380 }
6381
5999 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the 6382 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the
6000 /// autopilot that moves an avatar to a sit target!. 6383 /// autopilot that moves an avatar to a sit target!.
6001 /// </summary> 6384 /// </summary>
@@ -6003,6 +6386,7 @@ namespace OpenSim.Region.Framework.Scenes
6003 /// This is not intended as a permament location for this method. 6386 /// This is not intended as a permament location for this method.
6004 /// </remarks> 6387 /// </remarks>
6005 /// <param name="presence"></param> 6388 /// <param name="presence"></param>
6389/* move to target is now done on presence update
6006 private void HandleOnSignificantClientMovement(ScenePresence presence) 6390 private void HandleOnSignificantClientMovement(ScenePresence presence)
6007 { 6391 {
6008 if (presence.MovingToTarget) 6392 if (presence.MovingToTarget)
@@ -6059,7 +6443,7 @@ namespace OpenSim.Region.Framework.Scenes
6059 } 6443 }
6060 } 6444 }
6061 } 6445 }
6062 6446*/
6063 // manage and select spawn points in sequence 6447 // manage and select spawn points in sequence
6064 public int SpawnPoint() 6448 public int SpawnPoint()
6065 { 6449 {
@@ -6074,8 +6458,13 @@ namespace OpenSim.Region.Framework.Scenes
6074 return m_SpawnPoint - 1; 6458 return m_SpawnPoint - 1;
6075 } 6459 }
6076 6460
6461 private void HandleGcCollect(string module, string[] args)
6462 {
6463 GC.Collect();
6464 }
6465
6077 /// <summary> 6466 /// <summary>
6078 /// Wrappers to get physics modules retrieve assets. 6467 /// Wrappers to get physics modules retrieve assets.
6079 /// </summary> 6468 /// </summary>
6080 /// <remarks> 6469 /// <remarks>
6081 /// Has to be done this way 6470 /// Has to be done this way
@@ -6144,5 +6533,21 @@ namespace OpenSim.Region.Framework.Scenes
6144 6533
6145 m_eventManager.TriggerExtraSettingChanged(this, name, String.Empty); 6534 m_eventManager.TriggerExtraSettingChanged(this, name, String.Empty);
6146 } 6535 }
6536
6537 public bool InTeleportTargetsCoolDown(UUID sourceID, UUID targetID, double timeout)
6538 {
6539 lock(TeleportTargetsCoolDown)
6540 {
6541 UUID lastSource = UUID.Zero;
6542 TeleportTargetsCoolDown.TryGetValue(targetID, out lastSource);
6543 if(lastSource == UUID.Zero)
6544 {
6545 TeleportTargetsCoolDown.Add(targetID, sourceID, timeout);
6546 return false;
6547 }
6548 TeleportTargetsCoolDown.AddOrUpdate(targetID, sourceID, timeout);
6549 return lastSource == sourceID;
6550 }
6551 }
6147 } 6552 }
6148} 6553}