#include #include #include "compat/GL.hpp" #include "compat/AKeyCodes.hpp" #include "App.hpp" #include "AppPlatform_sdl.hpp" #include "NinecraftApp.hpp" #ifdef __EMSCRIPTEN__ #include #include #endif void LogMsg(const char* fmt, ...) { va_list lst; va_start(lst, fmt); vprintf(fmt, lst); printf("\n"); va_end(lst); } // I hate duplicating code, but yeah void LogMsgNoCR(const char* fmt, ...) { va_list lst; va_start(lst, fmt); vprintf(fmt, lst); va_end(lst); } AppPlatform_sdl *g_AppPlatform; NinecraftApp *g_pApp; SDL_Window *window = NULL; SDL_GLContext context = NULL; static void teardown() { if (window != NULL) { SDL_GL_DeleteContext(context); SDL_DestroyWindow(window); SDL_Quit(); window = NULL; } } // Resize From JS #ifdef __EMSCRIPTEN__ extern "C" void resize_from_js(int new_width, int new_height) { SDL_SetWindowSize(window, new_width, new_height); } #endif // Handle Events static bool window_resized = false; static void handle_events() { SDL_Event event; while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_KEYDOWN: case SDL_KEYUP: { if (event.key.keysym.sym == SDLK_F2) { if (event.key.state == SDL_PRESSED && g_AppPlatform != nullptr) { g_AppPlatform->saveScreenshot("", -1, -1); } break; } Keyboard::feed(event.key.state == SDL_PRESSED ? 1 : 0, translate_sdl_key_to_mcpe(event.key.keysym.sym)); if (event.key.keysym.sym == SDLK_LSHIFT || event.key.keysym.sym == SDLK_RSHIFT) { g_AppPlatform->setShiftPressed(event.key.state == SDL_PRESSED, event.key.keysym.sym == SDLK_LSHIFT); } break; } case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: { Mouse::feed(event.button.button == SDL_BUTTON_LEFT ? 1 : 2, event.button.state == SDL_PRESSED ? 1 : 0, event.button.x, event.button.y); break; } case SDL_MOUSEMOTION: { Mouse::_x = event.motion.x; Mouse::_y = event.motion.y; Mouse::feed(0, 0, event.motion.x, event.motion.y); g_AppPlatform->setMouseDiff(event.motion.xrel, event.motion.yrel); break; } case SDL_MOUSEWHEEL: { Mouse::feed(3, event.wheel.y, Mouse::_x, Mouse::_y); break; } case SDL_TEXTINPUT: { if (g_pApp != nullptr) { char x = event.text.text[0]; if (x >= ' ' && x <= '~') { g_pApp->handleCharInput(x); } } break; } case SDL_WINDOWEVENT: { if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) { window_resized = true; } break; } case SDL_QUIT: { g_pApp->quit(); break; } } } } // GUI Scale static void calulate_gui_scale() { int width = Minecraft::width; // Modified Version Of https://github.com/MCPI-Revival/Ninecraft/blob/3f71638a10b581f6a50669edb24bc1ef1a92fbea/ninecraft/src/main.c#L243-L255 if (width < 1000) { if (width < 400) { Gui::InvGuiScale = 1.0f; } else { Gui::InvGuiScale = 0.5f; } } else { Gui::InvGuiScale = 0.25f; } } // Resizing static void resize() { SDL_GL_GetDrawableSize(window, &Minecraft::width, &Minecraft::height); if (g_pApp != nullptr) { g_pApp->sizeUpdate(Minecraft::width, Minecraft::height); } } // Main Loop #ifndef __EMSCRIPTEN__ #define EM_BOOL bool #define EM_TRUE true #define EM_FALSE false #endif static bool is_first_window_resize = true; static EM_BOOL main_loop(double time, void *user_data) { // Handle Events handle_events(); // Screen Size if (window_resized) { window_resized = false; resize(); } // Update MCPE g_pApp->update(); // Swap Buffers SDL_GL_SwapWindow(window); if (g_pApp->wantToQuit()) { delete g_pApp; delete g_AppPlatform; teardown(); // Stop Looping return EM_FALSE; } else { // Keep Looping return EM_TRUE; } } // Main int main(int argc, char *argv[]) { if (SDL_Init(SDL_INIT_VIDEO) < 0) { LOGE("Unable To Initialize SDL: %s\n", SDL_GetError()); exit(EXIT_FAILURE); } // Configure OpenGL ES Context SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); #ifdef USE_GLES1_COMPATIBILITY_LAYER SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); #else SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); #endif // Double-Buffering SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); // Window Size #ifdef __EMSCRIPTEN__ Minecraft::width = std::stoi(argv[1]); Minecraft::height = std::stoi(argv[2]); #endif // Create Window window = SDL_CreateWindow("ReMinecraftPE", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, Minecraft::width, Minecraft::height, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE); if (!window) { LOGE("Unable To Create SDL Window\n"); exit(EXIT_FAILURE); } // Enable Text Input SDL_StartTextInput(); // Create OpenGL ES Context context = SDL_GL_CreateContext(window); if (!context) { LOGE("Unable To Create OpenGL Context\n"); exit(EXIT_FAILURE); } // Setup Compatibility Layer If Needed #ifdef USE_GLES1_COMPATIBILITY_LAYER init_gles_compatibility_layer(); #endif // Setup Teardown #ifndef __EMSCRIPTEN__ atexit(teardown); #endif // Set Size resize(); // Storage Directory #ifdef _WIN32 std::string storagePath = getenv("APPDATA"); #elif defined(__EMSCRIPTEN__) std::string storagePath = ""; #else std::string storagePath = getenv("HOME"); #endif storagePath += "/.reminecraftpe"; ensure_screenshots_folder(storagePath.c_str()); // Start MCPE g_pApp = new NinecraftApp; g_pApp->m_externalStorageDir = storagePath; g_AppPlatform = new AppPlatform_sdl(g_pApp->m_externalStorageDir, window); g_pApp->m_pPlatform = g_AppPlatform; g_pApp->init(); // Loop #ifndef __EMSCRIPTEN__ while (true) { EM_BOOL result = main_loop(0, nullptr); if (result == EM_FALSE) { break; } } #else emscripten_request_animation_frame_loop(main_loop, nullptr); #endif return 0; }