From 17ba584fe254eeaee3489cc20e03810a59f3ef9b Mon Sep 17 00:00:00 2001 From: TeTpaAka Date: Tue, 2 Jun 2015 20:30:04 +0200 Subject: Fix bug when craft input isn't replaced --- src/inventorymanager.cpp | 93 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 67 insertions(+), 26 deletions(-) (limited to 'src/inventorymanager.cpp') diff --git a/src/inventorymanager.cpp b/src/inventorymanager.cpp index c3a9576f9..640e3395b 100644 --- a/src/inventorymanager.cpp +++ b/src/inventorymanager.cpp @@ -691,72 +691,112 @@ ICraftAction::ICraftAction(std::istream &is) craft_inv.deSerialize(ts); } -void ICraftAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGameDef *gamedef) +void ICraftAction::apply(InventoryManager *mgr, + ServerActiveObject *player, IGameDef *gamedef) { Inventory *inv_craft = mgr->getInventory(craft_inv); - if(!inv_craft){ - infostream<<"ICraftAction::apply(): FAIL: inventory not found: " - <<"craft_inv=\""<getList("craft"); InventoryList *list_craftresult = inv_craft->getList("craftresult"); + InventoryList *list_main = inv_craft->getList("main"); /* If a list doesn't exist or the source item doesn't exist */ - if(!list_craft){ - infostream<<"ICraftAction::apply(): FAIL: craft list not found: " - <<"craft_inv=\""<getSize() < 1){ - infostream<<"ICraftAction::apply(): FAIL: craftresult list too short: " - <<"craft_inv=\""<getSize() < 1) { + infostream << "ICraftAction::apply(): FAIL: craftresult list too short: " + << "craft_inv=\"" << craft_inv.dump() << "\"" << std::endl; return; } ItemStack crafted; ItemStack craftresultitem; int count_remaining = count; - getCraftingResult(inv_craft, crafted, false, gamedef); + std::vector output_replacements; + getCraftingResult(inv_craft, crafted, output_replacements, false, gamedef); PLAYER_TO_SA(player)->item_CraftPredict(crafted, player, list_craft, craft_inv); bool found = !crafted.empty(); - while(found && list_craftresult->itemFits(0, crafted)) - { + while (found && list_craftresult->itemFits(0, crafted)) { InventoryList saved_craft_list = *list_craft; - + + std::vector temp; // Decrement input and add crafting output - getCraftingResult(inv_craft, crafted, true, gamedef); + getCraftingResult(inv_craft, crafted, temp, true, gamedef); PLAYER_TO_SA(player)->item_OnCraft(crafted, player, &saved_craft_list, craft_inv); list_craftresult->addItem(0, crafted); mgr->setInventoryModified(craft_inv); - actionstream<getDescription() - <<" crafts " - <getItemDefManager(); + for (std::vector::iterator it = temp.begin(); + it != temp.end(); it++) { + for (std::vector::iterator jt = output_replacements.begin(); + jt != output_replacements.end(); jt++) { + if (it->name == jt->name) { + *it = jt->addItem(*it, itemdef); + if (it->empty()) + continue; + } + } + output_replacements.push_back(*it); + } + + actionstream << player->getDescription() + << " crafts " + << crafted.getItemString() + << std::endl; // Decrement counter - if(count_remaining == 1) + if (count_remaining == 1) break; - else if(count_remaining > 1) + else if (count_remaining > 1) count_remaining--; // Get next crafting result - found = getCraftingResult(inv_craft, crafted, false, gamedef); + found = getCraftingResult(inv_craft, crafted, temp, false, gamedef); PLAYER_TO_SA(player)->item_CraftPredict(crafted, player, list_craft, craft_inv); found = !crafted.empty(); } + // Put the replacements in the inventory or drop them on the floor, if + // the invenotry is full + for (std::vector::iterator it = output_replacements.begin(); + it != output_replacements.end(); it++) { + if (list_main) + *it = list_main->addItem(*it); + if (it->empty()) + continue; + u16 count = it->count; + do { + PLAYER_TO_SA(player)->item_OnDrop(*it, player, + player->getBasePosition() + v3f(0,1,0)); + if (count >= it->count) { + errorstream << "Couldn't drop replacement stack " << + it->getItemString() << " because drop loop didn't " + "decrease count." << std::endl; + + break; + } + } while (!it->empty()); + } + infostream<<"ICraftAction::apply(): crafted " <<" craft_inv=\""< &output_replacements, bool decrementInput, IGameDef *gamedef) { DSTACK(__FUNCTION_NAME); @@ -792,7 +833,7 @@ bool getCraftingResult(Inventory *inv, ItemStack& result, // Find out what is crafted and add it to result item slot CraftOutput co; bool found = gamedef->getCraftDefManager()->getCraftResult( - ci, co, decrementInput, gamedef); + ci, co, output_replacements, decrementInput, gamedef); if(found) result.deSerialize(co.item, gamedef->getItemDefManager()); -- cgit v1.2.3