diff options
author | cheapie <no-email-for-you@example.com> | 2021-03-05 00:00:01 -0600 |
---|---|---|
committer | cheapie <no-email-for-you@example.com> | 2021-03-05 00:00:01 -0600 |
commit | 17dc9a8247c35b9710741d0f23d502e7d66d37ba (patch) | |
tree | cef1ef11cf26f4411741840a1ae99cbf1619122e | |
download | playersettings-17dc9a8247c35b9710741d0f23d502e7d66d37ba.tar playersettings-17dc9a8247c35b9710741d0f23d502e7d66d37ba.tar.gz playersettings-17dc9a8247c35b9710741d0f23d502e7d66d37ba.tar.bz2 playersettings-17dc9a8247c35b9710741d0f23d502e7d66d37ba.tar.xz playersettings-17dc9a8247c35b9710741d0f23d502e7d66d37ba.zip |
Add initial content
-rw-r--r-- | COPYING | 24 | ||||
-rw-r--r-- | README | 76 | ||||
-rw-r--r-- | init.lua | 176 | ||||
-rw-r--r-- | mod.conf | 5 | ||||
-rw-r--r-- | textures/playersettings_settings_button.png | bin | 0 -> 5577 bytes |
5 files changed, 281 insertions, 0 deletions
@@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to <http://unlicense.org/> @@ -0,0 +1,76 @@ +playersettings +============== + +This mod provides a GUI (via unified_inventory) that allows players to change various per-player settings. +No settings are actually included, but other mods can provide their own. + +To register a setting: + +playersettings.register("yourmodname:yoursettingname",{ + + type = "number", + -- Specifies the type of the setting to register. + -- Valid types are: + ---- "number": An integer or floating-point value. + ---- "string": A text string. + ---- "boolean": A simple yes/no checkbox. + ---- "enum": A list of possible choices. + + shortdesc = "Short Description", + -- A short (human-readable) description of the setting, to be shown as the setting name in the menu. + + longdesc = "Long Description Goes Here", + -- A longer desciption that is shown when the user selects your setting in the menu. + + default = 5, + -- The default value of the setting. + + min = 0, + -- For "number" settings: The smallest selectable value. + + max = 10, + -- For "number" settings: The largest selectable value. + + integer = true, + -- For "integer" settings: If true, entered numbers will be rounded down to the nearest integer. + + values = "some text here", + -- For "string" settings: Text to be displayed under the entry field to assist the user in selecting valid values. + + values = {"Apple", "Orange", "Banana"}, + -- For "enum" settings: A list of the possible choices. + + onjoin = function(player_name,setting_value), + -- A function to be called whenever a player joins the game. + -- 'player_name' is the name of the player that just joined. + -- 'setting_value' is the current value of the setting. + + onchange = function(player_name,old_value,new_value) + -- A function to be called when a player tries to change the setting, before the setting is actually changed. + -- Custom validation logic should go here. + -- 'player_name' is the name of the player trying to change the setting. + -- 'old_value' is the current value of the setting. + -- 'new_value' is the value the player wants to change the setting to. + -- Return true to allow the change to take place, or false (or nothing at all) to prevent the change. + + afterchange = function(player_name,old_value,new_value) + -- A function to be called after the setting is changed. + -- Code to apply the new value of the setting should go here. + -- 'player_name' is the name of the player that changed the setting. + -- 'old_value' is the old value of the setting, before it was changed. + -- 'new_value' is the value that the setting was changed to. +}) + +To set a setting (from another mod): + +playersettings.set(player_name,setting_name,new_value) +-- 'player_name' is the player to change the setting for. +-- 'setting_name' is the name of the setting to change. +-- 'new_value' is the new value of the setting. +-- Changing settings via this interface bypasses the built-in validation (such as range checking on numbers) but NOT any specified onchange or afterchange actions. + +To get the value of a setting (from another mod): + +playersettings.get(player_name,setting_name) +-- 'player_name' is the player to get the setting value from. +-- 'setting_name' is the name of the setting to get. 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) diff --git a/mod.conf b/mod.conf new file mode 100644 index 0000000..66ae225 --- /dev/null +++ b/mod.conf @@ -0,0 +1,5 @@ +name = playersettings +description = Per-Player Settings System +optional_depends = unified_inventory +author = cheapie +title = Per-Player Settings System diff --git a/textures/playersettings_settings_button.png b/textures/playersettings_settings_button.png Binary files differnew file mode 100644 index 0000000..124b098 --- /dev/null +++ b/textures/playersettings_settings_button.png |