]> git.lizzy.rs Git - minetest.git/blobdiff - src/craftdef.cpp
Report collisionMoveSimple for client and server. (#13105)
[minetest.git] / src / craftdef.cpp
index 24b7437cbe7ec15bfaba220fd8b31f15abaf8581..eb703fdbee4251fad6ffc5b5a7663ae8adb7bf81 100644 (file)
@@ -22,7 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "irrlichttypes.h"
 #include "log.h"
 #include <sstream>
-#include <set>
+#include <unordered_set>
 #include <algorithm>
 #include "gamedef.h"
 #include "inventory.h"
@@ -229,6 +229,7 @@ static void craftDecrementOrReplaceInput(CraftInput &input,
                                rep.deSerialize(j->second, gamedef->idef());
                                item.remove(1);
                                found_replacement = true;
+                               pairs.erase(j);
                                output_replacements.push_back(rep);
                                break;
 
@@ -287,6 +288,15 @@ std::string craftDumpMatrix(const std::vector<ItemStack> &items,
        CraftInput
 */
 
+bool CraftInput::empty() const
+{
+       for (const auto &item : items) {
+               if (!item.empty())
+                       return false;
+       }
+       return true;
+}
+
 std::string CraftInput::dump() const
 {
        std::ostringstream os(std::ios::binary);
@@ -725,7 +735,8 @@ bool CraftDefinitionCooking::check(const CraftInput &input, IGameDef *gamedef) c
        }
 
        // Check the single input item
-       return inputItemMatchesRecipe(input_filtered[0], recipe, gamedef->idef());
+       std::string rec_name = craftGetItemName(recipe, gamedef);
+       return inputItemMatchesRecipe(input_filtered[0], rec_name, gamedef->idef());
 }
 
 CraftOutput CraftDefinitionCooking::getOutput(const CraftInput &input, IGameDef *gamedef) const
@@ -827,7 +838,8 @@ bool CraftDefinitionFuel::check(const CraftInput &input, IGameDef *gamedef) cons
        }
 
        // Check the single input item
-       return inputItemMatchesRecipe(input_filtered[0], recipe, gamedef->idef());
+       std::string rec_name = craftGetItemName(recipe, gamedef);
+       return inputItemMatchesRecipe(input_filtered[0], rec_name, gamedef->idef());
 }
 
 CraftOutput CraftDefinitionFuel::getOutput(const CraftInput &input, IGameDef *gamedef) const
@@ -906,18 +918,7 @@ class CCraftDefManager: public IWritableCraftDefManager
                        std::vector<ItemStack> &output_replacement, bool decrementInput,
                        IGameDef *gamedef) const
        {
-               output.item = "";
-               output.time = 0;
-
-               // If all input items are empty, abort.
-               bool all_empty = true;
-               for (const auto &item : input.items) {
-                       if (!item.empty()) {
-                               all_empty = false;
-                               break;
-                       }
-               }
-               if (all_empty)
+               if (input.empty())
                        return false;
 
                std::vector<std::string> input_names;
@@ -1002,86 +1003,55 @@ class CCraftDefManager: public IWritableCraftDefManager
                return recipes;
        }
 
