diff --git a/build_registries.js b/build_registries.js index 3e11284..6693675 100644 --- a/build_registries.js +++ b/build_registries.js @@ -45,7 +45,8 @@ const blockWhitelist = [ "moss_carpet", "oak_slab", "stone_slab", - "cobblestone_slab" + "cobblestone_slab", + "composter" ]; // Currently, only 4 biome types are supported, excluding "beach" diff --git a/include/procedures.h b/include/procedures.h index 888d46d..e4bba8b 100644 --- a/include/procedures.h +++ b/include/procedures.h @@ -29,6 +29,7 @@ uint8_t isInstantlyMined (PlayerData *player, uint8_t block); uint8_t isColumnBlock (uint8_t block); uint8_t isPassableBlock (uint8_t block); uint8_t isReplaceableBlock (uint8_t block); +uint32_t isCompostItem (uint16_t item); uint16_t getMiningResult (uint16_t held_item, uint8_t block); void bumpToolDurability (PlayerData *player); diff --git a/src/crafting.c b/src/crafting.c index 0ce7311..5c287ac 100644 --- a/src/crafting.c +++ b/src/crafting.c @@ -207,6 +207,24 @@ void getCraftingOutput (PlayerData *player, uint8_t *count, uint16_t *item) { } break; + case 7: + switch (first_item) { + case I_oak_slab: + if ( + identical && + player->craft_items[1] == 0 && + player->craft_items[4] == 0 + ) { + *item = I_composter; + *count = 1; + return; + } + break; + + default: break; + } + break; + case 8: switch (first_item) { case I_cobblestone: diff --git a/src/packets.c b/src/packets.c index f3d75d8..5bcd2bb 100644 --- a/src/packets.c +++ b/src/packets.c @@ -502,6 +502,23 @@ int cs_useItemOn (int client_fd) { } else if (target == B_furnace) { sc_openScreen(client_fd, 14, "Furnace", 7); return 0; + } else if (target == B_composter) { + // Check if the player is holding anything + uint8_t *count = &player->inventory_count[player->hotbar]; + if (*count == 0) return 0; + // Check if the item is a valid compost item + uint16_t item = player->inventory_items[player->hotbar]; + uint32_t compost_chance = isCompostItem(item); + if (compost_chance != 0) { + // Take away composted item + if ((*count -= 1) == 0) item = 0; + sc_setContainerSlot(client_fd, 0, serverSlotToClientSlot(0, player->hotbar), *count, item); + // Test compost chance and give bone meal on success + if (fast_rand() < compost_chance) { + givePlayerItem(player, I_bone_meal, 1); + } + return 0; + } } } diff --git a/src/procedures.c b/src/procedures.c index 3206c22..483024d 100644 --- a/src/procedures.c +++ b/src/procedures.c @@ -472,6 +472,34 @@ uint8_t isReplaceableBlock (uint8_t block) { ); } +// Checks whether the given item can be used in a composter +// Returns the probability (out of 2^32) to return bone meal +uint32_t isCompostItem (uint16_t item) { + + // Output values calculated using the following formula: + // P = 2^32 / (7 / compost_chance) + + if ( // Compost chance: 30% + item == I_oak_leaves || + item == I_short_grass || + item == I_wheat_seeds || + item == I_oak_sapling || + item == I_moss_carpet + ) return 184070026; + + if ( // Compost chance: 50% + item == I_cactus || + item == I_sugar_cane + ) return 306783378; + + if ( // Compost chance: 65% + item == I_apple || + item == I_lily_pad + ) return 398818392; + + return 0; +} + void handlePlayerAction (PlayerData *player, int action, short x, short y, short z) { // In creative, only the "start mining" action is sent