quest api variables are now properly saved and restored
This commit is contained in:
parent
522179cf28
commit
5cf3e412c5
@ -9,6 +9,13 @@ 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"
|
||||
|
||||
-- Where shall player-specific varialbes (usually quest states) be stored?
|
||||
yl_speak_up.player_vars_save_file = "yl_speak_up_player_vars"
|
||||
|
||||
-- amount of time in seconds that has to have passed before the above file will be saved again
|
||||
-- (more time can pass if no variable is changed)
|
||||
yl_speak_up.player_vars_min_save_time = 60
|
||||
|
||||
-- Texts
|
||||
|
||||
yl_speak_up.message_button_option_exit = "Farewell!"
|
||||
|
@ -122,7 +122,7 @@ end
|
||||
|
||||
-- returns a human-readable text as description of the effects
|
||||
-- (as shown in the edit options dialog and in the edit effect formspec)
|
||||
yl_speak_up.show_effect = function(r)
|
||||
yl_speak_up.show_effect = function(r, pname)
|
||||
if(not(r.r_type) or r.r_type == "") then
|
||||
return "(nothing): Nothing to do. No effect."
|
||||
elseif(r.r_type == "give_item") then
|
||||
@ -138,18 +138,22 @@ yl_speak_up.show_effect = function(r)
|
||||
elseif(r.r_type == "dialog") then
|
||||
return "Switch to dialog \""..tostring(r.r_value).."\"."
|
||||
elseif(r.r_type == "state") then
|
||||
local var_name = "VARIABLE[ - ? - ]"
|
||||
if(r.r_variable) then
|
||||
var_name = "VARIABLE[ "..tostring(
|
||||
yl_speak_up.strip_pname_from_var(r.r_variable, pname)).." ]"
|
||||
end
|
||||
if(not(r.r_operator)) then
|
||||
return "Error: Operator not defined."
|
||||
elseif(r.r_operator == "set_to") then
|
||||
return "set VARIABLE[ "..tostring(r.r_variable).." ] to value \""..
|
||||
return "set "..var_name.." to value \""..
|
||||
tostring(r.r_var_cmp_value).."\""
|
||||
elseif(r.r_operator == "unset") then
|
||||
return "discard VARIABLE[ "..tostring(r.r_variable).." ] (unset)"
|
||||
return "discard "..var_name.." (unset)"
|
||||
elseif(r.r_operator == "set_to_current_time") then
|
||||
return "set VARIABLE[ "..tostring(r.r_variable).." ] to the current time"
|
||||
return "set "..var_name.." to the current time"
|
||||
else
|
||||
return "ERROR: Wrong operator \""..tostring(r.r_operator).."\" for "..
|
||||
"VARIABLE[ "..tostring(r.r_variable).." ]"
|
||||
return "ERROR: Wrong operator \""..tostring(r.r_operator).."\" for "..var_name
|
||||
end
|
||||
elseif(r.r_type == "block") then
|
||||
if(not(r.r_pos) or type(r.r_pos) ~= "table"
|
||||
@ -251,7 +255,7 @@ yl_speak_up.execute_all_relevant_effects = function(player, effects, o_id, actio
|
||||
for i, k in ipairs(sorted_key_list) do
|
||||
local r = effects[ k ]
|
||||
yl_speak_up.debug_msg(player, n_id, o_id, "..executing "..
|
||||
tostring(r.r_id)..": "..yl_speak_up.show_effect(r))
|
||||
tostring(r.r_id)..": "..yl_speak_up.show_effect(r, pname))
|
||||
-- do not execute effects in edit mode
|
||||
if(not(edit_mode)) then
|
||||
yl_speak_up.debug_msg(player, n_id, o_id,
|
||||
|
@ -242,7 +242,7 @@ yl_speak_up.save_element_p_or_a_or_e = function(
|
||||
v[ id_prefix.."value" ] = "expression"
|
||||
v[ id_prefix.."operator" ] = values_operator[ data.operator ]
|
||||
v[ id_prefix.."var_cmp_value" ] = (data.var_cmp_value or "")
|
||||
v[ id_prefix.."variable" ] = data.variable_name
|
||||
v[ id_prefix.."variable" ] = yl_speak_up.add_pname_to_var(data.variable_name, pname)
|
||||
|
||||
-- "a block somewhere", -- 3
|
||||
elseif(data.what == 3 and id_prefix ~= "a_") then
|
||||
@ -899,6 +899,7 @@ yl_speak_up.input_fs_edit_option_related = function(player, formname, fields,
|
||||
-- get the list of available variables (with the same elements
|
||||
-- and the same sort order as when the dropdown was displayed)
|
||||
local var_list = get_sorted_player_var_list_function(pname)
|
||||
yl_speak_up.strip_pname_from_varlist(var_list, pname)
|
||||
local nr = table.indexof(var_list, fields.select_variable)
|
||||
if(nr) then
|
||||
yl_speak_up.speak_to[pname][ tmp_data_cache ].variable = nr
|
||||
@ -1125,7 +1126,7 @@ yl_speak_up.get_fs_edit_option_related = function(player, table_click_result,
|
||||
minetest.formspec_escape(elements[ x_id ][ id_prefix.."type"])..
|
||||
","..
|
||||
minetest.formspec_escape(
|
||||
show_element_function(elements[ x_id ]))..";0]"..
|
||||
show_element_function(elements[ x_id ], pname))..";0]"..
|
||||
"button[2.0,1.8;1.5,0.9;delete_element;Delete]"..
|
||||
"button[4.0,1.8;1.5,0.9;change_element;Change]"..
|
||||
"button[6.0,1.8;5.5,0.9;back;Back to edit dialog option \""..
|
||||
@ -1327,11 +1328,12 @@ yl_speak_up.get_fs_edit_option_p_and_e_state = function(
|
||||
if(e) then
|
||||
data.operator = math.max(1,table.indexof(values_operator, e[ id_prefix.."operator" ]))
|
||||
data.var_cmp_value = e[ id_prefix.."var_cmp_value" ]
|
||||
data.variable_name = e[ id_prefix.."variable" ]
|
||||
data.variable = math.max(1, table.indexof(var_list, e[ id_prefix.."variable"])+1)
|
||||
data.variable_name = yl_speak_up.strip_pname_from_var(e[ id_prefix.."variable" ], pname)
|
||||
data.variable = table.indexof(var_list, e[ id_prefix.."variable"])
|
||||
end
|
||||
local var_list_stripped = yl_speak_up.strip_pname_from_varlist(var_list, pname)
|
||||
if(not(data.variable) or data.variable < 1) then
|
||||
data.variable = 1
|
||||
data.variable = 0
|
||||
-- not enough selected yet for saving
|
||||
save_button = ""
|
||||
elseif(not(data.operator) or data.operator == 1) then
|
||||
@ -1351,22 +1353,12 @@ yl_speak_up.get_fs_edit_option_p_and_e_state = function(
|
||||
-- the list of available variables needs to be extended with the ones
|
||||
-- the player has read access to, and the order has to be constant
|
||||
-- (because dropdown just returns an index)
|
||||
local var_list_text = "- please select -"
|
||||
for i, v in ipairs(var_list) do
|
||||
local parts = string.split(v, " ")
|
||||
local var_name = v
|
||||
if(parts and parts[1] and parts[1] == pname) then
|
||||
table.remove(parts, 1)
|
||||
var_name = table.concat(parts, " ")
|
||||
end
|
||||
var_list_text = var_list_text..","..minetest.formspec_escape(tostring(var_name))
|
||||
end
|
||||
return formspec..
|
||||
"label[0.2,3.3;"..text_variable.."]"..
|
||||
"label[0.2,4.3;Name of variable:]"..
|
||||
"dropdown[0.2,4.8;6.5,0.6;select_variable;"..
|
||||
var_list_text..";"..
|
||||
tostring(data.variable)..";]"..
|
||||
"- please select -"..var_list_stripped..";"..
|
||||
tostring(data.variable + 1)..";]"..
|
||||
"label[7.0,4.3;"..text_select_operator.."]"..
|
||||
"dropdown[7.0,4.8;4.0,0.6;select_operator;"..
|
||||
table.concat(check_operator, ",")..";"..
|
||||
|
@ -236,7 +236,7 @@ yl_speak_up.get_fs_edit_option_dialog = function(player, n_id, d_id, o_id, calle
|
||||
minetest.formspec_escape(v.p_id)..",#FFFF00,"..
|
||||
minetest.formspec_escape(v.p_type)..","..
|
||||
minetest.formspec_escape(
|
||||
yl_speak_up.show_precondition(v))..","
|
||||
yl_speak_up.show_precondition(v, pname))..","
|
||||
count_prereq = count_prereq + 1
|
||||
end
|
||||
end
|
||||
@ -299,7 +299,7 @@ yl_speak_up.get_fs_edit_option_dialog = function(player, n_id, d_id, o_id, calle
|
||||
minetest.formspec_escape(v.r_id)..",#999999,"..
|
||||
minetest.formspec_escape(v.r_type)..","..
|
||||
minetest.formspec_escape(
|
||||
yl_speak_up.show_effect(v))..","
|
||||
yl_speak_up.show_effect(v, pname))..","
|
||||
-- there may be more than one in the data structure
|
||||
target_dialog = v.r_value
|
||||
target_effect = v
|
||||
@ -308,7 +308,7 @@ yl_speak_up.get_fs_edit_option_dialog = function(player, n_id, d_id, o_id, calle
|
||||
minetest.formspec_escape(v.r_id)..",#FFFF00,"..
|
||||
minetest.formspec_escape(v.r_type)..","..
|
||||
minetest.formspec_escape(
|
||||
yl_speak_up.show_effect(v))..","
|
||||
yl_speak_up.show_effect(v, pname))..","
|
||||
end
|
||||
count_effects = count_effects + 1
|
||||
end
|
||||
|
@ -135,7 +135,7 @@ end
|
||||
|
||||
-- returns a human-readable text as description of the precondition
|
||||
-- (as shown in the edit options dialog and in the edit precondition formspec)
|
||||
yl_speak_up.show_precondition = function(p)
|
||||
yl_speak_up.show_precondition = function(p, pname)
|
||||
if(not(p.p_type) or p.p_type == "") then
|
||||
return "(nothing): Always true."
|
||||
elseif(p.p_type == "item") then
|
||||
@ -147,25 +147,30 @@ yl_speak_up.show_precondition = function(p)
|
||||
elseif(p.p_type == "function") then
|
||||
return "function: evaluate "..tostring(p.p_value)
|
||||
elseif(p.p_type == "state") then
|
||||
local var_name = "VALUE_OF[ - ? - ]"
|
||||
if(p.p_variable) then
|
||||
var_name = "VALUE_OF[ "..tostring(
|
||||
yl_speak_up.strip_pname_from_var(p.p_variable, pname)).." ]"
|
||||
end
|
||||
if(not(p.p_operator)) then
|
||||
return "Error: Operator not defined."
|
||||
elseif(p.p_operator == "not") then
|
||||
return "not( VALUE_OF[ "..tostring(p.p_variable).." ] )"
|
||||
return "not( "..var_name.." )"
|
||||
elseif(p.p_operator == "is_set") then
|
||||
return "VALUE_OF[ "..tostring(p.p_variable).." ] ~= nil (is_set)"
|
||||
return var_name.." ~= nil (is_set)"
|
||||
elseif(p.p_operator == "is_unset") then
|
||||
return "VALUE_OF[ "..tostring(p.p_variable).." ] == nil (is_unset)"
|
||||
return var_name.." == nil (is_unset)"
|
||||
elseif(p.p_operator == "more_than_x_seconds_ago") then
|
||||
return "VALUE_OF[ "..tostring(p.p_variable).." ] was set to current time "..
|
||||
return var_name.." was set to current time "..
|
||||
"*more* than "..tostring(p.p_var_cmp_value).." seconds ago"
|
||||
elseif(p.p_operator == "less_than_x_seconds_ago") then
|
||||
return "VALUE_OF[ "..tostring(p.p_variable).." ] was set to current time "..
|
||||
return var_name.." was set to current time "..
|
||||
"*less* than "..tostring(p.p_var_cmp_value).." seconds ago"
|
||||
end
|
||||
if(p.p_var_cmp_value == "") then
|
||||
return "VALUE_OF[ "..tostring(p.p_variable).." ] "..tostring(p.p_operator).." \"\""
|
||||
return var_name.." "..tostring(p.p_operator).." \"\""
|
||||
end
|
||||
return "VALUE_OF[ "..tostring(p.p_variable).." ] "..tostring(p.p_operator).." "..
|
||||
return var_name.." "..tostring(p.p_operator).." "..
|
||||
tostring(p.p_var_cmp_value)
|
||||
elseif(p.p_type == "block") then
|
||||
if(not(p.p_pos) or type(p.p_pos) ~= "table"
|
||||
@ -224,7 +229,7 @@ yl_speak_up.eval_all_preconditions = function(player, prereq, o_id)
|
||||
yl_speak_up.debug_msg(player, n_id, o_id, "Checking preconditions..")
|
||||
for k, p in pairs(prereq) do
|
||||
yl_speak_up.debug_msg(player, n_id, o_id, "..checking "..
|
||||
tostring(p.p_id)..": "..yl_speak_up.show_precondition(p))
|
||||
tostring(p.p_id)..": "..yl_speak_up.show_precondition(p, pname))
|
||||
if(not(yl_speak_up.eval_precondition(player, n_id, p))) then
|
||||
yl_speak_up.debug_msg(player, n_id, o_id, tostring(p.p_id)..
|
||||
" -> is false. Aborting.")
|
||||
|
100
quest_api.lua
100
quest_api.lua
@ -4,34 +4,79 @@
|
||||
-- TODO: handle read (and write?) access for other players
|
||||
-- TODO: add a function to check if the player has read/write access
|
||||
-- TODO: mark some vars as "need to be saved" while others are less important (i.e. timestamps)
|
||||
-- TODO: save state whenever a new variable is added - or else if the last change was more than x minutes ago?
|
||||
|
||||
-- the keys are of the form:
|
||||
-- <player name> <blank> <variable name> (makes it easier to grant read access)
|
||||
-- $ <blank> <player name> <blank> <variable name> (makes it easier to grant read access)
|
||||
-- the values are of the form:
|
||||
-- <current player name as key> : <value of variable for that player as value>
|
||||
yl_speak_up.player_vars = {}
|
||||
|
||||
-- store when player_vars was last saved to disc
|
||||
yl_speak_up.player_vars_last_save_time = 0
|
||||
|
||||
-- save the data to disc; either if force_save is set or enough time has passed
|
||||
yl_speak_up.save_quest_variables = function(force_save)
|
||||
if(not(force_save)
|
||||
and (yl_speak_up.player_vars_last_save_time + yl_speak_up.player_vars_min_save_time >
|
||||
math.floor(minetest.get_us_time()/1000000))) then
|
||||
return
|
||||
end
|
||||
local json = minetest.write_json( yl_speak_up.player_vars )
|
||||
-- actually store it on disk
|
||||
minetest.safe_file_write(yl_speak_up.worldpath..yl_speak_up.player_vars_save_file..".json", json)
|
||||
end
|
||||
|
||||
|
||||
-- load the data from disc
|
||||
yl_speak_up.load_quest_variables = function()
|
||||
-- load the data from the file
|
||||
local file, err = io.open(yl_speak_up.worldpath..yl_speak_up.player_vars_save_file..".json", "r")
|
||||
if err then
|
||||
return
|
||||
end
|
||||
io.input(file)
|
||||
local text = io.read()
|
||||
-- all values saved in the tables as such are strings
|
||||
local data = minetest.parse_json(text, -1)
|
||||
io.close(file)
|
||||
|
||||
if(type(data) ~= "table") then
|
||||
return
|
||||
end
|
||||
for k,v in pairs(data) do
|
||||
if(v == -1) then
|
||||
data[ k ] = {}
|
||||
end
|
||||
end
|
||||
yl_speak_up.player_vars = data
|
||||
end
|
||||
-- do so when this file is parsed
|
||||
yl_speak_up.load_quest_variables()
|
||||
|
||||
|
||||
-- new variables have to be added somehow
|
||||
yl_speak_up.add_quest_variable = function(owner_name, variable_name)
|
||||
local k = tostring(owner_name).." "..tostring(variable_name)
|
||||
local k = "$ "..tostring(owner_name).." "..tostring(variable_name)
|
||||
if(not(owner_name) or not(variable_name)) then
|
||||
return false
|
||||
end
|
||||
-- create a new empty table;
|
||||
-- keys will be the names of players for which values are set
|
||||
yl_speak_up.player_vars[ k ] = {}
|
||||
-- a new variable was created - that deserves a forced save
|
||||
yl_speak_up.save_quest_variables(true)
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
-- accidentally created or no longer needed variables need to be deleted somehow
|
||||
yl_speak_up.del_quest_variable = function(owner_name, variable_name)
|
||||
local k = tostring(owner_name).." "..tostring(variable_name)
|
||||
local k = "$ "..tostring(owner_name).." "..tostring(variable_name)
|
||||
if(not(owner_name) or not(variable_name)) then
|
||||
return false
|
||||
end
|
||||
-- a variable was deleted - that deserves a forced save
|
||||
yl_speak_up.save_quest_variables(true)
|
||||
yl_speak_up.player_vars[ k ] = nil
|
||||
end
|
||||
|
||||
@ -44,7 +89,9 @@ yl_speak_up.set_quest_variable_value = function(player_name, variable_name, new_
|
||||
if(not(variable_name) or not(player_name) or not(yl_speak_up.player_vars[ k ])) then
|
||||
return false
|
||||
end
|
||||
yl_speak_up.player_vars[ k ][ player_name ] = new_value
|
||||
yl_speak_up.player_vars[ k ][ player_name ] = tostring(new_value)
|
||||
-- a quest variable was changed - save that to disc (but no need to force it)
|
||||
yl_speak_up.save_quest_variables(false)
|
||||
return true
|
||||
end
|
||||
|
||||
@ -70,7 +117,7 @@ yl_speak_up.get_quest_variables_with_read_access = function(pname)
|
||||
local liste = {}
|
||||
for k, v in pairs(yl_speak_up.player_vars) do
|
||||
local parts = string.split(k, " ")
|
||||
if(parts and parts[1] and parts[1] == pname) then
|
||||
if(parts and parts[1] and parts[1] == "$" and parts[2] and parts[2] == pname) then
|
||||
table.insert(liste, k)
|
||||
end
|
||||
end
|
||||
@ -88,7 +135,7 @@ yl_speak_up.get_quest_variables_with_write_access = function(pname)
|
||||
local liste = {}
|
||||
for k, v in pairs(yl_speak_up.player_vars) do
|
||||
local parts = string.split(k, " ")
|
||||
if(parts and parts[1] and parts[1] == pname) then
|
||||
if(parts and parts[1] and parts[1] == "$" and parts[2] and parts[2] == pname) then
|
||||
table.insert(liste, k)
|
||||
end
|
||||
end
|
||||
@ -151,3 +198,42 @@ yl_speak_up.get_fs_manage_variables = function(player, param)
|
||||
-- TODO: delete variable
|
||||
"button[2.0,3.5;1.0,0.6;back;Back]"
|
||||
end
|
||||
|
||||
|
||||
-- variables are personalized; they are prefixed by "$ <PLAYER_NAME> <VAR_NAME>"
|
||||
|
||||
-- helper function;
|
||||
-- strip "$ PNAME " from variable names (but only for those owned by player with name pname)
|
||||
yl_speak_up.strip_pname_from_var = function(var_name, pname)
|
||||
local parts = string.split(var_name, " ")
|
||||
if(parts and parts[1] and parts[1] == "$" and parts[2] and parts[2] == pname) then
|
||||
table.remove(parts, 1) -- remove "$"
|
||||
table.remove(parts, 1) -- remove pname
|
||||
return table.concat(parts, " ")
|
||||
end
|
||||
return var_name
|
||||
end
|
||||
|
||||
|
||||
-- does the opposite of the function above; adds "$ PNAME " if needed
|
||||
yl_speak_up.add_pname_to_var = function(var_name, pname)
|
||||
local parts = string.split(var_name, " ")
|
||||
if(parts and parts[1] and parts[1] ~= "$") then
|
||||
return "$ "..tostring(pname).." "..tostring(var_name)
|
||||
end
|
||||
return var_name
|
||||
end
|
||||
|
||||
|
||||
-- helper function for yl_speak_up.input_fs_edit_option_related
|
||||
-- and yl_speak_up.get_fs_edit_option_p_and_e_state
|
||||
yl_speak_up.strip_pname_from_varlist = function(var_list, pname)
|
||||
local var_list_text = ""
|
||||
-- strip pname from the variable names
|
||||
for i, v in ipairs(var_list) do
|
||||
var_list[i] = yl_speak_up.strip_pname_from_var(v, pname)
|
||||
-- useful for presenting a list
|
||||
var_list_text = var_list_text..","..minetest.formspec_escape(tostring(var_list[i]))
|
||||
end
|
||||
return var_list_text
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user