aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDS <vorunbekannt75@web.de>2022-10-01 21:21:06 +0200
committerGitHub <noreply@github.com>2022-10-01 15:21:06 -0400
commit22cbc058080127445b69d2137e346ad52f8b3387 (patch)
treebd42bead55d1a05acf5c65385cc59d64bbfa9617
parent977f656e09c4b542e09ec210b202ba46eb45ac5e (diff)
downloadminetest-22cbc058080127445b69d2137e346ad52f8b3387.tar.xz
Add an item pick up callback (2) (#7712)
Co-authored-by: SmallJoker <mk939@ymail.com> Co-authored-by: Jude Melton-Houghton <jwmhjwmh@gmail.com>
-rw-r--r--LICENSE.txt9
-rw-r--r--builtin/game/item.lua26
-rw-r--r--builtin/game/item_entity.lua33
-rw-r--r--builtin/game/register.lua1
-rw-r--r--doc/lua_api.txt25
-rw-r--r--games/devtest/mods/testitems/init.lua108
-rw-r--r--games/devtest/mods/testitems/textures/testitems_callback_1.pngbin0 -> 148 bytes
-rw-r--r--games/devtest/mods/testitems/textures/testitems_callback_2.pngbin0 -> 148 bytes
8 files changed, 189 insertions, 13 deletions
diff --git a/LICENSE.txt b/LICENSE.txt
index af4c4c546..0a27f907a 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -14,6 +14,9 @@ https://www.apache.org/licenses/LICENSE-2.0.html
Textures by Zughy are under CC BY-SA 4.0
https://creativecommons.org/licenses/by-sa/4.0/
+Media files by DS are under CC BY-SA 4.0
+https://creativecommons.org/licenses/by-sa/4.0/
+
textures/base/pack/server_public.png is under CC-BY 4.0, taken from Twitter's Twemoji set
https://creativecommons.org/licenses/by/4.0/
@@ -62,7 +65,7 @@ Zughy:
appgurueu:
textures/base/pack/server_incompatible.png
-
+
erlehmann, Warr1024, rollerozxa:
textures/base/pack/no_screenshot.png
@@ -73,6 +76,10 @@ SmallJoker:
textures/base/pack/cdb_clear.png
textures/base/pack/server_favorite_delete.png (based on server_favorite.png)
+DS:
+ games/devtest/mods/testitems/textures/testitems_callback_1.png
+ games/devtest/mods/testitems/textures/testitems_callback_2.png
+
License of Minetest source code
-------------------------------
diff --git a/builtin/game/item.lua b/builtin/game/item.lua
index af3fcb645..2e8fcc343 100644
--- a/builtin/game/item.lua
+++ b/builtin/game/item.lua
@@ -349,8 +349,26 @@ function core.item_drop(itemstack, dropper, pos)
-- environment failed
end
+function core.item_pickup(itemstack, picker, pointed_thing, ...)
+ itemstack = ItemStack(itemstack)
+ -- Invoke global on_item_pickup callbacks.
+ for _, callback in ipairs(core.registered_on_item_pickups) do
+ local result = callback(itemstack, picker, pointed_thing, ...)
+ if result then
+ return ItemStack(result)
+ end
+ end
+
+ -- Pickup item.
+ local inv = picker and picker:get_inventory()
+ if inv then
+ return inv:add_item("main", itemstack)
+ end
+ return itemstack
+end
+
function core.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed_thing)
- for _, callback in pairs(core.registered_on_item_eats) do
+ for _, callback in ipairs(core.registered_on_item_eats) do
local result = callback(hp_change, replace_with_item, itemstack, user, pointed_thing)
if result then
return result
@@ -589,6 +607,7 @@ core.nodedef_default = {
-- Interaction callbacks
on_place = redef_wrapper(core, 'item_place'), -- core.item_place
on_drop = redef_wrapper(core, 'item_drop'), -- core.item_drop
+ on_pickup = redef_wrapper(core, 'item_pickup'), -- core.item_pickup
on_use = nil,
can_dig = nil,
@@ -641,6 +660,7 @@ core.craftitemdef_default = {
-- Interaction callbacks
on_place = redef_wrapper(core, 'item_place'), -- core.item_place
on_drop = redef_wrapper(core, 'item_drop'), -- core.item_drop
+ on_pickup = redef_wrapper(core, 'item_pickup'), -- core.item_pickup
on_secondary_use = redef_wrapper(core, 'item_secondary_use'),
on_use = nil,
}
@@ -661,6 +681,7 @@ core.tooldef_default = {
on_place = redef_wrapper(core, 'item_place'), -- core.item_place
on_secondary_use = redef_wrapper(core, 'item_secondary_use'),
on_drop = redef_wrapper(core, 'item_drop'), -- core.item_drop
+ on_pickup = redef_wrapper(core, 'item_pickup'), -- core.item_pickup
on_use = nil,
}
@@ -677,8 +698,9 @@ core.noneitemdef_default = { -- This is used for the hand and unknown items
tool_capabilities = nil,
-- Interaction callbacks
- on_place = redef_wrapper(core, 'item_place'),
+ on_place = redef_wrapper(core, 'item_place'), -- core.item_place
on_secondary_use = redef_wrapper(core, 'item_secondary_use'),
+ on_pickup = redef_wrapper(core, 'item_pickup'), -- core.item_pickup
on_drop = nil,
on_use = nil,
}
diff --git a/builtin/game/item_entity.lua b/builtin/game/item_entity.lua
index 53f98a7c7..f321bb1dd 100644
--- a/builtin/game/item_entity.lua
+++ b/builtin/game/item_entity.lua
@@ -318,16 +318,29 @@ core.register_entity(":__builtin:item", {
end
end,
- on_punch = function(self, hitter)
- local inv = hitter:get_inventory()
- if inv and self.itemstring ~= "" then
- local left = inv:add_item("main", self.itemstring)
- if left and not left:is_empty() then
- self:set_item(left)
- return
- end
+ on_punch = function(self, hitter, ...)
+ if self.itemstring == "" then
+ self.object:remove()
+ return
+ end
+
+ -- Call on_pickup callback in item definition.
+ local itemstack = ItemStack(self.itemstring)
+ local callback = itemstack:get_definition().on_pickup
+
+ local ret = callback(itemstack, hitter, {type = "object", ref = self.object}, ...)
+ if not ret then
+ -- Don't modify (and don't reset rotation)
+ return
+ end
+ itemstack = ItemStack(ret)
+
+ -- Handle the leftover itemstack
+ if itemstack:is_empty() then
+ self.itemstring = ""
+ self.object:remove()
+ else
+ self:set_item(itemstack)
end
- self.itemstring = ""
- self.object:remove()
end,
})
diff --git a/builtin/game/register.lua b/builtin/game/register.lua
index 8b6f5b990..d4c876898 100644
--- a/builtin/game/register.lua
+++ b/builtin/game/register.lua
@@ -607,6 +607,7 @@ core.registered_on_crafts, core.register_on_craft = make_registration()
core.registered_craft_predicts, core.register_craft_predict = make_registration()
core.registered_on_protection_violation, core.register_on_protection_violation = make_registration()
core.registered_on_item_eats, core.register_on_item_eat = make_registration()
+core.registered_on_item_pickups, core.register_on_item_pickup = make_registration()
core.registered_on_punchplayers, core.register_on_punchplayer = make_registration()
core.registered_on_priv_grant, core.register_on_priv_grant = make_registration()
core.registered_on_priv_revoke, core.register_on_priv_revoke = make_registration()
diff --git a/doc/lua_api.txt b/doc/lua_api.txt
index 201f4d123..390bf8b2f 100644
--- a/doc/lua_api.txt
+++ b/doc/lua_api.txt
@@ -5318,6 +5318,13 @@ Call these functions only at load time!
* `minetest.register_on_item_eat(function(hp_change, replace_with_item, itemstack, user, pointed_thing))`
* Called when an item is eaten, by `minetest.item_eat`
* Return `itemstack` to cancel the default item eat response (i.e.: hp increase).
+* `minetest.register_on_item_pickup(function(itemstack, picker, pointed_thing, time_from_last_punch, ...))`
+ * Called by `minetest.item_pickup` before an item is picked up.
+ * Function is added to `minetest.registered_on_item_pickups`.
+ * Oldest functions are called first.
+ * Parameters are the same as in the `on_pickup` callback.
+ * Return an itemstack to cancel the default item pick-up response (i.e.: adding
+ the item into inventory).
* `minetest.register_on_priv_grant(function(name, granter, priv))`
* Called when `granter` grants the priv `priv` to `name`.
* Note that the callback will be called twice if it's done by a player,
@@ -5964,6 +5971,11 @@ Defaults for the `on_place` and `on_drop` item definition functions
* `param2` overrides facedir and wallmounted `param2`
* returns `itemstack, position`
* `position`: the location the node was placed to. `nil` if nothing was placed.
+* `minetest.item_pickup(itemstack, picker, pointed_thing, time_from_last_punch, ...)`
+ * Runs callbacks registered by `minetest.register_on_item_pickup` and adds
+ the item to the picker's `"main"` inventory list.
+ * Parameters are the same as in `on_pickup`.
+ * Returns the leftover itemstack.
* `minetest.item_drop(itemstack, dropper, pos)`
* Drop the item
* returns the leftover itemstack
@@ -8074,6 +8086,19 @@ Used by `minetest.register_node`, `minetest.register_craftitem`, and
-- The dropper may be any ObjectRef or nil.
-- default: minetest.item_drop
+ on_pickup = function(itemstack, picker, pointed_thing, time_from_last_punch, ...),
+ -- Called when a dropped item is punched by a player.
+ -- Shall pick-up the item and return the leftover itemstack or nil to not
+ -- modify the dropped item.
+ -- Parameters:
+ -- * `itemstack`: The `ItemStack` to be picked up.
+ -- * `picker`: Any `ObjectRef` or `nil`.
+ -- * `pointed_thing` (optional): The dropped item (a `"__builtin:item"`
+ -- luaentity) as `type="object"` `pointed_thing`.
+ -- * `time_from_last_punch, ...` (optional): Other parameters from
+ -- `luaentity:on_punch`.
+ -- default: `minetest.item_pickup`
+
on_use = function(itemstack, user, pointed_thing),
-- default: nil
-- When user pressed the 'punch/mine' key with the item in hand.
diff --git a/games/devtest/mods/testitems/init.lua b/games/devtest/mods/testitems/init.lua
index 33ebf50fc..0c4cc60de 100644
--- a/games/devtest/mods/testitems/init.lua
+++ b/games/devtest/mods/testitems/init.lua
@@ -53,3 +53,111 @@ minetest.register_craftitem("testitems:overlay_global", {
})
+--
+-- Item callbacks
+--
+
+minetest.register_craftitem("testitems:callback_1", {
+ description = "Callback test item 1\n(Use/Drop + Sneak to switch to item 2)",
+ inventory_image = "testitems_callback_1.png",
+ wield_image = "testitems_callback_1.png",
+
+ on_secondary_use = function(itemstack, user, pointed_thing)
+ minetest.log("[testitems:callback_1 on_secondary_use] " .. itemstack:get_name())
+ local ctrl = user and user:get_player_control() or {}
+ if ctrl.sneak then
+ itemstack = ItemStack(itemstack)
+ itemstack:set_name("testitems:callback_2")
+ return itemstack
+ end
+ end,
+
+ on_drop = function(itemstack, dropper, pos)
+ minetest.log("[testitems:callback_1 on_drop] " .. itemstack:get_name())
+ local ctrl = dropper and dropper:get_player_control() or {}
+ if ctrl.sneak then
+ itemstack = ItemStack(itemstack)
+ itemstack:set_name("testitems:callback_2")
+ end
+
+ return minetest.item_drop(itemstack, dropper, pos)
+ end,
+
+ on_pickup = function(itemstack, picker, pointed_thing, ...)
+ minetest.log("[testitems:callback_1 on_pickup]")
+ assert(pointed_thing.ref:get_luaentity().name == "__builtin:item")
+ local ctrl = picker and picker:get_player_control() or {}
+ if ctrl.aux1 then
+ -- Debug message
+ minetest.log(dump({...}))
+ end
+ if ctrl.sneak then
+ -- Pick up one item of the other kind at once
+ local taken = itemstack:take_item()
+ taken:set_name("testitems:callback_2")
+ local leftover = minetest.item_pickup(taken, picker, pointed_thing, ...)
+ leftover:set_name("testitems:callback_1")
+ itemstack:add_item(leftover)
+ return itemstack
+ elseif ctrl.up then
+ -- Don't pick up
+ return
+ elseif ctrl.left then
+ -- Eat it
+ return minetest.do_item_eat(2, nil, itemstack, picker, pointed_thing)
+ else
+ -- Normal: pick up everything
+ return minetest.item_pickup(itemstack, picker, pointed_thing, ...)
+ end
+ end,
+
+ on_use = function(itemstack, user, pointed_thing)
+ minetest.log("[testitems:callback_1 on_use] " .. itemstack:get_name())
+ local ctrl = user and user:get_player_control() or {}
+ if ctrl.sneak then
+ itemstack = ItemStack(itemstack)
+ itemstack:set_name("testitems:callback_2")
+ return itemstack
+ end
+ end,
+
+ after_use = function(itemstack, user, node, digparams) -- never called
+ minetest.log("[testitems:callback_1 after_use]")
+ local ctrl = user and user:get_player_control() or {}
+ if ctrl.up then
+ itemstack = ItemStack(itemstack)
+ itemstack:set_name("testitems:callback_2")
+ return itemstack
+ end
+ end,
+})
+
+minetest.register_craftitem("testitems:callback_2", {
+ description = "Callback test item 2\n(Use to switch to item 1)",
+ inventory_image = "testitems_callback_2.png",
+ wield_image = "testitems_callback_2.png",
+
+ on_use = function(itemstack, user, pointed_thing)
+ minetest.log("[testitems:callback_2 on_use]")
+ itemstack = ItemStack(itemstack)
+ itemstack:set_name("testitems:callback_1")
+ return itemstack
+ end,
+})
+
+minetest.register_on_item_pickup(function(itemstack, picker, pointed_thing, time_from_last_punch, ...)
+ assert(not pointed_thing or pointed_thing.ref:get_luaentity().name == "__builtin:item")
+
+ local item_name = itemstack:get_name()
+ if item_name ~= "testitems:callback_1" and item_name ~= "testitems:callback_2" then
+ return
+ end
+ minetest.log("["..item_name.." register_on_item_pickup]")
+
+ local ctrl = picker and picker:get_player_control() or {}
+ if item_name == "testitems:callback_2" and not ctrl.sneak then
+ -- Same here. Pick up the other item type.
+ itemstack:set_name("testitems:callback_1")
+ return picker:get_inventory():add_item("main", itemstack)
+ end
+end)
diff --git a/games/devtest/mods/testitems/textures/testitems_callback_1.png b/games/devtest/mods/testitems/textures/testitems_callback_1.png
new file mode 100644
index 000000000..92cbc1be3
--- /dev/null
+++ b/games/devtest/mods/testitems/textures/testitems_callback_1.png
Binary files differ
diff --git a/games/devtest/mods/testitems/textures/testitems_callback_2.png b/games/devtest/mods/testitems/textures/testitems_callback_2.png
new file mode 100644
index 000000000..85732af7c
--- /dev/null
+++ b/games/devtest/mods/testitems/textures/testitems_callback_2.png
Binary files differ