summaryrefslogtreecommitdiff
path: root/init.lua
diff options
context:
space:
mode:
authorcheapie <no-email-for-you@example.com>2021-03-05 00:00:01 -0600
committercheapie <no-email-for-you@example.com>2021-03-05 00:00:01 -0600
commit17dc9a8247c35b9710741d0f23d502e7d66d37ba (patch)
treecef1ef11cf26f4411741840a1ae99cbf1619122e /init.lua
downloadplayersettings-main.tar
playersettings-main.tar.gz
playersettings-main.tar.bz2
playersettings-main.tar.xz
playersettings-main.zip
Add initial contentHEADmain
Diffstat (limited to 'init.lua')
-rw-r--r--init.lua176
1 files changed, 176 insertions, 0 deletions
diff --git a/init.lua b/init.lua
new file mode 100644
index 0000000..814431e
--- /dev/null
+++ b/init.lua
@@ -0,0 +1,176 @@
+local storage = minetest.get_mod_storage()
+
+playersettings = {}
+
+playersettings.registered = {}
+
+playersettings.settingslist = {}
+
+playersettings.highlighted = {}
+
+playersettings.form = "formspec_version[4]"..
+ "size[15,15]" ..
+ "button[12.5,13.5;2,1;quit;Save and Exit]"..
+ "textlist[0.5,0.5;7,14;settinglist;%s;%d;false]"..
+ "label[8,2;%s]"..
+ "label[8,3;%s]"..
+ "%s"
+
+function playersettings.openform(player)
+ if type(player) == "string" then player = minetest.get_player_by_name(player) end
+ local name = player:get_player_name()
+ if #playersettings.settingslist < 1 then
+ local form = "formspec_version[4]size[12,3]label[0.5,1;No settings currently exist.]label[0.5,1.5;To use the settings menu, one or more mods that provide some settings must be installed.]button_exit[5,2;2,1;quit;Close]"
+ minetest.show_formspec(name,"playersettings:nosettings",form)
+ return
+ end
+ if not playersettings.highlighted[name] then playersettings.highlighted[name] = 1 end
+ local settingslist = ""
+ for _,setting in ipairs(playersettings.settingslist) do
+ settingslist = settingslist..minetest.formspec_escape(playersettings.registered[setting].shortdesc)..","
+ end
+ settingslist = settingslist:sub(1,-2)
+ local settingname = playersettings.settingslist[playersettings.highlighted[name]]
+ local def = playersettings.registered[settingname]
+ local extras = ""
+ if def.type == "boolean" then
+ extras = "checkbox[8,8;checkbox;Enabled;%s]"
+ extras = extras:format(playersettings.get(name,settingname) and "true" or "false")
+ elseif def.type == "string" then
+ extras = "field[8,8;6,1;field;Enter value:;%s]label[8,9.5;Allowed values: %s]field_close_on_enter[field;false]"
+ extras = extras:format(minetest.formspec_escape(playersettings.get(name,settingname)),minetest.formspec_escape(def.values or "any string"))
+ elseif def.type == "number" then
+ extras = "field[8,8;6,1;field;Enter value:;%s]label[8,9.5;Allowed values: %s]field_close_on_enter[field;false]"
+ local allowed = "any number"
+ if def.min and def.max then
+ allowed = "numbers "..def.min.." to "..def.max
+ elseif def.max then
+ allowed = "numbers up to "..def.max
+ elseif def.min then
+ allowed = "numbers "..def.min.." and up"
+ end
+ if def.integer then
+ allowed = allowed.." (whole numbers only)"
+ end
+ extras = extras:format(minetest.formspec_escape(playersettings.get(name,settingname)),allowed)
+ elseif def.type == "enum" then
+ extras = "dropdown[8,8;6,1;dropdown;%s;%d;false]"
+ local choices = ""
+ local current = playersettings.get(name,settingname)
+ local selected = 1
+ for k,v in ipairs(def.values) do
+ choices = choices..minetest.formspec_escape(v)..","
+ if v == current then selected = k end
+ end
+ choices = choices:sub(1,-2)
+ extras = extras:format(choices,selected)
+ end
+ local form = playersettings.form:format(settingslist,playersettings.highlighted[name],minetest.formspec_escape(def.shortdesc),minetest.formspec_escape(def.longdesc),extras)
+ minetest.show_formspec(name,"playersettings:settings",form)
+end
+
+function playersettings.handleform(player,form,fields)
+ if form ~= "playersettings:settings" then return end
+ local name = player:get_player_name()
+ local settingname = playersettings.settingslist[playersettings.highlighted[name]]
+ local def = playersettings.registered[settingname]
+ if def.type == "boolean" and fields.checkbox then
+ playersettings.set(name,settingname,fields.checkbox == "true")
+ elseif def.type == "enum" and fields.dropdown then
+ playersettings.set(name,settingname,fields.dropdown)
+ elseif def.type == "number" and fields.field then
+ local value = tonumber(fields.field)
+ if value
+ and ((not def.max) or (value <= def.max))
+ and ((not def.min) or (value >= def.min)) then
+ if def.integer then value = math.floor(value) end
+ playersettings.set(name,settingname,value)
+ end
+ elseif def.type == "string" and fields.field then
+ playersettings.set(name,settingname,fields.field)
+ end
+ if fields.settinglist then
+ local exp = minetest.explode_textlist_event(fields.settinglist)
+ if exp.type == "CHG" then
+ playersettings.highlighted[name] = exp.index
+ playersettings.openform(player)
+ end
+ end
+ if fields.quit then
+ minetest.close_formspec(name,"playersettings:settings")
+ end
+end
+
+function playersettings.getdefault(setting)
+ local def = playersettings.registered[setting]
+ if def.default ~= nil then return def.default end
+ if def.type == "boolean" then
+ return false
+ elseif def.type == "number" then
+ return def.min or 0
+ elseif def.type == "string" then
+ return ""
+ end
+end
+
+function playersettings.get(name,setting)
+ assert(type(name) == "string",string.format("Invalid player name (expected string, got %s)",type(name)))
+ assert(type(setting) == "string",string.format("Invalid setting name (expected string, got %s)",type(setting)))
+ assert(playersettings.registered[setting],"No such setting: "..setting)
+ local value = minetest.deserialize(storage:get_string(string.format("%s|%s",name,setting)))
+ if value then
+ return value
+ else
+ return playersettings.getdefault(setting)
+ end
+end
+
+function playersettings.set(name,setting,value)
+ assert(type(name) == "string",string.format("Invalid player name (expected string, got %s)",type(name)))
+ assert(type(setting) == "string",string.format("Invalid setting name (expected string, got %s)",type(setting)))
+ assert(playersettings.registered[setting],"No such setting: "..setting)
+ local old = playersettings.get(name,setting)
+ local def = playersettings.registered[setting]
+ if def.onchange then
+ if not def.onchange(name,old,value) then return end
+ end
+ storage:set_string(string.format("%s|%s",name,setting),minetest.serialize(value))
+ if def.afterchange then def.afterchange(name,old,value) end
+end
+
+function playersettings.register(setting,def)
+ assert(type(setting) == "string",string.format("Invalid setting name (expected string, got %s)",type(setting)))
+ assert(not playersettings.registered[setting],string.format("Setting %s already defined",setting))
+ assert(type(def) == "table",string.format("Invalid setting definition (expected table, got %s)",type(def)))
+ table.insert(playersettings.settingslist,setting)
+ table.sort(playersettings.settingslist)
+ playersettings.registered[setting] = def
+end
+
+function playersettings.onjoin(player)
+ local name = player:get_player_name()
+ for setting,def in pairs(playersettings.registered) do
+ if type(def.onjoin) == "function" then
+ def.onjoin(name,playersettings.get(name,setting))
+ end
+ end
+end
+
+if minetest.get_modpath("unified_inventory") then
+ unified_inventory.register_button("playersettings",
+ {
+ action = playersettings.openform,
+ tooltip = "Settings",
+ type = "image",
+ image = "playersettings_settings_button.png"
+ }
+ )
+end
+
+minetest.register_chatcommand("settings",{
+ description = "Open player settings menu",
+ func = playersettings.openform,
+})
+
+minetest.register_on_joinplayer(playersettings.onjoin)
+minetest.register_on_player_receive_fields(playersettings.handleform)