mirror of
				https://gitea.your-land.de/Sokomine/yl_speak_up.git
				synced 2025-10-31 20:33:07 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			527 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			527 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
| 
 | |
| -- just some handling of variables
 | |
| 
 | |
| -- TODO: mark some vars as "need to be saved" while others are less important (i.e. timestamps)
 | |
| 
 | |
| -- the keys are of the form:
 | |
| -- 	$ <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
 | |
| 	if(not(yl_speak_up.player_vars.meta)) then
 | |
| 		yl_speak_up.player_vars["meta"] = {}
 | |
| 	end
 | |
| 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)
 | |
| 	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
 | |
| 
 | |
| 
 | |
| -- time based variables are used for "Limit guessing:" and "Limit repeating:"; they ensure that
 | |
| -- options with actions cannot be repeated indefintely;
 | |
| -- returns false if the variable could not be created; else it returns the variable metadata
 | |
| yl_speak_up.add_time_based_variable = function(variable_name)
 | |
| 	if(not(yl_speak_up.player_vars[ variable_name ])) then
 | |
| 		yl_speak_up.player_vars[ variable_name ] = {}
 | |
| 		yl_speak_up.player_vars[ variable_name ][ "$META$" ] = {}
 | |
| 		yl_speak_up.player_vars[ variable_name ][ "$META$"][ "var_type" ] = "time_based"
 | |
| 		yl_speak_up.save_quest_variables(true)
 | |
| 		return yl_speak_up.player_vars[ variable_name ][ "$META$"]
 | |
| 	elseif(yl_speak_up.player_vars[ variable_name ]
 | |
| 	  and  yl_speak_up.player_vars[ variable_name ][ "$META$"]
 | |
| 	  and  type(yl_speak_up.player_vars[ variable_name ][ "$META$"]) == "table"
 | |
| 	  and  yl_speak_up.player_vars[ variable_name ][ "$META$"][ "var_type" ] == "time_based") then
 | |
| 		return yl_speak_up.player_vars[ variable_name ][ "$META$"]
 | |
| 	end
 | |
| 	return false
 | |
| end
 | |
| 
 | |
| 
 | |
| -- accidentally created or no longer needed variables need to be deleted somehow
 | |
| -- force_delete if set, the variable will be deleted no matter what; this is for
 | |
| --              manual maintenance and not used in this mod
 | |
| yl_speak_up.del_quest_variable = function(owner_name, variable_name, force_delete)
 | |
| 	if(not(owner_name) or not(variable_name)) then
 | |
| 		return " could not be deleted. Parameters mismatch."
 | |
| 	end
 | |
| 	local var_name = yl_speak_up.restore_complete_var_name(variable_name, owner_name)
 | |
| 	if(not(var_name) or not(yl_speak_up.player_vars[ var_name ])) then
 | |
| 		return text.." does not exist."
 | |
| 	end
 | |
| 	local text = "Variable \""..minetest.formspec_escape(var_name).."\""
 | |
| 	-- forcefully delete - even if the variable is still beeing used
 | |
| 	if(force_delete) then
 | |
| 		yl_speak_up.player_vars[ k ] = nil
 | |
| 		yl_speak_up.save_quest_variables(true)
 | |
| 		return text.." deleted by force."
 | |
| 	end
 | |
| 	-- check if the player really owns the variable: not that important because only unused
 | |
| 	-- variables can be deleted;
 | |
| 	-- check if the variable is used by an NPC
 | |
| 	local var_data = yl_speak_up.player_vars[ var_name ]
 | |
| 	local npc_users = yl_speak_up.get_variable_metadata(var_name, "used_by_npc")
 | |
