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