minecraft.h/.cpp Changes

This commit is contained in:
TheBrokenRail 2024-07-14 05:06:27 -04:00
parent 688bee1aaa
commit d2b07f7661
17 changed files with 84 additions and 112 deletions

View File

@ -59,7 +59,7 @@ string(CONCAT COMPILE_FLAGS_SETUP
# C Standard # C Standard
"add_definitions(-D_GNU_SOURCE)\n" "add_definitions(-D_GNU_SOURCE)\n"
"set(CMAKE_C_STANDARD 99)\n" "set(CMAKE_C_STANDARD 99)\n"
"set(CMAKE_CXX_STANDARD 11)\n" "set(CMAKE_CXX_STANDARD 20)\n"
# Skip RPath # Skip RPath
"set(CMAKE_SKIP_BUILD_RPATH TRUE)" "set(CMAKE_SKIP_BUILD_RPATH TRUE)"

@ -1 +1 @@
Subproject commit 6098f57b03cae72668c6d2c1624a3a3f01d13fa9 Subproject commit 11342dbb78b8897ddf75fb4c1b72d40915fab245

View File

@ -5,82 +5,48 @@
#if defined(REBORN_HAS_PATCH_CODE) && defined(__cplusplus) #if defined(REBORN_HAS_PATCH_CODE) && defined(__cplusplus)
#include <string> #include <string>
#include <functional>
// Init // Init
void reborn_init_patch(); void reborn_init_patch();
// Replace Call Located At start With A Call To target // Replace Call Located At start With A Call To target
void _overwrite_call(const char *file, int line, void *start, void *target); void overwrite_call(void *start, void *target);
#define overwrite_call(...) \
_overwrite_call(__FILE__, __LINE__, __VA_ARGS__)
// Replace All Calls To Method start With target // Replace All Calls To Method start With target
void *_overwrite_calls_manual(const char *file, int line, void *start, void *target); void *overwrite_calls_manual(void *start, void *target, bool allow_no_callsites = false);
#define overwrite_calls_manual(...) \ template <typename T>
_overwrite_calls_manual(__FILE__, __LINE__, __VA_ARGS__) void overwrite_calls(T &target, typename T::overwrite_type replacement) {
template <typename overwrite_t> DEBUG("Overwriting Method: %s", target.get_name());
void _overwrite_calls(const char *file, int line, std::string (*set_overwrite)(const overwrite_t &, const std::function<void *(void *, void *)> &), const overwrite_t &target) { if (!target.overwrite(replacement)) {
std::string ret = set_overwrite(target, [&file, &line](void *start, void *target2) { ERR("Unable To Overwrite Method: %s", target.get_name());
return _overwrite_calls_manual(file, line, start, target2);
});
if (!ret.empty()) {
ERR("%s", ret.c_str());
} }
} }
#define overwrite_calls(start, ...) \
_overwrite_calls< \ // Thunk Enabler
__overwrite_##start##_t \ void *reborn_thunk_enabler(void *target, void *thunk);
>( \
__FILE__, __LINE__, \
__set_overwrite_for_##start, \
__VA_ARGS__ \
)
// Replace All Calls To start With target Within [to, from) // Replace All Calls To start With target Within [to, from)
void _overwrite_calls_within_manual(const char *file, int line, void *from, void *to, void *start, void *target); void overwrite_calls_within_manual(void *from, void *to, void *start, void *target);
#define overwrite_calls_within_manual(...) \ template <typename T>
_overwrite_calls_within(__FILE__, __LINE__, __VA_ARGS__) void _overwrite_calls_within(void *from, void *to, const T &start, typename T::ptr_type target) {
template <typename start_t> overwrite_calls_within_manual(from, to, (void *) start, (void *) target);
void _overwrite_calls_within(const char *file, int line, void *from, void *to, start_t start, start_t target) {
_overwrite_calls_within_manual(file, line, from, to, (void *) start, (void *) target);
} }
#define overwrite_calls_within(from, to, start, ...) \
_overwrite_calls_within< \
__raw_##start##_t \
>( \
__FILE__, __LINE__, \
from, to, \
start, \
__VA_ARGS__ \
)
// Get Target Address From BL Instruction // Get Target Address From BL Instruction
void *extract_from_bl_instruction(unsigned char *from); void *extract_from_bl_instruction(unsigned char *from);
// Patch Instruction // Patch Instruction
void _patch(const char *file, int line, void *start, unsigned char patch[4]); void patch(void *start, unsigned char patch[4]);
#define patch(...) \
_patch(__FILE__, __LINE__, __VA_ARGS__)
// Patch 4 Bytes Of Data // Patch 4 Bytes Of Data
void _patch_address(const char *file, int line, void *start, void *target); void patch_address(void *start, void *target);
#define patch_address(...) \
_patch_address(__FILE__, __LINE__, __VA_ARGS__)
// Patch VTable Entry // Patch VTable Entry
// This does not affect sub-classes. // This does not affect subclasses.
template <typename start_t> template <typename T>
void _patch_vtable(const char *file, int line, start_t *start, start_t target) { void patch_vtable(const T &start, typename T::ptr_type target) {
_patch_address(file, line, (void *) start, (void *) target); DEBUG("Patching VTable: %s", start.get_name());
patch_address((void *) start.get_vtable_addr(), (void *) target);
} }
#define patch_vtable(start, ...) \
_patch_vtable< \
__raw_##start##_t \
>( \
__FILE__, __LINE__, \
start##_vtable_addr, \
__VA_ARGS__ \
)
#endif #endif

View File

@ -84,7 +84,7 @@ void ensure_directory(const char *path);
/* Allocate VTable */ \ /* Allocate VTable */ \
if (vtable == NULL) { \ if (vtable == NULL) { \
/* Init */ \ /* Init */ \
vtable = dup_##parent##_vtable(parent##_vtable_base); \ vtable = dup_vtable(parent##_vtable_base); \
ALLOC_CHECK(vtable); \ ALLOC_CHECK(vtable); \
/* Setup */ \ /* Setup */ \
_setup_##name##_vtable(vtable); \ _setup_##name##_vtable(vtable); \

View File

@ -5,28 +5,28 @@
// Limit To 512 overwrite_calls() Uses // Limit To 512 overwrite_calls() Uses
#define CODE_BLOCK_SIZE 4096 #define CODE_BLOCK_SIZE 4096
static unsigned char *code_block = NULL; static unsigned char *code_block = nullptr;
#define CODE_SIZE 8 #define CODE_SIZE 8
static int code_block_remaining = CODE_BLOCK_SIZE; static int code_block_remaining = CODE_BLOCK_SIZE;
// Create Long Overwrite At Current Position // Create Long Overwrite At Current Position
static void long_overwrite(void *start, void *target) { static void long_overwrite(void *start, void *target) {
unsigned char patch_data[4] = {0x04, 0xf0, 0x1f, 0xe5}; // "ldr pc, [pc, #-0x4]" unsigned char patch_data[4] = {0x04, 0xf0, 0x1f, 0xe5}; // "ldr pc, [pc, #-0x4]"
_patch(NULL, -1, start, patch_data); patch(start, patch_data);
_patch_address(NULL, -1, (void *) (((unsigned char *) start) + 4), target); patch_address((void *) (((unsigned char *) start) + 4), target);
} }
void *update_code_block(void *target) { void *update_code_block(void *target) {
// BL Instructions can only access a limited portion of memory. // BL Instructions can only access a limited portion of memory.
// So this allocates memory closer to the original instruction, // So this allocates memory closer to the original instruction,
// that when run, will jump into the actual target. // that when run, will jump into the actual target.
if (code_block == NULL) { if (code_block == nullptr) {
code_block = (unsigned char *) mmap((void *) 0x200000, CODE_BLOCK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); code_block = (unsigned char *) mmap((void *) 0x200000, CODE_BLOCK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (code_block == MAP_FAILED) { if (code_block == MAP_FAILED) {
ERR("Unable To Allocate Code Block: %s", strerror(errno)); ERR("Unable To Allocate Code Block: %s", strerror(errno));
} }
DEBUG("Code Block Allocated At: 0x%08x", (uint32_t) code_block); DEBUG("Code Block Allocated At: 0x%08x", (uint32_t) code_block);
// Store Segment // Store Segment
segment_data data; segment_data data = {};
data.start = code_block; data.start = code_block;
data.end = (void *) (((uintptr_t) code_block) + CODE_BLOCK_SIZE); data.end = (void *) (((uintptr_t) code_block) + CODE_BLOCK_SIZE);
data.is_executable = true; data.is_executable = true;

View File

@ -10,20 +10,20 @@
#include "patch-internal.h" #include "patch-internal.h"
// Overwrite Specific B(L) Instruction // Overwrite Specific B(L) Instruction
static void _overwrite_call_internal(const char *file, int line, void *start, void *target, int use_b_instruction) { static void _overwrite_call_internal(void *start, void *target, const bool use_b_instruction) {
// Add New Target To Code Block // Add New Target To Code Block
void *code_block = update_code_block(target); void *code_block = update_code_block(target);
// Patch // Patch
uint32_t new_instruction = generate_bl_instruction(start, code_block, use_b_instruction); uint32_t new_instruction = generate_bl_instruction(start, code_block, use_b_instruction);
_patch(file, line, start, (unsigned char *) &new_instruction); patch(start, (unsigned char *) &new_instruction);
// Increment Code Block Position // Increment Code Block Position
increment_code_block(); increment_code_block();
} }
void _overwrite_call(const char *file, int line, void *start, void *target) { void overwrite_call(void *start, void *target) {
int use_b_instruction = ((unsigned char *) start)[3] == B_INSTRUCTION; const bool use_b_instruction = ((unsigned char *) start)[3] == B_INSTRUCTION;
_overwrite_call_internal(file, line, start, target, use_b_instruction); _overwrite_call_internal(start, target, use_b_instruction);
} }
// .rodata Information // .rodata Information
@ -38,11 +38,11 @@ void _overwrite_call(const char *file, int line, void *start, void *target) {
uint32_t *addr = (uint32_t *) i; \ uint32_t *addr = (uint32_t *) i; \
if (*addr == (uintptr_t) target) { \ if (*addr == (uintptr_t) target) { \
/* Found VTable Entry */ \ /* Found VTable Entry */ \
_patch_address(file, line, addr, replacement); \ patch_address(addr, replacement); \
found++; \ found++; \
} \ } \
} }
static int _patch_vtables(const char *file, int line, void *target, void *replacement) { static int _patch_vtables(void *target, void *replacement) {
int found = 0; int found = 0;
scan_vtables(RODATA); scan_vtables(RODATA);
scan_vtables(DATA_REL_RO); scan_vtables(DATA_REL_RO);
@ -51,11 +51,11 @@ static int _patch_vtables(const char *file, int line, void *target, void *replac
#undef scan_vtables #undef scan_vtables
// Patch Calls Within Range // Patch Calls Within Range
static int _overwrite_calls_within_internal(const char *file, int line, void *from, void *to, void *target, void *replacement) { static int _overwrite_calls_within_internal(void *from, void *to, void *target, void *replacement) {
int found = 0; int found = 0;
for (uintptr_t i = (uintptr_t) from; i < (uintptr_t) to; i = i + 4) { for (uintptr_t i = (uintptr_t) from; i < (uintptr_t) to; i = i + 4) {
unsigned char *addr = (unsigned char *) i; unsigned char *addr = (unsigned char *) i;
int use_b_instruction = addr[3] == B_INSTRUCTION; const int use_b_instruction = addr[3] == B_INSTRUCTION;
// Check If Instruction is B Or BL // Check If Instruction is B Or BL
if (addr[3] == BL_INSTRUCTION || use_b_instruction) { if (addr[3] == BL_INSTRUCTION || use_b_instruction) {
uint32_t check_instruction = generate_bl_instruction(addr, target, use_b_instruction); uint32_t check_instruction = generate_bl_instruction(addr, target, use_b_instruction);
@ -64,7 +64,7 @@ static int _overwrite_calls_within_internal(const char *file, int line, void *fr
if (addr[0] == check_instruction_array[0] && addr[1] == check_instruction_array[1] && addr[2] == check_instruction_array[2]) { if (addr[0] == check_instruction_array[0] && addr[1] == check_instruction_array[1] && addr[2] == check_instruction_array[2]) {
// Patch Instruction // Patch Instruction
uint32_t new_instruction = generate_bl_instruction(addr, replacement, use_b_instruction); uint32_t new_instruction = generate_bl_instruction(addr, replacement, use_b_instruction);
_patch(file, line, addr, (unsigned char *) &new_instruction); patch(addr, (unsigned char *) &new_instruction);
found++; found++;
} }
} }
@ -76,57 +76,54 @@ static int _overwrite_calls_within_internal(const char *file, int line, void *fr
#define TEXT_START 0xde60 #define TEXT_START 0xde60
#define TEXT_END 0x1020c0 #define TEXT_END 0x1020c0
// Overwrite All B(L) Intrusctions That Target The Specified Address // Overwrite All B(L) Intrusctions That Target The Specified Address
#define NO_CALLSITE_ERROR "(%s:%i) Unable To Find Callsites For %p" #define NO_CALLSITE_ERROR() ERR("Unable To Find Callsites")
void *_overwrite_calls_manual(const char *file, int line, void *start, void *target) { void *overwrite_calls_manual(void *start, void *target, const bool allow_no_callsites) {
// Add New Target To Code Block // Add New Target To Code Block
void *code_block = update_code_block(target); void *code_block = update_code_block(target);
// Patch Code // Patch Code
int found = _overwrite_calls_within_internal(file, line, (void *) TEXT_START, (void *) TEXT_END, start, code_block); int found = _overwrite_calls_within_internal((void *) TEXT_START, (void *) TEXT_END, start, code_block);
// Patch VTables // Patch VTables
found += _patch_vtables(file, line, start, code_block); found += _patch_vtables(start, code_block);
// Increment Code Block Position // Increment Code Block Position
increment_code_block(); increment_code_block();
// Check // Check
if (found < 1) { if (found < 1 && !allow_no_callsites) {
ERR(NO_CALLSITE_ERROR, file, line, start); NO_CALLSITE_ERROR();
} }
// Return // Return
return code_block; return code_block;
} }
void _overwrite_calls_within_manual(const char *file, int line, void *from /* inclusive */, void *to /* exclusive */, void *target, void *replacement) { void overwrite_calls_within_manual(void *from /* inclusive */, void *to /* exclusive */, void *target, void *replacement) {
// Add New Target To Code Block // Add New Target To Code Block
void *code_block = update_code_block(replacement); void *code_block = update_code_block(replacement);
// Patch // Patch
int found = _overwrite_calls_within_internal(file, line, from, to, target, code_block); const int found = _overwrite_calls_within_internal(from, to, target, code_block);
// Check // Check
if (found < 1) { if (found < 1) {
ERR(NO_CALLSITE_ERROR, file, line, target); NO_CALLSITE_ERROR();
} }
// Increment Code Block Position // Increment Code Block Position
increment_code_block(); increment_code_block();
} }
// Print Patch Debug Data
#define PATCH_PRINTF(file, line, start, str) if (file != NULL) DEBUG("(%s:%i): Patching (%p) - " str ": %02x %02x %02x %02x", file, line, start, data[0], data[1], data[2], data[3]);
// Patch Instruction // Patch Instruction
static void safe_mprotect(void *addr, size_t len, int prot) { static void safe_mprotect(void *addr, size_t len, int prot) {
long page_size = sysconf(_SC_PAGESIZE); const long page_size = sysconf(_SC_PAGESIZE);
long diff = ((uintptr_t) addr) % page_size; const long diff = uintptr_t(addr) % page_size;
void *aligned_addr = (void *) (((uintptr_t) addr) - diff); void *aligned_addr = (void *) (((uintptr_t) addr) - diff);
size_t aligned_len = len + diff; size_t aligned_len = len + diff;
int ret = mprotect(aligned_addr, aligned_len, prot); const int ret = mprotect(aligned_addr, aligned_len, prot);
if (ret == -1) { if (ret == -1) {
ERR("Unable To Set Permissions: %p: %s", addr, strerror(errno)); ERR("Unable To Set Permissions: %p: %s", addr, strerror(errno));
} }
} }
void _patch(const char *file, int line, void *start, unsigned char patch[4]) { void patch(void *start, unsigned char patch[4]) {
if (((uint32_t) start) % 4 != 0) { if (((uint32_t) start) % 4 != 0) {
ERR("Invalid Address: %p", start); ERR("Invalid Address: %p", start);
} }
@ -142,14 +139,12 @@ void _patch(const char *file, int line, void *start, unsigned char patch[4]) {
} }
// Allow Writing To Code Memory // Allow Writing To Code Memory
uint32_t size = 4; const uint32_t size = 4;
safe_mprotect(start, size, prot | PROT_WRITE); safe_mprotect(start, size, prot | PROT_WRITE);
// Patch // Patch
unsigned char *data = (unsigned char *) start; unsigned char *data = (unsigned char *) start;
PATCH_PRINTF(file, line, start, "original");
memcpy(data, patch, 4); memcpy(data, patch, 4);
PATCH_PRINTF(file, line, start, "result");
// Reset Code Memory Permissions // Reset Code Memory Permissions
safe_mprotect(start, size, prot); safe_mprotect(start, size, prot);
@ -159,8 +154,13 @@ void _patch(const char *file, int line, void *start, unsigned char patch[4]) {
} }
// Patch Address // Patch Address
void _patch_address(const char *file, int line, void *start, void *target) { void patch_address(void *start, void *target) {
uint32_t addr = (uint32_t) target; uint32_t addr = (uint32_t) target;
unsigned char *patch_data = (unsigned char *) &addr; unsigned char *patch_data = (unsigned char *) &addr;
_patch(file, line, start, patch_data); patch(start, patch_data);
} }
// Thunks
void *reborn_thunk_enabler(void *target, void *thunk) {
return overwrite_calls_manual(target, thunk, true);
}

View File

@ -10,6 +10,9 @@ int32_t misc_get_real_selected_slot(Player *player);
void misc_render_background(int color, Minecraft *minecraft, int x, int y, int width, int height); void misc_render_background(int color, Minecraft *minecraft, int x, int y, int width, int height);
extern bool is_in_chat; extern bool is_in_chat;
typedef RakNet_RakString *(*RakNet_RakString_constructor_t)(RakNet_RakString *self, const char *format, ...);
extern RakNet_RakString_constructor_t RakNet_RakString_constructor;
} }
void misc_run_on_update(const std::function<void(Minecraft *)> &func); void misc_run_on_update(const std::function<void(Minecraft *)> &func);

View File

@ -136,7 +136,7 @@ static int BucketItem_getUseDuration(__attribute__((unused)) FoodItem *item, Ite
static ItemInstance BucketItem_useTimeDepleted(FoodItem *item, ItemInstance *item_instance, Level *level, Player *player) { static ItemInstance BucketItem_useTimeDepleted(FoodItem *item, ItemInstance *item_instance, Level *level, Player *player) {
if (item_instance->auxiliary == 1) { if (item_instance->auxiliary == 1) {
*item_instance = (*FoodItem_useTimeDepleted_vtable_addr)(item, item_instance, level, player); *item_instance = FoodItem_useTimeDepleted.get()(item, item_instance, level, player);
// Set it to a empty bucket // Set it to a empty bucket
item_instance->auxiliary = 0; item_instance->auxiliary = 0;
item_instance->count = 1; item_instance->count = 1;
@ -154,7 +154,7 @@ static bool BucketItem_isFood(__attribute__((unused)) FoodItem *item) {
static ItemInstance *BucketItem_use(FoodItem *item, ItemInstance *item_instance, __attribute__((unused)) Level *level, Player *player) { static ItemInstance *BucketItem_use(FoodItem *item, ItemInstance *item_instance, __attribute__((unused)) Level *level, Player *player) {
if (item_instance->auxiliary == 1) { if (item_instance->auxiliary == 1) {
return (*FoodItem_use_vtable_addr)(item, item_instance, level, player); return FoodItem_use.get()(item, item_instance, level, player);
} }
return item_instance; return item_instance;
} }
@ -188,7 +188,7 @@ static FoodItem *create_bucket(int32_t id, int32_t texture_x, int32_t texture_y,
// Construct // Construct
FoodItem *item = new FoodItem; FoodItem *item = new FoodItem;
ALLOC_CHECK(item); ALLOC_CHECK(item);
Item_constructor((Item *) item, id); // FoodItem's Constructor Was Inlined Item_constructor.get()((Item *) item, id); // FoodItem's Constructor Was Inlined
// Set VTable // Set VTable
item->vtable = get_bucket_vtable(); item->vtable = get_bucket_vtable();

View File

@ -102,7 +102,7 @@ static int Cake_use(__attribute__((unused)) Tile *tile, Level *level, int x, int
// Eat // Eat
player->foodData.eat(3); player->foodData.eat(3);
// Set the new tile // Set the new tile
int data = level->getData(x, y, z); const int data = level->getData(x, y, z);
if (data >= 5) { if (data >= 5) {
// Remove the cake, it has been completely gobbled up // Remove the cake, it has been completely gobbled up
level->setTileAndData(x, y, z, 0, 0); level->setTileAndData(x, y, z, 0, 0);
@ -123,7 +123,7 @@ static void make_cake() {
cake->texture = texture; cake->texture = texture;
// Set VTable // Set VTable
cake->vtable = dup_Tile_vtable(Tile_vtable_base); cake->vtable = dup_vtable(Tile_vtable_base);
ALLOC_CHECK(cake->vtable); ALLOC_CHECK(cake->vtable);
// Set shape // Set shape

View File

@ -93,7 +93,7 @@ static void Player_actuallyHurt_injection(Self *player, int32_t damage) {
int32_t old_health = player->health; int32_t old_health = player->health;
// Call Original Method // Call Original Method
(*Mob_actuallyHurt_vtable_addr)((Mob *) player, damage); Mob_actuallyHurt.get()((Mob *) player, damage);
if (is_hurt) { if (is_hurt) {
return; return;
} }
@ -122,7 +122,7 @@ void init_death() {
// Death Messages // Death Messages
if (feature_has("Implement Death Messages", server_auto)) { if (feature_has("Implement Death Messages", server_auto)) {
patch_vtable(ServerPlayer_die, [](ServerPlayer *player, Entity *cause) { patch_vtable(ServerPlayer_die, [](ServerPlayer *player, Entity *cause) {
Player_die_injection<ServerPlayer, Player>(*Player_die_vtable_addr, player, cause); Player_die_injection<ServerPlayer, Player>(Player_die.get(), player, cause);
}); });
overwrite_calls(LocalPlayer_die, Player_die_injection<LocalPlayer, LocalPlayer>); overwrite_calls(LocalPlayer_die, Player_die_injection<LocalPlayer, LocalPlayer>);
patch_vtable(LocalPlayer_actuallyHurt, Player_actuallyHurt_injection); patch_vtable(LocalPlayer_actuallyHurt, Player_actuallyHurt_injection);

View File

@ -21,7 +21,7 @@ static void set_is_survival(bool new_is_survival) {
patch((void *) 0x16ee4, size_patch); patch((void *) 0x16ee4, size_patch);
// Replace Default CreatorMode Constructor With CreatorMode Or SurvivalMode Constructor // Replace Default CreatorMode Constructor With CreatorMode Or SurvivalMode Constructor
overwrite_call((void *) 0x16ef4, new_is_survival ? (void *) SurvivalMode_constructor : (void *) CreatorMode_constructor); overwrite_call((void *) 0x16ef4, new_is_survival ? (void *) SurvivalMode_constructor.get() : (void *) CreatorMode_constructor.get());
is_survival = new_is_survival; is_survival = new_is_survival;
} }
@ -54,7 +54,7 @@ void init_game_mode() {
overwrite_calls(Minecraft_setIsCreativeMode, Minecraft_setIsCreativeMode_injection); overwrite_calls(Minecraft_setIsCreativeMode, Minecraft_setIsCreativeMode_injection);
// Replace CreatorLevel With ServerLevel (This Fixes Beds And Mob Spawning) // Replace CreatorLevel With ServerLevel (This Fixes Beds And Mob Spawning)
overwrite_call((void *) 0x16f84, (void *) ServerLevel_constructor); overwrite_call((void *) 0x16f84, (void *) ServerLevel_constructor.get());
// Allocate Correct Size For ServerLevel // Allocate Correct Size For ServerLevel
uint32_t level_size = sizeof(ServerLevel); uint32_t level_size = sizeof(ServerLevel);

View File

@ -1,8 +1,10 @@
#include <libreborn/libreborn.h> #include <libreborn/libreborn.h>
#include <mods/init/init.h> #include <mods/init/init.h>
#include <media-layer/core.h> #include <media-layer/core.h>
#include <symbols/minecraft.h>
__attribute__((constructor)) static void init() { __attribute__((constructor)) static void init() {
thunk_enabler = reborn_thunk_enabler;
media_ensure_loaded(); media_ensure_loaded();
reborn_init_patch(); reborn_init_patch();
run_tests(); run_tests();

View File

@ -15,7 +15,7 @@ void input_set_is_ctrl(const bool val) {
// Handle Drop Item Presses // Handle Drop Item Presses
static void _handle_drop(Minecraft *minecraft) { static void _handle_drop(Minecraft *minecraft) {
if (!creative_is_restricted() || !Minecraft_isCreativeMode(minecraft)) { if (!creative_is_restricted() || !minecraft->isCreativeMode()) {
// Get Player // Get Player
LocalPlayer *player = minecraft->player; LocalPlayer *player = minecraft->player;
if (player != nullptr) { if (player != nullptr) {

View File

@ -90,7 +90,7 @@ static void Gui_renderHearts_injection(Gui_renderHearts_t original, Gui *gui) {
original(gui); original(gui);
} }
static GuiComponent_blit_t get_blit_with_classic_hud_offset() { static GuiComponent_blit_t get_blit_with_classic_hud_offset() {
return use_classic_hud ? Gui_renderHearts_GuiComponent_blit_hearts_injection : GuiComponent_blit; return use_classic_hud ? Gui_renderHearts_GuiComponent_blit_hearts_injection : GuiComponent_blit.get();
} }
#define PINK_HEART_FULL 70 #define PINK_HEART_FULL 70
#define PINK_HEART_HALF 79 #define PINK_HEART_HALF 79
@ -130,7 +130,7 @@ static void Gui_renderChatMessages_injection(Gui_renderChatMessages_t original,
// Handle Classic HUD // Handle Classic HUD
if (use_classic_hud) { if (use_classic_hud) {
Minecraft *minecraft = gui->minecraft; Minecraft *minecraft = gui->minecraft;
if (!Minecraft_isCreativeMode(minecraft)) { if (!minecraft->isCreativeMode()) {
y_offset -= (HUD_ELEMENT_HEIGHT * 2) + NEW_HUD_PADDING; y_offset -= (HUD_ELEMENT_HEIGHT * 2) + NEW_HUD_PADDING;
} }
} }
@ -231,6 +231,7 @@ static void LoginPacket_read_injection(LoginPacket_read_t original, LoginPacket
// RakNet::RakString's format constructor is often given unsanitized user input and is never used for formatting, // RakNet::RakString's format constructor is often given unsanitized user input and is never used for formatting,
// this is a massive security risk, allowing clients to run arbitrary format specifiers, this disables the // this is a massive security risk, allowing clients to run arbitrary format specifiers, this disables the
// formatting functionality. // formatting functionality.
RakNet_RakString_constructor_t RakNet_RakString_constructor = (RakNet_RakString_constructor_t) 0xea5cc;
static RakNet_RakString *RakNet_RakString_injection(RakNet_RakString *rak_string, const char *format, ...) { static RakNet_RakString *RakNet_RakString_injection(RakNet_RakString *rak_string, const char *format, ...) {
// Call Original Method // Call Original Method
return RakNet_RakString_constructor(rak_string, "%s", format); return RakNet_RakString_constructor(rak_string, "%s", format);
@ -363,7 +364,7 @@ static void anGenBuffers_injection(__attribute__((unused)) Common_anGenBuffers_t
// Fix Graphics Bug When Switching To First-Person While Sneaking // Fix Graphics Bug When Switching To First-Person While Sneaking
static void PlayerRenderer_render_injection(PlayerRenderer *model_renderer, Entity *entity, float param_2, float param_3, float param_4, float param_5, float param_6) { static void PlayerRenderer_render_injection(PlayerRenderer *model_renderer, Entity *entity, float param_2, float param_3, float param_4, float param_5, float param_6) {
(*HumanoidMobRenderer_render_vtable_addr)((HumanoidMobRenderer *) model_renderer, entity, param_2, param_3, param_4, param_5, param_6); HumanoidMobRenderer_vtable_base->render((HumanoidMobRenderer *) model_renderer, entity, param_2, param_3, param_4, param_5, param_6);
HumanoidModel *model = model_renderer->model; HumanoidModel *model = model_renderer->model;
model->is_sneaking = false; model->is_sneaking = false;
} }

View File

@ -70,7 +70,7 @@ static Screen *last_screen = nullptr;
static std::string current_splash; static std::string current_splash;
static void StartMenuScreen_render_Screen_render_injection(Screen *screen, int x, int y, float param_1) { static void StartMenuScreen_render_Screen_render_injection(Screen *screen, int x, int y, float param_1) {
// Call Original Method // Call Original Method
(*Screen_render_vtable_addr)(screen, x, y, param_1); Screen_render.get()(screen, x, y, param_1);
// Load Splashes // Load Splashes
static std::vector<std::string> splashes; static std::vector<std::string> splashes;

View File

@ -73,10 +73,10 @@ void init_touch() {
// Force Touch Inventory // Force Touch Inventory
if (feature_has("Force Touch GUI Inventory", server_disabled)) { if (feature_has("Force Touch GUI Inventory", server_disabled)) {
overwrite_call((void *) 0x2943c, (void *) operator_new_IngameBlockSelectionScreen_injection); overwrite_call((void *) 0x2943c, (void *) operator_new_IngameBlockSelectionScreen_injection);
overwrite_call((void *) 0x29444, (void *) Touch_IngameBlockSelectionScreen_constructor); overwrite_call((void *) 0x29444, (void *) Touch_IngameBlockSelectionScreen_constructor.get());
// Make "Craft" And "Armor" Buttons Use Classic GUI Style (Button And TButton Have The Same Size) // Make "Craft" And "Armor" Buttons Use Classic GUI Style (Button And TButton Have The Same Size)
overwrite_call((void *) 0x3b060, (void *) Button_constructor); overwrite_call((void *) 0x3b060, (void *) Button_constructor.get());
overwrite_call((void *) 0x3b08c, (void *) Button_constructor); overwrite_call((void *) 0x3b08c, (void *) Button_constructor.get());
} }
// Force Touch Button Behavior // Force Touch Button Behavior

View File

@ -1,4 +1,4 @@
constructor (const char *format, ...) = 0xea5cc; //constructor (const char *format, ...) = 0xea5cc;
method void Assign(const char *str) = 0xe9e34; method void Assign(const char *str) = 0xe9e34;