added inventory to npc which is stored to disk

This commit is contained in:
Sokomine 2021-05-17 00:15:59 +02:00
parent 5fe7991599
commit 0efa7f4f63
4 changed files with 169 additions and 1 deletions

View File

@ -6,6 +6,9 @@ yl_speak_up.talk_after_spawn = true
yl_speak_up.path = "yl_speak_up_dialogs"
-- What shall we call the folder all the inventories of the NPC will reside in?
yl_speak_up.inventory_path = "yl_speak_up_inventories"
-- Texts
yl_speak_up.message_button_option_exit = "Farewell!"

View File

@ -1457,6 +1457,14 @@ local function get_fs_talkdialog(player, n_id, d_id)
"a conversation is started.]")
end
-- access the inventory of the NPC
h = h + 1
table.insert(formspec, "button[0.5," .. h .. ";53.8,0.9;show_inventory;]")
table.insert(formspec, "tooltip[show_inventory;Access and manage the inventory of the NPC. "..
"This is used for adding trade items, getting collected payments and managing "..
"quest items.]")
table.insert(formspec, "label[0.7,"..(h+0.45)..";I am your owner. Show me your inventory!]")
-- chat option: Mute/Unmute NPC
h = h + 1
local obj = yl_speak_up.speak_to[pname].obj
@ -1717,10 +1725,26 @@ minetest.register_on_player_receive_fields( function(player, formname, fields)
elseif formname == "yl_speak_up:fashion" then
yl_speak_up.input_fashion(player, formname, fields)
return true
elseif formname == "yl_speak_up:inventory" then
yl_speak_up.input_inventory(player, formname, fields)
return true
end
end)
-- the player has closed the inventory formspec of the NPC - save it
yl_speak_up.input_inventory = function(player, formname, fields)
local pname = player:get_player_name()
local d_id = yl_speak_up.speak_to[pname].d_id
local n_id = yl_speak_up.speak_to[pname].n_id
-- after closing the inventory formspec:
-- ..save the (very probably) modified inventory
yl_speak_up.save_npc_inventory(n_id)
-- ..and go back to the normal talk formspec
minetest.show_formspec(pname, "yl_speak_up:talk", get_fs_talkdialog(player, n_id, d_id))
end
yl_speak_up.input_optiondialog = function(player, formname, fields)
if formname ~= "yl_speak_up:optiondialog" then
return
@ -2742,6 +2766,14 @@ yl_speak_up.input_talk = function(player, formname, fields)
return
end
-- the player wants to access the inventory of the NPC
if(edit_mode and fields.show_inventory) then
local dialog = yl_speak_up.speak_to[pname].dialog
-- the inventory is just an inventory with a back button; come back to this dialog here
minetest.show_formspec(pname, "yl_speak_up:inventory", yl_speak_up.get_fs_inventory(player, n_id, dialog.n_npc))
return
end
-- change skin, cape and wielded items
if(edit_mode and fields.edit_skin) then
local dialog = yl_speak_up.speak_to[pname].dialog
@ -3147,6 +3179,9 @@ function yl_speak_up.after_activate(self, staticdata, def, dtime)
end
yl_speak_up.update_nametag(self)
-- create a detached inventory for the npc and load its inventory
yl_speak_up.load_npc_inventory("n_"..tostring(self.yl_speak_up.id))
end
function yl_speak_up.talk(self, clicker)

View File

@ -17,12 +17,16 @@ yl_speak_up.speak_to = {}
dofile(modpath .. "config.lua")
dofile(modpath .. "privs.lua")
-- inventory management, trading and handling of quest items:
dofile(modpath .. "inventory.lua")
dofile(modpath .. "functions.lua")
dofile(modpath .. "tools.lua")
dofile(modpath .. "mobs.lua")
--dofile(modpath .. "debug.lua")
minetest.mkdir(yl_speak_up.worldpath..yl_speak_up.path)
minetest.mkdir(yl_speak_up.worldpath..yl_speak_up.inventory_path)
yl_speak_up.mob_table = yl_speak_up.init_mob_table() or {}
minetest.log("action","[MOD] yl_speak_up loaded")
minetest.log("action","[MOD] yl_speak_up loaded")

126
inventory.lua Normal file
View File

