WIP New Modding API
Some checks failed
Build / Build (AMD64, Server) (push) Failing after 3m17s
Build / Build (AMD64, Client) (push) Successful in 8m28s
Build / Build (ARM64, Client) (push) Successful in 8m27s
Build / Build (ARM64, Server) (push) Failing after 4m1s
Build / Build (ARMHF, Server) (push) Failing after 3m31s
Build / Build (ARMHF, Client) (push) Successful in 7m38s
Build / Release (push) Has been skipped
Build / Test (Client) (push) Failing after 5m48s
Build / Test (Server) (push) Failing after 3m9s
Some checks failed
Build / Build (AMD64, Server) (push) Failing after 3m17s
Build / Build (AMD64, Client) (push) Successful in 8m28s
Build / Build (ARM64, Client) (push) Successful in 8m27s
Build / Build (ARM64, Server) (push) Failing after 4m1s
Build / Build (ARMHF, Server) (push) Failing after 3m31s
Build / Build (ARMHF, Client) (push) Successful in 7m38s
Build / Release (push) Has been skipped
Build / Test (Client) (push) Failing after 5m48s
Build / Test (Server) (push) Failing after 3m9s
This commit is contained in:
parent
0be1f4fce8
commit
aa92da6fdd
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -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
|
||||
|
|
2
LICENSE
2
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
|
||||
|
|
4
dependencies/CMakeLists.txt
vendored
4
dependencies/CMakeLists.txt
vendored
|
@ -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()
|
||||
|
|
20
dependencies/symbol-processor/CMakeLists.txt
vendored
Normal file
20
dependencies/symbol-processor/CMakeLists.txt
vendored
Normal file
|
@ -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()
|
1
dependencies/symbol-processor/src
vendored
Submodule
1
dependencies/symbol-processor/src
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 1062e048c493607b7b57faf83570562fa44c0f9c
|
|
@ -8,6 +8,7 @@ target_include_directories(
|
|||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
|
||||
"$<INSTALL_INTERFACE:${MCPI_SDK_INCLUDE_DIR}/mods>"
|
||||
)
|
||||
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()
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <string>
|
||||
// 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
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#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);
|
||||
|
|
|
@ -2,25 +2,31 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#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
|
||||
}
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
#include <mods/init/init.h>
|
||||
|
||||
// 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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -6,22 +6,22 @@
|
|||
#include <mods/misc/misc.h>
|
||||
|
||||
// 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<Recipes_Type> 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
|
||||
|
|
|
@ -7,28 +7,28 @@
|
|||
#include <mods/init/init.h>
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
#include <mods/feature/feature.h>
|
||||
|
||||
// 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() {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */ \
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
#include <libreborn/libreborn.h>
|
||||
|
||||
#include <mods/init/init.h>
|
||||
|
||||
#include <media-layer/core.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
__attribute__((constructor)) static void init() {
|
||||
media_ensure_loaded();
|
||||
run_tests();
|
||||
init_symbols();
|
||||
init_version();
|
||||
init_compat();
|
||||
#ifdef MCPI_SERVER_MODE
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 |