From 40bc9b16665c6be21219eed5323263bae9937cb9 Mon Sep 17 00:00:00 2001 From: flux <25628292+fluxionary@users.noreply.github.com> Date: Sun, 26 Feb 2023 12:16:09 -0800 Subject: [PATCH 1/3] properly invoke on_crafted callbacks; use FakeInventory to avoid spamming temporary inventory changes over the network --- craft_all.lua | 60 +++++++++++++++++++++++++++--------------------- init.lua | 4 ++-- mod.conf | 4 ++-- settingtypes.txt | 3 ++- 4 files changed, 40 insertions(+), 31 deletions(-) diff --git a/craft_all.lua b/craft_all.lua index c811c52..502bbd5 100644 --- a/craft_all.lua +++ b/craft_all.lua @@ -49,8 +49,8 @@ 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) @@ -58,22 +58,28 @@ local function craft_craftall(player) 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, @@ -81,16 +87,28 @@ local function craft_craftall(player) }) 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. + 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 @@ -103,23 +121,15 @@ 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 @@ -127,8 +137,6 @@ local function craft_craftall(player) 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 diff --git a/init.lua b/init.lua index 047ce71..d5c8bdd 100644 --- a/init.lua +++ b/init.lua @@ -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) @@ -27,7 +28,6 @@ unified_inventory_plus = { has = { stamina = minetest.global_exists("stamina"), - skyblock = minetest.get_modpath("skyblock"), }, log = function(level, message_fmt, ...) diff --git a/mod.conf b/mod.conf index 779f118..1d03f77 100644 --- a/mod.conf +++ b/mod.conf @@ -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 diff --git a/settingtypes.txt b/settingtypes.txt index f15f93e..29eae3f 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -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 From 6f0c80bc74addd41ead52377420111fc58bcf120 Mon Sep 17 00:00:00 2001 From: flux <25628292+fluxionary@users.noreply.github.com> Date: Sun, 26 Feb 2023 12:40:27 -0800 Subject: [PATCH 2/3] document use of undocumented API --- craft_all.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/craft_all.lua b/craft_all.lua index 502bbd5..595dbcb 100644 --- a/craft_all.lua +++ b/craft_all.lua @@ -95,6 +95,8 @@ local function craft_craftall(player) 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 From ca05153dc68bb482546044070440227b91267b3e Mon Sep 17 00:00:00 2001 From: flux <25628292+fluxionary@users.noreply.github.com> Date: Sun, 26 Feb 2023 20:58:29 -0800 Subject: [PATCH 3/3] add futil to luacheck --- .luacheckrc | 1 + .pre-commit-config.yaml | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 .pre-commit-config.yaml diff --git a/.luacheckrc b/.luacheckrc index 614271a..58ffe0c 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -7,6 +7,7 @@ globals = { } read_globals = { + "futil", "stamina", "skyblock", "ItemStack", diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..71bce29 --- /dev/null +++ b/.pre-commit-config.yaml @@ -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 ]