432 lines
17 KiB
Lua
432 lines
17 KiB
Lua
-- who is allowed to edit and create new reward inventories?
|
|
-- works with player object and player name
|
|
reward_inv.may_edit = function(pname)
|
|
return minetest.check_player_privs(pname, {give=true})
|
|
end
|
|
|
|
|
|
reward_inv.show_error_msg_fs = function(pname, error_msg)
|
|
local formspec = {"size[10,3]"..
|
|
"label[0.2,0.5;Error:]"..
|
|
"label[0.5,1.0;"}
|
|
table.insert(formspec, minetest.colorize("#FFFF00",
|
|
minetest.formspec_escape(
|
|
minetest.wrap_text(tostring(error_msg), 80))))
|
|
table.insert(formspec, "]")
|
|
table.insert(formspec, "button[3.5,2.0;2,0.9;back_from_error_msg;Back]")
|
|
minetest.show_formspec(pname, "reward_inv:main", table.concat(formspec, ""))
|
|
return true
|
|
end
|
|
|
|
|
|
reward_inv.input_handler = function(player, formname, fields)
|
|
if(not(formname) or formname ~= "reward_inv:main") then
|
|
return false
|
|
end
|
|
local pname = player:get_player_name()
|
|
|
|
local reward_data = {}
|
|
if(reward_inv.player_using[pname]) then
|
|
reward_data = reward_inv.get_reward_data(reward_inv.player_using[pname])
|
|
end
|
|
-- if in edit mode: give items that were added back
|
|
local liste = {}
|
|
if(reward_inv.player_is_editing[pname]) then
|
|
-- make sure we do have a content we can compare with
|
|
if(not(reward_data.content)) then
|
|
reward_data.content = {}
|
|
for i=1, 32 do
|
|
reward_data.content[i] = ""
|
|
end
|
|
end
|
|
local inv_name = reward_inv.reward_inv_get_name(pname)
|
|
-- has the inventory already been created? Then don't create it anew
|
|
local inv = minetest.get_inventory({type="detached", name=inv_name})
|
|
if(inv) then
|
|
-- returns a list of stacks
|
|
liste = inv:get_list("main")
|
|
end
|
|
-- the reason why we return items here is because something complex like
|
|
-- written books or other itemstacks with complex metadata shall not be lost
|
|
local player_inv = player:get_inventory()
|
|
for i, work_stack in pairs(liste) do
|
|
local prev_stack = ItemStack(reward_data.content[i] or "")
|
|
-- there is something or something diffrent in the detached inv now
|
|
if(not(work_stack:equals(prev_stack))) then
|
|
-- is there more in the stack than there used to be?
|
|
if( work_stack:get_name() == prev_stack:get_name()
|
|
and work_stack:get_count() > prev_stack:get_count()) then
|
|
local c = work_stack:get_count() - prev_stack:get_count()
|
|
work_stack:set_count(c)
|
|
-- return the leftover parts
|
|
player_inv:add_item("main", work_stack)
|
|
else
|
|
-- diffrent stack (even if only in metadata) - so return all
|
|
player_inv:add_item("main", work_stack)
|
|
end
|
|
end
|
|
liste[i] = liste[i]:to_table()
|
|
end
|
|
end
|
|
|
|
if(fields.show_reward_list) then
|
|
reward_inv.show_reward_list_fs(player, reward_inv.player_using[pname])
|
|
return true
|
|
end
|
|
-- any input here is only accepted if the player is allwed to edit this
|
|
if(not(player) or not(fields) or not(reward_inv.may_edit(player))) then
|
|
return false
|
|
end
|
|
if(fields.exit or fields.quit) then
|
|
return true
|
|
end
|
|
if(fields.back_from_error_msg) then
|
|
reward_inv.show_reward_fs(player, reward_inv.player_using[pname])
|
|
return true
|
|
end
|
|
local reward_id = ""
|
|
if(fields.select_reward_id and fields.set_reward_id) then
|
|
reward_id = fields.select_reward_id
|
|
if(not(reward_id) or reward_id == "") then
|
|
return reward_inv.show_error_msg_fs(pname, "Please select a name for the new "..
|
|
"reward ID or enter a new name!")
|
|
end
|
|
elseif(fields.new_reward_id and fields.create_reward_id) then
|
|
reward_id = fields.new_reward_id
|
|
if(string.len(reward_id) < 2 or string.len(reward_id) > 120) then
|
|
return reward_inv.show_error_msg_fs(pname, "The reward ID needs to be between "..
|
|
"2 and 120 characters long.")
|
|
end
|
|
else
|
|
reward_id = reward_inv.player_using[pname]
|
|
end
|
|
if(not(reward_id) or reward_id == "") then
|
|
return reward_inv.show_error_msg_fs(pname, "No reward_id selected.")
|
|
end
|
|
|
|
-- if it's a chest make sure reward_id is stored in its metadata
|
|
if(reward_inv.clicked_at_chest[pname]) then
|
|
local meta = minetest.get_meta(reward_inv.clicked_at_chest[pname])
|
|
meta:set_string("reward_id", reward_id)
|
|
-- update infotext as well
|
|
meta:set_string("infotext", "Treasure chest")
|
|
end
|
|
|
|
-- the player is working on this reward and editing it (until the Store button is clicked)
|
|
reward_inv.player_using[pname] = reward_id
|
|
reward_inv.player_is_editing[pname] = true
|
|
|
|
if(fields.save) then
|
|
-- save the new reward inventory
|
|
reward_data.content = liste
|
|
-- set values for which we got input
|
|
if(fields.input_text_hint) then
|
|
reward_data.hint = fields.input_text_hint
|
|
end
|
|
if(fields.input_text_when_found) then
|
|
reward_data.text_when_found = fields.input_text_when_found
|
|
end
|
|
if(fields.input_refill_after_t_seconds and fields.input_refill_after_t_seconds ~= "") then
|
|
reward_data.refill_after_t_seconds = tonumber(fields.input_refill_after_t_seconds)
|
|
end
|
|
if(reward_inv.clicked_at_chest[pname]) then
|
|
reward_data.pos = reward_inv.clicked_at_chest[pname]
|
|
elseif(minetest.global_exists("yl_speak_up")) then
|
|
reward_data.npc = yl_speak_up.speak_to[pname].n_id
|
|
end
|
|
-- actually save it
|
|
reward_inv.set_inv_data(reward_id, reward_data)
|
|
-- leave edit mode
|
|
reward_inv.player_is_editing[pname] = nil
|
|
end
|
|
reward_inv.show_reward_fs(player, reward_inv.player_using[pname])
|
|
return true
|
|
end
|
|
|
|
|
|
-- show the initial formspec for assinging a reward_id
|
|
reward_inv.get_fs_set_reward_id = function(player)
|
|
local pname = player:get_player_name()
|
|
local suggested_id = ""
|
|
-- is this for a chest?
|
|
if(reward_inv.clicked_at_chest[pname]) then
|
|
suggested_id = minetest.pos_to_string(reward_inv.clicked_at_chest[pname])
|
|
-- or for an NPC?
|
|
elseif(minetest.global_exists("yl_speak_up")
|
|
and yl_speak_up.speak_to[pname]) then
|
|
suggested_id = yl_speak_up.speak_to[pname]
|
|
end
|
|
local liste = reward_inv.get_sorted_reward_id_list()
|
|
local formspec = {}
|
|
table.insert(formspec, "size[8,4.5]")
|
|
table.insert(formspec, "label[0,0;Not yet configured. No reward_id set. "..
|
|
"You have the priv to set one.]")
|
|
table.insert(formspec, "label[0,1;Select existing:]")
|
|
table.insert(formspec, "dropdown[2.2,0.9;4.8,1;select_reward_id;")
|
|
table.insert(formspec, table.concat(liste, ","))
|
|
table.insert(formspec, ";1;false]")
|
|
table.insert(formspec, "button[6.8,0.8;1.2,1;set_reward_id;Set]")
|
|
table.insert(formspec, "label[0,2;..or create new:]")
|
|
table.insert(formspec, "field[2.5,2.1;4.7,1;new_reward_id;;")
|
|
table.insert(formspec, minetest.formspec_escape(suggested_id))
|
|
table.insert(formspec, "]")
|
|
table.insert(formspec, "button[6.8,1.8;1.2,1;create_reward_id;Create]")
|
|
table.insert(formspec, "tooltip[new_reward_id;"..
|
|
"The reward_id you store here is needed in order to reference the reward.\n"..
|
|
"If you are adding a treasure chest, just go with the suggested name/pos.\n"..
|
|
"When adding a treasure for an NPC, add some description that will help\n"..
|
|
"you remember what this reward is for.]")
|
|
table.insert(formspec, "tooltip[create_reward_id;Click here to proceed.]")
|
|
table.insert(formspec, "tooltip[select_reward_id;"..
|
|
"You can select an existing reward_id.\n"..
|
|
"Note that this is seldom necessary. It is usually only needed when you\n"..
|
|
"moved a treasure chest a few blocks away and want to keep the data.\n"..
|
|
"Or when you changed the dialog structure of the NPC that hands out the\n"..
|
|
"reward.]")
|
|
table.insert(formspec, "tooltip[set_reward_id;"..
|
|
"Click here to store the selected reward_id. This is seldom needed.\n"..
|
|
"Usually, creating a new one is the better choice.]")
|
|
table.insert(formspec, "label[0,2.6;Note: Select a name which will help you remember "..
|
|
"what this]")
|
|
table.insert(formspec, "label[0,3.0;reward is for and/or where it will be handed out.]")
|
|
table.insert(formspec, "label[0,3.4;In general, just click on \"Create\" to proceed.]")
|
|
table.insert(formspec, "button_exit[3,3.9;2,1;exit;Exit]")
|
|
return table.concat(formspec, "")
|
|
end
|
|
|
|
|
|
-- create a formspec with the updated reward inventory for the player
|
|
reward_inv.get_reward_fs = function(player, reward_id)
|
|
if(not(player)) then
|
|
return ""
|
|
end
|
|
local pname = player:get_player_name()
|
|
reward_inv.player_using[pname] = reward_id
|
|
-- make the detached inventory contain those items that according to
|
|
-- our stored data are still available to the player
|
|
local inv = reward_inv.update_reward_inv(player, reward_id)
|
|
if(not(inv)) then
|
|
-- nothing to show
|
|
return "size[10,2]"..
|
|
"label[0,0;Internal error: Failed to create detached inventory.]"..
|
|
"button[4,1;2,1;close;Close]"
|
|
end
|
|
-- is the player editing this?
|
|
local edit_mode = reward_inv.player_is_editing[pname]
|
|
-- we use the "give" priv as that seems most fitting
|
|
local has_edit_priv = reward_inv.may_edit(pname, {give=true})
|
|
-- do we need to assign a reward_id here first?
|
|
if(not(reward_id) or reward_id == "") then
|
|
if(not(has_edit_priv)) then
|
|
return "size[6,1]"..
|
|
"label[0,0;No reward assigned. Please come back later!]"..
|
|
"button_exit[2,0.5;2,1;exit;Exit]"
|
|
end
|
|
return reward_inv.get_fs_set_reward_id(player)
|
|
end
|
|
|
|
-- get general information about the reward as such
|
|
local reward_data = reward_inv.get_reward_data(reward_id)
|
|
if(not(reward_data)) then
|
|
if(not(has_edit_priv)) then
|
|
return "size[6,1]"..
|
|
"label[0,0;Not yet filled. Please come back later!]"..
|
|
"button_exit[2,0.5;2,1;exit;Exit]"
|
|
end
|
|
-- no data yet - force entering edit mode so that we get data
|
|
reward_inv.player_is_editing[pname] = true
|
|
edit_mode = true
|
|
reward_data = {}
|
|
end
|
|
|
|
-- for showing the player when and how much he/she took
|
|
local access_data = reward_inv.get_access_data(pname, reward_id) or {0, 0, {}, 0}
|
|
|
|
-- create the formspec
|
|
local formspec = {"size[12,11]"}
|
|
|
|
local text = "Congratulations! You've "
|
|
local error_msg = ""
|
|
if(edit_mode) then
|
|
text = "You are in edit mode and editing this reward with ID \""..
|
|
minetest.formspec_escape(reward_id).."\""
|
|
elseif(not(reward_data)) then
|
|
text = text.."found something not yet ready to use"
|
|
-- TODO: add assign reward_id button?
|
|
elseif(reward_data.pos) then
|
|
text = text.."found this treasure chest at "..
|
|
minetest.formspec_escape(minetest.pos_to_string(reward_data.pos))
|
|
elseif(reward_data.npc_name) then
|
|
text = text.."been awarded this reward by "..
|
|
table.insert(formspec, minetest.formspec_escape(reward_data.npc_name))
|
|
else
|
|
text = text.."found this treasure"
|
|
end
|
|
table.insert(formspec, "label[1,-0.3;")
|
|
table.insert(formspec, text)
|
|
table.insert(formspec, ":]")
|
|
|
|
-- provide information about how to identify this reward
|
|
local text_hint = reward_data.hint
|
|
local text_when_found = reward_data.text_when_found
|
|
if(text_hint and (not(text_when_found) or text_when_found=="")) then
|
|
text_when_found = text_hint
|
|
end
|
|
table.insert(formspec, "container[0.2,0.2]")
|
|
table.insert(formspec, "label[0,0;The hint that was supposed to lead you here was:]")
|
|
table.insert(formspec, "label[0,1;Now this will be listed like this when you type \"/rewards\":]")
|
|
text_hint = minetest.formspec_escape(text_hint or "")
|
|
text_when_found = minetest.formspec_escape(text_when_found or "")
|
|
if(edit_mode) then
|
|
table.insert(formspec, "field[0.5,0.6;7.6,1.0;input_text_hint;;")
|
|
table.insert(formspec, text_hint)
|
|
table.insert(formspec, "]")
|
|
table.insert(formspec, "field[0.5,1.6;7.6,1.0;input_text_when_found;;")
|
|
table.insert(formspec, text_when_found)
|
|
table.insert(formspec, "]")
|
|
table.insert(formspec, "label[8.0,0;Refill reward after t seconds:]")
|
|
table.insert(formspec, "field[8.5,0.6;3.7,1.0;input_refill_after_t_seconds;;")
|
|
table.insert(formspec, minetest.formspec_escape(reward_data.refill_after_t_seconds or 0))
|
|
table.insert(formspec, "]")
|
|
table.insert(formspec, "tooltip[input_text_hint;"..
|
|
"This hint will be shown to players who have not found or not\n"..
|
|
"been awarded this reward yet. The hint ought to help players\n"..
|
|
"locate the general area where to search, i.e.\n"..
|
|
"\tTavern \"The Lion's Inn\" in Capital City "..
|
|
minetest.formspec_escape("[Area ID 1234]")..
|
|
"\nor something like:\n"..
|
|
"\tTalk to shopkeeper in the village Lone Valley\n"..
|
|
"If no text is set, then this reward will not show up in /rewards.]")
|
|
table.insert(formspec, "tooltip[input_text_when_found;"..
|
|
"This text will be shown to players who have found or been\n"..
|
|
"awarded this reward.\n"..
|
|
"If nothing is set here, the hint text will be shown.]")
|
|
table.insert(formspec, "tooltip[input_refill_after_t_secons;"..
|
|
"If this value is higher than 0, players can claim this reward\n"..
|
|
"again if more than this many seconds have passed since they\n"..
|
|
"last took something from this reward.\n"..
|
|
"Hour: 3600 s, day: 86400 s, week: 604800 s, month: 18144000 s\n"..
|
|
"Leave it at 0 in order to hand each reward out only once.]")
|
|
else
|
|
if(text_hint == "") then
|
|
text_hint = "- none -"
|
|
end
|
|
if(text_when_found == "") then
|
|
text_when_found = "- not listed -"
|
|
end
|
|
table.insert(formspec, "label[0.5,0.5;")
|
|
table.insert(formspec, minetest.colorize("#CCCCFF", text_hint))
|
|
table.insert(formspec, "]")
|
|
table.insert(formspec, "label[0.5,1.5;")
|
|
table.insert(formspec, minetest.colorize("#00FF00", text_when_found))
|
|
table.insert(formspec, "]")
|
|
end
|
|
if(reward_data
|
|
and reward_data.refill_after_t_seconds
|
|
and reward_data.refill_after_t_seconds > 0) then
|
|
table.insert(formspec, "label[8.0,6;This treasure refills sometimes.]")
|
|
table.insert(formspec, "label[8.0,6.3;")
|
|
table.insert(formspec, minetest.colorize("#FFFF00", "Might be worth comming back!"))
|
|
table.insert(formspec, "]")
|
|
else
|
|
table.insert(formspec, "label[8.0,6;But beware: There is no refill.]")
|
|
table.insert(formspec, "label[8.0,6.3;You will get this only once.]")
|
|
end
|
|
table.insert(formspec, "container_end[]")
|
|
|
|
-- show some simple access data to all
|
|
table.insert(formspec, "container[8.2,2]")
|
|
table.insert(formspec, "box[-0.2,0.3;3.9,2.9;#000000]")
|
|
table.insert(formspec, "label[1,0.5;Statistic:]")
|
|
table.insert(formspec, "label[0,2.5;Found by:]")
|
|
table.insert(formspec, "label[2,2.5;")
|
|
table.insert(formspec, tostring(reward_data.anz_found or 0))
|
|
table.insert(formspec, " people]")
|
|
table.insert(formspec, "label[0,1.0;First found:]")
|
|
table.insert(formspec, "label[0,1.5;Last found:]")
|
|
table.insert(formspec, "label[0,2.0;Last taken:]")
|
|
-- player-specific information
|
|
table.insert(formspec, "box[-0.2,4.9;3.9,2.1;#000000]")
|
|
table.insert(formspec, "label[1,5.0;Your data:]")
|
|
table.insert(formspec, "label[0,5.5;First found:]")
|
|
table.insert(formspec, "label[0,6.0;Last taken:]")
|
|
table.insert(formspec, "label[0,6.5;Items taken:]")
|
|
local offset = 0.5
|
|
local dates = {reward_data.first_found or 0,
|
|
reward_data.last_found or 0,
|
|
reward_data.last_taken or 0,
|
|
access_data[1] or 0,
|
|
access_data[4] or 0}
|
|
for i, date in ipairs(dates) do
|
|
local txt = "- never -"
|
|
if(date and date > 0) then
|
|
txt = os.date("%m/%d/%y %H:%M", date)
|
|
end
|
|
table.insert(formspec, "label[1.6,")
|
|
table.insert(formspec, tostring(offset + (0.5 * i)))
|
|
table.insert(formspec, ";")
|
|
table.insert(formspec, minetest.formspec_escape(txt))
|
|
table.insert(formspec, "]")
|
|
-- for the "Your data:" part
|
|
if(i==3) then
|
|
offset = 3.5
|
|
end
|
|
end
|
|
local anz_taken = 0
|
|
for k, v in pairs(access_data[3] or {}) do
|
|
anz_taken = anz_taken + v
|
|
end
|
|
table.insert(formspec, "label[2,6.5;")
|
|
table.insert(formspec, tostring(anz_taken))
|
|
table.insert(formspec, "]")
|
|
|
|
table.insert(formspec, "button_exit[-0.2,-0.5;4.1,1;show_reward_list;Show reward list]")
|
|
table.insert(formspec, "button_exit[-0.2,8.2;4.1,1;exit;Close]")
|
|
if(edit_mode) then
|
|
table.insert(formspec, "button[-0.2,3.4;4.1,1;save;Save changes]")
|
|
else
|
|
table.insert(formspec, "button[-0.2,3.4;4.1,1;start_edit;Edit]")
|
|
end
|
|
table.insert(formspec, "container_end[]")
|
|
|
|
-- add a short text in the space between the two inventories
|
|
if(edit_mode) then
|
|
table.insert(formspec, "label[0.5,6.15;Fill this inventory with what you want the "..
|
|
"reward to be.]")
|
|
table.insert(formspec, "label[0.5,6.45;Each player may then take out one copy of it.]")
|
|
else
|
|
table.insert(formspec, "label[0.5,6.15;Don't worry if you can't carry it all.]")
|
|
table.insert(formspec, "label[0.5,6.45;You can come back any time later and claim the rest.]")
|
|
end
|
|
|
|
local reward_inv_name = reward_inv.reward_inv_get_name(pname)
|
|
table.insert(formspec, "container[0,2]")
|
|
-- table.insert(formspec, "background[0,0;8,9;default_gold_block.png;true]")
|
|
-- table.insert(formspec, "background[0,0;8,9;default_chest_top.png;true]")
|
|
|
|
table.insert(formspec, "list[current_player;main;0,4.95;8,1;]")
|
|
table.insert(formspec, "list[current_player;main;0,6.08;8,3;8]")
|
|
table.insert(formspec, "list[detached:")
|
|
table.insert(formspec, reward_inv_name)
|
|
table.insert(formspec, ";main;0,0.3;8,4;]")
|
|
table.insert(formspec, "listring[detached:")
|
|
table.insert(formspec, reward_inv_name)
|
|
table.insert(formspec, ";main]")
|
|
table.insert(formspec, "listring[current_player;main]")
|
|
table.insert(formspec, "container_end[]")
|
|
return table.concat(formspec, "")
|
|
end
|
|
|
|
|
|
-- show a formspec with the updated reward inventory to the player
|
|
reward_inv.show_reward_fs = function(player, reward_id)
|
|
if(not(player)) then
|
|
return
|
|
end
|
|
local pname = player:get_player_name()
|
|
-- create the formspec
|
|
local formspec = reward_inv.get_reward_fs(player, reward_id)
|
|
-- actually show the reward formspec to the player
|
|
minetest.show_formspec(pname, "reward_inv:main", formspec)
|
|
end
|