diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/Scene.cs | 333 |
1 files changed, 171 insertions, 162 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index f38a6fc..d4bfd46 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -131,7 +131,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
131 | protected ICapabilitiesModule m_capsModule; | 131 | protected ICapabilitiesModule m_capsModule; |
132 | // Central Update Loop | 132 | // Central Update Loop |
133 | protected int m_fps = 10; | 133 | protected int m_fps = 10; |
134 | protected uint m_frame; | 134 | |
135 | /// <summary> | ||
136 | /// Current scene frame number | ||
137 | /// </summary> | ||
138 | public uint Frame | ||
139 | { | ||
140 | get; | ||
141 | protected set; | ||
142 | } | ||
143 | |||
135 | protected float m_timespan = 0.089f; | 144 | protected float m_timespan = 0.089f; |
136 | protected DateTime m_lastupdate = DateTime.UtcNow; | 145 | protected DateTime m_lastupdate = DateTime.UtcNow; |
137 | 146 | ||
@@ -1212,6 +1221,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
1212 | try | 1221 | try |
1213 | { | 1222 | { |
1214 | Update(); | 1223 | Update(); |
1224 | |||
1225 | m_lastUpdate = Util.EnvironmentTickCount(); | ||
1226 | m_firstHeartbeat = false; | ||
1215 | } | 1227 | } |
1216 | catch (ThreadAbortException) | 1228 | catch (ThreadAbortException) |
1217 | { | 1229 | { |
@@ -1225,190 +1237,180 @@ namespace OpenSim.Region.Framework.Scenes | |||
1225 | Watchdog.RemoveThread(); | 1237 | Watchdog.RemoveThread(); |
1226 | } | 1238 | } |
1227 | 1239 | ||
1228 | /// <summary> | ||
1229 | /// Performs per-frame updates on the scene, this should be the central scene loop | ||
1230 | /// </summary> | ||
1231 | public override void Update() | 1240 | public override void Update() |
1232 | { | 1241 | { |
1233 | float physicsFPS; | 1242 | TimeSpan SinceLastFrame = DateTime.UtcNow - m_lastupdate; |
1234 | int maintc; | 1243 | float physicsFPS = 0f; |
1244 | |||
1245 | int maintc = Util.EnvironmentTickCount(); | ||
1246 | int tmpFrameMS = maintc; | ||
1247 | tempOnRezMS = eventMS = backupMS = terrainMS = landMS = 0; | ||
1248 | |||
1249 | // Increment the frame counter | ||
1250 | ++Frame; | ||
1235 | 1251 | ||
1236 | while (!shuttingdown) | 1252 | try |
1237 | { | 1253 | { |
1238 | TimeSpan SinceLastFrame = DateTime.UtcNow - m_lastupdate; | 1254 | // Check if any objects have reached their targets |
1239 | physicsFPS = 0f; | 1255 | CheckAtTargets(); |
1240 | 1256 | ||
1241 | maintc = Util.EnvironmentTickCount(); | 1257 | // Update SceneObjectGroups that have scheduled themselves for updates |
1242 | int tmpFrameMS = maintc; | 1258 | // Objects queue their updates onto all scene presences |
1243 | tempOnRezMS = eventMS = backupMS = terrainMS = landMS = 0; | 1259 | if (Frame % m_update_objects == 0) |
1260 | m_sceneGraph.UpdateObjectGroups(); | ||
1244 | 1261 | ||
1245 | // Increment the frame counter | 1262 | // Run through all ScenePresences looking for updates |
1246 | ++m_frame; | 1263 | // Presence updates and queued object updates for each presence are sent to clients |
1264 | if (Frame % m_update_presences == 0) | ||
1265 | m_sceneGraph.UpdatePresences(); | ||
1247 | 1266 | ||
1248 | try | 1267 | // Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client) |
1268 | if (Frame % m_update_coarse_locations == 0) | ||
1249 | { | 1269 | { |
1250 | // Check if any objects have reached their targets | 1270 | List<Vector3> coarseLocations; |
1251 | CheckAtTargets(); | 1271 | List<UUID> avatarUUIDs; |
1272 | SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60); | ||
1273 | // Send coarse locations to clients | ||
1274 | ForEachScenePresence(delegate(ScenePresence presence) | ||
1275 | { | ||
1276 | presence.SendCoarseLocations(coarseLocations, avatarUUIDs); | ||
1277 | }); | ||
1278 | } | ||
1252 | 1279 | ||
1253 | // Update SceneObjectGroups that have scheduled themselves for updates | 1280 | int tmpPhysicsMS2 = Util.EnvironmentTickCount(); |
1254 | // Objects queue their updates onto all scene presences | 1281 | if ((Frame % m_update_physics == 0) && m_physics_enabled) |
1255 | if (m_frame % m_update_objects == 0) | 1282 | m_sceneGraph.UpdatePreparePhysics(); |
1256 | m_sceneGraph.UpdateObjectGroups(); | 1283 | physicsMS2 = Util.EnvironmentTickCountSubtract(tmpPhysicsMS2); |
1257 | 1284 | ||
1258 | // Run through all ScenePresences looking for updates | 1285 | // Apply any pending avatar force input to the avatar's velocity |
1259 | // Presence updates and queued object updates for each presence are sent to clients | 1286 | if (Frame % m_update_entitymovement == 0) |
1260 | if (m_frame % m_update_presences == 0) | 1287 | m_sceneGraph.UpdateScenePresenceMovement(); |
1261 | m_sceneGraph.UpdatePresences(); | ||
1262 | 1288 | ||
1263 | // Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client) | 1289 | // Perform the main physics update. This will do the actual work of moving objects and avatars according to their |
1264 | if (m_frame % m_update_coarse_locations == 0) | 1290 | // velocity |
1265 | { | 1291 | int tmpPhysicsMS = Util.EnvironmentTickCount(); |
1266 | List<Vector3> coarseLocations; | 1292 | if (Frame % m_update_physics == 0) |
1267 | List<UUID> avatarUUIDs; | 1293 | { |
1268 | SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60); | 1294 | if (m_physics_enabled) |
1269 | // Send coarse locations to clients | 1295 | physicsFPS = m_sceneGraph.UpdatePhysics(Math.Max(SinceLastFrame.TotalSeconds, m_timespan)); |
1270 | ForEachScenePresence(delegate(ScenePresence presence) | 1296 | if (SynchronizeScene != null) |
1271 | { | 1297 | SynchronizeScene(this); |
1272 | presence.SendCoarseLocations(coarseLocations, avatarUUIDs); | 1298 | } |
1273 | }); | 1299 | physicsMS = Util.EnvironmentTickCountSubtract(tmpPhysicsMS); |
1274 | } | ||
1275 | |||
1276 | int tmpPhysicsMS2 = Util.EnvironmentTickCount(); | ||
1277 | if ((m_frame % m_update_physics == 0) && m_physics_enabled) | ||
1278 | m_sceneGraph.UpdatePreparePhysics(); | ||
1279 | physicsMS2 = Util.EnvironmentTickCountSubtract(tmpPhysicsMS2); | ||
1280 | 1300 | ||
1281 | // Apply any pending avatar force input to the avatar's velocity | 1301 | // Delete temp-on-rez stuff |
1282 | if (m_frame % m_update_entitymovement == 0) | 1302 | if (Frame % 1000 == 0 && !m_cleaningTemps) |
1283 | m_sceneGraph.UpdateScenePresenceMovement(); | 1303 | { |
1304 | int tmpTempOnRezMS = Util.EnvironmentTickCount(); | ||
1305 | m_cleaningTemps = true; | ||
1306 | Util.FireAndForget(delegate { CleanTempObjects(); m_cleaningTemps = false; }); | ||
1307 | tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpTempOnRezMS); | ||
1308 | } | ||
1284 | 1309 | ||
1285 | // Perform the main physics update. This will do the actual work of moving objects and avatars according to their | 1310 | if (RegionStatus != RegionStatus.SlaveScene) |
1286 | // velocity | 1311 | { |
1287 | int tmpPhysicsMS = Util.EnvironmentTickCount(); | 1312 | if (Frame % m_update_events == 0) |
1288 | if (m_frame % m_update_physics == 0) | ||
1289 | { | 1313 | { |
1290 | if (m_physics_enabled) | 1314 | int evMS = Util.EnvironmentTickCount(); |
1291 | physicsFPS = m_sceneGraph.UpdatePhysics(Math.Max(SinceLastFrame.TotalSeconds, m_timespan)); | 1315 | UpdateEvents(); |
1292 | if (SynchronizeScene != null) | 1316 | eventMS = Util.EnvironmentTickCountSubtract(evMS); ; |
1293 | SynchronizeScene(this); | ||
1294 | } | 1317 | } |
1295 | physicsMS = Util.EnvironmentTickCountSubtract(tmpPhysicsMS); | ||
1296 | 1318 | ||
1297 | // Delete temp-on-rez stuff | 1319 | if (Frame % m_update_backup == 0) |
1298 | if (m_frame % 1000 == 0 && !m_cleaningTemps) | ||
1299 | { | 1320 | { |
1300 | int tmpTempOnRezMS = Util.EnvironmentTickCount(); | 1321 | int backMS = Util.EnvironmentTickCount(); |
1301 | m_cleaningTemps = true; | 1322 | UpdateStorageBackup(); |
1302 | Util.FireAndForget(delegate { CleanTempObjects(); m_cleaningTemps = false; }); | 1323 | backupMS = Util.EnvironmentTickCountSubtract(backMS); |
1303 | tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpTempOnRezMS); | ||
1304 | } | 1324 | } |
1305 | 1325 | ||
1306 | if (RegionStatus != RegionStatus.SlaveScene) | 1326 | if (Frame % m_update_terrain == 0) |
1307 | { | 1327 | { |
1308 | if (m_frame % m_update_events == 0) | 1328 | int terMS = Util.EnvironmentTickCount(); |
1309 | { | 1329 | UpdateTerrain(); |
1310 | int evMS = Util.EnvironmentTickCount(); | 1330 | terrainMS = Util.EnvironmentTickCountSubtract(terMS); |
1311 | UpdateEvents(); | ||
1312 | eventMS = Util.EnvironmentTickCountSubtract(evMS); ; | ||
1313 | } | ||
1314 | |||
1315 | if (m_frame % m_update_backup == 0) | ||
1316 | { | ||
1317 | int backMS = Util.EnvironmentTickCount(); | ||
1318 | UpdateStorageBackup(); | ||
1319 | backupMS = Util.EnvironmentTickCountSubtract(backMS); | ||
1320 | } | ||
1321 | |||
1322 | if (m_frame % m_update_terrain == 0) | ||
1323 | { | ||
1324 | int terMS = Util.EnvironmentTickCount(); | ||
1325 | UpdateTerrain(); | ||
1326 | terrainMS = Util.EnvironmentTickCountSubtract(terMS); | ||
1327 | } | ||
1328 | |||
1329 | if (m_frame % m_update_land == 0) | ||
1330 | { | ||
1331 | int ldMS = Util.EnvironmentTickCount(); | ||
1332 | UpdateLand(); | ||
1333 | landMS = Util.EnvironmentTickCountSubtract(ldMS); | ||
1334 | } | ||
1335 | |||
1336 | frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS); | ||
1337 | otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS; | ||
1338 | lastCompletedFrame = Util.EnvironmentTickCount(); | ||
1339 | |||
1340 | // if (m_frame%m_update_avatars == 0) | ||
1341 | // UpdateInWorldTime(); | ||
1342 | StatsReporter.AddPhysicsFPS(physicsFPS); | ||
1343 | StatsReporter.AddTimeDilation(TimeDilation); | ||
1344 | StatsReporter.AddFPS(1); | ||
1345 | StatsReporter.SetRootAgents(m_sceneGraph.GetRootAgentCount()); | ||
1346 | StatsReporter.SetChildAgents(m_sceneGraph.GetChildAgentCount()); | ||
1347 | StatsReporter.SetObjects(m_sceneGraph.GetTotalObjectsCount()); | ||
1348 | StatsReporter.SetActiveObjects(m_sceneGraph.GetActiveObjectsCount()); | ||
1349 | StatsReporter.addFrameMS(frameMS); | ||
1350 | StatsReporter.addPhysicsMS(physicsMS + physicsMS2); | ||
1351 | StatsReporter.addOtherMS(otherMS); | ||
1352 | StatsReporter.SetActiveScripts(m_sceneGraph.GetActiveScriptsCount()); | ||
1353 | StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS()); | ||
1354 | } | 1331 | } |
1355 | 1332 | ||
1356 | if (LoginsDisabled && m_frame == 20) | 1333 | if (Frame % m_update_land == 0) |
1357 | { | 1334 | { |
1358 | // In 99.9% of cases it is a bad idea to manually force garbage collection. However, | 1335 | int ldMS = Util.EnvironmentTickCount(); |
1359 | // this is a rare case where we know we have just went through a long cycle of heap | 1336 | UpdateLand(); |
1360 | // allocations, and there is no more work to be done until someone logs in | 1337 | landMS = Util.EnvironmentTickCountSubtract(ldMS); |
1361 | GC.Collect(); | 1338 | } |
1362 | 1339 | ||
1363 | IConfig startupConfig = m_config.Configs["Startup"]; | 1340 | frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS); |
1364 | if (startupConfig == null || !startupConfig.GetBoolean("StartDisabled", false)) | 1341 | otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS; |
1365 | { | 1342 | lastCompletedFrame = Util.EnvironmentTickCount(); |
1366 | m_log.DebugFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName); | 1343 | |
1367 | LoginsDisabled = false; | 1344 | // if (Frame%m_update_avatars == 0) |
1368 | m_sceneGridService.InformNeighborsThatRegionisUp(RequestModuleInterface<INeighbourService>(), RegionInfo); | 1345 | // UpdateInWorldTime(); |
1369 | } | 1346 | StatsReporter.AddPhysicsFPS(physicsFPS); |
1347 | StatsReporter.AddTimeDilation(TimeDilation); | ||
1348 | StatsReporter.AddFPS(1); | ||
1349 | StatsReporter.SetRootAgents(m_sceneGraph.GetRootAgentCount()); | ||
1350 | StatsReporter.SetChildAgents(m_sceneGraph.GetChildAgentCount()); | ||
1351 | StatsReporter.SetObjects(m_sceneGraph.GetTotalObjectsCount()); | ||
1352 | StatsReporter.SetActiveObjects(m_sceneGraph.GetActiveObjectsCount()); | ||
1353 | StatsReporter.addFrameMS(frameMS); | ||
1354 | StatsReporter.addPhysicsMS(physicsMS + physicsMS2); | ||
1355 | StatsReporter.addOtherMS(otherMS); | ||
1356 | StatsReporter.SetActiveScripts(m_sceneGraph.GetActiveScriptsCount()); | ||
1357 | StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS()); | ||
1358 | } | ||
1359 | |||
1360 | if (LoginsDisabled && Frame == 20) | ||
1361 | { | ||
1362 | // In 99.9% of cases it is a bad idea to manually force garbage collection. However, | ||
1363 | // this is a rare case where we know we have just went through a long cycle of heap | ||
1364 | // allocations, and there is no more work to be done until someone logs in | ||
1365 | GC.Collect(); | ||
1366 | |||
1367 | IConfig startupConfig = m_config.Configs["Startup"]; | ||
1368 | if (startupConfig == null || !startupConfig.GetBoolean("StartDisabled", false)) | ||
1369 | { | ||
1370 | m_log.DebugFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName); | ||
1371 | LoginsDisabled = false; | ||
1372 | m_sceneGridService.InformNeighborsThatRegionisUp(RequestModuleInterface<INeighbourService>(), RegionInfo); | ||
1370 | } | 1373 | } |
1371 | } | 1374 | } |
1372 | catch (NotImplementedException) | 1375 | } |
1373 | { | 1376 | catch (NotImplementedException) |
1374 | throw; | 1377 | { |
1375 | } | 1378 | throw; |
1376 | catch (AccessViolationException e) | 1379 | } |
1377 | { | 1380 | catch (AccessViolationException e) |
1378 | m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName); | 1381 | { |
1379 | } | 1382 | m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName); |
1380 | //catch (NullReferenceException e) | 1383 | } |
1381 | //{ | 1384 | //catch (NullReferenceException e) |
1382 | // m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName); | 1385 | //{ |
1383 | //} | 1386 | // m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName); |
1384 | catch (InvalidOperationException e) | 1387 | //} |
1385 | { | 1388 | catch (InvalidOperationException e) |
1386 | m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName); | 1389 | { |
1387 | } | 1390 | m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName); |
1388 | catch (Exception e) | 1391 | } |
1389 | { | 1392 | catch (Exception e) |
1390 | m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName); | 1393 | { |
1391 | } | 1394 | m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName); |
1392 | finally | 1395 | } |
1393 | { | 1396 | finally |
1394 | m_lastupdate = DateTime.UtcNow; | 1397 | { |
1395 | } | 1398 | m_lastupdate = DateTime.UtcNow; |
1399 | } | ||
1396 | 1400 | ||
1397 | maintc = Util.EnvironmentTickCountSubtract(maintc); | 1401 | maintc = Util.EnvironmentTickCountSubtract(maintc); |
1398 | maintc = (int)(m_timespan * 1000) - maintc; | 1402 | maintc = (int)(m_timespan * 1000) - maintc; |
1399 | 1403 | ||
1400 | if (maintc > 0) | ||
1401 | Thread.Sleep(maintc); | ||
1402 | 1404 | ||
1403 | // Tell the watchdog that this thread is still alive | 1405 | m_lastUpdate = Util.EnvironmentTickCount(); |
1404 | Watchdog.UpdateThread(); | 1406 | m_firstHeartbeat = false; |
1405 | 1407 | ||
1406 | m_lastUpdate = Util.EnvironmentTickCount(); | 1408 | if (maintc > 0) |
1407 | m_firstHeartbeat = false; | 1409 | Thread.Sleep(maintc); |
1408 | } | ||
1409 | } | ||
1410 | 1410 | ||
1411 | 1411 | // Tell the watchdog that this thread is still alive | |
1412 | Watchdog.UpdateThread(); | ||
1413 | } | ||
1412 | 1414 | ||
1413 | public void AddGroupTarget(SceneObjectGroup grp) | 1415 | public void AddGroupTarget(SceneObjectGroup grp) |
1414 | { | 1416 | { |
@@ -3127,7 +3129,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
3127 | (childagentYN ? "child" : "root"), agentID, RegionInfo.RegionName); | 3129 | (childagentYN ? "child" : "root"), agentID, RegionInfo.RegionName); |
3128 | 3130 | ||
3129 | m_sceneGraph.removeUserCount(!childagentYN); | 3131 | m_sceneGraph.removeUserCount(!childagentYN); |
3130 | CapsModule.RemoveCapsHandler(agentID); | 3132 | |
3133 | if (CapsModule != null) | ||
3134 | CapsModule.RemoveCapsHandler(agentID); | ||
3131 | 3135 | ||
3132 | // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever | 3136 | // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever |
3133 | // this method is doing is HORRIBLE!!! | 3137 | // this method is doing is HORRIBLE!!! |
@@ -3405,8 +3409,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
3405 | RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, | 3409 | RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, |
3406 | agent.AgentID, agent.circuitcode); | 3410 | agent.AgentID, agent.circuitcode); |
3407 | 3411 | ||
3408 | CapsModule.NewUserConnection(agent); | 3412 | if (CapsModule != null) |
3409 | CapsModule.AddCapsHandler(agent.AgentID); | 3413 | { |
3414 | CapsModule.NewUserConnection(agent); | ||
3415 | CapsModule.AddCapsHandler(agent.AgentID); | ||
3416 | } | ||
3410 | } | 3417 | } |
3411 | else | 3418 | else |
3412 | { | 3419 | { |
@@ -3421,7 +3428,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
3421 | agent.AgentID, RegionInfo.RegionName); | 3428 | agent.AgentID, RegionInfo.RegionName); |
3422 | 3429 | ||
3423 | sp.AdjustKnownSeeds(); | 3430 | sp.AdjustKnownSeeds(); |
3424 | CapsModule.NewUserConnection(agent); | 3431 | |
3432 | if (CapsModule != null) | ||
3433 | CapsModule.NewUserConnection(agent); | ||
3425 | } | 3434 | } |
3426 | } | 3435 | } |
3427 | 3436 | ||
@@ -3933,15 +3942,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
3933 | public void RequestTeleportLocation(IClientAPI remoteClient, string regionName, Vector3 position, | 3942 | public void RequestTeleportLocation(IClientAPI remoteClient, string regionName, Vector3 position, |
3934 | Vector3 lookat, uint teleportFlags) | 3943 | Vector3 lookat, uint teleportFlags) |
3935 | { | 3944 | { |
3936 | GridRegion regionInfo = GridService.GetRegionByName(UUID.Zero, regionName); | 3945 | List<GridRegion> regions = GridService.GetRegionsByName(RegionInfo.ScopeID, regionName, 1); |
3937 | if (regionInfo == null) | 3946 | if (regions == null || regions.Count == 0) |
3938 | { | 3947 | { |
3939 | // can't find the region: Tell viewer and abort | 3948 | // can't find the region: Tell viewer and abort |
3940 | remoteClient.SendTeleportFailed("The region '" + regionName + "' could not be found."); | 3949 | remoteClient.SendTeleportFailed("The region '" + regionName + "' could not be found."); |
3941 | return; | 3950 | return; |
3942 | } | 3951 | } |
3943 | 3952 | ||
3944 | RequestTeleportLocation(remoteClient, regionInfo.RegionHandle, position, lookat, teleportFlags); | 3953 | RequestTeleportLocation(remoteClient, regions[0].RegionHandle, position, lookat, teleportFlags); |
3945 | } | 3954 | } |
3946 | 3955 | ||
3947 | /// <summary> | 3956 | /// <summary> |