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