Fancy New API!

This commit is contained in:
TheBrokenRail 2024-11-08 02:34:58 -05:00
parent a6dad72778
commit dd25805af9
25 changed files with 519 additions and 455 deletions

@ -1 +1 @@
Subproject commit f72c4f0567c62897d74c734819c11705df0bf4ee Subproject commit 308a36b4ba7f4b1b9917967f66df07860e7d0c56

View File

@ -77,25 +77,6 @@ const char *get_home_subdirectory_for_game_data();
// Make Sure Directory Exists // Make Sure Directory Exists
void ensure_directory(const char *path); 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 #ifdef __cplusplus
} }
#endif #endif

View File

@ -33,6 +33,9 @@ set(SRC
src/misc/graphics.cpp src/misc/graphics.cpp
src/misc/ui.cpp src/misc/ui.cpp
src/misc/tinting.cpp src/misc/tinting.cpp
# extend
src/extend/Screen.cpp
src/extend/DynamicTexture.cpp
# options # options
src/options/options.cpp src/options/options.cpp
src/options/ui.cpp src/options/ui.cpp

View File

@ -0,0 +1,9 @@
#pragma once
#include <symbols/minecraft.h>
// Custom Screen
CREATE_HELPER(DynamicTexture)
// Functions
virtual void tick() = 0;
};

View File

@ -0,0 +1,18 @@
#pragma once
#include <symbols/minecraft.h>
// 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);
};

View File

