From dd25805af955b273630e99dfe6fa7c930e5c7d77 Mon Sep 17 00:00:00 2001 From: TheBrokenRail Date: Fri, 8 Nov 2024 02:34:58 -0500 Subject: [PATCH] Fancy New API! --- dependencies/symbol-processor/src | 2 +- libreborn/include/libreborn/util.h | 19 -- mods/CMakeLists.txt | 3 + mods/include/mods/extend/DynamicTexture.h | 9 + mods/include/mods/extend/Screen.h | 18 ++ mods/include/mods/extend/extend.h | 69 +++++ .../mods/text-input-box/TextInputScreen.h | 34 +-- mods/src/benchmark/benchmark.cpp | 2 +- mods/src/bucket/bucket.cpp | 1 + mods/src/cake/cake.cpp | 3 +- mods/src/chat/ui.cpp | 130 ++++----- mods/src/creative/creative.cpp | 2 +- mods/src/extend/DynamicTexture.cpp | 6 + mods/src/extend/README.md | 2 + mods/src/extend/Screen.cpp | 47 ++++ mods/src/extend/extend-internal.h | 25 ++ mods/src/game-mode/ui.cpp | 174 ++++++------ mods/src/input/misc.cpp | 2 +- mods/src/misc/graphics.cpp | 2 +- mods/src/misc/misc.cpp | 2 +- mods/src/options/info.cpp | 92 +++---- mods/src/shading/normals.cpp | 4 +- mods/src/text-input-box/TextInputScreen.cpp | 15 +- mods/src/textures/lava.cpp | 254 ++++++++---------- mods/src/title-screen/welcome.cpp | 57 ++-- 25 files changed, 519 insertions(+), 455 deletions(-) create mode 100644 mods/include/mods/extend/DynamicTexture.h create mode 100644 mods/include/mods/extend/Screen.h create mode 100644 mods/include/mods/extend/extend.h create mode 100644 mods/src/extend/DynamicTexture.cpp create mode 100644 mods/src/extend/README.md create mode 100644 mods/src/extend/Screen.cpp create mode 100644 mods/src/extend/extend-internal.h diff --git a/dependencies/symbol-processor/src b/dependencies/symbol-processor/src index f72c4f0567..308a36b4ba 160000 --- a/dependencies/symbol-processor/src +++ b/dependencies/symbol-processor/src @@ -1 +1 @@ -Subproject commit f72c4f0567c62897d74c734819c11705df0bf4ee +Subproject commit 308a36b4ba7f4b1b9917967f66df07860e7d0c56 diff --git a/libreborn/include/libreborn/util.h b/libreborn/include/libreborn/util.h index e7dc8f7910..25a883c50c 100644 --- a/libreborn/include/libreborn/util.h +++ b/libreborn/include/libreborn/util.h @@ -77,25 +77,6 @@ const char *get_home_subdirectory_for_game_data(); // Make Sure Directory Exists void ensure_directory(const char *path); -// Customize VTable -#define CUSTOM_VTABLE(name, parent) \ - void _setup_##name##_vtable(parent##_vtable *vtable); \ - static parent##_vtable *get_##name##_vtable() { \ - static parent##_vtable *vtable = NULL; \ - /* Allocate VTable */ \ - if (vtable == NULL) { \ - /* Init */ \ - vtable = dup_vtable(parent##_vtable_base); \ - ALLOC_CHECK(vtable); \ - /* Setup */ \ - _setup_##name##_vtable(vtable); \ - } \ - /* Return */ \ - return vtable; \ - } \ - /* User-Defined Setup Code */ \ - void _setup_##name##_vtable(parent##_vtable *vtable) - #ifdef __cplusplus } #endif diff --git a/mods/CMakeLists.txt b/mods/CMakeLists.txt index 19341defa6..93ef2bfd46 100644 --- a/mods/CMakeLists.txt +++ b/mods/CMakeLists.txt @@ -33,6 +33,9 @@ set(SRC src/misc/graphics.cpp src/misc/ui.cpp src/misc/tinting.cpp + # extend + src/extend/Screen.cpp + src/extend/DynamicTexture.cpp # options src/options/options.cpp src/options/ui.cpp diff --git a/mods/include/mods/extend/DynamicTexture.h b/mods/include/mods/extend/DynamicTexture.h new file mode 100644 index 0000000000..37a1ee4f29 --- /dev/null +++ b/mods/include/mods/extend/DynamicTexture.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +// Custom Screen +CREATE_HELPER(DynamicTexture) + // Functions + virtual void tick() = 0; +}; \ No newline at end of file diff --git a/mods/include/mods/extend/Screen.h b/mods/include/mods/extend/Screen.h new file mode 100644 index 0000000000..513cd3de9a --- /dev/null +++ b/mods/include/mods/extend/Screen.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +// Custom Screen +CREATE_HELPER(Screen) + // Functions + virtual void init(); + virtual void render(int x, int y, float param_1); + virtual void setupPositions(); + virtual bool handleBackEvent(bool do_nothing); + virtual void tick(); + virtual void buttonClicked(Button *button); + virtual void mouseClicked(int x, int y, int param_1); + virtual void mouseReleased(int x, int y, int param_1); + virtual void keyPressed(int key); + virtual void keyboardNewChar(char key); +}; \ No newline at end of file diff --git a/mods/include/mods/extend/extend.h b/mods/include/mods/extend/extend.h new file mode 100644 index 0000000000..df37e026b7 --- /dev/null +++ b/mods/include/mods/extend/extend.h @@ -0,0 +1,69 @@ +#pragma once + +#include +#include + +// Duplicate VTable +template +T *extend_dup_vtable(T *vtable) { + // Get Size + const unsigned char *const real_vtable = ((const unsigned char *) vtable) - sizeof(void *); + constexpr size_t real_vtable_size = sizeof(T) + sizeof(void *); + // Allocate + unsigned char *const new_vtable = (unsigned char *) ::operator new(real_vtable_size); + T *ret = (T *) (new_vtable + sizeof(void *)); + new (ret) T; + // Copy + memcpy(new_vtable, real_vtable, real_vtable_size); + // Return + return ret; +} + +// Customize VTable +template +T *extend_get_vtable() { + static T *vtable = nullptr; + if (!vtable) { + vtable = extend_dup_vtable(T::base); + setup_vtable(vtable); + } + return vtable; +} +#define CUSTOM_VTABLE(name, parent) \ + static void setup_##name##_vtable(parent##_vtable *); \ + static parent##_vtable *get_##name##_vtable() { \ + return extend_get_vtable(); \ + } \ + static void setup_##name##_vtable(parent##_vtable *vtable) + +// Extend MCPI Classes +template +Self *extend_get_data(Super *super) { + return (Self *) (super + 1); +} +template +auto extend_struct(auto&&... args) -> decltype(Super::allocate()) { + constexpr size_t size = sizeof(Super) + sizeof(Self); + Super *super = (Super *) ::operator new(size); + Self *self = extend_get_data(super); + new (self) Self(std::forward(args)...); + return super; +} + +// Helpers +#define CREATE_HELPER(name) \ + struct Custom##name { \ + explicit Custom##name(auto&&... args): super(((name *) this) - 1) { \ + super->constructor(std::forward(args)...); \ + super->vtable = get_vtable(); \ + } \ + name *const super; \ + static name##_vtable *get_vtable(); \ + private: \ + static void setup_vtable(name##_vtable *vtable); \ + protected: \ + virtual ~Custom##name() = default; \ + public: +#include "Screen.h" +#include "DynamicTexture.h" +#undef CREATE_HELPER \ No newline at end of file diff --git a/mods/include/mods/text-input-box/TextInputScreen.h b/mods/include/mods/text-input-box/TextInputScreen.h index 414a712304..6f22c7e22a 100644 --- a/mods/include/mods/text-input-box/TextInputScreen.h +++ b/mods/include/mods/text-input-box/TextInputScreen.h @@ -3,33 +3,15 @@ #include #include +#include -struct TextInputScreen { +struct TextInputScreen : CustomScreen { std::vector *m_textInputs = nullptr; - template - static void setup(Screen_vtable *vtable) { -#define PATCH_VTABLE(name) \ - static Screen_##name##_t original_##name = vtable->name; \ - vtable->name = [](Screen *super, auto... args) { \ - original_##name(super, std::forward(args)...); \ - T *self = (T *) super; \ - self->data.text_input.name(std::forward(args)...); \ - } - PATCH_VTABLE(keyPressed); - PATCH_VTABLE(keyboardNewChar); - PATCH_VTABLE(mouseClicked); - PATCH_VTABLE(render); - PATCH_VTABLE(init); - PATCH_VTABLE(removed); -#undef PATCH_VTABLE - } - -private: - void keyPressed(int key) const; - void keyboardNewChar(char key) const; - void mouseClicked(int x, int y, int param_1) const; - void render(int x, int y, float param_1) const; - void init(); - void removed() const; + void keyPressed(int key) override; + void keyboardNewChar(char key) override; + void mouseClicked(int x, int y, int param_1) override; + void render(int x, int y, float param_1) override; + void init() override; + ~TextInputScreen() override; }; diff --git a/mods/src/benchmark/benchmark.cpp b/mods/src/benchmark/benchmark.cpp index e1c80cdedf..516091a25f 100644 --- a/mods/src/benchmark/benchmark.cpp +++ b/mods/src/benchmark/benchmark.cpp @@ -156,7 +156,7 @@ static void Minecraft_update_injection(Minecraft *minecraft) { // PerformanceTestChunkSource static RandomLevelSource *PerformanceTestChunkSource_constructor(__attribute__((unused)) RandomLevelSource_constructor_t original, __attribute__((unused)) RandomLevelSource *self, Level *level, __attribute__((unused)) int seed, __attribute__((unused)) int version, __attribute__((unused)) bool enable_spawning) { PerformanceTestChunkSource *self2 = (PerformanceTestChunkSource *) self; - self2->vtable = PerformanceTestChunkSource_vtable_base; + self2->vtable = PerformanceTestChunkSource_vtable::base; self2->level = level; return self; } diff --git a/mods/src/bucket/bucket.cpp b/mods/src/bucket/bucket.cpp index dab3b6ade0..c87a1d5a02 100644 --- a/mods/src/bucket/bucket.cpp +++ b/mods/src/bucket/bucket.cpp @@ -5,6 +5,7 @@ #include #include #include +#include // Items static FoodItem *bucket = nullptr; diff --git a/mods/src/cake/cake.cpp b/mods/src/cake/cake.cpp index c4f9333e75..dc17aa75b6 100644 --- a/mods/src/cake/cake.cpp +++ b/mods/src/cake/cake.cpp @@ -5,6 +5,7 @@ #include #include #include +#include static Tile *cake = nullptr; @@ -123,7 +124,7 @@ static void make_cake() { cake->texture = texture; // Set VTable - cake->vtable = dup_vtable(Tile_vtable_base); + cake->vtable = extend_dup_vtable(Tile_vtable::base); ALLOC_CHECK(cake->vtable); // Set shape diff --git a/mods/src/chat/ui.cpp b/mods/src/chat/ui.cpp index 1392b7353a..e9198e0b38 100644 --- a/mods/src/chat/ui.cpp +++ b/mods/src/chat/ui.cpp @@ -15,81 +15,66 @@ static std::vector &get_history() { } // Structure -EXTEND_STRUCT(ChatScreen, Screen, struct { - TextInputScreen text_input; +struct ChatScreen final : TextInputScreen { TextInputBox *chat; Button *send; int history_pos; -}); -CUSTOM_VTABLE(chat_screen, Screen) { - TextInputScreen::setup(vtable); // Init - static std::vector local_history = {}; - static Screen_init_t original_init = vtable->init; - vtable->init = [](Screen *super) { - original_init(super); - ChatScreen *self = (ChatScreen *) super; + std::vector local_history = {}; + void init() override { + TextInputScreen::init(); // Text Input - self->data.chat = new TextInputBox; - self->data.text_input.m_textInputs->push_back(self->data.chat); - self->data.chat->init(super->font); - self->data.chat->setFocused(true); - self->data.history_pos = get_history().size(); + chat = new TextInputBox; + m_textInputs->push_back(chat); + chat->init(super->font); + chat->setFocused(true); + history_pos = get_history().size(); local_history = get_history(); local_history.push_back(""); // Determine Max Length const std::string prefix = _chat_get_prefix(Strings::default_username); const int max_length = MAX_CHAT_MESSAGE_LENGTH - prefix.length(); - self->data.chat->setMaxLength(max_length); + chat->setMaxLength(max_length); // Send Button - self->data.send = touch_create_button(1, "Send"); - super->rendered_buttons.push_back(self->data.send); - super->selectable_buttons.push_back(self->data.send); + send = touch_create_button(1, "Send"); + super->rendered_buttons.push_back(send); + super->selectable_buttons.push_back(send); // Hide Chat Messages is_in_chat = true; - }; + } // Removal - static Screen_removed_t original_removed = vtable->removed; - vtable->removed = [](Screen *super) { - original_removed(super); + ~ChatScreen() override { is_in_chat = false; - const ChatScreen *self = (ChatScreen *) super; - delete self->data.chat; - self->data.send->destructor_deleting(); - }; + delete chat; + send->destructor_deleting(); + } // Rendering - static Screen_render_t original_render = vtable->render; - vtable->render = [](Screen *super, const int x, const int y, const float param_1) { + void render(const int x, const int y, const float param_1) override { // Background super->renderBackground(); // Render Chat super->minecraft->gui.renderChatMessages(super->height, 20, true, super->font); // Call Original Method - original_render(super, x, y, param_1); - }; + TextInputScreen::render(x, y, param_1); + } // Positioning - static Screen_setupPositions_t original_setupPositions = vtable->setupPositions; - vtable->setupPositions = [](Screen *super) { - original_setupPositions(super); - const ChatScreen *self = (ChatScreen *) super; - self->data.send->height = 24; - self->data.send->width = 40; + void setupPositions() override { + TextInputScreen::setupPositions(); + send->height = 24; + send->width = 40; constexpr int x = 0; - const int y = super->height - self->data.send->height; - const int width = super->width - self->data.send->width; - self->data.chat->setSize(x, y, width, self->data.send->height); - self->data.send->y = super->height - self->data.send->height; - self->data.send->x = x + width; - }; + const int y = super->height - send->height; + const int width = super->width - send->width; + chat->setSize(x, y, width, send->height); + send->y = super->height - send->height; + send->x = x + width; + } // Key Presses - static Screen_keyPressed_t original_keyPressed = vtable->keyPressed; - vtable->keyPressed = [](Screen *super, const int key) { - // Handle Enter - ChatScreen *self = (ChatScreen *) super; - if (self->data.chat->isFocused()) { + void keyPressed(const int key) override { + if (chat->isFocused()) { if (key == MC_KEY_RETURN) { - if (self->data.chat->getText().length() > 0) { - const std::string text = self->data.chat->getText(); + if (chat->getText().length() > 0) { + const std::string text = chat->getText(); if (get_history().size() == 0 || text != get_history().back()) { get_history().push_back(text); } @@ -98,50 +83,39 @@ CUSTOM_VTABLE(chat_screen, Screen) { super->minecraft->setScreen(nullptr); } else if (key == MC_KEY_UP) { // Up - local_history.at(self->data.history_pos) = self->data.chat->getText(); + local_history.at(history_pos) = chat->getText(); // Change - self->data.history_pos -= 1; - if (self->data.history_pos < 0) self->data.history_pos = local_history.size() - 1; - self->data.chat->setText(local_history.at(self->data.history_pos)); + history_pos -= 1; + if (history_pos < 0) history_pos = local_history.size() - 1; + chat->setText(local_history.at(history_pos)); return; } else if (key == MC_KEY_DOWN) { // Down - local_history.at(self->data.history_pos) = self->data.chat->getText(); + local_history.at(history_pos) = chat->getText(); // Change - self->data.history_pos += 1; - if (self->data.history_pos > int(local_history.size()) - 1) self->data.history_pos = 0; - self->data.chat->setText(local_history.at(self->data.history_pos)); + history_pos += 1; + if (history_pos > int(local_history.size()) - 1) history_pos = 0; + chat->setText(local_history.at(history_pos)); return; } } // Call Original Method - original_keyPressed(super, key); - }; + TextInputScreen::keyPressed(key); + } // Button Click - static Screen_buttonClicked_t original_buttonClicked = vtable->buttonClicked; - vtable->buttonClicked = [](Screen *super, Button *button) { - ChatScreen *self = (ChatScreen *) super; - if (button == self->data.send) { + void buttonClicked(Button *button) override { + if (button == send) { // Send - self->data.chat->setFocused(true); + chat->setFocused(true); super->keyPressed(0x0d); } else { // Call Original Method - original_buttonClicked(super, button); + TextInputScreen::buttonClicked(button); } - }; -} + } +}; static Screen *create_chat_screen() { - // Construct - ChatScreen *screen = new ChatScreen; - ALLOC_CHECK(screen); - screen->super()->constructor(); - - // Set VTable - screen->super()->vtable = get_chat_screen_vtable(); - - // Return - return (Screen *) screen; + return extend_struct(); } // Init diff --git a/mods/src/creative/creative.cpp b/mods/src/creative/creative.cpp index 6fedff51c1..4b91fb796d 100644 --- a/mods/src/creative/creative.cpp +++ b/mods/src/creative/creative.cpp @@ -89,7 +89,7 @@ static TileItem *Tile_initTiles_TileItem_injection(TileItem *tile_item, int32_t tile_item->constructor(id); // Switch VTable - tile_item->vtable = (TileItem_vtable *) AuxDataTileItem_vtable_base; + tile_item->vtable = (TileItem_vtable *) AuxDataTileItem_vtable::base; // Configure Item tile_item->is_stacked_by_data = true; tile_item->max_damage = 0; diff --git a/mods/src/extend/DynamicTexture.cpp b/mods/src/extend/DynamicTexture.cpp new file mode 100644 index 0000000000..22b257a8cf --- /dev/null +++ b/mods/src/extend/DynamicTexture.cpp @@ -0,0 +1,6 @@ +#include "extend-internal.h" + +// VTable +SETUP_VTABLE(DynamicTexture) + PATCH_VTABLE(tick); +} \ No newline at end of file diff --git a/mods/src/extend/README.md b/mods/src/extend/README.md new file mode 100644 index 0000000000..263423a2d4 --- /dev/null +++ b/mods/src/extend/README.md @@ -0,0 +1,2 @@ +# `extend` Mod +This mod allows easily extending various Minecraft structures. \ No newline at end of file diff --git a/mods/src/extend/Screen.cpp b/mods/src/extend/Screen.cpp new file mode 100644 index 0000000000..b75c460991 --- /dev/null +++ b/mods/src/extend/Screen.cpp @@ -0,0 +1,47 @@ +#include "extend-internal.h" + +// Easily Create Custom Screens +void CustomScreen::init() { + Screen_vtable::base->init(super); +} +void CustomScreen::render(const int x, const int y, const float param_1) { + Screen_vtable::base->render(super, x, y, param_1); +} +void CustomScreen::setupPositions() { + Screen_vtable::base->setupPositions(super); +} +bool CustomScreen::handleBackEvent(const bool do_nothing) { + return Screen_vtable::base->handleBackEvent(super, do_nothing); +} +void CustomScreen::tick() { + Screen_vtable::base->tick(super); +} +void CustomScreen::buttonClicked(Button *button) { + Screen_vtable::base->buttonClicked(super, button); +} +void CustomScreen::mouseClicked(const int x, const int y, const int param_1) { + Screen_vtable::base->mouseClicked(super, x, y, param_1); +} +void CustomScreen::mouseReleased(const int x, const int y, const int param_1) { + Screen_vtable::base->mouseReleased(super, x, y, param_1); +} +void CustomScreen::keyPressed(const int key) { + Screen_vtable::base->keyPressed(super, key); +} +void CustomScreen::keyboardNewChar(const char key) { + Screen_vtable::base->keyboardNewChar(super, key); +} + +// VTable +SETUP_VTABLE(Screen) + PATCH_VTABLE(init); + PATCH_VTABLE(render); + PATCH_VTABLE(setupPositions); + PATCH_VTABLE(handleBackEvent); + PATCH_VTABLE(tick); + PATCH_VTABLE(buttonClicked); + PATCH_VTABLE(mouseClicked); + PATCH_VTABLE(mouseReleased); + PATCH_VTABLE(keyPressed); + PATCH_VTABLE(keyboardNewChar); +} \ No newline at end of file diff --git a/mods/src/extend/extend-internal.h b/mods/src/extend/extend-internal.h new file mode 100644 index 0000000000..4e7f8ab175 --- /dev/null +++ b/mods/src/extend/extend-internal.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +// VTable Patching +#define PATCH_VTABLE(name) \ + vtable->name = [](_Super *super, auto... args) { \ + return extend_get_data<_Super, _Self>(super)->name(std::forward(args)...); \ + } +#define _PATCH_VTABLE_DESTRUCTOR(name, type) \ + vtable->type = [](_Super *super) { \ + extend_get_data<_Super, _Self>(super)->~_Self(); \ + return name##_vtable::base->type(super); \ + } +#define _PATCH_VTABLE_DESTRUCTORS(name) \ + _PATCH_VTABLE_DESTRUCTOR(name, destructor_complete); \ + _PATCH_VTABLE_DESTRUCTOR(name, destructor_deleting) +#define SETUP_VTABLE(name) \ + name##_vtable *Custom##name::get_vtable() { \ + return extend_get_vtable(); \ + } \ + typedef name _Super; \ + typedef Custom##name _Self; \ + void Custom##name::setup_vtable(name##_vtable *vtable) { \ + _PATCH_VTABLE_DESTRUCTORS(name); diff --git a/mods/src/game-mode/ui.cpp b/mods/src/game-mode/ui.cpp index 94d9468c95..c164b84f50 100644 --- a/mods/src/game-mode/ui.cpp +++ b/mods/src/game-mode/ui.cpp @@ -16,147 +16,127 @@ #define SURVIVAL_STR GAME_MODE_STR("Survival") #define CREATIVE_STR GAME_MODE_STR("Creative") +// Constants +static constexpr int bottom_padding = 4; +static constexpr int inner_padding = 4; +static constexpr int description_padding = 4; +static constexpr int title_padding = 8; +static constexpr int button_height = 24; +static constexpr int content_y_offset_top = (title_padding * 2) + line_height; +static constexpr int content_y_offset_bottom = button_height + (bottom_padding * 2); + // Structure -EXTEND_STRUCT(CreateWorldScreen, Screen, struct { - TextInputScreen text_input; +static void create_world(Minecraft *, std::string, bool, const std::string &); +struct CreateWorldScreen final : TextInputScreen { TextInputBox *name; TextInputBox *seed; Button *game_mode; Button *create; Button *back; -}); -static void create_world(Minecraft *minecraft, std::string name, bool is_creative, std::string seed_str); -CUSTOM_VTABLE(create_world_screen, Screen) { - TextInputScreen::setup(vtable); - // Constants - static constexpr int bottom_padding = 4; - static constexpr int inner_padding = 4; - static constexpr int description_padding = 4; - static constexpr int title_padding = 8; - static constexpr int button_height = 24; - static constexpr int content_y_offset_top = (title_padding * 2) + line_height; - static constexpr int content_y_offset_bottom = button_height + (bottom_padding * 2); // Init - static Screen_init_t original_init = vtable->init; - vtable->init = [](Screen *super) { - original_init(super); - CreateWorldScreen *self = (CreateWorldScreen *) super; + void init() override { + TextInputScreen::init(); // Name - self->data.name = new TextInputBox("World Name", "Unnamed world"); - self->data.text_input.m_textInputs->push_back(self->data.name); - self->data.name->init(super->font); - self->data.name->setFocused(true); + name = new TextInputBox("World Name", "Unnamed world"); + m_textInputs->push_back(name); + name->init(super->font); + name->setFocused(true); // Seed - self->data.seed = new TextInputBox("Seed"); - self->data.text_input.m_textInputs->push_back(self->data.seed); - self->data.seed->init(super->font); - self->data.seed->setFocused(false); + seed = new TextInputBox("Seed"); + m_textInputs->push_back(seed); + seed->init(super->font); + seed->setFocused(false); // Game Mode - self->data.game_mode = touch_create_button(1, CREATIVE_STR); - super->rendered_buttons.push_back(self->data.game_mode); - super->selectable_buttons.push_back(self->data.game_mode); + game_mode = touch_create_button(1, CREATIVE_STR); + super->rendered_buttons.push_back(game_mode); + super->selectable_buttons.push_back(game_mode); // Create - self->data.create = touch_create_button(2, "Create"); - super->rendered_buttons.push_back(self->data.create); - super->selectable_buttons.push_back(self->data.create); + create = touch_create_button(2, "Create"); + super->rendered_buttons.push_back(create); + super->selectable_buttons.push_back(create); // Back - self->data.back = touch_create_button(3, "Back"); - super->rendered_buttons.push_back(self->data.back); - super->selectable_buttons.push_back(self->data.back); - }; + back = touch_create_button(3, "Back"); + super->rendered_buttons.push_back(back); + super->selectable_buttons.push_back(back); + } // Removal - static Screen_removed_t original_removed = vtable->removed; - vtable->removed = [](Screen *super) { - original_removed(super); - CreateWorldScreen *self = (CreateWorldScreen *) super; - delete self->data.name; - delete self->data.seed; - self->data.game_mode->destructor_deleting(); - self->data.back->destructor_deleting(); - self->data.create->destructor_deleting(); - }; + ~CreateWorldScreen() override { + delete name; + delete seed; + game_mode->destructor_deleting(); + back->destructor_deleting(); + create->destructor_deleting(); + } // Rendering - static Screen_render_t original_render = vtable->render; - vtable->render = [](Screen *super, const int x, const int y, const float param_1) { + void render(const int x, const int y, const float param_1) override { // Background misc_render_background(80, super->minecraft, 0, 0, super->width, super->height); misc_render_background(32, super->minecraft, 0, content_y_offset_top, super->width, super->height - content_y_offset_top - content_y_offset_bottom); // Call Original Method - original_render(super, x, y, param_1); + TextInputScreen::render(x, y, param_1); // Title std::string title = "Create world"; super->drawCenteredString(super->font, title, super->width / 2, title_padding, 0xffffffff); // Game Mode Description - CreateWorldScreen *self = (CreateWorldScreen *) super; - const bool is_creative = self->data.game_mode->text == CREATIVE_STR; + const bool is_creative = game_mode->text == CREATIVE_STR; std::string description = is_creative ? Strings::creative_mode_description : Strings::survival_mode_description; - super->drawString(super->font, description, self->data.game_mode->x, self->data.game_mode->y + self->data.game_mode->height + description_padding, 0xa0a0a0); - }; + super->drawString(super->font, description, game_mode->x, game_mode->y + game_mode->height + description_padding, 0xa0a0a0); + } // Positioning - static Screen_setupPositions_t original_setupPositions = vtable->setupPositions; - vtable->setupPositions = [](Screen *super) { - original_setupPositions(super); - CreateWorldScreen *self = (CreateWorldScreen *) super; + void setupPositions() override { + TextInputScreen::setupPositions(); // Height/Width constexpr int width = 120; - const int height = button_height; - self->data.create->width = self->data.back->width = self->data.game_mode->width = width; - int seed_width = self->data.game_mode->width; - int name_width = width * 1.5f; - self->data.create->height = self->data.back->height = self->data.game_mode->height = height; - int text_box_height = self->data.game_mode->height; + constexpr int height = button_height; + create->width = back->width = game_mode->width = width; + const int seed_width = game_mode->width; + constexpr int name_width = width * 1.5f; + create->height = back->height = game_mode->height = height; + const int text_box_height = game_mode->height; // Find Center Y - const int top = content_y_offset_top; + constexpr int top = content_y_offset_top; const int bottom = super->height - content_y_offset_bottom; int center_y = ((bottom - top) / 2) + top; center_y -= (description_padding + line_height) / 2; // X/Y - self->data.create->y = self->data.back->y = super->height - bottom_padding - height; - self->data.create->x = self->data.game_mode->x = (super->width / 2) - inner_padding - width; - self->data.back->x = (super->width / 2) + inner_padding; - const int seed_x = self->data.back->x; + create->y = back->y = super->height - bottom_padding - height; + create->x = game_mode->x = (super->width / 2) - inner_padding - width; + back->x = (super->width / 2) + inner_padding; + const int seed_x = back->x; const int name_x = (super->width / 2) - (name_width / 2); const int name_y = center_y - inner_padding - height; - self->data.game_mode->y = center_y + inner_padding; - const int seed_y = self->data.game_mode->y; + game_mode->y = center_y + inner_padding; + const int seed_y = game_mode->y; // Update Text Boxes - self->data.name->setSize(name_x, name_y, name_width, text_box_height); - self->data.seed->setSize(seed_x, seed_y, seed_width, text_box_height); - }; + name->setSize(name_x, name_y, name_width, text_box_height); + seed->setSize(seed_x, seed_y, seed_width, text_box_height); + } // ESC - vtable->handleBackEvent = [](Screen *super, const bool do_nothing) { + bool handleBackEvent(const bool do_nothing) override { if (!do_nothing) { super->minecraft->screen_chooser.setScreen(5); } return true; - }; + } // Button Click - vtable->buttonClicked = [](Screen *super, Button *button) { - CreateWorldScreen *self = (CreateWorldScreen *) super; - const bool is_creative = self->data.game_mode->text == CREATIVE_STR; - if (button == self->data.game_mode) { + void buttonClicked(Button *button) override { + const bool is_creative = game_mode->text == CREATIVE_STR; + if (button == game_mode) { // Toggle Game Mode - self->data.game_mode->text = is_creative ? SURVIVAL_STR : CREATIVE_STR; - } else if (button == self->data.back) { + game_mode->text = is_creative ? SURVIVAL_STR : CREATIVE_STR; + } else if (button == back) { // Back super->handleBackEvent(false); - } else if (button == self->data.create) { + } else if (button == create) { // Create - create_world(super->minecraft, self->data.name->getText(), is_creative, self->data.seed->getText()); + create_world(super->minecraft, name->getText(), is_creative, seed->getText()); + } else { + TextInputScreen::buttonClicked(button); } - }; -} + } +}; static Screen *create_create_world_screen() { - // Construct - CreateWorldScreen *screen = new CreateWorldScreen; - ALLOC_CHECK(screen); - screen->super()->constructor(); - - // Set VTable - screen->super()->vtable = get_create_world_screen_vtable(); - - // Return - return (Screen *) screen; + return extend_struct(); } // Unique Level Name (https://github.com/ReMinecraftPE/mcpe/blob/d7a8b6baecf8b3b050538abdbc976f690312aa2d/source/client/gui/screens/CreateWorldScreen.cpp#L65-L83) @@ -191,9 +171,9 @@ int get_seed_from_string(std::string str) { } return seed; } -static void create_world(Minecraft *minecraft, std::string name, const bool is_creative, std::string seed_str) { +static void create_world(Minecraft *minecraft, std::string name, const bool is_creative, const std::string &seed_str) { // Get Seed - const int seed = get_seed_from_string(std::move(seed_str)); + const int seed = get_seed_from_string(seed_str); // Get Folder Name name = Util::stringTrim(name); diff --git a/mods/src/input/misc.cpp b/mods/src/input/misc.cpp index 34ef4c5447..34f54f2e41 100644 --- a/mods/src/input/misc.cpp +++ b/mods/src/input/misc.cpp @@ -48,7 +48,7 @@ static bool InBedScreen_handleBackEvent_injection(InBedScreen *screen, const boo // Block UI Interaction When Mouse Is Locked static bool Gui_tickItemDrop_Minecraft_isCreativeMode_call_injection(Minecraft *minecraft) { - const bool is_in_game = minecraft->screen == nullptr || minecraft->screen->vtable == (Screen_vtable *) Touch_IngameBlockSelectionScreen_vtable_base; + const bool is_in_game = minecraft->screen == nullptr || minecraft->screen->vtable == (Screen_vtable *) Touch_IngameBlockSelectionScreen_vtable::base; if (!enable_misc || (media_SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF && is_in_game)) { // Call Original Method return creative_is_restricted() && minecraft->isCreativeMode(); diff --git a/mods/src/misc/graphics.cpp b/mods/src/misc/graphics.cpp index e721581f45..8c2d2af04e 100644 --- a/mods/src/misc/graphics.cpp +++ b/mods/src/misc/graphics.cpp @@ -328,7 +328,7 @@ static int CarriedTile_getTexture2_injection(CarriedTile_getTexture2_t original, // Fix Graphics Bug When Switching To First-Person While Sneaking static void PlayerRenderer_render_injection(PlayerRenderer *model_renderer, Entity *entity, const float param_2, const float param_3, const float param_4, const float param_5, const float param_6) { - HumanoidMobRenderer_vtable_base->render((HumanoidMobRenderer *) model_renderer, entity, param_2, param_3, param_4, param_5, param_6); + HumanoidMobRenderer_vtable::base->render((HumanoidMobRenderer *) model_renderer, entity, param_2, param_3, param_4, param_5, param_6); HumanoidModel *model = model_renderer->model; model->is_sneaking = false; } diff --git a/mods/src/misc/misc.cpp b/mods/src/misc/misc.cpp index 34f39c7353..fb06175983 100644 --- a/mods/src/misc/misc.cpp +++ b/mods/src/misc/misc.cpp @@ -377,7 +377,7 @@ static void LocalPlayer_tick_injection(LocalPlayer_tick_t original, LocalPlayer // Send To Server PlayerActionPacket *packet = PlayerActionPacket::allocate(); Packet_constructor->get(false)((Packet *) packet); - packet->vtable = PlayerActionPacket_vtable_base; + packet->vtable = PlayerActionPacket_vtable::base; packet->entity_id = self->id; packet->action = real ? PLAYER_ACTION_START_SNEAKING : PLAYER_ACTION_STOP_SNEAKING; self->minecraft->rak_net_instance->send(*(Packet *) packet); diff --git a/mods/src/options/info.cpp b/mods/src/options/info.cpp index 973c4c1c8f..bcbdd02073 100644 --- a/mods/src/options/info.cpp +++ b/mods/src/options/info.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "options-internal.h" @@ -104,12 +105,12 @@ struct info_line_position { static info_line_position positioned_info[info_size]; static int content_height = 0; static int line_button_width = 0; -static void position_info(Font *font, int width, int height) { +static void position_info(Font *font, const int width, const int height) { // First Stage (Find Max Text Width) int info_text_width = 0; for (int i = 0; i < info_size; i++) { std::string text = info[i].get_text(); - int text_width = font->width(text); + const int text_width = font->width(text); if (text_width > info_text_width) { info_text_width = text_width; } @@ -170,68 +171,68 @@ void open_url(const std::string &url) { } // Create VTable -CUSTOM_VTABLE(info_screen, Screen) { +struct InfoScreen final : CustomScreen { // Buttons - static Button *discord; - static Button *back; - static Button *info_buttons[info_size]; + Button *discord; + Button *back; + Button *info_buttons[info_size]; // Init - vtable->init = [](Screen *self) { + void init() override { + CustomScreen::init(); // Info for (int i = 0; i < info_size; i++) { Button *button = touch_create_button(INFO_ID_START + i, info[i].button_text); - self->rendered_buttons.push_back(button); - self->selectable_buttons.push_back(button); + super->rendered_buttons.push_back(button); + super->selectable_buttons.push_back(button); info_buttons[i] = button; } // Discord Button discord = touch_create_button(DISCORD_ID, "Discord"); - self->rendered_buttons.push_back(discord); - self->selectable_buttons.push_back(discord); + super->rendered_buttons.push_back(discord); + super->selectable_buttons.push_back(discord); // Back Button back = touch_create_button(BACK_ID, "Back"); - self->rendered_buttons.push_back(back); - self->selectable_buttons.push_back(back); - }; + super->rendered_buttons.push_back(back); + super->selectable_buttons.push_back(back); + } // Handle Back - vtable->handleBackEvent = [](Screen *self, const bool do_nothing) { + bool handleBackEvent(const bool do_nothing) override { if (!do_nothing) { OptionsScreen *screen = OptionsScreen::allocate(); - ALLOC_CHECK(screen); screen->constructor(); - self->minecraft->setScreen((Screen *) screen); + super->minecraft->setScreen((Screen *) screen); } return true; - }; + } // Rendering - static Screen_render_t original_render = vtable->render; - vtable->render = [](Screen *self, const int x, const int y, const float param_1) { + void render(const int x, const int y, const float param_1) override { // Background - misc_render_background(80, self->minecraft, 0, 0, self->width, self->height); - misc_render_background(32, self->minecraft, 0, content_y_offset_top, self->width, content_height); + misc_render_background(80, super->minecraft, 0, 0, super->width, super->height); + misc_render_background(32, super->minecraft, 0, content_y_offset_top, super->width, content_height); // Call Original Method - original_render(self, x, y, param_1); + CustomScreen::render(x, y, param_1); // Title std::string title = "Reborn Information"; - self->drawCenteredString(self->font, title, self->width / 2, title_padding, 0xffffffff); + super->drawCenteredString(super->font, title, super->width / 2, title_padding, 0xffffffff); // Info Text for (int i = 0; i < info_size; i++) { std::string text = info[i].get_text(); - self->drawString(self->font, text, positioned_info[i].text.x, positioned_info[i].text.y, 0xffffffff); + super->drawString(super->font, text, positioned_info[i].text.x, positioned_info[i].text.y, 0xffffffff); } - }; + } // Positioning - vtable->setupPositions = [](Screen *self) { + void setupPositions() override { + CustomScreen::setupPositions(); // Height/Width constexpr int width = 120; discord->width = back->width = width; discord->height = back->height = line_button_height; // X/Y - discord->y = back->y = self->height - bottom_padding - line_button_height; - discord->x = (self->width / 2) - inner_padding - width; - back->x = (self->width / 2) + inner_padding; + discord->y = back->y = super->height - bottom_padding - line_button_height; + discord->x = (super->width / 2) - inner_padding - width; + back->x = (super->width / 2) + inner_padding; // Info - position_info(self->font, self->width, self->height); + position_info(super->font, super->width, super->height); for (int i = 0; i < info_size; i++) { Button *button = info_buttons[i]; button->width = line_button_width; @@ -239,18 +240,18 @@ CUSTOM_VTABLE(info_screen, Screen) { button->x = positioned_info[i].button.x; button->y = positioned_info[i].button.y; } - }; + } // Cleanup - vtable->removed = [](Screen *self) { - for (Button *button : self->rendered_buttons) { + ~InfoScreen() override { + for (Button *button : super->rendered_buttons) { button->destructor_deleting(); } - }; + } // Handle Button Click - vtable->buttonClicked = [](Screen *self, Button *button) { + void buttonClicked(Button *button) override { if (button->id == BACK_ID) { // Back - self->handleBackEvent(false); + super->handleBackEvent(false); } else if (button->id == DISCORD_ID) { // Open Discord Invite open_url(MCPI_DISCORD_INVITE); @@ -258,20 +259,13 @@ CUSTOM_VTABLE(info_screen, Screen) { // Open Info URL const int i = button->id - INFO_ID_START; open_url(info[i].button_url); + } else { + CustomScreen::buttonClicked(button); } - }; -} + } +}; // Create Screen Screen *_create_options_info_screen() { - // Allocate - Screen *screen = Screen::allocate(); - ALLOC_CHECK(screen); - screen->constructor(); - - // Set VTable - screen->vtable = get_info_screen_vtable(); - - // Return - return screen; + return extend_struct(); } diff --git a/mods/src/shading/normals.cpp b/mods/src/shading/normals.cpp index b249154287..bb4dc8dc86 100644 --- a/mods/src/shading/normals.cpp +++ b/mods/src/shading/normals.cpp @@ -5,10 +5,10 @@ // PolygonQuad Vec3 vector_to(const Vec3 &a, const Vec3 &b) { - return Vec3(a.x - b.x, a.y - b.y, a.z - b.z); + return Vec3(b.x - a.x, b.y - a.y, b.z - a.z); } Vec3 vector_cross(const Vec3 &a, const Vec3 &b) { - return Vec3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x); + return Vec3((a.y * b.z) - (a.z * b.y), (a.z * b.x) - (a.x * b.z), (a.x * b.y) - (a.y * b.x)); } static void PolygonQuad_render_injection(PolygonQuad_render_t original, PolygonQuad *self, Tesselator &t, const float scale, const int buffer) { // Set Normal diff --git a/mods/src/text-input-box/TextInputScreen.cpp b/mods/src/text-input-box/TextInputScreen.cpp index a4f5558e1a..5086e51a1c 100644 --- a/mods/src/text-input-box/TextInputScreen.cpp +++ b/mods/src/text-input-box/TextInputScreen.cpp @@ -1,25 +1,29 @@ #include // VTable -void TextInputScreen::keyPressed(const int key) const { +void TextInputScreen::keyPressed(const int key) { + CustomScreen::keyPressed(key); for (int i = 0; i < int(m_textInputs->size()); i++) { TextInputBox *textInput = (*m_textInputs)[i]; textInput->keyPressed(key); } } -void TextInputScreen::keyboardNewChar(const char key) const { +void TextInputScreen::keyboardNewChar(const char key) { + CustomScreen::keyboardNewChar(key); for (int i = 0; i < int(m_textInputs->size()); i++) { TextInputBox *textInput = (*m_textInputs)[i]; textInput->charPressed(key); } } -void TextInputScreen::mouseClicked(const int x, const int y, __attribute__((unused)) int param_1) const { +void TextInputScreen::mouseClicked(const int x, const int y, const int param_1) { + CustomScreen::mouseClicked(x, y, param_1); for (int i = 0; i < int(m_textInputs->size()); i++) { TextInputBox *textInput = (*m_textInputs)[i]; textInput->onClick(x, y); } } -void TextInputScreen::render(__attribute__((unused)) int x, __attribute__((unused)) int y, __attribute__((unused)) float param_1) const { +void TextInputScreen::render(const int x, const int y, const float param_1) { + CustomScreen::render(x, y, param_1); for (int i = 0; i < int(m_textInputs->size()); i++) { TextInputBox *textInput = (*m_textInputs)[i]; textInput->tick(); @@ -27,8 +31,9 @@ void TextInputScreen::render(__attribute__((unused)) int x, __attribute__((unuse } } void TextInputScreen::init() { + CustomScreen::init(); m_textInputs = new std::vector; } -void TextInputScreen::removed() const { +TextInputScreen::~TextInputScreen() { delete m_textInputs; } diff --git a/mods/src/textures/lava.cpp b/mods/src/textures/lava.cpp index 987f9fe05d..d3cfc97bb6 100644 --- a/mods/src/textures/lava.cpp +++ b/mods/src/textures/lava.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include "textures-internal.h" @@ -8,16 +9,70 @@ // Lava texture code was originally decompiled by @iProgramMC as part of ReMinecraftPE. // See: https://github.com/ReMinecraftPE/mcpe -// Structures -EXTEND_STRUCT(LavaTexture, DynamicTexture, struct { +// LavaTexture +struct LavaTexture final : CustomDynamicTexture { int field_14; int field_18; float m_data1[256]; float m_data2[256]; float m_data3[256]; float m_data4[256]; -}); -EXTEND_STRUCT(LavaSideTexture, DynamicTexture, struct { + LavaTexture(): CustomDynamicTexture(Tile::lava->texture) { + field_14 = 0; + field_18 = 0; + for (int i = 0; i < 256; i++) { + m_data1[i] = 0.0f; + m_data2[i] = 0.0f; + m_data3[i] = 0.0f; + m_data4[i] = 0.0f; + } + } + void tick() override { + for (int x = 0; x < 16; x++) { + for (int y = 0; y < 16; y++) { + float f = 0.0F; + const int ax = int(Mth::sin((float(x) * float(M_PI) * 2) / 16.0f) * 1.2f); + const int ay = int(Mth::sin((float(y) * float(M_PI) * 2) / 16.0f) * 1.2f); + for (int bx = x - 1; bx <= x + 1; bx++) { + for (int by = y - 1; by <= y + 1; by++) { + const int k2 = (bx + ay) & 0xf; + const int i3 = (by + ax) & 0xf; + f += m_data1[k2 + i3 * 16]; + } + } + m_data2[x + y * 16] = f / 10.0f + ((m_data3[(x & 0xf) + ((y + 0) & 0xf) * 16] + m_data3[((x + 1) & 0xf) + (y & 0xf) * 16] + m_data3[((x + 1) & 0xf) + ((y + 1) & 0xf) * 16] + m_data3[(x & 0xf) + ((y + 1) & 0xf) * 16]) * 0.25f) * 0.8f; + m_data3[x + y * 16] += m_data4[x + y * 16] * 0.01f; + if (m_data3[x + y * 16] < 0.0f) { + m_data3[x + y * 16] = 0.0f; + } + m_data4[x + y * 16] -= 0.06f; + if (Mth::random() < 0.005f) { + m_data4[x + y * 16] = 1.5f; + } + } + } + std::swap(m_data1, m_data2); + for (int i = 0; i < 256; i++) { + float x1 = m_data1[i] * 2.0f; + if (x1 > 1.0f) { + x1 = 1.0f; + } + if (x1 < 0.0f) { + x1 = 0.0f; + } + super->pixels[i * 4 + 0] = int(155.0f + 100.0f * x1); + super->pixels[i * 4 + 1] = int(255.0f * x1 * x1); + super->pixels[i * 4 + 2] = int(128.0f * x1 * x1 * x1 * x1); + super->pixels[i * 4 + 3] = 255; + } + } +}; +static DynamicTexture *create_lava_texture() { + return extend_struct(); +} + +// LavaSideTexture +struct LavaSideTexture final : CustomDynamicTexture { int field_14; int field_18; int field_1C; @@ -25,81 +80,20 @@ EXTEND_STRUCT(LavaSideTexture, DynamicTexture, struct { float m_data2[256]; float m_data3[256]; float m_data4[256]; -}); -EXTEND_STRUCT(FireTexture, DynamicTexture, struct { - float m_data1[320]; - float m_data2[320]; - Random *m_random; -}); - -// LavaTexture -CUSTOM_VTABLE(lava_texture, DynamicTexture) { - vtable->tick = [](DynamicTexture *super) { - LavaTexture *self = (LavaTexture *) super; - for (int x = 0; x < 16; x++) { - for (int y = 0; y < 16; y++) { - float f = 0.0F; - const int ax = int(Mth::sin((float(x) * float(M_PI) * 2) / 16.0f) * 1.2f); - const int ay = int(Mth::sin((float(y) * float(M_PI) * 2) / 16.0f) * 1.2f); - for (int bx = x - 1; bx <= x + 1; bx++) { - for (int by = y - 1; by <= y + 1; by++) { - const int k2 = (bx + ay) & 0xf; - const int i3 = (by + ax) & 0xf; - f += self->data.m_data1[k2 + i3 * 16]; - } - } - self->data.m_data2[x + y * 16] = f / 10.0f + ((self->data.m_data3[(x & 0xf) + ((y + 0) & 0xf) * 16] + self->data.m_data3[((x + 1) & 0xf) + (y & 0xf) * 16] + self->data.m_data3[((x + 1) & 0xf) + ((y + 1) & 0xf) * 16] + self->data.m_data3[(x & 0xf) + ((y + 1) & 0xf) * 16]) * 0.25f) * 0.8f; - self->data.m_data3[x + y * 16] += self->data.m_data4[x + y * 16] * 0.01f; - if (self->data.m_data3[x + y * 16] < 0.0f) { - self->data.m_data3[x + y * 16] = 0.0f; - } - self->data.m_data4[x + y * 16] -= 0.06f; - if (Mth::random() < 0.005f) { - self->data.m_data4[x + y * 16] = 1.5f; - } - } - } - std::swap(self->data.m_data1, self->data.m_data2); + LavaSideTexture(): CustomDynamicTexture(Tile::lava->texture + 1) { + field_14 = 0; + field_18 = 0; + field_1C = 0; + super->texture_size = 2; for (int i = 0; i < 256; i++) { - float x1 = self->data.m_data1[i] * 2.0f; - if (x1 > 1.0f) { - x1 = 1.0f; - } - if (x1 < 0.0f) { - x1 = 0.0f; - } - self->super()->pixels[i * 4 + 0] = int(155.0f + 100.0f * x1); - self->super()->pixels[i * 4 + 1] = int(255.0f * x1 * x1); - self->super()->pixels[i * 4 + 2] = int(128.0f * x1 * x1 * x1 * x1); - self->super()->pixels[i * 4 + 3] = 255; + m_data1[i] = 0.0f; + m_data2[i] = 0.0f; + m_data3[i] = 0.0f; + m_data4[i] = 0.0f; } - }; -} -static DynamicTexture *create_lava_texture() { - // Construct - LavaTexture *texture = new LavaTexture; - ALLOC_CHECK(texture); - texture->super()->constructor(Tile::lava->texture); - // Set VTable - texture->super()->vtable = get_lava_texture_vtable(); - // Setup - texture->data.field_14 = 0; - texture->data.field_18 = 0; - for (int i = 0; i < 256; i++) { - texture->data.m_data1[i] = 0.0f; - texture->data.m_data2[i] = 0.0f; - texture->data.m_data3[i] = 0.0f; - texture->data.m_data4[i] = 0.0f; } - // Return - return (DynamicTexture *) texture; -} - -// LavaSideTexture -CUSTOM_VTABLE(lava_side_texture, DynamicTexture) { - vtable->tick = [](DynamicTexture *super) { - LavaSideTexture *self = (LavaSideTexture *) super; - self->data.field_1C++; + void tick() override { + field_1C++; for (int x = 0; x < 16; x++) { for (int y = 0; y < 16; y++) { float f = 0.0F; @@ -109,120 +103,98 @@ CUSTOM_VTABLE(lava_side_texture, DynamicTexture) { for (int by = y - 1; by <= y + 1; by++) { const int k2 = (bx + ay) & 0xf; const int i3 = (by + ax) & 0xf; - f += self->data.m_data1[k2 + i3 * 16]; + f += m_data1[k2 + i3 * 16]; } } - self->data.m_data2[x + y * 16] = f / 10.0f + ((self->data.m_data3[(x & 0xf) + ((y + 0) & 0xf) * 16] + self->data.m_data3[((x + 1) & 0xf) + (y & 0xf) * 16] + self->data.m_data3[((x + 1) & 0xf) + ((y + 1) & 0xf) * 16] + self->data.m_data3[(x & 0xf) + ((y + 1) & 0xf) * 16]) * 0.25f) * 0.8f; - self->data.m_data3[x + y * 16] += self->data.m_data4[x + y * 16] * 0.01f; - if (self->data.m_data3[x + y * 16] < 0.0f) { - self->data.m_data3[x + y * 16] = 0.0f; + m_data2[x + y * 16] = f / 10.0f + ((m_data3[(x & 0xf) + ((y + 0) & 0xf) * 16] + m_data3[((x + 1) & 0xf) + (y & 0xf) * 16] + m_data3[((x + 1) & 0xf) + ((y + 1) & 0xf) * 16] + m_data3[(x & 0xf) + ((y + 1) & 0xf) * 16]) * 0.25f) * 0.8f; + m_data3[x + y * 16] += m_data4[x + y * 16] * 0.01f; + if (m_data3[x + y * 16] < 0.0f) { + m_data3[x + y * 16] = 0.0f; } - self->data.m_data4[x + y * 16] -= 0.06f; + m_data4[x + y * 16] -= 0.06f; if (Mth::random() < 0.005f) { - self->data.m_data4[x + y * 16] = 1.5f; + m_data4[x + y * 16] = 1.5f; } } } - std::swap(self->data.m_data1, self->data.m_data2); + std::swap(m_data1, m_data2); for (int i = 0; i < 256; i++) { - float x1 = self->data.m_data1[(i - 16 * (self->data.field_1C / 3)) & 0xFF] * 2.0f; + float x1 = m_data1[(i - 16 * (field_1C / 3)) & 0xFF] * 2.0f; if (x1 > 1.0f) { x1 = 1.0f; } if (x1 < 0.0f) { x1 = 0.0f; } - self->super()->pixels[i * 4 + 0] = int(155.0f + 100.0f * x1); - self->super()->pixels[i * 4 + 1] = int(255.0f * x1 * x1); - self->super()->pixels[i * 4 + 2] = int(128.0f * x1 * x1 * x1 * x1); - self->super()->pixels[i * 4 + 3] = 255; + super->pixels[i * 4 + 0] = int(155.0f + 100.0f * x1); + super->pixels[i * 4 + 1] = int(255.0f * x1 * x1); + super->pixels[i * 4 + 2] = int(128.0f * x1 * x1 * x1 * x1); + super->pixels[i * 4 + 3] = 255; } - }; -} + } +}; static DynamicTexture *create_lava_side_texture() { - // Construct - LavaSideTexture *texture = new LavaSideTexture; - ALLOC_CHECK(texture); - texture->super()->constructor(Tile::lava->texture + 1); - // Set VTable - texture->super()->vtable = get_lava_side_texture_vtable(); - // Setup - texture->data.field_14 = 0; - texture->data.field_18 = 0; - texture->data.field_1C = 0; - texture->super()->texture_size = 2; - for (int i = 0; i < 256; i++) { - texture->data.m_data1[i] = 0.0f; - texture->data.m_data2[i] = 0.0f; - texture->data.m_data3[i] = 0.0f; - texture->data.m_data4[i] = 0.0f; - } - // Return - return (DynamicTexture *) texture; + return extend_struct(); } // FireTexture -CUSTOM_VTABLE(fire_texture, DynamicTexture) { - vtable->tick = [](DynamicTexture *super) { - FireTexture *self = (FireTexture *) super; +struct FireTexture final : CustomDynamicTexture { + float m_data1[320]; + float m_data2[320]; + Random *m_random; + explicit FireTexture(const int a2): CustomDynamicTexture(Tile::fire->texture + (16 * a2)) { + m_random = Random::allocate(); + m_random->constructor(); + for (int i = 0; i < 320; i++) { + m_data1[i] = 0.0f; + m_data2[i] = 0.0f; + } + } + void tick() override { for (int i = 0; i < 16; i++) { for (int j = 0; j < 20; j++) { int l = 18; - float f1 = self->data.m_data1[i + ((j + 1) % 20) * 16] * l; + float f1 = m_data1[i + ((j + 1) % 20) * 16] * l; for (int i1 = i - 1; i1 <= i + 1; i1++) { for (int k1 = j; k1 <= j + 1; k1++) { const int i2 = i1; const int k2 = k1; if (i2 >= 0 && k2 >= 0 && i2 < 16 && k2 < 20) { - f1 += self->data.m_data1[i2 + k2 * 16]; + f1 += m_data1[i2 + k2 * 16]; } l++; } } - self->data.m_data2[i + j * 16] = f1 / 25.2f; + m_data2[i + j * 16] = f1 / 25.2f; if (j >= 19) { union { uint32_t x; uint8_t b[4]; } a = {}; - a.x = self->data.m_random->genrand_int32(); - self->data.m_data2[i + j * 16] = 0.2f + (((a.b[3] / 256.0f) * 0.1f) + ((((a.b[0] / 256.0f) * (a.b[1] / 256.0f)) * (a.b[2] / 256.0f)) * 4.0f)); + a.x = m_random->genrand_int32(); + m_data2[i + j * 16] = 0.2f + (((a.b[3] / 256.0f) * 0.1f) + ((((a.b[0] / 256.0f) * (a.b[1] / 256.0f)) * (a.b[2] / 256.0f)) * 4.0f)); } } } - std::swap(self->data.m_data1, self->data.m_data2); + std::swap(m_data1, m_data2); for (int i = 0; i < 256; i++) { - float x = self->data.m_data1[i] * 1.8f; + float x = m_data1[i] * 1.8f; if (x > 1.0f) { x = 1.0f; } if (x < 0.0f) { x = 0.0f; } - self->super()->pixels[4 * i + 0] = int(x * 155.0f + 100.0f); - self->super()->pixels[4 * i + 1] = int(x * x * 255.0f); - self->super()->pixels[4 * i + 2] = int(x * x * x * x * x * x * x * x * x * x * 255.0f); - self->super()->pixels[4 * i + 3] = x >= 0.5f ? 255 : 0; + super->pixels[4 * i + 0] = int(x * 155.0f + 100.0f); + super->pixels[4 * i + 1] = int(x * x * 255.0f); + super->pixels[4 * i + 2] = int(x * x * x * x * x * x * x * x * x * x * 255.0f); + super->pixels[4 * i + 3] = x >= 0.5f ? 255 : 0; } - }; -} -static DynamicTexture *create_fire_texture(const int a2) { - // Construct - FireTexture *texture = new FireTexture; - ALLOC_CHECK(texture); - texture->super()->constructor(Tile::fire->texture + (16 * a2)); - // Set VTable - texture->super()->vtable = get_fire_texture_vtable(); - // Setup Random - texture->data.m_random = Random::allocate(); - texture->data.m_random->constructor(); - for (int i = 0; i < 320; i++) { - texture->data.m_data1[i] = 0.0f; - texture->data.m_data2[i] = 0.0f; } - // Return - return (DynamicTexture *) texture; +}; +static DynamicTexture *create_fire_texture(const int a2) { + return extend_struct(a2); } // Add Textures diff --git a/mods/src/title-screen/welcome.cpp b/mods/src/title-screen/welcome.cpp index 027fa93a62..8ed2270e51 100644 --- a/mods/src/title-screen/welcome.cpp +++ b/mods/src/title-screen/welcome.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "title-screen-internal.h" @@ -75,61 +76,55 @@ static void position_screen(const int width, const int height) { } // Welcome Screen -CUSTOM_VTABLE(welcome_screen, Screen) { +struct WelcomeScreen final : CustomScreen { // Init - vtable->init = [](__attribute__((unused)) Screen *self) { + void init() override { + CustomScreen::init(); // Buttons getting_started = touch_create_button(0, "Getting Started"); changelog = touch_create_button(1, "Changelog"); proceed = touch_create_button(2, "Proceed"); for (Button *button : {getting_started, changelog, proceed}) { - self->rendered_buttons.push_back(button); - self->selectable_buttons.push_back(button); + super->rendered_buttons.push_back(button); + super->selectable_buttons.push_back(button); } - }; + } // Rendering - static Screen_render_t original_render = vtable->render; - vtable->render = [](Screen *self, const int x, const int y, const float param_1) { + void render(const int x, const int y, const float param_1) override { // Background - self->renderBackground(); + super->renderBackground(); // Call Original Method - original_render(self, x, y, param_1); + CustomScreen::render(x, y, param_1); // Text - self->drawCenteredString(self->font, line1, self->width / 2, text_y, 0xFFFFFFFF); - }; + super->drawCenteredString(super->font, line1, super->width / 2, text_y, 0xFFFFFFFF); + } // Positioning - vtable->setupPositions = [](Screen *self) { - position_screen(self->width, self->height); - }; + void setupPositions() override { + CustomScreen::setupPositions(); + position_screen(super->width, super->height); + } // Cleanup - vtable->removed = [](Screen *self) { - for (Button *button : self->rendered_buttons) { + ~WelcomeScreen() override { + for (Button *button : super->rendered_buttons) { button->destructor_deleting(); } - }; + } // Handle Button Click - vtable->buttonClicked = [](Screen *self, Button *button) { + void buttonClicked(Button *button) override { if (button == getting_started) { open_url(MCPI_DOCUMENTATION "GETTING_STARTED.md"); } else if (button == changelog) { open_url(MCPI_DOCUMENTATION CHANGELOG_FILE); } else if (button == proceed) { mark_welcome_as_shown(); - self->minecraft->screen_chooser.setScreen(1); + super->minecraft->screen_chooser.setScreen(1); + } else { + CustomScreen::buttonClicked(button); } - }; -} + } +}; static Screen *create_welcome_screen() { - // Allocate - Screen *screen = Screen::allocate(); - ALLOC_CHECK(screen); - screen->constructor(); - - // Set VTable - screen->vtable = get_welcome_screen_vtable(); - - // Return - return screen; + return extend_struct(); } // Show Welcome Screen