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
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

View File

@ -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

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 <mods/text-input-box/TextInputBox.h>
#include <mods/extend/extend.h>
struct TextInputScreen {
struct TextInputScreen : CustomScreen {
std::vector<TextInputBox *> *m_textInputs = nullptr;
template <typename T>
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<decltype(args)>(args)...); \
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;
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;
};

View File

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

View File

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

View File

@ -5,6 +5,7 @@
#include <mods/init/init.h>
#include <mods/misc/misc.h>
#include <mods/bucket/bucket.h>
#include <mods/extend/extend.h>
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

View File

@ -15,81 +15,66 @@ static std::vector<std::string> &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<ChatScreen>(vtable);
// Init
static std::vector<std::string> local_history = {};
static Screen_init_t original_init = vtable->init;
vtable->init = [](Screen *super) {
original_init(super);
ChatScreen *self = (ChatScreen *) super;
std::vector<std::string> 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<Screen, ChatScreen>();
}
// Init

View File

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

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 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<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
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<Screen, CreateWorldScreen>();
}
// 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);

View File

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

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

View File

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

View File

@ -6,6 +6,7 @@
#include <mods/touch/touch.h>
#include <mods/misc/misc.h>
#include <mods/options/info.h>
#include <mods/extend/extend.h>
#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<Screen, InfoScreen>();
}

View File

@ -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

View File

@ -1,25 +1,29 @@
#include <mods/text-input-box/TextInputScreen.h>
// 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<TextInputBox *>;
}
void TextInputScreen::removed() const {
TextInputScreen::~TextInputScreen() {
delete m_textInputs;
}

View File

@ -1,6 +1,7 @@
#include <cmath>
#include <libreborn/libreborn.h>
#include <mods/extend/extend.h>
#include <symbols/minecraft.h>
#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<DynamicTexture, LavaTexture>();
}
// LavaSideTexture
struct LavaSideTexture final : CustomDynamicTexture {
int field_14;
int field_18;
int field_1C;
@ -25,17 +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;
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++) {
m_data1[i] = 0.0f;
m_data2[i] = 0.0f;
m_data3[i] = 0.0f;
m_data4[i] = 0.0f;
}
}
void tick() override {
field_1C++;
for (int x = 0; x < 16; x++) {
for (int y = 0; y < 16; y++) {
float f = 0.0F;
@ -45,184 +103,98 @@ CUSTOM_VTABLE(lava_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] * 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;
}
};
}
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++;
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];
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;
}
}
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++) {
float x1 = self->data.m_data1[(i - 16 * (self->data.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;
}
};
}
};
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<DynamicTexture, LavaSideTexture>();
}
// 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;
return extend_struct<DynamicTexture, FireTexture>(a2);
}
// Add Textures

View File

@ -7,6 +7,7 @@
#include <mods/touch/touch.h>
#include <mods/options/info.h>
#include <mods/misc/misc.h>
#include <mods/extend/extend.h>
#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<Screen, WelcomeScreen>();
}
// Show Welcome Screen