diff --git a/.gitmodules b/.gitmodules index 58c35e5f28..c9727407b8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -19,3 +19,6 @@ [submodule "archives"] path = archives url = https://gitea.thebrokenrail.com/minecraft-pi-reborn/archives.git +[submodule "dependencies/symbol-processor/src"] + path = dependencies/symbol-processor/src + url = https://gitea.thebrokenrail.com/minecraft-pi-reborn/symbol-processor.git diff --git a/LICENSE b/LICENSE index 2eee90d1b8..938a0d819b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 TheBrokenRail +Copyright (c) 2024 TheBrokenRail Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/dependencies/CMakeLists.txt b/dependencies/CMakeLists.txt index c6e4d50f14..f4cc313fde 100644 --- a/dependencies/CMakeLists.txt +++ b/dependencies/CMakeLists.txt @@ -30,3 +30,7 @@ if(BUILD_MEDIA_LAYER_CORE AND NOT MCPI_HEADLESS_MODE AND MCPI_USE_GLES1_COMPATIB endif() # UTF8-CPP add_subdirectory(utf8cpp) +# Symbol Prcoessor +if(BUILD_ARM_COMPONENTS) + add_subdirectory(symbol-processor) +endif() diff --git a/dependencies/symbol-processor/CMakeLists.txt b/dependencies/symbol-processor/CMakeLists.txt new file mode 100644 index 0000000000..024cd4957d --- /dev/null +++ b/dependencies/symbol-processor/CMakeLists.txt @@ -0,0 +1,20 @@ +project(symbol-processor) + +# Install Dependencies +set(SRC "${CMAKE_CURRENT_SOURCE_DIR}/src") +set(NODE_MODULES "${SRC}/node_modules") +function(npm_run) + execute_process( + COMMAND npm ${ARGV} + WORKING_DIRECTORY "${SRC}" + RESULT_VARIABLE RESULT + ) + if(NOT RESULT EQUAL 0) + file(REMOVE_RECURSE "${NODE_MODULES}") + message(FATAL_ERROR "Unable To Run NPM Command") + endif() +endfunction() +if(NOT EXISTS "${NODE_MODULES}") + npm_run(ci --silent) + npm_run(run --silent lint) +endif() diff --git a/dependencies/symbol-processor/src b/dependencies/symbol-processor/src new file mode 160000 index 0000000000..1062e048c4 --- /dev/null +++ b/dependencies/symbol-processor/src @@ -0,0 +1 @@ +Subproject commit 1062e048c493607b7b57faf83570562fa44c0f9c diff --git a/mods/CMakeLists.txt b/mods/CMakeLists.txt index 84a322c26a..b9dac354d9 100644 --- a/mods/CMakeLists.txt +++ b/mods/CMakeLists.txt @@ -8,6 +8,7 @@ target_include_directories( "$" "$" ) +target_link_libraries(mods-headers INTERFACE symbols) # SDK install(TARGETS mods-headers EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}") install(DIRECTORY "include/" DESTINATION "${MCPI_SDK_INCLUDE_DIR}/mods") @@ -115,7 +116,7 @@ add_library(test SHARED src/test/test.c) target_link_libraries(test mods-headers reborn-patch home) add_library(init SHARED src/init/init.c) -target_link_libraries(init mods-headers reborn-util compat game-mode misc death options chat creative bucket textures home version test media-layer-core) +target_link_libraries(init symbols mods-headers reborn-util compat game-mode misc death options chat creative bucket textures home version test media-layer-core) if(MCPI_SERVER_MODE) target_link_libraries(init server) else() diff --git a/mods/include/mods/chat/chat.h b/mods/include/mods/chat/chat.h index 36caba2da6..e9d4ad8760 100644 --- a/mods/include/mods/chat/chat.h +++ b/mods/include/mods/chat/chat.h @@ -1,11 +1,12 @@ #pragma once #include +#include #ifdef __cplusplus #include // Send API Command -std::string chat_send_api_command(unsigned char *minecraft, char *str); +std::string chat_send_api_command(Minecraft *minecraft, std::string str); #endif #ifdef __cplusplus @@ -18,8 +19,8 @@ unsigned int chat_get_counter(); #endif // Override using the HOOK() macro to provide customized chat behavior. -void chat_send_message(unsigned char *server_side_network_handler, char *username, char *message); -void chat_handle_packet_send(unsigned char *minecraft, unsigned char *packet); +void chat_send_message(ServerSideNetworkHandler *server_side_network_handler, char *username, char *message); +void chat_handle_packet_send(Minecraft *minecraft, ChatPacket *packet); #ifdef __cplusplus } diff --git a/mods/include/mods/input/input.h b/mods/include/mods/input/input.h index 782221640b..c738365e04 100644 --- a/mods/include/mods/input/input.h +++ b/mods/include/mods/input/input.h @@ -1,10 +1,12 @@ #pragma once +#include + #ifdef __cplusplus extern "C" { #endif -typedef void (*input_tick_function_t)(unsigned char *minecraft); +typedef void (*input_tick_function_t)(Minecraft *minecraft); void input_run_on_tick(input_tick_function_t function); void input_set_is_right_click(int val); diff --git a/mods/include/mods/misc/misc.h b/mods/include/mods/misc/misc.h index 9e08cfcc36..291384bd1a 100644 --- a/mods/include/mods/misc/misc.h +++ b/mods/include/mods/misc/misc.h @@ -2,25 +2,31 @@ #include +#include + #ifdef __cplusplus extern "C" { #endif -int32_t misc_get_real_selected_slot(unsigned char *player); +int32_t misc_get_real_selected_slot(Player *player); -typedef void (*misc_update_function_t)(unsigned char *obj); -void misc_run_on_update(misc_update_function_t function); // obj == Minecraft * -void misc_run_on_tick(misc_update_function_t function); // obj == Minecraft * -void misc_run_on_recipes_setup(misc_update_function_t function); // obj == Recipes * -void misc_run_on_furnace_recipes_setup(misc_update_function_t function); // obj == FurnaceRecipes * -void misc_run_on_creative_inventory_setup(misc_update_function_t function); // obj == FillingContainer * -void misc_run_on_tiles_setup(misc_update_function_t function); // obj == NULL -void misc_run_on_items_setup(misc_update_function_t function); // obj == NULL +typedef void (*misc_update_function_Minecraft_t)(Minecraft *obj); +void misc_run_on_update(misc_update_function_Minecraft_t function); // obj == Minecraft * +void misc_run_on_tick(misc_update_function_Minecraft_t function); // obj == Minecraft * +typedef void (*misc_update_function_Recipes_t)(Recipes *obj); +void misc_run_on_recipes_setup(misc_update_function_Recipes_t function); // obj == Recipes * +typedef void (*misc_update_function_FurnaceRecipes_t)(FurnaceRecipes *obj); +void misc_run_on_furnace_recipes_setup(misc_update_function_FurnaceRecipes_t function); // obj == FurnaceRecipes * +typedef void (*misc_update_function_FillingContainer_t)(FillingContainer *obj); +void misc_run_on_creative_inventory_setup(misc_update_function_FillingContainer_t function); // obj == FillingContainer * +typedef void (*misc_update_function_void_t)(void *obj); +void misc_run_on_tiles_setup(misc_update_function_void_t function); // obj == NULL +void misc_run_on_items_setup(misc_update_function_void_t function); // obj == NULL -void Level_saveLevelData_injection(unsigned char *level); +void Level_saveLevelData_injection(Level *level); // Use this instead of directly calling Gui::addMessage(), it has proper logging! -void misc_add_message(unsigned char *gui, const char *text); +void misc_add_message(Gui *gui, const char *text); #ifdef __cplusplus } diff --git a/mods/src/atlas/atlas.cpp b/mods/src/atlas/atlas.cpp index af0fe2a79a..6ba57e198e 100644 --- a/mods/src/atlas/atlas.cpp +++ b/mods/src/atlas/atlas.cpp @@ -7,9 +7,9 @@ #include // Fix Grass And Leaves Inventory Rendering When The gui_blocks Atlas Is Disabled -static void ItemRenderer_renderGuiItemCorrect_injection(unsigned char *font, unsigned char *textures, ItemInstance *item_instance, int32_t param_1, int32_t param_2) { - int32_t leaves_id = *(int32_t *) (*Tile_leaves + Tile_id_property_offset); - int32_t grass_id = *(int32_t *) (*Tile_grass + Tile_id_property_offset); +static void ItemRenderer_renderGuiItemCorrect_injection(Font *font, Textures *textures, ItemInstance *item_instance, int32_t param_1, int32_t param_2) { + int32_t leaves_id = (*Tile_leaves)->id; + int32_t grass_id = (*Tile_grass)->id; // Replace Rendered Item With Carried Variant ItemInstance carried_item_instance; bool use_carried = false; @@ -40,7 +40,7 @@ static void ItemRenderer_renderGuiItemCorrect_injection(unsigned char *font, uns static int item_color_fix_mode = 0; #define POTENTIAL_FURNACE_ITEM_TRANSPARENCY 0x33 #define INVALID_FURNACE_ITEM_MULTIPLIER 0.25f -static void Tesselator_color_injection(unsigned char *tesselator, int32_t r, int32_t g, int32_t b, int32_t a) { +static void Tesselator_color_injection(Tesselator *tesselator, int32_t r, int32_t g, int32_t b, int32_t a) { // Fix Furnace UI if (item_color_fix_mode != 0) { // Force Translucent @@ -57,7 +57,7 @@ static void Tesselator_color_injection(unsigned char *tesselator, int32_t r, int // Call Original Method (*Tesselator_color)(tesselator, r, g, b, a); } -static void Tesselator_begin_injection(unsigned char *tesselator, int32_t mode) { +static void Tesselator_begin_injection(Tesselator *tesselator, int32_t mode) { // Call Original Method (*Tesselator_begin)(tesselator, mode); @@ -67,21 +67,21 @@ static void Tesselator_begin_injection(unsigned char *tesselator, int32_t mode) (*Tesselator_color_injection)(tesselator, 0xff, 0xff, 0xff, 0xff); } } -static void InventoryPane_renderBatch_Tesselator_color_injection(unsigned char *tesselator, int32_t r, int32_t g, int32_t b) { +static void InventoryPane_renderBatch_Tesselator_color_injection(Tesselator *tesselator, int32_t r, int32_t g, int32_t b) { // Call Original Method (*Tesselator_color)(tesselator, r, g, b, 0xff); // Enable Item Color Fix item_color_fix_mode = 2; } -static void ItemRenderer_renderGuiItem_two_injection(unsigned char *font, unsigned char *textures, ItemInstance *item_instance, float param_1, float param_2, float param_3, float param_4, bool param_5) { +static void ItemRenderer_renderGuiItem_two_injection(Font *font, Textures *textures, ItemInstance *item_instance, float param_1, float param_2, float param_3, float param_4, bool param_5) { // Call Original Method (*ItemRenderer_renderGuiItem_two)(font, textures, item_instance, param_1, param_2, param_3, param_4, param_5); // Disable Item Color Fix item_color_fix_mode = 0; } -static void FurnaceScreen_render_ItemRenderer_renderGuiItem_one_injection(unsigned char *font, unsigned char *textures, ItemInstance *item_instance, float param_1, float param_2, bool param_3) { +static void FurnaceScreen_render_ItemRenderer_renderGuiItem_one_injection(Font *font, Textures *textures, ItemInstance *item_instance, float param_1, float param_2, bool param_3) { // Enable Item Color Fix item_color_fix_mode = 1; diff --git a/mods/src/benchmark/benchmark.cpp b/mods/src/benchmark/benchmark.cpp index b71715831f..24ef3a319f 100644 --- a/mods/src/benchmark/benchmark.cpp +++ b/mods/src/benchmark/benchmark.cpp @@ -36,7 +36,7 @@ __attribute__((constructor)) static void _init_active(int argc, char *argv[]) { #define BENCHMARK_ROTATION_AMOUNT 10 // Create/Start World -static void start_world(unsigned char *minecraft) { +static void start_world(Minecraft *minecraft) { // Log INFO("Loading Benchmark"); @@ -46,19 +46,18 @@ static void start_world(unsigned char *minecraft) { settings.seed = BENCHMARK_SEED; // Delete World If It Already Exists - unsigned char *level_source = (*Minecraft_getLevelSource)(minecraft); - unsigned char *level_source_vtable = *(unsigned char **) level_source; - ExternalFileLevelStorageSource_deleteLevel_t ExternalFileLevelStorageSource_deleteLevel = *(ExternalFileLevelStorageSource_deleteLevel_t *) (level_source_vtable + ExternalFileLevelStorageSource_deleteLevel_vtable_offset); - (*ExternalFileLevelStorageSource_deleteLevel)(level_source, BENCHMARK_WORLD_NAME); + LevelStorageSource *level_source = (*Minecraft_getLevelSource)(minecraft); + std::string name = BENCHMARK_WORLD_NAME; + level_source->vtable->deleteLevel(level_source, &name); // Select Level - (*Minecraft_selectLevel)(minecraft, BENCHMARK_WORLD_NAME, BENCHMARK_WORLD_NAME, settings); + minecraft->vtable->selectLevel(minecraft, &name, &name, &settings); // Open ProgressScreen - void *screen = ::operator new(PROGRESS_SCREEN_SIZE); + ProgressScreen *screen = alloc_ProgressScreen(); ALLOC_CHECK(screen); - screen = (*ProgressScreen)((unsigned char *) screen); - (*Minecraft_setScreen)(minecraft, (unsigned char *) screen); + screen = (*ProgressScreen_constructor)(screen); + (*Minecraft_setScreen)(minecraft, (Screen *) screen); } // Track Frames @@ -73,7 +72,7 @@ HOOK(media_swap_buffers, void, ()) { // Track Ticks static unsigned long long int ticks = 0; -static void Minecraft_tick_injection(__attribute__((unused)) unsigned char *minecraft) { +static void Minecraft_tick_injection(__attribute__((unused)) Minecraft *minecraft) { ticks++; } @@ -100,7 +99,7 @@ static int32_t last_logged_status = -1; // Runs Every Tick static bool loaded = false; static bool exit_requested = false; -static void Minecraft_update_injection(unsigned char *minecraft) { +static void Minecraft_update_injection(Minecraft *minecraft) { // Create/Start World if (!loaded) { start_world(minecraft); diff --git a/mods/src/bucket/bucket.cpp b/mods/src/bucket/bucket.cpp index 7190bed235..1a05bcbb24 100644 --- a/mods/src/bucket/bucket.cpp +++ b/mods/src/bucket/bucket.cpp @@ -6,22 +6,22 @@ #include // Items -unsigned char *bucket = NULL; +Item *bucket = NULL; // Description And Texture -static std::string BucketItem_getDescriptionId(__attribute__((unused)) unsigned char *item, const ItemInstance *item_instance) { - if (item_instance->auxiliary == *(int32_t *) (*Tile_water + Tile_id_property_offset)) { +static std::string BucketItem_getDescriptionId(__attribute__((unused)) Item *item, ItemInstance *item_instance) { + if (item_instance->auxiliary == (*Tile_water)->id) { return "item.bucketWater"; - } else if (item_instance->auxiliary == *(int32_t *) (*Tile_lava + Tile_id_property_offset)) { + } else if (item_instance->auxiliary == (*Tile_lava)->id) { return "item.bucketLava"; } else { return "item.bucket"; } } -static int32_t BucketItem_getIcon(__attribute__((unused)) unsigned char *item, int32_t auxiliary) { - if (auxiliary == *(int32_t *) (*Tile_water + Tile_id_property_offset)) { +static int32_t BucketItem_getIcon(__attribute__((unused)) Item *item, int32_t auxiliary) { + if (auxiliary == (*Tile_water)->id) { return 75; - } else if (auxiliary == *(int32_t *) (*Tile_lava + Tile_id_property_offset)) { + } else if (auxiliary == (*Tile_lava)->id) { return 76; } else { return 74; @@ -29,17 +29,17 @@ static int32_t BucketItem_getIcon(__attribute__((unused)) unsigned char *item, i } // Use Bucket -static int32_t BucketItem_useOn(__attribute__((unused)) unsigned char *item, ItemInstance *item_instance, unsigned char *player, unsigned char *level, int32_t x, int32_t y, int32_t z, int32_t hit_side, __attribute__((unused)) float hit_x, __attribute__((unused)) float hit_y, __attribute__((unused)) float hit_z) { +static int32_t BucketItem_useOn(__attribute__((unused)) Item *item, ItemInstance *item_instance, Player *player, Level *level, int32_t x, int32_t y, int32_t z, int32_t hit_side, __attribute__((unused)) float hit_x, __attribute__((unused)) float hit_y, __attribute__((unused)) float hit_z) { if (item_instance->count < 1) { return 0; } else if (item_instance->auxiliary == 0) { // Empty Bucket int32_t new_auxiliary = 0; - int32_t tile = (*Level_getTile)(level, x, y, z); - if (tile == *(int32_t *) (*Tile_calmWater + Tile_id_property_offset)) { - new_auxiliary = *(int32_t *) (*Tile_water + Tile_id_property_offset); - } else if (tile == *(int32_t *) (*Tile_calmLava + Tile_id_property_offset)) { - new_auxiliary = *(int32_t *) (*Tile_lava + Tile_id_property_offset); + int32_t tile = level->vtable->getTile(level, x, y, z); + if (tile == (*Tile_calmWater)->id) { + new_auxiliary = (*Tile_water)->id; + } else if (tile == (*Tile_calmLava)->id) { + new_auxiliary = (*Tile_lava)->id; } if (new_auxiliary != 0) { // Valid @@ -49,13 +49,11 @@ static int32_t BucketItem_useOn(__attribute__((unused)) unsigned char *item, Ite success = true; } else { ItemInstance new_item; - new_item.id = *(int32_t *) (bucket + Item_id_property_offset); + new_item.id = bucket->id; new_item.count = 1; new_item.auxiliary = new_auxiliary; - unsigned char *inventory = *(unsigned char **) (player + Player_inventory_property_offset); - unsigned char *inventory_vtable = *(unsigned char **) inventory; - FillingContainer_add_t FillingContainer_add = *(FillingContainer_add_t *) (inventory_vtable + FillingContainer_add_vtable_offset); - if ((*FillingContainer_add)(inventory, &new_item)) { + Inventory *inventory = player->inventory; + if (inventory->vtable->add(inventory, &new_item)) { // Added To Inventory success = true; item_instance->count -= 1; @@ -101,13 +99,11 @@ static int32_t BucketItem_useOn(__attribute__((unused)) unsigned char *item, Ite } // Get Current Tile bool valid = false; - unsigned char *material = (*Level_getMaterial)(level, x, y, z); + Material *material = level->vtable->getMaterial(level, x, y, z); if (material != NULL) { - unsigned char *material_vtable = *(unsigned char **) material; - Material_isSolid_t Material_isSolid = *(Material_isSolid_t *) (material_vtable + Material_isSolid_vtable_offset); - valid = !(*Material_isSolid)(material); + valid = !material->vtable->isSolid(material); } - if (item_instance->auxiliary != *(int32_t *) (*Tile_water + Tile_id_property_offset) && item_instance->auxiliary != *(int32_t *) (*Tile_lava + Tile_id_property_offset)) { + if (item_instance->auxiliary != (*Tile_water)->id && item_instance->auxiliary != (*Tile_lava)->id) { valid = false; } if (valid) { @@ -121,59 +117,49 @@ static int32_t BucketItem_useOn(__attribute__((unused)) unsigned char *item, Ite } // Bucket VTable -static unsigned char *get_bucket_vtable() { - static unsigned char *vtable = NULL; +static Item_vtable *get_bucket_vtable() { + static Item_vtable *vtable = NULL; if (vtable == NULL) { // Init - vtable = (unsigned char *) malloc(ITEM_VTABLE_SIZE); + vtable = dup_Item_vtable(Item_vtable_base); ALLOC_CHECK(vtable); - // Copy Old VTable - memcpy((void *) vtable, (void *) Item_vtable, ITEM_VTABLE_SIZE); // Modify - *(Item_getDescriptionId_t *) (vtable + Item_getDescriptionId_vtable_offset) = BucketItem_getDescriptionId; - *(Item_getIcon_t *) (vtable + Item_getIcon_vtable_offset) = BucketItem_getIcon; - *(Item_useOn_t *) (vtable + Item_useOn_vtable_offset) = BucketItem_useOn; + vtable->getDescriptionId = BucketItem_getDescriptionId; + vtable->getIcon = BucketItem_getIcon; + vtable->useOn = BucketItem_useOn; } return vtable; } -__attribute__((destructor)) static void free_bucket_vtable() { - free(get_bucket_vtable()); -} // Create Items -static unsigned char *create_bucket(int32_t id, int32_t texture_x, int32_t texture_y, const char *name) { +static Item *create_bucket(int32_t id, int32_t texture_x, int32_t texture_y, std::string name) { // Construct - unsigned char *item = (unsigned char *) ::operator new(ITEM_SIZE); + Item *item = alloc_Item(); ALLOC_CHECK(item); - (*Item)(item, id); + (*Item_constructor)(item, id); // Set VTable - *(unsigned char **) item = get_bucket_vtable(); - - // Get Functions - unsigned char *vtable = *(unsigned char **) item; - Item_setIcon_t Item_setIcon = *(Item_setIcon_t *) (vtable + Item_setIcon_vtable_offset); - Item_setDescriptionId_t Item_setDescriptionId = *(Item_setDescriptionId_t *) (vtable + Item_setDescriptionId_vtable_offset); + item->vtable = get_bucket_vtable(); // Setup - (*Item_setIcon)(item, texture_x, texture_y); - (*Item_setDescriptionId)(item, name); - *(int32_t *) (item + Item_is_stacked_by_data_property_offset) = 1; - *(int32_t *) (item + Item_category_property_offset) = 2; - *(int32_t *) (item + Item_max_damage_property_offset) = 0; - *(int32_t *) (item + Item_max_stack_size_property_offset) = 1; + item->vtable->setIcon(item, texture_x, texture_y); + item->vtable->setDescriptionId(item, &name); + item->is_stacked_by_data = 1; + item->category = 2; + item->max_damage = 0; + item->max_stack_size = 1; // Return return item; } -static void Item_initItems_injection(__attribute__((unused)) unsigned char *null) { +static void Item_initItems_injection(__attribute__((unused)) void *null) { bucket = create_bucket(69, 10, 4, "bucket"); } // Change Max Stack Size Based On Auxiliary static int32_t ItemInstance_getMaxStackSize_injection(ItemInstance *item_instance) { - if (item_instance->id == *(int32_t *) (bucket + Item_id_property_offset) && item_instance->auxiliary == 0) { + if (item_instance->id == bucket->id && item_instance->auxiliary == 0) { // Custom Value return 16; } else { @@ -183,60 +169,56 @@ static int32_t ItemInstance_getMaxStackSize_injection(ItemInstance *item_instanc } // Creative Inventory -static void inventory_add_item(unsigned char *inventory, unsigned char *item, int32_t auxiliary) { +static void inventory_add_item(FillingContainer *inventory, Item *item, int32_t auxiliary) { ItemInstance *item_instance = new ItemInstance; ALLOC_CHECK(item_instance); item_instance = (*ItemInstance_constructor_item_extra)(item_instance, item, 1, auxiliary); (*FillingContainer_addItem)(inventory, item_instance); } -static void Inventory_setupDefault_FillingContainer_addItem_call_injection(unsigned char *filling_container) { +static void Inventory_setupDefault_FillingContainer_addItem_call_injection(FillingContainer *filling_container) { inventory_add_item(filling_container, bucket, 0); - inventory_add_item(filling_container, bucket, *(int32_t *) (*Tile_water + Tile_id_property_offset)); - inventory_add_item(filling_container, bucket, *(int32_t *) (*Tile_lava + Tile_id_property_offset)); + inventory_add_item(filling_container, bucket, (*Tile_water)->id); + inventory_add_item(filling_container, bucket, (*Tile_lava)->id); } // Make Liquids Selectable static bool is_holding_bucket = false; -static HitResult Mob_pick_Level_clip_injection(unsigned char *level, unsigned char *param_1, unsigned char *param_2, __attribute__((unused)) bool clip_liquids, bool param_3) { +static HitResult Mob_pick_Level_clip_injection(Level *level, unsigned char *param_1, unsigned char *param_2, __attribute__((unused)) bool clip_liquids, bool param_3) { // Call Original Method return (*Level_clip)(level, param_1, param_2, is_holding_bucket, param_3); } -static void handle_tick(unsigned char *minecraft) { - unsigned char *player = *(unsigned char **) (minecraft + Minecraft_player_property_offset); +static void handle_tick(Minecraft *minecraft) { + LocalPlayer *player = minecraft->player; if (player != NULL) { // Get Selected Slot - int32_t selected_slot = misc_get_real_selected_slot(player); - unsigned char *inventory = *(unsigned char **) (player + Player_inventory_property_offset); - - // Prepare - unsigned char *inventory_vtable = *(unsigned char **) inventory; - FillingContainer_getItem_t FillingContainer_getItem = *(FillingContainer_getItem_t *) (inventory_vtable + FillingContainer_getItem_vtable_offset); + int32_t selected_slot = misc_get_real_selected_slot((Player *) player); + Inventory *inventory = player->inventory; // Get Item - ItemInstance *inventory_item = (*FillingContainer_getItem)(inventory, selected_slot); + ItemInstance *inventory_item = inventory->vtable->getItem(inventory, selected_slot); // Check - is_holding_bucket = inventory_item != NULL && inventory_item->id == (*(int32_t *) (bucket + Item_id_property_offset)) && inventory_item->auxiliary == 0; + is_holding_bucket = inventory_item != NULL && inventory_item->id == bucket->id && inventory_item->auxiliary == 0; } } // Prevent Breaking Liquid static bool is_calm_liquid(int32_t id) { - if (id == *(int32_t *) (*Tile_calmWater + Tile_id_property_offset)) { + if (id == (*Tile_calmWater)->id) { return true; - } else if (id == *(int32_t *) (*Tile_calmLava + Tile_id_property_offset)) { + } else if (id == (*Tile_calmLava)->id) { return true; } else { return false; } } -static void Minecraft_handleMouseDown_injection(unsigned char *minecraft, int param_1, bool can_destroy) { +static void Minecraft_handleMouseDown_injection(Minecraft *minecraft, int param_1, bool can_destroy) { // Check - unsigned char *level = *(unsigned char **) (minecraft + Minecraft_level_property_offset); + Level *level = minecraft->level; if (level != NULL) { - int32_t x = *(int32_t *) (minecraft + Minecraft_targeted_x_property_offset); - int32_t y = *(int32_t *) (minecraft + Minecraft_targeted_y_property_offset); - int32_t z = *(int32_t *) (minecraft + Minecraft_targeted_z_property_offset); - int32_t tile = (*Level_getTile)(level, x, y, z); + int32_t x = minecraft->hit_result.x; + int32_t y = minecraft->hit_result.y; + int32_t z = minecraft->hit_result.z; + int32_t tile = level->vtable->getTile(level, x, y, z); if (is_calm_liquid(tile)) { can_destroy = false; } @@ -247,7 +229,7 @@ static void Minecraft_handleMouseDown_injection(unsigned char *minecraft, int pa } // Custom Crafting Recipes -static void Recipes_injection(unsigned char *recipes) { +static void Recipes_injection(Recipes *recipes) { // Add Recipes_Type type1 = { .item = 0, @@ -261,15 +243,18 @@ static void Recipes_injection(unsigned char *recipes) { }; ItemInstance result = { .count = 1, - .id = (*(int32_t *) (bucket + Item_id_property_offset)), + .id = bucket->id, .auxiliary = 0 }; - (*Recipes_addShapedRecipe_2)(recipes, result, "# #", " # ", {type1}); + std::string line1 = "# #"; + std::string line2 = " # "; + std::vector types = {type1}; + (*Recipes_addShapedRecipe_2)(recipes, &result, &line1, &line2, &types); } // Custom Furnace Fuel -static int32_t FurnaceTileEntity_getBurnDuration_injection(ItemInstance const& item_instance) { - if (item_instance.count > 0 && item_instance.id == (*(int32_t *) (bucket + Item_id_property_offset)) && item_instance.auxiliary == (*(int32_t *) (*Tile_lava + Tile_id_property_offset))) { +static int32_t FurnaceTileEntity_getBurnDuration_injection(ItemInstance *item_instance) { + if (item_instance->count > 0 && item_instance->id == bucket->id && item_instance->auxiliary == (*Tile_lava)->id) { return 20000; } else { // Call Original Method @@ -278,7 +263,7 @@ static int32_t FurnaceTileEntity_getBurnDuration_injection(ItemInstance const& i } static void FurnaceTileEntity_tick_ItemInstance_setNull_injection(ItemInstance *item_instance) { // Replace Lava Bucket With Empty Bucket When It Burns Out - if (item_instance->id == (*(int32_t *) (bucket + Item_id_property_offset))) { + if (item_instance->id == bucket->id) { item_instance->auxiliary = 0; } else { // Original Behavior diff --git a/mods/src/camera/camera.cpp b/mods/src/camera/camera.cpp index 6319b215b1..b56feb3d19 100644 --- a/mods/src/camera/camera.cpp +++ b/mods/src/camera/camera.cpp @@ -7,28 +7,28 @@ #include // Take Screenshot Using TripodCamera -static void AppPlatform_linux_saveScreenshot_injection(__attribute__((unused)) unsigned char *app_platform, __attribute__((unused)) std::string const& path, __attribute__((unused)) int32_t width, __attribute__((unused)) int32_t height) { +static void AppPlatform_linux_saveScreenshot_injection(__attribute__((unused)) AppPlatform *app_platform, __attribute__((unused)) std::string const& path, __attribute__((unused)) int32_t width, __attribute__((unused)) int32_t height) { #ifndef MCPI_HEADLESS_MODE screenshot_take(home_get()); #endif } // Enable TripodCameraRenderer -static unsigned char *EntityRenderDispatcher_injection(unsigned char *dispatcher) { +static EntityRenderDispatcher *EntityRenderDispatcher_injection(EntityRenderDispatcher *dispatcher) { // Call Original Method - (*EntityRenderDispatcher)(dispatcher); + (*EntityRenderDispatcher_constructor)(dispatcher); // Register TripodCameraRenderer - unsigned char *renderer = (unsigned char *) ::operator new(TRIPOD_CAMERA_RENDERER_SIZE); + TripodCameraRenderer *renderer = alloc_TripodCameraRenderer(); ALLOC_CHECK(renderer); - (*TripodCameraRenderer)(renderer); - (*EntityRenderDispatcher_assign)(dispatcher, (unsigned char) 0x5, renderer); + (*TripodCameraRenderer_constructor)(renderer); + (*EntityRenderDispatcher_assign)(dispatcher, (unsigned char) 0x5, (EntityRenderer *) renderer); return dispatcher; } // Display Smoke From TripodCamera Higher -static void TripodCamera_tick_Level_addParticle_call_injection(unsigned char *level, std::string const& particle, float x, float y, float z, float deltaX, float deltaY, float deltaZ, int count) { +static void TripodCamera_tick_Level_addParticle_call_injection(Level *level, std::string *particle, float x, float y, float z, float deltaX, float deltaY, float deltaZ, int count) { // Call Original Method (*Level_addParticle)(level, particle, x, y + 0.5, z, deltaX, deltaY, deltaZ, count); } @@ -41,7 +41,7 @@ void init_camera() { // Fix Camera Rendering if (feature_has("Fix Camera Rendering", server_disabled)) { // Enable TripodCameraRenderer - overwrite_calls((void *) EntityRenderDispatcher, (void *) EntityRenderDispatcher_injection); + overwrite_calls((void *) EntityRenderDispatcher_constructor, (void *) EntityRenderDispatcher_injection); // Display Smoke From TripodCamera Higher overwrite_call((void *) 0x87dc4, (void *) TripodCamera_tick_Level_addParticle_call_injection); } diff --git a/mods/src/chat/chat.cpp b/mods/src/chat/chat.cpp index 4b6b8ceb54..93203fb564 100644 --- a/mods/src/chat/chat.cpp +++ b/mods/src/chat/chat.cpp @@ -29,14 +29,14 @@ int _chat_enabled = 0; #define MAX_CHAT_MESSAGE_LENGTH 512 // Send API Command -std::string chat_send_api_command(unsigned char *minecraft, char *str) { +std::string chat_send_api_command(Minecraft *minecraft, std::string str) { struct ConnectedClient client; client.sock = -1; client.str = ""; client.time = 0; - unsigned char *command_server = *(unsigned char **) (minecraft + Minecraft_command_server_property_offset); + CommandServer *command_server = minecraft->command_server; if (command_server != NULL) { - return (*CommandServer_parse)(command_server, client, str); + return (*CommandServer_parse)(command_server, &client, &str); } else { return ""; } @@ -44,7 +44,7 @@ std::string chat_send_api_command(unsigned char *minecraft, char *str) { #ifndef MCPI_HEADLESS_MODE // Send API Chat Command -static void send_api_chat_command(unsigned char *minecraft, char *str) { +static void send_api_chat_command(Minecraft *minecraft, char *str) { char *command = NULL; safe_asprintf(&command, "chat.post(%s)\n", str); chat_send_api_command(minecraft, command); @@ -53,45 +53,43 @@ static void send_api_chat_command(unsigned char *minecraft, char *str) { #endif // Send Message To Players -void chat_send_message(unsigned char *server_side_network_handler, char *username, char *message) { +void chat_send_message(ServerSideNetworkHandler *server_side_network_handler, char *username, char *message) { char *full_message = NULL; safe_asprintf(&full_message, "<%s> %s", username, message); sanitize_string(&full_message, MAX_CHAT_MESSAGE_LENGTH, 0); - (*ServerSideNetworkHandler_displayGameMessage)(server_side_network_handler, std::string(full_message)); + std::string cpp_string = full_message; free(full_message); + (*ServerSideNetworkHandler_displayGameMessage)(server_side_network_handler, &cpp_string); } // Handle Chat packet Send -void chat_handle_packet_send(unsigned char *minecraft, unsigned char *packet) { - unsigned char *rak_net_instance = *(unsigned char **) (minecraft + Minecraft_rak_net_instance_property_offset); - unsigned char *rak_net_instance_vtable = *(unsigned char **) rak_net_instance; - RakNetInstance_isServer_t RakNetInstance_isServer = *(RakNetInstance_isServer_t *) (rak_net_instance_vtable + RakNetInstance_isServer_vtable_offset); - if ((*RakNetInstance_isServer)(rak_net_instance)) { +void chat_handle_packet_send(Minecraft *minecraft, ChatPacket *packet) { + RakNetInstance *rak_net_instance = minecraft->rak_net_instance; + if (rak_net_instance->vtable->isServer(rak_net_instance)) { // Hosting Multiplayer - char *message = *(char **) (packet + ChatPacket_message_property_offset); - unsigned char *server_side_network_handler = *(unsigned char **) (minecraft + Minecraft_network_handler_property_offset); - chat_send_message(server_side_network_handler, *default_username, message); + char *message = packet->message; + ServerSideNetworkHandler *server_side_network_handler = (ServerSideNetworkHandler *) minecraft->network_handler; + chat_send_message(server_side_network_handler, *Strings_default_username, message); } else { // Client - RakNetInstance_send_t RakNetInstance_send = *(RakNetInstance_send_t *) (rak_net_instance_vtable + RakNetInstance_send_vtable_offset); - (*RakNetInstance_send)(rak_net_instance, packet); + rak_net_instance->vtable->send(rak_net_instance, (Packet *) packet); } } // Manually Send (And Loopback) ChatPacket -static void CommandServer_parse_CommandServer_dispatchPacket_injection(unsigned char *command_server, unsigned char *packet) { - unsigned char *minecraft = *(unsigned char **) (command_server + CommandServer_minecraft_property_offset); +static void CommandServer_parse_CommandServer_dispatchPacket_injection(CommandServer *command_server, Packet *packet) { + Minecraft *minecraft = command_server->minecraft; if (minecraft != NULL) { - chat_handle_packet_send(minecraft, packet); + chat_handle_packet_send(minecraft, (ChatPacket *) packet); } } // Handle ChatPacket Server-Side -static void ServerSideNetworkHandler_handle_ChatPacket_injection(unsigned char *server_side_network_handler, RakNet_RakNetGUID *rak_net_guid, unsigned char *chat_packet) { - unsigned char *player = (*ServerSideNetworkHandler_getPlayer)(server_side_network_handler, rak_net_guid); +static void ServerSideNetworkHandler_handle_ChatPacket_injection(ServerSideNetworkHandler *server_side_network_handler, RakNet_RakNetGUID *rak_net_guid, ChatPacket *chat_packet) { + Player *player = (*ServerSideNetworkHandler_getPlayer)(server_side_network_handler, rak_net_guid); if (player != NULL) { - char *username = *(char **) (player + Player_username_property_offset); - char *message = *(char **) (chat_packet + ChatPacket_message_property_offset); - chat_send_message(server_side_network_handler, username, message); + const char *username = player->username.c_str(); + char *message = chat_packet->message; + chat_send_message(server_side_network_handler, (char *) username, message); } } @@ -112,7 +110,7 @@ void _chat_queue_message(char *message) { } // Empty Queue unsigned int old_chat_counter = 0; -static void send_queued_messages(unsigned char *minecraft) { +static void send_queued_messages(Minecraft *minecraft) { // Lock pthread_mutex_lock(&queue_mutex); // If Message Was Submitted, No Other Chat Windows Are Open, And The Game Is Not Paused, Then Re-Lock Cursor diff --git a/mods/src/creative/creative.cpp b/mods/src/creative/creative.cpp index 8940d7bd47..4046578567 100644 --- a/mods/src/creative/creative.cpp +++ b/mods/src/creative/creative.cpp @@ -8,20 +8,26 @@ #ifndef MCPI_SERVER_MODE // Add Item To Inventory -static void inventory_add_item(unsigned char *inventory, unsigned char *item, bool is_tile) { +static void inventory_add_item(FillingContainer *inventory, Item *item) { ItemInstance *item_instance = new ItemInstance; ALLOC_CHECK(item_instance); - item_instance = (*(is_tile ? ItemInstance_constructor_tile : ItemInstance_constructor_item))(item_instance, item); + item_instance = (*ItemInstance_constructor_item)(item_instance, item); + (*FillingContainer_addItem)(inventory, item_instance); +} +static void inventory_add_item(FillingContainer *inventory, Tile *item) { + ItemInstance *item_instance = new ItemInstance; + ALLOC_CHECK(item_instance); + item_instance = (*ItemInstance_constructor_tile)(item_instance, item); (*FillingContainer_addItem)(inventory, item_instance); } // Expand Creative Inventory -static void Inventory_setupDefault_FillingContainer_addItem_call_injection(unsigned char *filling_container) { +static void Inventory_setupDefault_FillingContainer_addItem_call_injection(FillingContainer *filling_container) { // Add Items - inventory_add_item(filling_container, *Item_flintAndSteel, false); - inventory_add_item(filling_container, *Item_snowball, false); - inventory_add_item(filling_container, *Item_egg, false); - inventory_add_item(filling_container, *Item_shears, false); + inventory_add_item(filling_container, *Item_flintAndSteel); + inventory_add_item(filling_container, *Item_snowball); + inventory_add_item(filling_container, *Item_egg); + inventory_add_item(filling_container, *Item_shears); // Dyes for (int i = 0; i < 16; i++) { if (i == 15) { @@ -33,20 +39,20 @@ static void Inventory_setupDefault_FillingContainer_addItem_call_injection(unsig new_item_instance = (*ItemInstance_constructor_item_extra)(new_item_instance, *Item_dye_powder, 1, i); (*FillingContainer_addItem)(filling_container, new_item_instance); } - inventory_add_item(filling_container, *Item_camera, false); + inventory_add_item(filling_container, *Item_camera); // Add Tiles - inventory_add_item(filling_container, *Tile_water, true); - inventory_add_item(filling_container, *Tile_lava, true); - inventory_add_item(filling_container, *Tile_calmWater, true); - inventory_add_item(filling_container, *Tile_calmLava, true); - inventory_add_item(filling_container, *Tile_glowingObsidian, true); - inventory_add_item(filling_container, *Tile_web, true); - inventory_add_item(filling_container, *Tile_topSnow, true); - inventory_add_item(filling_container, *Tile_ice, true); - inventory_add_item(filling_container, *Tile_invisible_bedrock, true); - inventory_add_item(filling_container, *Tile_bedrock, true); - inventory_add_item(filling_container, *Tile_info_updateGame1, true); - inventory_add_item(filling_container, *Tile_info_updateGame2, true); + inventory_add_item(filling_container, *Tile_water); + inventory_add_item(filling_container, *Tile_lava); + inventory_add_item(filling_container, *Tile_calmWater); + inventory_add_item(filling_container, *Tile_calmLava); + inventory_add_item(filling_container, *Tile_glowingObsidian); + inventory_add_item(filling_container, *Tile_web); + inventory_add_item(filling_container, *Tile_topSnow); + inventory_add_item(filling_container, *Tile_ice); + inventory_add_item(filling_container, *Tile_invisible_bedrock); + inventory_add_item(filling_container, *Tile_bedrock); + inventory_add_item(filling_container, *Tile_info_updateGame1); + inventory_add_item(filling_container, *Tile_info_updateGame2); // Nether Reactor for (int i = 0; i < 3; i++) { if (i == 0) { @@ -80,19 +86,19 @@ static void Inventory_setupDefault_FillingContainer_addItem_call_injection(unsig #endif // Hook Specific TileItem Constructor -static unsigned char *Tile_initTiles_TileItem_injection(unsigned char *tile_item, int32_t id) { +static TileItem *Tile_initTiles_TileItem_injection(TileItem *tile_item, int32_t id) { // Call Original Method - unsigned char *ret = (*TileItem)(tile_item, id); + (*TileItem_constructor)(tile_item, id); // Switch VTable - *(unsigned char **) tile_item = AuxDataTileItem_vtable; + tile_item->vtable = (TileItem_vtable *) AuxDataTileItem_vtable_base; // Configure Item - *(bool *) (tile_item + Item_is_stacked_by_data_property_offset) = true; - *(int32_t *) (tile_item + Item_max_damage_property_offset) = 0; - *(unsigned char **) (tile_item + AuxDataTileItem_icon_tile_property_offset) = Tile_tiles[id + 0x100]; + tile_item->is_stacked_by_data = true; + tile_item->max_damage = 0; + ((AuxDataTileItem *) tile_item)->icon_tile = Tile_tiles[id + 0x100]; // Return - return ret; + return tile_item; } // Check Restriction Status diff --git a/mods/src/death/death.cpp b/mods/src/death/death.cpp index c70c7e22b4..2679d061a8 100644 --- a/mods/src/death/death.cpp +++ b/mods/src/death/death.cpp @@ -7,9 +7,9 @@ #include // Death Messages -static std::string get_death_message(unsigned char *player) { +static std::string get_death_message(Player *player) { // Get Username - std::string *username = (std::string *) (player + Player_username_property_offset); + std::string *username = &player->username; // Prepare Death Message std::string message; @@ -20,44 +20,36 @@ static std::string get_death_message(unsigned char *player) { return message; } -// Common Death Message Logic -static void Player_actuallyHurt_injection_helper(unsigned char *player, int32_t damage, bool is_local_player) { - // Store Old Health - int32_t old_health = *(int32_t *) (player + Mob_health_property_offset); - - // Call Original Method - (*(is_local_player ? LocalPlayer_actuallyHurt : Mob_actuallyHurt))(player, damage); - - // Store New Health - int32_t new_health = *(int32_t *) (player + Mob_health_property_offset); - - // Get Variables - unsigned char *minecraft = *(unsigned char **) (player + (is_local_player ? LocalPlayer_minecraft_property_offset : ServerPlayer_minecraft_property_offset)); - unsigned char *rak_net_instance = *(unsigned char **) (minecraft + Minecraft_rak_net_instance_property_offset); - unsigned char *rak_net_instance_vtable = *(unsigned char **) rak_net_instance; - // Only Run On Server-Side - RakNetInstance_isServer_t RakNetInstance_isServer = *(RakNetInstance_isServer_t *) (rak_net_instance_vtable + RakNetInstance_isServer_vtable_offset); - if ((*RakNetInstance_isServer)(rak_net_instance)) { - // Check Health - if (new_health < 1 && old_health >= 1) { - // Get Death Message - std::string message = get_death_message(player); - - // Post Death Message - unsigned char *server_side_network_handler = *(unsigned char **) (minecraft + Minecraft_network_handler_property_offset); - (*ServerSideNetworkHandler_displayGameMessage)(server_side_network_handler, message); - } +// Death Message Logic +#define Player_actuallyHurt_injection(type) \ + static void type##Player_actuallyHurt_injection(type##Player *player, int32_t damage) { \ + /* Store Old Health */ \ + int32_t old_health = player->health; \ + \ + /* Call Original Method */ \ + (*type##Player_actuallyHurt_non_virtual)(player, damage); \ + \ + /* Store New Health */ \ + int32_t new_health = player->health; \ + \ + /* Get Variables */ \ + Minecraft *minecraft = player->minecraft; \ + RakNetInstance *rak_net_instance = minecraft->rak_net_instance; \ + /* Only Run On Server-Side */ \ + if (rak_net_instance->vtable->isServer(rak_net_instance)) { \ + /* Check Health */ \ + if (new_health < 1 && old_health >= 1) { \ + /* Get Death Message */ \ + std::string message = get_death_message((Player *) player); \ + \ + /* Post Death Message */ \ + ServerSideNetworkHandler *server_side_network_handler = (ServerSideNetworkHandler *) minecraft->network_handler; \ + (*ServerSideNetworkHandler_displayGameMessage)(server_side_network_handler, &message); \ + } \ + } \ } -} - -// ServerPlayer Death Message Logic -static void ServerPlayer_actuallyHurt_injection(unsigned char *player, int32_t damage) { - Player_actuallyHurt_injection_helper(player, damage, false); -} -// LocalPlayer Death Message Logic -static void LocalPlayer_actuallyHurt_injection(unsigned char *player, int32_t damage) { - Player_actuallyHurt_injection_helper(player, damage, true); -} +Player_actuallyHurt_injection(Local) +Player_actuallyHurt_injection(Server) // Init void init_death() { diff --git a/mods/src/game-mode/game-mode.c b/mods/src/game-mode/game-mode.c index 66ca18bf3f..0edcff2560 100644 --- a/mods/src/game-mode/game-mode.c +++ b/mods/src/game-mode/game-mode.c @@ -21,14 +21,14 @@ static void set_is_survival(int new_is_survival) { patch((void *) 0x16ee4, size_patch); // Replace Default CreatorMode Constructor With CreatorMode Or SurvivalMode Constructor - overwrite_call((void *) 0x16ef4, new_is_survival ? SurvivalMode : CreatorMode); + overwrite_call((void *) 0x16ef4, new_is_survival ? (void *) SurvivalMode_constructor : (void *) CreatorMode_constructor); is_survival = new_is_survival; } } // Handle Gamemode Switching -static void Minecraft_setIsCreativeMode_injection(unsigned char *this, int32_t new_game_mode) { +static void Minecraft_setIsCreativeMode_injection(Minecraft *this, int32_t new_game_mode) { set_is_survival(!new_game_mode); // Call Original Method @@ -36,7 +36,7 @@ static void Minecraft_setIsCreativeMode_injection(unsigned char *this, int32_t n } // Disable CreatorMode-Specific API Features (Polling Block Hits) In SurvivalMode, This Is Preferable To Crashing -static unsigned char *Minecraft_getCreator_injection(unsigned char *minecraft) { +static unsigned char *Minecraft_getCreator_injection(Minecraft *minecraft) { if (is_survival) { // SurvivalMode, Return NULL return NULL; @@ -54,7 +54,7 @@ void init_game_mode() { overwrite_calls((void *) Minecraft_setIsCreativeMode, (void *) Minecraft_setIsCreativeMode_injection); // Replace CreatorLevel With ServerLevel (This Fixes Beds And Mob Spawning) - overwrite_call((void *) 0x16f84, (void *) ServerLevel); + overwrite_call((void *) 0x16f84, (void *) ServerLevel_constructor); // Allocate Correct Size For ServerLevel uint32_t level_size = SERVER_LEVEL_SIZE; diff --git a/mods/src/game-mode/ui.cpp b/mods/src/game-mode/ui.cpp index 9ca899fa3e..eb8dee6823 100644 --- a/mods/src/game-mode/ui.cpp +++ b/mods/src/game-mode/ui.cpp @@ -51,12 +51,12 @@ typedef enum { DIALOG_OPEN, DIALOG_SUCCESS } create_world_state_dialog_t; -typedef struct { +struct create_world_state_t { volatile create_world_state_dialog_t dialog_state = DIALOG_CLOSED; volatile char *name = NULL; volatile int32_t game_mode = 0; volatile int32_t seed = 0; -} create_world_state_t; +}; static create_world_state_t create_world_state; // Destructor __attribute__((destructor)) static void _free_create_world_state_name() { @@ -80,9 +80,9 @@ static void reset_create_world_state() { #define GAME_MODE_DIALOG_SIZE "200" static void *create_world_thread(__attribute__((unused)) void *nop) { // Run Dialogs + char *world_name = NULL; { // World Name - char *world_name = NULL; { // Open const char *command[] = { @@ -201,6 +201,7 @@ static void *create_world_thread(__attribute__((unused)) void *nop) { pthread_mutex_lock(&create_world_state_lock); reset_create_world_state(); pthread_mutex_unlock(&create_world_state_lock); + free(world_name); // Return return NULL; } @@ -214,15 +215,10 @@ static void open_create_world() { pthread_create(&thread, NULL, create_world_thread, NULL); } -// Get Minecraft From Screen -static unsigned char *get_minecraft_from_screen(unsigned char *screen) { - return *(unsigned char **) (screen + Screen_minecraft_property_offset); -} - // Create World -static void create_world(unsigned char *host_screen, std::string folder_name) { +static void create_world(Screen *host_screen, std::string folder_name) { // Get Minecraft - unsigned char *minecraft = get_minecraft_from_screen(host_screen); + Minecraft *minecraft = host_screen->minecraft; // Settings LevelSettings settings; @@ -231,16 +227,16 @@ static void create_world(unsigned char *host_screen, std::string folder_name) { // Create World std::string world_name = (char *) create_world_state.name; - (*Minecraft_selectLevel)(minecraft, folder_name, world_name, settings); + minecraft->vtable->selectLevel(minecraft, &folder_name, &world_name, &settings); // Multiplayer (*Minecraft_hostMultiplayer)(minecraft, 19132); // Open ProgressScreen - unsigned char *screen = (unsigned char *) ::operator new(PROGRESS_SCREEN_SIZE); + ProgressScreen *screen = alloc_ProgressScreen(); ALLOC_CHECK(screen); - screen = (*ProgressScreen)(screen); - (*Minecraft_setScreen)(minecraft, screen); + screen = (*ProgressScreen_constructor)(screen); + (*Minecraft_setScreen)(minecraft, (Screen *) screen); // Reset reset_create_world_state(); @@ -248,11 +244,11 @@ static void create_world(unsigned char *host_screen, std::string folder_name) { // Redirect Create World Button #define create_SelectWorldScreen_tick_injection(prefix) \ - static void prefix##SelectWorldScreen_tick_injection(unsigned char *screen) { \ + static void prefix##SelectWorldScreen_tick_injection(prefix##SelectWorldScreen *screen) { \ /* Lock */ \ pthread_mutex_lock(&create_world_state_lock); \ \ - bool *should_create_world = (bool *) (screen + prefix##SelectWorldScreen_should_create_world_property_offset); \ + bool *should_create_world = &screen->should_create_world; \ if (*should_create_world) { \ /* Check State */ \ if (create_world_state.dialog_state == DIALOG_CLOSED) { \ @@ -264,7 +260,7 @@ static void create_world(unsigned char *host_screen, std::string folder_name) { *should_create_world = false; \ } else { \ /* Call Original Method */ \ - (*prefix##SelectWorldScreen_tick)(screen); \ + (*prefix##SelectWorldScreen_tick_non_virtual)(screen); \ } \ \ /* Create World If Dialog Succeeded */ \ @@ -273,10 +269,10 @@ static void create_world(unsigned char *host_screen, std::string folder_name) { \ /* Get New World Name */ \ std::string name = (char *) create_world_state.name; \ - std::string new_name = (*prefix##SelectWorldScreen_getUniqueLevelName)(screen, name); \ + std::string new_name = (*prefix##SelectWorldScreen_getUniqueLevelName)(screen, &name); \ \ /* Create World */ \ - create_world(screen, new_name); \ + create_world((Screen *) screen, new_name); \ } \ \ /* Lock/Unlock UI */ \ diff --git a/mods/src/home/home.c b/mods/src/home/home.c index 201ae15b11..8da3d686cc 100644 --- a/mods/src/home/home.c +++ b/mods/src/home/home.c @@ -24,7 +24,7 @@ __attribute__((destructor)) static void _free_home() { // Init void init_home() { // Store Data In ~/.minecraft-pi Instead Of ~/.minecraft - patch_address((void *) default_path, (void *) HOME_SUBDIRECTORY_FOR_GAME_DATA); + patch_address((void *) Strings_default_path, (void *) HOME_SUBDIRECTORY_FOR_GAME_DATA); // The override code resolves assets manually, // making changing directory redundant. diff --git a/mods/src/init/init.c b/mods/src/init/init.c index 86c8638238..5823111b15 100644 --- a/mods/src/init/init.c +++ b/mods/src/init/init.c @@ -1,12 +1,12 @@ #include - #include - #include +#include __attribute__((constructor)) static void init() { media_ensure_loaded(); run_tests(); + init_symbols(); init_version(); init_compat(); #ifdef MCPI_SERVER_MODE diff --git a/mods/src/input/attack.c b/mods/src/input/attack.c index 9f40957282..9968646b3e 100644 --- a/mods/src/input/attack.c +++ b/mods/src/input/attack.c @@ -14,15 +14,15 @@ void input_set_is_left_click(int val) { } // Add Attacking To MouseBuildInput -static int32_t MouseBuildInput_tickBuild_injection(unsigned char *mouse_build_input, unsigned char *local_player, uint32_t *build_action_intention_return) { +static int32_t MouseBuildInput_tickBuild_injection(MouseBuildInput *mouse_build_input, Player *local_player, uint32_t *build_action_intention_return) { // Call Original Method - int32_t ret = (*MouseBuildInput_tickBuild)(mouse_build_input, local_player, build_action_intention_return); + int32_t ret = (*MouseBuildInput_tickBuild_non_virtual)(mouse_build_input, local_player, build_action_intention_return); // Use Attack/Place BuildActionIntention If No Other Valid BuildActionIntention Was Selected And This Was Not A Repeated Left Click if (ret != 0 && is_left_click == 1 && *build_action_intention_return == 0xa) { // Get Target HitResult - unsigned char *minecraft = *(unsigned char **) (local_player + LocalPlayer_minecraft_property_offset); - HitResult *hit_result = (HitResult *) (minecraft + Minecraft_hit_result_property_offset); + Minecraft *minecraft = ((LocalPlayer *) local_player)->minecraft; + HitResult *hit_result = &minecraft->hit_result; int32_t hit_result_type = hit_result->type; // Check if The Target Is An Entity Using HitResult if (hit_result_type == 1) { @@ -37,14 +37,12 @@ static int32_t MouseBuildInput_tickBuild_injection(unsigned char *mouse_build_in // Fix Holding Attack static bool last_player_attack_successful = 0; -static bool Player_attack_Entity_hurt_injection(unsigned char *entity, unsigned char *attacker, int32_t damage) { +static bool Player_attack_Entity_hurt_injection(Entity *entity, Entity *attacker, int32_t damage) { // Call Original Method - unsigned char *entity_vtable = *(unsigned char **) entity; - Entity_hurt_t Entity_hurt = *(Entity_hurt_t *) (entity_vtable + Entity_hurt_vtable_offset); - last_player_attack_successful = (*Entity_hurt)(entity, attacker, damage); + last_player_attack_successful = entity->vtable->hurt(entity, attacker, damage); return last_player_attack_successful; } -static ItemInstance *Player_attack_Inventory_getSelected_injection(unsigned char *inventory) { +static ItemInstance *Player_attack_Inventory_getSelected_injection(Inventory *inventory) { // Check If Attack Was Successful if (!last_player_attack_successful) { return NULL; diff --git a/mods/src/input/bow.c b/mods/src/input/bow.c index a0f2bb9c83..1a243b0dad 100644 --- a/mods/src/input/bow.c +++ b/mods/src/input/bow.c @@ -15,16 +15,12 @@ void input_set_is_right_click(int val) { static int fix_bow = 0; // Handle Bow & Arrow -static void _handle_bow(unsigned char *minecraft) { +static void _handle_bow(Minecraft *minecraft) { if (fix_bow && !is_right_click) { - // GameMode Is Offset From minecraft By 0x160 - // Player Is Offset From minecraft By 0x18c - unsigned char *game_mode = *(unsigned char **) (minecraft + Minecraft_game_mode_property_offset); - unsigned char *player = *(unsigned char **) (minecraft + Minecraft_player_property_offset); - if (player != NULL && game_mode != NULL && (*Player_isUsingItem)(player)) { - unsigned char *game_mode_vtable = *(unsigned char **) game_mode; - GameMode_releaseUsingItem_t GameMode_releaseUsingItem = *(GameMode_releaseUsingItem_t *) (game_mode_vtable + GameMode_releaseUsingItem_vtable_offset); - (*GameMode_releaseUsingItem)(game_mode, player); + GameMode *game_mode = minecraft->game_mode; + LocalPlayer *player = minecraft->player; + if (player != NULL && game_mode != NULL && (*LocalPlayer_isUsingItem)(player)) { + game_mode->vtable->releaseUsingItem(game_mode, (Player *) player); } } } diff --git a/mods/src/input/crafting.cpp b/mods/src/input/crafting.cpp index b3975a7fd8..c0bad592d4 100644 --- a/mods/src/input/crafting.cpp +++ b/mods/src/input/crafting.cpp @@ -10,16 +10,16 @@ static int should_open_crafting = 0; void input_open_crafting() { should_open_crafting = 1; } -static void _handle_open_crafting(unsigned char *minecraft) { +static void _handle_open_crafting(Minecraft *minecraft) { if (should_open_crafting) { should_open_crafting = 0; // Set Screen if (!creative_is_restricted() || !(*Minecraft_isCreativeMode)(minecraft)) { - unsigned char *screen = (unsigned char *) ::operator new(WORKBENCH_SCREEN_SIZE); + WorkbenchScreen *screen = alloc_WorkbenchScreen(); ALLOC_CHECK(screen); - screen = (*WorkbenchScreen)(screen, 0); - (*Minecraft_setScreen)(minecraft, screen); + screen = (*WorkbenchScreen_constructor)(screen, 0); + (*Minecraft_setScreen)(minecraft, (Screen *) screen); } } } diff --git a/mods/src/input/drop.cpp b/mods/src/input/drop.cpp index 7038cbefd2..b8189354a4 100644 --- a/mods/src/input/drop.cpp +++ b/mods/src/input/drop.cpp @@ -24,23 +24,17 @@ void input_drop(int drop_slot) { } // Handle Drop Item Presses -static void _handle_drop(unsigned char *minecraft) { - if (((*(unsigned char **) (minecraft + Minecraft_screen_property_offset)) == NULL) && (!creative_is_restricted() || !(*Minecraft_isCreativeMode)(minecraft)) && (drop_item_presses > 0 || drop_slot_pressed)) { +static void _handle_drop(Minecraft *minecraft) { + if ((minecraft->screen == NULL) && (!creative_is_restricted() || !(*Minecraft_isCreativeMode)(minecraft)) && (drop_item_presses > 0 || drop_slot_pressed)) { // Get Player - unsigned char *player = *(unsigned char **) (minecraft + Minecraft_player_property_offset); + LocalPlayer *player = minecraft->player; if (player != NULL) { // Get Selected Slot - int32_t selected_slot = misc_get_real_selected_slot(player); - unsigned char *inventory = *(unsigned char **) (player + Player_inventory_property_offset); - - // Prepare - unsigned char *player_vtable = *(unsigned char **) player; - Player_drop_t Player_drop = *(Player_drop_t *) (player_vtable + Player_drop_vtable_offset); - unsigned char *inventory_vtable = *(unsigned char **) inventory; - FillingContainer_getItem_t FillingContainer_getItem = *(FillingContainer_getItem_t *) (inventory_vtable + FillingContainer_getItem_vtable_offset); + int32_t selected_slot = misc_get_real_selected_slot((Player *) player); + Inventory *inventory = player->inventory; // Get Item - ItemInstance *inventory_item = (*FillingContainer_getItem)(inventory, selected_slot); + ItemInstance *inventory_item = inventory->vtable->getItem(inventory, selected_slot); // Check if (inventory_item != NULL && inventory_item->count > 0) { // Copy @@ -65,12 +59,12 @@ static void _handle_drop(unsigned char *minecraft) { // Empty Slot If Needed if (inventory_item->count < 1) { - (*FillingContainer_release)(inventory, selected_slot); - (*FillingContainer_compressLinkedSlotList)(inventory, selected_slot); + (*Inventory_release)(inventory, selected_slot); + (*Inventory_compressLinkedSlotList)(inventory, selected_slot); } // Drop - (*Player_drop)(player, dropped_item, false); + player->vtable->drop(player, dropped_item, false); } } } diff --git a/mods/src/input/input.cpp b/mods/src/input/input.cpp index 3cc410f4bd..db3777f9d3 100644 --- a/mods/src/input/input.cpp +++ b/mods/src/input/input.cpp @@ -19,7 +19,7 @@ void input_run_on_tick(input_tick_function_t function) { } // Handle Input Fixes -static void Minecraft_tickInput_injection(unsigned char *minecraft) { +static void Minecraft_tickInput_injection(Minecraft *minecraft) { // Call Original Method (*Minecraft_tickInput)(minecraft); diff --git a/mods/src/input/misc.c b/mods/src/input/misc.c index 1eb693cc1d..2f84f66032 100644 --- a/mods/src/input/misc.c +++ b/mods/src/input/misc.c @@ -21,42 +21,38 @@ int input_back() { } // Handle Back Button Presses -static void _handle_back(unsigned char *minecraft) { +static void _handle_back(Minecraft *minecraft) { // If Minecraft's Level property is initialized, but Minecraft's Player property is NULL, then Minecraft::handleBack may crash. - if ((*(unsigned char **) (minecraft + Minecraft_level_property_offset)) != NULL && (*(unsigned char **) (minecraft + Minecraft_player_property_offset)) == NULL) { + if (minecraft->level != NULL && minecraft->player == NULL) { // Unable to safely run Minecraft::handleBack, deferring until safe. return; } // Send Event - unsigned char *minecraft_vtable = *(unsigned char **) minecraft; - Minecraft_handleBack_t Minecraft_handleBack = *(Minecraft_handleBack_t *) (minecraft_vtable + Minecraft_handleBack_vtable_offset); for (int i = 0; i < back_button_presses; i++) { - (*Minecraft_handleBack)(minecraft, 0); + minecraft->vtable->handleBack(minecraft, 0); } back_button_presses = 0; } // Fix OptionsScreen Ignoring The Back Button -static int32_t OptionsScreen_handleBackEvent_injection(unsigned char *screen, bool do_nothing) { +static int32_t OptionsScreen_handleBackEvent_injection(OptionsScreen *screen, bool do_nothing) { if (!do_nothing) { - unsigned char *minecraft = *(unsigned char **) (screen + Screen_minecraft_property_offset); + Minecraft *minecraft = screen->minecraft; (*Minecraft_setScreen)(minecraft, NULL); } return 1; } // Fix "Sleeping Beauty" Bug -static int32_t InBedScreen_handleBackEvent_injection(unsigned char *screen, bool do_nothing) { +static int32_t InBedScreen_handleBackEvent_injection(InBedScreen *screen, bool do_nothing) { if (!do_nothing) { // Close Screen - unsigned char *minecraft = *(unsigned char **) (screen + Screen_minecraft_property_offset); + Minecraft *minecraft = screen->minecraft; (*Minecraft_setScreen)(minecraft, NULL); // Stop Sleeping - unsigned char *player = *(unsigned char **) (minecraft + Minecraft_player_property_offset); + LocalPlayer *player = minecraft->player; if (player != NULL) { - unsigned char *player_vtable = *(unsigned char **) player; - Player_stopSleepInBed_t Player_stopSleepInBed = *(Player_stopSleepInBed_t *) (player_vtable + Player_stopSleepInBed_vtable_offset); - (*Player_stopSleepInBed)(player, 1, 1, 1); + player->vtable->stopSleepInBed(player, 1, 1, 1); } } return 1; @@ -69,7 +65,7 @@ void input_set_mouse_grab_state(int state) { } // Grab/Un-Grab Mouse -static void _handle_mouse_grab(unsigned char *minecraft) { +static void _handle_mouse_grab(Minecraft *minecraft) { if (mouse_grab_state == -1) { // Grab (*Minecraft_grabMouse)(minecraft); @@ -83,7 +79,7 @@ static void _handle_mouse_grab(unsigned char *minecraft) { #include // Block UI Interaction When Mouse Is Locked -static bool Gui_tickItemDrop_Minecraft_isCreativeMode_call_injection(unsigned char *minecraft) { +static bool Gui_tickItemDrop_Minecraft_isCreativeMode_call_injection(Minecraft *minecraft) { if (!enable_misc || SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF) { // Call Original Method return creative_is_restricted() && (*Minecraft_isCreativeMode)(minecraft); @@ -94,7 +90,7 @@ static bool Gui_tickItemDrop_Minecraft_isCreativeMode_call_injection(unsigned ch } // Block UI Interaction When Mouse Is Locked -static void Gui_handleClick_injection(unsigned char *gui, int32_t param_2, int32_t param_3, int32_t param_4) { +static void Gui_handleClick_injection(Gui *gui, int32_t param_2, int32_t param_3, int32_t param_4) { if (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF) { // Call Original Method (*Gui_handleClick)(gui, param_2, param_3, param_4); diff --git a/mods/src/input/toggle.c b/mods/src/input/toggle.c index ad26f61952..e20a919f88 100644 --- a/mods/src/input/toggle.c +++ b/mods/src/input/toggle.c @@ -19,59 +19,59 @@ void input_third_person() { } // Handle Toggle Options -static void _handle_toggle_options(unsigned char *minecraft) { +static void _handle_toggle_options(Minecraft *minecraft) { if (enable_toggles) { // Handle Functions - unsigned char *options = minecraft + Minecraft_options_property_offset; + Options *options = &minecraft->options; if (hide_gui_toggle % 2 != 0) { // Toggle Hide GUI - *(options + Options_hide_gui_property_offset) = *(options + Options_hide_gui_property_offset) ^ 1; + options->hide_gui = options->hide_gui ^ 1; } hide_gui_toggle = 0; if (third_person_toggle % 2 != 0) { // Toggle Third Person - *(options + Options_third_person_property_offset) = (*(options + Options_third_person_property_offset) + 1) % 3; + options->third_person = (options->third_person + 1) % 3; } third_person_toggle = 0; // Fix Broken Value From Third-Person OptionsButton Toggle // (Because Front-Facing Code Repurposes A Boolean As A Ternary) - if (*(options + Options_third_person_property_offset) == 3) { - *(options + Options_third_person_property_offset) = 0; + if (options->third_person == 3) { + options->third_person = 0; } } } // Font-Facing View -static void invert_rotation(unsigned char *entity) { +static void invert_rotation(Entity *entity) { if (entity != NULL) { - *(float *) (entity + Entity_yaw_property_offset) = 180.f + (*(float *) (entity + Entity_yaw_property_offset)); - *(float *) (entity + Entity_old_yaw_property_offset) = 180.f + (*(float *) (entity + Entity_old_yaw_property_offset)); - *(float *) (entity + Entity_pitch_property_offset) = -(*(float *) (entity + Entity_pitch_property_offset)); - *(float *) (entity + Entity_old_pitch_property_offset) = -(*(float *) (entity + Entity_old_pitch_property_offset)); + entity->yaw = 180.f + entity->yaw; + entity->old_yaw = 180.f + entity->old_yaw; + entity->pitch = -entity->pitch; + entity->old_pitch = -entity->old_pitch; } } -static void revert_rotation(unsigned char *entity) { +static void revert_rotation(Entity *entity) { if (entity != NULL) { - *(float *) (entity + Entity_yaw_property_offset) = -180.f + (*(float *) (entity + Entity_yaw_property_offset)); - *(float *) (entity + Entity_old_yaw_property_offset) = -180.f + (*(float *) (entity + Entity_old_yaw_property_offset)); - *(float *) (entity + Entity_pitch_property_offset) = -(*(float *) (entity + Entity_pitch_property_offset)); - *(float *) (entity + Entity_old_pitch_property_offset) = -(*(float *) (entity + Entity_old_pitch_property_offset)); + entity->yaw = -180.f + entity->yaw; + entity->old_yaw = -180.f + entity->old_yaw; + entity->pitch = -entity->pitch; + entity->old_pitch = -entity->old_pitch; } } static int is_front_facing = 0; -static unsigned char *stored_player = NULL; -static void GameRenderer_setupCamera_injection(unsigned char *game_renderer, float param_1, int param_2) { +static LocalPlayer *stored_player = NULL; +static void GameRenderer_setupCamera_injection(GameRenderer *game_renderer, float param_1, int param_2) { // Get Objects - unsigned char *minecraft = *(unsigned char **) (game_renderer + GameRenderer_minecraft_property_offset); - stored_player = *(unsigned char **) (minecraft + Minecraft_player_property_offset); + Minecraft *minecraft = game_renderer->minecraft; + stored_player = minecraft->player; // Check If In Third-Person - unsigned char *options = minecraft + Minecraft_options_property_offset; - is_front_facing = (*(options + Options_third_person_property_offset) == 2); + Options *options = &minecraft->options; + is_front_facing = (options->third_person == 2); // Invert Rotation if (is_front_facing) { - invert_rotation(stored_player); + invert_rotation((Entity *) stored_player); } // Call Original Method @@ -79,21 +79,21 @@ static void GameRenderer_setupCamera_injection(unsigned char *game_renderer, flo // Revert if (is_front_facing) { - revert_rotation(stored_player); + revert_rotation((Entity *) stored_player); } } -static void ParticleEngine_render_injection(unsigned char *particle_engine, unsigned char *entity, float param_2) { +static void ParticleEngine_render_injection(ParticleEngine *particle_engine, Entity *entity, float param_2) { // Invert Rotation - if (is_front_facing && stored_player == entity) { - invert_rotation(stored_player); + if (is_front_facing && (Entity *) stored_player == entity) { + invert_rotation((Entity *) stored_player); } // Call Original Method (*ParticleEngine_render)(particle_engine, entity, param_2); // Revert - if (is_front_facing && stored_player == entity) { - revert_rotation(stored_player); + if (is_front_facing && (Entity *) stored_player == entity) { + revert_rotation((Entity *) stored_player); } } diff --git a/mods/src/misc/api.cpp b/mods/src/misc/api.cpp index bc2e88a8be..f0fecb7119 100644 --- a/mods/src/misc/api.cpp +++ b/mods/src/misc/api.cpp @@ -7,35 +7,35 @@ #include "misc-internal.h" // Callbacks -#define SETUP_CALLBACK(name) \ - static std::vector &get_misc_##name##_functions() { \ - static std::vector functions; \ +#define SETUP_CALLBACK(name, type) \ +static std::vector &get_misc_##name##_functions() { \ + static std::vector functions; \ return functions; \ } \ - static void handle_misc_##name(unsigned char *obj) { \ - for (misc_update_function_t function : get_misc_##name##_functions()) { \ + static void handle_misc_##name(type *obj) { \ + for (misc_update_function_##type##_t function : get_misc_##name##_functions()) { \ (*function)(obj); \ } \ } \ - void misc_run_on_##name(misc_update_function_t function) { \ + void misc_run_on_##name(misc_update_function_##type##_t function) { \ get_misc_##name##_functions().push_back(function); \ } // Run Functions On Update -SETUP_CALLBACK(update); +SETUP_CALLBACK(update, Minecraft); // Handle Custom Update Behavior -static void Minecraft_update_injection(unsigned char *minecraft) { +static void Minecraft_update_injection(Minecraft *minecraft) { // Call Original Method - (*Minecraft_update)(minecraft); + (*Minecraft_update_non_virtual)(minecraft); // Run Functions handle_misc_update(minecraft); } // Run Functions On Tick -SETUP_CALLBACK(tick); +SETUP_CALLBACK(tick, Minecraft); // Handle Custom Tick Behavior -static void Minecraft_tick_injection(unsigned char *minecraft, int32_t param_1, int32_t param_2) { +static void Minecraft_tick_injection(Minecraft *minecraft, int32_t param_1, int32_t param_2) { // Call Original Method (*Minecraft_tick)(minecraft, param_1, param_2); @@ -44,11 +44,11 @@ static void Minecraft_tick_injection(unsigned char *minecraft, int32_t param_1, } // Run Functions On Recipes Setup -SETUP_CALLBACK(recipes_setup); +SETUP_CALLBACK(recipes_setup, Recipes); // Handle Custom Recipes Setup Behavior -static unsigned char *Recipes_injection(unsigned char *recipes) { +static Recipes *Recipes_injection(Recipes *recipes) { // Call Original Method - (*Recipes)(recipes); + (*Recipes_constructor)(recipes); // Run Functions handle_misc_recipes_setup(recipes); @@ -58,11 +58,11 @@ static unsigned char *Recipes_injection(unsigned char *recipes) { } // Run Functions On Furnace Recipes Setup -SETUP_CALLBACK(furnace_recipes_setup); +SETUP_CALLBACK(furnace_recipes_setup, FurnaceRecipes); // Handle Custom Furnace Recipes Setup Behavior -static unsigned char *FurnaceRecipes_injection(unsigned char *recipes) { +static FurnaceRecipes *FurnaceRecipes_injection(FurnaceRecipes *recipes) { // Call Original Method - (*FurnaceRecipes)(recipes); + (*FurnaceRecipes_constructor)(recipes); // Run Functions handle_misc_furnace_recipes_setup(recipes); @@ -72,9 +72,9 @@ static unsigned char *FurnaceRecipes_injection(unsigned char *recipes) { } // Run Functions On Creative Inventory Setup -SETUP_CALLBACK(creative_inventory_setup); +SETUP_CALLBACK(creative_inventory_setup, FillingContainer); // Handle Custom Creative Inventory Setup Behavior -static void Inventory_setupDefault_FillingContainer_addItem_call_injection(unsigned char *filling_container, ItemInstance *item_instance) { +static void Inventory_setupDefault_FillingContainer_addItem_call_injection(FillingContainer *filling_container, ItemInstance *item_instance) { // Call Original Method (*FillingContainer_addItem)(filling_container, item_instance); // Run Functions @@ -82,7 +82,7 @@ static void Inventory_setupDefault_FillingContainer_addItem_call_injection(unsig } // Run Functions On Tiles Setup -SETUP_CALLBACK(tiles_setup); +SETUP_CALLBACK(tiles_setup, void); // Handle Custom Tiles Setup Behavior static void Tile_initTiles_injection() { // Run Functions @@ -93,7 +93,7 @@ static void Tile_initTiles_injection() { } // Run Functions On Items Setup -SETUP_CALLBACK(items_setup); +SETUP_CALLBACK(items_setup, void); // Handle Custom Items Setup Behavior static void Item_initItems_injection() { // Run Functions @@ -106,12 +106,12 @@ static void Item_initItems_injection() { // Init void _init_misc_api() { // Handle Custom Update Behavior - overwrite_calls((void *) Minecraft_update, (void *) Minecraft_update_injection); + overwrite_calls((void *) Minecraft_update_non_virtual, (void *) Minecraft_update_injection); // Handle Custom Tick Behavior overwrite_calls((void *) Minecraft_tick, (void *) Minecraft_tick_injection); // Handle Custom Recipe Setup Behavior - overwrite_calls((void *) Recipes, (void *) Recipes_injection); - overwrite_calls((void *) FurnaceRecipes, (void *) FurnaceRecipes_injection); + overwrite_calls((void *) Recipes_constructor, (void *) Recipes_injection); + overwrite_calls((void *) FurnaceRecipes_constructor, (void *) FurnaceRecipes_injection); // Handle Custom Creative Inventory Setup Behavior overwrite_call((void *) 0x8e0fc, (void *) Inventory_setupDefault_FillingContainer_addItem_call_injection); // Handle Custom Item/Tile Init Behavior diff --git a/mods/src/misc/logging.cpp b/mods/src/misc/logging.cpp index f6d1b602f7..c71241567c 100644 --- a/mods/src/misc/logging.cpp +++ b/mods/src/misc/logging.cpp @@ -8,11 +8,12 @@ // Print Chat To Log static bool Gui_addMessage_recursing = false; -static void Gui_addMessage_injection(unsigned char *gui, std::string const& text) { +static void Gui_addMessage_injection(Gui *gui, std::string *text) { // Sanitize Message - char *new_message = strdup(text.c_str()); + char *new_message = strdup(text->c_str()); ALLOC_CHECK(new_message); sanitize_string(&new_message, -1, 1); + std::string cpp_str = new_message; // Process Message if (!Gui_addMessage_recursing) { @@ -25,28 +26,29 @@ static void Gui_addMessage_injection(unsigned char *gui, std::string const& text free(safe_message); // Call Original Method - (*Gui_addMessage)(gui, std::string(new_message)); + (*Gui_addMessage)(gui, &cpp_str); // End Recursing Gui_addMessage_recursing = false; } else { // Call Original Method - (*Gui_addMessage)(gui, std::string(new_message)); + (*Gui_addMessage)(gui, &cpp_str); } // Free free(new_message); } -void misc_add_message(unsigned char *gui, const char *text) { - Gui_addMessage_injection(gui, text); +void misc_add_message(Gui *gui, const char *text) { + std::string str = text; + Gui_addMessage_injection(gui, &str); } // Print Progress Reports static int last_progress = -1; static const char *last_message = NULL; -static void print_progress(unsigned char *minecraft) { +static void print_progress(Minecraft *minecraft) { const char *message = (*Minecraft_getProgressMessage)(minecraft); - int32_t progress = *(int32_t *) (minecraft + Minecraft_progress_property_offset); + int32_t progress = minecraft->progress; if ((*Minecraft_isLevelGenerated)(minecraft)) { message = "Ready"; progress = -1; @@ -71,13 +73,13 @@ static void print_progress(unsigned char *minecraft) { } // Print Progress Reports Regularly -static void Minecraft_update_injection(unsigned char *minecraft) { +static void Minecraft_update_injection(Minecraft *minecraft) { // Print Progress Reports print_progress(minecraft); } // Log When Game Is Saved -void Level_saveLevelData_injection(unsigned char *level) { +void Level_saveLevelData_injection(Level *level) { // Print Log Message DEBUG("Saving Game"); diff --git a/mods/src/misc/misc.c b/mods/src/misc/misc.c index 994d61cc84..81f0c28299 100644 --- a/mods/src/misc/misc.c +++ b/mods/src/misc/misc.c @@ -29,47 +29,47 @@ #define DEFAULT_BUBBLES_PADDING 1 #define NUMBER_OF_SLOTS 9 static int use_classic_hud = 0; -static void Gui_renderHearts_GuiComponent_blit_hearts_injection(unsigned char *component, int32_t x_dest, int32_t y_dest, int32_t x_src, int32_t y_src, int32_t width_dest, int32_t height_dest, int32_t width_src, int32_t height_src) { - unsigned char *minecraft = *(unsigned char **) (component + Gui_minecraft_property_offset); +static void Gui_renderHearts_GuiComponent_blit_hearts_injection(Gui *component, int32_t x_dest, int32_t y_dest, int32_t x_src, int32_t y_src, int32_t width_dest, int32_t height_dest, int32_t width_src, int32_t height_src) { + Minecraft *minecraft = component->minecraft; x_dest -= DEFAULT_HUD_PADDING; - float width = ((float) *(int32_t *) (minecraft + Minecraft_screen_width_property_offset)) * *InvGuiScale; - float height = ((float) *(int32_t *) (minecraft + Minecraft_screen_height_property_offset)) * *InvGuiScale; + float width = ((float) minecraft->screen_width) * *Gui_InvGuiScale; + float height = ((float) minecraft->screen_height) * *Gui_InvGuiScale; x_dest += (width - (NUMBER_OF_SLOTS * SLOT_WIDTH)) / 2; y_dest -= DEFAULT_HUD_PADDING; y_dest += height - HUD_ELEMENT_HEIGHT - TOOLBAR_HEIGHT - NEW_HUD_PADDING; // Call Original Method - (*GuiComponent_blit)(component, x_dest, y_dest, x_src, y_src, width_dest, height_dest, width_src, height_src); + (*Gui_blit)(component, x_dest, y_dest, x_src, y_src, width_dest, height_dest, width_src, height_src); } -static void Gui_renderHearts_GuiComponent_blit_armor_injection(unsigned char *component, int32_t x_dest, int32_t y_dest, int32_t x_src, int32_t y_src, int32_t width_dest, int32_t height_dest, int32_t width_src, int32_t height_src) { - unsigned char *minecraft = *(unsigned char **) (component + Gui_minecraft_property_offset); +static void Gui_renderHearts_GuiComponent_blit_armor_injection(Gui *component, int32_t x_dest, int32_t y_dest, int32_t x_src, int32_t y_src, int32_t width_dest, int32_t height_dest, int32_t width_src, int32_t height_src) { + Minecraft *minecraft = component->minecraft; x_dest -= DEFAULT_HUD_PADDING + HUD_ELEMENT_WIDTH; - float width = ((float) *(int32_t *) (minecraft + Minecraft_screen_width_property_offset)) * *InvGuiScale; - float height = ((float) *(int32_t *) (minecraft + Minecraft_screen_height_property_offset)) * *InvGuiScale; + float width = ((float) minecraft->screen_width) * *Gui_InvGuiScale; + float height = ((float) minecraft->screen_height) * *Gui_InvGuiScale; x_dest += width - ((width - (NUMBER_OF_SLOTS * SLOT_WIDTH)) / 2) - HUD_ELEMENT_WIDTH; y_dest -= DEFAULT_HUD_PADDING; y_dest += height - HUD_ELEMENT_HEIGHT - TOOLBAR_HEIGHT - NEW_HUD_PADDING; // Call Original Method - (*GuiComponent_blit)(component, x_dest, y_dest, x_src, y_src, width_dest, height_dest, width_src, height_src); + (*Gui_blit)(component, x_dest, y_dest, x_src, y_src, width_dest, height_dest, width_src, height_src); } -static void Gui_renderBubbles_GuiComponent_blit_injection(unsigned char *component, int32_t x_dest, int32_t y_dest, int32_t x_src, int32_t y_src, int32_t width_dest, int32_t height_dest, int32_t width_src, int32_t height_src) { - unsigned char *minecraft = *(unsigned char **) (component + Gui_minecraft_property_offset); +static void Gui_renderBubbles_GuiComponent_blit_injection(Gui *component, int32_t x_dest, int32_t y_dest, int32_t x_src, int32_t y_src, int32_t width_dest, int32_t height_dest, int32_t width_src, int32_t height_src) { + Minecraft *minecraft = component->minecraft; x_dest -= DEFAULT_HUD_PADDING; - float width = ((float) *(int32_t *) (minecraft + Minecraft_screen_width_property_offset)) * *InvGuiScale; - float height = ((float) *(int32_t *) (minecraft + Minecraft_screen_height_property_offset)) * *InvGuiScale; + float width = ((float) minecraft->screen_width) * *Gui_InvGuiScale; + float height = ((float) minecraft->screen_height) * *Gui_InvGuiScale; x_dest += (width - (NUMBER_OF_SLOTS * SLOT_WIDTH)) / 2; y_dest -= DEFAULT_HUD_PADDING + DEFAULT_BUBBLES_PADDING + HUD_ELEMENT_HEIGHT; y_dest += height - HUD_ELEMENT_HEIGHT - TOOLBAR_HEIGHT - HUD_ELEMENT_HEIGHT - NEW_HUD_PADDING; // Call Original Method - (*GuiComponent_blit)(component, x_dest, y_dest, x_src, y_src, width_dest, height_dest, width_src, height_src); + (*Gui_blit)(component, x_dest, y_dest, x_src, y_src, width_dest, height_dest, width_src, height_src); } // Additional GUI Rendering static int hide_chat_messages = 0; static int render_selected_item_text = 0; -static void Gui_renderChatMessages_injection(unsigned char *gui, int32_t y_offset, uint32_t max_messages, bool disable_fading, unsigned char *font) { +static void Gui_renderChatMessages_injection(Gui *gui, int32_t y_offset, uint32_t max_messages, bool disable_fading, Font *font) { // Handle Classic HUD if (use_classic_hud) { - unsigned char *minecraft = *(unsigned char **) (gui + Gui_minecraft_property_offset); + Minecraft *minecraft = gui->minecraft; if (!(*Minecraft_isCreativeMode)(minecraft)) { y_offset -= (HUD_ELEMENT_HEIGHT * 2) + NEW_HUD_PADDING; } @@ -85,22 +85,22 @@ static void Gui_renderChatMessages_injection(unsigned char *gui, int32_t y_offse // Fix GL Mode glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Calculate Selected Item Text Scale - unsigned char *minecraft = *(unsigned char **) (gui + Gui_minecraft_property_offset); - int32_t screen_width = *(int32_t *) (minecraft + Minecraft_screen_width_property_offset); - float scale = ((float) screen_width) * *InvGuiScale; + Minecraft *minecraft = gui->minecraft; + int32_t screen_width = minecraft->screen_width; + float scale = ((float) screen_width) * *Gui_InvGuiScale; // Render Selected Item Text (*Gui_renderOnSelectItemNameText)(gui, (int32_t) scale, font, y_offset - 0x13); } } // Reset Selected Item Text Timer On Slot Select static uint32_t reset_selected_item_text_timer = 0; -static void Gui_tick_injection(unsigned char *gui) { +static void Gui_tick_injection(Gui *gui) { // Call Original Method (*Gui_tick)(gui); // Handle Reset if (render_selected_item_text) { - float *selected_item_text_timer = (float *) (gui + Gui_selected_item_text_timer_property_offset); + float *selected_item_text_timer = &gui->selected_item_text_timer; if (reset_selected_item_text_timer) { // Reset *selected_item_text_timer = 0; @@ -109,7 +109,7 @@ static void Gui_tick_injection(unsigned char *gui) { } } // Trigger Reset Selected Item Text Timer On Slot Select -static void Inventory_selectSlot_injection(unsigned char *inventory, int32_t slot) { +static void Inventory_selectSlot_injection(Inventory *inventory, int32_t slot) { // Call Original Method (*Inventory_selectSlot)(inventory, slot); @@ -120,7 +120,7 @@ static void Inventory_selectSlot_injection(unsigned char *inventory, int32_t slo } // Translucent Toolbar -static void Gui_renderToolBar_injection(unsigned char *gui, float param_1, int32_t param_2, int32_t param_3) { +static void Gui_renderToolBar_injection(Gui *gui, float param_1, int32_t param_2, int32_t param_3) { // Call Original Method int was_blend_enabled = glIsEnabled(GL_BLEND); if (!was_blend_enabled) { @@ -138,24 +138,24 @@ static void Gui_renderToolBar_glColor4f_injection(GLfloat red, GLfloat green, GL } // Fix Screen Rendering When GUI is Hidden -static void Screen_render_injection(unsigned char *screen, int32_t param_1, int32_t param_2, float param_3) { +static void Screen_render_injection(Screen *screen, int32_t param_1, int32_t param_2, float param_3) { // Fix glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Call Original Method - (*Screen_render)(screen, param_1, param_2, param_3); + (*Screen_render_non_virtual)(screen, param_1, param_2, param_3); } // Sanitize Username #define MAX_USERNAME_LENGTH 16 -static void LoginPacket_read_injection(unsigned char *packet, unsigned char *bit_stream) { +static void LoginPacket_read_injection(LoginPacket *packet, unsigned char *bit_stream) { // Call Original Method - (*LoginPacket_read)(packet, bit_stream); + (*LoginPacket_read_non_virtual)(packet, bit_stream); // Prepare - unsigned char *rak_string = packet + LoginPacket_username_property_offset; + RakNet_RakString *rak_string = &packet->username; // Get Original Username - unsigned char *shared_string = *(unsigned char **) (rak_string + RakNet_RakString_sharedString_property_offset); - char *c_str = *(char **) (shared_string + RakNet_RakString_SharedString_c_str_property_offset); + RakNet_RakString_SharedString *shared_string = rak_string->sharedString; + char *c_str = shared_string->c_str; // Sanitize char *new_username = strdup(c_str); ALLOC_CHECK(new_username); @@ -171,9 +171,9 @@ static void LoginPacket_read_injection(unsigned char *packet, unsigned char *bit // 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 // formatting functionality. -static unsigned char *RakNet_RakString_injection(unsigned char *rak_string, const char *format, ...) { +static RakNet_RakString *RakNet_RakString_injection(RakNet_RakString *rak_string, const char *format, ...) { // Call Original Method - return (*RakNet_RakString)(rak_string, "%s", format); + return (*RakNet_RakString_constructor)(rak_string, "%s", format); } // Print Error Message If RakNet Startup Fails @@ -196,9 +196,9 @@ static char *RAKNET_ERROR_NAMES[] = { #else #define PRINT_RAKNET_STARTUP_FAILURE WARN #endif -static RakNet_StartupResult RakNetInstance_host_RakNet_RakPeer_Startup_injection(unsigned char *rak_peer, unsigned short maxConnections, unsigned char *socketDescriptors, uint32_t socketDescriptorCount, int32_t threadPriority) { +static RakNet_StartupResult RakNetInstance_host_RakNet_RakPeer_Startup_injection(RakNet_RakPeer *rak_peer, unsigned short maxConnections, unsigned char *socketDescriptors, uint32_t socketDescriptorCount, int32_t threadPriority) { // Call Original Method - RakNet_StartupResult result = (*RakNet_RakPeer_Startup)(rak_peer, maxConnections, socketDescriptors, socketDescriptorCount, threadPriority); + RakNet_StartupResult result = rak_peer->vtable->Startup(rak_peer, maxConnections, socketDescriptors, socketDescriptorCount, threadPriority); // Print Error if (result != RAKNET_STARTED) { @@ -210,32 +210,30 @@ static RakNet_StartupResult RakNetInstance_host_RakNet_RakPeer_Startup_injection } // Fix Bug Where RakNetInstance Starts Pinging Potential Servers Before The "Join Game" Screen Is Opened -static unsigned char *RakNetInstance_injection(unsigned char *rak_net_instance) { +static RakNetInstance *RakNetInstance_injection(RakNetInstance *rak_net_instance) { // Call Original Method - unsigned char *result = (*RakNetInstance)(rak_net_instance); + RakNetInstance *result = (*RakNetInstance_constructor)(rak_net_instance); // Fix - *(unsigned char *) (rak_net_instance + RakNetInstance_pinging_for_hosts_property_offset) = 0; + rak_net_instance->pinging_for_hosts = 0; // Return return result; } // Close Current Screen On Death To Prevent Bugs -static void LocalPlayer_die_injection(unsigned char *entity, unsigned char *cause) { +static void LocalPlayer_die_injection(LocalPlayer *entity, Entity *cause) { // Close Screen - unsigned char *minecraft = *(unsigned char **) (entity + LocalPlayer_minecraft_property_offset); + Minecraft *minecraft = entity->minecraft; (*Minecraft_setScreen)(minecraft, NULL); // Call Original Method - (*LocalPlayer_die)(entity, cause); + (*LocalPlayer_die_non_virtual)(entity, cause); } // Fix Furnace Not Checking Item Auxiliary When Inserting New Item -static int32_t FurnaceScreen_handleAddItem_injection(unsigned char *furnace_screen, int32_t slot, ItemInstance const *item) { +static int32_t FurnaceScreen_handleAddItem_injection(FurnaceScreen *furnace_screen, int32_t slot, ItemInstance *item) { // Get Existing Item - unsigned char *tile_entity = *(unsigned char **) (furnace_screen + FurnaceScreen_tile_entity_property_offset); - unsigned char *tile_entity_vtable = *(unsigned char **) tile_entity; - FurnaceTileEntity_getItem_t FurnaceTileEntity_getItem = *(FurnaceTileEntity_getItem_t *) (tile_entity_vtable + FurnaceTileEntity_getItem_vtable_offset); - ItemInstance *existing_item = (*FurnaceTileEntity_getItem)(tile_entity, slot); + FurnaceTileEntity *tile_entity = furnace_screen->tile_entity; + ItemInstance *existing_item = tile_entity->vtable->getItem(tile_entity, slot); // Check Item int valid; @@ -268,7 +266,7 @@ static int32_t FurnaceScreen_handleAddItem_injection(unsigned char *furnace_scre // The default behavior for Touch GUI is to only render the cursor when the mouse is clicking, this fixes that. // This also makes the cursor always render if the mouse is unlocked, instead of just when there is a Screen showing. #ifndef MCPI_HEADLESS_MODE -static void GameRenderer_render_injection(unsigned char *game_renderer, float param_1) { +static void GameRenderer_render_injection(GameRenderer *game_renderer, float param_1) { // Call Original Method (*GameRenderer_render)(game_renderer, param_1); @@ -277,25 +275,25 @@ static void GameRenderer_render_injection(unsigned char *game_renderer, float pa // Fix GL Mode glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Get X And Y - float x = (*Mouse_getX)() * (*InvGuiScale); - float y = (*Mouse_getY)() * (*InvGuiScale); + float x = (*Mouse_getX)() * (*Gui_InvGuiScale); + float y = (*Mouse_getY)() * (*Gui_InvGuiScale); // Render Cursor - unsigned char *minecraft = *(unsigned char **) (game_renderer + GameRenderer_minecraft_property_offset); - (*renderCursor)(x, y, minecraft); + Minecraft *minecraft = game_renderer->minecraft; + (*Common_renderCursor)(x, y, minecraft); } } #endif // Get Real Selected Slot -int32_t misc_get_real_selected_slot(unsigned char *player) { +int32_t misc_get_real_selected_slot(Player *player) { // Get Selected Slot - unsigned char *inventory = *(unsigned char **) (player + Player_inventory_property_offset); - int32_t selected_slot = *(int32_t *) (inventory + Inventory_selectedSlot_property_offset); + Inventory *inventory = player->inventory; + int32_t selected_slot = inventory->selectedSlot; // Linked Slots - int32_t linked_slots_length = *(int32_t *) (inventory + FillingContainer_linked_slots_length_property_offset); + int32_t linked_slots_length = inventory->linked_slots_length; if (selected_slot < linked_slots_length) { - int32_t *linked_slots = *(int32_t **) (inventory + FillingContainer_linked_slots_property_offset); + int32_t *linked_slots = inventory->linked_slots; selected_slot = linked_slots[selected_slot]; } @@ -311,10 +309,10 @@ static void anGenBuffers_injection(int32_t count, uint32_t *buffers) { #endif // Fix Graphics Bug When Switching To First-Person While Sneaking -static void HumanoidMobRenderer_render_injection(unsigned char *model_renderer, unsigned char *entity, float param_2, float param_3, float param_4, float param_5, float param_6) { - (*HumanoidMobRenderer_render)(model_renderer, entity, param_2, param_3, param_4, param_5, param_6); - unsigned char *model = *(unsigned char **) (model_renderer + HumanoidMobRenderer_model_property_offset); - *(bool *) (model + HumanoidModel_is_sneaking_property_offset) = 0; +static void HumanoidMobRenderer_render_injection(HumanoidMobRenderer *model_renderer, Entity *entity, float param_2, float param_3, float param_4, float param_5, float param_6) { + (*HumanoidMobRenderer_render_non_virtual)(model_renderer, entity, param_2, param_3, param_4, param_5, param_6); + HumanoidModel *model = model_renderer->model; + model->is_sneaking = 0; } // Custom API Port @@ -337,17 +335,15 @@ HOOK(bind, int, (int sockfd, const struct sockaddr *addr, socklen_t addrlen)) { } // Change Grass Color -static int32_t get_color(unsigned char *level_source, int32_t x, int32_t z) { - unsigned char *level_source_vtable = *(unsigned char **) level_source; - LevelSource_getBiome_t LevelSource_getBiome = *(LevelSource_getBiome_t *) (level_source_vtable + LevelSource_getBiome_vtable_offset); - unsigned char *biome = (*LevelSource_getBiome)(level_source, x, z); +static int32_t get_color(LevelSource *level_source, int32_t x, int32_t z) { + Biome *biome = level_source->vtable->getBiome(level_source, x, z); if (biome == NULL) { return 0; } - return *(int32_t *) (biome + Biome_color_property_offset); + return biome->color; } #define BIOME_BLEND_SIZE 7 -static int32_t GrassTile_getColor_injection(__attribute__((unused)) unsigned char *tile, unsigned char *level_source, int32_t x, __attribute__((unused)) int32_t y, int32_t z) { +static int32_t GrassTile_getColor_injection(__attribute__((unused)) Tile *tile, LevelSource *level_source, int32_t x, __attribute__((unused)) int32_t y, int32_t z) { int r_sum = 0; int g_sum = 0; int b_sum = 0; @@ -368,30 +364,28 @@ static int32_t GrassTile_getColor_injection(__attribute__((unused)) unsigned cha int b_avg = b_sum / color_sum; return (r_avg << 16) | (g_avg << 8) | b_avg; } -static int32_t TallGrass_getColor_injection(unsigned char *tile, unsigned char *level_source, int32_t x, int32_t y, int32_t z) { - int32_t original_color = (*TallGrass_getColor)(tile, level_source, x, y, z); +static int32_t TallGrass_getColor_injection(TallGrass *tile, LevelSource *level_source, int32_t x, int32_t y, int32_t z) { + int32_t original_color = (*TallGrass_getColor_non_virtual)(tile, level_source, x, y, z); if (original_color == 0x339933) { - return GrassTile_getColor_injection(tile, level_source, x, y, z); + return GrassTile_getColor_injection((Tile *) tile, level_source, x, y, z); } else { return original_color; } } // Generate Caves -static void RandomLevelSource_buildSurface_injection(unsigned char *random_level_source, int32_t chunk_x, int32_t chunk_y, unsigned char *chunk_data, unsigned char **biomes) { +static void RandomLevelSource_buildSurface_injection(RandomLevelSource *random_level_source, int32_t chunk_x, int32_t chunk_y, unsigned char *chunk_data, Biome **biomes) { // Call Original Method (*RandomLevelSource_buildSurface)(random_level_source, chunk_x, chunk_y, chunk_data, biomes); // Get Level - unsigned char *level = *(unsigned char **) (random_level_source + RandomLevelSource_level_property_offset); + Level *level = random_level_source->level; // Get Cave Feature - unsigned char *cave_feature = random_level_source + RandomLevelSource_cave_feature_property_offset; - unsigned char *cave_feature_vtable = *(unsigned char **) cave_feature; + LargeCaveFeature *cave_feature = &random_level_source->cave_feature; // Generate - LargeFeature_apply_t LargeCaveFeature_apply = *(LargeFeature_apply_t *) (cave_feature_vtable + LargeFeature_apply_vtable_offset); - (*LargeCaveFeature_apply)(cave_feature, random_level_source, level, chunk_x, chunk_y, chunk_data, 0); + cave_feature->vtable->apply(cave_feature, (ChunkSource *) random_level_source, level, chunk_x, chunk_y, chunk_data, 0); } // No Block Tinting @@ -400,18 +394,21 @@ static int32_t Tile_getColor_injection() { } // Disable Hostile AI In Creative Mode -static unsigned char *PathfinderMob_findAttackTarget_injection(unsigned char *mob) { +#define has_vtable(obj, type) (((void *) obj->vtable) == type##_vtable_base) +static Entity *PathfinderMob_findAttackTarget_injection(PathfinderMob *mob) { // Call Original Method - unsigned char *mob_vtable = *(unsigned char **) mob; - PathfinderMob_findAttackTarget_t PathfinderMob_findAttackTarget = *(PathfinderMob_findAttackTarget_t *) (mob_vtable + PathfinderMob_findAttackTarget_vtable_offset); - unsigned char *target = (*PathfinderMob_findAttackTarget)(mob); + Entity *target = mob->vtable->findAttackTarget(mob); // Check If Creative Mode if (target != NULL) { - unsigned char *inventory = *(unsigned char **) (target + Player_inventory_property_offset); - bool is_creative = *(bool *) (inventory + FillingContainer_is_creative_property_offset); - if (is_creative) { - target = NULL; + bool is_player = has_vtable(target, Player) || has_vtable(target, LocalPlayer) || has_vtable(target, ServerPlayer) || has_vtable(target, RemotePlayer); + if (is_player) { + Player *player = (Player *) target; + Inventory *inventory = player->inventory; + bool is_creative = inventory->is_creative; + if (is_creative) { + target = NULL; + } } } @@ -420,29 +417,27 @@ static unsigned char *PathfinderMob_findAttackTarget_injection(unsigned char *mo } // 3D Chests -static int32_t Tile_getRenderShape_injection(unsigned char *tile) { +static int32_t Tile_getRenderShape_injection(Tile *tile) { if (tile == *Tile_chest) { // Don't Render "Simple" Chest Model return -1; } else { // Call Original Method - unsigned char *tile_vtable = *(unsigned char **) tile; - Tile_getRenderShape_t Tile_getRenderShape = *(Tile_getRenderShape_t *) (tile_vtable + Tile_getRenderShape_vtable_offset); - return (*Tile_getRenderShape)(tile); + return tile->vtable->getRenderShape(tile); } } -static unsigned char *ChestTileEntity_injection(unsigned char *tile_entity) { +static ChestTileEntity *ChestTileEntity_injection(ChestTileEntity *tile_entity) { // Call Original Method - (*ChestTileEntity)(tile_entity); + (*ChestTileEntity_constructor)(tile_entity); // Enable Renderer - *(int32_t *) (tile_entity + TileEntity_renderer_id_property_offset) = 1; + tile_entity->renderer_id = 1; // Return return tile_entity; } static bool is_rendering_chest = 0; -static void ModelPart_render_injection(unsigned char *model_part, float scale) { +static void ModelPart_render_injection(ModelPart *model_part, float scale) { // Start is_rendering_chest = 1; @@ -452,7 +447,7 @@ static void ModelPart_render_injection(unsigned char *model_part, float scale) { // Stop is_rendering_chest = 0; } -static void Tesselator_vertexUV_injection(unsigned char *tesselator, float x, float y, float z, float u, float v) { +static void Tesselator_vertexUV_injection(Tesselator *tesselator, float x, float y, float z, float u, float v) { // Fix Chest Texture if (is_rendering_chest) { v /= 2; @@ -466,35 +461,31 @@ static bool ChestTileEntity_shouldSave_injection(__attribute__((unused)) unsigne } // Animated 3D Chest -static unsigned char *ContainerMenu_injection(unsigned char *container_menu, unsigned char *container, int32_t param_1) { +static ContainerMenu *ContainerMenu_injection(ContainerMenu *container_menu, Container *container, int32_t param_1) { // Call Original Method - (*ContainerMenu)(container_menu, container, param_1); + (*ContainerMenu_constructor)(container_menu, container, param_1); // Play Animation - unsigned char *tile_entity = container - ChestTileEntity_container_property_offset; - bool is_client = *(bool *) (tile_entity + TileEntity_is_client_property_offset); + ChestTileEntity *tile_entity = (ChestTileEntity *) (((unsigned char *) container) - offsetof(ChestTileEntity, container)); + bool is_client = tile_entity->is_client; if (!is_client) { - unsigned char *container_vtable = *(unsigned char **) container; - Container_startOpen_t Container_startOpen = *(Container_startOpen_t *) (container_vtable + Container_startOpen_vtable_offset); - (*Container_startOpen)(container); + container->vtable->startOpen(container); } // Return return container_menu; } -static unsigned char *ContainerMenu_destructor_injection(unsigned char *container_menu) { +static unsigned char *ContainerMenu_destructor_injection(ContainerMenu *container_menu) { // Play Animation - unsigned char *container = *(unsigned char **) (container_menu + ContainerMenu_container_property_offset); - unsigned char *tile_entity = container - ChestTileEntity_container_property_offset; - bool is_client = *(bool *) (tile_entity + TileEntity_is_client_property_offset); + Container *container = container_menu->container; + ChestTileEntity *tile_entity = (ChestTileEntity *) (((unsigned char *) container) - offsetof(ChestTileEntity, container)); + bool is_client = tile_entity->is_client; if (!is_client) { - unsigned char *container_vtable = *(unsigned char **) container; - Container_stopOpen_t Container_stopOpen = *(Container_stopOpen_t *) (container_vtable + Container_stopOpen_vtable_offset); - (*Container_stopOpen)(container); + container->vtable->stopOpen(container); } // Call Original Method - return (*ContainerMenu_destructor)(container_menu); + return (*ContainerMenu_destructor_non_virtual)(container_menu); } #ifndef MCPI_HEADLESS_MODE @@ -511,7 +502,7 @@ static void glColor4f_injection(__attribute__((unused)) GLfloat red, __attribute line_width = strtof(custom_line_width, NULL); } else { // Guess - line_width = 2 / (*InvGuiScale); + line_width = 2 / (*Gui_InvGuiScale); } // Clamp Line Width float range[2]; @@ -560,19 +551,19 @@ void init_misc() { } // Fix Screen Rendering When GUI is Hidden - overwrite_calls((void *) Screen_render, (void *) Screen_render_injection); + overwrite_calls((void *) Screen_render_non_virtual, (void *) Screen_render_injection); // Sanitize Username patch_address(LoginPacket_read_vtable_addr, (void *) LoginPacket_read_injection); // Fix RakNet::RakString Security Bug - overwrite_calls((void *) RakNet_RakString, (void *) RakNet_RakString_injection); + overwrite_calls((void *) RakNet_RakString_constructor, (void *) RakNet_RakString_injection); // Print Error Message If RakNet Startup Fails overwrite_call((void *) 0x73778, (void *) RakNetInstance_host_RakNet_RakPeer_Startup_injection); // Fix Bug Where RakNetInstance Starts Pinging Potential Servers Before The "Join Game" Screen Is Opened - overwrite_calls((void *) RakNetInstance, (void *) RakNetInstance_injection); + overwrite_calls((void *) RakNetInstance_constructor, (void *) RakNetInstance_injection); // Close Current Screen On Death To Prevent Bugs if (feature_has("Close Current Screen On Death", server_disabled)) { @@ -613,12 +604,12 @@ void init_misc() { // Remove Forced GUI Lag if (feature_has("Remove Forced GUI Lag (Can Break Joining Servers)", server_enabled)) { - overwrite_calls((void *) sleepMs, (void *) nop); + overwrite_calls((void *) Common_sleepMs, (void *) nop); } #ifndef MCPI_HEADLESS_MODE // Properly Generate Buffers - overwrite((void *) anGenBuffers, (void *) anGenBuffers_injection); + overwrite((void *) Common_anGenBuffers, (void *) anGenBuffers_injection); #endif // Fix Graphics Bug When Switching To First-Person While Sneaking @@ -653,7 +644,7 @@ void init_misc() { patch_address((void *) TallGrass_getColor_vtable_addr, (void *) Tile_getColor_injection); patch_address((void *) StemTile_getColor_vtable_addr, (void *) Tile_getColor_injection); patch_address((void *) LeafTile_getColor_vtable_addr, (void *) Tile_getColor_injection); - overwrite((void *) LiquidTile_getColor, (void *) Tile_getColor_injection); + overwrite((void *) LiquidTile_getColor_non_virtual, (void *) Tile_getColor_injection); } // Custom GUI Scale @@ -676,7 +667,7 @@ void init_misc() { // 3D Chests if (feature_has("3D Chest Model", server_disabled)) { overwrite_call((void *) 0x5e830, (void *) Tile_getRenderShape_injection); - overwrite_calls((void *) ChestTileEntity, (void *) ChestTileEntity_injection); + overwrite_calls((void *) ChestTileEntity_constructor, (void *) ChestTileEntity_injection); overwrite_call((void *) 0x6655c, (void *) ModelPart_render_injection); overwrite_call((void *) 0x66568, (void *) ModelPart_render_injection); overwrite_call((void *) 0x66574, (void *) ModelPart_render_injection); @@ -687,8 +678,8 @@ void init_misc() { patch((void *) 0x66404, chest_color_patch); // Animation - overwrite_calls((void *) ContainerMenu, (void *) ContainerMenu_injection); - overwrite_calls((void *) ContainerMenu_destructor, (void *) ContainerMenu_destructor_injection); + overwrite_calls((void *) ContainerMenu_constructor, (void *) ContainerMenu_injection); + overwrite_calls((void *) ContainerMenu_destructor_non_virtual, (void *) ContainerMenu_destructor_injection); patch_address(ContainerMenu_destructor_vtable_addr, (void *) ContainerMenu_destructor_injection); } patch_address((void *) 0x115b48, (void *) ChestTileEntity_shouldSave_injection); diff --git a/mods/src/misc/misc.cpp b/mods/src/misc/misc.cpp index b32a5e7cd8..d543ca1beb 100644 --- a/mods/src/misc/misc.cpp +++ b/mods/src/misc/misc.cpp @@ -12,7 +12,7 @@ #include // Read Asset File -static AppPlatform_readAssetFile_return_value AppPlatform_readAssetFile_injection(__attribute__((unused)) unsigned char *app_platform, std::string const& path) { +static AppPlatform_readAssetFile_return_value AppPlatform_readAssetFile_injection(__attribute__((unused)) AppPlatform *app_platform, std::string const& path) { // Open File std::ifstream stream("data/" + path, std::ios_base::binary | std::ios_base::ate); if (!stream) { @@ -36,21 +36,19 @@ static AppPlatform_readAssetFile_return_value AppPlatform_readAssetFile_injectio } // Add Missing Buttons To Pause Menu -static void PauseScreen_init_injection(unsigned char *screen) { +static void PauseScreen_init_injection(PauseScreen *screen) { // Call Original Method - (*PauseScreen_init)(screen); + (*PauseScreen_init_non_virtual)(screen); // Check If Server - unsigned char *minecraft = *(unsigned char **) (screen + Screen_minecraft_property_offset); - unsigned char *rak_net_instance = *(unsigned char **) (minecraft + Minecraft_rak_net_instance_property_offset); + Minecraft *minecraft = screen->minecraft; + RakNetInstance *rak_net_instance = minecraft->rak_net_instance; if (rak_net_instance != NULL) { - unsigned char *rak_net_instance_vtable = *(unsigned char**) rak_net_instance; - RakNetInstance_isServer_t RakNetInstance_isServer = *(RakNetInstance_isServer_t *) (rak_net_instance_vtable + RakNetInstance_isServer_vtable_offset); - if ((*RakNetInstance_isServer)(rak_net_instance)) { + if (rak_net_instance->vtable->isServer(rak_net_instance)) { // Add Button - std::vector *rendered_buttons = (std::vector *) (screen + Screen_rendered_buttons_property_offset); - std::vector *selectable_buttons = (std::vector *) (screen + Screen_selectable_buttons_property_offset); - unsigned char *button = *(unsigned char **) (screen + PauseScreen_server_visibility_button_property_offset); + std::vector