Add Cake And Crafting Remainders

- Revert `misc_run_on_tile_setup` running after the original function is called, as it broke custom tiles.
- More symbols
This commit is contained in:
Bigjango13 2024-01-28 14:18:22 -05:00
parent f78a4e47ac
commit 9de256e6c7
20 changed files with 359 additions and 11 deletions

View File

@ -5,6 +5,9 @@
* By Default, The Outline Width Is Set Using The GUI Scale * By Default, The Outline Width Is Set Using The GUI Scale
* This Can Be Overridden Using The ``MCPI_BLOCK_OUTLINE_WIDTH`` Environmental Variable * This Can Be Overridden Using The ``MCPI_BLOCK_OUTLINE_WIDTH`` Environmental Variable
* Added ``overwrite_calls_within`` Function * Added ``overwrite_calls_within`` Function
* Add ``Add Cake`` Feature Flag (Enabled By Default)
* Add Milk Buckets
* Implement Crafting Remainders
**2.5.2** **2.5.2**
* Add ``3D Chest Model`` Feature Flag (Enabled By Default) * Add ``3D Chest Model`` Feature Flag (Enabled By Default)

View File

@ -51,3 +51,4 @@ TRUE Disable Hostile AI In Creative Mode
TRUE Load Custom Skins TRUE Load Custom Skins
TRUE 3D Chest Model TRUE 3D Chest Model
TRUE Replace Block Highlight With Outline TRUE Replace Block Highlight With Outline
TRUE Add Cake

View File

@ -109,6 +109,9 @@ target_link_libraries(options mods-headers reborn-patch symbols feature home)
add_library(bucket SHARED src/bucket/bucket.cpp) add_library(bucket SHARED src/bucket/bucket.cpp)
target_link_libraries(bucket mods-headers reborn-patch symbols feature misc) target_link_libraries(bucket mods-headers reborn-patch symbols feature misc)
add_library(cake SHARED src/cake/cake.cpp)
target_link_libraries(cake mods-headers reborn-patch symbols feature misc)
add_library(home SHARED src/home/home.c) add_library(home SHARED src/home/home.c)
target_link_libraries(home mods-headers reborn-patch symbols) target_link_libraries(home mods-headers reborn-patch symbols)
@ -116,7 +119,7 @@ add_library(test SHARED src/test/test.c)
target_link_libraries(test mods-headers reborn-patch home) target_link_libraries(test mods-headers reborn-patch home)
add_library(init SHARED src/init/init.c) add_library(init SHARED src/init/init.c)
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) target_link_libraries(init symbols mods-headers reborn-util compat game-mode misc death options chat creative bucket cake textures home version test media-layer-core)
if(MCPI_SERVER_MODE) if(MCPI_SERVER_MODE)
target_link_libraries(init server) target_link_libraries(init server)
else() else()
@ -127,7 +130,7 @@ if(NOT MCPI_HEADLESS_MODE)
endif() endif()
## Install Mods ## Install Mods
set(MODS_TO_INSTALL init compat readdir feature game-mode misc override death options chat creative bucket textures home version test) set(MODS_TO_INSTALL init compat readdir feature game-mode misc override death options chat creative bucket cake textures home version test)
if(MCPI_SERVER_MODE) if(MCPI_SERVER_MODE)
list(APPEND MODS_TO_INSTALL server) list(APPEND MODS_TO_INSTALL server)
else() else()

View File

