mirror of
				https://github.com/luanti-org/luanti.git
				synced 2025-11-04 01:05:48 +01:00 
			
		
		
		
	Add a callback: minetest.register_on_craft(itemstack, player,
old_craft_grid, craft_inv) and minetest.register_craft_predict(itemstack, player, old_craft_grid, craft_inv)
This commit is contained in:
		@@ -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()
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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 "
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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");
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user