@ -0,0 +1,126 @@
-- inventory management, trading and handling of quest items for talking to NPCs
-- cache the inventory of NPCs for easier access
yl_speak_up.npc_inventory = {}
-- where are they stored on the disk?
yl_speak_up.get_inventory_save_path = function(n_id)
return yl_speak_up.worldpath .. yl_speak_up.inventory_path .. DIR_DELIM .. "inv_" .. n_id .. ".json"
end
-- access the inventory of the NPC (only possible for players with the right priv)
yl_speak_up.get_fs_inventory = function(player, n_id, npc_name)
return "size[12,11]" ..
"label[2,-0.2;Inventory of "..minetest.formspec_escape(npc_name)..
" (ID: "..tostring(n_id).."):]"..
"list[detached:yl_npc_"..tostring(n_id)..";npc_main;0,0.3;12,6;]" ..
"list[current_player;main;2,6.85;8,1;]" ..
"list[current_player;main;2,8.08;8,3;8]" ..
"listring[detached:yl_npc_"..tostring(n_id)..";npc_main]" ..
"listring[current_player;main]" ..
"button[10.0,10.2;2,0.9;back_from_inventory;Back]"
end
-- save the inventory of the NPC with the id n_id
yl_speak_up.save_npc_inventory = function( n_id )
-- only save something if we actually can
if(not(n_id) or not(yl_speak_up.npc_inventory[ n_id ])) then
return
end
-- convert the inventory data to something we can actually store
local inv = yl_speak_up.npc_inventory[ n_id ]
local inv_as_table = {}
for i=1, inv:get_size("npc_main") do
local stack = inv:get_stack("npc_main", i)
-- only save those slots that are not empty
if(not(stack:is_empty())) then
inv_as_table[ i ] = stack:to_table()
end
end
-- convert the table into json
local json = minetest.write_json( inv_as_table )
-- get a file name for storing the data
local file_name = yl_speak_up.get_inventory_save_path(n_id)
-- actually store it on disk
minetest.safe_file_write(file_name, json)
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
yl_speak_up.load_npc_inventory = function(n_id)
if(not(n_id)) then
return
end
-- the inventory is already loaded
if( yl_speak_up.npc_inventory[ n_id ]) then
return
end
-- create the detached inventory (it is empty for now)
local npc_inv = minetest.create_detached_inventory("yl_npc_"..tostring(n_id), {
allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
if(not(yl_speak_up.may_edit_npc(player, n_id))) then
return 0
end
return count
end,
-- Called when a player wants to move items inside the inventory.
-- Return value: number of items allowed to move.
allow_put = function(inv, listname, index, stack, player)
if(not(yl_speak_up.may_edit_npc(player, n_id))) then
return 0
end
return stack:get_count()
end,
-- Called when a player wants to put something into the inventory.
-- Return value: number of items allowed to put.
-- Return value -1: Allow and don't modify item count in inventory.
allow_take = function(inv, listname, index, stack, player)
if(not(yl_speak_up.may_edit_npc(player, n_id))) then
return 0
end
return stack:get_count()
end
-- Called when a player wants to take something out of the inventory.
-- Return value: number of items allowed to take.
-- Return value -1: Allow and don't modify item count in inventory.
-- on_move = function(inv, from_list, from_index, to_list, to_index, count, player) end,
-- on_put = function(inv, listname, index, stack, player) end,
-- on_take = function(inv, listname, index, stack, player) end,
-- Called after the actual action has happened, according to what was
-- allowed.
-- No return value.
})
-- the NPC needs enough room for trade items, payment and questitems
npc_inv:set_size("npc_main", 6*12)
-- cache a pointer to this inventory for easier access
yl_speak_up.npc_inventory[ n_id ] = npc_inv
-- find out where the inventory of the NPC is stored
local file_name = yl_speak_up.get_inventory_save_path(n_id)
-- load the data from the file
local file, err = io.open(file_name, "r")
if err then
return
end
io.input(file)
local text = io.read()
local inv_as_table = minetest.parse_json(text)
io.close(file)
if(type(inv_as_table) ~= "table") then
return
end
-- restore the inventory
for i=1, npc_inv:get_size("npc_main") do
npc_inv:set_stack("npc_main", i, ItemStack( inv_as_table[ i ]))
end
end