@ -33,6 +33,7 @@ void init_death();
void init_options(); void init_options();
void init_chat(); void init_chat();
void init_bucket(); void init_bucket();
void init_cake();
void init_home(); void init_home();
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -157,6 +157,17 @@ static ItemInstance *BucketItem_use(FoodItem *item, ItemInstance *item_instance,
return item_instance; return item_instance;
} }
static ItemInstance *BucketItem_getCraftingRemainingItem(FoodItem *item, ItemInstance *item_instance) {
if (item_instance->auxiliary == 0) {
return NULL;
}
ItemInstance *ret = alloc_ItemInstance();
ret->id = item->id;
ret->count = item_instance->count;
ret->auxiliary = 0;
return ret;
}
// Bucket VTable // Bucket VTable
static FoodItem_vtable *get_bucket_vtable() { static FoodItem_vtable *get_bucket_vtable() {
static FoodItem_vtable *vtable = NULL; static FoodItem_vtable *vtable = NULL;
@ -174,6 +185,7 @@ static FoodItem_vtable *get_bucket_vtable() {
vtable->getUseAnimation = BucketItem_getUseAnimation; vtable->getUseAnimation = BucketItem_getUseAnimation;
vtable->isFood = BucketItem_isFood; vtable->isFood = BucketItem_isFood;
vtable->use = BucketItem_use; vtable->use = BucketItem_use;
vtable->getCraftingRemainingItem = BucketItem_getCraftingRemainingItem;
} }
return vtable; return vtable;
} }

3
mods/src/cake/README.md Normal file
View File

@ -0,0 +1,3 @@
# ``cake`` Mod
This mod adds cake.

242
mods/src/cake/cake.cpp Normal file
View File