| 	if(npc_users and #npc_users > 0) then
 | |
| 		return text.." could not be deleted.\nIt is used by "..tostring(#npc_users).." NPC."
 | |
| 	end
 | |
| 	-- check if the variable is used by a node position (for quests)
 | |
| 	local node_pos_users = yl_speak_up.get_variable_metadata(var_name, "used_by_node_pos")
 | |
| 	if(node_pos_users and #node_pos_users > 0) then
 | |
| 		return text.." could not be deleted.\nIt is used by "..tostring(#node_pos_users)..
 | |
| 				" node positions (quest)."
 | |
| 	end
 | |
| 	-- check if the variable has any values stored
 | |
| 	for k, v in pairs(var_data) do
 | |
| 		if(k and k ~= "$META$") then
 | |
| 			return text.." could not be deleted.\nIt contains at least one stored value."
 | |
| 		end
 | |
| 	end
 | |
| 	-- actually delete the variable
 | |
| 	yl_speak_up.player_vars[ var_name ] = nil
 | |
| 	-- a variable was deleted - that deserves a forced save
 | |
| 	yl_speak_up.save_quest_variables(true)
 | |
| 	return text.." deleted successfully."
 | |
| end
 | |
| 
 | |
| 
 | |
| -- set the value of a variable used by a player in an NPC;
 | |
| -- returns false if the variable cannot be set (i.e. does not exist)
 | |
| yl_speak_up.set_quest_variable_value = function(player_name, variable_name, new_value)
 | |
| 	-- the owner name is alrady encoded in the variable name
 | |
| 	local k = tostring(variable_name)
 | |
| 	if(not(variable_name) or not(player_name) or not(yl_speak_up.player_vars[ k ])) then
 | |
| 		return false
 | |
| 	end
 | |
| 	if(yl_speak_up.player_vars[ k ]["$META$"]
 | |
| 	  and yl_speak_up.player_vars[ k ]["$META$"][ "debug" ]
 | |
| 	  and type(yl_speak_up.player_vars[ k ]["$META$"][ "debug" ]) == "table") then
 | |
| 		for p, _ in pairs(yl_speak_up.player_vars[ k ]["$META$"][ "debug" ]) do
 | |
| 			minetest.chat_send_player(p, "[Variable "..
 | |
| 				minetest.colorize("#FFFF00", tostring(k))..
 | |
| 				", player "..
 | |
| 				minetest.colorize("#FFFF00", tostring(player_name))..
 | |
| 				"] old value: \""..
 | |
| 				minetest.colorize("#FFFF00",
 | |
| 					tostring(yl_speak_up.player_vars[ k ][ player_name ]))..
 | |
| 				"\" new value: \""..
 | |
| 				minetest.colorize("#FFFF00", tostring(new_value)).."\".")
 | |
| 		end
 | |
| 	end
 | |
| 	if(new_value ~= nil) then
 | |
| 		new_value = tostring(new_value)
 | |
| 	end
 | |
| 	yl_speak_up.player_vars[ k ][ player_name ] = 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
 | |
| 
 | |
| 
 | |
| -- get the value of a variable used by a player in an NPC;
 | |
| -- returns nil if the variable does not exist
 | |
| yl_speak_up.get_quest_variable_value = function(player_name, variable_name)
 | |
| 	-- the owner name is alrady encoded in the variable name
 | |
| 	local k = tostring(variable_name)
 | |
| 	if(not(variable_name) or not(player_name) or not(yl_speak_up.player_vars[ k ])) then
 | |
| 		return nil
 | |
| 	end
 | |
| 	return yl_speak_up.player_vars[ k ][ player_name ]
 | |
| end
 | |
| 
 | |
| 
 | |
| yl_speak_up.get_quest_variables = function(pname, has_write_access)
 | |
| 	if(not(pname)) then
 | |
| 		return {}
 | |
| 	end
 | |
| 	local liste = {}
 | |
| 	-- first: list the variables owned by the player
 | |
| 	for k, v in pairs(yl_speak_up.player_vars) do
 | |
| 		local parts = string.split(k, " ")
 | |
| 		if(parts and parts[1] and parts[1] == "$" and parts[2] and parts[2] == pname) then
 | |
| 			table.insert(liste, k)
 | |
| 		end
 | |
| 	end
 | |
| 	-- if the player has the right privs: allow to access all other variables as well
 | |
| 	if( minetest.check_player_privs(pname, {npc_master=true})
 | |
| 	 or minetest.check_player_privs(pname, {npc_talk_master=true})) then
 | |
| 		for k, v in pairs(yl_speak_up.player_vars) do
 | |
| 			local parts = string.split(k, " ")
 | |
| 			-- variables owned by *other* players
 | |
| 			if(parts and parts[1] and parts[1] == "$" and parts[2] and parts[2] ~= pname) then
 | |
| 				table.insert(liste, k)
 | |
| 			end
 | |
| 		end
 | |
| 	else
 | |
| 		local right = "read_access"
 | |
| 		if(has_write_access) then
 | |
| 			right = "write_access"
 | |
| 		end
 | |
| 		-- insert those vars owned by other players where this one has access
 | |
| 		for k, v in pairs(yl_speak_up.player_vars) do
 | |
| 			if(   k[ "$META$"]
 | |
| 			  and k[ "$META$"][ right ]
 | |
| 			  and k[ "$META$"][ right ][ pname ]) then
 | |
| 				table.insert(liste, k)
 | |
| 			end
 | |
| 		end
 | |
| 	end
 | |
| 	table.sort(liste)
 | |
| 	return liste
 | |
| end
 | |
| 
 | |
| 
 | |
| -- which variables can player pname read and use in preconditions?
 | |
| -- returns a sorted list
 | |
| yl_speak_up.get_quest_variables_with_read_access = function(pname)
 | |
| 	return yl_speak_up.get_quest_variables(pname, false)
 | |
| end
 | |
| 
 | |
| 
 | |
| -- which variables can player pname write and use in effects/results?
 | |
| yl_speak_up.get_quest_variables_with_write_access = function(pname)
 | |
| 	return yl_speak_up.get_quest_variables(pname, true)
 | |
| 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)
 | |
| 	if(not(var_name)) then
 | |
| 		return ""
 | |
| 	end
 | |
| 	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
 | |
| 
 | |
| 
 | |
| -- (partly) the opposite of the function above - add the name of the player to a variable
 | |
| -- name again if needed
 | |
| yl_speak_up.restore_complete_var_name = function(var_name, pname)
 | |
| 	local vparts = string.split(var_name or "", " ")
 | |
| 	-- has the player name been stripped from the variable name for better readability?
 | |
| 	if(vparts and #vparts > 0 and vparts[1] ~= "$") then
 | |
| 		return "$ "..tostring(pname).." "..table.concat(vparts, " ")
 | |
| 	end
 | |
| 	return var_name
 | |
| end
 | |
| 
 | |
| 
 | |
| -- helper function for saving NPC data;
 | |
| -- this only works if *someone* is currently talking to that NPC
 | |
| yl_speak_up.get_pname_for_n_id = function(n_id)
 | |
| 	for k, v in pairs(yl_speak_up.speak_to) do
 | |
| 		if(v and v.n_id and v.n_id == n_id) then
 | |
| 			return k
 | |
| 		end
 | |
| 	end
 | |
| end
 | |
| 
 | |
| 
 | |
| -- add or revoke read or write access to a variable
 | |
| --
 | |
| -- k:              name of the variable
 | |
| -- pname:          the name of the player trying to grant or revoke the right
 | |
| -- grant_to_pname: the name of the player who shall have that access right
 | |
| -- grant_write_access:
 | |
| -- 	if false: grant read access
 | |
| -- 	if true:  grant write access
 | |
| -- do_grant:
 | |
| -- 	if false: revoke acces
 | |
| -- 	if true:  grant access
 | |
| -- returns true if the variable was found
 | |
| yl_speak_up.manage_access_to_quest_variable = function(k, pname, grant_to_pname, what_to_grant, do_grant)
 | |
| 	-- only read and write access can be granted
 | |
| 	if(not(what_to_grant) or (what_to_grant ~= "read_access" and what_to_grant ~= "write_access")) then
 | |
| 		return false
 | |
| 	end
 | |
| 	return yl_speak_up.set_variable_metadata(k, pname, what_to_grant, grant_to_pname, do_grant)
 | |
| end
 | |
| 
 | |
| 
 | |
| -- a more general way of setting metadata for variables
 | |
| -- in general, meta_name is a table containing entries entry_name (usually players or npc_ids)
 | |
| -- with assigned values (usually true) for quick lookup
 | |
| yl_speak_up.set_variable_metadata = function(k, pname, meta_name, entry_name, new_value)
 | |
| 	if(pname) then
 | |
| 		k = yl_speak_up.add_pname_to_var(k, pname)
 | |
| 	end
 | |
| 	-- delete/unset
 | |
| 	if(not(new_value)) then
 | |
| 		new_value = nil
 | |
| 	end
 | |
| 	-- the variable needs to exist
 | |
| 	if(not(yl_speak_up.player_vars[ k ])) then
 | |
| 		return false
 | |
| 	end
 | |
| 	-- make sure all the necessary tables exist
 | |
| 	if( not(yl_speak_up.player_vars[ k ][ "$META$" ])) then
 | |
| 		yl_speak_up.player_vars[ k ][ "$META$" ] = { meta_name = {} }
 | |
| 	end
 | |
| 
 | |
| 	-- var_type (the type of the variable) is a single string
 | |
| 	if(meta_name == "var_type") then
 | |
| 		yl_speak_up.player_vars[ k ][ "$META$"][ meta_name ] = new_value
 | |
| 	else
 | |
| 		if( not(yl_speak_up.player_vars[ k ][ "$META$" ][ meta_name ])
 | |
| 		or type(yl_speak_up.player_vars[ k ][ "$META$" ][ meta_name ]) ~= "table") then
 | |
| 			yl_speak_up.player_vars[ k ][ "$META$" ][ meta_name ] = {}
 | |
| 		end
 | |
| 		yl_speak_up.player_vars[ k ][ "$META$"][ meta_name ][ entry_name ] = new_value
 | |
| 	end
 | |
| 	yl_speak_up.save_quest_variables(true)
 | |
| 	return true
 | |
| end
 | |
| 
 | |
| 
 | |
| -- get a list of all players who have read or write access to variable k (belonging to pname)
 | |
| -- (technically a table and not a list)
 | |
| yl_speak_up.get_access_list_for_var = function(k, pname, access_what)
 | |
| 	k = yl_speak_up.add_pname_to_var(k, pname)
 | |
| 	if(not(k)
 | |
| 	  or not(yl_speak_up.player_vars[ k ])
 | |
| 	  or not(yl_speak_up.player_vars[ k ][ "$META$"])
 | |
| 	  or not(yl_speak_up.player_vars[ k ][ "$META$"][ access_what ])) then
 | |
| 		return {}
 | |
| 	end
 | |
| 	return yl_speak_up.player_vars[ k ][ "$META$"][ access_what ]
 | |
| end
 | |
| 
 | |
| 
 | |
| -- the dialog data of an NPC is saved - use this to save some statistical data
 | |
| -- plus store which variables are used by this NPC
 | |
| -- TODO: show this data in a formspec to admins for maintenance
 | |
| yl_speak_up.update_stored_npc_data = function(n_id, dialog)
 | |
| 	-- in order to determine the position of the NPC, we need its object
 | |
| 	local pname = yl_speak_up.get_pname_for_n_id(n_id)
 | |
| 	local npc_pos = ""
 | |
| 	if(pname) then
 | |
| 		local obj = yl_speak_up.speak_to[pname].obj
 | |
| 		if(obj and obj:get_pos()) then
 | |
| 			npc_pos = minetest.pos_to_string(obj:get_pos())
 | |
| 		end
 | |
| 	end
 | |
| 	-- gather statistical data about the NPC and find out which variables it uses
 | |
| 	local anz_dialogs = 0
 | |
| 	local anz_options = 0
 | |
| 	local anz_preconditions = 0
 | |
| 	local anz_actions = 0
 | |
| 	local anz_effects = 0
 | |
| 	local anz_trades  = 0
 | |
| 	local variables_p = {}
 | |
| 	local variables_e = {}
 | |
| 	if(dialog and dialog.n_dialogs) then
 | |
| 		for d_id, d in pairs(dialog.n_dialogs) do
 | |
| 			anz_dialogs = anz_dialogs + 1
 | |
| 			if(d and d.d_options) then
 | |
| 				for o_id, o in pairs(d.d_options) do
 | |
| 					anz_options = anz_options + 1
 | |
| 					if(o and o.o_prerequisites) then
 | |
| 						for p_id, p in pairs(o.o_prerequisites) do
 | |
| 							anz_preconditions = anz_preconditions + 1
 | |
| 							if(p and p.p_type and p.p_type == "state"
 | |
| 							  and p.p_variable and p.p_variable ~= "") then
 | |
| 								variables_p[ p.p_variable ] = true
 | |
| 							end
 | |
| 						end
 | |
| 					end
 | |
| 					if(o and o.actions) then
 | |
| 						for a_id, a_data in pairs(o.actions) do
 | |
| 							anz_actions = anz_actions + 1
 | |
| 						end
 | |
| 					end
 | |
| 					if(o and o.o_results) then
 | |
| 						for r_id, r in pairs(o.o_results) do
 | |
| 							anz_effects = anz_effects + 1
 | |
| 							if(r and r.r_type and r.r_type == "state"
 | |
| 							  and r.r_variable and r.r_variable ~= "") then
 | |
| 								variables_e[ r.r_variable ] = true
 | |
| 							end
 | |
| 						end
 | |
| 					end
 | |
| 				end
 | |
| 			end
 | |
| 		end
 | |
| 	end
 | |
| 	if(dialog and dialog.trades) then
 | |
| 		for trade_id, t_data in pairs(dialog.trades) do
 | |
| 			-- not a trade that is the action of a dialog option; only trade list trades count
 | |
| 			if(not(t_data.d_id)) then
 | |
| 				anz_trades = anz_trades + 1
 | |
| 			end
 | |
| 		end
 | |
| 	end
 | |
| 	-- add a special variable (if needed) for saving the NPC meta data
 | |
| 	if(not(yl_speak_up.player_vars[ "$NPC_META_DATA$" ])) then
 | |
| 		yl_speak_up.player_vars[ "$NPC_META_DATA$" ] = {}
 | |
| 	end
 | |
| 	yl_speak_up.player_vars[ "$NPC_META_DATA$" ][ n_id ] = {
 | |
| 		n_id = n_id,
 | |
| 		name = tostring(dialog.n_npc),
 | |
| 		owner = tostring(yl_speak_up.npc_owner[ n_id ]),
 | |
| 		may_edit = dialog.n_may_edit or {},
 | |
| 		pos = tostring(npc_pos),
 | |
| 		anz_dialogs = anz_dialogs,
 | |
| 		anz_options = anz_options,
 | |
| 		anz_preconditions = anz_preconditions,
 | |
| 		anz_actions = anz_actions,
 | |
| 		anz_effects = anz_effects,
 | |
| 		anz_trades = anz_trades,
 | |
| 		last_modified = os.date(),
 | |
| 	}
 | |
| 
 | |
| 	-- delete all old entries that are not longer needed
 | |
| 	for k, v in pairs(yl_speak_up.player_vars) do
 | |
| 		if(not(variables_p[ k ]) and not(variables_e[ k ])) then
 | |
| 			yl_speak_up.set_variable_metadata(k, pname, "used_by_npc", n_id, false)
 | |
| 		end
 | |
| 	end
 | |
| 
 | |
| 	-- save in the variables' metadata which NPC uses it
 | |
| 	-- (this is what we're mostly after - know which variable is used in which NPC)
 | |
| 	for k, v in pairs(variables_p) do
 | |
| 		yl_speak_up.set_variable_metadata(k, pname, "used_by_npc", n_id, true)
 | |
| 	end
 | |
| 	for k, v in pairs(variables_e) do
 | |
| 		yl_speak_up.set_variable_metadata(k, pname, "used_by_npc", n_id, true)
 | |
| 	end
 | |
| 	-- force writing the data
 | |
| 	yl_speak_up.save_quest_variables(true)
 | |
| end
 | |
| 
 | |
| 
 | |
| -- which NPC do use this variable?
 | |
| yl_speak_up.get_variable_metadata = function(var_name, meta_name, get_as_is)
 | |
| 	-- var_type (the type of the variable) is a single string
 | |
| 	if(meta_name and var_name and meta_name == "var_type") then
 | |
| 		if(  not(yl_speak_up.player_vars[ var_name ])
 | |
| 		  or not(yl_speak_up.player_vars[ var_name ][ "$META$"])) then
 | |
| 			return nil
 | |
| 		end
 | |
| 		return yl_speak_up.player_vars[ var_name ][ "$META$"][ meta_name ]
 | |
| 	end
 | |
| 	-- no variable, or nothing stored? then it's not used by any NPC either
 | |
| 	if(not(var_name)
 | |
| 	  or  not(meta_name)
 | |
| 	  or  not(yl_speak_up.player_vars[ var_name ])
 | |
| 	  or  not(yl_speak_up.player_vars[ var_name ][ "$META$"])
 | |
| 	  or  not(yl_speak_up.player_vars[ var_name ][ "$META$"][ meta_name ])
 | |
| 	  or type(yl_speak_up.player_vars[ var_name ][ "$META$"][ meta_name ]) ~= "table") then
 | |
| 		return {}
 | |
| 	end
 | |
| 	-- do not transform into a list; get the table
 | |
| 	if(get_as_is) then
 | |
| 		return yl_speak_up.player_vars[ var_name ][ "$META$"][ meta_name ]
 | |
| 	end
 | |
| 	local meta_list = {}
 | |
| 	for k, v in pairs(yl_speak_up.player_vars[ var_name ][ "$META$"][ meta_name ]) do
 | |
| 		table.insert(meta_list, k)
 | |
| 	end
 | |
| 	table.sort(meta_list)
 | |
| 	return meta_list
 | |
| end
 | |
| 
 | |
| 
 | |
| -- show which variables the player is currently debugging
 | |
| yl_speak_up.get_list_of_debugged_variables = function(pname)
 | |
| 	if(not(pname) or pname == "") then
 | |
| 		return
 | |
| 	end
 | |
| 	local res = {}
 | |
| 	for k, v in pairs(yl_speak_up.player_vars) do
 | |
| 		if(k and v and v[ "$META$" ] and v[ "$META$" ][ "debug" ]) then
 | |
| 			-- this will be used in a table presented to the player
 | |
| 			table.insert(res, minetest.formspec_escape(k))
 | |
| 		end
 | |
| 	end
 | |
| 	return res
 | |
| end
 | |
| 
 | |
| 
 | |
| -- helper function; time is sometimes needed
 | |
| yl_speak_up.get_time_in_seconds = function()
 | |
| 	return math.floor(minetest.get_us_time()/1000000)
 | |
| end
 |