From d58789e7038c991ff601b44de8328fb9252a4ea2 Mon Sep 17 00:00:00 2001 From: Sokomine Date: Thu, 15 Feb 2024 22:19:08 +0100 Subject: [PATCH] only load detached npc inventories when they are really needed - either by the npc dialog or in edit_mode --- api/api_inventory.lua | 55 ++++++++++++++++++++++++++- editor/fs/fs_talkdialog_edit_mode.lua | 2 + fs/fs_inventory.lua | 3 ++ functions.lua | 8 ++-- 4 files changed, 62 insertions(+), 6 deletions(-) diff --git a/api/api_inventory.lua b/api/api_inventory.lua index 7dd0a8a..b0e5a55 100644 --- a/api/api_inventory.lua +++ b/api/api_inventory.lua @@ -98,10 +98,54 @@ yl_speak_up.inventory_allow_item = function(player, stack, input_to) end +-- checks dialog and tries to find out if this dialog needs a detached inventory for the NPC; +-- returns true if the NPC needs one; else false +yl_speak_up.dialog_requires_inventory = function(dialog) + if(not(dialog)) then + return false + end + for t, t_data in pairs(dialog.trades or {}) do + if(t and t ~= "limits") then + return true + end + end + for d_id, d_data in pairs(dialog.n_dialogs or {}) do + for o_id, o_data in pairs(d_data.d_options or {}) do + -- check preconditions: + for p_id, p_data in pairs(o_data.o_prerequisites or {}) do + local t = p_data.p_type or "?" + if(t == "trade" or t == "npc_inv" or t == "player_offered_item") then + return true + end + end + -- check actions: + for a_id, a_data in pairs(o_data.actions or {}) do + local t = a_data.a_type or "?" + if(t == "trade" or t == "npc_gives" or t == "npc_wants") then + return true + end + end + -- check effects: + for r_id, r_data in pairs(o_data.o_results or {}) do + local t = r_data.r_type or "?" + if(t == "block" or t == "craft" or t == "put_into_block_inv" + or t == "take_from_block_inv" or t == "deal_with_offered_item") then + return true + end + end + end + end + -- nothing found that actually uses the NPC's inventory - so don't load it + return false +end + + -- create and load the detached inventory in yl_speak_up.after_activate; -- direct access to this inventory is only possible for players with the right privs -- (this is an inventory for the *NPC*, which is stored to disk sometimes) -yl_speak_up.load_npc_inventory = function(n_id) +-- if force_load is true, the inventory will be loaded even if the NPC doesn't usually +-- need one (i.e. in edit_mode, or with "show me your inventory"). +yl_speak_up.load_npc_inventory = function(n_id, force_load, dialog) if(not(n_id)) then return end @@ -125,9 +169,16 @@ yl_speak_up.load_npc_inventory = function(n_id) yl_speak_up.npc_inventory_last_used[ n_id ] = os.time() -- the inventory is already loaded - if( yl_speak_up.npc_inventory[ n_id ]) then + if(yl_speak_up.npc_inventory[ n_id ]) then return end + + -- check if the NPC actually needs an inventory - else don't load it + if(not(force_load) and dialog + and not(yl_speak_up.dialog_requires_inventory(dialog))) then + return + end + -- create the detached inventory (it is empty for now) local npc_inv = minetest.create_detached_inventory("yl_speak_up_npc_"..tostring(n_id), { allow_move = function(inv, from_list, from_index, to_list, to_index, count, player) diff --git a/editor/fs/fs_talkdialog_edit_mode.lua b/editor/fs/fs_talkdialog_edit_mode.lua index 577e818..9738340 100644 --- a/editor/fs/fs_talkdialog_edit_mode.lua +++ b/editor/fs/fs_talkdialog_edit_mode.lua @@ -49,6 +49,8 @@ yl_speak_up.input_talk = function(player, formname, fields) -- result return end + -- make sure the inventory of the NPC is loaded + yl_speak_up.load_npc_inventory(n_id, true, nil) -- for older formspec versions: reset scroll counter yl_speak_up.speak_to[pname].counter = 1 yl_speak_up.speak_to[pname].option_index = 1 diff --git a/fs/fs_inventory.lua b/fs/fs_inventory.lua index 2dfdadb..621f978 100644 --- a/fs/fs_inventory.lua +++ b/fs/fs_inventory.lua @@ -45,6 +45,9 @@ yl_speak_up.get_fs_inventory = function(player) "button_exit[2,1.5;1,0.9;exit;Exit]" end + -- make sure the inventory of the NPC is loaded + yl_speak_up.load_npc_inventory(n_id, true, nil) + return table.concat({"size[12,11]", "label[2,-0.2;Inventory of ", minetest.formspec_escape(dialog.n_npc), diff --git a/functions.lua b/functions.lua index ec44389..cbe52ca 100644 --- a/functions.lua +++ b/functions.lua @@ -589,10 +589,6 @@ function yl_speak_up.talk(self, clicker) self = yl_speak_up.initialize_npc(self) end - -- TODO: load inventory only when the npc actually uses one? - -- create a detached inventory for the npc and load its inventory - yl_speak_up.load_npc_inventory(id_prefix.."_"..tostring(self.yl_speak_up.id)) - local npc_id = self.yl_speak_up.id local n_id = id_prefix.."_" .. npc_id @@ -646,6 +642,10 @@ function yl_speak_up.talk(self, clicker) dialog.trades = {} end + -- create a detached inventory for the npc and load its inventory + yl_speak_up.load_npc_inventory(id_prefix.."_"..tostring(self.yl_speak_up.id), false, dialog) + + -- some NPC may have reset the animation; at least set it to the desired -- value whenever we talk to the NPC if self.yl_speak_up and self.yl_speak_up.animation then