-       virtual bool clearCraftRecipesByOutput(const CraftOutput &output, IGameDef *gamedef)
+       virtual bool clearCraftsByOutput(const CraftOutput &output, IGameDef *gamedef)
        {
-               auto vec_iter = m_output_craft_definitions.find(output.item);
+               auto to_clear = m_output_craft_definitions.find(output.item);
 
-               if (vec_iter == m_output_craft_definitions.end())
+               if (to_clear == m_output_craft_definitions.end())
                        return false;
 
-               std::vector<CraftDefinition*> &vec = vec_iter->second;
-               for (auto def : vec) {
+               for (auto def : to_clear->second) {
                        // Recipes are not yet hashed at this point
-                       std::vector<CraftDefinition*> &unhashed_inputs_vec = m_craft_defs[(int) CRAFT_HASH_TYPE_UNHASHED][0];
-                       std::vector<CraftDefinition*> new_vec_by_input;
-                       /* We will preallocate necessary memory addresses, so we don't need to reallocate them later.
-                               This would save us some performance. */
-                       new_vec_by_input.reserve(unhashed_inputs_vec.size());
-                       for (auto &i2 : unhashed_inputs_vec) {
-                               if (def != i2) {
-                                       new_vec_by_input.push_back(i2);
-                               }
-                       }
-                       m_craft_defs[(int) CRAFT_HASH_TYPE_UNHASHED][0].swap(new_vec_by_input);
+                       std::vector<CraftDefinition *> &defs = m_craft_defs[(int)CRAFT_HASH_TYPE_UNHASHED][0];
+                       defs.erase(std::remove(defs.begin(), defs.end(), def), defs.end());
+                       delete def;
                }
-               m_output_craft_definitions.erase(output.item);
+               m_output_craft_definitions.erase(to_clear);
                return true;
        }
 
-       virtual bool clearCraftRecipesByInput(CraftMethod craft_method, unsigned int craft_grid_width,
-               const std::vector<std::string> &recipe, IGameDef *gamedef)
+       virtual bool clearCraftsByInput(const CraftInput &input, IGameDef *gamedef)
        {
-               bool all_empty = true;
-               for (const auto &i : recipe) {
-                       if (!i.empty()) {
-                               all_empty = false;
-                               break;
-                       }
-               }
-               if (all_empty)
+               if (input.empty())
                        return false;
 
-               CraftInput input(craft_method, craft_grid_width, craftGetItems(recipe, gamedef));
                // Recipes are not yet hashed at this point
-               std::vector<CraftDefinition*> &unhashed_inputs_vec = m_craft_defs[(int) CRAFT_HASH_TYPE_UNHASHED][0];
-               std::vector<CraftDefinition*> new_vec_by_input;
-               bool got_hit = false;
-               for (std::vector<CraftDefinition*>::size_type
-                               i = unhashed_inputs_vec.size(); i > 0; i--) {
-                       CraftDefinition *def = unhashed_inputs_vec[i - 1];
-                       /* If the input doesn't match the recipe definition, this recipe definition later
-                               will be added back in source map. */
-                       if (!def->check(input, gamedef)) {
-                               new_vec_by_input.push_back(def);
-                               continue;
-                       }
-                       CraftOutput output = def->getOutput(input, gamedef);
-                       got_hit = true;
-                       auto vec_iter = m_output_craft_definitions.find(output.item);
-                       if (vec_iter == m_output_craft_definitions.end())
-                               continue;
-                       std::vector<CraftDefinition*> &vec = vec_iter->second;
-                       std::vector<CraftDefinition*> new_vec_by_output;
-                       /* We will preallocate necessary memory addresses, so we don't need
-                               to reallocate them later. This would save us some performance. */
-                       new_vec_by_output.reserve(vec.size());
-                       for (auto &vec_i : vec) {
-                               /* If pointers from map by input and output are not same,
-                                       we will add 'CraftDefinition*' to a new vector. */
-                               if (def != vec_i) {
-                                       /* Adding dereferenced iterator value (which are
-                                               'CraftDefinition' reference) to a new vector. */
-                                       new_vec_by_output.push_back(vec_i);
-                               }
+               std::vector<CraftDefinition *> &defs = m_craft_defs[(int)CRAFT_HASH_TYPE_UNHASHED][0];
+               std::unordered_set<const CraftDefinition *> defs_to_remove;
+               std::vector<CraftDefinition *> new_defs;
+
+               for (auto def : defs) {
+                       if (def->check(input, gamedef))
+                               defs_to_remove.insert(def);
+                       else
+                               new_defs.push_back(def);
+               }
+
+               if (!defs_to_remove.empty()) {
+                       for (auto def : defs_to_remove)
+                               delete def;
+
+                       defs.swap(new_defs);
+
+                       for (auto &output : m_output_craft_definitions) {
+                               std::vector<CraftDefinition *> &outdefs = output.second;
+                               outdefs.erase(std::remove_if(outdefs.begin(), outdefs.end(), [&](const CraftDefinition* def) {
+                                       return defs_to_remove.find(def) != defs_to_remove.end();
+                               }), outdefs.end());
                        }
-                       // Swaps assigned to current key value with new vector for output map.
-                       m_output_craft_definitions[output.item].swap(new_vec_by_output);
                }
-               if (got_hit)
-                       // Swaps value with new vector for input map.
-                       m_craft_defs[(int) CRAFT_HASH_TYPE_UNHASHED][0].swap(new_vec_by_input);
 
-               return got_hit;
+               return !defs_to_remove.empty();
        }
 
        virtual std::string dump() const
@@ -1104,8 +1074,8 @@ class CCraftDefManager: public IWritableCraftDefManager
        }
        virtual void registerCraft(CraftDefinition *def, IGameDef *gamedef)
        {
-               verbosestream << "registerCraft: registering craft definition: "
-                               << def->dump() << std::endl;
+               TRACESTREAM(<< "registerCraft: registering craft definition: "
+                               << def->dump() << std::endl);
                m_craft_defs[(int) CRAFT_HASH_TYPE_UNHASHED][0].push_back(def);
 
                CraftInput input;