@ -0,0 +1,69 @@
#pragma once
#include <cstring>
#include <utility>
// Duplicate VTable
template <typename T>
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 <typename T, void (*setup_vtable)(T *)>
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<parent##_vtable, setup_##name##_vtable>(); \
} \
static void setup_##name##_vtable(parent##_vtable *vtable)
// Extend MCPI Classes
template <typename Super, typename Self>
Self *extend_get_data(Super *super) {
return (Self *) (super + 1);
}
template <typename Super, typename Self>
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, Self>(super);
new (self) Self(std::forward<decltype(args)>(args)...);
return super;
}
// Helpers
#define CREATE_HELPER(name) \
struct Custom##name { \
explicit Custom##name(auto&&... args): super(((name *) this) - 1) { \
super->constructor(std::forward<decltype(args)>(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

View File

@ -3,33 +3,15 @@
#include <symbols/minecraft.h> #include <symbols/minecraft.h>
#include <mods/text-input-box/TextInputBox.h> #include <mods/text-input-box/TextInputBox.h>
#include <mods/extend/extend.h>
struct TextInputScreen { struct TextInputScreen : CustomScreen {
std::vector<TextInputBox *> *m_textInputs = nullptr; std::vector<TextInputBox *> *m_textInputs = nullptr;
template <typename T> void keyPressed(int key) override;
static void setup(Screen_vtable *vtable) { void keyboardNewChar(char key) override;
#define PATCH_VTABLE(name) \ void mouseClicked(int x, int y, int param_1) override;
static Screen_##name##_t original_##name = vtable->name; \ void render(int x, int y, float param_1) override;
vtable->name = [](Screen *super, auto... args) { \ void init() override;
original_##name(super, std::forward<decltype(args)>(args)...); \ ~TextInputScreen() override;
T *self = (T *) super; \
self->data.text_input.name(std::forward<decltype(args)>(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;
}; };

View File

@ -156,7 +156,7 @@ static void Minecraft_update_injection(Minecraft *minecraft) {
// PerformanceTestChunkSource // 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) { 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; PerformanceTestChunkSource *self2 = (PerformanceTestChunkSource *) self;
self2->vtable = PerformanceTestChunkSource_vtable_base; self2->vtable = PerformanceTestChunkSource_vtable::base;
self2->level = level; self2->level = level;
return self; return self;
} }

View File

@ -5,6 +5,7 @@
#include <mods/init/init.h> #include <mods/init/init.h>
#include <mods/misc/misc.h> #include <mods/misc/misc.h>
#include <mods/bucket/bucket.h> #include <mods/bucket/bucket.h>
#include <mods/extend/extend.h>
// Items // Items
static FoodItem *bucket = nullptr; static FoodItem *bucket = nullptr;

View File

@ -5,6 +5,7 @@
#include <mods/init/init.h> #include <mods/init/init.h>
#include <mods/misc/misc.h> #include <mods/misc/misc.h>
#include <mods/bucket/bucket.h> #include <mods/bucket/bucket.h>
#include <mods/extend/extend.h>
static Tile *cake = nullptr; static Tile *cake = nullptr;
@ -123,7 +124,7 @@ static void make_cake() {
cake->texture = texture; cake->texture = texture;
// Set VTable // Set VTable
cake->vtable = dup_vtable(Tile_vtable_base); cake->vtable = extend_dup_vtable(Tile_vtable::base);
ALLOC_CHECK(cake->vtable); ALLOC_CHECK(cake->vtable);
// Set shape // Set shape

View File

@ -15,81 +15,66 @@ static std::vector<std::string> &get_history() {
} }
// Structure // Structure
EXTEND_STRUCT(ChatScreen, Screen, struct { struct ChatScreen final : TextInputScreen {
TextInputScreen text_input;
TextInputBox *chat; TextInputBox *chat;
Button *send; Button *send;
int history_pos; int history_pos;
});
CUSTOM_VTABLE(chat_screen, Screen) {
TextInputScreen::setup<ChatScreen>(vtable);
// Init // Init
static std::vector<std::string> local_history = {}; std::vector<std::string> local_history = {};
static Screen_init_t original_init = vtable->init; void init() override {
vtable->init = [](Screen *super) { TextInputScreen::init();
original_init(super);
ChatScreen *self = (ChatScreen *) super;
// Text Input // Text Input
self->data.chat = new TextInputBox; chat = new TextInputBox;
self->data.text_input.m_textInputs->push_back(self->data.chat); m_textInputs->push_back(chat);
self->data.chat->init(super->font); chat->init(super->font);
self->data.chat->setFocused(true); chat->setFocused(true);
self->data.history_pos = get_history().size(); history_pos = get_history().size();
local_history = get_history(); local_history = get_history();
local_history.push_back(""); local_history.push_back("");
// Determine Max Length // Determine Max Length
const std::string prefix = _chat_get_prefix(Strings::default_username); const std::string prefix = _chat_get_prefix(Strings::default_username);
const int max_length = MAX_CHAT_MESSAGE_LENGTH - prefix.length(); const int max_length = MAX_CHAT_MESSAGE_LENGTH - prefix.length();
self->data.chat->setMaxLength(max_length); chat->setMaxLength(max_length);
// Send Button // Send Button
self->data.send = touch_create_button(1, "Send"); send = touch_create_button(1, "Send");
super->rendered_buttons.push_back(self->data.send); super->rendered_buttons.push_back(send);
super->selectable_buttons.push_back(self->data.send); super->selectable_buttons.push_back(send);
// Hide Chat Messages // Hide Chat Messages
is_in_chat = true; is_in_chat = true;
}; }
// Removal // Removal
static Screen_removed_t original_removed = vtable->removed; ~ChatScreen() override {
vtable->removed = [](Screen *super) {
original_removed(super);
is_in_chat = false; is_in_chat = false;
const ChatScreen *self = (ChatScreen *) super; delete chat;
delete self->data.chat; send->destructor_deleting();
self->data.send->destructor_deleting(); }
};
// Rendering // Rendering
static Screen_render_t original_render = vtable->render; void render(const int x, const int y, const float param_1) override {
vtable->render = [](Screen *super, const int x, const int y, const float param_1) {
// Background // Background
super->renderBackground(); super->renderBackground();
// Render Chat // Render Chat
super->minecraft->gui.renderChatMessages(super->height, 20, true, super->font); super->minecraft->gui.renderChatMessages(super->height, 20, true, super->font);
// Call Original Method // Call Original Method
original_render(super, x, y, param_1); TextInputScreen::render(x, y, param_1);
}; }
// Positioning // Positioning
static Screen_setupPositions_t original_setupPositions = vtable->setupPositions; void setupPositions() override {
vtable->setupPositions = [](Screen *super) { TextInputScreen::setupPositions();
original_setupPositions(super); send->height = 24;
const ChatScreen *self = (ChatScreen *) super; send->width = 40;
self->data.send->height = 24;
self->data.send->width = 40;
constexpr int x = 0; constexpr int x = 0;
const int y = super->height - self->data.send->height; const int y = super->height - send->height;
const int width = super->width - self->data.send->width; const int width = super->width - send->width;
self->data.chat->setSize(x, y, width, self->data.send->height); chat->setSize(x, y, width, send->height);
self->data.send->y = super->height - self->data.send->height; send->y = super->height - send->height;
self->data.send->x = x + width; send->x = x + width;
}; }
// Key Presses // Key Presses
static Screen_keyPressed_t original_keyPressed = vtable->keyPressed; void keyPressed(const int key) override {
vtable->keyPressed = [](Screen *super, const int key) { if (chat->isFocused()) {
// Handle Enter
ChatScreen *self = (ChatScreen *) super;
if (self->data.chat->isFocused()) {
if (key == MC_KEY_RETURN) { if (key == MC_KEY_RETURN) {
if (self->data.chat->getText().length() > 0) { if (chat->getText().length() > 0) {
const std::string text = self->data.chat->getText(); const std::string text = chat->getText();
if (get_history().size() == 0 || text != get_history().back()) { if (get_history().size() == 0 || text != get_history().back()) {
get_history().push_back(text); get_history().push_back(text);
} }
@ -98,50 +83,39 @@ CUSTOM_VTABLE(chat_screen, Screen) {
super->minecraft->setScreen(nullptr); super->minecraft->setScreen(nullptr);
} else if (key == MC_KEY_UP) { } else if (key == MC_KEY_UP) {
// Up // Up
local_history.at(self->data.history_pos) = self->data.chat->getText(); local_history.at(history_pos) = chat->getText();
// Change // Change
self->data.history_pos -= 1; history_pos -= 1;
if (self->data.history_pos < 0) self->data.history_pos = local_history.size() - 1; if (history_pos < 0) history_pos = local_history.size() - 1;
self->data.chat->setText(local_history.at(self->data.history_pos)); chat->setText(local_history.at(history_pos));
return; return;
} else if (key == MC_KEY_DOWN) { } else if (key == MC_KEY_DOWN) {
// Down // Down
local_history.at(self->data.history_pos) = self->data.chat->getText(); local_history.at(history_pos) = chat->getText();
// Change // Change
self->data.history_pos += 1; history_pos += 1;
if (self->data.history_pos > int(local_history.size()) - 1) self->data.history_pos = 0; if (history_pos > int(local_history.size()) - 1) history_pos = 0;
self->data.chat->setText(local_history.at(self->data.history_pos)); chat->setText(local_history.at(history_pos));
return; return;
} }
} }
// Call Original Method // Call Original Method
original_keyPressed(super, key); TextInputScreen::keyPressed(key);
}; }
// Button Click // Button Click
static Screen_buttonClicked_t original_buttonClicked = vtable->buttonClicked; void buttonClicked(Button *button) override {
vtable->buttonClicked = [](Screen *super, Button *button) { if (button == send) {
ChatScreen *self = (ChatScreen *) super;
if (button == self->data.send) {
// Send // Send
self->data.chat->setFocused(true); chat->setFocused(true);
super->keyPressed(0x0d); super->keyPressed(0x0d);
} else { } else {
// Call Original Method // Call Original Method
original_buttonClicked(super, button); TextInputScreen::buttonClicked(button);
} }
}; }
} };
static Screen *create_chat_screen() { static Screen *create_chat_screen() {
// Construct return extend_struct<Screen, ChatScreen>();
ChatScreen *screen = new ChatScreen;
ALLOC_CHECK(screen);
screen->super()->constructor();
// Set VTable
screen->super()->vtable = get_chat_screen_vtable();
// Return
return (Screen *) screen;
} }
// Init // Init

View File

@ -89,7 +89,7 @@ static TileItem *Tile_initTiles_TileItem_injection(TileItem *tile_item, int32_t
tile_item->constructor(id); tile_item->constructor(id);
// Switch VTable // Switch VTable
tile_item->vtable = (TileItem_vtable *) AuxDataTileItem_vtable_base; tile_item->vtable = (TileItem_vtable *) AuxDataTileItem_vtable::base;
// Configure Item // Configure Item
tile_item->is_stacked_by_data = true; tile_item->is_stacked_by_data = true;
tile_item->max_damage = 0; tile_item->max_damage = 0;

View File

@ -0,0 +1,6 @@
#include "extend-internal.h"
// VTable
SETUP_VTABLE(DynamicTexture)
PATCH_VTABLE(tick);
}

View File

@ -0,0 +1,2 @@
# `extend` Mod
This mod allows easily extending various Minecraft structures.

View File

@ -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);
}

View File

@ -0,0 +1,25 @@
#pragma once
#include <mods/extend/extend.h>
// VTable Patching
#define PATCH_VTABLE(name) \
vtable->name = [](_Super *super, auto... args) { \
return extend_get_data<_Super, _Self>(super)->name(std::forward<decltype(args)>(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<name##_vtable, setup_vtable>(); \
} \
typedef name _Super; \
typedef Custom##name _Self; \
void Custom##name::setup_vtable(name##_vtable *vtable) { \
_PATCH_VTABLE_DESTRUCTORS(name);

View File

@ -16,147 +16,127 @@
#define SURVIVAL_STR GAME_MODE_STR("Survival") #define SURVIVAL_STR GAME_MODE_STR("Survival")
#define CREATIVE_STR GAME_MODE_STR("Creative") #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 // Structure
EXTEND_STRUCT(CreateWorldScreen, Screen, struct { static void create_world(Minecraft *, std::string, bool, const std::string &);
TextInputScreen text_input; struct CreateWorldScreen final : TextInputScreen {
TextInputBox *name; TextInputBox *name;
TextInputBox *seed; TextInputBox *seed;
Button *game_mode; Button *game_mode;
Button *create; Button *create;
Button *back; 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<CreateWorldScreen>(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 // Init
static Screen_init_t original_init = vtable->init; void init() override {
vtable->init = [](Screen *super) { TextInputScreen::init();
original_init(super);
CreateWorldScreen *self = (CreateWorldScreen *) super;
// Name // Name
self->data.name = new TextInputBox("World Name", "Unnamed world"); name = new TextInputBox("World Name", "Unnamed world");
self->data.text_input.m_textInputs->push_back(self->data.name); m_textInputs->push_back(name);
self->data.name->init(super->font); name->init(super->font);
self->data.name->setFocused(true); name->setFocused(true);
// Seed // Seed
self->data.seed = new TextInputBox("Seed"); seed = new TextInputBox("Seed");
self->data.text_input.m_textInputs->push_back(self->data.seed); m_textInputs->push_back(seed);
self->data.seed->init(super->font); seed->init(super->font);
self->data.seed->setFocused(false); seed->setFocused(false);
// Game Mode // Game Mode
self->data.game_mode = touch_create_button(1, CREATIVE_STR); game_mode = touch_create_button(1, CREATIVE_STR);
super->rendered_buttons.push_back(self->data.game_mode); super->rendered_buttons.push_back(game_mode);
super->selectable_buttons.push_back(self->data.game_mode); super->selectable_buttons.push_back(game_mode);
// Create // Create
self->data.create = touch_create_button(2, "Create"); create = touch_create_button(2, "Create");
super->rendered_buttons.push_back(self->data.create); super->rendered_buttons.push_back(create);
super->selectable_buttons.push_back(self->data.create); super->selectable_buttons.push_back(create);
// Back // Back
self->data.back = touch_create_button(3, "Back"); back = touch_create_button(3, "Back");
super->rendered_buttons.push_back(self->data.back); super->rendered_buttons.push_back(back);
super->selectable_buttons.push_back(self->data.back); super->selectable_buttons.push_back(back);
}; }
// Removal // Removal
static Screen_removed_t original_removed = vtable->removed; ~CreateWorldScreen() override {
vtable->removed = [](Screen *super) { delete name;
original_removed(super); delete seed;
CreateWorldScreen *self = (CreateWorldScreen *) super; game_mode->destructor_deleting();
delete self->data.name; back->destructor_deleting();
delete self->data.seed; create->destructor_deleting();
self->data.game_mode->destructor_deleting(); }
self->data.back->destructor_deleting();
self->data.create->destructor_deleting();
};
// Rendering // Rendering
static Screen_render_t original_render = vtable->render; void render(const int x, const int y, const float param_1) override {
vtable->render = [](Screen *super, const int x, const int y, const float param_1) {
// Background // Background
misc_render_background(80, super->minecraft, 0, 0, super->width, super->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, super->height - content_y_offset_top - content_y_offset_bottom); 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 // Call Original Method
original_render(super, x, y, param_1); TextInputScreen::render(x, y, param_1);
// Title // Title
std::string title = "Create world"; std::string title = "Create world";
super->drawCenteredString(super->font, title, super->width / 2, title_padding, 0xffffffff); super->drawCenteredString(super->font, title, super->width / 2, title_padding, 0xffffffff);
// Game Mode Description // Game Mode Description
CreateWorldScreen *self = (CreateWorldScreen *) super; const bool is_creative = game_mode->text == CREATIVE_STR;
const bool is_creative = self->data.game_mode->text == CREATIVE_STR;
std::string description = is_creative ? Strings::creative_mode_description : Strings::survival_mode_description; 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 // Positioning
static Screen_setupPositions_t original_setupPositions = vtable->setupPositions; void setupPositions() override {
vtable->setupPositions = [](Screen *super) { TextInputScreen::setupPositions();
original_setupPositions(super);
CreateWorldScreen *self = (CreateWorldScreen *) super;
// Height/Width // Height/Width
constexpr int width = 120; constexpr int width = 120;
const int height = button_height; constexpr int height = button_height;
self->data.create->width = self->data.back->width = self->data.game_mode->width = width; create->width = back->width = game_mode->width = width;
int seed_width = self->data.game_mode->width; const int seed_width = game_mode->width;
int name_width = width * 1.5f; constexpr int name_width = width * 1.5f;
self->data.create->height = self->data.back->height = self->data.game_mode->height = height; create->height = back->height = game_mode->height = height;
int text_box_height = self->data.game_mode->height; const int text_box_height = game_mode->height;
// Find Center Y // 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; const int bottom = super->height - content_y_offset_bottom;
int center_y = ((bottom - top) / 2) + top; int center_y = ((bottom - top) / 2) + top;
center_y -= (description_padding + line_height) / 2; center_y -= (description_padding + line_height) / 2;
// X/Y // X/Y
self->data.create->y = self->data.back->y = super->height - bottom_padding - height; create->y = back->y = super->height - bottom_padding - height;
self->data.create->x = self->data.game_mode->x = (super->width / 2) - inner_padding - width; create->x = game_mode->x = (super->width / 2) - inner_padding - width;
self->data.back->x = (super->width / 2) + inner_padding; back->x = (super->width / 2) + inner_padding;
const int seed_x = self->data.back->x; const int seed_x = back->x;
const int name_x = (super->width / 2) - (name_width / 2); const int name_x = (super->width / 2) - (name_width / 2);
const int name_y = center_y - inner_padding - height; const int name_y = center_y - inner_padding - height;
self->data.game_mode->y = center_y + inner_padding; game_mode->y = center_y + inner_padding;
const int seed_y = self->data.game_mode->y; const int seed_y = game_mode->y;
// Update Text Boxes // Update Text Boxes
self->data.name->setSize(name_x, name_y, name_width, text_box_height); name->setSize(name_x, name_y, name_width, text_box_height);
self->data.seed->setSize(seed_x, seed_y, seed_width, text_box_height); seed->setSize(seed_x, seed_y, seed_width, text_box_height);
}; }
// ESC // ESC
vtable->handleBackEvent = [](Screen *super, const bool do_nothing) { bool handleBackEvent(const bool do_nothing) override {
if (!do_nothing) { if (!do_nothing) {
super->minecraft->screen_chooser.setScreen(5); super->minecraft->screen_chooser.setScreen(5);
} }
return true; return true;
}; }
// Button Click // Button Click
vtable->buttonClicked = [](Screen *super, Button *button) { void buttonClicked(Button *button) override {
CreateWorldScreen *self = (CreateWorldScreen *) super; const bool is_creative = game_mode->text == CREATIVE_STR;
const bool is_creative = self->data.game_mode->text == CREATIVE_STR; if (button == game_mode) {
if (button == self->data.game_mode) {
// Toggle Game Mode // Toggle Game Mode
self->data.game_mode->text = is_creative ? SURVIVAL_STR : CREATIVE_STR; game_mode->text = is_creative ? SURVIVAL_STR : CREATIVE_STR;
} else if (button == self->data.back) { } else if (button == back) {
// Back // Back
super->handleBackEvent(false); super->handleBackEvent(false);
} else if (button == self->data.create) { } else if (button == create) {
// 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() { static Screen *create_create_world_screen() {
// Construct return extend_struct<Screen, CreateWorldScreen>();
CreateWorldScreen *screen = new CreateWorldScreen;
ALLOC_CHECK(screen);
screen->super()->constructor();
// Set VTable
screen->super()->vtable = get_create_world_screen_vtable();
// Return
return (Screen *) screen;
} }
// Unique Level Name (https://github.com/ReMinecraftPE/mcpe/blob/d7a8b6baecf8b3b050538abdbc976f690312aa2d/source/client/gui/screens/CreateWorldScreen.cpp#L65-L83) // 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; 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 // 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 // Get Folder Name
name = Util::stringTrim(name); name = Util::stringTrim(name);

View File

@ -48,7 +48,7 @@ static bool InBedScreen_handleBackEvent_injection(InBedScreen *screen, const boo
// Block UI Interaction When Mouse Is Locked // Block UI Interaction When Mouse Is Locked
static bool Gui_tickItemDrop_Minecraft_isCreativeMode_call_injection(Minecraft *minecraft) { 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)) { if (!enable_misc || (media_SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF && is_in_game)) {
// Call Original Method // Call Original Method
return creative_is_restricted() && minecraft->isCreativeMode(); return creative_is_restricted() && minecraft->isCreativeMode();

View File

@ -328,7 +328,7 @@ static int CarriedTile_getTexture2_injection(CarriedTile_getTexture2_t original,
// Fix Graphics Bug When Switching To First-Person While Sneaking // 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) { 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; HumanoidModel *model = model_renderer->model;
model->is_sneaking = false; model->is_sneaking = false;
} }

View File

@ -377,7 +377,7 @@ static void LocalPlayer_tick_injection(LocalPlayer_tick_t original, LocalPlayer
// Send To Server // Send To Server
PlayerActionPacket *packet = PlayerActionPacket::allocate(); PlayerActionPacket *packet = PlayerActionPacket::allocate();
Packet_constructor->get(false)((Packet *) packet); Packet_constructor->get(false)((Packet *) packet);
packet->vtable = PlayerActionPacket_vtable_base; packet->vtable = PlayerActionPacket_vtable::base;
packet->entity_id = self->id; packet->entity_id = self->id;
packet->action = real ? PLAYER_ACTION_START_SNEAKING : PLAYER_ACTION_STOP_SNEAKING; packet->action = real ? PLAYER_ACTION_START_SNEAKING : PLAYER_ACTION_STOP_SNEAKING;
self->minecraft->rak_net_instance->send(*(Packet *) packet); self->minecraft->rak_net_instance->send(*(Packet *) packet);

View File

@ -6,6 +6,7 @@
#include <mods/touch/touch.h> #include <mods/touch/touch.h>
#include <mods/misc/misc.h> #include <mods/misc/misc.h>
#include <mods/options/info.h> #include <mods/options/info.h>
#include <mods/extend/extend.h>
#include "options-internal.h" #include "options-internal.h"
@ -104,12 +105,12 @@ struct info_line_position {
static info_line_position positioned_info[info_size]; static info_line_position positioned_info[info_size];
static int content_height = 0; static int content_height = 0;
static int line_button_width = 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) // First Stage (Find Max Text Width)
int info_text_width = 0; int info_text_width = 0;
for (int i = 0; i < info_size; i++) { for (int i = 0; i < info_size; i++) {
std::string text = info[i].get_text(); 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) { if (text_width > info_text_width) {
info_text_width = text_width; info_text_width = text_width;
} }
@ -170,68 +171,68 @@ void open_url(const std::string &url) {
} }
// Create VTable // Create VTable
CUSTOM_VTABLE(info_screen, Screen) { struct InfoScreen final : CustomScreen {
// Buttons // Buttons
static Button *discord; Button *discord;
static Button *back; Button *back;
static Button *info_buttons[info_size]; Button *info_buttons[info_size];
// Init // Init
vtable->init = [](Screen *self) { void init() override {
CustomScreen::init();
// Info // Info
for (int i = 0; i < info_size; i++) { for (int i = 0; i < info_size; i++) {
Button *button = touch_create_button(INFO_ID_START + i, info[i].button_text); Button *button = touch_create_button(INFO_ID_START + i, info[i].button_text);
self->rendered_buttons.push_back(button); super->rendered_buttons.push_back(button);
self->selectable_buttons.push_back(button); super->selectable_buttons.push_back(button);
info_buttons[i] = button; info_buttons[i] = button;
} }
// Discord Button // Discord Button
discord = touch_create_button(DISCORD_ID, "Discord"); discord = touch_create_button(DISCORD_ID, "Discord");
self->rendered_buttons.push_back(discord); super->rendered_buttons.push_back(discord);
self->selectable_buttons.push_back(discord); super->selectable_buttons.push_back(discord);
// Back Button // Back Button
back = touch_create_button(BACK_ID, "Back"); back = touch_create_button(BACK_ID, "Back");
self->rendered_buttons.push_back(back); super->rendered_buttons.push_back(back);
self->selectable_buttons.push_back(back); super->selectable_buttons.push_back(back);
}; }
// Handle Back // Handle Back
vtable->handleBackEvent = [](Screen *self, const bool do_nothing) { bool handleBackEvent(const bool do_nothing) override {
if (!do_nothing) { if (!do_nothing) {
OptionsScreen *screen = OptionsScreen::allocate(); OptionsScreen *screen = OptionsScreen::allocate();
ALLOC_CHECK(screen);
screen->constructor(); screen->constructor();
self->minecraft->setScreen((Screen *) screen); super->minecraft->setScreen((Screen *) screen);
} }
return true; return true;
}; }
// Rendering // Rendering
static Screen_render_t original_render = vtable->render; void render(const int x, const int y, const float param_1) override {
vtable->render = [](Screen *self, const int x, const int y, const float param_1) {
// Background // Background
misc_render_background(80, self->minecraft, 0, 0, self->width, self->height); misc_render_background(80, super->minecraft, 0, 0, super->width, super->height);
misc_render_background(32, self->minecraft, 0, content_y_offset_top, self->width, content_height); misc_render_background(32, super->minecraft, 0, content_y_offset_top, super->width, content_height);
// Call Original Method // Call Original Method
original_render(self, x, y, param_1); CustomScreen::render(x, y, param_1);
// Title // Title
std::string title = "Reborn Information"; 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 // Info Text
for (int i = 0; i < info_size; i++) { for (int i = 0; i < info_size; i++) {
std::string text = info[i].get_text(); 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 // Positioning
vtable->setupPositions = [](Screen *self) { void setupPositions() override {
CustomScreen::setupPositions();
// Height/Width // Height/Width
constexpr int width = 120; constexpr int width = 120;
discord->width = back->width = width; discord->width = back->width = width;
discord->height = back->height = line_button_height; discord->height = back->height = line_button_height;
// X/Y // X/Y
discord->y = back->y = self->height - bottom_padding - line_button_height; discord->y = back->y = super->height - bottom_padding - line_button_height;
discord->x = (self->width / 2) - inner_padding - width; discord->x = (super->width / 2) - inner_padding - width;
back->x = (self->width / 2) + inner_padding; back->x = (super->width / 2) + inner_padding;
// Info // 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++) { for (int i = 0; i < info_size; i++) {
Button *button = info_buttons[i]; Button *button = info_buttons[i];
button->width = line_button_width; button->width = line_button_width;
@ -239,18 +240,18 @@ CUSTOM_VTABLE(info_screen, Screen) {
button->x = positioned_info[i].button.x; button->x = positioned_info[i].button.x;
button->y = positioned_info[i].button.y; button->y = positioned_info[i].button.y;
} }
}; }
// Cleanup // Cleanup
vtable->removed = [](Screen *self) { ~InfoScreen() override {
for (Button *button : self->rendered_buttons) { for (Button *button : super->rendered_buttons) {
button->destructor_deleting(); button->destructor_deleting();
} }
}; }
// Handle Button Click // Handle Button Click
vtable->buttonClicked = [](Screen *self, Button *button) { void buttonClicked(Button *button) override {
if (button->id == BACK_ID) { if (button->id == BACK_ID) {
// Back // Back
self->handleBackEvent(false); super->handleBackEvent(false);
} else if (button->id == DISCORD_ID) { } else if (button->id == DISCORD_ID) {
// Open Discord Invite // Open Discord Invite
open_url(MCPI_DISCORD_INVITE); open_url(MCPI_DISCORD_INVITE);
@ -258,20 +259,13 @@ CUSTOM_VTABLE(info_screen, Screen) {
// Open Info URL // Open Info URL
const int i = button->id - INFO_ID_START; const int i = button->id - INFO_ID_START;
open_url(info[i].button_url); open_url(info[i].button_url);
} else {
CustomScreen::buttonClicked(button);
} }
}; }
} };
// Create Screen // Create Screen
Screen *_create_options_info_screen() { Screen *_create_options_info_screen() {
// Allocate return extend_struct<Screen, InfoScreen>();
Screen *screen = Screen::allocate();
ALLOC_CHECK(screen);
screen->constructor();
// Set VTable
screen->vtable = get_info_screen_vtable();
// Return
return screen;
} }

View File

@ -5,10 +5,10 @@
// PolygonQuad // PolygonQuad
Vec3 vector_to(const Vec3 &a, const Vec3 &b) { 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) { 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) { static void PolygonQuad_render_injection(PolygonQuad_render_t original, PolygonQuad *self, Tesselator &t, const float scale, const int buffer) {
// Set Normal // Set Normal

View File

@ -1,25 +1,29 @@
#include <mods/text-input-box/TextInputScreen.h> #include <mods/text-input-box/TextInputScreen.h>
// VTable // 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++) { for (int i = 0; i < int(m_textInputs->size()); i++) {
TextInputBox *textInput = (*m_textInputs)[i]; TextInputBox *textInput = (*m_textInputs)[i];
textInput->keyPressed(key); 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++) { for (int i = 0; i < int(m_textInputs->size()); i++) {
TextInputBox *textInput = (*m_textInputs)[i]; TextInputBox *textInput = (*m_textInputs)[i];
textInput->charPressed(key); 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++) { for (int i = 0; i < int(m_textInputs->size()); i++) {
TextInputBox *textInput = (*m_textInputs)[i]; TextInputBox *textInput = (*m_textInputs)[i];
textInput->onClick(x, y); 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++) { for (int i = 0; i < int(m_textInputs->size()); i++) {
TextInputBox *textInput = (*m_textInputs)[i]; TextInputBox *textInput = (*m_textInputs)[i];
textInput->tick(); textInput->tick();
@ -27,8 +31,9 @@ void TextInputScreen::render(__attribute__((unused)) int x, __attribute__((unuse
} }
} }
void TextInputScreen::init() { void TextInputScreen::init() {
CustomScreen::init();
m_textInputs = new std::vector<TextInputBox *>; m_textInputs = new std::vector<TextInputBox *>;
} }
void TextInputScreen::removed() const { TextInputScreen::~TextInputScreen() {
delete m_textInputs; delete m_textInputs;
} }

View File

@ -1,6 +1,7 @@
#include <cmath> #include <cmath>
#include <libreborn/libreborn.h> #include <libreborn/libreborn.h>
#include <mods/extend/extend.h>
#include <symbols/minecraft.h> #include <symbols/minecraft.h>
#include "textures-internal.h" #include "textures-internal.h"
@ -8,16 +9,70 @@
// Lava texture code was originally decompiled by @iProgramMC as part of ReMinecraftPE. // Lava texture code was originally decompiled by @iProgramMC as part of ReMinecraftPE.
// See: https://github.com/ReMinecraftPE/mcpe // See: https://github.com/ReMinecraftPE/mcpe
// Structures // LavaTexture
EXTEND_STRUCT(LavaTexture, DynamicTexture, struct { struct LavaTexture final : CustomDynamicTexture {
int field_14; int field_14;
int field_18; int field_18;
float m_data1[256]; float m_data1[256];
float m_data2[256]; float m_data2[256];
float m_data3[256]; float m_data3[256];
float m_data4[256]; float m_data4[256];
}); LavaTexture(): CustomDynamicTexture(Tile::lava->texture) {
EXTEND_STRUCT(LavaSideTexture, DynamicTexture, struct { 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<DynamicTexture, LavaTexture>();
}
// LavaSideTexture
struct LavaSideTexture final : CustomDynamicTexture {
int field_14; int field_14;
int field_18; int field_18;
int field_1C; int field_1C;
@ -25,81 +80,20 @@ EXTEND_STRUCT(LavaSideTexture, DynamicTexture, struct {
float m_data2[256]; float m_data2[256];
float m_data3[256]; float m_data3[256];
float m_data4[256]; float m_data4[256];
}); LavaSideTexture(): CustomDynamicTexture(Tile::lava->texture + 1) {
EXTEND_STRUCT(FireTexture, DynamicTexture, struct { field_14 = 0;
float m_data1[320]; field_18 = 0;
float m_data2[320]; field_1C = 0;
Random *m_random; super->texture_size = 2;
});
// 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);
for (int i = 0; i < 256; i++) { for (int i = 0; i < 256; i++) {
float x1 = self->data.m_data1[i] * 2.0f; m_data1[i] = 0.0f;
if (x1 > 1.0f) { m_data2[i] = 0.0f;
x1 = 1.0f; m_data3[i] = 0.0f;
} m_data4[i] = 0.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;
} }
};
}
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 void tick() override {
return (DynamicTexture *) texture; field_1C++;
}
// LavaSideTexture
CUSTOM_VTABLE(lava_side_texture, DynamicTexture) {
vtable->tick = [](DynamicTexture *super) {
LavaSideTexture *self = (LavaSideTexture *) super;
self->data.field_1C++;
for (int x = 0; x < 16; x++) { for (int x = 0; x < 16; x++) {
for (int y = 0; y < 16; y++) { for (int y = 0; y < 16; y++) {
float f = 0.0F; float f = 0.0F;
@ -109,120 +103,98 @@ CUSTOM_VTABLE(lava_side_texture, DynamicTexture) {
for (int by = y - 1; by <= y + 1; by++) { for (int by = y - 1; by <= y + 1; by++) {
const int k2 = (bx + ay) & 0xf; const int k2 = (bx + ay) & 0xf;
const int i3 = (by + ax) & 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; 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;
self->data.m_data3[x + y * 16] += self->data.m_data4[x + y * 16] * 0.01f; m_data3[x + y * 16] += m_data4[x + y * 16] * 0.01f;
if (self->data.m_data3[x + y * 16] < 0.0f) { if (m_data3[x + y * 16] < 0.0f) {
self->data.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) { 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++) { 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) { if (x1 > 1.0f) {
x1 = 1.0f; x1 = 1.0f;
} }
if (x1 < 0.0f) { if (x1 < 0.0f) {
x1 = 0.0f; x1 = 0.0f;
} }
self->super()->pixels[i * 4 + 0] = int(155.0f + 100.0f * x1); super->pixels[i * 4 + 0] = int(155.0f + 100.0f * x1);
self->super()->pixels[i * 4 + 1] = int(255.0f * x1 * x1); super->pixels[i * 4 + 1] = int(255.0f * x1 * x1);
self->super()->pixels[i * 4 + 2] = int(128.0f * x1 * x1 * x1 * x1); super->pixels[i * 4 + 2] = int(128.0f * x1 * x1 * x1 * x1);
self->super()->pixels[i * 4 + 3] = 255; super->pixels[i * 4 + 3] = 255;
} }
}; }
} };
static DynamicTexture *create_lava_side_texture() { static DynamicTexture *create_lava_side_texture() {
// Construct return extend_struct<DynamicTexture, LavaSideTexture>();
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;
} }
// FireTexture // FireTexture
CUSTOM_VTABLE(fire_texture, DynamicTexture) { struct FireTexture final : CustomDynamicTexture {
vtable->tick = [](DynamicTexture *super) { float m_data1[320];
FireTexture *self = (FireTexture *) super; 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 i = 0; i < 16; i++) {
for (int j = 0; j < 20; j++) { for (int j = 0; j < 20; j++) {
int l = 18; 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 i1 = i - 1; i1 <= i + 1; i1++) {
for (int k1 = j; k1 <= j + 1; k1++) { for (int k1 = j; k1 <= j + 1; k1++) {
const int i2 = i1; const int i2 = i1;
const int k2 = k1; const int k2 = k1;
if (i2 >= 0 && k2 >= 0 && i2 < 16 && k2 < 20) if (i2 >= 0 && k2 >= 0 && i2 < 16 && k2 < 20)
{ {
f1 += self->data.m_data1[i2 + k2 * 16]; f1 += m_data1[i2 + k2 * 16];
} }
l++; l++;
} }
} }
self->data.m_data2[i + j * 16] = f1 / 25.2f; m_data2[i + j * 16] = f1 / 25.2f;
if (j >= 19) { if (j >= 19) {
union { union {
uint32_t x; uint32_t x;
uint8_t b[4]; uint8_t b[4];
} a = {}; } a = {};
a.x = self->data.m_random->genrand_int32(); a.x = 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)); 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++) { 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) { if (x > 1.0f) {
x = 1.0f; x = 1.0f;
} }
if (x < 0.0f) { if (x < 0.0f) {
x = 0.0f; x = 0.0f;
} }
self->super()->pixels[4 * i + 0] = int(x * 155.0f + 100.0f); super->pixels[4 * i + 0] = int(x * 155.0f + 100.0f);
self->super()->pixels[4 * i + 1] = int(x * x * 255.0f); 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); 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 + 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<DynamicTexture, FireTexture>(a2);
} }
// Add Textures // Add Textures

View File

@ -7,6 +7,7 @@
#include <mods/touch/touch.h> #include <mods/touch/touch.h>
#include <mods/options/info.h> #include <mods/options/info.h>
#include <mods/misc/misc.h> #include <mods/misc/misc.h>
#include <mods/extend/extend.h>
#include "title-screen-internal.h" #include "title-screen-internal.h"
@ -75,61 +76,55 @@ static void position_screen(const int width, const int height) {
} }
// Welcome Screen // Welcome Screen
CUSTOM_VTABLE(welcome_screen, Screen) { struct WelcomeScreen final : CustomScreen {
// Init // Init
vtable->init = [](__attribute__((unused)) Screen *self) { void init() override {
CustomScreen::init();
// Buttons // Buttons
getting_started = touch_create_button(0, "Getting Started"); getting_started = touch_create_button(0, "Getting Started");
changelog = touch_create_button(1, "Changelog"); changelog = touch_create_button(1, "Changelog");
proceed = touch_create_button(2, "Proceed"); proceed = touch_create_button(2, "Proceed");
for (Button *button : {getting_started, changelog, proceed}) { for (Button *button : {getting_started, changelog, proceed}) {
self->rendered_buttons.push_back(button); super->rendered_buttons.push_back(button);
self->selectable_buttons.push_back(button); super->selectable_buttons.push_back(button);
} }
}; }
// Rendering // Rendering
static Screen_render_t original_render = vtable->render; void render(const int x, const int y, const float param_1) override {
vtable->render = [](Screen *self, const int x, const int y, const float param_1) {
// Background // Background
self->renderBackground(); super->renderBackground();
// Call Original Method // Call Original Method
original_render(self, x, y, param_1); CustomScreen::render(x, y, param_1);
// Text // Text
self->drawCenteredString(self->font, line1, self->width / 2, text_y, 0xFFFFFFFF); super->drawCenteredString(super->font, line1, super->width / 2, text_y, 0xFFFFFFFF);
}; }
// Positioning // Positioning
vtable->setupPositions = [](Screen *self) { void setupPositions() override {
position_screen(self->width, self->height); CustomScreen::setupPositions();
}; position_screen(super->width, super->height);
}
// Cleanup // Cleanup
vtable->removed = [](Screen *self) { ~WelcomeScreen() override {
for (Button *button : self->rendered_buttons) { for (Button *button : super->rendered_buttons) {
button->destructor_deleting(); button->destructor_deleting();
} }
}; }
// Handle Button Click // Handle Button Click
vtable->buttonClicked = [](Screen *self, Button *button) { void buttonClicked(Button *button) override {
if (button == getting_started) { if (button == getting_started) {
open_url(MCPI_DOCUMENTATION "GETTING_STARTED.md"); open_url(MCPI_DOCUMENTATION "GETTING_STARTED.md");
} else if (button == changelog) { } else if (button == changelog) {
open_url(MCPI_DOCUMENTATION CHANGELOG_FILE); open_url(MCPI_DOCUMENTATION CHANGELOG_FILE);
} else if (button == proceed) { } else if (button == proceed) {
mark_welcome_as_shown(); 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() { static Screen *create_welcome_screen() {
// Allocate return extend_struct<Screen, WelcomeScreen>();
Screen *screen = Screen::allocate();
ALLOC_CHECK(screen);
screen->constructor();
// Set VTable
screen->vtable = get_welcome_screen_vtable();
// Return
return screen;
} }
// Show Welcome Screen // Show Welcome Screen