Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

craft all: properly invoke on_crafted callbacks #23

Merged
merged 3 commits into from
Feb 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .luacheckrc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ globals = {
}

read_globals = {
"futil",
"stamina",
"skyblock",
"ItemStack",
Expand Down
19 changes: 19 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.3.0
hooks:
- id: fix-byte-order-marker
- id: end-of-file-fixer
- id: trailing-whitespace
- id: mixed-line-ending
args: [ --fix=lf ]

- repo: local
hooks:
- id: luacheck
name: luacheck
language: system
entry: luacheck
pass_filenames: true
types: [ file, lua ]
args: [ -q ]
62 changes: 36 additions & 26 deletions craft_all.lua
Original file line number Diff line number Diff line change
Expand Up @@ -49,48 +49,68 @@ end

-- Craft max possible items and put the result in the main inventory
local function craft_craftall(player)
local player_inv = player:get_inventory()
local player_name = player:get_player_name()
local player_inv = player:get_inventory()
local craft_list = player_inv:get_list("craft")
local expected_result = player_inv:get_stack("craftpreview", 1)
local craft_width = infer_width(craft_list, expected_result)
if not craft_width then
return
end

if (
has.stamina and
stamina.get_saturation and
stamina.get_saturation(player) <= settings.craft_all_min_saturation
) then
minetest.chat_send_player(player_name, S("You are too hungry to use Craft All at this time."))
return
end

local num_crafted = 0
-- don't modify player's inventory until end, in case something goes wrong (e.g. crash)
local tmp_inv_name = ("uip_tmp_%s"):format(player_name)
local tmp_inv = minetest.create_detached_inventory(tmp_inv_name, {}, player_name)
-- don't modify player's inventory until we're done, in case something goes wrong (e.g. crash)
-- use FakeInventory instead of a detached inventory, because detached inventory actions all result in packets
-- sent to the player.
local tmp_inv = futil.FakeInventory()
tmp_inv:set_size("main", player_inv:get_size("main"))
tmp_inv:set_list("main", player_inv:get_list("main"))
tmp_inv:set_size("craft", player_inv:get_size("craft"))
tmp_inv:set_list("craft", craft_list)

while true do
if (
has.stamina and
stamina.get_saturation and
stamina.get_saturation(player) <= settings.craft_all_min_saturation
) then
minetest.chat_send_player(player_name, S("You are too hungry to use Craft All at this time."))
break
end

-- note that get_craft_result can be *very* slow, until minetest 5.7.0 is released.
-- see https://github.com/minetest/minetest/issues/13231
local output, decremented_input = minetest.get_craft_result({
method = "normal",
width = craft_width,
items = craft_list,
})

if output.item:get_name() ~= expected_result:get_name() then
-- the recipe changed, so we've run out of something. stop processing.
break
end

-- minetest.on_craft expects to see the decremented input list.
tmp_inv:set_list("craft", decremented_input.items)

-- invoke callbacks, for compatibility w/ stamina, skyblock, moretrees, etc.
-- note that this is an *undocumented* handler of the minetest lua API, and possibly is subject to change
-- in the future.
output.item = minetest.on_craft(output.item, player, craft_list, tmp_inv)

-- track items added to the inventory, in case we need to remove them later
local added = {}

if tmp_inv:room_for_item("main", output.item) then
tmp_inv:add_item("main", output.item) -- should be no remainder, ignore it
table.insert(added, output.item)
else
-- no room for the output item, stop
break
end

-- we now try to add all replacements.
local all_added = true
for _, replacement_stk in ipairs(output.replacements) do
if tmp_inv:room_for_item("main", replacement_stk) then
Expand All @@ -103,32 +123,22 @@ local function craft_craftall(player)
end

if not all_added then
-- if we failed to add all the replacements, remove what we've added, and abort
for _, stk in ipairs(added) do
tmp_inv:remove_item("main", stk) -- should be no remainder, ignore it
end
break
end

if has.stamina and stamina.exhaust_player then
stamina.exhaust_player(player, stamina.settings.exhaust_craft, stamina.exhaustion_reasons.craft)
end

-- support skyblock quests
if has.skyblock then
-- track crafting, mimic minetest.register_on_craft as it's bypassed using this function ;)
skyblock.feats.on_craft(expected_result, player)
end

craft_list = decremented_input.items
-- the craft list can be modified by the callbacks, so re-load it
craft_list = tmp_inv:get_list("craft")

num_crafted = num_crafted + 1
end

player_inv:set_list("craft", craft_list)
player_inv:set_list("main", tmp_inv:get_list("main"))

minetest.remove_detached_inventory(tmp_inv_name)

uip.log("action", S("%s crafts %s %i"), player_name, expected_result:to_string(), num_crafted)
end

Expand Down
4 changes: 2 additions & 2 deletions init.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
-- Unified Inventory Plus for Minetest 0.4.8+
-- Unified Inventory Plus for Minetest
futil.check_version({ year = 2023, month = 02, day = 26 })

local modname = minetest.get_current_modname()
local modpath = minetest.get_modpath(modname)
Expand Down Expand Up @@ -27,7 +28,6 @@ unified_inventory_plus = {

has = {
stamina = minetest.global_exists("stamina"),
skyblock = minetest.get_modpath("skyblock"),
},

log = function(level, message_fmt, ...)
Expand Down
4 changes: 2 additions & 2 deletions mod.conf
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name = unified_inventory_plus
depends = unified_inventory
optional_depends = stamina, skyblock
depends = unified_inventory, futil
optional_depends = stamina
min_minetest_version = 5.4.0
3 changes: 2 additions & 1 deletion settingtypes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ unified_inventory_plus.enable_craft_rotate (enable rotate buttons) bool true
unified_inventory_plus.enable_craft_clear (enable "clear" button) bool true

# Disable the "craft all" feature if saturation (from the stamina mod) is below a given value.
unified_inventory_plus.craft_all_min_saturation (Minimum saturation for "craft all") int 1 0 20
# Set to -1 always allow "craft all".
unified_inventory_plus.craft_all_min_saturation (Minimum saturation for "craft all") int 1 -1 20