From 755989b8ffe1d3afe8683d552f5f89d47ca973d5 Mon Sep 17 00:00:00 2001
From: Brad Hefta-Gaub <brad@highfidelity.io>
Date: Thu, 28 Jul 2016 10:01:05 -0700
Subject: [PATCH 1/4] don't allow punished scripts to slow stop or shutdown

---
 libraries/script-engine/src/ScriptEngine.cpp | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp
index 21eae99307..cb82974f4f 100644
--- a/libraries/script-engine/src/ScriptEngine.cpp
+++ b/libraries/script-engine/src/ScriptEngine.cpp
@@ -845,14 +845,24 @@ void ScriptEngine::run() {
         // it means our script is taking too long in it's updates, and we want to punish the
         // script a little bit. So we will force the sleepUntil to be at least our averageUpdate
         // time into the future.
-        auto wouldSleep = (sleepUntil - clock::now());
+        auto wouldSleep = (sleepUntil - beforeSleep);
         auto avgerageUpdate = totalUpdates / thisFrame;
 
         if (wouldSleep < avgerageUpdate) {
             sleepUntil = beforeSleep + avgerageUpdate;
         }
 
-        std::this_thread::sleep_until(sleepUntil);
+        // We don't want to actually sleep for too long, because it causes our scripts to hang 
+        // on shutdown and stop... so we want to loop and sleep until we've spent our time in 
+        // purgatory, constantly checking to see if our script was asked to end
+        while (!_isFinished && clock::now() < sleepUntil) {
+            auto wouldSleepSlice = (sleepUntil - clock::now());
+            auto thisSleepUntil = sleepUntil;
+            if (wouldSleepSlice > FRAME_DURATION) {
+                thisSleepUntil = clock::now() + FRAME_DURATION;
+            }
+            std::this_thread::sleep_until(thisSleepUntil);
+        }
 
 #ifdef SCRIPT_DELAY_DEBUG
         {

From 22619a66bad13b3aca9c3c03332036283f26194c Mon Sep 17 00:00:00 2001
From: Brad Hefta-Gaub <brad@highfidelity.io>
Date: Thu, 28 Jul 2016 10:51:17 -0700
Subject: [PATCH 2/4] process events also

---
 libraries/script-engine/src/ScriptEngine.cpp | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp
index cb82974f4f..2dea38cfae 100644
--- a/libraries/script-engine/src/ScriptEngine.cpp
+++ b/libraries/script-engine/src/ScriptEngine.cpp
@@ -855,13 +855,18 @@ void ScriptEngine::run() {
         // We don't want to actually sleep for too long, because it causes our scripts to hang 
         // on shutdown and stop... so we want to loop and sleep until we've spent our time in 
         // purgatory, constantly checking to see if our script was asked to end
+        bool firstTime = true;
         while (!_isFinished && clock::now() < sleepUntil) {
+            if (!firstTime) {
+                QCoreApplication::processEvents(); // before we sleep again, give events a chance to process
+            }
             auto wouldSleepSlice = (sleepUntil - clock::now());
             auto thisSleepUntil = sleepUntil;
             if (wouldSleepSlice > FRAME_DURATION) {
                 thisSleepUntil = clock::now() + FRAME_DURATION;
             }
             std::this_thread::sleep_until(thisSleepUntil);
+            firstTime = false;
         }
 
 #ifdef SCRIPT_DELAY_DEBUG

From 74a3835a1e3d4639ab7fadaf5dd1c19e7c569932 Mon Sep 17 00:00:00 2001
From: Brad Hefta-Gaub <brad@highfidelity.io>
Date: Thu, 28 Jul 2016 15:15:33 -0700
Subject: [PATCH 3/4] CR feedback

---
 libraries/script-engine/src/ScriptEngine.cpp | 24 +++++---------------
 1 file changed, 6 insertions(+), 18 deletions(-)

diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp
index 2dea38cfae..f98b07478b 100644
--- a/libraries/script-engine/src/ScriptEngine.cpp
+++ b/libraries/script-engine/src/ScriptEngine.cpp
@@ -839,34 +839,22 @@ void ScriptEngine::run() {
         // calculate a sleepUntil to be the time from our start time until the original target
         // sleepUntil for this frame.
         const std::chrono::microseconds FRAME_DURATION(USECS_PER_SECOND / SCRIPT_FPS + 1);
-        clock::time_point sleepUntil(startTime + thisFrame++ * FRAME_DURATION);
+        clock::time_point targetSleepUntil(startTime + thisFrame++ * FRAME_DURATION);
 
         // However, if our sleepUntil is not at least our average update time into the future
         // it means our script is taking too long in it's updates, and we want to punish the
         // script a little bit. So we will force the sleepUntil to be at least our averageUpdate
         // time into the future.
-        auto wouldSleep = (sleepUntil - beforeSleep);
-        auto avgerageUpdate = totalUpdates / thisFrame;
-
-        if (wouldSleep < avgerageUpdate) {
-            sleepUntil = beforeSleep + avgerageUpdate;
-        }
+        auto averageUpdate = totalUpdates / thisFrame;
+        auto sleepUntil = std::max(targetSleepUntil, beforeSleep + averageUpdate);
 
         // We don't want to actually sleep for too long, because it causes our scripts to hang 
         // on shutdown and stop... so we want to loop and sleep until we've spent our time in 
         // purgatory, constantly checking to see if our script was asked to end
-        bool firstTime = true;
         while (!_isFinished && clock::now() < sleepUntil) {
-            if (!firstTime) {
-                QCoreApplication::processEvents(); // before we sleep again, give events a chance to process
-            }
-            auto wouldSleepSlice = (sleepUntil - clock::now());
-            auto thisSleepUntil = sleepUntil;
-            if (wouldSleepSlice > FRAME_DURATION) {
-                thisSleepUntil = clock::now() + FRAME_DURATION;
-            }
+            QCoreApplication::processEvents(); // before we sleep again, give events a chance to process
+            auto thisSleepUntil = std::min(sleepUntil, clock::now() + FRAME_DURATION);
             std::this_thread::sleep_until(thisSleepUntil);
-            firstTime = false;
         }
 
 #ifdef SCRIPT_DELAY_DEBUG
@@ -880,7 +868,7 @@ void ScriptEngine::run() {
                     qCDebug(scriptengine) <<
                         "Frame:" << thisFrame <<
                         "Slept (us):" << std::chrono::duration_cast<std::chrono::microseconds>(actuallySleptUntil - beforeSleep).count() <<
-                        "Avg Updates (us):" << avgerageUpdate.count() <<
+                        "Avg Updates (us):" << averageUpdate.count() <<
                         "FPS:" << fps;
                 }
             }

From e879f22c952772658276153fb3bd8690affe31fe Mon Sep 17 00:00:00 2001
From: Brad Hefta-Gaub <brad@highfidelity.io>
Date: Thu, 28 Jul 2016 15:15:52 -0700
Subject: [PATCH 4/4] fix behavior with no entity server

---
 interface/src/Application.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index e294ae38ad..5d50a1c9fe 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -4685,7 +4685,8 @@ void Application::packetSent(quint64 length) {
 void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine) {
 
     scriptEngine->setEmitScriptUpdatesFunction([this]() {
-        return isPhysicsEnabled();
+        SharedNodePointer entityServerNode = DependencyManager::get<NodeList>()->soloNodeOfType(NodeType::EntityServer);
+        return !entityServerNode || isPhysicsEnabled();
     });
 
     // setup the packet senders and jurisdiction listeners of the script engine's scripting interfaces so