diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/Scene.cs')
-rwxr-xr-x[-rw-r--r--] | OpenSim/Region/Framework/Scenes/Scene.cs | 2560 |
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 && | 4399 | Label_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 | { | ||
5464 | int pid = System.Diagnostics.Process.GetCurrentProcess().Id; | ||
5465 | System.Diagnostics.Process proc = new System.Diagnostics.Process(); | ||
5466 | proc.EnableRaisingEvents=false; | ||
5467 | proc.StartInfo.FileName = "/bin/kill"; | ||
5468 | proc.StartInfo.Arguments = "-QUIT " + pid.ToString(); | ||
5469 | proc.Start(); | ||
5470 | proc.WaitForExit(); | ||
5471 | Thread.Sleep(1000); | ||
5472 | Environment.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 | } |