@ -0,0 +1,242 @@
#include <libreborn/libreborn.h>
#include <symbols/minecraft.h>
#include <mods/feature/feature.h>
#include <mods/init/init.h>
#include <mods/misc/misc.h>
Tile *cake = NULL;
#define CAKE_LEN 0.0625F
// Description
static std::string Cake_getDescriptionId(__attribute__((unused)) Tile *tile) {
return "tile.cake";
}
// Textures
static int Cake_getTexture2(__attribute__((unused)) Tile *tile, int face) {
if (face == 1) {
// Top texture
return 121;
} else if (face == 0) {
// Bottom texture
return 124;
}
// Side texture
return 122;
}
static int Cake_getTexture3(__attribute__((unused)) Tile *tile, Level *level, int x, int y, int z, int face) {
// Eaten face
if (face == 3) {
int data = level->vtable->getData(level, x, y, z);
if (data != 0 && data < 6) {
// Sliced texture
return 123;
}
}
// Normal
return Cake_getTexture2(tile, face);
}
// Rendering
static bool Cake_isSolidRender(__attribute__((unused)) Tile *tile) {
// Stop it from turning other blocks invisable
return 0;
}
static int Cake_getRenderLayer(__attribute__((unused)) Tile *tile) {
// Stop weird transparency issues
return 1;
}
static bool Cake_isCubeShaped(__attribute__((unused)) Tile *tile) {
return false;
}
// Size
static void Cake_updateDefaultShape(Tile *tile) {
// Set the default shape
tile->vtable->setShape(
tile,
CAKE_LEN, 0.0, CAKE_LEN,
1.0 - CAKE_LEN, 0.5, 1.0 - CAKE_LEN
);
}
static AABB *Cake_getAABB(Tile *tile, Level *level, int x, int y, int z) {
// Get the size of the slices
int data = level->vtable->getData(level, x, y, z);
if (data >= 6) data = 0;
float slice_size = (1.0 / 7.0) * (float) data;
// Corner 1
AABB *aabb = &tile->aabb;
aabb->x1 = (float) x + CAKE_LEN;
aabb->y1 = (float) y;
aabb->z1 = (float) z + CAKE_LEN;
// Corner 2
aabb->x2 = (float) x + (1.0 - CAKE_LEN);
aabb->y2 = (float) y + 0.5;
aabb->z2 = (float) z + (1.0 - CAKE_LEN) - slice_size;
return aabb;
}
static void Cake_updateShape(Tile *tile, Level *level, int x, int y, int z) {
// Set cake
int data = level->vtable->getData(level, x, y, z);
if (data >= 6) data = 0;
// Get slice amount
float slice_size = (1.0 / 7.0) * (float) data;
tile->vtable->setShape(
tile,
CAKE_LEN, 0.0, CAKE_LEN,
1.0 - CAKE_LEN, 0.5, (1.0 - CAKE_LEN) - slice_size
);
}
// Eating
static int Cake_use(__attribute__((unused)) Tile *tile, Level *level, int x, int y, int z, Player *player) {
// Eat
SimpleFoodData_eat(&player->foodData, 3);
// Set the new tile
int data = level->vtable->getData(level, x, y, z);
if (data >= 5) {
// Remove the cake, it has been completely gobbled up
Level_setTileAndData(level, x, y, z, 0, 0);
} else {
// Remove a slice
Level_setTileAndData(level, x, y, z, 92, data + 1);
}
return 1;
}
// Makes the cakes
static void make_cake() {
// Construct
cake = alloc_Tile();
ALLOC_CHECK(cake);
int texture = 122;
Tile_constructor(cake, 92, texture, Material_dirt);
cake->texture = texture;
// Set VTable
cake->vtable = dup_Tile_vtable(Tile_vtable_base);
ALLOC_CHECK(cake->vtable);
// Set shape
cake->vtable->setShape(
cake,
CAKE_LEN, 0.0, CAKE_LEN,
1.0 - CAKE_LEN, 0.5, 1.0 - CAKE_LEN
);
// Modify functions
cake->vtable->getDescriptionId = Cake_getDescriptionId;
cake->vtable->getTexture3 = Cake_getTexture3;
cake->vtable->getTexture2 = Cake_getTexture2;
cake->vtable->isSolidRender = Cake_isSolidRender;
cake->vtable->getRenderLayer = Cake_getRenderLayer;
cake->vtable->isCubeShaped = Cake_isCubeShaped;
cake->vtable->updateShape = Cake_updateShape;
cake->vtable->updateDefaultShape = Cake_updateDefaultShape;
cake->vtable->getAABB = Cake_getAABB;
cake->vtable->use = Cake_use;
// Init
Tile_init(cake);
cake->vtable->setDestroyTime(cake, 1.0f);
cake->vtable->setExplodeable(cake, 20.0f);
cake->category = 4;
std::string name = "Cake";
cake->vtable->setDescriptionId(cake, &name);
}
static void Tile_initTiles_injection(__attribute__((unused)) void *null) {
make_cake();
}
// Add cake to creative inventory
static void Inventory_setupDefault_FillingContainer_addItem_call_injection(FillingContainer *filling_container) {
ItemInstance *cake_instance = new ItemInstance;
ALLOC_CHECK(cake_instance);
cake_instance->count = 255;
cake_instance->auxiliary = 0;
cake_instance->id = 92;
(*FillingContainer_addItem)(filling_container, cake_instance);
}
// Recipe (only when buckets are enabled)
static void Recipes_injection(Recipes *recipes) {
// Sugar
Recipes_Type sugar = {
.item = 0,
.tile = 0,
.instance = {
.count = 1,
.id = 353,
.auxiliary = 0
},
.letter = 's'
};
// Wheat
Recipes_Type wheat = {
.item = 0,
.tile = 0,
.instance = {
.count = 1,
.id = 296,
.auxiliary = 0
},
.letter = 'w'
};
// Eggs
Recipes_Type eggs = {
.item = 0,
.tile = 0,
.instance = {
.count = 1,
.id = 344,
.auxiliary = 0
},
.letter = 'e'
};
// Milk
Recipes_Type milk = {
.item = 0,
.tile = 0,
.instance = {
.count = 1,
.id = 325,
.auxiliary = 1
},
.letter = 'm'
};
// Cake
ItemInstance cake_item = {
.count = 1,
.id = 92,
.auxiliary = 0
};
// Add
std::string line1 = "mmm";
std::string line2 = "ses";
std::string line3 = "www";
std::vector<Recipes_Type> ingredients = {milk, sugar, wheat, eggs};
Recipes_addShapedRecipe_3(recipes, &cake_item, &line1, &line2, &line3, &ingredients);
}
void init_cake() {
// Add cakes
if (feature_has("Add Cake", server_enabled)) {
misc_run_on_tiles_setup(Tile_initTiles_injection);
misc_run_on_creative_inventory_setup(Inventory_setupDefault_FillingContainer_addItem_call_injection);
if (feature_has("Add Buckets", server_enabled)) {
// The recipe needs milk buckets
misc_run_on_recipes_setup(Recipes_injection);
}
}
}

