aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builtin/misc_register.lua16
-rw-r--r--doc/lua_api.txt9
-rw-r--r--src/inventorymanager.cpp8
-rw-r--r--src/script/cpp_api/s_item.cpp51
-rw-r--r--src/script/cpp_api/s_item.h6
-rw-r--r--src/server.cpp3
6 files changed, 93 insertions, 0 deletions
diff --git a/builtin/misc_register.lua b/builtin/misc_register.lua
index f1d816124..aa8399f16 100644
--- a/builtin/misc_register.lua
+++ b/builtin/misc_register.lua
@@ -230,6 +230,20 @@ function minetest.register_biome(biome)
register_biome_raw(biome)
end
+function minetest.on_craft(itemstack, player, old_craft_list, craft_inv)
+ for _, func in ipairs(minetest.registered_on_crafts) do
+ itemstack = func(itemstack, player, old_craft_list, craft_inv) or itemstack
+ end
+ return itemstack
+end
+
+function minetest.craft_predict(itemstack, player, old_craft_list, craft_inv)
+ for _, func in ipairs(minetest.registered_craft_predicts) do
+ itemstack = func(itemstack, player, old_craft_list, craft_inv) or itemstack
+ end
+ return itemstack
+end
+
-- Alias the forbidden item names to "" so they can't be
-- created via itemstrings (e.g. /give)
local name
@@ -327,4 +341,6 @@ minetest.registered_on_joinplayers, minetest.register_on_joinplayer = make_regis
minetest.registered_on_leaveplayers, minetest.register_on_leaveplayer = make_registration()
minetest.registered_on_player_receive_fields, minetest.register_on_player_receive_fields = make_registration_reverse()
minetest.registered_on_cheats, minetest.register_on_cheat = make_registration()
+minetest.registered_on_crafts, minetest.register_on_craft = make_registration()
+minetest.registered_craft_predicts, minetest.register_craft_predict = make_registration()
diff --git a/doc/lua_api.txt b/doc/lua_api.txt
index 5a0d5817f..e94fd30a9 100644
--- a/doc/lua_api.txt
+++ b/doc/lua_api.txt
@@ -1145,6 +1145,15 @@ minetest.register_on_player_receive_fields(func(player, formname, fields))
minetest.register_on_mapgen_init(func(MapgenParams))
^ Called just before the map generator is initialized but before the environment is initialized
^ MapgenParams consists of a table with the fields mgname, seed, water_level, and flags
+minetest.register_on_craft(func(itemstack, player, old_craft_grid, craft_inv))
+^ Called when player crafts something
+^ itemstack is the output
+^ old_craft_grid contains the recipe (Note: the one in the inventory is cleared)
+^ craft_inv is the inventory with the crafting grid
+^ Return either an ItemStack, to replace the output, or nil, to not modify it
+minetest.register_craft_predict(func(itemstack, player, old_craft_grid, craft_inv))
+^ The same as before, except that it is called before the player crafts, to make
+^ craft prediction, and it should not change anything.
Other registration functions:
minetest.register_chatcommand(cmd, chatcommand definition)
diff --git a/src/inventorymanager.cpp b/src/inventorymanager.cpp
index c81f7a19e..1c511e9cb 100644
--- a/src/inventorymanager.cpp
+++ b/src/inventorymanager.cpp
@@ -724,13 +724,19 @@ void ICraftAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGam
}
ItemStack crafted;
+ ItemStack craftresultitem;
int count_remaining = count;
bool found = getCraftingResult(inv_craft, crafted, false, gamedef);
+ PLAYER_TO_SA(player)->item_CraftPredict(crafted, player, list_craft, craft_inv);
+ found = !crafted.empty();
while(found && list_craftresult->itemFits(0, crafted))
{
+ InventoryList saved_craft_list = *list_craft;
+
// Decrement input and add crafting output
getCraftingResult(inv_craft, crafted, true, gamedef);
+ PLAYER_TO_SA(player)->item_OnCraft(crafted, player, &saved_craft_list, craft_inv);
list_craftresult->addItem(0, crafted);
mgr->setInventoryModified(craft_inv);
@@ -747,6 +753,8 @@ void ICraftAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGam
// Get next crafting result
found = getCraftingResult(inv_craft, crafted, false, gamedef);
+ PLAYER_TO_SA(player)->item_CraftPredict(crafted, player, list_craft, craft_inv);
+ found = !crafted.empty();
}
infostream<<"ICraftAction::apply(): crafted "
diff --git a/src/script/cpp_api/s_item.cpp b/src/script/cpp_api/s_item.cpp
index b4536ac63..1d5f218cf 100644
--- a/src/script/cpp_api/s_item.cpp
+++ b/src/script/cpp_api/s_item.cpp
@@ -22,9 +22,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "common/c_converter.h"
#include "common/c_content.h"
#include "lua_api/l_item.h"
+#include "lua_api/l_inventory.h"
#include "server.h"
#include "log.h"
#include "util/pointedthing.h"
+#include "inventory.h"
+#include "inventorymanager.h"
bool ScriptApiItem::item_OnDrop(ItemStack &item,
ServerActiveObject *dropper, v3f pos)
@@ -86,6 +89,54 @@ bool ScriptApiItem::item_OnUse(ItemStack &item,
return true;
}
+bool ScriptApiItem::item_OnCraft(ItemStack &item, ServerActiveObject *user,
+ const InventoryList *old_craft_grid, const InventoryLocation &craft_inv)
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ lua_getglobal(L, "minetest");
+ lua_getfield(L, -1, "on_craft");
+ LuaItemStack::create(L, item);
+ objectrefGetOrCreate(user);
+
+ //Push inventory list
+ std::vector<ItemStack> items;
+ for(u32 i=0; i<old_craft_grid->getSize(); i++)
+ items.push_back(old_craft_grid->getItem(i));
+ push_items(L, items);
+
+ InvRef::create(L, craft_inv);
+ if(lua_pcall(L, 4, 1, 0))
+ scriptError("error: %s", lua_tostring(L, -1));
+ if(!lua_isnil(L, -1))
+ item = read_item(L,-1, getServer());
+ return true;
+}
+
+bool ScriptApiItem::item_CraftPredict(ItemStack &item, ServerActiveObject *user,
+ const InventoryList *old_craft_grid, const InventoryLocation &craft_inv)
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ lua_getglobal(L, "minetest");
+ lua_getfield(L, -1, "craft_predict");
+ LuaItemStack::create(L, item);
+ objectrefGetOrCreate(user);
+
+ //Push inventory list
+ std::vector<ItemStack> items;
+ for(u32 i=0; i<old_craft_grid->getSize(); i++)
+ items.push_back(old_craft_grid->getItem(i));
+ push_items(L, items);
+
+ InvRef::create(L, craft_inv);
+ if(lua_pcall(L, 4, 1, 0))
+ scriptError("error: %s", lua_tostring(L, -1));
+ if(!lua_isnil(L, -1))
+ item = read_item(L,-1, getServer());
+ return true;
+}
+
// Retrieves minetest.registered_items[name][callbackname]
// If that is nil or on error, return false and stack is unchanged
// If that is a function, returns true and pushes the
diff --git a/src/script/cpp_api/s_item.h b/src/script/cpp_api/s_item.h
index 0f2b16042..4964dd5b4 100644
--- a/src/script/cpp_api/s_item.h
+++ b/src/script/cpp_api/s_item.h
@@ -29,6 +29,8 @@ class ServerActiveObject;
struct ItemDefinition;
class LuaItemStack;
class ModApiItemMod;
+class InventoryList;
+class InventoryLocation;
class ScriptApiItem
: virtual public ScriptApiBase
@@ -40,6 +42,10 @@ public:
ServerActiveObject *placer, const PointedThing &pointed);
bool item_OnUse(ItemStack &item,
ServerActiveObject *user, const PointedThing &pointed);
+ bool item_OnCraft(ItemStack &item, ServerActiveObject *user,
+ const InventoryList *old_craft_grid, const InventoryLocation &craft_inv);
+ bool item_CraftPredict(ItemStack &item, ServerActiveObject *user,
+ const InventoryList *old_craft_grid, const InventoryLocation &craft_inv);
protected:
friend class LuaItemStack;
diff --git a/src/server.cpp b/src/server.cpp
index 8350b7013..c29ec3d83 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -4775,7 +4775,10 @@ void Server::UpdateCrafting(u16 peer_id)
// Get a preview for crafting
ItemStack preview;
+ InventoryLocation loc;
+ loc.setPlayer(player->getName());
getCraftingResult(&player->inventory, preview, false, this);
+ m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(), (&player->inventory)->getList("craft"), loc);
// Put the new preview in
InventoryList *plist = player->inventory.getList("craftpreview");