diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 2815c257..61e38cfd 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -16,7 +16,7 @@ * Add `Optimized Chunk Sorting` Feature Flag (Enabled By Default) * Add `Add Cake` Feature Flag (Enabled By Default) * Add `Add Reborn Info To Options` Feature Flag (Enabled By Default) -* Add `Track FPS` Feature Flag (Disabled By Default) +* Add `Log FPS` Feature Flag (Disabled By Default) * Split Up `Remove Creative Mode Restrictions` Feature Flag * `Remove Creative Mode Restrictions` (Disabled By Default) * `Display Slot Count In Creative Mode` (Disabled By Default) diff --git a/launcher/src/client/available-feature-flags b/launcher/src/client/available-feature-flags index 381d5869..34b3dac1 100644 --- a/launcher/src/client/available-feature-flags +++ b/launcher/src/client/available-feature-flags @@ -66,5 +66,6 @@ TRUE Display Date In Select World Screen TRUE Optimized Chunk Sorting TRUE Fix Held Item Caching TRUE Add Reborn Info To Options -FALSE Track FPS -TRUE Add Welcome Screen \ No newline at end of file +FALSE Log FPS +TRUE Add Welcome Screen +TRUE F3 Debug Information \ No newline at end of file diff --git a/libreborn/include/libreborn/util.h b/libreborn/include/libreborn/util.h index 4b4ba3b7..b2b7eb42 100644 --- a/libreborn/include/libreborn/util.h +++ b/libreborn/include/libreborn/util.h @@ -15,6 +15,18 @@ } \ } +// Align Number +#define ALIGN_UP(x, alignment) \ + ({ \ + int _align_x = (x); \ + int _align_alignment = (alignment); \ + int _align_diff = _align_x % _align_alignment; \ + if (_align_diff > 0) { \ + _align_x += (_align_alignment - _align_diff); \ + } \ + _align_x; \ + }) + // Hook Library Function #ifdef __cplusplus #define hooked_function_setup extern "C" diff --git a/media-layer/core/src/media.cpp b/media-layer/core/src/media.cpp index 8ac8e8b0..9db8872a 100644 --- a/media-layer/core/src/media.cpp +++ b/media-layer/core/src/media.cpp @@ -107,6 +107,9 @@ static SDLKey glfw_key_to_sdl_key(const int key) { // Screenshot case GLFW_KEY_F2: return SDLK_F2; + // Debug + case GLFW_KEY_F3: + return SDLK_F3; // Hide GUI case GLFW_KEY_F1: return SDLK_F1; @@ -457,6 +460,9 @@ void media_cleanup() { // Cleanup OpenAL _media_audio_cleanup(); + + // Mark As Stopped + glfw_window = nullptr; } } @@ -558,4 +564,4 @@ void media_get_framebuffer_size(int *width, int *height) { *width = DEFAULT_WIDTH; *height = DEFAULT_HEIGHT; } -} +} \ No newline at end of file diff --git a/media-layer/include/SDL/SDL_keysym.h b/media-layer/include/SDL/SDL_keysym.h index e4ef34e0..95de1b7c 100644 --- a/media-layer/include/SDL/SDL_keysym.h +++ b/media-layer/include/SDL/SDL_keysym.h @@ -35,12 +35,12 @@ typedef enum { SDLK_LEFT = 276, SDLK_F1 = 282, SDLK_F2 = 283, + SDLK_F3 = 284, SDLK_F5 = 286, SDLK_F11 = 292, SDLK_F12 = 293, SDLK_RSHIFT = 303, - SDLK_LSHIFT = 304, - SDLK_WORLD_0 = 160 // Used For Controller Crafting Button + SDLK_LSHIFT = 304 } SDLKey; typedef enum { diff --git a/media-layer/trampoline/src/GLESv1_CM.cpp b/media-layer/trampoline/src/GLESv1_CM.cpp index a5b37418..1d08a3b3 100644 --- a/media-layer/trampoline/src/GLESv1_CM.cpp +++ b/media-layer/trampoline/src/GLESv1_CM.cpp @@ -262,8 +262,7 @@ static int get_texture_size(const GLsizei width, const GLsizei height, const GLe int alignment; glGetIntegerv(is_upload ? GL_UNPACK_ALIGNMENT : GL_PACK_ALIGNMENT, &alignment); // Round - int diff = line_size % alignment; - line_size = line_size + (alignment - diff); + line_size = ALIGN_UP(line_size, alignment); } // Return return line_size * height; @@ -718,7 +717,7 @@ CALL(65, glReadPixels, void, (GLint x, GLint y, GLsizei width, GLsizei height, G GLsizei height = args.next(); GLenum format = args.next(); GLenum type = args.next(); - int data_size = get_texture_size(width, height, format, type, false); + const int data_size = get_texture_size(width, height, format, type, false); unsigned char *data = new unsigned char[data_size]; func(x, y, width, height, format, type, data); writer(args.next(), data, data_size); diff --git a/mods/CMakeLists.txt b/mods/CMakeLists.txt index 3059446e..1004cfd5 100644 --- a/mods/CMakeLists.txt +++ b/mods/CMakeLists.txt @@ -87,6 +87,8 @@ set(SRC src/benchmark/benchmark.cpp # init src/init/init.cpp + # f3 + src/f3/f3.cpp ) # Install Splashes install( diff --git a/mods/include/mods/init/init.h b/mods/include/mods/init/init.h index cd529cf9..776252a8 100644 --- a/mods/include/mods/init/init.h +++ b/mods/include/mods/init/init.h @@ -28,4 +28,5 @@ void init_cake(); void init_home(); void init_override(); void init_screenshot(); +void init_f3(); } diff --git a/mods/include/mods/input/key-list.h b/mods/include/mods/input/key-list.h index f3cafd87..a01fdbec 100644 --- a/mods/include/mods/input/key-list.h +++ b/mods/include/mods/input/key-list.h @@ -5,6 +5,7 @@ KEY(LEFT, 0x25) KEY(RIGHT, 0x27) KEY(F1, 0x70) KEY(F2, 0x71) +KEY(F3, 0x72) KEY(F5, 0x74) KEY(F11, 0x7a) KEY(RETURN, 0xd) diff --git a/mods/include/mods/misc/misc.h b/mods/include/mods/misc/misc.h index 372db1f4..c6ac41bb 100644 --- a/mods/include/mods/misc/misc.h +++ b/mods/include/mods/misc/misc.h @@ -9,9 +9,6 @@ extern "C" { int32_t misc_get_real_selected_slot(Player *player); void misc_render_background(int color, Minecraft *minecraft, int x, int y, int width, int height); -typedef void (*misc_update_function_FillingContainer_t)(FillingContainer *obj); -void misc_run_on_creative_inventory_setup(misc_update_function_FillingContainer_t function); // obj == FillingContainer * - extern bool is_in_chat; } @@ -24,3 +21,5 @@ void misc_run_on_items_setup(const std::function &func); void misc_run_on_language_setup(const std::function &func); void misc_run_on_game_key_press(const std::function &func); void misc_run_on_key_press(const std::function &func); +void misc_run_on_creative_inventory_setup(const std::function &function); +void misc_run_on_swap_buffers(const std::function &function); \ No newline at end of file diff --git a/mods/src/benchmark/benchmark.cpp b/mods/src/benchmark/benchmark.cpp index 91cb036a..154cbb1f 100644 --- a/mods/src/benchmark/benchmark.cpp +++ b/mods/src/benchmark/benchmark.cpp @@ -48,9 +48,7 @@ static void start_world(Minecraft *minecraft) { // Track Frames static unsigned long long int frames = 0; -HOOK(media_swap_buffers, void, ()) { - ensure_media_swap_buffers(); - real_media_swap_buffers(); +static void handle_swap_buffers() { frames++; } @@ -64,8 +62,8 @@ static void Minecraft_tick_injection(__attribute__((unused)) Minecraft *minecraf static long long int get_time() { timespec ts = {}; clock_gettime(CLOCK_MONOTONIC_RAW, &ts); - long long int a = (long long int) ts.tv_nsec; - long long int b = ((long long int) ts.tv_sec) * NANOSECONDS_IN_SECOND; + const long long int a = ts.tv_nsec; + const long long int b = ((long long int) ts.tv_sec) * NANOSECONDS_IN_SECOND; return a + b; } @@ -161,6 +159,8 @@ void init_benchmark() { bool active = getenv(_MCPI_BENCHMARK_ENV) != nullptr; if (active) { misc_run_on_update(Minecraft_update_injection); + // Track Frames + misc_run_on_swap_buffers(handle_swap_buffers); // Track Ticks misc_run_on_tick(Minecraft_tick_injection); // Disable Interaction diff --git a/mods/src/f3/README.md b/mods/src/f3/README.md new file mode 100644 index 00000000..ecb64e63 --- /dev/null +++ b/mods/src/f3/README.md @@ -0,0 +1,2 @@ +# `f3` Mod +This mod add a proper F3 debug screen. \ No newline at end of file diff --git a/mods/src/f3/f3.cpp b/mods/src/f3/f3.cpp new file mode 100644 index 00000000..9ac3fe9d --- /dev/null +++ b/mods/src/f3/f3.cpp @@ -0,0 +1,87 @@ +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +// Get Debug Information +static std::string to_string_with_precision(const double x, const int precision) { + std::stringstream stream; + stream << std::fixed << std::setprecision(precision) << x; + return stream.str(); +} +static int debug_precision = 3; +static std::vector get_debug_info(const Minecraft *minecraft) { + std::vector info; + // Version + info.push_back(std::string("MCPI ") + version_get()); + // FPS + info.push_back("FPS: " + to_string_with_precision(fps, debug_precision)); + // X/Y/Z + if (minecraft->player) { + info.push_back(""); + float x = minecraft->player->x; + float y = minecraft->player->y - minecraft->player->height_offset; + float z = minecraft->player->z; + minecraft->command_server->pos_translator.to(&x, &y, &z); + info.push_back("X: " + to_string_with_precision(x, debug_precision)); + info.push_back("Y: " + to_string_with_precision(y, debug_precision)); + info.push_back("Z: " + to_string_with_precision(z, debug_precision)); + } + // Return + return info; +} + +// Render Text With Background +static uint32_t debug_background_color = 0x90505050; +static int debug_text_color = 0xe0e0e0; +static int debug_background_padding = 1; +static int line_height = 8; +static void render_debug_line(Gui *gui, std::string &line, const int x, const int y) { + // Draw Background + int width = gui->minecraft->font->width(&line); + if (width == 0) { + return; + } + gui->fill(x - debug_background_padding, y - debug_background_padding, x + width + debug_background_padding, y + line_height, debug_background_color); + // Draw Text + gui->minecraft->font->draw(&line, float(x), float(y), debug_text_color); +} +// Draw Debug Information +static bool debug_info_shown = false; +static int debug_margin = 2; +static int debug_line_padding = 1; +static void Gui_renderDebugInfo_injection(__attribute__((unused)) Gui_renderDebugInfo_t original, Gui *self) { + if (debug_info_shown) { + std::vector info = get_debug_info(self->minecraft); + int y = debug_margin; + for (std::string &line : info) { + render_debug_line(self, line, debug_margin, y); + y += line_height; + y += debug_line_padding; + } + } +} + +// Init +void init_f3() { + if (feature_has("F3 Debug Information", server_disabled)) { + overwrite_calls(Gui_renderDebugInfo, Gui_renderDebugInfo_injection); + misc_run_on_game_key_press([](__attribute__((unused)) Minecraft *minecraft, int key) { + if (key == MC_KEY_F3) { + debug_info_shown = !debug_info_shown; + return true; + } else { + return false; + } + }); + } +} \ No newline at end of file diff --git a/mods/src/fps/fps.cpp b/mods/src/fps/fps.cpp index 6bdc6831..03609504 100644 --- a/mods/src/fps/fps.cpp +++ b/mods/src/fps/fps.cpp @@ -6,49 +6,42 @@ #include #include -// Track FPS +// Get Time #define NANOSECONDS_IN_SECOND 1000000000ll static long long int get_time() { timespec ts = {}; clock_gettime(CLOCK_MONOTONIC_RAW, &ts); - long long int a = (long long int) ts.tv_nsec; - long long int b = ((long long int) ts.tv_sec) * NANOSECONDS_IN_SECOND; + const long long int a = ts.tv_nsec; + const long long int b = ((long long int) ts.tv_sec) * NANOSECONDS_IN_SECOND; return a + b; } + +// Track FPS +static bool log_fps; double fps = 0; -static void update_fps(__attribute__((unused)) Minecraft *minecraft) { - static bool is_last_update_time_set = false; - static long long int last_update_time; - long long int time = get_time(); - if (is_last_update_time_set) { - long long int update_time = time - last_update_time; - fps = ((double) NANOSECONDS_IN_SECOND) / ((double) update_time); - } else { - is_last_update_time_set = true; - } - last_update_time = time; -} - -// Print FPS -static void print_fps(__attribute__((unused)) Minecraft *minecraft) { - // Track Ticks - static int ticks = 0; - ticks++; - if (ticks == 20) { - // One Second Has Passed, Reset - ticks = 0; - } - - // Print - if (ticks == 0) { - INFO("FPS: %f", fps); +static void update_fps() { + // Track Frames + static long long int frames = 0; + frames++; + // Get Delta + const long long int time = get_time(); + static long long int last_time = time; + const long long int delta = time - last_time; + const double delta_seconds = double(delta) / double(NANOSECONDS_IN_SECOND); + // Calculate FPS + if (delta_seconds >= 1) { + fps = double(frames) / delta_seconds; + frames = 0; + last_time = time; + // Log + if (log_fps) { + INFO("FPS: %f", fps); + } } } // Init void init_fps() { - if (feature_has("Track FPS", server_disabled)) { - misc_run_on_update(update_fps); - misc_run_on_tick(print_fps); - } + misc_run_on_swap_buffers(update_fps); + log_fps = feature_has("Log FPS", server_disabled); } diff --git a/mods/src/init/init.cpp b/mods/src/init/init.cpp index bb7ceb70..c522104e 100644 --- a/mods/src/init/init.cpp +++ b/mods/src/init/init.cpp @@ -23,8 +23,8 @@ __attribute__((constructor)) static void init() { init_title_screen(); if (!reborn_is_headless()) { init_skin(); + init_fps(); } - init_fps(); init_touch(); init_textures(); init_creative(); @@ -42,5 +42,6 @@ __attribute__((constructor)) static void init() { } if (!reborn_is_headless()) { init_screenshot(); + init_f3(); } } diff --git a/mods/src/misc/api.cpp b/mods/src/misc/api.cpp index c2a443cc..062f9c31 100644 --- a/mods/src/misc/api.cpp +++ b/mods/src/misc/api.cpp @@ -1,4 +1,3 @@ -#include #include #include @@ -9,31 +8,43 @@ #include "misc-internal.h" // Callbacks -#define STORE_CALLBACK(name, type) \ - static std::vector &get_misc_##name##_functions() { \ - static std::vector functions; \ +template +struct Callbacks { + std::vector> functions; + void run(Args... args) { + for (const std::function &func : functions) { + func(args...); + } + } +}; + +// Callbacks +#define SETUP_CALLBACK(name, ...) \ + static Callbacks<__VA_ARGS__> &get_misc_##name##_functions() { \ + static Callbacks<__VA_ARGS__> functions; \ return functions; \ } \ - void misc_run_on_##name(misc_update_function_##type##_t function) { \ - get_misc_##name##_functions().push_back(function); \ - } -#define SETUP_CALLBACK(name, type) \ - STORE_CALLBACK(name, type) \ - static void handle_misc_##name(type *obj) { \ - for (misc_update_function_##type##_t function : get_misc_##name##_functions()) { \ - function(obj); \ - } \ + void misc_run_on_##name(const std::function &function) { \ + get_misc_##name##_functions().functions.push_back(function); \ } // Run Functions On Creative Inventory Setup -SETUP_CALLBACK(creative_inventory_setup, FillingContainer); +SETUP_CALLBACK(creative_inventory_setup, FillingContainer *); // Handle Custom Creative Inventory Setup Behavior static void Inventory_setupDefault_FillingContainer_addItem_call_injection(FillingContainer *filling_container, ItemInstance *item_instance) { // Call Original Method filling_container->addItem(item_instance); // Run Functions - handle_misc_creative_inventory_setup(filling_container); + get_misc_creative_inventory_setup_functions().run(filling_container); +} + +// Track Frames +SETUP_CALLBACK(swap_buffers); +HOOK(media_swap_buffers, void, ()) { + get_misc_swap_buffers_functions().run(); + ensure_media_swap_buffers(); + real_media_swap_buffers(); } // API diff --git a/mods/src/screenshot/screenshot.cpp b/mods/src/screenshot/screenshot.cpp index bb963a38..c8c4507e 100644 --- a/mods/src/screenshot/screenshot.cpp +++ b/mods/src/screenshot/screenshot.cpp @@ -78,10 +78,7 @@ void screenshot_take(Gui *gui) { int alignment; glGetIntegerv(GL_PACK_ALIGNMENT, &alignment); // Round - int diff = line_size % alignment; - if (diff > 0) { - line_size = line_size + (alignment - diff); - } + line_size = ALIGN_UP(line_size, alignment); } int size = height * line_size; diff --git a/mods/src/textures/textures.cpp b/mods/src/textures/textures.cpp index 7a6155b6..d5cbb8d7 100644 --- a/mods/src/textures/textures.cpp +++ b/mods/src/textures/textures.cpp @@ -92,10 +92,7 @@ static int get_line_size(int width) { int alignment; glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment); // Round - int diff = line_size % alignment; - if (diff > 0) { - line_size = line_size + (alignment - diff); - } + line_size = ALIGN_UP(line_size, alignment); } return line_size; } diff --git a/symbols/src/api/OffsetPosTranslator.def b/symbols/src/api/OffsetPosTranslator.def index 72789872..a74e2d95 100644 --- a/symbols/src/api/OffsetPosTranslator.def +++ b/symbols/src/api/OffsetPosTranslator.def @@ -1,4 +1,5 @@ method void from(int *x, int *y, int *z) = 0x27c98; +method void to(float *x, float *y, float *z) = 0x27be0; property float x = 0x4; property float y = 0x8; diff --git a/symbols/src/gui/Font.def b/symbols/src/gui/Font.def index 2914ff8d..663afb68 100644 --- a/symbols/src/gui/Font.def +++ b/symbols/src/gui/Font.def @@ -1 +1,2 @@ method int width(std::string *string) = 0x24d4c; +method void draw(std::string *string, float x, float y, uint color) = 0x250e0; \ No newline at end of file diff --git a/symbols/src/gui/Gui.def b/symbols/src/gui/Gui.def index f676ea6c..c37878dc 100644 --- a/symbols/src/gui/Gui.def +++ b/symbols/src/gui/Gui.def @@ -14,6 +14,7 @@ method void renderSlot(int slot, int x, int y, float alpha) = 0x25cc0; method void renderSlotText(ItemInstance *item, float x, float y, bool finite, bool shadow) = 0x25df8; method void handleKeyPressed(int key) = 0x25a08; method void renderHearts() = 0x2641c; +method void renderDebugInfo() = 0x26958; property Minecraft *minecraft = 0x9f4; property float selected_item_text_timer = 0x9fc; diff --git a/symbols/src/gui/components/GuiComponent.def b/symbols/src/gui/components/GuiComponent.def index f5f18376..46d23b21 100644 --- a/symbols/src/gui/components/GuiComponent.def +++ b/symbols/src/gui/components/GuiComponent.def @@ -7,4 +7,6 @@ method void blit(int x_dest, int y_dest, int x_src, int y_src, int width_dest, i method void drawCenteredString(Font *font, std::string *text, int x, int y, uint color) = 0x2821c; method void drawString(Font *font, std::string *text, int x, int y, uint color) = 0x28284; method void fill(int x1, int y1, int x2, int y2, uint color) = 0x285f0; -method void fillGradient(int x1, int y1, int x2, int y2, int color1, int color2) = 0x287c0; \ No newline at end of file +method void fillGradient(int x1, int y1, int x2, int y2, int color1, int color2) = 0x287c0; + +property float z = 0x4; \ No newline at end of file diff --git a/symbols/src/misc/Tesselator.def b/symbols/src/misc/Tesselator.def index 92ea2e35..e9aa9565 100644 --- a/symbols/src/misc/Tesselator.def +++ b/symbols/src/misc/Tesselator.def @@ -2,7 +2,7 @@ method void begin(int mode) = 0x529d4; method void draw() = 0x52e08; method void colorABGR(int color) = 0x52b54; method void color(int r, int g, int b, int a) = 0x52a48; -method void vertex(float x, float y, float z) = 052bc0; +method void vertex(float x, float y, float z) = 0x52bc0; method void vertexUV(float x, float y, float z, float u, float v) = 0x52d40; method void addOffset(float x, float y, float z) = 0x52d90;