satoshinm / NetCraft

Web-based fork of fogleman/Craft ⛺
https://satoshinm.github.io/NetCraft/
MIT License
57 stars 13 forks source link

Fix WebGL init waiting on server; show sky while connecting. Closes GH-107 #134

Closed satoshinm closed 7 years ago

satoshinm commented 7 years ago

https://github.com/satoshinm/NetCraft/issues/107

satoshinm commented 7 years ago

First cleaning up the main loop related functions which were split at the very first commit for the emscripten port, it is overdue. But it seems one_iter() is still being called too early, before fully initialized.


Yes, main_init is a main loop blocker. But main_inited has to be called first (from the client_opened callback) to completely initialize, but one_iter is called too early before this occurs, due to emscripten_set_main_loop(one_iter, 0, 1);.

satoshinm commented 7 years ago
build $ git diff
diff --git a/src/main.c b/src/main.c
index 0c3b4d3..af42a9e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -133,6 +133,7 @@ typedef struct {
 typedef struct {
     bool running;
     bool shutdown;
+    bool initialized;
     double last_commit;
     double last_update;
     double previous_iter_timestamp;
@@ -3042,6 +3043,7 @@ int main(int argc, char **argv) {
     // OUTER LOOP //
     g->running = true;
     g->shutdown = false;
+    g->initialized = false;
 #ifdef __EMSCRIPTEN__
     emscripten_push_main_loop_blocker(main_init, NULL); // run before main loop
     emscripten_set_main_loop(one_iter, 0, 1);
@@ -3139,6 +3141,7 @@ void main_inited() {

     // BEGIN MAIN LOOP //
     g->previous_iter_timestamp = glfwGetTime();
+    g->initialized = true;
 }

 void main_shutdown() {
@@ -3158,6 +3161,8 @@ void main_shutdown() {

 void render_scene();
 void one_iter() {
+    if (!g->initialized) return; // only run after main_inited()
+
     Player *me = g->players;
     State *s = &g->players->state;

Adding a flag to exit one_iter() if not initialized by main_inited() yet works, but, emscripten also provides functions to pause/resume the main loop - this could be cleaner: http://kripken.github.io/emscripten-site/docs/api_reference/emscripten.h.html#c.emscripten_pause_main_loop

--

or could it? Trying pausing the main loop before it starts, but it is still called a few times - whether I pause before or after emscripten_set_main_loop. Is it even possible to set the main loop "paused"? If not, then may have to set it in main_inited... but then main() returns before setting the main loop! Abandoning this:

--- a/src/main.c
+++ b/src/main.c
@@ -3044,7 +3044,7 @@ int main(int argc, char **argv) {
     g->shutdown = false;
 #ifdef __EMSCRIPTEN__
     emscripten_push_main_loop_blocker(main_init, NULL); // run before main loop
-    emscripten_set_main_loop(one_iter, 0, 1);
+    //emscripten_set_main_loop(one_iter, 0, 1);
     //main_shutdown(); // called in one_iter() if g->shutdown
 #else
     while (g->running) {
@@ -3119,6 +3119,7 @@ void main_init(void *unused) {
 }

 void main_inited() {
+    printf("main_inited\n");
     // LOCAL VARIABLES //
     reset_model();
     sky_buffer = gen_sky_buffer();
@@ -3139,6 +3140,9 @@ void main_inited() {

     // BEGIN MAIN LOOP //
     g->previous_iter_timestamp = glfwGetTime();
+#ifdef __EMSCRIPTEN__
+    emscripten_set_main_loop(one_iter, 0, 1);
+#endif
 }

 void main_shutdown() {
@@ -3158,6 +3162,7 @@ void main_shutdown() {

 void render_scene();
 void one_iter() {
+    printf("one_iter\n");
     Player *me = g->players;
     State *s = &g->players->state;