Fancy New API!
This commit is contained in:
parent
a6dad72778
commit
dd25805af9
2
dependencies/symbol-processor/src
vendored
2
dependencies/symbol-processor/src
vendored
@ -1 +1 @@
|
||||
Subproject commit f72c4f0567c62897d74c734819c11705df0bf4ee
|
||||
Subproject commit 308a36b4ba7f4b1b9917967f66df07860e7d0c56
|
@ -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
|
||||
|
@ -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
|
||||
|
9
mods/include/mods/extend/DynamicTexture.h
Normal file
9
mods/include/mods/extend/DynamicTexture.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
// Custom Screen
|
||||
CREATE_HELPER(DynamicTexture)
|
||||
// Functions
|
||||
virtual void tick() = 0;
|
||||
};
|
18
mods/include/mods/extend/Screen.h
Normal file
18
mods/include/mods/extend/Screen.h
Normal 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);
|
||||
};
|
69
mods/include/mods/extend/extend.h
Normal file
69
mods/include/mods/extend/extend.h
Normal 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
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
6
mods/src/extend/DynamicTexture.cpp
Normal file
6
mods/src/extend/DynamicTexture.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
#include "extend-internal.h"
|
||||
|
||||
// VTable
|
||||
SETUP_VTABLE(DynamicTexture)
|
||||
PATCH_VTABLE(tick);
|
||||
}
|
2
mods/src/extend/README.md
Normal file
2
mods/src/extend/README.md
Normal file
@ -0,0 +1,2 @@
|
||||
# `extend` Mod
|
||||
This mod allows easily extending various Minecraft structures.
|
47
mods/src/extend/Screen.cpp
Normal file
47
mods/src/extend/Screen.cpp
Normal 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);
|
||||
}
|
25
mods/src/extend/extend-internal.h
Normal file
25
mods/src/extend/extend-internal.h
Normal 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);
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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>();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,81 +80,20 @@ EXTEND_STRUCT(LavaSideTexture, DynamicTexture, struct {
|
||||
float m_data2[256];
|
||||
float m_data3[256];
|
||||
float m_data4[256];
|
||||
});
|
||||
EXTEND_STRUCT(FireTexture, DynamicTexture, struct {
|
||||
float m_data1[320];
|
||||
float m_data2[320];
|
||||
Random *m_random;
|
||||
});
|
||||
|
||||
// LavaTexture
|
||||
CUSTOM_VTABLE(lava_texture, DynamicTexture) {
|
||||
vtable->tick = [](DynamicTexture *super) {
|
||||
LavaTexture *self = (LavaTexture *) super;
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int y = 0; y < 16; y++) {
|
||||
float f = 0.0F;
|
||||
const int ax = int(Mth::sin((float(x) * float(M_PI) * 2) / 16.0f) * 1.2f);
|
||||
const int ay = int(Mth::sin((float(y) * float(M_PI) * 2) / 16.0f) * 1.2f);
|
||||
for (int bx = x - 1; bx <= x + 1; bx++) {
|
||||
for (int by = y - 1; by <= y + 1; by++) {
|
||||
const int k2 = (bx + ay) & 0xf;
|
||||
const int i3 = (by + ax) & 0xf;
|
||||
f += self->data.m_data1[k2 + i3 * 16];
|
||||
}
|
||||
}
|
||||
self->data.m_data2[x + y * 16] = f / 10.0f + ((self->data.m_data3[(x & 0xf) + ((y + 0) & 0xf) * 16] + self->data.m_data3[((x + 1) & 0xf) + (y & 0xf) * 16] + self->data.m_data3[((x + 1) & 0xf) + ((y + 1) & 0xf) * 16] + self->data.m_data3[(x & 0xf) + ((y + 1) & 0xf) * 16]) * 0.25f) * 0.8f;
|
||||
self->data.m_data3[x + y * 16] += self->data.m_data4[x + y * 16] * 0.01f;
|
||||
if (self->data.m_data3[x + y * 16] < 0.0f) {
|
||||
self->data.m_data3[x + y * 16] = 0.0f;
|
||||
}
|
||||
self->data.m_data4[x + y * 16] -= 0.06f;
|
||||
if (Mth::random() < 0.005f) {
|
||||
self->data.m_data4[x + y * 16] = 1.5f;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::swap(self->data.m_data1, self->data.m_data2);
|
||||
LavaSideTexture(): CustomDynamicTexture(Tile::lava->texture + 1) {
|
||||
field_14 = 0;
|
||||
field_18 = 0;
|
||||
field_1C = 0;
|
||||
super->texture_size = 2;
|
||||
for (int i = 0; i < 256; i++) {
|
||||
float x1 = self->data.m_data1[i] * 2.0f;
|
||||
if (x1 > 1.0f) {
|
||||
x1 = 1.0f;
|
||||
}
|
||||
if (x1 < 0.0f) {
|
||||
x1 = 0.0f;
|
||||
}
|
||||
self->super()->pixels[i * 4 + 0] = int(155.0f + 100.0f * x1);
|
||||
self->super()->pixels[i * 4 + 1] = int(255.0f * x1 * x1);
|
||||
self->super()->pixels[i * 4 + 2] = int(128.0f * x1 * x1 * x1 * x1);
|
||||
self->super()->pixels[i * 4 + 3] = 255;
|
||||
m_data1[i] = 0.0f;
|
||||
m_data2[i] = 0.0f;
|
||||
m_data3[i] = 0.0f;
|
||||
m_data4[i] = 0.0f;
|
||||
}
|
||||
};
|
||||
}
|
||||
static DynamicTexture *create_lava_texture() {
|
||||
// Construct
|
||||
LavaTexture *texture = new LavaTexture;
|
||||
ALLOC_CHECK(texture);
|
||||
texture->super()->constructor(Tile::lava->texture);
|
||||
// Set VTable
|
||||
texture->super()->vtable = get_lava_texture_vtable();
|
||||
// Setup
|
||||
texture->data.field_14 = 0;
|
||||
texture->data.field_18 = 0;
|
||||
for (int i = 0; i < 256; i++) {
|
||||
texture->data.m_data1[i] = 0.0f;
|
||||
texture->data.m_data2[i] = 0.0f;
|
||||
texture->data.m_data3[i] = 0.0f;
|
||||
texture->data.m_data4[i] = 0.0f;
|
||||
}
|
||||
// Return
|
||||
return (DynamicTexture *) texture;
|
||||
}
|
||||
|
||||
// LavaSideTexture
|
||||
CUSTOM_VTABLE(lava_side_texture, DynamicTexture) {
|
||||
vtable->tick = [](DynamicTexture *super) {
|
||||
LavaSideTexture *self = (LavaSideTexture *) super;
|
||||
self->data.field_1C++;
|
||||
void tick() override {
|
||||
field_1C++;
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int y = 0; y < 16; y++) {
|
||||
float f = 0.0F;
|
||||
@ -109,120 +103,98 @@ CUSTOM_VTABLE(lava_side_texture, DynamicTexture) {
|
||||
for (int by = y - 1; by <= y + 1; by++) {
|
||||
const int k2 = (bx + ay) & 0xf;
|
||||
const int i3 = (by + ax) & 0xf;
|
||||
f += self->data.m_data1[k2 + i3 * 16];
|
||||
f += m_data1[k2 + i3 * 16];
|
||||
}
|
||||
}
|
||||
self->data.m_data2[x + y * 16] = f / 10.0f + ((self->data.m_data3[(x & 0xf) + ((y + 0) & 0xf) * 16] + self->data.m_data3[((x + 1) & 0xf) + (y & 0xf) * 16] + self->data.m_data3[((x + 1) & 0xf) + ((y + 1) & 0xf) * 16] + self->data.m_data3[(x & 0xf) + ((y + 1) & 0xf) * 16]) * 0.25f) * 0.8f;
|
||||
self->data.m_data3[x + y * 16] += self->data.m_data4[x + y * 16] * 0.01f;
|
||||
if (self->data.m_data3[x + y * 16] < 0.0f) {
|
||||
self->data.m_data3[x + y * 16] = 0.0f;
|
||||
m_data2[x + y * 16] = f / 10.0f + ((m_data3[(x & 0xf) + ((y + 0) & 0xf) * 16] + m_data3[((x + 1) & 0xf) + (y & 0xf) * 16] + m_data3[((x + 1) & 0xf) + ((y + 1) & 0xf) * 16] + m_data3[(x & 0xf) + ((y + 1) & 0xf) * 16]) * 0.25f) * 0.8f;
|
||||
m_data3[x + y * 16] += m_data4[x + y * 16] * 0.01f;
|
||||
if (m_data3[x + y * 16] < 0.0f) {
|
||||
m_data3[x + y * 16] = 0.0f;
|
||||
}
|
||||
self->data.m_data4[x + y * 16] -= 0.06f;
|
||||
m_data4[x + y * 16] -= 0.06f;
|
||||
if (Mth::random() < 0.005f) {
|
||||
self->data.m_data4[x + y * 16] = 1.5f;
|
||||
m_data4[x + y * 16] = 1.5f;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::swap(self->data.m_data1, self->data.m_data2);
|
||||
std::swap(m_data1, m_data2);
|
||||
for (int i = 0; i < 256; i++) {
|
||||
float x1 = self->data.m_data1[(i - 16 * (self->data.field_1C / 3)) & 0xFF] * 2.0f;
|
||||
float x1 = m_data1[(i - 16 * (field_1C / 3)) & 0xFF] * 2.0f;
|
||||
if (x1 > 1.0f) {
|
||||
x1 = 1.0f;
|
||||
}
|
||||
if (x1 < 0.0f) {
|
||||
x1 = 0.0f;
|
||||
}
|
||||
self->super()->pixels[i * 4 + 0] = int(155.0f + 100.0f * x1);
|
||||
self->super()->pixels[i * 4 + 1] = int(255.0f * x1 * x1);
|
||||
self->super()->pixels[i * 4 + 2] = int(128.0f * x1 * x1 * x1 * x1);
|
||||
self->super()->pixels[i * 4 + 3] = 255;
|
||||
super->pixels[i * 4 + 0] = int(155.0f + 100.0f * x1);
|
||||
super->pixels[i * 4 + 1] = int(255.0f * x1 * x1);
|
||||
super->pixels[i * 4 + 2] = int(128.0f * x1 * x1 * x1 * x1);
|
||||
super->pixels[i * 4 + 3] = 255;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
static DynamicTexture *create_lava_side_texture() {
|
||||
// Construct
|
||||
LavaSideTexture *texture = new LavaSideTexture;
|
||||
ALLOC_CHECK(texture);
|
||||
texture->super()->constructor(Tile::lava->texture + 1);
|
||||
// Set VTable
|
||||
texture->super()->vtable = get_lava_side_texture_vtable();
|
||||
// Setup
|
||||
texture->data.field_14 = 0;
|
||||
texture->data.field_18 = 0;
|
||||
texture->data.field_1C = 0;
|
||||
texture->super()->texture_size = 2;
|
||||
for (int i = 0; i < 256; i++) {
|
||||
texture->data.m_data1[i] = 0.0f;
|
||||
texture->data.m_data2[i] = 0.0f;
|
||||
texture->data.m_data3[i] = 0.0f;
|
||||
texture->data.m_data4[i] = 0.0f;
|
||||
}
|
||||
// Return
|
||||
return (DynamicTexture *) texture;
|
||||
return extend_struct<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;
|
||||
};
|
||||
static DynamicTexture *create_fire_texture(const int a2) {
|
||||
return extend_struct<DynamicTexture, FireTexture>(a2);
|
||||
}
|
||||
|
||||
// Add Textures
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user