View File

@ -32,6 +32,7 @@ __attribute__((constructor)) static void init() {
init_options(); init_options();
init_chat(); init_chat();
init_bucket(); init_bucket();
init_cake();
init_home(); init_home();
#ifndef MCPI_SERVER_MODE #ifndef MCPI_SERVER_MODE
init_benchmark(); init_benchmark();

View File

@ -5,3 +5,4 @@ This mod has several miscellaneous mods that are too small to be their own mod,
* Removing the red background from unobtainable items in the inventory. * Removing the red background from unobtainable items in the inventory.
* Loading the bundled language file. * Loading the bundled language file.
* Printing chat messages to the log. * Printing chat messages to the log.
* Implementing crafting remainders.

View File

@ -86,11 +86,11 @@ static void Inventory_setupDefault_FillingContainer_addItem_call_injection(Filli
SETUP_CALLBACK(tiles_setup, void); SETUP_CALLBACK(tiles_setup, void);
// Handle Custom Tiles Setup Behavior // Handle Custom Tiles Setup Behavior
static void Tile_initTiles_injection() { static void Tile_initTiles_injection() {
// Call Original Method
Tile_initTiles();
// Run Functions // Run Functions
handle_misc_tiles_setup(NULL); handle_misc_tiles_setup(NULL);
// Call Original Method
Tile_initTiles();
} }
// Run Functions On Items Setup // Run Functions On Items Setup

View File

@ -58,6 +58,38 @@ static void PauseScreen_init_injection(PauseScreen *screen) {
} }
} }
// Implement crafting remainders
void PaneCraftingScreen_craftSelectedItem_PaneCraftingScreen_recheckRecipes_injection(PaneCraftingScreen *self) {
// Check for crafting remainders
CItem *item = self->item;
for (size_t i = 0; i < item->ingredients.size(); i++) {
ItemInstance requested_item_instance = item->ingredients[i].requested_item;
Item *requested_item = Item_items[requested_item_instance.id];
ItemInstance *craftingRemainingItem = requested_item->vtable->getCraftingRemainingItem(requested_item, &requested_item_instance);
if (craftingRemainingItem != NULL) {
// Add or drop remainder
LocalPlayer *player = self->minecraft->player;
if (!player->inventory->vtable->add(player->inventory, craftingRemainingItem)) {
// Drop
player->vtable->drop(player, craftingRemainingItem, false);
}
}
}
// Call Original Method
PaneCraftingScreen_recheckRecipes(self);
}
ItemInstance *Item_getCraftingRemainingItem_injection(Item *self, ItemInstance *item_instance) {
if (self->craftingRemainingItem != NULL) {
ItemInstance *ret = alloc_ItemInstance();
ret->id = self->craftingRemainingItem->id;
ret->count = item_instance->count;
ret->auxiliary = 0;
return ret;
}
return NULL;
}
// Init // Init
void _init_misc_cpp() { void _init_misc_cpp() {
// Implement AppPlatform::readAssetFile So Translations Work // Implement AppPlatform::readAssetFile So Translations Work
@ -70,4 +102,8 @@ void _init_misc_cpp() {
// Add Missing Buttons To Pause Menu // Add Missing Buttons To Pause Menu
patch_address(PauseScreen_init_vtable_addr, (void *) PauseScreen_init_injection); patch_address(PauseScreen_init_vtable_addr, (void *) PauseScreen_init_injection);
} }
// Implement crafting remainders
overwrite_call((void *) 0x2e230, (void *) PaneCraftingScreen_craftSelectedItem_PaneCraftingScreen_recheckRecipes_injection);
overwrite((void *) Item_getCraftingRemainingItem_non_virtual, (void *) Item_getCraftingRemainingItem_injection);
} }

