diff --git a/images/CMakeLists.txt b/images/CMakeLists.txt index 9edf6b4..c5dc5c7 100644 --- a/images/CMakeLists.txt +++ b/images/CMakeLists.txt @@ -9,6 +9,14 @@ if(NOT MCPI_HEADLESS_MODE) ) endif() +# Chest Model +if(NOT MCPI_HEADLESS_MODE) + install( + FILES "chest.png" + DESTINATION "${MCPI_INSTALL_DIR}/data/images/item" + ) +endif() + # Icon install( FILES "icon.png" diff --git a/images/chest.png b/images/chest.png new file mode 100644 index 0000000..5866e93 Binary files /dev/null and b/images/chest.png differ diff --git a/images/chest.png~ b/images/chest.png~ new file mode 100644 index 0000000..d9429e8 Binary files /dev/null and b/images/chest.png~ differ diff --git a/launcher/src/client/available-feature-flags b/launcher/src/client/available-feature-flags index 128202c..5fcacab 100644 --- a/launcher/src/client/available-feature-flags +++ b/launcher/src/client/available-feature-flags @@ -49,3 +49,4 @@ TRUE Generate Caves FALSE Disable Block Tinting TRUE Disable Hostile AI In Creative Mode TRUE Load Custom Skins +TRUE 3D Chest Model diff --git a/mods/src/misc/misc.c b/mods/src/misc/misc.c index 6cf4121..815065b 100644 --- a/mods/src/misc/misc.c +++ b/mods/src/misc/misc.c @@ -415,6 +415,52 @@ static unsigned char *PathfinderMob_findAttackTarget_injection(unsigned char *mo return target; } +// 3D Chests +static int32_t Tile_getRenderShape_injection(unsigned char *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); + } +} +static unsigned char *ChestTileEntity_injection(unsigned char *tile_entity) { + // Call Original Method + (*ChestTileEntity)(tile_entity); + + // Enable Renderer + *(int32_t *) (tile_entity + TileEntity_renderer_id_property_offset) = 1; + + // Return + return tile_entity; +} +static bool is_rendering_chest = 0; +static void ModelPart_render_injection(unsigned char *model_part, float scale) { + // Start + is_rendering_chest = 1; + + // Call Original Method + (*ModelPart_render)(model_part, scale); + + // Stop + is_rendering_chest = 0; +} +static void Tesselator_vertexUV_injection(unsigned char *tesselator, float x, float y, float z, float u, float v) { + // Fix Chest Texture + if (is_rendering_chest) { + v /= 2; + } + + // Call Original Method + (*Tesselator_vertexUV)(tesselator, x, y, z, u, v); +} +static bool ChestTileEntity_shouldSave_injection(__attribute__((unused)) unsigned char *tile_entity) { + return 1; +} + // Init static void nop() { } @@ -557,6 +603,21 @@ void init_misc() { overwrite_call((void *) 0x83b8c, (void *) PathfinderMob_findAttackTarget_injection); } + // 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_call((void *) 0x6655c, (void *) ModelPart_render_injection); + overwrite_call((void *) 0x66568, (void *) ModelPart_render_injection); + overwrite_call((void *) 0x66574, (void *) ModelPart_render_injection); + overwrite_calls((void *) Tesselator_vertexUV, (void *) Tesselator_vertexUV_injection); + unsigned char chest_model_patch[4] = {0x13, 0x20, 0xa0, 0xe3}; // "mov r2, #0x13" + patch((void *) 0x66fc8, chest_model_patch); + unsigned char chest_color_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop" + patch((void *) 0x66404, chest_color_patch); + } + patch_address((void *) 0x115b48, (void *) ChestTileEntity_shouldSave_injection); + // Init C++ And Logging _init_misc_cpp(); _init_misc_logging(); diff --git a/symbols/include/symbols/minecraft.h b/symbols/include/symbols/minecraft.h index 0ef788d..7b8a2ee 100644 --- a/symbols/include/symbols/minecraft.h +++ b/symbols/include/symbols/minecraft.h @@ -45,6 +45,7 @@ static unsigned char **Item_egg = (unsigned char **) 0x17bbd0; // Item static unsigned char **Item_dye_powder = (unsigned char **) 0x17bbe0; // Item static unsigned char **Item_camera = (unsigned char **) 0x17bc14; // Item +static unsigned char **Tile_chest = (unsigned char **) 0x181d60; // Tile static unsigned char **Tile_water = (unsigned char **) 0x181b3c; // Tile static unsigned char **Tile_lava = (unsigned char **) 0x181cc8; // Tile static unsigned char **Tile_calmWater = (unsigned char **) 0x181b40; // Tile @@ -132,6 +133,9 @@ static uint32_t Tile_use_vtable_offset = 0x98; typedef int32_t (*Tile_getColor_t)(unsigned char *tile, unsigned char *level_source, int32_t x, int32_t y, int32_t z); static uint32_t Tile_getColor_vtable_offset = 0xb8; +typedef int32_t (*Tile_getRenderShape_t)(unsigned char *tile); +static uint32_t Tile_getRenderShape_vtable_offset = 0xc; + static uint32_t Tile_id_property_offset = 0x8; // int32_t static uint32_t Tile_category_property_offset = 0x3c; // int32_t @@ -830,6 +834,17 @@ static EntityRenderDispatcher_assign_t EntityRenderDispatcher_assign = (EntityRe // TileEntity static uint32_t TileEntity_id_property_offset = 0x18; // int32_t +static uint32_t TileEntity_renderer_id_property_offset = 0x24; // int32_t + +// ChestTileEntity + +typedef unsigned char *(*ChestTileEntity_t)(unsigned char *tile_entity); +static ChestTileEntity_t ChestTileEntity = (ChestTileEntity_t) 0xcfa78; + +// ModelPart + +typedef void (*ModelPart_render_t)(unsigned char *model_part, float scale); +static ModelPart_render_t ModelPart_render = (ModelPart_render_t) 0x416dc; // ItemRenderer @@ -853,6 +868,9 @@ static Tesselator_colorABGR_t Tesselator_colorABGR = (Tesselator_colorABGR_t) 0x typedef void (*Tesselator_color_t)(unsigned char *tesselator, int32_t r, int32_t g, int32_t b, int32_t a); static Tesselator_color_t Tesselator_color = (Tesselator_color_t) 0x52a48; +typedef void (*Tesselator_vertexUV_t)(unsigned char *tesselator, float x, float y, float z, float u, float v); +static Tesselator_vertexUV_t Tesselator_vertexUV = (Tesselator_vertexUV_t) 0x52d40; + // SoundEngine typedef void (*SoundEngine_init_t)(unsigned char *sound_engine, unsigned char *minecraft, unsigned char *options);