Add type annotations to vl_tuning, convert minetest->core in vl_tuning, remove last remnants of [1] value accesses, fix several issues uncoverted by type checking, rename some fields

This commit is contained in:
teknomunk 2025-01-01 07:43:18 -06:00
parent fee35e79c4
commit 427f2cf847
9 changed files with 85 additions and 50 deletions

View file

@ -3,6 +3,7 @@
"diagnostics": { "disable": ["lowercase-global"] },
"diagnostics.globals": [
"minetest",
"core",
"dump",
"dump2",
"Raycast",
@ -18,5 +19,6 @@
"AreaStore",
"vector"
],
"workspace.library": ["/usr/share/luanti/luanti-lls-definitions/library", "/usr/share/luanti/builtin"],
"workspace.ignoreDir": [".luacheckrc"]
}

View file

@ -1,8 +1,8 @@
local modname = "vl_tuning"
local modpath = minetest.get_modpath(modname)
local S = minetest.get_translator(modname)
local F = function(f) return minetest.formspec_escape(S(f)) end
local FE = minetest.formspec_escape
local modpath = core.get_modpath(modname)
local S = core.get_translator(modname)
local F = function(f) return core.formspec_escape(S(f)) end
local FE = core.formspec_escape
local mod = vl_tuning
local function bool_to_string(value)
@ -18,12 +18,12 @@ local function formspec_for_setting(y, name)
local fs = {}
table.insert(fs, "label[0,"..(y+0.15)..";"..FE(name).."]")
table.insert(fs, "hypertext[0.15,"..(y+0.25)..";14.85,0.65;;"..FE("<style color=black>"..(setting.description or "").."</style>").."]")
table.insert(fs, "hypertext[0.15,"..(y+0.25)..";14.85,0.65;;"..FE("<style color=black>"..setting.description.."</style>").."]")
if setting_type == "bool" then
table.insert(fs, "checkbox[17,"..(y+0.15)..";"..FE(name)..";;"..bool_to_string(setting[1]).."]")
table.insert(fs, "checkbox[17,"..(y+0.15)..";"..FE(name)..";;"..bool_to_string(setting.getter()).."]")
elseif setting_type == "number" then
table.insert(fs, "field[15,"..y..";2.5,0.75;"..FE(name)..";;"..string.format("%.4g", setting[1]).."]")
table.insert(fs, "field[15,"..y..";2.5,0.75;"..FE(name)..";;"..string.format("%.4g", setting.getter()).."]")
table.insert(fs, "field_close_on_enter["..FE(name)..";false]")
elseif setting_type == "string" then
end
@ -66,12 +66,12 @@ function vl_tuning.show_formspec(player_name, tab)
"scrollbar[18.75,0.75;0.75,9.25;vertical;settings;0]",
})
minetest.show_formspec(player_name, "vl_tuning:settings", formspec)
core.show_formspec(player_name, "vl_tuning:settings", formspec)
end
minetest.register_on_player_receive_fields(function(player, formname, fields)
core.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "vl_tuning:settings" then return end
minetest.log("action",dump({
core.log("action",dump({
player = player,
fields = fields,
formname = formname,
@ -86,12 +86,11 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
if fields.quit or (not fields.tab or fields.old_tab == fields.tab) then return end
minetest.log("Seting settings formspec")
mod.show_formspec(player:get_player_name(), fields.tab)
end)
minetest.register_chatcommand("settings",{
func = function(player_name, param)
core.register_chatcommand("settings",{
func = function(player_name, _)
dofile(modpath.."/gui.lua")
mod.show_formspec(player_name)
end

View file

@ -1,13 +1,14 @@
local modname = minetest.get_current_modname()
local modpath = minetest.get_modpath(modname)
local S = minetest.get_translator(modname)
local storage = minetest.get_mod_storage()
local modname = core.get_current_modname()
local modpath = core.get_modpath(modname)
local S = core.get_translator(modname)
local storage = core.get_mod_storage()
local mod = {}
vl_tuning = mod
local DEBUG = false
-- All registered tunable parameters
--- @type table<string, vl_tuning.Setting>
local tunables = {}
vl_tuning.registered_settings = tunables
@ -30,11 +31,26 @@ local tunable_types = {
}
-- Tunable metatable functions
---@class (exact) vl_tuning.Setting
---@field name string
---@field setting_type "string"|"number"|"bool"
---@field description string
---@field default? string|integer|boolean
---@field set fun(self : vl_tuning.Setting, value, no_hook : boolean?)
---@field setter fun(value)
---@field getter fun() : string|boolean|number
---@field from_string fun(value : string)
---@field to_string fun(value : any)
---@field on_change? fun(self : vl_tuning.Setting)
---@field getter fun()
local tunable_class = {}
---@param self vl_tuning.Setting
---@param value any
---@param no_hook? boolean
function tunable_class:set(value, no_hook)
local self_type = self.type
if type(value) == "string" then
local new_value = self_type.from_string(value)
local new_value = self.from_string(value)
if new_value == nil then new_value = self.default end
self.setter(new_value)
@ -43,7 +59,7 @@ function tunable_class:set(value, no_hook)
end
if DEBUG then
minetest.log("action", "[vl_tuning] Set "..self.setting.." to "..dump(self.getter()))
core.log("action", "[vl_tuning] Set "..self.name.." to "..dump(self.getter()))
end
-- Call on_change hook
@ -53,50 +69,66 @@ function tunable_class:set(value, no_hook)
end
-- Persist value
storage:set_string(self.setting,self_type.to_string(self.getter()))
storage:set_string(self.name,self.to_string(self.getter()))
end
function tunable_class:get_string()
return self.type.to_string(self.getter())
return self.to_string(self.getter())
end
function mod.setting(setting, setting_type, def )
---@class vl_tuning.SettingDef
---@field set fun(value : any)
---@field get fun(): string|boolean|number
---@field default any
---@field description? string
---@param name string
---@param p_type? "bool"|"number"|"string"
---@param def? vl_tuning.SettingDef
---@return vl_tuning.Setting?
function mod.setting(name, p_type, def )
-- return the existing setting if it was previously registered. Don't update the definition
local tunable = tunables[setting]
local tunable = tunables[name]
if tunable then return tunable end
assert(setting_type)
assert(p_type)
assert(def)
assert(type(def.set) == "function", "Tunable requires set method")
assert(type(def.get) == "function", "Tunable required get method")
-- Setup the tunable data
tunable = table.copy(def)
tunable.setting = setting
tunable.setter = def.set
tunable.getter = def.get
tunable.type = tunable_types[setting_type]
tunable.setting_type = setting_type
if tunable.default then
tunable.set(tunable.default)
---@type vl_tuning.Setting
tunable = {
name = name,
setting_type = p_type,
description = def.description or "",
setter = def.set,
getter = def.get,
set = tunable_class.set,
get_string = tunable_class.get_string,
from_string = tunable_types[p_type].from_string,
to_string = tunable_types[p_type].to_string,
}
if def.default then
tunable:set(def.default)
end
setmetatable(tunable, {__index=tunable_class})
-- Load the setting value from mod storage
local setting_value = storage:get_string(setting)
local setting_value = storage:get_string(name)
if setting_value and setting_value ~= "" then
tunable:set(setting_value, true)
if DEBUG then
minetest.log("action", "[vl_tuning] Loading "..setting.." = "..dump(setting_value).." ("..dump(tunable[1])..")")
core.log("action", "[vl_tuning] Loading "..name.." = "..dump(setting_value).." ("..dump(tunable.getter())..")")
end
end
-- Add to the list of all available settings
tunables[setting] = tunable
tunables[name] = tunable
-- Provide it so that the current value in [1] can be accessed without having to call into this API again
-- Provide it so that the current value can be retrieved from result.getter()
return tunable
end
minetest.register_chatcommand("set_setting", {
core.register_chatcommand("set_setting", {
description = S("Admin tool to tune settings and game rules"),
params = S("<setting> <value>"),
privs = { debug = true },
@ -117,17 +149,17 @@ minetest.register_chatcommand("set_setting", {
end
if DEBUG then
minetest.log("action", "[vl_tuning] "..name.." set ".. params[1] .." to "..params[2])
core.log("action", "[vl_tuning] "..name.." set ".. params[1] .." to "..params[2])
end
tunable:set(params[2])
return true
end
})
minetest.register_chatcommand("get_setting", {
core.register_chatcommand("get_setting", {
description = S("Admin tool to view settings and game rules"),
params = S("<setting>"),
privs = { debug = true },
func = function(name, param)
func = function(_, param)
local tunable = tunables[param]
if tunable then
return true, tunable:get_string()
@ -137,11 +169,11 @@ minetest.register_chatcommand("get_setting", {
end
})
minetest.register_chatcommand("gamerule", {
core.register_chatcommand("gamerule", {
description = S("Display or set customizable options"),
params = S("<rule> [<value>]"),
privs = { server = true },
func = function(name, params_raw)
func = function(_, params_raw)
-- Split apart the params
local params = {}
for str in string.gmatch(params_raw, "([^ ]+)") do
@ -160,7 +192,7 @@ minetest.register_chatcommand("gamerule", {
local value = params[2]
if value then
if DEBUG then
minetest.log("action", "[vl_tuning] Setting game rule "..params[1].." to "..params[2])
core.log("action", "[vl_tuning] Setting game rule "..params[1].." to "..params[2])
end
tunable:set(params[2])
return true

View file

@ -297,7 +297,7 @@ mcl_events.register_event("raid",{
health_max = 1,
exclusive_to_area = 128,
enable_bossbar = true,
cond_start = function(self)
cond_start = function(_)
if gamerule_disableRaids then return false end
--minetest.log("Cond start raid")

View file

@ -3,7 +3,6 @@ local modname = minetest.get_current_modname()
local modpath = minetest.get_modpath(modname)
local S = minetest.get_translator(modname)
local mods_loaded = false
local NIGHT_VISION_RATIO = 0.45
local DEBUG = false

View file

@ -238,8 +238,9 @@ minetest.register_on_leaveplayer(function(player)
end)
local keep_inventory = vl_tuning.setting("gamerule:keepInventory")
assert(keep_inventory)
minetest.register_on_dieplayer(function(player)
if not keep_inventory[1] then
if not keep_inventory:getter() then
mcl_experience.throw_xp(player:get_pos(), mcl_experience.get_xp(player))
mcl_experience.set_xp(player, 0)
end

View file

@ -96,7 +96,7 @@ local nether_portal_survival_delay = 4
vl_tuning.setting("gamerule:playersNetherPortalDefaultDelay", "number", {
default = 4,
set = function(val) nether_portal_survival_delay = val end,
get = function() return nether_portal_survive_delay end,
get = function() return nether_portal_survival_delay end,
})
-- Speeds up the search by allowing some non-air nodes to be replaced when

View file

@ -435,9 +435,10 @@ minetest.register_globalstep(function(dtime)
end)
local keep_inventory = vl_tuning.setting("gamerule:keepInventory")
assert(keep_inventory)
minetest.register_on_dieplayer(function(player)
remove_shield_hud(player)
if not keep_inventory[1] then
if not keep_inventory.getter() then
remove_shield_entity(player, 1)
remove_shield_entity(player, 2)
end

View file

@ -736,8 +736,9 @@ end
init()
local keep_inventory = vl_tuning.setting("gamerule:keepInventory")
assert(keep_inventory)
minetest.register_on_respawnplayer(function(player)
if not keep_inventory[1] then
if not keep_inventory.getter() then
mcl_skins.update_player_skin(player) -- ensures players have their cape again after dying with an elytra
end
end)