View File

@ -100,6 +100,7 @@ set(SRC
src/gui/screens/StartMenuScreen.def src/gui/screens/StartMenuScreen.def
src/gui/screens/ProgressScreen.def src/gui/screens/ProgressScreen.def
src/gui/screens/Touch_SelectWorldScreen.def src/gui/screens/Touch_SelectWorldScreen.def
src/gui/screens/PaneCraftingScreen.def
src/gui/Font.def src/gui/Font.def
src/gui/components/ImageButton.def src/gui/components/ImageButton.def
src/gui/components/OptionButton.def src/gui/components/OptionButton.def
@ -128,6 +129,7 @@ set(SRC
src/tile/HeavyTile.def src/tile/HeavyTile.def
src/misc/Strings.def src/misc/Strings.def
src/misc/I18n.def src/misc/I18n.def
src/misc/SimpleFoodData.def
src/entity/ModelPart.def src/entity/ModelPart.def
src/misc/Tesselator.def src/misc/Tesselator.def
src/misc/AABB.def src/misc/AABB.def
@ -147,6 +149,8 @@ set(SRC
src/recipes/FurnaceRecipes.def src/recipes/FurnaceRecipes.def
src/recipes/Recipes.def src/recipes/Recipes.def
src/recipes/Recipes_Type.def src/recipes/Recipes_Type.def
src/recipes/ReqItem.def
src/recipes/CItem.def
) )
# Resolve Definition Files # Resolve Definition Files
set(RESOLVED_SRC "") set(RESOLVED_SRC "")

View File

@ -17,3 +17,4 @@ property std::string username = 0xbf4;
property bool immortal = 0xbfc; property bool immortal = 0xbfc;
property bool infinite_items = 0xbff; property bool infinite_items = 0xbff;
property ItemInstance itemBeingUsed = 0xc34; property ItemInstance itemBeingUsed = 0xc34;
property SimpleFoodData foodData = 0xc00;

View File

@ -0,0 +1,5 @@
method void craftSelectedItem() = 0x2e0e4;
method void recheckRecipes() = 0x2dc98;
property Minecraft *minecraft = 0x14;
property CItem *item = 0x74;

View File

@ -20,6 +20,8 @@ virtual-method bool isFood() = 0x64;
virtual-method bool isArmor() = 0x68; virtual-method bool isArmor() = 0x68;
virtual-method void setDescriptionId(std::string *name) = 0x6c; virtual-method void setDescriptionId(std::string *name) = 0x6c;
virtual-method std::string getDescriptionId(ItemInstance *item_instance) = 0x7c; virtual-method std::string getDescriptionId(ItemInstance *item_instance) = 0x7c;
// This returns an Item*, but it's never called normally so it doesn't matter if we invent a better system over top of it
virtual-method ItemInstance *getCraftingRemainingItem(ItemInstance *item_instance) = 0x84;
// Swing = 0, eating = 1, drinking = 2, bow = 4, anything else is nothing // Swing = 0, eating = 1, drinking = 2, bow = 4, anything else is nothing
virtual-method int getUseAnimation() = 0x94; virtual-method int getUseAnimation() = 0x94;
@ -30,6 +32,7 @@ property int category = 0x10;
property int max_stack_size = 0x14; property int max_stack_size = 0x14;
property bool equipped = 0x18; property bool equipped = 0x18;
property bool is_stacked_by_data = 0x19; property bool is_stacked_by_data = 0x19;
property Item *craftingRemainingItem = 0x1c;
property std::string description_id = 0x20; property std::string description_id = 0x20;
// Globals // Globals

View File

@ -1,4 +1,7 @@
virtual-method bool isSolid() = 0x8; virtual-method bool isSolid() = 0x8;
// Globals // Globals
static-property Material *Material_stone = 0x180a9c; static-property Material *dirt = 0x180a94;
static-property Material *stone = 0x180a9c;
static-property Material *metal = 0x180aa0;
static-property Material *glass = 0x180acc;

View File

@ -0,0 +1,5 @@
size 0x4;
method void eat(int amount) = 0x91470;
property int health = 0x0;

View File

@ -0,0 +1,3 @@
property ItemInstance item = 0x0;
property std::vector<ReqItem> ingredients = 0x20;
property bool craftable = 0x2c;

View File

@ -0,0 +1,3 @@
size 0x10;
property ItemInstance requested_item = 0x0;

View File

@ -3,20 +3,38 @@ static-method void initTiles() = 0xc358c;
vtable 0x115670; vtable 0x115670;
vtable-size 0x104; vtable-size 0x104;
constructor (int id, int texture, void *material) = 0xc33a0; constructor (int id, int texture, Material *material) = 0xc33a0;
size 0x5c; size 0x5c;
method Tile *init() = 0xc34dc; method Tile *init() = 0xc34dc;
virtual-method Tile *setDestroyTime(float destroy_time) = 0xf8;
virtual-method Tile *setExplodeable(float explodeable) = 0xf4; virtual-method bool isCubeShaped() = 0x8;
virtual-method Tile *setSoundType(Tile_SoundType *sound_type) = 0xe8; virtual-method int getRenderShape() = 0xc;
virtual-method void setShape(float x1, float y1, float z1, float x2, float y2, float z2) = 0x10;
virtual-method void updateShape(Level *level, int x, int y, int z) = 0x14;
virtual-method void updateDefaultShape() = 0x18;
virtual-method int getTexture1() = 0x28;
virtual-method int getTexture2(int face) = 0x2c;
virtual-method int getTexture3(Level *level, int x, int y, int z, int face) = 0x30;
virtual-method AABB *getAABB(Level *level, int x, int y, int z) = 0x34;
virtual-method bool isSolidRender() = 0x40;
virtual-method void tick(Level *level, int x, int y, int z) = 0x58;
virtual-method void neighborChanged(Level *level, int x, int y, int z, int neighborId) = 0x64;
virtual-method void onPlace(Level *level, int x, int y, int z) = 0x68;
virtual-method void onRemove(Level *level, int x, int y, int z) = 0x6c;
virtual-method int getRenderLayer() = 0x94;
virtual-method int use(Level *level, int x, int y, int z, Player *player) = 0x98; virtual-method int use(Level *level, int x, int y, int z, Player *player) = 0x98;
virtual-method int getColor(LevelSource *level_source, int x, int y, int z) = 0xb8; virtual-method int getColor(LevelSource *level_source, int x, int y, int z) = 0xb8;
virtual-method int getRenderShape() = 0xc; virtual-method std::string getDescriptionId() = 0xdc;
virtual-method Tile *setDescriptionId(std::string *description_id) = 0xe0; virtual-method Tile *setDescriptionId(std::string *description_id) = 0xe0;
virtual-method Tile *setSoundType(Tile_SoundType *sound_type) = 0xe8;
virtual-method Tile *setExplodeable(float explodeable) = 0xf4;
virtual-method Tile *setDestroyTime(float destroy_time) = 0xf8;
property int texture = 0x4;
property int id = 0x8; property int id = 0x8;
property int category = 0x3c; property int category = 0x3c;
property AABB aabb = 0x40;
// Globals // Globals
static-property-array Tile *tiles = 0x180e08; static-property-array Tile *tiles = 0x180e08;