aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/Scene.cs
diff options
context:
space:
mode:
authoronefang2019-05-19 21:24:15 +1000
committeronefang2019-05-19 21:24:15 +1000
commit5e4d6cab00cb29cd088ab7b62ab13aff103b64cb (patch)
treea9fbc62df9eb2d1d9ba2698d8552eae71eca20d8 /OpenSim/Region/Framework/Scenes/Scene.cs
parentAdd a build script. (diff)
downloadopensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.zip
opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.gz
opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.bz2
opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.xz
Dump OpenSim 0.9.0.1 into it's own branch.
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/Scene.cs')
-rwxr-xr-x[-rw-r--r--]OpenSim/Region/Framework/Scenes/Scene.cs2560
1 files changed, 1425 insertions, 1135 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 2fe6e22..15a0493 100644..100755
--- 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
232 /// </summary> 237 /// to compensate for SL bug
233 public bool AllowAvatarCrossing { get; set; }
234
235 public bool m_useFlySlow;
236 public bool m_useTrashOnDelete = true;
237
238 /// <summary>
239 /// Temporarily setting to trigger appearance resends at 60 second intervals.
240 /// </summary> 238 /// </summary>
241 public bool SendPeriodicAppearanceUpdates { get; set; } 239 public bool LegacySitOffsets = true;
242 240
243 /// <summary> 241 /// <summary>
244 /// How much a root agent has to change position before updates are sent to viewers. 242 /// Can avatars cross from and to this region?
245 /// </summary>
246 public float RootPositionUpdateTolerance { get; set; }
247
248 /// <summary>
249 /// How much a root agent has to rotate before updates are sent to viewers.
250 /// </summary> 243 /// </summary>
251 public float RootRotationUpdateTolerance { get; set; } 244 public bool AllowAvatarCrossing { get; set; }
252 245
253 /// <summary> 246 /// Max prims an Physical object will hold
254 /// How much a root agent has to change velocity before updates are sent to viewers.
255 /// </summary> 247 /// </summary>
256 public float RootVelocityUpdateTolerance { get; set; } 248 ///
249 public int m_linksetPhysCapacity = 0;
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;
@@ -339,17 +337,6 @@ namespace OpenSim.Region.Framework.Scenes
339 private Dictionary<string, string> m_extraSettings; 337 private Dictionary<string, string> m_extraSettings;
340 338
341 /// <summary> 339 /// <summary>
342 /// If true then the next time the scene loop is activated, updates will be performed by firing of a timer
343 /// rather than on a single thread that sleeps.
344 /// </summary>
345 public bool UpdateOnTimer { get; set; }
346
347 /// <summary>
348 /// Only used if we are updating scene on a timer rather than sleeping a thread.
349 /// </summary>
350 private Timer m_sceneUpdateTimer;
351
352 /// <summary>
353 /// Current scene frame number 340 /// Current scene frame number
354 /// </summary> 341 /// </summary>
355 public uint Frame 342 public uint Frame
@@ -359,87 +346,38 @@ namespace OpenSim.Region.Framework.Scenes
359 } 346 }
360 347
361 /// <summary> 348 /// <summary>
362 /// Current maintenance run number 349 /// 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> 350 /// </remarks>
374 public int MinFrameTicks 351 public float FrameTime { get; private set; }
375 { 352 public int FrameTimeWarnPercent { get; private set; }
376 get { return m_minFrameTicks; } 353 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 354
388 // Normalize the frame related stats to nominal 55fps for viewer and scripts option 355 // Normalize the frame related stats to nominal 55fps for viewer and scripts option
389 // see SimStatsReporter.cs 356 // see SimStatsReporter.cs
390 public bool Normalized55FPS { get; private set; } 357 public bool Normalized55FPS { get; private set; }
391 358
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; 359 private int m_update_physics = 1;
411 private int m_update_entitymovement = 1; 360 private int m_update_entitymovement = 1;
412 private int m_update_objects = 1; 361 private int m_update_objects = 1;
413 private int m_update_presences = 1; // Update scene presence movements 362 private int m_update_presences = 1; // Update scene presence movements
414 private int m_update_events = 1; 363 private int m_update_events = 1;
415 private int m_update_backup = 200; 364 private int m_update_backup = 200;
416 private int m_update_terrain = 50; 365
417 // private int m_update_land = 1; 366 private int m_update_terrain = 1000;
418 private int m_update_coarse_locations = 50; 367
368 private int m_update_coarse_locations = 5;
419 private int m_update_temp_cleaning = 180; 369 private int m_update_temp_cleaning = 180;
420 370
421 private int agentMS; 371 private float agentMS;
422 private int frameMS; 372 private float frameMS;
423 private int physicsMS2; 373 private float physicsMS2;
424 private int physicsMS; 374 private float physicsMS;
425 private int otherMS; 375 private float otherMS;
426 private int tempOnRezMS; 376 private float tempOnRezMS;
427 private int eventMS; 377 private float eventMS;
428 private int backupMS; 378 private float backupMS;
429 private int terrainMS; 379 private float terrainMS;
430 private int landMS; 380 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 381
444 /// <summary> 382 /// <summary>
445 /// Tick at which the last frame was processed. 383 /// Tick at which the last frame was processed.
@@ -447,11 +385,6 @@ namespace OpenSim.Region.Framework.Scenes
447 private int m_lastFrameTick; 385 private int m_lastFrameTick;
448 386
449 /// <summary> 387 /// <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 388 /// Total script execution time (in Stopwatch Ticks) since the last frame
456 /// </summary> 389 /// </summary>
457 private long m_scriptExecutionTime = 0; 390 private long m_scriptExecutionTime = 0;
@@ -461,23 +394,19 @@ namespace OpenSim.Region.Framework.Scenes
461 /// asynchronously from the update loop. 394 /// asynchronously from the update loop.
462 /// </summary> 395 /// </summary>
463 private bool m_cleaningTemps = false; 396 private bool m_cleaningTemps = false;
397 private bool m_sendingCoarseLocations = false; // same for async course locations sending
464 398
465 /// <summary> 399 /// <summary>
466 /// Used to control main scene thread looping time when not updating via timer. 400 /// Used to control main scene thread looping time when not updating via timer.
467 /// </summary> 401 /// </summary>
468 private ManualResetEvent m_updateWaitEvent = new ManualResetEvent(false); 402 private ManualResetEvent m_updateWaitEvent = new ManualResetEvent(false);
469 403
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. 404 // TODO: Possibly stop other classes being able to manipulate this directly.
476 private SceneGraph m_sceneGraph; 405 private SceneGraph m_sceneGraph;
477 private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing 406 private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing
478 private volatile bool m_backingup; 407 private volatile bool m_backingup;
479 private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>(); 408 private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>();
480 private Dictionary<UUID, SceneObjectGroup> m_groupsWithTargets = new Dictionary<UUID, SceneObjectGroup>(); 409 private Dictionary<UUID, int> m_groupsWithTargets = new Dictionary<UUID, int>();
481 410
482 private string m_defaultScriptEngine; 411 private string m_defaultScriptEngine;
483 412
@@ -492,6 +421,11 @@ namespace OpenSim.Region.Framework.Scenes
492 /// </summary> 421 /// </summary>
493 private int m_LastLogin; 422 private int m_LastLogin;
494 423
424 private int m_lastIncoming;
425 private int m_lastOutgoing;
426 private int m_hbRestarts = 0;
427
428
495 /// <summary> 429 /// <summary>
496 /// Thread that runs the scene loop. 430 /// Thread that runs the scene loop.
497 /// </summary> 431 /// </summary>
@@ -510,7 +444,7 @@ namespace OpenSim.Region.Framework.Scenes
510 /// Is the scene active? 444 /// Is the scene active?
511 /// </summary> 445 /// </summary>
512 /// <remarks> 446 /// <remarks>
513 /// If false, maintenance and update loops are not being run, though after setting to false update may still 447 /// 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 448 /// be active for a period (and IsRunning will still be true). Updates can still be triggered manually if
515 /// the scene is not active. 449 /// the scene is not active.
516 /// </remarks> 450 /// </remarks>
@@ -540,9 +474,21 @@ namespace OpenSim.Region.Framework.Scenes
540 public bool IsRunning { get { return m_isRunning; } } 474 public bool IsRunning { get { return m_isRunning; } }
541 private volatile bool m_isRunning; 475 private volatile bool m_isRunning;
542 476
477 private bool m_firstHeartbeat = true;
478
479// private UpdatePrioritizationSchemes m_priorityScheme = UpdatePrioritizationSchemes.Time;
480// private bool m_reprioritizationEnabled = true;
481// private double m_reprioritizationInterval = 5000.0;
482// private double m_rootReprioritizationDistance = 10.0;
483// private double m_childReprioritizationDistance = 20.0;
484
485
543 private Timer m_mapGenerationTimer = new Timer(); 486 private Timer m_mapGenerationTimer = new Timer();
544 private bool m_generateMaptiles; 487 private bool m_generateMaptiles;
545 488
489 protected int m_lastHealth = -1;
490 protected int m_lastUsers = -1;
491
546 #endregion Fields 492 #endregion Fields
547 493
548 #region Properties 494 #region Properties
@@ -571,6 +517,19 @@ namespace OpenSim.Region.Framework.Scenes
571 get { return m_sceneGridService; } 517 get { return m_sceneGridService; }
572 } 518 }
573 519
520 public ISnmpModule SnmpService
521 {
522 get
523 {
524 if (m_snmpService == null)
525 {
526 m_snmpService = RequestModuleInterface<ISnmpModule>();
527 }
528
529 return m_snmpService;
530 }
531 }
532
574 public ISimulationDataService SimulationDataService 533 public ISimulationDataService SimulationDataService
575 { 534 {
576 get 535 get
@@ -777,22 +736,25 @@ namespace OpenSim.Region.Framework.Scenes
777 get { return m_capsModule; } 736 get { return m_capsModule; }
778 } 737 }
779 738
780 public int MonitorFrameTime { get { return frameMS; } } 739 public int MonitorFrameTime { get { return (int)frameMS; } }
781 public int MonitorPhysicsUpdateTime { get { return physicsMS; } } 740 public int MonitorPhysicsUpdateTime { get { return (int)physicsMS; } }
782 public int MonitorPhysicsSyncTime { get { return physicsMS2; } } 741 public int MonitorPhysicsSyncTime { get { return (int)physicsMS2; } }
783 public int MonitorOtherTime { get { return otherMS; } } 742 public int MonitorOtherTime { get { return (int)otherMS; } }
784 public int MonitorTempOnRezTime { get { return tempOnRezMS; } } 743 public int MonitorTempOnRezTime { get { return (int)tempOnRezMS; } }
785 public int MonitorEventTime { get { return eventMS; } } // This may need to be divided into each event? 744 public int MonitorEventTime { get { return (int)eventMS; } } // This may need to be divided into each event?
786 public int MonitorBackupTime { get { return backupMS; } } 745 public int MonitorBackupTime { get { return (int)backupMS; } }
787 public int MonitorTerrainTime { get { return terrainMS; } } 746 public int MonitorTerrainTime { get { return (int)terrainMS; } }
788 public int MonitorLandTime { get { return landMS; } } 747 public int MonitorLandTime { get { return (int)landMS; } }
789 public int MonitorLastFrameTick { get { return m_lastFrameTick; } } 748 public int MonitorLastFrameTick { get { return m_lastFrameTick; } }
790 749
791 public UpdatePrioritizationSchemes UpdatePrioritizationScheme { get; set; } 750 public UpdatePrioritizationSchemes UpdatePrioritizationScheme { get; set; }
792 public bool IsReprioritizationEnabled { get; set; } 751 public bool IsReprioritizationEnabled { get; set; }
793 public double ReprioritizationInterval { get; set; } 752 public float ReprioritizationInterval { get; set; }
794 public double RootReprioritizationDistance { get; set; } 753 public float ReprioritizationDistance { get; set; }
795 public double ChildReprioritizationDistance { get; set; } 754 private float m_minReprioritizationDistance = 32f;
755 public bool ObjectsCullingByDistance = false;
756
757 private ExpiringCache<UUID, UUID> TeleportTargetsCoolDown = new ExpiringCache<UUID, UUID>();
796 758
797 public AgentCircuitManager AuthenticateHandler 759 public AgentCircuitManager AuthenticateHandler
798 { 760 {
@@ -857,17 +819,16 @@ namespace OpenSim.Region.Framework.Scenes
857 819
858 #region Constructors 820 #region Constructors
859 821
860 public Scene(RegionInfo regInfo, AgentCircuitManager authen, 822 public Scene(RegionInfo regInfo, AgentCircuitManager authen,
861 ISimulationDataService simDataService, IEstateDataService estateDataService, 823 ISimulationDataService simDataService, IEstateDataService estateDataService,
862 IConfigSource config, string simulatorVersion) 824 IConfigSource config, string simulatorVersion)
863 : this(regInfo) 825 : this(regInfo)
864 { 826 {
865 m_config = config; 827 m_config = config;
866 MinFrameTicks = 89; 828 FrameTime = 0.0908f;
867 FrameTimeWarnPercent = 60; 829 FrameTimeWarnPercent = 60;
868 FrameTimeCritPercent = 40; 830 FrameTimeCritPercent = 40;
869 Normalized55FPS = true; 831 Normalized55FPS = true;
870 MinMaintenanceTicks = 1000;
871 SeeIntoRegion = true; 832 SeeIntoRegion = true;
872 833
873 Random random = new Random(); 834 Random random = new Random();
@@ -878,6 +839,9 @@ namespace OpenSim.Region.Framework.Scenes
878 m_SimulationDataService = simDataService; 839 m_SimulationDataService = simDataService;
879 m_EstateDataService = estateDataService; 840 m_EstateDataService = estateDataService;
880 841
842 m_lastIncoming = 0;
843 m_lastOutgoing = 0;
844
881 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this); 845 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
882 m_asyncSceneObjectDeleter.Enabled = true; 846 m_asyncSceneObjectDeleter.Enabled = true;
883 847
@@ -935,9 +899,9 @@ namespace OpenSim.Region.Framework.Scenes
935 EventManager.OnLandObjectRemoved += 899 EventManager.OnLandObjectRemoved +=
936 new EventManager.LandObjectRemoved(simDataService.RemoveLandObject); 900 new EventManager.LandObjectRemoved(simDataService.RemoveLandObject);
937 901
938 RegisterDefaultSceneEvents(); 902 RegisterDefaultSceneEvents();
939 903
940 // XXX: Don't set the public property since we don't want to activate here. This needs to be handled 904 // 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. 905 // better in the future.
942 m_scripts_enabled = !RegionInfo.RegionSettings.DisableScripts; 906 m_scripts_enabled = !RegionInfo.RegionSettings.DisableScripts;
943 907
@@ -956,6 +920,18 @@ namespace OpenSim.Region.Framework.Scenes
956 StartDisabled = startupConfig.GetBoolean("StartDisabled", false); 920 StartDisabled = startupConfig.GetBoolean("StartDisabled", false);
957 921
958 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance", m_defaultDrawDistance); 922 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance", m_defaultDrawDistance);
923 m_maxDrawDistance = startupConfig.GetFloat("MaxDrawDistance", m_maxDrawDistance);
924 m_maxRegionViewDistance = startupConfig.GetFloat("MaxRegionsViewDistance", m_maxRegionViewDistance);
925
926 // old versions compatibility
927 LegacySitOffsets = startupConfig.GetBoolean("LegacySitOffsets", LegacySitOffsets);
928
929 if (m_defaultDrawDistance > m_maxDrawDistance)
930 m_defaultDrawDistance = m_maxDrawDistance;
931
932 if (m_maxRegionViewDistance > m_maxDrawDistance)
933 m_maxRegionViewDistance = m_maxDrawDistance;
934
959 UseBackup = startupConfig.GetBoolean("UseSceneBackup", UseBackup); 935 UseBackup = startupConfig.GetBoolean("UseSceneBackup", UseBackup);
960 if (!UseBackup) 936 if (!UseBackup)
961 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName); 937 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName);
@@ -967,9 +943,8 @@ namespace OpenSim.Region.Framework.Scenes
967 943
968 MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20); 944 MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20);
969 945
970 PhysicalPrims = startupConfig.GetBoolean("physical_prim", PhysicalPrims); 946 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true);
971 CollidablePrims = startupConfig.GetBoolean("collidable_prim", CollidablePrims); 947 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
972
973 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys); 948 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys);
974 if (RegionInfo.NonphysPrimMin > 0) 949 if (RegionInfo.NonphysPrimMin > 0)
975 { 950 {
@@ -989,11 +964,24 @@ namespace OpenSim.Region.Framework.Scenes
989 } 964 }
990 965
991 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys); 966 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys);
967
992 if (RegionInfo.PhysPrimMax > 0) 968 if (RegionInfo.PhysPrimMax > 0)
993 { 969 {
994 m_maxPhys = RegionInfo.PhysPrimMax; 970 m_maxPhys = RegionInfo.PhysPrimMax;
995 } 971 }
996 972
973 m_linksetCapacity = startupConfig.GetInt("LinksetPrims", m_linksetCapacity);
974 if (RegionInfo.LinksetCapacity > 0)
975 {
976 m_linksetCapacity = RegionInfo.LinksetCapacity;
977 }
978
979 m_linksetPhysCapacity = startupConfig.GetInt("LinksetPhysPrims", m_linksetPhysCapacity);
980
981
982 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest");
983 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false);
984
997 // Here, if clamping is requested in either global or 985 // Here, if clamping is requested in either global or
998 // local config, it will be used 986 // local config, it will be used
999 // 987 //
@@ -1003,13 +991,9 @@ namespace OpenSim.Region.Framework.Scenes
1003 m_clampPrimSize = true; 991 m_clampPrimSize = true;
1004 } 992 }
1005 993
1006 m_linksetCapacity = startupConfig.GetInt("LinksetPrims", m_linksetCapacity); 994 m_clampNegativeZ = startupConfig.GetBoolean("ClampNegativeZ", m_clampNegativeZ);
1007 if (RegionInfo.LinksetCapacity > 0)
1008 {
1009 m_linksetCapacity = RegionInfo.LinksetCapacity;
1010 }
1011 995
1012 m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete", m_useTrashOnDelete); 996 m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete",m_useTrashOnDelete);
1013 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries); 997 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries);
1014 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings); 998 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings);
1015 m_dontPersistBefore = 999 m_dontPersistBefore =
@@ -1020,11 +1004,10 @@ namespace OpenSim.Region.Framework.Scenes
1020 m_persistAfter *= 10000000; 1004 m_persistAfter *= 10000000;
1021 1005
1022 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 1006 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
1023 1007 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
1024 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest");
1025 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false);
1026 1008
1027 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 1009 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
1010 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
1028 1011
1029 string[] possibleMapConfigSections = new string[] { "Map", "Startup" }; 1012 string[] possibleMapConfigSections = new string[] { "Map", "Startup" };
1030 1013
@@ -1070,7 +1053,7 @@ namespace OpenSim.Region.Framework.Scenes
1070 1053
1071 if (grant.Length > 0) 1054 if (grant.Length > 0)
1072 { 1055 {
1073 foreach (string viewer in grant.Split('|')) 1056 foreach (string viewer in grant.Split(','))
1074 { 1057 {
1075 m_AllowedViewers.Add(viewer.Trim().ToLower()); 1058 m_AllowedViewers.Add(viewer.Trim().ToLower());
1076 } 1059 }
@@ -1086,17 +1069,16 @@ namespace OpenSim.Region.Framework.Scenes
1086 1069
1087 if (grant.Length > 0) 1070 if (grant.Length > 0)
1088 { 1071 {
1089 foreach (string viewer in grant.Split('|')) 1072 foreach (string viewer in grant.Split(','))
1090 { 1073 {
1091 m_BannedViewers.Add(viewer.Trim().ToLower()); 1074 m_BannedViewers.Add(viewer.Trim().ToLower());
1092 } 1075 }
1093 } 1076 }
1094 1077
1095 if (startupConfig.Contains("MinFrameTime")) 1078 FrameTime = startupConfig.GetFloat( "FrameTime", FrameTime);
1096 MinFrameTicks = (int)(startupConfig.GetFloat("MinFrameTime") * 1000);
1097 FrameTimeWarnPercent = startupConfig.GetInt( "FrameTimeWarnPercent", FrameTimeWarnPercent); 1079 FrameTimeWarnPercent = startupConfig.GetInt( "FrameTimeWarnPercent", FrameTimeWarnPercent);
1098 FrameTimeCritPercent = startupConfig.GetInt( "FrameTimeCritPercent", FrameTimeCritPercent); 1080 FrameTimeCritPercent = startupConfig.GetInt( "FrameTimeCritPercent", FrameTimeCritPercent);
1099 Normalized55FPS = startupConfig.GetBoolean( "Normalized55FPS", Normalized55FPS); 1081 Normalized55FPS = startupConfig.GetBoolean( "Normalized55FPS", Normalized55FPS);
1100 1082
1101 m_update_backup = startupConfig.GetInt("UpdateStorageEveryNFrames", m_update_backup); 1083 m_update_backup = startupConfig.GetInt("UpdateStorageEveryNFrames", m_update_backup);
1102 m_update_coarse_locations = startupConfig.GetInt("UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations); 1084 m_update_coarse_locations = startupConfig.GetInt("UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations);
@@ -1108,21 +1090,6 @@ namespace OpenSim.Region.Framework.Scenes
1108 m_update_terrain = startupConfig.GetInt("UpdateTerrainEveryNFrames", m_update_terrain); 1090 m_update_terrain = startupConfig.GetInt("UpdateTerrainEveryNFrames", m_update_terrain);
1109 m_update_temp_cleaning = startupConfig.GetInt("UpdateTempCleaningEveryNSeconds", m_update_temp_cleaning); 1091 m_update_temp_cleaning = startupConfig.GetInt("UpdateTempCleaningEveryNSeconds", m_update_temp_cleaning);
1110 1092
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 } 1093 }
1127 1094
1128 #endregion Region Config 1095 #endregion Region Config
@@ -1131,6 +1098,7 @@ namespace OpenSim.Region.Framework.Scenes
1131 if (entityTransferConfig != null) 1098 if (entityTransferConfig != null)
1132 { 1099 {
1133 AllowAvatarCrossing = entityTransferConfig.GetBoolean("AllowAvatarCrossing", AllowAvatarCrossing); 1100 AllowAvatarCrossing = entityTransferConfig.GetBoolean("AllowAvatarCrossing", AllowAvatarCrossing);
1101 DisableObjectTransfer = entityTransferConfig.GetBoolean("DisableObjectTransfer", false);
1134 } 1102 }
1135 1103
1136 #region Interest Management 1104 #region Interest Management
@@ -1153,60 +1121,51 @@ namespace OpenSim.Region.Framework.Scenes
1153 IsReprioritizationEnabled 1121 IsReprioritizationEnabled
1154 = interestConfig.GetBoolean("ReprioritizationEnabled", IsReprioritizationEnabled); 1122 = interestConfig.GetBoolean("ReprioritizationEnabled", IsReprioritizationEnabled);
1155 ReprioritizationInterval 1123 ReprioritizationInterval
1156 = interestConfig.GetDouble("ReprioritizationInterval", ReprioritizationInterval); 1124 = interestConfig.GetFloat("ReprioritizationInterval", ReprioritizationInterval);
1157 RootReprioritizationDistance 1125 ReprioritizationDistance
1158 = interestConfig.GetDouble("RootReprioritizationDistance", RootReprioritizationDistance); 1126 = interestConfig.GetFloat("RootReprioritizationDistance", ReprioritizationDistance);
1159 ChildReprioritizationDistance
1160 = interestConfig.GetDouble("ChildReprioritizationDistance", ChildReprioritizationDistance);
1161 1127
1162 RootTerseUpdatePeriod = interestConfig.GetInt("RootTerseUpdatePeriod", RootTerseUpdatePeriod); 1128 if(ReprioritizationDistance < m_minReprioritizationDistance)
1163 ChildTerseUpdatePeriod = interestConfig.GetInt("ChildTerseUpdatePeriod", ChildTerseUpdatePeriod); 1129 ReprioritizationDistance = m_minReprioritizationDistance;
1130
1131 ObjectsCullingByDistance
1132 = interestConfig.GetBoolean("ObjectsCullingByDistance", ObjectsCullingByDistance);
1164 1133
1165 RootPositionUpdateTolerance
1166 = interestConfig.GetFloat("RootPositionUpdateTolerance", RootPositionUpdateTolerance);
1167 RootRotationUpdateTolerance
1168 = interestConfig.GetFloat("RootRotationUpdateTolerance", RootRotationUpdateTolerance);
1169 RootVelocityUpdateTolerance
1170 = interestConfig.GetFloat("RootVelocityUpdateTolerance", RootVelocityUpdateTolerance);
1171 } 1134 }
1172 1135
1173 m_log.DebugFormat("[SCENE]: Using the {0} prioritization scheme", UpdatePrioritizationScheme); 1136 m_log.DebugFormat("[SCENE]: Using the {0} prioritization scheme", UpdatePrioritizationScheme);
1174 1137
1175 #endregion Interest Management 1138 #endregion Interest Management
1176 1139
1177 // The timer used by the Stopwatch class depends on the system hardware and operating system; inform 1140 StatsReporter = new SimStatsReporter(this);
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 1141
1185 // Acquire the statistics section of the OpenSim.ini file located 1142 StatsReporter.OnSendStatsResult += SendSimStatsPackets;
1186 // in the bin directory 1143 StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats;
1187 IConfig statisticsConfig = m_config.Configs["Statistics"];
1188 1144
1189 // Confirm that the statistics section existed in the configuration 1145 IConfig restartConfig = config.Configs["RestartModule"];
1190 // file 1146 if (restartConfig != null)
1191 if (statisticsConfig != null)
1192 {
1193 // Create the StatsReporter using the number of frames to store
1194 // for the frame time statistics, or 10 frames if the config
1195 // file doesn't contain a value
1196 StatsReporter = new SimStatsReporter(this,
1197 statisticsConfig.GetInt("NumberOfFrames",
1198 m_defaultNumberFramesStored));
1199 }
1200 else
1201 { 1147 {
1202 // Create a StatsReporter with the current scene and a default 1148 string markerPath = restartConfig.GetString("MarkerPath", String.Empty);
1203 // 10 frames stored for the frame time statistics
1204 StatsReporter = new SimStatsReporter(this);
1205 }
1206 1149
1207 StatsReporter.OnSendStatsResult += SendSimStatsPackets; 1150 if (markerPath != String.Empty)
1208 StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats; 1151 {
1152 string path = Path.Combine(markerPath, RegionInfo.RegionID.ToString() + ".started");
1153 try
1154 {
1155 string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
1156 FileStream fs = File.Create(path);
1157 System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
1158 Byte[] buf = enc.GetBytes(pidstring);
1159 fs.Write(buf, 0, buf.Length);
1160 fs.Close();
1161 }
1162 catch (Exception)
1163 {
1164 }
1165 }
1166 }
1209 1167
1168 StartTimerWatchdog();
1210 } 1169 }
1211 1170
1212 public Scene(RegionInfo regInfo) 1171 public Scene(RegionInfo regInfo)
@@ -1240,15 +1199,12 @@ namespace OpenSim.Region.Framework.Scenes
1240 UpdatePrioritizationScheme = UpdatePrioritizationSchemes.Time; 1199 UpdatePrioritizationScheme = UpdatePrioritizationSchemes.Time;
1241 ReprioritizationInterval = 5000; 1200 ReprioritizationInterval = 5000;
1242 1201
1243 RootRotationUpdateTolerance = 0.1f; 1202 ReprioritizationDistance = m_minReprioritizationDistance;
1244 RootVelocityUpdateTolerance = 0.001f;
1245 RootPositionUpdateTolerance = 0.05f;
1246 RootReprioritizationDistance = 10.0;
1247 ChildReprioritizationDistance = 20.0;
1248 1203
1249 m_eventManager = new EventManager(); 1204 m_eventManager = new EventManager();
1250 1205
1251 m_permissions = new ScenePermissions(this); 1206 m_permissions = new ScenePermissions(this);
1207
1252 } 1208 }
1253 1209
1254 #endregion 1210 #endregion
@@ -1285,7 +1241,6 @@ namespace OpenSim.Region.Framework.Scenes
1285 if (!fm.TryGetFeature("OpenSimExtras", out openSimExtras)) 1241 if (!fm.TryGetFeature("OpenSimExtras", out openSimExtras))
1286 openSimExtras = new OSDMap(); 1242 openSimExtras = new OSDMap();
1287 1243
1288 float FrameTime = MinFrameTicks / 1000.0f;
1289 float statisticsFPSfactor = 1.0f; 1244 float statisticsFPSfactor = 1.0f;
1290 if(Normalized55FPS) 1245 if(Normalized55FPS)
1291 statisticsFPSfactor = 55.0f * FrameTime; 1246 statisticsFPSfactor = 55.0f * FrameTime;
@@ -1302,7 +1257,7 @@ namespace OpenSim.Region.Framework.Scenes
1302 1257
1303 protected virtual void RegisterDefaultSceneEvents() 1258 protected virtual void RegisterDefaultSceneEvents()
1304 { 1259 {
1305 m_eventManager.OnSignificantClientMovement += HandleOnSignificantClientMovement; 1260// m_eventManager.OnSignificantClientMovement += HandleOnSignificantClientMovement;
1306 } 1261 }
1307 1262
1308 public override string GetSimulatorVersion() 1263 public override string GetSimulatorVersion()
@@ -1325,20 +1280,8 @@ namespace OpenSim.Region.Framework.Scenes
1325 { 1280 {
1326 if (RegionInfo.RegionHandle != otherRegion.RegionHandle) 1281 if (RegionInfo.RegionHandle != otherRegion.RegionHandle)
1327 { 1282 {
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 1283
1338 //m_log.InfoFormat("[SCENE]: (on region {0}): Region {1} up in coords {2}-{3}", 1284 if (isNeighborRegion(otherRegion))
1339 // RegionInfo.RegionName, otherRegion.RegionName, newRegionX, newRegionY);
1340
1341 if (!Util.IsOutsideView(dist, thisRegionX, newRegionX, thisRegionY, newRegionY))
1342 { 1285 {
1343 // Let the grid service module know, so this can be cached 1286 // Let the grid service module know, so this can be cached
1344 m_eventManager.TriggerOnRegionUp(otherRegion); 1287 m_eventManager.TriggerOnRegionUp(otherRegion);
@@ -1373,6 +1316,21 @@ namespace OpenSim.Region.Framework.Scenes
1373 } 1316 }
1374 } 1317 }
1375 1318
1319 public bool isNeighborRegion(GridRegion otherRegion)
1320 {
1321 int tmp = otherRegion.RegionLocX - (int)RegionInfo.WorldLocX; ;
1322
1323 if (tmp < -otherRegion.RegionSizeX && tmp > RegionInfo.RegionSizeX)
1324 return false;
1325
1326 tmp = otherRegion.RegionLocY - (int)RegionInfo.WorldLocY;
1327
1328 if (tmp < -otherRegion.RegionSizeY && tmp > RegionInfo.RegionSizeY)
1329 return false;
1330
1331 return true;
1332 }
1333
1376 public void AddNeighborRegion(RegionInfo region) 1334 public void AddNeighborRegion(RegionInfo region)
1377 { 1335 {
1378 lock (m_neighbours) 1336 lock (m_neighbours)
@@ -1475,13 +1433,24 @@ namespace OpenSim.Region.Framework.Scenes
1475 return; 1433 return;
1476 } 1434 }
1477 1435
1436 IEtcdModule etcd = RequestModuleInterface<IEtcdModule>();
1437 if (etcd != null)
1438 {
1439 etcd.Delete("Health");
1440 etcd.Delete("HealthFlags");
1441 etcd.Delete("RootAgents");
1442 }
1443
1478 m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName); 1444 m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName);
1479 1445
1480 StatsReporter.Close();
1481 1446
1447 StatsReporter.Close();
1482 m_restartTimer.Stop(); 1448 m_restartTimer.Stop();
1483 m_restartTimer.Close(); 1449 m_restartTimer.Close();
1484 1450
1451 if (!GridService.DeregisterRegion(RegionInfo.RegionID))
1452 m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name);
1453
1485 // Kick all ROOT agents with the message, 'The simulator is going down' 1454 // Kick all ROOT agents with the message, 'The simulator is going down'
1486 ForEachScenePresence(delegate(ScenePresence avatar) 1455 ForEachScenePresence(delegate(ScenePresence avatar)
1487 { 1456 {
@@ -1504,13 +1473,15 @@ namespace OpenSim.Region.Framework.Scenes
1504 // Stop all client threads. 1473 // Stop all client threads.
1505 ForEachScenePresence(delegate(ScenePresence avatar) { CloseAgent(avatar.UUID, false); }); 1474 ForEachScenePresence(delegate(ScenePresence avatar) { CloseAgent(avatar.UUID, false); });
1506 1475
1507 m_log.Debug("[SCENE]: Persisting changed objects"); 1476 m_log.Debug("[SCENE]: TriggerSceneShuttingDown");
1508 EventManager.TriggerSceneShuttingDown(this); 1477 EventManager.TriggerSceneShuttingDown(this);
1509 Backup(false);
1510 m_sceneGraph.Close();
1511 1478
1512 if (!GridService.DeregisterRegion(RegionInfo.RegionID)) 1479 m_log.Debug("[SCENE]: Persisting changed objects");
1513 m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name); 1480 Backup(true);
1481
1482 m_log.Debug("[SCENE]: Closing scene");
1483
1484 m_sceneGraph.Close();
1514 1485
1515 base.Close(); 1486 base.Close();
1516 1487
@@ -1519,6 +1490,7 @@ namespace OpenSim.Region.Framework.Scenes
1519 // attempt to reference a null or disposed physics scene. 1490 // attempt to reference a null or disposed physics scene.
1520 if (PhysicsScene != null) 1491 if (PhysicsScene != null)
1521 { 1492 {
1493 m_log.Debug("[SCENE]: Dispose Physics");
1522 PhysicsScene phys = PhysicsScene; 1494 PhysicsScene phys = PhysicsScene;
1523 // remove the physics engine from both Scene and SceneGraph 1495 // remove the physics engine from both Scene and SceneGraph
1524 PhysicsScene = null; 1496 PhysicsScene = null;
@@ -1537,7 +1509,7 @@ namespace OpenSim.Region.Framework.Scenes
1537 /// </summary> 1509 /// </summary>
1538 /// <param name='startScripts'> 1510 /// <param name='startScripts'>
1539 /// Start the scripts within the scene. 1511 /// Start the scripts within the scene.
1540 /// </param> 1512 /// </param>
1541 public void Start(bool startScripts) 1513 public void Start(bool startScripts)
1542 { 1514 {
1543 if (IsRunning) 1515 if (IsRunning)
@@ -1550,10 +1522,31 @@ namespace OpenSim.Region.Framework.Scenes
1550// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); 1522// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName);
1551 if (m_heartbeatThread != null) 1523 if (m_heartbeatThread != null)
1552 { 1524 {
1525 m_hbRestarts++;
1526 if(m_hbRestarts > 10)
1527 Environment.Exit(1);
1528 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1529
1530//int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
1531//System.Diagnostics.Process proc = new System.Diagnostics.Process();
1532//proc.EnableRaisingEvents=false;
1533//proc.StartInfo.FileName = "/bin/kill";
1534//proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
1535//proc.Start();
1536//proc.WaitForExit();
1537//Thread.Sleep(1000);
1538//Environment.Exit(1);
1553 m_heartbeatThread.Abort(); 1539 m_heartbeatThread.Abort();
1540 Watchdog.AbortThread(m_heartbeatThread.ManagedThreadId);
1554 m_heartbeatThread = null; 1541 m_heartbeatThread = null;
1555 } 1542 }
1556 1543
1544 GC.Collect();
1545 GC.WaitForPendingFinalizers();
1546 GC.Collect();
1547 // tell physics to finish building actor
1548 m_sceneGraph.ProcessPhysicsPreSimulation();
1549
1557 m_heartbeatThread 1550 m_heartbeatThread
1558 = WorkManager.StartThread( 1551 = WorkManager.StartThread(
1559 Heartbeat, string.Format("Heartbeat-({0})", RegionInfo.RegionName.Replace(" ", "_")), ThreadPriority.Normal, false, false); 1552 Heartbeat, string.Format("Heartbeat-({0})", RegionInfo.RegionName.Replace(" ", "_")), ThreadPriority.Normal, false, false);
@@ -1596,136 +1589,13 @@ namespace OpenSim.Region.Framework.Scenes
1596 // alarms for scenes with many objects. 1589 // alarms for scenes with many objects.
1597 Update(1); 1590 Update(1);
1598 1591
1599 WorkManager.StartThread(
1600 Maintenance, string.Format("Maintenance ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, true);
1601
1602 Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true; 1592 Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true;
1603 m_lastFrameTick = Util.EnvironmentTickCount(); 1593 m_lastFrameTick = Util.EnvironmentTickCount();
1604 1594 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(); 1595 Watchdog.RemoveThread();
1649 } 1596 }
1650 1597
1651 public void DoMaintenance(int runs) 1598 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 { 1599 {
1730 long? endFrame = null; 1600 long? endFrame = null;
1731 1601
@@ -1733,119 +1603,97 @@ namespace OpenSim.Region.Framework.Scenes
1733 endFrame = Frame + frames; 1603 endFrame = Frame + frames;
1734 1604
1735 float physicsFPS = 0f; 1605 float physicsFPS = 0f;
1736 int previousFrameTick, tmpMS; 1606 float frameTimeMS = FrameTime * 1000.0f;
1737 1607
1738 // These variables will be used to save the precise frame time using the 1608 int previousFrameTick;
1739 // Stopwatch class of Microsoft SDK; the times are recorded at the start 1609
1740 // and end of a particular section of code, and then used to calculate 1610 double tmpMS;
1741 // the frame times, which are the sums of the sections for each given name 1611 double tmpMS2;
1742 double preciseTotalFrameTime = 0.0; 1612 double framestart;
1743 double preciseSimFrameTime = 0.0; 1613 float sleepMS;
1744 double precisePhysicsFrameTime = 0.0; 1614 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 1615
1753 while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame)) 1616 while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame))
1754 { 1617 {
1618 framestart = Util.GetTimeStampMS();
1755 ++Frame; 1619 ++Frame;
1756 1620
1757 // m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName); 1621 // m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName);
1758 1622
1759 agentMS = eventMS = backupMS = terrainMS = landMS = spareMS = 0; 1623 agentMS = tempOnRezMS = eventMS = backupMS = terrainMS = landMS = 0f;
1760 1624
1761 try 1625 try
1762 { 1626 {
1763 EventManager.TriggerRegionHeartbeatStart(this); 1627 EventManager.TriggerRegionHeartbeatStart(this);
1764 1628
1765 // Apply taints in terrain module to terrain in physics scene 1629 // Apply taints in terrain module to terrain in physics scene
1630
1631 tmpMS = Util.GetTimeStampMS();
1632
1633 if (Frame % 4 == 0)
1634 {
1635 CheckTerrainUpdates();
1636 }
1637
1766 if (Frame % m_update_terrain == 0) 1638 if (Frame % m_update_terrain == 0)
1767 { 1639 {
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(); 1640 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 } 1641 }
1788 1642
1789 // At several points inside the code there was a need to 1643 tmpMS2 = Util.GetTimeStampMS();
1790 // create a more precise measurement of time elapsed. This 1644 terrainMS = (float)(tmpMS2 - tmpMS);
1791 // led to the addition of variables that have a similar 1645 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
1799 tmpMS = Util.EnvironmentTickCount();
1800 1646
1801 // Begin the stopwatch to track the time to prepare physics
1802 physicsFrameStopwatch.Start();
1803 if (PhysicsEnabled && Frame % m_update_physics == 0) 1647 if (PhysicsEnabled && Frame % m_update_physics == 0)
1804 m_sceneGraph.UpdatePreparePhysics(); 1648 m_sceneGraph.UpdatePreparePhysics();
1805 1649
1806 // Get the time it took to prepare the physics, this 1650 tmpMS2 = Util.GetTimeStampMS();
1807 // would report the most precise time that physics was 1651 physicsMS2 = (float)(tmpMS2 - tmpMS);
1808 // running on the machine and should the physics not be 1652 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 1653
1654/*
1815 // Apply any pending avatar force input to the avatar's velocity 1655 // 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) 1656 if (Frame % m_update_entitymovement == 0)
1819 m_sceneGraph.UpdateScenePresenceMovement(); 1657 m_sceneGraph.UpdateScenePresenceMovement();
1658*/
1659 if (Frame % (m_update_coarse_locations) == 0 && !m_sendingCoarseLocations)
1660 {
1661 m_sendingCoarseLocations = true;
1662 WorkManager.RunInThreadPool(
1663 delegate
1664 {
1665 List<Vector3> coarseLocations;
1666 List<UUID> avatarUUIDs;
1667 SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60);
1668 // Send coarse locations to clients
1669 ForEachScenePresence(delegate(ScenePresence presence)
1670 {
1671 presence.SendCoarseLocations(coarseLocations, avatarUUIDs);
1672 });
1673 m_sendingCoarseLocations = false;
1674 }, null, string.Format("SendCoarseLocations ({0})", Name));
1675 }
1820 1676
1821 // Get the simulation frame time that the avatar force input 1677 // Get the simulation frame time that the avatar force input
1822 // took 1678 // took
1823 simFrameStopwatch.Stop(); 1679 tmpMS2 = Util.GetTimeStampMS();
1824 preciseSimFrameTime += 1680 agentMS = (float)(tmpMS2 - tmpMS);
1825 simFrameStopwatch.Elapsed.TotalMilliseconds; 1681 tmpMS = tmpMS2;
1826 agentMS = Util.EnvironmentTickCountSubtract(tmpMS);
1827 1682
1828 // Perform the main physics update. This will do the actual work of moving objects and avatars according to their 1683 // Perform the main physics update. This will do the actual work of moving objects and avatars according to their
1829 // velocity 1684 // velocity
1830 tmpMS = Util.EnvironmentTickCount();
1831 physicsFrameStopwatch.Restart();
1832 if (Frame % m_update_physics == 0) 1685 if (Frame % m_update_physics == 0)
1833 { 1686 {
1834 if (PhysicsEnabled) 1687 if (PhysicsEnabled)
1835 physicsFPS = m_sceneGraph.UpdatePhysics(MinFrameSeconds); 1688 physicsFPS = m_sceneGraph.UpdatePhysics(FrameTime);
1836 1689
1837 if (SynchronizeScene != null) 1690 if (SynchronizeScene != null)
1838 SynchronizeScene(this); 1691 SynchronizeScene(this);
1839 } 1692 }
1840 1693
1841 // Add the main physics update time to the prepare physics time 1694 tmpMS2 = Util.GetTimeStampMS();
1842 physicsFrameStopwatch.Stop(); 1695 physicsMS = (float)(tmpMS2 - tmpMS);
1843 precisePhysicsFrameTime += physicsFrameStopwatch.Elapsed.TotalMilliseconds; 1696 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 1697
1850 // Check if any objects have reached their targets 1698 // Check if any objects have reached their targets
1851 CheckAtTargets(); 1699 CheckAtTargets();
@@ -1860,20 +1708,37 @@ namespace OpenSim.Region.Framework.Scenes
1860 if (Frame % m_update_presences == 0) 1708 if (Frame % m_update_presences == 0)
1861 m_sceneGraph.UpdatePresences(); 1709 m_sceneGraph.UpdatePresences();
1862 1710
1863 agentMS += Util.EnvironmentTickCountSubtract(tmpMS); 1711 tmpMS2 = Util.GetTimeStampMS();
1712 agentMS += (float)(tmpMS2 - tmpMS);
1713 tmpMS = tmpMS2;
1714
1715 // Delete temp-on-rez stuff
1716 if (Frame % m_update_temp_cleaning == 0 && !m_cleaningTemps)
1717 {
1718 m_cleaningTemps = true;
1719 WorkManager.RunInThreadPool(
1720 delegate { CleanTempObjects(); m_cleaningTemps = false; }, null, string.Format("CleanTempObjects ({0})", Name));
1721 tmpMS2 = Util.GetTimeStampMS();
1722 tempOnRezMS = (float)(tmpMS2 - tmpMS); // bad.. counts the FireAndForget, not CleanTempObjects
1723 tmpMS = tmpMS2;
1724 }
1864 1725
1865 if (Frame % m_update_events == 0) 1726 if (Frame % m_update_events == 0)
1866 { 1727 {
1867 tmpMS = Util.EnvironmentTickCount();
1868 UpdateEvents(); 1728 UpdateEvents();
1869 eventMS = Util.EnvironmentTickCountSubtract(tmpMS); 1729
1730 tmpMS2 = Util.GetTimeStampMS();
1731 eventMS = (float)(tmpMS2 - tmpMS);
1732 tmpMS = tmpMS2;
1870 } 1733 }
1871 1734
1872 if (PeriodicBackup && Frame % m_update_backup == 0) 1735 if (PeriodicBackup && Frame % m_update_backup == 0)
1873 { 1736 {
1874 tmpMS = Util.EnvironmentTickCount();
1875 UpdateStorageBackup(); 1737 UpdateStorageBackup();
1876 backupMS = Util.EnvironmentTickCountSubtract(tmpMS); 1738
1739 tmpMS2 = Util.GetTimeStampMS();
1740 backupMS = (float)(tmpMS2 - tmpMS);
1741 tmpMS = tmpMS2;
1877 } 1742 }
1878 1743
1879 //if (Frame % m_update_land == 0) 1744 //if (Frame % m_update_land == 0)
@@ -1885,13 +1750,9 @@ namespace OpenSim.Region.Framework.Scenes
1885 1750
1886 if (!LoginsEnabled && Frame == 20) 1751 if (!LoginsEnabled && Frame == 20)
1887 { 1752 {
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(); 1753 GC.Collect();
1894 1754 GC.WaitForPendingFinalizers();
1755 GC.Collect();
1895 if (!LoginLock) 1756 if (!LoginLock)
1896 { 1757 {
1897 if (!StartDisabled) 1758 if (!StartDisabled)
@@ -1916,6 +1777,7 @@ namespace OpenSim.Region.Framework.Scenes
1916 // LoginLock can currently only be set by a region module implementation. 1777 // 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 1778 // If somehow this hasn't been done then the quickest way to bugfix is to see the
1918 // NullReferenceException 1779 // NullReferenceException
1780
1919 IRegionReadyModule rrm = RequestModuleInterface<IRegionReadyModule>(); 1781 IRegionReadyModule rrm = RequestModuleInterface<IRegionReadyModule>();
1920 rrm.TriggerRegionReady(this); 1782 rrm.TriggerRegionReady(this);
1921 } 1783 }
@@ -1930,79 +1792,64 @@ namespace OpenSim.Region.Framework.Scenes
1930 } 1792 }
1931 1793
1932 EventManager.TriggerRegionHeartbeatEnd(this); 1794 EventManager.TriggerRegionHeartbeatEnd(this);
1933 otherMS = eventMS + backupMS + terrainMS + landMS; 1795 m_firstHeartbeat = false;
1796 Watchdog.UpdateThread();
1934 1797
1935 // Get the elapsed time for the simulation frame 1798 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS;
1936 simFrameStopwatch.Stop();
1937 preciseSimFrameTime +=
1938 simFrameStopwatch.Elapsed.TotalMilliseconds;
1939 1799
1940 if (!UpdateOnTimer) 1800 tmpMS = Util.GetTimeStampMS();
1941 {
1942 Watchdog.UpdateThread();
1943 1801
1944 spareMS = MinFrameTicks - Util.EnvironmentTickCountSubtract(m_lastFrameTick); 1802 previousFrameTick = m_lastFrameTick;
1803 m_lastFrameTick = (int)(tmpMS + 0.5);
1945 1804
1946 if (spareMS > 0) 1805 // estimate sleep time
1947 m_updateWaitEvent.WaitOne(spareMS); 1806 tmpMS2 = tmpMS - framestart;
1948 else 1807 tmpMS2 = (double)frameTimeMS - tmpMS2 - sleepError;
1949 spareMS = 0; 1808
1950 } 1809 // reuse frameMS as temporary
1810 frameMS = (float)tmpMS2;
1811
1812 // sleep if we can
1813 if (tmpMS2 > 0)
1814 {
1815 Thread.Sleep((int)(tmpMS2 + 0.5));
1816
1817 tmpMS2 = Util.GetTimeStampMS();
1818 sleepMS = (float)(tmpMS2 - tmpMS);
1819 sleepError = sleepMS - frameMS;
1820 Util.Clamp(sleepError, 0.0f, 20f);
1821 frameMS = (float)(tmpMS2 - framestart);
1822 }
1951 else 1823 else
1952 { 1824 {
1953 spareMS = Math.Max(0, MinFrameTicks - physicsMS2 - agentMS - physicsMS - otherMS); 1825 tmpMS2 = Util.GetTimeStampMS();
1954 } 1826 frameMS = (float)(tmpMS2 - framestart);
1827 sleepMS = 0.0f;
1828 sleepError = 0.0f;
1829 }
1955 1830
1956 // Get the total frame time 1831 // script time is not scene frame time, but is displayed per frame
1957 totalFrameStopwatch.Stop(); 1832 float scriptTimeMS = GetAndResetScriptExecutionTime();
1958 preciseTotalFrameTime = 1833 StatsReporter.AddFrameStats(TimeDilation, physicsFPS, agentMS,
1959 totalFrameStopwatch.Elapsed.TotalMilliseconds; 1834 physicsMS + physicsMS2, otherMS , sleepMS, frameMS, scriptTimeMS);
1960 1835
1961 // Restart the stopwatch for the total time of the next frame
1962 totalFrameStopwatch.Restart();
1963 1836
1964 previousFrameTick = m_lastFrameTick;
1965 frameMS = Util.EnvironmentTickCountSubtract(m_lastFrameTick);
1966 m_lastFrameTick = Util.EnvironmentTickCount();
1967 1837
1968 // if (Frame%m_update_avatars == 0) 1838 // if (Frame%m_update_avatars == 0)
1969 // UpdateInWorldTime(); 1839 // UpdateInWorldTime();
1970 StatsReporter.AddPhysicsFPS(physicsFPS); 1840
1971 StatsReporter.AddTimeDilation(TimeDilation); 1841 // 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 1842 if (DebugUpdates
1993 && Util.EnvironmentTickCountSubtract( 1843 && Util.EnvironmentTickCountSubtract(
1994 m_lastFrameTick, previousFrameTick) > MinFrameTicks * 2) 1844 m_lastFrameTick, previousFrameTick) > (int)(FrameTime * 1000 * 2))
1845
1995 m_log.WarnFormat( 1846 m_log.WarnFormat(
1996 "[SCENE]: Frame took {0} ms (desired max {1} ms) in {2}", 1847 "[SCENE]: Frame took {0} ms (desired max {1} ms) in {2}",
1997 Util.EnvironmentTickCountSubtract(m_lastFrameTick, previousFrameTick), 1848 Util.EnvironmentTickCountSubtract(m_lastFrameTick, previousFrameTick),
1998 MinFrameTicks, 1849 FrameTime * 1000,
1850
1999 RegionInfo.RegionName); 1851 RegionInfo.RegionName);
2000 } 1852 }
2001
2002 // Finished updating scene frame, so stop the total frame's Stopwatch
2003 totalFrameStopwatch.Stop();
2004
2005 return spareMS >= 0;
2006 } 1853 }
2007 1854
2008 /// <summary> 1855 /// <summary>
@@ -2011,24 +1858,28 @@ namespace OpenSim.Region.Framework.Scenes
2011 /// <param name="ticks">Elapsed Stopwatch ticks</param> 1858 /// <param name="ticks">Elapsed Stopwatch ticks</param>
2012 public void AddScriptExecutionTime(long ticks) 1859 public void AddScriptExecutionTime(long ticks)
2013 { 1860 {
1861 StatsReporter.addScriptEvents(1);
2014 Interlocked.Add(ref m_scriptExecutionTime, ticks); 1862 Interlocked.Add(ref m_scriptExecutionTime, ticks);
2015 } 1863 }
2016 1864
2017 /// <summary> 1865 /// <summary>
2018 /// Returns the total execution time of all the scripts in the region since the last frame 1866 /// 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. 1867 /// (in milliseconds), and clears the value in preparation for the next call.
2020 /// </summary> 1868 /// </summary>
2021 /// <returns>Time in milliseconds</returns> 1869 /// <returns>Time in milliseconds</returns>
2022 private long GetAndResetScriptExecutionTime() 1870
1871 // Warning: this is now called from StatsReporter, and can't be shared
1872
1873 public long GetAndResetScriptExecutionTime()
2023 { 1874 {
2024 long ticks = Interlocked.Exchange(ref m_scriptExecutionTime, 0); 1875 long ticks = Interlocked.Exchange(ref m_scriptExecutionTime, 0);
2025 return (ticks * 1000) / Stopwatch.Frequency; 1876 return (ticks * 1000L) / Stopwatch.Frequency;
2026 } 1877 }
2027 1878
2028 public void AddGroupTarget(SceneObjectGroup grp) 1879 public void AddGroupTarget(SceneObjectGroup grp)
2029 { 1880 {
2030 lock (m_groupsWithTargets) 1881 lock (m_groupsWithTargets)
2031 m_groupsWithTargets[grp.UUID] = grp; 1882 m_groupsWithTargets[grp.UUID] = 0;
2032 } 1883 }
2033 1884
2034 public void RemoveGroupTarget(SceneObjectGroup grp) 1885 public void RemoveGroupTarget(SceneObjectGroup grp)
@@ -2039,18 +1890,24 @@ namespace OpenSim.Region.Framework.Scenes
2039 1890
2040 private void CheckAtTargets() 1891 private void CheckAtTargets()
2041 { 1892 {
2042 List<SceneObjectGroup> objs = null; 1893 List<UUID> objs = null;
2043 1894
2044 lock (m_groupsWithTargets) 1895 lock (m_groupsWithTargets)
2045 { 1896 {
2046 if (m_groupsWithTargets.Count != 0) 1897 if (m_groupsWithTargets.Count != 0)
2047 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values); 1898 objs = new List<UUID>(m_groupsWithTargets.Keys);
2048 } 1899 }
2049 1900
2050 if (objs != null) 1901 if (objs != null)
2051 { 1902 {
2052 foreach (SceneObjectGroup entry in objs) 1903 foreach (UUID entry in objs)
2053 entry.checkAtTargets(); 1904 {
1905 SceneObjectGroup grp = GetSceneObjectGroup(entry);
1906 if (grp == null)
1907 m_groupsWithTargets.Remove(entry);
1908 else
1909 grp.checkAtTargets();
1910 }
2054 } 1911 }
2055 } 1912 }
2056 1913
@@ -2074,6 +1931,11 @@ namespace OpenSim.Region.Framework.Scenes
2074 EventManager.TriggerTerrainTick(); 1931 EventManager.TriggerTerrainTick();
2075 } 1932 }
2076 1933
1934 private void CheckTerrainUpdates()
1935 {
1936 EventManager.TriggerTerrainCheckUpdates();
1937 }
1938
2077 /// <summary> 1939 /// <summary>
2078 /// Back up queued up changes 1940 /// Back up queued up changes
2079 /// </summary> 1941 /// </summary>
@@ -2081,8 +1943,7 @@ namespace OpenSim.Region.Framework.Scenes
2081 { 1943 {
2082 if (!m_backingup) 1944 if (!m_backingup)
2083 { 1945 {
2084 m_backingup = true; 1946 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 } 1947 }
2087 } 1948 }
2088 1949
@@ -2110,38 +1971,58 @@ namespace OpenSim.Region.Framework.Scenes
2110 { 1971 {
2111 lock (m_returns) 1972 lock (m_returns)
2112 { 1973 {
2113 EventManager.TriggerOnBackup(SimulationDataService, forced); 1974 if(m_backingup)
2114 m_backingup = false; 1975 {
1976 m_log.WarnFormat("[Scene] Backup of {0} already running. New call skipped", RegionInfo.RegionName);
1977 return;
1978 }
2115 1979
2116 foreach (KeyValuePair<UUID, ReturnInfo> ret in m_returns) 1980 m_backingup = true;
1981 try
2117 { 1982 {
2118 UUID transaction = UUID.Random(); 1983 EventManager.TriggerOnBackup(SimulationDataService, forced);
2119 1984
2120 GridInstantMessage msg = new GridInstantMessage(); 1985 if(m_returns.Count == 0)
2121 msg.fromAgentID = new Guid(UUID.Zero.ToString()); // From server 1986 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 1987
2140 IMessageTransferModule tr = RequestModuleInterface<IMessageTransferModule>(); 1988 IMessageTransferModule tr = RequestModuleInterface<IMessageTransferModule>();
2141 if (tr != null) 1989 if (tr == null)
1990 return;
1991
1992 uint unixtime = (uint)Util.UnixTimeSinceEpoch();
1993 uint estateid = RegionInfo.EstateSettings.ParentEstateID;
1994 Guid regionguid = RegionInfo.RegionID.Guid;
1995
1996 foreach (KeyValuePair<UUID, ReturnInfo> ret in m_returns)
1997 {
1998 GridInstantMessage msg = new GridInstantMessage();
1999 msg.fromAgentID = Guid.Empty; // From server
2000 msg.toAgentID = ret.Key.Guid;
2001 msg.imSessionID = Guid.NewGuid();
2002 msg.timestamp = unixtime;
2003 msg.fromAgentName = "Server";
2004 msg.dialog = 19; // Object msg
2005 msg.fromGroup = false;
2006 msg.offline = 1;
2007 msg.ParentEstateID = estateid;
2008 msg.Position = Vector3.Zero;
2009 msg.RegionID = regionguid;
2010
2011 // We must fill in a null-terminated 'empty' string here since bytes[0] will crash viewer 3.
2012 msg.binaryBucket = new Byte[1] {0};
2013 if (ret.Value.count > 1)
2014 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);
2015 else
2016 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);
2017
2142 tr.SendInstantMessage(msg, delegate(bool success) { }); 2018 tr.SendInstantMessage(msg, delegate(bool success) { });
2019 }
2020 m_returns.Clear();
2021 }
2022 finally
2023 {
2024 m_backingup = false;
2143 } 2025 }
2144 m_returns.Clear();
2145 } 2026 }
2146 } 2027 }
2147 2028
@@ -2159,7 +2040,7 @@ namespace OpenSim.Region.Framework.Scenes
2159 } 2040 }
2160 2041
2161 /// <summary> 2042 /// <summary>
2162 /// Tell an agent that their object has been returned. 2043 /// Tell an agent that their object has been returned.
2163 /// </summary> 2044 /// </summary>
2164 /// <remarks> 2045 /// <remarks>
2165 /// The actual return is handled by the caller. 2046 /// The actual return is handled by the caller.
@@ -2199,7 +2080,16 @@ namespace OpenSim.Region.Framework.Scenes
2199 /// </summary> 2080 /// </summary>
2200 public void SaveTerrain() 2081 public void SaveTerrain()
2201 { 2082 {
2202 SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); 2083 SimulationDataService.StoreTerrain(Heightmap.GetTerrainData(), RegionInfo.RegionID);
2084 }
2085
2086 /// <summary>
2087 /// Store the terrain in the persistant data store
2088 /// </summary>
2089 public void SaveBakedTerrain()
2090 {
2091 if(Bakedmap != null)
2092 SimulationDataService.StoreBakedTerrain(Bakedmap.GetTerrainData(), RegionInfo.RegionID);
2203 } 2093 }
2204 2094
2205 public void StoreWindlightProfile(RegionLightShareData wl) 2095 public void StoreWindlightProfile(RegionLightShareData wl)
@@ -2222,20 +2112,44 @@ namespace OpenSim.Region.Framework.Scenes
2222 { 2112 {
2223 try 2113 try
2224 { 2114 {
2115 Bakedmap = null;
2116 TerrainData map = SimulationDataService.LoadBakedTerrain(RegionInfo.RegionID, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ);
2117 if (map != null)
2118 {
2119 Bakedmap = new TerrainChannel(map);
2120 }
2121 }
2122 catch (Exception e)
2123 {
2124 m_log.WarnFormat(
2125 "[TERRAIN]: Scene.cs: LoadWorldMap() baked terrain - Failed with exception {0}{1}", e.Message, e.StackTrace);
2126 }
2127
2128 try
2129 {
2225 TerrainData map = SimulationDataService.LoadTerrain(RegionInfo.RegionID, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ); 2130 TerrainData map = SimulationDataService.LoadTerrain(RegionInfo.RegionID, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ);
2226 if (map == null) 2131 if (map == null)
2227 { 2132 {
2228 // This should be in the Terrain module, but it isn't because 2133 if(Bakedmap != null)
2229 // the heightmap is needed _way_ before the modules are initialized... 2134 {
2230 IConfig terrainConfig = m_config.Configs["Terrain"]; 2135 m_log.Warn("[TERRAIN]: terrain not found. Used stored baked terrain.");
2231 String m_InitialTerrain = "pinhead-island"; 2136 Heightmap = Bakedmap.MakeCopy();
2232 if (terrainConfig != null) 2137 SimulationDataService.StoreTerrain(Heightmap.GetTerrainData(), RegionInfo.RegionID);
2233 m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain); 2138 }
2139 else
2140 {
2141 // This should be in the Terrain module, but it isn't because
2142 // the heightmap is needed _way_ before the modules are initialized...
2143 IConfig terrainConfig = m_config.Configs["Terrain"];
2144 String m_InitialTerrain = "pinhead-island";
2145 if (terrainConfig != null)
2146 m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain);
2234 2147
2235 m_log.InfoFormat("[TERRAIN]: No default terrain. Generating a new terrain {0}.", m_InitialTerrain); 2148 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); 2149 Heightmap = new TerrainChannel(m_InitialTerrain, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ);
2237 2150
2238 SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); 2151 SimulationDataService.StoreTerrain(Heightmap.GetTerrainData(), RegionInfo.RegionID);
2152 }
2239 } 2153 }
2240 else 2154 else
2241 { 2155 {
@@ -2248,13 +2162,12 @@ namespace OpenSim.Region.Framework.Scenes
2248 "[TERRAIN]: Scene.cs: LoadWorldMap() - Regenerating as failed with exception {0}{1}", 2162 "[TERRAIN]: Scene.cs: LoadWorldMap() - Regenerating as failed with exception {0}{1}",
2249 e.Message, e.StackTrace); 2163 e.Message, e.StackTrace);
2250 2164
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 2165#pragma warning disable 0162
2253 if ((int)Constants.RegionSize != 256) 2166 if ((int)Constants.RegionSize != 256)
2254 { 2167 {
2255 Heightmap = new TerrainChannel(); 2168 Heightmap = new TerrainChannel();
2256 2169
2257 SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); 2170 SimulationDataService.StoreTerrain(Heightmap.GetTerrainData(), RegionInfo.RegionID);
2258 } 2171 }
2259 } 2172 }
2260 catch (Exception e) 2173 catch (Exception e)
@@ -2262,6 +2175,12 @@ namespace OpenSim.Region.Framework.Scenes
2262 m_log.WarnFormat( 2175 m_log.WarnFormat(
2263 "[TERRAIN]: Scene.cs: LoadWorldMap() - Failed with exception {0}{1}", e.Message, e.StackTrace); 2176 "[TERRAIN]: Scene.cs: LoadWorldMap() - Failed with exception {0}{1}", e.Message, e.StackTrace);
2264 } 2177 }
2178
2179 if(Bakedmap == null && Heightmap != null)
2180 {
2181 Bakedmap = Heightmap.MakeCopy();
2182 SimulationDataService.StoreBakedTerrain(Bakedmap.GetTerrainData(), RegionInfo.RegionID);
2183 }
2265 } 2184 }
2266 2185
2267 /// <summary> 2186 /// <summary>
@@ -2277,12 +2196,12 @@ namespace OpenSim.Region.Framework.Scenes
2277 //// stored in the GridService, because that's what the world map module uses 2196 //// 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... 2197 //// to send the map image UUIDs (of other regions) to the viewer...
2279 if (m_generateMaptiles) 2198 if (m_generateMaptiles)
2280 RegenerateMaptile(); 2199 RegenerateMaptile();
2281 2200
2282 GridRegion region = new GridRegion(RegionInfo); 2201 GridRegion region = new GridRegion(RegionInfo);
2283 string error = GridService.RegisterRegion(RegionInfo.ScopeID, region); 2202 string error = GridService.RegisterRegion(RegionInfo.ScopeID, region);
2284 // m_log.DebugFormat("[SCENE]: RegisterRegionWithGrid. name={0},id={1},loc=<{2},{3}>,size=<{4},{5}>", 2203 // m_log.DebugFormat("[SCENE]: RegisterRegionWithGrid. name={0},id={1},loc=<{2},{3}>,size=<{4},{5}>",
2285 // m_regionName, 2204 // m_regionName,
2286 // RegionInfo.RegionID, 2205 // RegionInfo.RegionID,
2287 // RegionInfo.RegionLocX, RegionInfo.RegionLocY, 2206 // RegionInfo.RegionLocX, RegionInfo.RegionLocY,
2288 // RegionInfo.RegionSizeX, RegionInfo.RegionSizeY); 2207 // RegionInfo.RegionSizeX, RegionInfo.RegionSizeY);
@@ -2344,7 +2263,9 @@ namespace OpenSim.Region.Framework.Scenes
2344 EventManager.TriggerOnSceneObjectLoaded(group); 2263 EventManager.TriggerOnSceneObjectLoaded(group);
2345 SceneObjectPart rootPart = group.GetPart(group.UUID); 2264 SceneObjectPart rootPart = group.GetPart(group.UUID);
2346 rootPart.Flags &= ~PrimFlags.Scripted; 2265 rootPart.Flags &= ~PrimFlags.Scripted;
2266
2347 rootPart.TrimPermissions(); 2267 rootPart.TrimPermissions();
2268 group.InvalidateDeepEffectivePerms();
2348 2269
2349 // Don't do this here - it will get done later on when sculpt data is loaded. 2270 // Don't do this here - it will get done later on when sculpt data is loaded.
2350 // group.CheckSculptAndLoad(); 2271 // group.CheckSculptAndLoad();
@@ -2383,93 +2304,166 @@ namespace OpenSim.Region.Framework.Scenes
2383 /// <returns></returns> 2304 /// <returns></returns>
2384 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 2305 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
2385 { 2306 {
2386 Vector3 pos = Vector3.Zero;
2387 if (RayEndIsIntersection == (byte)1)
2388 {
2389 pos = RayEnd;
2390 return pos;
2391 }
2392 2307
2393 if (RayTargetID != UUID.Zero) 2308 Vector3 dir = RayEnd - RayStart;
2309
2310 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
2311 Vector3 wpos = Vector3.Zero;
2312 // Check for water surface intersection from above
2313 if ((RayStart.Z > wheight) && (RayEnd.Z < wheight))
2394 { 2314 {
2395 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 2315 float ratio = (wheight - RayStart.Z) / dir.Z;
2316 wpos.X = RayStart.X + (ratio * dir.X);
2317 wpos.Y = RayStart.Y + (ratio * dir.Y);
2318 wpos.Z = wheight;
2319 }
2396 2320
2397 Vector3 direction = Vector3.Normalize(RayEnd - RayStart); 2321 Vector3 pos = Vector3.Zero;
2398 Vector3 AXOrigin = RayStart;
2399 Vector3 AXdirection = direction;
2400 2322
2401 if (target != null) 2323 if (RayEndIsIntersection != (byte)1)
2324 {
2325 float dist = dir.Length();
2326 if (dist != 0)
2402 { 2327 {
2403 pos = target.AbsolutePosition; 2328 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 2329
2406 // TODO: Raytrace better here 2330 dist += 1.0f;
2407 2331
2408 //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection)); 2332 if (SupportsRayCastFiltered())
2409 Ray NewRay = new Ray(AXOrigin, AXdirection); 2333 {
2334 RayFilterFlags rayfilter = RayFilterFlags.BackFaceCull;
2335 rayfilter |= RayFilterFlags.land;
2336 rayfilter |= RayFilterFlags.physical;
2337 rayfilter |= RayFilterFlags.nonphysical;
2338 rayfilter |= RayFilterFlags.LSLPhantom; // ubODE will only see volume detectors
2339
2340 // get some more contacts ???
2341 int physcount = 4;
2342
2343 List<ContactResult> physresults =
2344 (List<ContactResult>)RayCastFiltered(RayStart, direction, dist, physcount, rayfilter);
2345 if (physresults != null && physresults.Count > 0)
2346 {
2347 // look for terrain ?
2348 if(RayTargetID == UUID.Zero)
2349 {
2350 foreach (ContactResult r in physresults)
2351 {
2352 if (r.ConsumerID == 0)
2353 {
2354 pos = r.Normal * scale;
2355 pos *= 0.5f;
2356 pos = r.Pos + pos;
2357
2358 if (wpos.Z > pos.Z) pos = wpos;
2359 return pos;
2360 }
2361 }
2362 }
2363 else
2364 {
2365 foreach (ContactResult r in physresults)
2366 {
2367 SceneObjectPart part = GetSceneObjectPart(r.ConsumerID);
2368 if (part == null)
2369 continue;
2370 if (part.UUID == RayTargetID)
2371 {
2372 pos = r.Normal * scale;
2373 pos *= 0.5f;
2374 pos = r.Pos + pos;
2375
2376 if (wpos.Z > pos.Z) pos = wpos;
2377 return pos;
2378 }
2379 }
2380 }
2381 // else the first we got
2382 pos = physresults[0].Normal * scale;
2383 pos *= 0.5f;
2384 pos = physresults[0].Pos + pos;
2385
2386 if (wpos.Z > pos.Z)
2387 pos = wpos;
2388 return pos;
2389 }
2410 2390
2411 // Ray Trace against target here 2391 }
2412 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 2392 if (RayTargetID != UUID.Zero)
2393 {
2394 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
2413 2395
2414 // Un-comment out the following line to Get Raytrace results printed to the console. 2396 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 2397
2418 // If we hit something 2398 if (target != null)
2419 if (ei.HitTF) 2399 {
2420 { 2400 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 2401
2437 } 2402 // Ray Trace against target here
2403 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
2438 2404
2439 return pos; 2405 // Un-comment out the following line to Get Raytrace results printed to the console.
2440 } 2406 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
2441 else 2407 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 2408
2445 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 2409 // If we hit something
2410 if (ei.HitTF)
2411 {
2412 Vector3 scaleComponent = ei.AAfaceNormal;
2413 if (scaleComponent.X != 0) ScaleOffset = scale.X;
2414 if (scaleComponent.Y != 0) ScaleOffset = scale.Y;
2415 if (scaleComponent.Z != 0) ScaleOffset = scale.Z;
2416 ScaleOffset = Math.Abs(ScaleOffset);
2417 Vector3 intersectionpoint = ei.ipoint;
2418 Vector3 normal = ei.normal;
2419 // Set the position to the intersection point
2420 Vector3 offset = (normal * (ScaleOffset / 2f));
2421 pos = (intersectionpoint + offset);
2422
2423 //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
2424 //And in cases when we weren't rezzing from inventory we were re-adding the 0.25 straight after calling this method
2425 // Un-offset the prim (it gets offset later by the consumer method)
2426 //pos.Z -= 0.25F;
2427
2428 if (wpos.Z > pos.Z) pos = wpos;
2429 return pos;
2430 }
2431 }
2432 else
2433 {
2434 // We don't have a target here, so we're going to raytrace all the objects in the scene.
2435 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(NewRay, true, false);
2446 2436
2447 // Un-comment the following line to print the raytrace results to the console. 2437 // 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()); 2438 //m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
2449 2439
2450 if (ei.HitTF) 2440 if (ei.HitTF)
2451 { 2441 {
2452 pos = ei.ipoint; 2442 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
2453 } 2443 }
2454 else 2444 else
2455 { 2445 {
2456 // fall back to our stupid functionality 2446 // fall back to our stupid functionality
2457 pos = RayEnd; 2447 pos = RayEnd;
2458 } 2448 }
2459 2449
2460 return pos; 2450 if (wpos.Z > pos.Z) pos = wpos;
2451 return pos;
2452 }
2453 }
2461 } 2454 }
2462 } 2455 }
2463 else
2464 {
2465 // fall back to our stupid functionality
2466 pos = RayEnd;
2467 2456
2468 //increase height so its above the ground. 2457 // fall back to our stupid functionality
2469 //should be getting the normal of the ground at the rez point and using that? 2458 pos = RayEnd;
2470 pos.Z += scale.Z / 2f; 2459
2471 return pos; 2460 //increase height so its above the ground.
2472 } 2461 //should be getting the normal of the ground at the rez point and using that?
2462 pos.Z += scale.Z / 2f;
2463 // return pos;
2464 // check against posible water intercept
2465 if (wpos.Z > pos.Z) pos = wpos;
2466 return pos;
2473 } 2467 }
2474 2468
2475 2469
@@ -2523,13 +2517,26 @@ namespace OpenSim.Region.Framework.Scenes
2523 { 2517 {
2524 // Otherwise, use this default creation code; 2518 // Otherwise, use this default creation code;
2525 sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape); 2519 sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape);
2526 AddNewSceneObject(sceneObject, true);
2527 sceneObject.SetGroup(groupID, null); 2520 sceneObject.SetGroup(groupID, null);
2521 AddNewSceneObject(sceneObject, true);
2522
2523 if (AgentPreferencesService != null) // This will override the brave new full perm world!
2524 {
2525 AgentPrefs prefs = AgentPreferencesService.GetAgentPreferences(ownerID);
2526 // Only apply user selected prefs if the user set them
2527 if (prefs != null && prefs.PermNextOwner != 0)
2528 {
2529 sceneObject.RootPart.GroupMask = (uint)prefs.PermGroup;
2530 sceneObject.RootPart.EveryoneMask = (uint)prefs.PermEveryone;
2531 sceneObject.RootPart.NextOwnerMask = (uint)prefs.PermNextOwner;
2532 }
2533 }
2528 } 2534 }
2529 2535
2530 if (UserManagementModule != null) 2536 if (UserManagementModule != null)
2531 sceneObject.RootPart.CreatorIdentification = UserManagementModule.GetUserUUI(ownerID); 2537 sceneObject.RootPart.CreatorIdentification = UserManagementModule.GetUserUUI(ownerID);
2532 2538
2539 sceneObject.InvalidateDeepEffectivePerms();;
2533 sceneObject.ScheduleGroupForFullUpdate(); 2540 sceneObject.ScheduleGroupForFullUpdate();
2534 2541
2535 return sceneObject; 2542 return sceneObject;
@@ -2560,12 +2567,12 @@ namespace OpenSim.Region.Framework.Scenes
2560 { 2567 {
2561 if (m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates)) 2568 if (m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates))
2562 { 2569 {
2570 sceneObject.IsDeleted = false;
2563 EventManager.TriggerObjectAddedToScene(sceneObject); 2571 EventManager.TriggerObjectAddedToScene(sceneObject);
2564 return true; 2572 return true;
2565 } 2573 }
2566 2574
2567 return false; 2575 return false;
2568
2569 } 2576 }
2570 2577
2571 /// <summary> 2578 /// <summary>
@@ -2657,6 +2664,15 @@ namespace OpenSim.Region.Framework.Scenes
2657 /// </summary> 2664 /// </summary>
2658 public void DeleteAllSceneObjects() 2665 public void DeleteAllSceneObjects()
2659 { 2666 {
2667 DeleteAllSceneObjects(false);
2668 }
2669
2670 /// <summary>
2671 /// Delete every object from the scene. This does not include attachments worn by avatars.
2672 /// </summary>
2673 public void DeleteAllSceneObjects(bool exceptNoCopy)
2674 {
2675 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
2660 lock (Entities) 2676 lock (Entities)
2661 { 2677 {
2662 EntityBase[] entities = Entities.GetEntities(); 2678 EntityBase[] entities = Entities.GetEntities();
@@ -2665,11 +2681,24 @@ namespace OpenSim.Region.Framework.Scenes
2665 if (e is SceneObjectGroup) 2681 if (e is SceneObjectGroup)
2666 { 2682 {
2667 SceneObjectGroup sog = (SceneObjectGroup)e; 2683 SceneObjectGroup sog = (SceneObjectGroup)e;
2668 if (!sog.IsAttachment) 2684 if (sog != null && !sog.IsAttachment)
2669 DeleteSceneObject((SceneObjectGroup)e, false); 2685 {
2686 if (!exceptNoCopy || ((sog.EffectiveOwnerPerms & (uint)PermissionMask.Copy) != 0))
2687 {
2688 DeleteSceneObject((SceneObjectGroup)e, false);
2689 }
2690 else
2691 {
2692 toReturn.Add((SceneObjectGroup)e);
2693 }
2694 }
2670 } 2695 }
2671 } 2696 }
2672 } 2697 }
2698 if (toReturn.Count > 0)
2699 {
2700 returnObjects(toReturn.ToArray(), null);
2701 }
2673 } 2702 }
2674 2703
2675 /// <summary> 2704 /// <summary>
@@ -2728,7 +2757,11 @@ namespace OpenSim.Region.Framework.Scenes
2728 2757
2729 group.DeleteGroupFromScene(silent); 2758 group.DeleteGroupFromScene(silent);
2730 2759
2731 // m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2760 // use this to mean also full delete
2761 if (removeScripts)
2762 group.Clear();
2763 partList = null;
2764 // m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2732 } 2765 }
2733 2766
2734 /// <summary> 2767 /// <summary>
@@ -2763,6 +2796,13 @@ namespace OpenSim.Region.Framework.Scenes
2763 return false; 2796 return false;
2764 } 2797 }
2765 2798
2799
2800 public void updateScenePartGroup(SceneObjectPart part, SceneObjectGroup grp)
2801 {
2802 m_sceneGraph.updateScenePartGroup(part, grp);
2803 }
2804
2805/* not in use, outdate by async method
2766 /// <summary> 2806 /// <summary>
2767 /// Move the given scene object into a new region depending on which region its absolute position has moved 2807 /// Move the given scene object into a new region depending on which region its absolute position has moved
2768 /// into. 2808 /// into.
@@ -2811,6 +2851,7 @@ namespace OpenSim.Region.Framework.Scenes
2811 if (EntityTransferModule != null) 2851 if (EntityTransferModule != null)
2812 EntityTransferModule.Cross(grp, attemptedPosition, silent); 2852 EntityTransferModule.Cross(grp, attemptedPosition, silent);
2813 } 2853 }
2854*/
2814 2855
2815 // Simple test to see if a position is in the current region. 2856 // 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. 2857 // This test is mostly used to see if a region crossing is necessary.
@@ -2818,27 +2859,15 @@ namespace OpenSim.Region.Framework.Scenes
2818 // Return 'true' if position inside region. 2859 // Return 'true' if position inside region.
2819 public bool PositionIsInCurrentRegion(Vector3 pos) 2860 public bool PositionIsInCurrentRegion(Vector3 pos)
2820 { 2861 {
2821 bool ret = false; 2862 float t = pos.X;
2822 int xx = (int)Math.Floor(pos.X); 2863 if (t < 0 || t >= RegionInfo.RegionSizeX)
2823 int yy = (int)Math.Floor(pos.Y);
2824 if (xx < 0 || yy < 0)
2825 return false; 2864 return false;
2826 2865
2827 IRegionCombinerModule regionCombinerModule = RequestModuleInterface<IRegionCombinerModule>(); 2866 t = pos.Y;
2828 if (regionCombinerModule == null) 2867 if (t < 0 || t >= RegionInfo.RegionSizeY)
2829 { 2868 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 2869
2870 return true;
2842 } 2871 }
2843 2872
2844 /// <summary> 2873 /// <summary>
@@ -2880,6 +2909,23 @@ namespace OpenSim.Region.Framework.Scenes
2880 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2909 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2881 public bool AddSceneObject(SceneObjectGroup sceneObject) 2910 public bool AddSceneObject(SceneObjectGroup sceneObject)
2882 { 2911 {
2912 if (sceneObject.OwnerID == UUID.Zero)
2913 {
2914 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2915 return false;
2916 }
2917
2918 // If the user is banned, we won't let any of their objects
2919 // enter. Period.
2920 //
2921 int flags = GetUserFlags(sceneObject.OwnerID);
2922 if (RegionInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2923 {
2924 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID);
2925
2926 return false;
2927 }
2928
2883 // Force allocation of new LocalId 2929 // Force allocation of new LocalId
2884 // 2930 //
2885 SceneObjectPart[] parts = sceneObject.Parts; 2931 SceneObjectPart[] parts = sceneObject.Parts;
@@ -2889,9 +2935,9 @@ namespace OpenSim.Region.Framework.Scenes
2889 if (sceneObject.IsAttachmentCheckFull()) // Attachment 2935 if (sceneObject.IsAttachmentCheckFull()) // Attachment
2890 { 2936 {
2891 sceneObject.RootPart.AddFlag(PrimFlags.TemporaryOnRez); 2937 sceneObject.RootPart.AddFlag(PrimFlags.TemporaryOnRez);
2892 sceneObject.RootPart.AddFlag(PrimFlags.Phantom); 2938// sceneObject.RootPart.AddFlag(PrimFlags.Phantom);
2893 2939
2894 // Don't sent a full update here because this will cause full updates to be sent twice for 2940 // 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. 2941 // attachments on region crossings, resulting in viewer glitches.
2896 AddRestoredSceneObject(sceneObject, false, false, false); 2942 AddRestoredSceneObject(sceneObject, false, false, false);
2897 2943
@@ -2912,7 +2958,7 @@ namespace OpenSim.Region.Framework.Scenes
2912 2958
2913 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2959 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2914 2960
2915 // We must currently not resume scripts at this stage since AttachmentsModule does not have the 2961 // 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. 2962 // information that this is due to a teleport/border cross rather than an ordinary attachment.
2917 // We currently do this in Scene.MakeRootAgent() instead. 2963 // We currently do this in Scene.MakeRootAgent() instead.
2918 if (AttachmentsModule != null) 2964 if (AttachmentsModule != null)
@@ -2920,18 +2966,60 @@ namespace OpenSim.Region.Framework.Scenes
2920 } 2966 }
2921 else 2967 else
2922 { 2968 {
2923 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2969 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2924 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 2970// RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2971// RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2972 }
2973 if (sceneObject.OwnerID == UUID.Zero)
2974 {
2975 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
2976 return false;
2925 } 2977 }
2926 } 2978 }
2927 else 2979 else
2928 { 2980 {
2981 if (sceneObject.OwnerID == UUID.Zero)
2982 {
2983 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
2984 return false;
2985 }
2929 AddRestoredSceneObject(sceneObject, true, false); 2986 AddRestoredSceneObject(sceneObject, true, false);
2930 } 2987 }
2931 2988
2932 return true; 2989 return true;
2933 } 2990 }
2934 2991
2992 private int GetStateSource(SceneObjectGroup sog)
2993 {
2994 if(!sog.IsAttachmentCheckFull())
2995 return 2; // StateSource.PrimCrossing
2996
2997 ScenePresence sp = GetScenePresence(sog.OwnerID);
2998 if (sp != null)
2999 return sp.GetStateSource();
3000
3001 return 2; // StateSource.PrimCrossing
3002 }
3003
3004 public int GetUserFlags(UUID user)
3005 {
3006 //Unfortunately the SP approach means that the value is cached until region is restarted
3007 /*
3008 ScenePresence sp;
3009 if (TryGetScenePresence(user, out sp))
3010 {
3011 return sp.UserFlags;
3012 }
3013 else
3014 {
3015 */
3016 UserAccount uac = UserAccountService.GetUserAccount(RegionInfo.ScopeID, user);
3017 if (uac == null)
3018 return 0;
3019 return uac.UserFlags;
3020 //}
3021 }
3022
2935 #endregion 3023 #endregion
2936 3024
2937 #region Add/Remove Avatar Methods 3025 #region Add/Remove Avatar Methods
@@ -2968,47 +3056,34 @@ namespace OpenSim.Region.Framework.Scenes
2968 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 3056 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0
2969 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 3057 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2970 3058
2971 // CheckHeartbeat(); 3059 CheckHeartbeat();
2972 3060
2973 sp = GetScenePresence(client.AgentId); 3061 sp = GetScenePresence(client.AgentId);
2974 3062
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) 3063 if (sp == null)
2980 { 3064 {
2981 m_log.DebugFormat( 3065 m_log.DebugFormat(
2982 "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", 3066 "[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); 3067 client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos,
2984 3068 ((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 3069
2998 m_clientManager.Add(client); 3070 m_clientManager.Add(client);
2999 SubscribeToClientEvents(client); 3071 SubscribeToClientEvents(client);
3000 m_eventManager.TriggerOnNewPresence(sp); 3072
3073 sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type);
3001 3074
3002 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; 3075 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags;
3076
3077 m_eventManager.TriggerOnNewPresence(sp);
3003 } 3078 }
3004 else 3079 else
3005 { 3080 {
3006 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the 3081 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the
3007 // client is for a root or child agent. 3082 // 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. 3083 // 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 3084 // But need to know what happens in the case where a ScenePresence is already present (and if this
3010 // actually occurs). 3085 // actually occurs).
3011 client.SceneAgent = sp; 3086
3012 3087
3013 m_log.WarnFormat( 3088 m_log.WarnFormat(
3014 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", 3089 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence",
@@ -3016,8 +3091,9 @@ namespace OpenSim.Region.Framework.Scenes
3016 3091
3017 reallyNew = false; 3092 reallyNew = false;
3018 } 3093 }
3094 client.SceneAgent = sp;
3019 3095
3020 // This is currently also being done earlier in NewUserConnection for real users to see if this 3096 // 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 3097 // 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. 3098 // places. However, we still need to do it here for NPCs.
3023 CacheUserName(sp, aCircuit); 3099 CacheUserName(sp, aCircuit);
@@ -3063,7 +3139,7 @@ namespace OpenSim.Region.Framework.Scenes
3063 3139
3064 if (sp != null && sp.PresenceType == PresenceType.Npc) 3140 if (sp != null && sp.PresenceType == PresenceType.Npc)
3065 { 3141 {
3066 UserManagementModule.AddUser(aCircuit.AgentID, first, last); 3142 UserManagementModule.AddUser(aCircuit.AgentID, first, last, true);
3067 } 3143 }
3068 else 3144 else
3069 { 3145 {
@@ -3134,19 +3210,15 @@ namespace OpenSim.Region.Framework.Scenes
3134 // and the scene presence and the client, if they exist 3210 // and the scene presence and the client, if they exist
3135 try 3211 try
3136 { 3212 {
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); 3213 ScenePresence sp = WaitGetScenePresence(agentID);
3214
3140 if (sp != null) 3215 if (sp != null)
3141 { 3216 {
3142 PresenceService.LogoutAgent(sp.ControllingClient.SessionId); 3217 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
3143 3218
3144 CloseAgent(sp.UUID, false); 3219 CloseAgent(sp.UUID, false);
3145 } 3220 }
3146 else 3221
3147 {
3148 m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID);
3149 }
3150 // BANG! SLASH! 3222 // BANG! SLASH!
3151 m_authenticateHandler.RemoveCircuit(agentID); 3223 m_authenticateHandler.RemoveCircuit(agentID);
3152 3224
@@ -3183,7 +3255,7 @@ namespace OpenSim.Region.Framework.Scenes
3183 3255
3184 public virtual void SubscribeToClientTerrainEvents(IClientAPI client) 3256 public virtual void SubscribeToClientTerrainEvents(IClientAPI client)
3185 { 3257 {
3186 client.OnRegionHandShakeReply += SendLayerData; 3258// client.OnRegionHandShakeReply += SendLayerData;
3187 } 3259 }
3188 3260
3189 public virtual void SubscribeToClientPrimEvents(IClientAPI client) 3261 public virtual void SubscribeToClientPrimEvents(IClientAPI client)
@@ -3191,6 +3263,8 @@ namespace OpenSim.Region.Framework.Scenes
3191 client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition; 3263 client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition;
3192 client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition; 3264 client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition;
3193 3265
3266 client.onClientChangeObject += m_sceneGraph.ClientChangeObject;
3267
3194 client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation; 3268 client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation;
3195 client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation; 3269 client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation;
3196 client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation; 3270 client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation;
@@ -3204,9 +3278,6 @@ namespace OpenSim.Region.Framework.Scenes
3204 client.OnObjectRequest += RequestPrim; 3278 client.OnObjectRequest += RequestPrim;
3205 client.OnObjectSelect += SelectPrim; 3279 client.OnObjectSelect += SelectPrim;
3206 client.OnObjectDeselect += DeselectPrim; 3280 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; 3281 client.OnDeRezObject += DeRezObjects;
3211 3282
3212 client.OnObjectName += m_sceneGraph.PrimName; 3283 client.OnObjectName += m_sceneGraph.PrimName;
@@ -3222,6 +3293,9 @@ namespace OpenSim.Region.Framework.Scenes
3222 client.OnGrabObject += ProcessObjectGrab; 3293 client.OnGrabObject += ProcessObjectGrab;
3223 client.OnGrabUpdate += ProcessObjectGrabUpdate; 3294 client.OnGrabUpdate += ProcessObjectGrabUpdate;
3224 client.OnDeGrabObject += ProcessObjectDeGrab; 3295 client.OnDeGrabObject += ProcessObjectDeGrab;
3296 client.OnSpinStart += ProcessSpinStart;
3297 client.OnSpinUpdate += ProcessSpinObject;
3298 client.OnSpinStop += ProcessSpinObjectStop;
3225 client.OnUndo += m_sceneGraph.HandleUndo; 3299 client.OnUndo += m_sceneGraph.HandleUndo;
3226 client.OnRedo += m_sceneGraph.HandleRedo; 3300 client.OnRedo += m_sceneGraph.HandleRedo;
3227 client.OnObjectDescription += m_sceneGraph.PrimDescription; 3301 client.OnObjectDescription += m_sceneGraph.PrimDescription;
@@ -3247,6 +3321,7 @@ namespace OpenSim.Region.Framework.Scenes
3247 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory; 3321 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory;
3248 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 3322 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
3249 client.OnCopyInventoryItem += CopyInventoryItem; 3323 client.OnCopyInventoryItem += CopyInventoryItem;
3324 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
3250 client.OnMoveInventoryItem += MoveInventoryItem; 3325 client.OnMoveInventoryItem += MoveInventoryItem;
3251 client.OnRemoveInventoryItem += RemoveInventoryItem; 3326 client.OnRemoveInventoryItem += RemoveInventoryItem;
3252 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 3327 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -3308,7 +3383,7 @@ namespace OpenSim.Region.Framework.Scenes
3308 3383
3309 public virtual void UnSubscribeToClientTerrainEvents(IClientAPI client) 3384 public virtual void UnSubscribeToClientTerrainEvents(IClientAPI client)
3310 { 3385 {
3311 client.OnRegionHandShakeReply -= SendLayerData; 3386// client.OnRegionHandShakeReply -= SendLayerData;
3312 } 3387 }
3313 3388
3314 public virtual void UnSubscribeToClientPrimEvents(IClientAPI client) 3389 public virtual void UnSubscribeToClientPrimEvents(IClientAPI client)
@@ -3316,6 +3391,8 @@ namespace OpenSim.Region.Framework.Scenes
3316 client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition; 3391 client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition;
3317 client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition; 3392 client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition;
3318 3393
3394 client.onClientChangeObject -= m_sceneGraph.ClientChangeObject;
3395
3319 client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation; 3396 client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation;
3320 client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation; 3397 client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation;
3321 client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation; 3398 client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation;
@@ -3329,9 +3406,6 @@ namespace OpenSim.Region.Framework.Scenes
3329 client.OnObjectRequest -= RequestPrim; 3406 client.OnObjectRequest -= RequestPrim;
3330 client.OnObjectSelect -= SelectPrim; 3407 client.OnObjectSelect -= SelectPrim;
3331 client.OnObjectDeselect -= DeselectPrim; 3408 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; 3409 client.OnDeRezObject -= DeRezObjects;
3336 client.OnObjectName -= m_sceneGraph.PrimName; 3410 client.OnObjectName -= m_sceneGraph.PrimName;
3337 client.OnObjectClickAction -= m_sceneGraph.PrimClickAction; 3411 client.OnObjectClickAction -= m_sceneGraph.PrimClickAction;
@@ -3344,7 +3418,11 @@ namespace OpenSim.Region.Framework.Scenes
3344 client.OnRequestObjectPropertiesFamily -= m_sceneGraph.RequestObjectPropertiesFamily; 3418 client.OnRequestObjectPropertiesFamily -= m_sceneGraph.RequestObjectPropertiesFamily;
3345 client.OnObjectPermissions -= HandleObjectPermissionsUpdate; 3419 client.OnObjectPermissions -= HandleObjectPermissionsUpdate;
3346 client.OnGrabObject -= ProcessObjectGrab; 3420 client.OnGrabObject -= ProcessObjectGrab;
3421 client.OnGrabUpdate -= ProcessObjectGrabUpdate;
3347 client.OnDeGrabObject -= ProcessObjectDeGrab; 3422 client.OnDeGrabObject -= ProcessObjectDeGrab;
3423 client.OnSpinStart -= ProcessSpinStart;
3424 client.OnSpinUpdate -= ProcessSpinObject;
3425 client.OnSpinStop -= ProcessSpinObjectStop;
3348 client.OnUndo -= m_sceneGraph.HandleUndo; 3426 client.OnUndo -= m_sceneGraph.HandleUndo;
3349 client.OnRedo -= m_sceneGraph.HandleRedo; 3427 client.OnRedo -= m_sceneGraph.HandleRedo;
3350 client.OnObjectDescription -= m_sceneGraph.PrimDescription; 3428 client.OnObjectDescription -= m_sceneGraph.PrimDescription;
@@ -3440,13 +3518,15 @@ namespace OpenSim.Region.Framework.Scenes
3440 /// <param name="GroupID">Group of new object</param> 3518 /// <param name="GroupID">Group of new object</param>
3441 public void DuplicateObject(uint originalPrim, Vector3 offset, uint flags, UUID AgentID, UUID GroupID) 3519 public void DuplicateObject(uint originalPrim, Vector3 offset, uint flags, UUID AgentID, UUID GroupID)
3442 { 3520 {
3443 SceneObjectGroup copy = SceneGraph.DuplicateObject(originalPrim, offset, flags, AgentID, GroupID, Quaternion.Identity); 3521 bool createSelected = (flags & (uint)PrimFlags.CreateSelected) != 0;
3522 SceneObjectGroup copy = SceneGraph.DuplicateObject(originalPrim, offset, AgentID,
3523 GroupID, Quaternion.Identity, createSelected);
3444 if (copy != null) 3524 if (copy != null)
3445 EventManager.TriggerObjectAddedToScene(copy); 3525 EventManager.TriggerObjectAddedToScene(copy);
3446 } 3526 }
3447 3527
3448 /// <summary> 3528 /// <summary>
3449 /// Duplicates object specified by localID at position raycasted against RayTargetObject using 3529 /// Duplicates object specified by localID at position raycasted against RayTargetObject using
3450 /// RayEnd and RayStart to determine what the angle of the ray is 3530 /// RayEnd and RayStart to determine what the angle of the ray is
3451 /// </summary> 3531 /// </summary>
3452 /// <param name="localID">ID of object to duplicate</param> 3532 /// <param name="localID">ID of object to duplicate</param>
@@ -3470,11 +3550,11 @@ namespace OpenSim.Region.Framework.Scenes
3470 SceneObjectPart target = GetSceneObjectPart(localID); 3550 SceneObjectPart target = GetSceneObjectPart(localID);
3471 SceneObjectPart target2 = GetSceneObjectPart(RayTargetObj); 3551 SceneObjectPart target2 = GetSceneObjectPart(RayTargetObj);
3472 3552
3553 bool createSelected = (dupeFlags & (uint)PrimFlags.CreateSelected) != 0;
3554
3473 if (target != null && target2 != null) 3555 if (target != null && target2 != null)
3474 { 3556 {
3475 Vector3 direction = Vector3.Normalize(RayEnd - RayStart); 3557 Vector3 direction = Vector3.Normalize(RayEnd - RayStart);
3476 Vector3 AXOrigin = RayStart;
3477 Vector3 AXdirection = direction;
3478 3558
3479 pos = target2.AbsolutePosition; 3559 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()); 3560 //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 +3562,7 @@ namespace OpenSim.Region.Framework.Scenes
3482 // TODO: Raytrace better here 3562 // TODO: Raytrace better here
3483 3563
3484 //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection)); 3564 //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection));
3485 Ray NewRay = new Ray(AXOrigin, AXdirection); 3565 Ray NewRay = new Ray(RayStart,direction);
3486 3566
3487 // Ray Trace against target here 3567 // Ray Trace against target here
3488 EntityIntersection ei = target2.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, CopyCenters); 3568 EntityIntersection ei = target2.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, CopyCenters);
@@ -3513,13 +3593,13 @@ namespace OpenSim.Region.Framework.Scenes
3513 Quaternion worldRot = target2.GetWorldRotation(); 3593 Quaternion worldRot = target2.GetWorldRotation();
3514 3594
3515 // SceneObjectGroup obj = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, worldRot); 3595 // SceneObjectGroup obj = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, worldRot);
3516 copy = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, worldRot); 3596 copy = m_sceneGraph.DuplicateObject(localID, pos, AgentID, GroupID, worldRot, createSelected);
3517 //obj.Rotation = worldRot; 3597 //obj.Rotation = worldRot;
3518 //obj.UpdateGroupRotationR(worldRot); 3598 //obj.UpdateGroupRotationR(worldRot);
3519 } 3599 }
3520 else 3600 else
3521 { 3601 {
3522 copy = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, Quaternion.Identity); 3602 copy = m_sceneGraph.DuplicateObject(localID, pos, AgentID, GroupID, Quaternion.Identity, createSelected);
3523 } 3603 }
3524 3604
3525 if (copy != null) 3605 if (copy != null)
@@ -3553,7 +3633,7 @@ namespace OpenSim.Region.Framework.Scenes
3553 } 3633 }
3554 3634
3555 /// <summary> 3635 /// <summary>
3556 /// Remove the given client from the scene. 3636 /// Remove the given client from the scene.
3557 /// </summary> 3637 /// </summary>
3558 /// <remarks> 3638 /// <remarks>
3559 /// Only clientstack code should call this directly. All other code should call IncomingCloseAgent() instead 3639 /// Only clientstack code should call this directly. All other code should call IncomingCloseAgent() instead
@@ -3564,11 +3644,15 @@ namespace OpenSim.Region.Framework.Scenes
3564 /// <param name='closeChildAgents'> 3644 /// <param name='closeChildAgents'>
3565 /// Close the neighbour child agents associated with this client. 3645 /// Close the neighbour child agents associated with this client.
3566 /// </param> 3646 /// </param>
3647 ///
3648
3649 private object m_removeClientPrivLock = new Object();
3650
3567 public void RemoveClient(UUID agentID, bool closeChildAgents) 3651 public void RemoveClient(UUID agentID, bool closeChildAgents)
3568 { 3652 {
3569 AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID); 3653 AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID);
3570 3654
3571 // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which 3655 // 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 3656 // 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. 3657 // However, will keep for now just in case.
3574 if (acd == null) 3658 if (acd == null)
@@ -3580,13 +3664,13 @@ namespace OpenSim.Region.Framework.Scenes
3580 } 3664 }
3581 3665
3582 // TODO: Can we now remove this lock? 3666 // TODO: Can we now remove this lock?
3583 lock (acd) 3667 lock (m_removeClientPrivLock)
3584 { 3668 {
3585 bool isChildAgent = false; 3669 bool isChildAgent = false;
3586 3670
3587 ScenePresence avatar = GetScenePresence(agentID); 3671 ScenePresence avatar = GetScenePresence(agentID);
3588 3672
3589 // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which 3673 // 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 3674 // 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. 3675 // However, will keep for now just in case.
3592 if (avatar == null) 3676 if (avatar == null)
@@ -3625,7 +3709,7 @@ namespace OpenSim.Region.Framework.Scenes
3625 // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop 3709 // 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 3710 // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI
3627 if (closeChildAgents && CapsModule != null) 3711 if (closeChildAgents && CapsModule != null)
3628 CapsModule.RemoveCaps(agentID); 3712 CapsModule.RemoveCaps(agentID, avatar.ControllingClient.CircuitCode);
3629 3713
3630 if (closeChildAgents && !isChildAgent) 3714 if (closeChildAgents && !isChildAgent)
3631 { 3715 {
@@ -3637,13 +3721,17 @@ namespace OpenSim.Region.Framework.Scenes
3637 } 3721 }
3638 3722
3639 m_eventManager.TriggerClientClosed(agentID, this); 3723 m_eventManager.TriggerClientClosed(agentID, this);
3724// m_log.Debug("[Scene]TriggerClientClosed done");
3640 m_eventManager.TriggerOnRemovePresence(agentID); 3725 m_eventManager.TriggerOnRemovePresence(agentID);
3726// m_log.Debug("[Scene]TriggerOnRemovePresence done");
3641 3727
3642 if (!isChildAgent) 3728 if (!isChildAgent)
3643 { 3729 {
3644 if (AttachmentsModule != null) 3730 if (AttachmentsModule != null)
3645 { 3731 {
3732// m_log.Debug("[Scene]DeRezAttachments");
3646 AttachmentsModule.DeRezAttachments(avatar); 3733 AttachmentsModule.DeRezAttachments(avatar);
3734// m_log.Debug("[Scene]DeRezAttachments done");
3647 } 3735 }
3648 3736
3649 ForEachClient( 3737 ForEachClient(
@@ -3657,7 +3745,11 @@ namespace OpenSim.Region.Framework.Scenes
3657 3745
3658 // It's possible for child agents to have transactions if changes are being made cross-border. 3746 // It's possible for child agents to have transactions if changes are being made cross-border.
3659 if (AgentTransactionsModule != null) 3747 if (AgentTransactionsModule != null)
3748 {
3749// m_log.Debug("[Scene]RemoveAgentAssetTransactions");
3660 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); 3750 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID);
3751 }
3752 m_log.Debug("[Scene] The avatar has left the building");
3661 } 3753 }
3662 catch (Exception e) 3754 catch (Exception e)
3663 { 3755 {
@@ -3691,7 +3783,7 @@ namespace OpenSim.Region.Framework.Scenes
3691 3783
3692 /// <summary> 3784 /// <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. 3785 /// 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 /// 3786 ///
3695 /// </summary> 3787 /// </summary>
3696 /// <param name="avatarID"></param> 3788 /// <param name="avatarID"></param>
3697 /// <param name="regionslst"></param> 3789 /// <param name="regionslst"></param>
@@ -3721,15 +3813,9 @@ namespace OpenSim.Region.Framework.Scenes
3721 foreach (uint localID in localIDs) 3813 foreach (uint localID in localIDs)
3722 { 3814 {
3723 SceneObjectPart part = GetSceneObjectPart(localID); 3815 SceneObjectPart part = GetSceneObjectPart(localID);
3724 if (part != null) // It is a prim 3816 if (part != null && part.ParentGroup != null &&
3725 { 3817 part.ParentGroup.RootPart == part)
3726 if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid 3818 deleteIDs.Add(localID);
3727 {
3728 if (part.ParentGroup.RootPart != part) // Child part
3729 continue;
3730 }
3731 }
3732 deleteIDs.Add(localID);
3733 } 3819 }
3734 3820
3735 ForEachClient(c => c.SendKillObject(deleteIDs)); 3821 ForEachClient(c => c.SendKillObject(deleteIDs));
@@ -3746,7 +3832,7 @@ namespace OpenSim.Region.Framework.Scenes
3746 /// <param name="teleportFlags"></param> 3832 /// <param name="teleportFlags"></param>
3747 /// <param name="source">Source region (may be null)</param> 3833 /// <param name="source">Source region (may be null)</param>
3748 /// <param name="reason">Outputs the reason for the false response on this string</param> 3834 /// <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 3835 /// <returns>True if the region accepts this agent. False if it does not. False will
3750 /// also return a reason.</returns> 3836 /// also return a reason.</returns>
3751 public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, GridRegion source, out string reason) 3837 public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, GridRegion source, out string reason)
3752 { 3838 {
@@ -3774,14 +3860,17 @@ namespace OpenSim.Region.Framework.Scenes
3774 /// <param name="reason">Outputs the reason for the false response on this string</param> 3860 /// <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 3861 /// <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> 3862 /// 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 3863 /// <returns>True if the region accepts this agent. False if it does not. False will
3778 /// also return a reason.</returns> 3864 /// also return a reason.</returns>
3865 ///
3866 private object m_newUserConnLock = new object();
3867
3779 public bool NewUserConnection(AgentCircuitData acd, uint teleportFlags, GridRegion source, out string reason, bool requirePresenceLookup) 3868 public bool NewUserConnection(AgentCircuitData acd, uint teleportFlags, GridRegion source, out string reason, bool requirePresenceLookup)
3780 { 3869 {
3781 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 || 3870 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 ||
3782 (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0); 3871 (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0);
3783 bool viahome = ((teleportFlags & (uint)TPFlags.ViaHome) != 0); 3872 bool viahome = ((teleportFlags & (uint)TPFlags.ViaHome) != 0);
3784 bool godlike = ((teleportFlags & (uint)TPFlags.Godlike) != 0); 3873// bool godlike = ((teleportFlags & (uint)TPFlags.Godlike) != 0);
3785 3874
3786 reason = String.Empty; 3875 reason = String.Empty;
3787 3876
@@ -3809,9 +3898,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) 3898 (source == null) ? "" : string.Format("From region {0} ({1}){2}", source.RegionName, source.RegionID, (source.RawServerURI == null) ? "" : " @ " + source.ServerURI)
3810 ); 3899 );
3811 3900
3901// m_log.DebugFormat("NewUserConnection stack {0}", Environment.StackTrace);
3902
3812 if (!LoginsEnabled) 3903 if (!LoginsEnabled)
3813 { 3904 {
3814 reason = "Logins Disabled"; 3905 reason = "Logins to this region are disabled";
3815 return false; 3906 return false;
3816 } 3907 }
3817 3908
@@ -3858,14 +3949,13 @@ namespace OpenSim.Region.Framework.Scenes
3858 return false; 3949 return false;
3859 } 3950 }
3860 3951
3861 ILandObject land;
3862 ScenePresence sp; 3952 ScenePresence sp;
3863 3953
3864 lock (m_removeClientLock) 3954 lock (m_removeClientLock)
3865 { 3955 {
3866 sp = GetScenePresence(acd.AgentID); 3956 sp = GetScenePresence(acd.AgentID);
3867 3957
3868 // We need to ensure that we are not already removing the scene presence before we ask it not to be 3958 // We need to ensure that we are not already removing the scene presence before we ask it not to be
3869 // closed. 3959 // closed.
3870 if (sp != null && sp.IsChildAgent 3960 if (sp != null && sp.IsChildAgent
3871 && (sp.LifecycleState == ScenePresenceState.Running 3961 && (sp.LifecycleState == ScenePresenceState.Running
@@ -3879,16 +3969,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 3969 // 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. 3970 // renews the lease on the child agent at B, we must make sure that the close from A does not succeed.
3881 // 3971 //
3882 // XXX: In the end, this should not be necessary if child agents are closed without delay on 3972 // 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 3973 // 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 3974 // 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 3975 // 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 3976 // 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). 3977 // flag when no teleport had taken place (and hence no close was going to come).
3888// if (!acd.ChildrenCapSeeds.ContainsKey(RegionInfo.RegionHandle)) 3978// if (!acd.ChildrenCapSeeds.ContainsKey(RegionInfo.RegionHandle))
3889// { 3979// {
3890// m_log.DebugFormat( 3980// m_log.DebugFormat(
3891// "[SCENE]: Setting DoNotCloseAfterTeleport for child scene presence {0} in {1} because source will attempt close.", 3981// "[SCENE]: Setting DoNotCloseAfterTeleport for child scene presence {0} in {1} because source will attempt close.",
3892// sp.Name, Name); 3982// sp.Name, Name);
3893// 3983//
3894// sp.DoNotCloseAfterTeleport = true; 3984// sp.DoNotCloseAfterTeleport = true;
@@ -3902,7 +3992,7 @@ namespace OpenSim.Region.Framework.Scenes
3902 sp.DoNotCloseAfterTeleport = true; 3992 sp.DoNotCloseAfterTeleport = true;
3903 3993
3904 m_log.DebugFormat( 3994 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.", 3995 "[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); 3996 sp.Name, Name);
3907 } 3997 }
3908 } 3998 }
@@ -3922,7 +4012,7 @@ namespace OpenSim.Region.Framework.Scenes
3922 if (sp.LifecycleState == ScenePresenceState.Removing) 4012 if (sp.LifecycleState == ScenePresenceState.Removing)
3923 { 4013 {
3924 m_log.WarnFormat( 4014 m_log.WarnFormat(
3925 "[SCENE]: Agent {0} in {1} was still being removed after {2}s. Aborting NewUserConnection.", 4015 "[SCENE]: Agent {0} in {1} was still being removed after {2}s. Aborting NewUserConnection.",
3926 sp.Name, Name, polls * pollInterval / 1000); 4016 sp.Name, Name, polls * pollInterval / 1000);
3927 4017
3928 return false; 4018 return false;
@@ -3936,14 +4026,14 @@ namespace OpenSim.Region.Framework.Scenes
3936 } 4026 }
3937 4027
3938 // TODO: can we remove this lock? 4028 // TODO: can we remove this lock?
3939 lock (acd) 4029 lock (m_newUserConnLock)
3940 { 4030 {
3941 if (sp != null && !sp.IsChildAgent) 4031 if (sp != null && !sp.IsChildAgent)
3942 { 4032 {
3943 // We have a root agent. Is it in transit? 4033 // We have a root agent. Is it in transit?
3944 if (!EntityTransferModule.IsInTransit(sp.UUID)) 4034 if (!EntityTransferModule.IsInTransit(sp.UUID))
3945 { 4035 {
3946 // We have a zombie from a crashed session. 4036 // We have a zombie from a crashed session.
3947 // Or the same user is trying to be root twice here, won't work. 4037 // Or the same user is trying to be root twice here, won't work.
3948 // Kill it. 4038 // Kill it.
3949 m_log.WarnFormat( 4039 m_log.WarnFormat(
@@ -3963,20 +4053,21 @@ namespace OpenSim.Region.Framework.Scenes
3963 // We need the circuit data here for some of the subsequent checks. (groups, for example) 4053 // We need the circuit data here for some of the subsequent checks. (groups, for example)
3964 // If the checks fail, we remove the circuit. 4054 // If the checks fail, we remove the circuit.
3965 acd.teleportFlags = teleportFlags; 4055 acd.teleportFlags = teleportFlags;
3966 m_authenticateHandler.AddNewCircuit(acd.circuitcode, acd);
3967
3968 land = LandChannel.GetLandObject(acd.startpos.X, acd.startpos.Y);
3969 4056
3970 // On login test land permisions
3971 if (vialogin) 4057 if (vialogin)
3972 { 4058 {
3973 if (land != null && !TestLandRestrictions(acd.AgentID, out reason, ref acd.startpos.X, ref acd.startpos.Y)) 4059 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3974 { 4060 if (cache != null)
3975 m_authenticateHandler.RemoveCircuit(acd.circuitcode); 4061// cache.Remove(acd.firstname + " " + acd.lastname);
3976 return false; 4062 cache.Remove(acd.AgentID);
3977 } 4063
4064 // Remove any preexisting circuit - we don't want duplicates
4065 // This is a stab at preventing avatar "ghosting"
4066 m_authenticateHandler.RemoveCircuit(acd.AgentID);
3978 } 4067 }
3979 4068
4069 m_authenticateHandler.AddNewCircuit(acd.circuitcode, acd);
4070
3980 if (sp == null) // We don't have an [child] agent here already 4071 if (sp == null) // We don't have an [child] agent here already
3981 { 4072 {
3982 if (requirePresenceLookup) 4073 if (requirePresenceLookup)
@@ -4024,7 +4115,7 @@ namespace OpenSim.Region.Framework.Scenes
4024 if (CapsModule != null) 4115 if (CapsModule != null)
4025 { 4116 {
4026 CapsModule.SetAgentCapsSeeds(acd); 4117 CapsModule.SetAgentCapsSeeds(acd);
4027 CapsModule.CreateCaps(acd.AgentID); 4118 CapsModule.CreateCaps(acd.AgentID, acd.circuitcode);
4028 } 4119 }
4029 } 4120 }
4030 else 4121 else
@@ -4039,13 +4130,13 @@ namespace OpenSim.Region.Framework.Scenes
4039 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", 4130 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
4040 acd.AgentID, RegionInfo.RegionName); 4131 acd.AgentID, RegionInfo.RegionName);
4041 4132
4042 sp.AdjustKnownSeeds();
4043
4044 if (CapsModule != null) 4133 if (CapsModule != null)
4045 { 4134 {
4046 CapsModule.SetAgentCapsSeeds(acd); 4135 CapsModule.SetAgentCapsSeeds(acd);
4047 CapsModule.CreateCaps(acd.AgentID); 4136 CapsModule.CreateCaps(acd.AgentID, acd.circuitcode);
4048 } 4137 }
4138
4139 sp.AdjustKnownSeeds();
4049 } 4140 }
4050 } 4141 }
4051 4142
@@ -4055,88 +4146,48 @@ namespace OpenSim.Region.Framework.Scenes
4055 CacheUserName(null, acd); 4146 CacheUserName(null, acd);
4056 } 4147 }
4057 4148
4058 if (vialogin) 4149 if (CapsModule != null)
4059 { 4150 {
4060// CleanDroppedAttachments(); 4151 CapsModule.ActivateCaps(acd.circuitcode);
4061 4152 }
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 4153
4116 // Final permissions check; this time we don't allow changing the position 4154// if (vialogin)
4117 if (!IsPositionAllowed(acd.AgentID, acd.startpos, ref reason)) 4155// {
4118 { 4156// CleanDroppedAttachments();
4119 m_authenticateHandler.RemoveCircuit(acd.circuitcode); 4157// }
4120 return false;
4121 }
4122 4158
4123 return true; 4159 if(teleportFlags != (uint) TPFlags.Default)
4124 } 4160 {
4161 // Make sure root avatar position is in the region
4162 if (acd.startpos.X < 0)
4163 acd.startpos.X = 1f;
4164 else if (acd.startpos.X >= RegionInfo.RegionSizeX)
4165 acd.startpos.X = RegionInfo.RegionSizeX - 1f;
4166 if (acd.startpos.Y < 0)
4167 acd.startpos.Y = 1f;
4168 else if (acd.startpos.Y >= RegionInfo.RegionSizeY)
4169 acd.startpos.Y = RegionInfo.RegionSizeY - 1f;
4170 }
4171 // only check access, actual relocations will happen later on ScenePresence MakeRoot
4172 // allow child agents creation
4173// if(!godlike && teleportFlags != (uint) TPFlags.Default)
4174 if(teleportFlags != (uint) TPFlags.Default)
4175 {
4176 bool checkTeleHub;
4177
4178 // don't check hubs if via home or via lure
4179 if((teleportFlags & (uint) TPFlags.ViaHome) != 0
4180 || (teleportFlags & (uint) TPFlags.ViaLure) != 0)
4181 checkTeleHub = false;
4182 else
4183 checkTeleHub = vialogin
4184 || (TelehubAllowLandmarks == true ? false : ((teleportFlags & (uint)TPFlags.ViaLandmark) != 0 ))
4185 || (teleportFlags & (uint) TPFlags.ViaLocation) != 0;
4125 4186
4126 // Honor parcel landing type and position. 4187 if(!CheckLandPositionAccess(acd.AgentID, true, checkTeleHub, acd.startpos, out reason))
4127 if (land != null)
4128 { 4188 {
4129 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 4189 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
4130 { 4190 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 } 4191 }
4141 } 4192 }
4142 4193
@@ -4162,12 +4213,13 @@ namespace OpenSim.Region.Framework.Scenes
4162 { 4213 {
4163 if (posX < 0) 4214 if (posX < 0)
4164 posX = 0; 4215 posX = 0;
4165 else if (posX >= (float)RegionInfo.RegionSizeX) 4216
4166 posX = (float)RegionInfo.RegionSizeX - 0.001f; 4217 else if (posX >= RegionInfo.RegionSizeX)
4218 posX = RegionInfo.RegionSizeX - 0.5f;
4167 if (posY < 0) 4219 if (posY < 0)
4168 posY = 0; 4220 posY = 0;
4169 else if (posY >= (float)RegionInfo.RegionSizeY) 4221 else if (posY >= RegionInfo.RegionSizeY)
4170 posY = (float)RegionInfo.RegionSizeY - 0.001f; 4222 posY = RegionInfo.RegionSizeY - 0.5f;
4171 4223
4172 reason = String.Empty; 4224 reason = String.Empty;
4173 if (Permissions.IsGod(agentID)) 4225 if (Permissions.IsGod(agentID))
@@ -4183,14 +4235,14 @@ namespace OpenSim.Region.Framework.Scenes
4183 if (banned || restricted) 4235 if (banned || restricted)
4184 { 4236 {
4185 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY); 4237 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY);
4238 Vector2? newPosition = null;
4186 if (nearestParcel != null) 4239 if (nearestParcel != null)
4187 { 4240 {
4188 //Move agent to nearest allowed 4241 //Move agent to nearest allowed
4189 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); 4242// Vector2 newPosition = GetParcelSafeCorner(nearestParcel);
4190 posX = newPosition.X; 4243 newPosition = nearestParcel.GetNearestPoint(new Vector3(posX, posY,0));
4191 posY = newPosition.Y;
4192 } 4244 }
4193 else 4245 if(newPosition == null)
4194 { 4246 {
4195 if (banned) 4247 if (banned)
4196 { 4248 {
@@ -4203,6 +4255,11 @@ namespace OpenSim.Region.Framework.Scenes
4203 } 4255 }
4204 return false; 4256 return false;
4205 } 4257 }
4258 else
4259 {
4260 posX = newPosition.Value.X;
4261 posY = newPosition.Value.Y;
4262 }
4206 } 4263 }
4207 reason = ""; 4264 reason = "";
4208 return true; 4265 return true;
@@ -4213,7 +4270,7 @@ namespace OpenSim.Region.Framework.Scenes
4213 /// </summary> 4270 /// </summary>
4214 /// <param name="agent">Circuit Data of the Agent we're verifying</param> 4271 /// <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> 4272 /// <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 4273 /// <returns>True if the user has a session on the grid. False if it does not. False will
4217 /// also return a reason.</returns> 4274 /// also return a reason.</returns>
4218 public virtual bool VerifyUserPresence(AgentCircuitData agent, out string reason) 4275 public virtual bool VerifyUserPresence(AgentCircuitData agent, out string reason)
4219 { 4276 {
@@ -4242,14 +4299,16 @@ namespace OpenSim.Region.Framework.Scenes
4242 /// </summary> 4299 /// </summary>
4243 /// <param name="agent">The circuit data for the agent</param> 4300 /// <param name="agent">The circuit data for the agent</param>
4244 /// <param name="reason">outputs the reason to this string</param> 4301 /// <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 4302 /// <returns>True if the region accepts this agent. False if it does not. False will
4246 /// also return a reason.</returns> 4303 /// also return a reason.</returns>
4247 protected virtual bool AuthorizeUser(AgentCircuitData agent, bool bypassAccessControl, out string reason) 4304 protected virtual bool AuthorizeUser(AgentCircuitData agent, bool bypassAccessControl, out string reason)
4248 { 4305 {
4249 reason = String.Empty; 4306 reason = String.Empty;
4250 4307
4251 if (!m_strictAccessControl) return true; 4308 if (!m_strictAccessControl)
4252 if (Permissions.IsGod(agent.AgentID)) return true; 4309 return true;
4310 if (Permissions.IsGod(agent.AgentID))
4311 return true;
4253 4312
4254 if (AuthorizationService != null) 4313 if (AuthorizationService != null)
4255 { 4314 {
@@ -4269,98 +4328,85 @@ namespace OpenSim.Region.Framework.Scenes
4269 // the root is done elsewhere (QueryAccess) 4328 // the root is done elsewhere (QueryAccess)
4270 if (!bypassAccessControl) 4329 if (!bypassAccessControl)
4271 { 4330 {
4272 if (RegionInfo.EstateSettings != null) 4331 if(RegionInfo.EstateSettings == null)
4273 { 4332 {
4274 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID)) 4333 // something is broken? let it get in
4275 { 4334 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", 4335 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 } 4336 }
4283 else 4337
4338 // check estate ban
4339 int flags = GetUserFlags(agent.AgentID);
4340 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, flags))
4284 { 4341 {
4285 m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!"); 4342 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
4343 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
4344 reason = String.Format("Denied access to region {0}: You have been banned from that region.",
4345 RegionInfo.RegionName);
4346 return false;
4286 } 4347 }
4287 4348
4288 List<UUID> agentGroups = new List<UUID>(); 4349 // public access
4350 if (RegionInfo.EstateSettings.PublicAccess)
4351 return true;
4352
4353 // in access list / owner / manager
4354 if (RegionInfo.EstateSettings.HasAccess(agent.AgentID))
4355 return true;
4289 4356
4290 if (m_groupsModule != null) 4357 // finally test groups
4358 bool groupAccess = false;
4359
4360 // some say GOTO is ugly
4361 if(m_groupsModule == null) // if no groups refuse
4362 goto Label_GroupsDone;
4363
4364 UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups;
4365
4366 if(estateGroups == null)
4291 { 4367 {
4292 GroupMembershipData[] GroupMembership = m_groupsModule.GetMembershipData(agent.AgentID); 4368 m_log.ErrorFormat("[CONNECTION BEGIN]: Estate GroupMembership is null!");
4369 goto Label_GroupsDone;
4370 }
4293 4371
4294 if (GroupMembership != null) 4372 if(estateGroups.Length == 0)
4295 { 4373 goto Label_GroupsDone;
4296 for (int i = 0; i < GroupMembership.Length; i++) 4374
4297 agentGroups.Add(GroupMembership[i].GroupID); 4375 List<UUID> agentGroups = new List<UUID>();
4298 } 4376 GroupMembershipData[] GroupMembership = m_groupsModule.GetMembershipData(agent.AgentID);
4299 else 4377
4300 { 4378 if(GroupMembership == null)
4301 m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!"); 4379 {
4302 } 4380 m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!");
4381 goto Label_GroupsDone;
4303 } 4382 }
4304 4383
4305 bool groupAccess = false; 4384 if(GroupMembership.Length == 0)
4306 UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups; 4385 goto Label_GroupsDone;
4386
4387 for(int i = 0;i < GroupMembership.Length;i++)
4388 agentGroups.Add(GroupMembership[i].GroupID);
4307 4389
4308 if (estateGroups != null) 4390 foreach(UUID group in estateGroups)
4309 { 4391 {
4310 foreach (UUID group in estateGroups) 4392 if(agentGroups.Contains(group))
4311 { 4393 {
4312 if (agentGroups.Contains(group)) 4394 groupAccess = true;
4313 { 4395 break;
4314 groupAccess = true;
4315 break;
4316 }
4317 } 4396 }
4318 } 4397 }
4319 else
4320 {
4321 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!");
4322 }
4323 4398
4324 if (!RegionInfo.EstateSettings.PublicAccess && 4399Label_GroupsDone:
4325 !RegionInfo.EstateSettings.HasAccess(agent.AgentID) && 4400 if (!groupAccess)
4326 !groupAccess)
4327 { 4401 {
4328 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate", 4402 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); 4403 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.", 4404 reason = String.Format("Denied access to private region {0}: You do not have access to that region.",
4331 RegionInfo.RegionName); 4405 RegionInfo.RegionName);
4332 return false; 4406 return false;
4333 } 4407 }
4334 } 4408 }
4335 4409
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; 4410 return true;
4365 } 4411 }
4366 4412
@@ -4449,7 +4495,7 @@ namespace OpenSim.Region.Framework.Scenes
4449// } 4495// }
4450 4496
4451 /// <summary> 4497 /// <summary>
4452 /// We've got an update about an agent that sees into this region, 4498 /// 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. 4499 /// send it to ScenePresence for processing It's the full data.
4454 /// </summary> 4500 /// </summary>
4455 /// <param name="cAgentData">Agent that contains all of the relevant things about an agent. 4501 /// <param name="cAgentData">Agent that contains all of the relevant things about an agent.
@@ -4460,8 +4506,25 @@ namespace OpenSim.Region.Framework.Scenes
4460 m_log.DebugFormat( 4506 m_log.DebugFormat(
4461 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName); 4507 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName);
4462 4508
4509 if (!LoginsEnabled)
4510 {
4511// reason = "Logins Disabled";
4512 m_log.DebugFormat(
4513 "[SCENE]: update for {0} in {1} refused: Logins Disabled", cAgentData.AgentID, RegionInfo.RegionName);
4514 return false;
4515 }
4516 // We have to wait until the viewer contacts this region after receiving EAC.
4517 // That calls AddNewClient, which finally creates the ScenePresence
4518 int flags = GetUserFlags(cAgentData.AgentID);
4519 if (RegionInfo.EstateSettings.IsBanned(cAgentData.AgentID, flags))
4520 {
4521 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
4522 return false;
4523 }
4524
4463 // TODO: This check should probably be in QueryAccess(). 4525 // TODO: This check should probably be in QueryAccess().
4464 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, RegionInfo.RegionSizeX / 2, RegionInfo.RegionSizeY / 2); 4526 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID,
4527 (float)RegionInfo.RegionSizeX * 0.5f, (float)RegionInfo.RegionSizeY * 0.5f);
4465 if (nearestParcel == null) 4528 if (nearestParcel == null)
4466 { 4529 {
4467 m_log.InfoFormat( 4530 m_log.InfoFormat(
@@ -4472,20 +4535,26 @@ namespace OpenSim.Region.Framework.Scenes
4472 } 4535 }
4473 4536
4474 // We have to wait until the viewer contacts this region 4537 // We have to wait until the viewer contacts this region
4475 // after receiving the EnableSimulator HTTP Event Queue message (for the v1 teleport protocol) 4538 // 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 4539 // 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. 4540 // a UseCircuitCode packet which in turn calls AddNewAgent which finally creates the ScenePresence.
4478 ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID); 4541 ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID);
4479 4542
4480 if (sp != null) 4543 if (sp != null)
4481 { 4544 {
4545 if (!sp.IsChildAgent)
4546 {
4547 m_log.WarnFormat("[SCENE]: Ignoring a child update on a root agent {0} {1} in {2}",
4548 sp.Name, sp.UUID, Name);
4549 return false;
4550 }
4482 if (cAgentData.SessionID != sp.ControllingClient.SessionId) 4551 if (cAgentData.SessionID != sp.ControllingClient.SessionId)
4483 { 4552 {
4484 m_log.WarnFormat( 4553 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).", 4554 "[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); 4555 sp.UUID, cAgentData.SessionID);
4487 4556
4488 Console.WriteLine(String.Format("[SCENE]: Attempt to update agent {0} ({1}) with invalid session id {2}", 4557 Console.WriteLine(String.Format("[SCENE]: Attempt to update agent {0} ({1}) with invalid session id {2}",
4489 sp.UUID, sp.ControllingClient.SessionId, cAgentData.SessionID)); 4558 sp.UUID, sp.ControllingClient.SessionId, cAgentData.SessionID));
4490 } 4559 }
4491 4560
@@ -4517,7 +4586,7 @@ namespace OpenSim.Region.Framework.Scenes
4517 } 4586 }
4518 4587
4519 /// <summary> 4588 /// <summary>
4520 /// We've got an update about an agent that sees into this region, 4589 /// 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 4590 /// send it to ScenePresence for processing It's only positional data
4522 /// </summary> 4591 /// </summary>
4523 /// <param name="cAgentData">AgentPosition that contains agent positional data so we can know what to send</param> 4592 /// <param name="cAgentData">AgentPosition that contains agent positional data so we can know what to send</param>
@@ -4525,7 +4594,7 @@ namespace OpenSim.Region.Framework.Scenes
4525 public virtual bool IncomingUpdateChildAgent(AgentPosition cAgentData) 4594 public virtual bool IncomingUpdateChildAgent(AgentPosition cAgentData)
4526 { 4595 {
4527// m_log.DebugFormat( 4596// m_log.DebugFormat(
4528// "[SCENE PRESENCE]: IncomingChildAgentDataUpdate POSITION for {0} in {1}, position {2}", 4597// "[SCENE PRESENCE]: IncomingChildAgentDataUpdate POSITION for {0} in {1}, position {2}",
4529// cAgentData.AgentID, Name, cAgentData.Position); 4598// cAgentData.AgentID, Name, cAgentData.Position);
4530 4599
4531 ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID); 4600 ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID);
@@ -4533,7 +4602,7 @@ namespace OpenSim.Region.Framework.Scenes
4533 { 4602 {
4534// if (childAgentUpdate.ControllingClient.SessionId != cAgentData.SessionID) 4603// if (childAgentUpdate.ControllingClient.SessionId != cAgentData.SessionID)
4535// // Only warn for now 4604// // 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?", 4605// 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); 4606// childAgentUpdate.UUID, cAgentData.SessionID);
4538 4607
4539 // I can't imagine *yet* why we would get an update if the agent is a root agent.. 4608 // I can't imagine *yet* why we would get an update if the agent is a root agent..
@@ -4563,10 +4632,10 @@ namespace OpenSim.Region.Framework.Scenes
4563 /// <param name='agentID'></param> 4632 /// <param name='agentID'></param>
4564 protected virtual ScenePresence WaitGetScenePresence(UUID agentID) 4633 protected virtual ScenePresence WaitGetScenePresence(UUID agentID)
4565 { 4634 {
4566 int ntimes = 20; 4635 int ntimes = 120; // 30s
4567 ScenePresence sp = null; 4636 ScenePresence sp = null;
4568 while ((sp = GetScenePresence(agentID)) == null && (ntimes-- > 0)) 4637 while ((sp = GetScenePresence(agentID)) == null && (ntimes-- > 0))
4569 Thread.Sleep(1000); 4638 Thread.Sleep(250);
4570 4639
4571 if (sp == null) 4640 if (sp == null)
4572 m_log.WarnFormat( 4641 m_log.WarnFormat(
@@ -4593,7 +4662,7 @@ namespace OpenSim.Region.Framework.Scenes
4593 if (acd == null) 4662 if (acd == null)
4594 { 4663 {
4595 m_log.DebugFormat( 4664 m_log.DebugFormat(
4596 "[SCENE]: Request to close agent {0} but no such agent in scene {1}. May have been closed previously.", 4665 "[SCENE]: Request to close agent {0} but no such agent in scene {1}. May have been closed previously.",
4597 agentID, Name); 4666 agentID, Name);
4598 4667
4599 return false; 4668 return false;
@@ -4606,13 +4675,23 @@ namespace OpenSim.Region.Framework.Scenes
4606 else 4675 else
4607 { 4676 {
4608 m_log.WarnFormat( 4677 m_log.WarnFormat(
4609 "[SCENE]: Request to close agent {0} with invalid authorization token {1} in {2}", 4678 "[SCENE]: Request to close agent {0} with invalid authorization token {1} in {2}",
4610 agentID, auth_token, Name); 4679 agentID, auth_token, Name);
4611 } 4680 }
4612 4681
4613 return false; 4682 return false;
4614 } 4683 }
4615 4684
4685// public bool IncomingCloseAgent(UUID agentID)
4686// {
4687// return IncomingCloseAgent(agentID, false);
4688// }
4689
4690// public bool IncomingCloseChildAgent(UUID agentID)
4691// {
4692// return IncomingCloseAgent(agentID, true);
4693// }
4694
4616 /// <summary> 4695 /// <summary>
4617 /// Tell a single client to prepare to close. 4696 /// Tell a single client to prepare to close.
4618 /// </summary> 4697 /// </summary>
@@ -4675,8 +4754,22 @@ namespace OpenSim.Region.Framework.Scenes
4675 4754
4676 if (sp == null) 4755 if (sp == null)
4677 { 4756 {
4757 // If there is no scene presence, we may be handling a dead
4758 // client. These can keep an avatar from reentering a region
4759 // and since they don't get cleaned up they will stick
4760 // around until region restart. So, if there is no SP,
4761 // remove the client as well.
4762 IClientAPI client = null;
4763 if (m_clientManager.TryGetValue(agentID, out client))
4764 {
4765 m_clientManager.Remove(agentID);
4766 if (CapsModule != null)
4767 CapsModule.RemoveCaps(agentID, 0);
4768 m_log.DebugFormat( "[SCENE]: Dead client for agent ID {0} was cleaned up in {1}", agentID, Name);
4769 return true;
4770 }
4678 m_log.DebugFormat( 4771 m_log.DebugFormat(
4679 "[SCENE]: Called CloseClient() with agent ID {0} but no such presence is in {1}", 4772 "[SCENE]: Called CloseClient() with agent ID {0} but no such presence is in {1}",
4680 agentID, Name); 4773 agentID, Name);
4681 4774
4682 return false; 4775 return false;
@@ -4709,7 +4802,11 @@ namespace OpenSim.Region.Framework.Scenes
4709 sp.LifecycleState = ScenePresenceState.Removing; 4802 sp.LifecycleState = ScenePresenceState.Removing;
4710 } 4803 }
4711 4804
4712 sp.ControllingClient.Close(force); 4805 if (sp != null)
4806 {
4807 sp.ControllingClient.Close(force, force);
4808 return true;
4809 }
4713 4810
4714 return true; 4811 return true;
4715 } 4812 }
@@ -4728,16 +4825,34 @@ namespace OpenSim.Region.Framework.Scenes
4728 public void RequestTeleportLocation(IClientAPI remoteClient, string regionName, Vector3 position, 4825 public void RequestTeleportLocation(IClientAPI remoteClient, string regionName, Vector3 position,
4729 Vector3 lookat, uint teleportFlags) 4826 Vector3 lookat, uint teleportFlags)
4730 { 4827 {
4731 GridRegion region = GridService.GetRegionByName(RegionInfo.ScopeID, regionName); 4828 if (EntityTransferModule == null)
4829 {
4830 m_log.DebugFormat("[SCENE]: Unable to perform teleports: no AgentTransferModule is active");
4831 return;
4832 }
4732 4833
4733 if (region == null) 4834 ScenePresence sp = GetScenePresence(remoteClient.AgentId);
4835 if (sp == null || sp.IsDeleted || sp.IsInTransit)
4836 return;
4837
4838 ulong regionHandle = 0;
4839 if(regionName == RegionInfo.RegionName)
4840 regionHandle = RegionInfo.RegionHandle;
4841 else
4842 {
4843 GridRegion region = GridService.GetRegionByName(RegionInfo.ScopeID, regionName);
4844 if (region != null)
4845 regionHandle = region.RegionHandle;
4846 }
4847
4848 if(regionHandle == 0)
4734 { 4849 {
4735 // can't find the region: Tell viewer and abort 4850 // can't find the region: Tell viewer and abort
4736 remoteClient.SendTeleportFailed("The region '" + regionName + "' could not be found."); 4851 remoteClient.SendTeleportFailed("The region '" + regionName + "' could not be found.");
4737 return; 4852 return;
4738 } 4853 }
4739 4854
4740 RequestTeleportLocation(remoteClient, region.RegionHandle, position, lookat, teleportFlags); 4855 EntityTransferModule.Teleport(sp, regionHandle, position, lookat, teleportFlags);
4741 } 4856 }
4742 4857
4743 /// <summary> 4858 /// <summary>
@@ -4751,19 +4866,17 @@ namespace OpenSim.Region.Framework.Scenes
4751 public void RequestTeleportLocation(IClientAPI remoteClient, ulong regionHandle, Vector3 position, 4866 public void RequestTeleportLocation(IClientAPI remoteClient, ulong regionHandle, Vector3 position,
4752 Vector3 lookAt, uint teleportFlags) 4867 Vector3 lookAt, uint teleportFlags)
4753 { 4868 {
4754 ScenePresence sp = GetScenePresence(remoteClient.AgentId); 4869 if (EntityTransferModule == null)
4755 if (sp != null)
4756 { 4870 {
4757 if (EntityTransferModule != null) 4871 m_log.DebugFormat("[SCENE]: Unable to perform teleports: no AgentTransferModule is active");
4758 { 4872 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 } 4873 }
4874
4875 ScenePresence sp = GetScenePresence(remoteClient.AgentId);
4876 if (sp == null || sp.IsDeleted || sp.IsInTransit)
4877 return;
4878
4879 EntityTransferModule.Teleport(sp, regionHandle, position, lookAt, teleportFlags);
4767 } 4880 }
4768 4881
4769 public bool CrossAgentToNewRegion(ScenePresence agent, bool isFlying) 4882 public bool CrossAgentToNewRegion(ScenePresence agent, bool isFlying)
@@ -4871,7 +4984,10 @@ namespace OpenSim.Region.Framework.Scenes
4871 4984
4872 public LandData GetLandData(float x, float y) 4985 public LandData GetLandData(float x, float y)
4873 { 4986 {
4874 return LandChannel.GetLandObject(x, y).LandData; 4987 ILandObject parcel = LandChannel.GetLandObject(x, y);
4988 if (parcel == null)
4989 return null;
4990 return parcel.LandData;
4875 } 4991 }
4876 4992
4877 /// <summary> 4993 /// <summary>
@@ -4886,72 +5002,69 @@ namespace OpenSim.Region.Framework.Scenes
4886 5002
4887 public LandData GetLandData(uint x, uint y) 5003 public LandData GetLandData(uint x, uint y)
4888 { 5004 {
4889 m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y); 5005// m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y);
4890 return LandChannel.GetLandObject((int)x, (int)y).LandData; 5006 ILandObject parcel = LandChannel.GetLandObject((int)x, (int)y);
5007 if (parcel == null)
5008 return null;
5009 return parcel.LandData;
4891 } 5010 }
4892 5011
4893 #endregion 5012 #endregion
4894 5013
4895 #region Script Engine 5014 #region Script Engine
4896 5015 public bool LSLScriptDanger(SceneObjectPart part, Vector3 pos)
4897 private bool ScriptDanger(SceneObjectPart part, Vector3 pos)
4898 { 5016 {
5017
4899 ILandObject parcel = LandChannel.GetLandObject(pos.X, pos.Y); 5018 ILandObject parcel = LandChannel.GetLandObject(pos.X, pos.Y);
4900 if (part != null) 5019 if (parcel == null)
4901 { 5020 return true;
4902 if (parcel != null) 5021
4903 { 5022 LandData ldata = parcel.LandData;
4904 if ((parcel.LandData.Flags & (uint)ParcelFlags.AllowOtherScripts) != 0) 5023 if (ldata == null)
4905 { 5024 return true;
4906 return true; 5025
4907 } 5026 uint landflags = ldata.Flags;
4908 else if ((part.OwnerID == parcel.LandData.OwnerID) || Permissions.IsGod(part.OwnerID)) 5027
4909 { 5028 uint mask = (uint)(ParcelFlags.CreateObjects | ParcelFlags.AllowAPrimitiveEntry);
4910 return true; 5029 if((landflags & mask) != mask)
4911 } 5030 return true;
4912 else if (((parcel.LandData.Flags & (uint)ParcelFlags.AllowGroupScripts) != 0) 5031
4913 && (parcel.LandData.GroupID != UUID.Zero) && (parcel.LandData.GroupID == part.GroupID)) 5032 if((landflags & (uint)ParcelFlags.AllowOtherScripts) != 0)
4914 { 5033 return false;
4915 return true;
4916 }
4917 else
4918 {
4919 return false;
4920 }
4921 }
4922 else
4923 {
4924 5034
4925 if (pos.X > 0f && pos.X < RegionInfo.RegionSizeX && pos.Y > 0f && pos.Y < RegionInfo.RegionSizeY) 5035 if(part == null)
4926 { 5036 return true;
4927 // The only time parcel != null when an object is inside a region is when 5037 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; 5038 return false;
4941 } 5039
5040 return true;
4942 } 5041 }
4943 5042
4944 public bool ScriptDanger(uint localID, Vector3 pos) 5043 private bool ScriptDanger(SceneObjectPart part, Vector3 pos)
4945 { 5044 {
4946 SceneObjectPart part = GetSceneObjectPart(localID); 5045 if (part == null)
4947 if (part != null) 5046 return false;
5047
5048 ILandObject parcel = LandChannel.GetLandObject(pos.X, pos.Y);
5049 if (parcel != null)
4948 { 5050 {
4949 return ScriptDanger(part, pos); 5051 if ((parcel.LandData.Flags & (uint)ParcelFlags.AllowOtherScripts) != 0)
5052 return true;
5053
5054 if ((part.OwnerID == parcel.LandData.OwnerID) || Permissions.IsGod(part.OwnerID))
5055 return true;
5056
5057 if (((parcel.LandData.Flags & (uint)ParcelFlags.AllowGroupScripts) != 0)
5058 && (parcel.LandData.GroupID != UUID.Zero) && (parcel.LandData.GroupID == part.GroupID))
5059 return true;
4950 } 5060 }
4951 else 5061 else
4952 { 5062 {
4953 return false; 5063 if (pos.X > 0f && pos.X < RegionInfo.RegionSizeX && pos.Y > 0f && pos.Y < RegionInfo.RegionSizeY)
5064 return true;
4954 } 5065 }
5066
5067 return false;
4955 } 5068 }
4956 5069
4957 public bool PipeEventsForScript(uint localID) 5070 public bool PipeEventsForScript(uint localID)
@@ -5177,7 +5290,7 @@ namespace OpenSim.Region.Framework.Scenes
5177 /// Get a scene object group that contains the prim with the given local id 5290 /// Get a scene object group that contains the prim with the given local id
5178 /// </summary> 5291 /// </summary>
5179 /// <param name="localID"></param> 5292 /// <param name="localID"></param>
5180 /// <returns>null if no scene object group containing that prim is found</returns> 5293 /// <returns>null if no scene object group containing that prim is found</returns>
5181 public SceneObjectGroup GetGroupByPrim(uint localID) 5294 public SceneObjectGroup GetGroupByPrim(uint localID)
5182 { 5295 {
5183 return m_sceneGraph.GetGroupByPrim(localID); 5296 return m_sceneGraph.GetGroupByPrim(localID);
@@ -5187,7 +5300,7 @@ namespace OpenSim.Region.Framework.Scenes
5187 /// Get a scene object group that contains the prim with the given uuid 5300 /// Get a scene object group that contains the prim with the given uuid
5188 /// </summary> 5301 /// </summary>
5189 /// <param name="fullID"></param> 5302 /// <param name="fullID"></param>
5190 /// <returns>null if no scene object group containing that prim is found</returns> 5303 /// <returns>null if no scene object group containing that prim is found</returns>
5191 public SceneObjectGroup GetGroupByPrim(UUID fullID) 5304 public SceneObjectGroup GetGroupByPrim(UUID fullID)
5192 { 5305 {
5193 return m_sceneGraph.GetGroupByPrim(fullID); 5306 return m_sceneGraph.GetGroupByPrim(fullID);
@@ -5221,7 +5334,12 @@ namespace OpenSim.Region.Framework.Scenes
5221 /// <param name="action"></param> 5334 /// <param name="action"></param>
5222 public void ForEachClient(Action<IClientAPI> action) 5335 public void ForEachClient(Action<IClientAPI> action)
5223 { 5336 {
5224 m_clientManager.ForEachSync(action); 5337 m_clientManager.ForEach(action);
5338 }
5339
5340 public int GetNumberOfClients()
5341 {
5342 return m_clientManager.Count;
5225 } 5343 }
5226 5344
5227 public bool TryGetClient(UUID avatarID, out IClientAPI client) 5345 public bool TryGetClient(UUID avatarID, out IClientAPI client)
@@ -5264,6 +5382,7 @@ namespace OpenSim.Region.Framework.Scenes
5264 5382
5265 public void CleanTempObjects() 5383 public void CleanTempObjects()
5266 { 5384 {
5385 DateTime now = DateTime.UtcNow;
5267 EntityBase[] entities = GetEntities(); 5386 EntityBase[] entities = GetEntities();
5268 foreach (EntityBase obj in entities) 5387 foreach (EntityBase obj in entities)
5269 { 5388 {
@@ -5275,13 +5394,12 @@ namespace OpenSim.Region.Framework.Scenes
5275 { 5394 {
5276 if ((grp.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 5395 if ((grp.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
5277 { 5396 {
5278 if (grp.RootPart.Expires <= DateTime.Now) 5397 if (grp.GetSittingAvatarsCount() == 0 && grp.RootPart.Expires <= now)
5279 DeleteSceneObject(grp, false); 5398 DeleteSceneObject(grp, false);
5280 } 5399 }
5281 } 5400 }
5282 } 5401 }
5283 } 5402 }
5284
5285 } 5403 }
5286 5404
5287 public void DeleteFromStorage(UUID uuid) 5405 public void DeleteFromStorage(UUID uuid)
@@ -5289,7 +5407,7 @@ namespace OpenSim.Region.Framework.Scenes
5289 SimulationDataService.RemoveObject(uuid, RegionInfo.RegionID); 5407 SimulationDataService.RemoveObject(uuid, RegionInfo.RegionID);
5290 } 5408 }
5291 5409
5292 public int GetHealth() 5410 public int GetHealth(out int flags, out string message)
5293 { 5411 {
5294 // Returns: 5412 // Returns:
5295 // 1 = sim is up and accepting http requests. The heartbeat has 5413 // 1 = sim is up and accepting http requests. The heartbeat has
@@ -5297,27 +5415,74 @@ namespace OpenSim.Region.Framework.Scenes
5297 // admin restart may succeed 5415 // admin restart may succeed
5298 // 5416 //
5299 // 2 = Sim is up and the heartbeat is running. The sim is likely 5417 // 2 = Sim is up and the heartbeat is running. The sim is likely
5300 // usable for people within and logins _may_ work 5418 // usable for people within
5419 //
5420 // 3 = Sim is up and one packet thread is running. Sim is
5421 // unstable and will not accept new logins
5301 // 5422 //
5302 // 3 = We have seen a new user enter within the past 4 minutes 5423 // 4 = Sim is up and both packet threads are running. Sim is
5424 // likely usable
5425 //
5426 // 5 = We have seen a new user enter within the past 4 minutes
5303 // which can be seen as positive confirmation of sim health 5427 // which can be seen as positive confirmation of sim health
5304 // 5428 //
5305 int health = 1; // Start at 1, means we're up 5429 int health = 1; // Start at 1, means we're up
5306 5430
5307 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 1000) 5431 flags = 0;
5308 health += 1; 5432 message = String.Empty;
5433
5434 CheckHeartbeat();
5435
5436 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
5437 {
5438 // We're still starting
5439 // 0 means "in startup", it can't happen another way, since
5440 // to get here, we must be able to accept http connections
5441 return 0;
5442 }
5443
5444 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 2000)
5445 {
5446 health+=1;
5447 flags |= 1;
5448 }
5449
5450 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 2000)
5451 {
5452 health+=1;
5453 flags |= 2;
5454 }
5455
5456 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 2000)
5457 {
5458 health+=1;
5459 flags |= 4;
5460 }
5461 /*
5309 else 5462 else
5463 {
5464int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
5465System.Diagnostics.Process proc = new System.Diagnostics.Process();
5466proc.EnableRaisingEvents=false;
5467proc.StartInfo.FileName = "/bin/kill";
5468proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
5469proc.Start();
5470proc.WaitForExit();
5471Thread.Sleep(1000);
5472Environment.Exit(1);
5473 }
5474 */
5475
5476 if (flags != 7)
5310 return health; 5477 return health;
5311 5478
5312 // A login in the last 4 mins? We can't be doing too badly 5479 // A login in the last 4 mins? We can't be doing too badly
5313 // 5480 //
5314 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 5481 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
5315 health++; 5482 health++;
5316 else 5483 else
5317 return health; 5484 return health;
5318 5485
5319// CheckHeartbeat();
5320
5321 return health; 5486 return health;
5322 } 5487 }
5323 5488
@@ -5405,7 +5570,7 @@ namespace OpenSim.Region.Framework.Scenes
5405 bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0); 5570 bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0);
5406 if (wasUsingPhysics) 5571 if (wasUsingPhysics)
5407 { 5572 {
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 5573 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 } 5574 }
5410 } 5575 }
5411 5576
@@ -5508,14 +5673,14 @@ namespace OpenSim.Region.Framework.Scenes
5508 return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z; 5673 return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z;
5509 } 5674 }
5510 5675
5511// private void CheckHeartbeat() 5676 private void CheckHeartbeat()
5512// { 5677 {
5513// if (m_firstHeartbeat) 5678 if (m_firstHeartbeat)
5514// return; 5679 return;
5515// 5680
5516// if (Util.EnvironmentTickCountSubtract(m_lastFrameTick) > 2000) 5681 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) > 5000)
5517// StartTimer(); 5682 Start();
5518// } 5683 }
5519 5684
5520 public override ISceneObject DeserializeObject(string representation) 5685 public override ISceneObject DeserializeObject(string representation)
5521 { 5686 {
@@ -5534,27 +5699,26 @@ namespace OpenSim.Region.Framework.Scenes
5534 5699
5535 public Vector3 GetNearestAllowedPosition(ScenePresence avatar, ILandObject excludeParcel) 5700 public Vector3 GetNearestAllowedPosition(ScenePresence avatar, ILandObject excludeParcel)
5536 { 5701 {
5537 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, excludeParcel); 5702 Vector3 pos = avatar.AbsolutePosition;
5703
5704 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, pos.X, pos.Y, excludeParcel);
5538 5705
5539 if (nearestParcel != null) 5706 if (nearestParcel != null)
5540 { 5707 {
5541 Vector3 dir = Vector3.Normalize(Vector3.Multiply(avatar.Velocity, -1)); 5708 Vector2? nearestPoint = null;
5542 //Try to get a location that feels like where they came from 5709 Vector3 dir = -avatar.Velocity;
5543 Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); 5710 float dirlen = dir.Length();
5544 if (nearestPoint != null) 5711 if(dirlen > 1.0f)
5545 { 5712 //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()); 5713 nearestPoint = nearestParcel.GetNearestPointAlongDirection(pos, dir);
5547 return nearestPoint.Value; 5714
5548 } 5715 if (nearestPoint == null)
5716 nearestPoint = nearestParcel.GetNearestPoint(pos);
5549 5717
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) 5718 if (nearestPoint != null)
5555 { 5719 {
5556 m_log.Debug("They had a zero velocity, sending them to: " + nearestPoint.ToString()); 5720 return GetPositionAtAvatarHeightOrGroundHeight(avatar,
5557 return nearestPoint.Value; 5721 nearestPoint.Value.X, nearestPoint.Value.Y);
5558 } 5722 }
5559 5723
5560 ILandObject dest = LandChannel.GetLandObject(avatar.lastKnownAllowedPosition.X, avatar.lastKnownAllowedPosition.Y); 5724 ILandObject dest = LandChannel.GetLandObject(avatar.lastKnownAllowedPosition.X, avatar.lastKnownAllowedPosition.Y);
@@ -5572,32 +5736,16 @@ namespace OpenSim.Region.Framework.Scenes
5572 //Go to the edge, this happens in teleporting to a region with no available parcels 5736 //Go to the edge, this happens in teleporting to a region with no available parcels
5573 Vector3 nearestRegionEdgePoint = GetNearestRegionEdgePosition(avatar); 5737 Vector3 nearestRegionEdgePoint = GetNearestRegionEdgePosition(avatar);
5574 5738
5575 //m_log.Debug("They are really in a place they don't belong, sending them to: " + nearestRegionEdgePoint.ToString()); 5739 //Debug.WriteLine("They are really in a place they don't belong, sending them to: " + nearestRegionEdgePoint.ToString());
5576
5577 return nearestRegionEdgePoint; 5740 return nearestRegionEdgePoint;
5578 } 5741 }
5579 5742
5580 private Vector3 GetParcelCenterAtGround(ILandObject parcel) 5743 private Vector3 GetParcelCenterAtGround(ILandObject parcel)
5581 { 5744 {
5582 Vector2 center = GetParcelCenter(parcel); 5745 Vector2 center = parcel.CenterPoint;
5583 return GetPositionAtGround(center.X, center.Y); 5746 return GetPositionAtGround(center.X, center.Y);
5584 } 5747 }
5585 5748
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) 5749 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y)
5602 { 5750 {
5603 return GetNearestAllowedParcel(avatarId, x, y, null); 5751 return GetNearestAllowedParcel(avatarId, x, y, null);
@@ -5605,18 +5753,30 @@ namespace OpenSim.Region.Framework.Scenes
5605 5753
5606 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y, ILandObject excludeParcel) 5754 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y, ILandObject excludeParcel)
5607 { 5755 {
5608 List<ILandObject> all = AllParcels(); 5756 if(LandChannel == null)
5609 float minParcelDistance = float.MaxValue; 5757 return null;
5758
5759 List<ILandObject> all = LandChannel.AllParcels();
5760
5761 if(all == null || all.Count == 0)
5762 return null;
5763
5764 float minParcelDistanceSQ = float.MaxValue;
5610 ILandObject nearestParcel = null; 5765 ILandObject nearestParcel = null;
5766 Vector2 curCenter;
5767 float parcelDistanceSQ;
5611 5768
5612 foreach (var parcel in all) 5769 foreach (var parcel in all)
5613 { 5770 {
5614 if (!parcel.IsEitherBannedOrRestricted(avatarId) && parcel != excludeParcel) 5771 if (parcel != excludeParcel && !parcel.IsEitherBannedOrRestricted(avatarId))
5615 { 5772 {
5616 float parcelDistance = GetParcelDistancefromPoint(parcel, x, y); 5773 curCenter = parcel.CenterPoint;
5617 if (parcelDistance < minParcelDistance) 5774 curCenter.X -= x;
5775 curCenter.Y -= y;
5776 parcelDistanceSQ = curCenter.LengthSquared();
5777 if (parcelDistanceSQ < minParcelDistanceSQ)
5618 { 5778 {
5619 minParcelDistance = parcelDistance; 5779 minParcelDistanceSQ = parcelDistanceSQ;
5620 nearestParcel = parcel; 5780 nearestParcel = parcel;
5621 } 5781 }
5622 } 5782 }
@@ -5625,82 +5785,52 @@ namespace OpenSim.Region.Framework.Scenes
5625 return nearestParcel; 5785 return nearestParcel;
5626 } 5786 }
5627 5787
5628 private List<ILandObject> AllParcels() 5788 private Vector2 GetParcelSafeCorner(ILandObject parcel)
5629 {
5630 return LandChannel.AllParcels();
5631 }
5632
5633 private float GetParcelDistancefromPoint(ILandObject parcel, float x, float y)
5634 {
5635 return Vector2.Distance(new Vector2(x, y), GetParcelCenter(parcel));
5636 }
5637
5638 //calculate the average center point of a parcel
5639 private Vector2 GetParcelCenter(ILandObject parcel)
5640 { 5789 {
5641 int count = 0; 5790 Vector2 place = parcel.StartPoint;
5642 int avgx = 0; 5791 place.X += 2f;
5643 int avgy = 0; 5792 place.Y += 2f;
5644 for (int x = 0; x < RegionInfo.RegionSizeX; x++) 5793 return place;
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 } 5794 }
5667 5795
5668 private Vector3 GetNearestRegionEdgePosition(ScenePresence avatar) 5796 private Vector3 GetNearestRegionEdgePosition(ScenePresence avatar)
5669 { 5797 {
5670 float xdistance = avatar.AbsolutePosition.X < RegionInfo.RegionSizeX / 2 5798 float posX = avatar.AbsolutePosition.X;
5671 ? avatar.AbsolutePosition.X : RegionInfo.RegionSizeX - avatar.AbsolutePosition.X; 5799 float posY = avatar.AbsolutePosition.Y;
5672 float ydistance = avatar.AbsolutePosition.Y < RegionInfo.RegionSizeY / 2 5800 float regionSizeX = RegionInfo.RegionSizeX;
5673 ? avatar.AbsolutePosition.Y : RegionInfo.RegionSizeY - avatar.AbsolutePosition.Y; 5801 float halfRegionSizeX = regionSizeX * 0.5f;
5802 float regionSizeY = RegionInfo.RegionSizeY;
5803 float halfRegionSizeY = regionSizeY * 0.5f;
5804
5805 float xdistance = posX < halfRegionSizeX ? posX : regionSizeX - posX;
5806 float ydistance = posY < halfRegionSizeY ? posY : regionSizeY - posY;
5674 5807
5675 //find out what vertical edge to go to 5808 //find out what vertical edge to go to
5676 if (xdistance < ydistance) 5809 if (xdistance < ydistance)
5677 { 5810 {
5678 if (avatar.AbsolutePosition.X < RegionInfo.RegionSizeX / 2) 5811 if (posX < halfRegionSizeX)
5679 { 5812 return GetPositionAtAvatarHeightOrGroundHeight(avatar, 0.5f, posY);
5680 return GetPositionAtAvatarHeightOrGroundHeight(avatar, 0.0f, avatar.AbsolutePosition.Y);
5681 }
5682 else 5813 else
5683 { 5814 return GetPositionAtAvatarHeightOrGroundHeight(avatar, regionSizeX - 0.5f, posY);
5684 return GetPositionAtAvatarHeightOrGroundHeight(avatar, RegionInfo.RegionSizeY, avatar.AbsolutePosition.Y);
5685 }
5686 } 5815 }
5687 //find out what horizontal edge to go to 5816 //find out what horizontal edge to go to
5688 else 5817 else
5689 { 5818 {
5690 if (avatar.AbsolutePosition.Y < RegionInfo.RegionSizeY / 2) 5819 if (posY < halfRegionSizeY)
5691 { 5820 return GetPositionAtAvatarHeightOrGroundHeight(avatar, posX, 0.5f);
5692 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, 0.0f);
5693 }
5694 else 5821 else
5695 { 5822 return GetPositionAtAvatarHeightOrGroundHeight(avatar, posX, regionSizeY - 0.5f);
5696 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, RegionInfo.RegionSizeY);
5697 }
5698 } 5823 }
5699 } 5824 }
5700 5825
5701 private Vector3 GetPositionAtAvatarHeightOrGroundHeight(ScenePresence avatar, float x, float y) 5826 private Vector3 GetPositionAtAvatarHeightOrGroundHeight(ScenePresence avatar, float x, float y)
5702 { 5827 {
5703 Vector3 ground = GetPositionAtGround(x, y); 5828 Vector3 ground = GetPositionAtGround(x, y);
5829 if(avatar.Appearance != null)
5830 ground.Z += avatar.Appearance.AvatarHeight * 0.5f;
5831 else
5832 ground.Z += 0.8f;
5833
5704 if (avatar.AbsolutePosition.Z > ground.Z) 5834 if (avatar.AbsolutePosition.Z > ground.Z)
5705 { 5835 {
5706 ground.Z = avatar.AbsolutePosition.Z; 5836 ground.Z = avatar.AbsolutePosition.Z;
@@ -5780,7 +5910,7 @@ namespace OpenSim.Region.Framework.Scenes
5780 g.GetAxisAlignedBoundingBoxRaw(out ominX, out omaxX, out ominY, out omaxY, out ominZ, out omaxZ); 5910 g.GetAxisAlignedBoundingBoxRaw(out ominX, out omaxX, out ominY, out omaxY, out ominZ, out omaxZ);
5781 5911
5782// m_log.DebugFormat( 5912// m_log.DebugFormat(
5783// "[SCENE]: For {0} found AxisAlignedBoundingBoxRaw {1}, {2}", 5913// "[SCENE]: For {0} found AxisAlignedBoundingBoxRaw {1}, {2}",
5784// g.Name, new Vector3(ominX, ominY, ominZ), new Vector3(omaxX, omaxY, omaxZ)); 5914// g.Name, new Vector3(ominX, ominY, ominZ), new Vector3(omaxX, omaxY, omaxZ));
5785 5915
5786 ominX += vec.X; 5916 ominX += vec.X;
@@ -5829,7 +5959,55 @@ namespace OpenSim.Region.Framework.Scenes
5829 mapModule.GenerateMaptile(); 5959 mapModule.GenerateMaptile();
5830 } 5960 }
5831 5961
5832 private void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e) 5962// public void CleanDroppedAttachments()
5963// {
5964// List<SceneObjectGroup> objectsToDelete =
5965// new List<SceneObjectGroup>();
5966//
5967// lock (m_cleaningAttachments)
5968// {
5969// ForEachSOG(delegate (SceneObjectGroup grp)
5970// {
5971// if (grp.RootPart.Shape.PCode == 0 && grp.RootPart.Shape.State != 0 && (!objectsToDelete.Contains(grp)))
5972// {
5973// UUID agentID = grp.OwnerID;
5974// if (agentID == UUID.Zero)
5975// {
5976// objectsToDelete.Add(grp);
5977// return;
5978// }
5979//
5980// ScenePresence sp = GetScenePresence(agentID);
5981// if (sp == null)
5982// {
5983// objectsToDelete.Add(grp);
5984// return;
5985// }
5986// }
5987// });
5988// }
5989//
5990// foreach (SceneObjectGroup grp in objectsToDelete)
5991// {
5992// m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
5993// DeleteSceneObject(grp, true);
5994// }
5995// }
5996
5997 public void ThreadAlive(int threadCode)
5998 {
5999 switch(threadCode)
6000 {
6001 case 1: // Incoming
6002 m_lastIncoming = Util.EnvironmentTickCount();
6003 break;
6004 case 2: // Incoming
6005 m_lastOutgoing = Util.EnvironmentTickCount();
6006 break;
6007 }
6008 }
6009
6010 public void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e)
5833 { 6011 {
5834 RegenerateMaptile(); 6012 RegenerateMaptile();
5835 6013
@@ -5861,13 +6039,16 @@ namespace OpenSim.Region.Framework.Scenes
5861 reason = string.Empty; 6039 reason = string.Empty;
5862 6040
5863 if (Permissions.IsGod(agentID)) 6041 if (Permissions.IsGod(agentID))
5864 {
5865 reason = String.Empty;
5866 return true; 6042 return true;
5867 }
5868 6043
5869 if (!AllowAvatarCrossing && !viaTeleport) 6044 if (!AllowAvatarCrossing && !viaTeleport)
6045 {
6046 reason = "Region Crossing not allowed";
5870 return false; 6047 return false;
6048 }
6049
6050 bool isAdmin = Permissions.IsAdministrator(agentID);
6051 bool isManager = Permissions.IsEstateManager(agentID);
5871 6052
5872 // FIXME: Root agent count is currently known to be inaccurate. This forces a recount before we check. 6053 // 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. 6054 // However, the long term fix is to make sure root agent count is always accurate.
@@ -5877,7 +6058,7 @@ namespace OpenSim.Region.Framework.Scenes
5877 6058
5878 if (num >= RegionInfo.RegionSettings.AgentLimit) 6059 if (num >= RegionInfo.RegionSettings.AgentLimit)
5879 { 6060 {
5880 if (!Permissions.IsAdministrator(agentID)) 6061 if (!(isAdmin || isManager))
5881 { 6062 {
5882 reason = "The region is full"; 6063 reason = "The region is full";
5883 6064
@@ -5915,6 +6096,7 @@ namespace OpenSim.Region.Framework.Scenes
5915 if (!AuthorizeUser(aCircuit, false, out reason)) 6096 if (!AuthorizeUser(aCircuit, false, out reason))
5916 { 6097 {
5917 //m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID); 6098 //m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
6099// reason = "Region authorization fail";
5918 return false; 6100 return false;
5919 } 6101 }
5920 } 6102 }
@@ -5925,52 +6107,101 @@ namespace OpenSim.Region.Framework.Scenes
5925 return false; 6107 return false;
5926 } 6108 }
5927 6109
5928 if (viaTeleport) 6110 // last check aditional land access restrictions and relocations
6111 // if crossing (viaTeleport false) check only the specified parcel
6112 return CheckLandPositionAccess(agentID, viaTeleport, true, position, out reason);
6113 }
6114
6115 // check access to land.
6116 public bool CheckLandPositionAccess(UUID agentID, bool NotCrossing, bool checkTeleHub, Vector3 position, out string reason)
6117 {
6118 reason = string.Empty;
6119
6120 if (Permissions.IsGod(agentID))
6121 return true;
6122
6123 // Permissions.IsAdministrator is the same as IsGod for now
6124// bool isAdmin = Permissions.IsAdministrator(agentID);
6125// if(isAdmin)
6126// return true;
6127
6128 // also honor estate managers access rights
6129 bool isManager = Permissions.IsEstateManager(agentID);
6130 if(isManager)
6131 return true;
6132
6133 if (NotCrossing)
5929 { 6134 {
5930 if (!RegionInfo.EstateSettings.AllowDirectTeleport) 6135 if (!RegionInfo.EstateSettings.AllowDirectTeleport)
5931 { 6136 {
5932 SceneObjectGroup telehub; 6137 SceneObjectGroup telehub;
5933 if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject)) != null) 6138 if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = GetSceneObjectGroup (RegionInfo.RegionSettings.TelehubObject)) != null && checkTeleHub)
5934 { 6139 {
5935 List<SpawnPoint> spawnPoints = RegionInfo.RegionSettings.SpawnPoints();
5936 bool banned = true; 6140 bool banned = true;
5937 foreach (SpawnPoint sp in spawnPoints) 6141 bool validTelehub = false;
6142 List<SpawnPoint> spawnPoints = RegionInfo.RegionSettings.SpawnPoints();
6143 Vector3 spawnPoint;
6144 ILandObject land = null;
6145 Vector3 telehubPosition = telehub.AbsolutePosition;
6146
6147 if(spawnPoints.Count == 0)
5938 { 6148 {
5939 Vector3 spawnPoint = sp.GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); 6149 // will this ever happen?
5940 ILandObject land = LandChannel.GetLandObject(spawnPoint.X, spawnPoint.Y); 6150 // if so use the telehub object position
5941 if (land == null) 6151 spawnPoint = telehubPosition;
5942 continue; 6152 land = LandChannel.GetLandObject(spawnPoint.X, spawnPoint.Y);
5943 if (land.IsEitherBannedOrRestricted(agentID)) 6153 if(land != null && !land.IsEitherBannedOrRestricted(agentID))
5944 continue; 6154 {
5945 banned = false; 6155 banned = false;
5946 break; 6156 validTelehub = true;
6157 }
6158 }
6159 else
6160 {
6161 Quaternion telehubRotation = telehub.GroupRotation;
6162 foreach (SpawnPoint spawn in spawnPoints)
6163 {
6164 spawnPoint = spawn.GetLocation(telehubPosition, telehubRotation);
6165 land = LandChannel.GetLandObject(spawnPoint.X, spawnPoint.Y);
6166 if (land == null)
6167 continue;
6168 validTelehub = true;
6169 if (!land.IsEitherBannedOrRestricted(agentID))
6170 {
6171 banned = false;
6172 break;
6173 }
6174 }
5947 } 6175 }
5948 6176
5949 if (banned) 6177 if(validTelehub)
5950 { 6178 {
5951 if (Permissions.IsAdministrator(agentID) == false || Permissions.IsGridGod(agentID) == false) 6179 if (banned)
5952 { 6180 {
5953 reason = "No suitable landing point found"; 6181 reason = "No suitable landing point found";
5954 return false; 6182 return false;
5955 } 6183 }
5956 reason = "Administrative access only"; 6184 else
5957 return true; 6185 return true;
5958 } 6186 }
6187 // possible broken telehub, fall into normal check
5959 } 6188 }
5960 } 6189 }
5961 6190
5962 float posX = 128.0f; 6191 float posX = position.X;
5963 float posY = 128.0f; 6192 float posY = position.Y;
5964 6193
6194 // allow position relocation
5965 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY)) 6195 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY))
5966 { 6196 {
5967 // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID); 6197 // 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"; 6198 reason = "You dont have access to the region parcels";
5969 return false; 6199 return false;
5970 } 6200 }
5971 } 6201 }
5972 else // Walking 6202 else // check for query region crossing only
5973 { 6203 {
6204 // no relocation allowed on crossings
5974 ILandObject land = LandChannel.GetLandObject(position.X, position.Y); 6205 ILandObject land = LandChannel.GetLandObject(position.X, position.Y);
5975 if (land == null) 6206 if (land == null)
5976 { 6207 {
@@ -5991,11 +6222,48 @@ namespace OpenSim.Region.Framework.Scenes
5991 } 6222 }
5992 } 6223 }
5993 6224
5994 reason = String.Empty;
5995 return true; 6225 return true;
5996 } 6226 }
5997 6227
5998 /// <summary> 6228 public void StartTimerWatchdog()
6229 {
6230 m_timerWatchdog.Interval = 1000;
6231 m_timerWatchdog.Elapsed += TimerWatchdog;
6232 m_timerWatchdog.AutoReset = true;
6233 m_timerWatchdog.Start();
6234 }
6235
6236 public void TimerWatchdog(object sender, ElapsedEventArgs e)
6237 {
6238 CheckHeartbeat();
6239
6240 IEtcdModule etcd = RequestModuleInterface<IEtcdModule>();
6241 int flags;
6242 string message;
6243 if (etcd != null)
6244 {
6245 int health = GetHealth(out flags, out message);
6246 if (health != m_lastHealth)
6247 {
6248 m_lastHealth = health;
6249
6250 etcd.Store("Health", health.ToString(), 300000);
6251 etcd.Store("HealthFlags", flags.ToString(), 300000);
6252 }
6253
6254 int roots = 0;
6255 foreach (ScenePresence sp in GetScenePresences())
6256 if (!sp.IsChildAgent && !sp.IsNPC)
6257 roots++;
6258
6259 if (m_lastUsers != roots)
6260 {
6261 m_lastUsers = roots;
6262 etcd.Store("RootAgents", roots.ToString(), 300000);
6263 }
6264 }
6265 }
6266
5999 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the 6267 /// 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!. 6268 /// autopilot that moves an avatar to a sit target!.
6001 /// </summary> 6269 /// </summary>
@@ -6003,6 +6271,7 @@ namespace OpenSim.Region.Framework.Scenes
6003 /// This is not intended as a permament location for this method. 6271 /// This is not intended as a permament location for this method.
6004 /// </remarks> 6272 /// </remarks>
6005 /// <param name="presence"></param> 6273 /// <param name="presence"></param>
6274/* move to target is now done on presence update
6006 private void HandleOnSignificantClientMovement(ScenePresence presence) 6275 private void HandleOnSignificantClientMovement(ScenePresence presence)
6007 { 6276 {
6008 if (presence.MovingToTarget) 6277 if (presence.MovingToTarget)
@@ -6059,7 +6328,7 @@ namespace OpenSim.Region.Framework.Scenes
6059 } 6328 }
6060 } 6329 }
6061 } 6330 }
6062 6331*/
6063 // manage and select spawn points in sequence 6332 // manage and select spawn points in sequence
6064 public int SpawnPoint() 6333 public int SpawnPoint()
6065 { 6334 {
@@ -6074,8 +6343,13 @@ namespace OpenSim.Region.Framework.Scenes
6074 return m_SpawnPoint - 1; 6343 return m_SpawnPoint - 1;
6075 } 6344 }
6076 6345
6346 private void HandleGcCollect(string module, string[] args)
6347 {
6348 GC.Collect();
6349 }
6350
6077 /// <summary> 6351 /// <summary>
6078 /// Wrappers to get physics modules retrieve assets. 6352 /// Wrappers to get physics modules retrieve assets.
6079 /// </summary> 6353 /// </summary>
6080 /// <remarks> 6354 /// <remarks>
6081 /// Has to be done this way 6355 /// Has to be done this way
@@ -6144,5 +6418,21 @@ namespace OpenSim.Region.Framework.Scenes
6144 6418
6145 m_eventManager.TriggerExtraSettingChanged(this, name, String.Empty); 6419 m_eventManager.TriggerExtraSettingChanged(this, name, String.Empty);
6146 } 6420 }
6421
6422 public bool InTeleportTargetsCoolDown(UUID sourceID, UUID targetID, double timeout)
6423 {
6424 lock(TeleportTargetsCoolDown)
6425 {
6426 UUID lastSource = UUID.Zero;
6427 TeleportTargetsCoolDown.TryGetValue(targetID, out lastSource);
6428 if(lastSource == UUID.Zero)
6429 {
6430 TeleportTargetsCoolDown.Add(targetID, sourceID, timeout);
6431 return false;
6432 }
6433 TeleportTargetsCoolDown.AddOrUpdate(targetID, sourceID, timeout);
6434 return lastSource == sourceID;
6435 }
6436 }
6147 } 6437 }
6148} 6438}