diff --git a/CMakeLists.txt b/CMakeLists.txt index 851ae3ad7..fc117df4a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,20 +4,42 @@ project(craft) FILE(GLOB SOURCE_FILES src/*.c) -add_executable( - craft - ${SOURCE_FILES} - deps/glew/src/glew.c - deps/lodepng/lodepng.c - deps/noise/noise.c - deps/sqlite/sqlite3.c - deps/tinycthread/tinycthread.c) +if (EMSCRIPTEN) + add_executable( + craft + ${SOURCE_FILES} + #deps/glew/src/glew.c + deps/lodepng/lodepng.c + deps/noise/noise.c + deps/sqlite/sqlite3.c + deps/tinycthread/tinycthread.c) + # Generate HTML file wrapper in addition to .js + set(CMAKE_EXECUTABLE_SUFFIX ".html") +else () + add_executable( + craft + ${SOURCE_FILES} + deps/glew/src/glew.c + deps/lodepng/lodepng.c + deps/noise/noise.c + deps/sqlite/sqlite3.c + deps/tinycthread/tinycthread.c) +endif () add_definitions(-std=c99 -O3) -add_subdirectory(deps/glfw) -include_directories(deps/glew/include) -include_directories(deps/glfw/include) +if (EMSCRIPTEN) + # Emscripten default is GLFW 2.x but we use GLFW 3.x, also include data files + set_target_properties(craft PROPERTIES LINK_FLAGS "-s USE_GLFW=3 --embed-file ../shaders/ -s TOTAL_MEMORY=33554432 --embed-file ../textures/") +endif () + +if (NOT EMSCRIPTEN) + # Emscripten includes its own GLFW and GLEW ports + add_subdirectory(deps/glfw) + include_directories(deps/glew/include) + include_directories(deps/glfw/include) +endif () + include_directories(deps/lodepng) include_directories(deps/noise) include_directories(deps/sqlite) @@ -30,8 +52,12 @@ if(MINGW) "C:/Program Files/CURL/include" "C:/Program Files (x86)/CURL/include") endif() -find_package(CURL REQUIRED) -include_directories(${CURL_INCLUDE_DIR}) +if (NOT EMSCRIPTEN) + find_package(CURL REQUIRED) + include_directories(${CURL_INCLUDE_DIR}) +else () + set(CURL_LIBRARIES "") +endif () if(APPLE) target_link_libraries(craft glfw diff --git a/README.md b/README.md index 8708e4c9d..a64f0d90f 100644 --- a/README.md +++ b/README.md @@ -59,9 +59,16 @@ terminal. git clone https://github.com/fogleman/Craft.git cd Craft - cmake . + mkdir build + pushd build + cmake .. make - ./craft + popd + ./build/craft + +To build for the web (experimental), install [Emscripten](http://emscripten.org) and instead run: + + cmake -DCMAKE_TOOLCHAIN_FILE=$EMSCRIPTEN/cmake/Modules/Platform/Emscripten.cmake .. ### Multiplayer diff --git a/shaders/block_fragment.glsl b/shaders/block_fragment.glsl index 31092ab13..4d0f1d1f7 100644 --- a/shaders/block_fragment.glsl +++ b/shaders/block_fragment.glsl @@ -1,4 +1,7 @@ -#version 120 +#ifdef GL_ES +precision mediump float; +precision mediump int; +#endif uniform sampler2D sampler; uniform sampler2D sky_sampler; diff --git a/shaders/block_vertex.glsl b/shaders/block_vertex.glsl index 30249e935..1ea677b54 100644 --- a/shaders/block_vertex.glsl +++ b/shaders/block_vertex.glsl @@ -1,4 +1,7 @@ -#version 120 +#ifdef GL_ES +precision mediump float; +precision mediump int; +#endif uniform mat4 matrix; uniform vec3 camera; @@ -17,7 +20,7 @@ varying float fog_height; varying float diffuse; const float pi = 3.14159265; -const vec3 light_direction = normalize(vec3(-1.0, 1.0, -1.0)); +vec3 light_direction = normalize(vec3(-1.0, 1.0, -1.0)); void main() { gl_Position = matrix * position; @@ -34,6 +37,6 @@ void main() { fog_factor = pow(clamp(camera_distance / fog_distance, 0.0, 1.0), 4.0); float dy = position.y - camera.y; float dx = distance(position.xz, camera.xz); - fog_height = (atan(dy, dx) + pi / 2) / pi; + fog_height = (atan(dy, dx) + pi / 2.0) / pi; } } diff --git a/shaders/line_fragment.glsl b/shaders/line_fragment.glsl index 5e21117d9..c56883b4a 100644 --- a/shaders/line_fragment.glsl +++ b/shaders/line_fragment.glsl @@ -1,4 +1,6 @@ -#version 120 +#ifdef GL_ES +precision mediump float; +#endif void main() { gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); diff --git a/shaders/line_vertex.glsl b/shaders/line_vertex.glsl index 8ccd4b598..6e1a7e92e 100644 --- a/shaders/line_vertex.glsl +++ b/shaders/line_vertex.glsl @@ -1,4 +1,6 @@ -#version 120 +#ifdef GL_ES +precision mediump float; +#endif uniform mat4 matrix; diff --git a/shaders/sky_fragment.glsl b/shaders/sky_fragment.glsl index 258289666..4b40bc2bd 100644 --- a/shaders/sky_fragment.glsl +++ b/shaders/sky_fragment.glsl @@ -1,4 +1,6 @@ -#version 120 +#ifdef GL_ES +precision mediump float; +#endif uniform sampler2D sampler; uniform float timer; diff --git a/shaders/sky_vertex.glsl b/shaders/sky_vertex.glsl index fe79e517b..aa78202a3 100644 --- a/shaders/sky_vertex.glsl +++ b/shaders/sky_vertex.glsl @@ -1,4 +1,6 @@ -#version 120 +#ifdef GL_ES +precision mediump float; +#endif uniform mat4 matrix; diff --git a/shaders/text_fragment.glsl b/shaders/text_fragment.glsl index 25ee603a9..a69a6723a 100644 --- a/shaders/text_fragment.glsl +++ b/shaders/text_fragment.glsl @@ -1,4 +1,6 @@ -#version 120 +#ifdef GL_ES +precision mediump float; +#endif uniform sampler2D sampler; uniform bool is_sign; diff --git a/shaders/text_vertex.glsl b/shaders/text_vertex.glsl index b842ae9e1..1d1b64d99 100644 --- a/shaders/text_vertex.glsl +++ b/shaders/text_vertex.glsl @@ -1,4 +1,6 @@ -#version 120 +#ifdef GL_ES +precision mediump float; +#endif uniform mat4 matrix; diff --git a/src/auth.c b/src/auth.c index 4ff781580..857f7ca96 100644 --- a/src/auth.c +++ b/src/auth.c @@ -1,4 +1,6 @@ +#ifndef __EMSCRIPTEN__ #include +#endif #include #include #include @@ -21,6 +23,9 @@ size_t write_function(char *data, size_t size, size_t count, void *arg) { int get_access_token( char *result, int length, char *username, char *identity_token) { +#ifdef __EMSCRIPTEN__ + return 0; +#else static char url[] = "https://craft.michaelfogleman.com/api/1/identity"; strncpy(result, "", length); CURL *curl = curl_easy_init(); @@ -46,4 +51,5 @@ int get_access_token( } } return 0; +#endif } diff --git a/src/main.c b/src/main.c index a0b622861..dd04cdcda 100644 --- a/src/main.c +++ b/src/main.c @@ -1,6 +1,11 @@ #include #include +#ifndef __EMSCRIPTEN__ #include +#endif +#ifdef __EMSCRIPTEN__ +#include +#endif #include #include #include @@ -2583,9 +2588,26 @@ void reset_model() { g->time_changed = 1; } +void one_iter(); +static FPS fps = {0, 0, 0}; +static double last_commit; +static double last_update; +static double previous; +static State *s; +static Player *me; +static Attrib block_attrib = {0}; +static Attrib line_attrib = {0}; +static Attrib text_attrib = {0}; +static Attrib sky_attrib = {0}; +static GLuint sky_buffer; +static int g_running; +static int g_inner_break; + int main(int argc, char **argv) { // INITIALIZATION // +#ifndef __EMSCRIPTEN__ curl_global_init(CURL_GLOBAL_DEFAULT); +#endif srand(time(NULL)); rand(); @@ -2600,7 +2622,6 @@ int main(int argc, char **argv) { } glfwMakeContextCurrent(g->window); - glfwSwapInterval(VSYNC); glfwSetInputMode(g->window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); glfwSetKeyCallback(g->window, on_key); glfwSetCharCallback(g->window, on_char); @@ -2613,7 +2634,9 @@ int main(int argc, char **argv) { glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); +#ifndef __EMSCRIPTEN__ // TODO: remove, what is replacement? glLogicOp not in >=GLES2: https://github.com/kripken/emscripten/issues/1416 glLogicOp(GL_INVERT); +#endif glClearColor(0, 0, 0, 1); // LOAD TEXTURES // @@ -2652,10 +2675,6 @@ int main(int argc, char **argv) { load_png_texture("textures/sign.png"); // LOAD SHADERS // - Attrib block_attrib = {0}; - Attrib line_attrib = {0}; - Attrib text_attrib = {0}; - Attrib sky_attrib = {0}; GLuint program; program = load_program( @@ -2727,8 +2746,8 @@ int main(int argc, char **argv) { } // OUTER LOOP // - int running = 1; - while (running) { + g_running = 1; + while (g_running) { // DATABASE INITIALIZATION // if (g->mode == MODE_OFFLINE || USE_CACHE) { db_enable(); @@ -2752,13 +2771,13 @@ int main(int argc, char **argv) { // LOCAL VARIABLES // reset_model(); - FPS fps = {0, 0, 0}; - double last_commit = glfwGetTime(); - double last_update = glfwGetTime(); - GLuint sky_buffer = gen_sky_buffer(); + //FPS fps = {0, 0, 0}; + last_commit = glfwGetTime(); + last_update = glfwGetTime(); + sky_buffer = gen_sky_buffer(); - Player *me = g->players; - State *s = &g->players->state; + me = g->players; + s = &g->players->state; me->id = 0; me->name[0] = '\0'; me->buffer = 0; @@ -2772,8 +2791,37 @@ int main(int argc, char **argv) { } // BEGIN MAIN LOOP // - double previous = glfwGetTime(); + previous = glfwGetTime(); +#ifdef __EMSCRIPTEN__ + emscripten_set_main_loop(one_iter, 60, 1); +#else + glfwSwapInterval(VSYNC); + g_inner_break = 0; while (1) { + one_iter(); + if (g_inner_break) break; + } +#endif + + // SHUTDOWN // + db_save_state(s->x, s->y, s->z, s->rx, s->ry); + db_close(); + db_disable(); + client_stop(); + client_disable(); + del_buffer(sky_buffer); + delete_all_chunks(); + delete_all_players(); + } + + glfwTerminate(); +#ifndef __EMSCRIPTEN__ + curl_global_cleanup(); +#endif + return 0; +} + +void one_iter() { // WINDOW SIZE AND SCALE // g->scale = get_scale_factor(); glfwGetFramebufferSize(g->window, &g->width, &g->height); @@ -2937,27 +2985,12 @@ int main(int argc, char **argv) { glfwSwapBuffers(g->window); glfwPollEvents(); if (glfwWindowShouldClose(g->window)) { - running = 0; - break; + g_running = 0; + g_inner_break = 1; } if (g->mode_changed) { g->mode_changed = 0; - break; + g_inner_break = 1; } - } - - // SHUTDOWN // - db_save_state(s->x, s->y, s->z, s->rx, s->ry); - db_close(); - db_disable(); - client_stop(); - client_disable(); - del_buffer(sky_buffer); - delete_all_chunks(); - delete_all_players(); - } - - glfwTerminate(); - curl_global_cleanup(); - return 0; } +