public override void Update()
{
float physicsFPS;
int maintc;
while (!shuttingdown)
{
TimeSpan SinceLastFrame = DateTime.UtcNow - m_lastupdate;
physicsFPS = 0f;
maintc = Util.EnvironmentTickCount();
int tmpFrameMS = maintc;
tempOnRezMS = eventMS = backupMS = terrainMS = landMS = 0;
// Increment the frame counter
++m_frame;
try
{
// Check if any objects have reached their targets
CheckAtTargets();
// Update SceneObjectGroups that have scheduled themselves for updates
// Objects queue their updates onto all scene presences
if (m_frame % m_update_objects == 0)
m_sceneGraph.UpdateObjectGroups();
// Run through all ScenePresences looking for updates
// Presence updates and queued object updates for each presence are sent to clients
if (m_frame % m_update_presences == 0)
m_sceneGraph.UpdatePresences();
// Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client)
if (m_frame % m_update_coarse_locations == 0)
{
List<Vector3> coarseLocations;
List<UUID> avatarUUIDs;
SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60);
// Send coarse locations to clients
ForEachScenePresence(delegate(ScenePresence presence)
{
presence.SendCoarseLocations(coarseLocations, avatarUUIDs);
});
}
int tmpPhysicsMS2 = Util.EnvironmentTickCount();
if ((m_frame % m_update_physics == 0) && m_physics_enabled)
m_sceneGraph.UpdatePreparePhysics();
physicsMS2 = Util.EnvironmentTickCountSubtract(tmpPhysicsMS2);
// Apply any pending avatar force input to the avatar's velocity
if (m_frame % m_update_entitymovement == 0)
m_sceneGraph.UpdateScenePresenceMovement();
// Perform the main physics update. This will do the actual work of moving objects and avatars according to their
// velocity
int tmpPhysicsMS = Util.EnvironmentTickCount();
if (m_frame % m_update_physics == 0)
{
if (m_physics_enabled)
physicsFPS = m_sceneGraph.UpdatePhysics(Math.Max(SinceLastFrame.TotalSeconds, m_timespan));
if (SynchronizeScene != null)
SynchronizeScene(this);
}
physicsMS = Util.EnvironmentTickCountSubtract(tmpPhysicsMS);
// Delete temp-on-rez stuff
if (m_frame % m_update_backup == 0)
{
int tmpTempOnRezMS = Util.EnvironmentTickCount();
CleanTempObjects();
tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpTempOnRezMS);
}
if (RegionStatus != RegionStatus.SlaveScene)
{
if (m_frame % m_update_events == 0)
{
int evMS = Util.EnvironmentTickCount();
UpdateEvents();
eventMS = Util.EnvironmentTickCountSubtract(evMS); ;
}
if (m_frame % m_update_backup == 0)
{
int backMS = Util.EnvironmentTickCount();
UpdateStorageBackup();
backupMS = Util.EnvironmentTickCountSubtract(backMS);
}
if (m_frame % m_update_terrain == 0)
{
int terMS = Util.EnvironmentTickCount();
UpdateTerrain();
terrainMS = Util.EnvironmentTickCountSubtract(terMS);
}
if (m_frame % m_update_land == 0)
{
int ldMS = Util.EnvironmentTickCount();
UpdateLand();
landMS = Util.EnvironmentTickCountSubtract(ldMS);
}
frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS);
otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS;
lastCompletedFrame = Util.EnvironmentTickCount();
// if (m_frame%m_update_avatars == 0)
// UpdateInWorldTime();
StatsReporter.AddPhysicsFPS(physicsFPS);
StatsReporter.AddTimeDilation(TimeDilation);
StatsReporter.AddFPS(1);
StatsReporter.SetRootAgents(m_sceneGraph.GetRootAgentCount());
StatsReporter.SetChildAgents(m_sceneGraph.GetChildAgentCount());
StatsReporter.SetObjects(m_sceneGraph.GetTotalObjectsCount());
StatsReporter.SetActiveObjects(m_sceneGraph.GetActiveObjectsCount());
StatsReporter.addFrameMS(frameMS);
StatsReporter.addPhysicsMS(physicsMS + physicsMS2);
StatsReporter.addOtherMS(otherMS);
StatsReporter.SetActiveScripts(m_sceneGraph.GetActiveScriptsCount());
StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS());
}
if (LoginsDisabled && m_frame == 20)
{
// In 99.9% of cases it is a bad idea to manually force garbage collection. However,
// this is a rare case where we know we have just went through a long cycle of heap
// allocations, and there is no more work to be done until someone logs in
GC.Collect();
IConfig startupConfig = m_config.Configs["Startup"];
if (startupConfig == null || !startupConfig.GetBoolean("StartDisabled", false))
{
m_log.DebugFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName);
LoginsDisabled = false;
m_sceneGridService.InformNeighborsThatRegionisUp(RequestModuleInterface<INeighbourService>(), RegionInfo);
}
}
}
catch (NotImplementedException)
{
throw;
}
catch (AccessViolationException e)
{
m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
}
//catch (NullReferenceException e)
//{
// m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
//}
catch (InvalidOperationException e)
{
m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
}
catch (Exception e)
{
m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
}
finally
{
m_lastupdate = DateTime.UtcNow;
}
maintc = Util.EnvironmentTickCountSubtract(maintc);
maintc = (int)(m_timespan * 1000) - maintc;
if (maintc > 0)
Thread.Sleep(maintc);
// Tell the watchdog that this thread is still alive
Watchdog.UpdateThread();
}
}