123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317 |
- -- multihome/init.lua
- multihome = {}
- -- Load settings from minetest.conf, else set to default values
- local max = tonumber(minetest.settings:get("multihome.max")) or 10
- local compat = minetest.settings:get("multihome.compatibility") or "none"
- local import = minetest.settings:get("multihome.import") or "false"
- -- Out of range is always bad, so log as error
- if max < 2 or max > 10000 then
- minetest.log("error", "multihome.max value of " .. dump(max) .. " in minetest.conf is outside of 2 - 10000 range. Resetting to 5.")
- max = 5
- end
- -- Any other value is always bad, so log as error
- if compat ~= "none" and compat ~= "deprecate" and compat ~= "override" then
- minetest.log("error", "multihome.compatibility value of '" .. compat .. "' in minetest.conf is invalid. Valid values are: none (default), deprecate, or override. Resetting to 'none'.")
- compat = "none"
- end
- -- The "sethome" mod can differ per world, so log as warning
- if compat ~= "none" and not minetest.get_modpath("sethome") then
- minetest.log("warning", "multihome.compatibility value of '" .. compat .. "' in minetest.conf is invalid when sethome mod not present. Resetting to 'none'.")
- compat = "none"
- end
- ---
- --- Load old homes from the homes file
- ---
- local homes_file = minetest.get_worldpath() .. "/homes"
- local oldhomes = {}
- local function old_loadhomes()
- local input = io.open(homes_file, "r")
- if not input then
- return -- no longer an error
- end
- -- Iterate over all stored positions in the format "x y z player" for each line
- for pos, name in input:read("*a"):gmatch("(%S+ %S+ %S+)%s([%w_-]+)[\r\n]") do
- oldhomes[name] = minetest.string_to_pos(pos)
- end
- input:close()
- end
- old_loadhomes()
- ---
- --- API
- ---
- -- [local function] Check attribute
- local function check_attr(player)
- if not player:get_attribute("multihome") then
- player:set_attribute("multihome", minetest.serialize({}))
- end
- end
- -- [local function] Count homes
- local function count_homes(list)
- local count = 0
- for _, h in pairs(list) do
- count = count + 1
- end
- return count
- end
- -- [function] Set home
- function multihome.set(player, name, pos)
- if type(player) == "string" then
- player = minetest.get_player_by_name(player)
- end
- local pos = pos or vector.round(player:getpos())
- local homes = minetest.deserialize(player:get_attribute("multihome"))
- local home_count = count_homes(homes)
- -- If home doesn't already exist (i.e. a new home is being created), check for space.
- -- Else, if count > max (should only happen if max gets lowered), indicate how many to remove.
- if not homes[name] and home_count == max then
- return false, "Error: too many homes. Replace one by reusing an existing name, or remove one with /multihome del <name> or /delhome <name>"
- elseif home_count > max then
- return false, "Error: too many homes. Remove at least " .. dump(home_count - max) .. " with /multihome del <name> or /delhome <name>"
- end
- homes[name] = pos
- player:set_attribute("multihome", minetest.serialize(homes))
- return true, "Set home \""..name.."\" to "..minetest.pos_to_string(pos)
- end
- -- [function] Remove home
- function multihome.remove(player, name)
- if type(player) == "string" then
- player = minetest.get_player_by_name(player)
- end
- local homes = minetest.deserialize(player:get_attribute("multihome"))
- if homes[name] then
- homes[name] = nil
- player:set_attribute("multihome", minetest.serialize(homes))
- return true, "Removed home \""..name.."\""
- else
- return false, "Home \""..name.."\" does not exist!"
- end
- end
- -- [function] Get home position
- function multihome.get(player, name)
- if type(player) == "string" then
- player = minetest.get_player_by_name(player)
- end
- local homes = minetest.deserialize(player:get_attribute("multihome"))
- return homes[name]
- end
- -- [function] Get player's default home
- function multihome.get_default(player)
- if type(player) == "string" then
- player = minetest.get_player_by_name(player)
- end
- local default
- local count = 0
- local homes = minetest.deserialize(player:get_attribute("multihome"))
- for home, pos in pairs(homes) do
- count = count + 1
- default = home
- end
- if count == 1 then
- return default
- end
- end
- -- [function] List homes
- function multihome.list(player)
- if type(player) == "string" then
- player = minetest.get_player_by_name(player)
- end
- local homes = minetest.deserialize(player:get_attribute("multihome"))
- if homes then
- local list = "None"
- for name, h in pairs(homes) do
- if list == "None" then
- list = name.." "..minetest.pos_to_string(h)
- else
- list = list..", "..name.." "..minetest.pos_to_string(h)
- end
- end
- return true, "Your Homes ("..count_homes(homes).."/"..max.."): "..list
- end
- end
- -- [function] Go to home
- function multihome.go(player, name)
- if type(player) == "string" then
- player = minetest.get_player_by_name(player)
- end
- local pos = multihome.get(player, name)
- if pos then
- player:setpos(pos)
- return true, "Teleported to home \""..name.."\""
- else
- local homes = minetest.deserialize(player:get_attribute("multihome"))
- if not homes then
- return false, "Set a home using /multihome set <name> or /sethome <name>"
- else
- return false, "Invalid home \""..name.."\""
- end
- end
- end
- ---
- --- Registrations
- ---
- -- [event] On join player
- minetest.register_on_joinplayer(function(player)
- -- Check attributes
- check_attr(player)
- -- Check if homes need to be imported
- if import == "true" and (compat == "deprecate" or compat == "override")
- and player:get_attribute("multihome:imported") ~= "true" then
- local name = player:get_player_name()
- local pos = minetest.string_to_pos(player:get_attribute("sethome:home")) or oldhomes[name]
- if pos then
- -- Set multihome entry
- multihome.set(player, "default", pos)
- -- Set imported attribute
- player:set_attribute("multihome:imported", "true")
- end
- end
- end)
- -- Compatibility mode: none or deprecate
- if compat == "none" or compat == "deprecate" then
- -- [privilege] Multihome
- minetest.register_privilege("multihome", {
- description = "Can use /multihome",
- give_to_singleplayer = false,
- })
- -- [chatcommand] /multihome
- minetest.register_chatcommand("multihome", {
- description = "Manage your home points",
- params = "<action> <home name> | <set, del, go, list>, <home name>",
- privs = {creative=true},
- func = function(name, params)
- local params = params:split(" ")
- if #params == 2 and params[1] == "set" then
- return multihome.set(name, params[2])
- elseif #params == 2 and params[1] == "del" then
- return multihome.remove(name, params[2])
- elseif params[1] == "go" then
- local home = params[2]
- if not home then
- home = multihome.get_default(name)
- if not home then
- return false, "Invalid parameters (see /help multihome)"
- end
- end
- return multihome.go(name, home)
- elseif params[1] == "list" then
- return multihome.list(name)
- else
- return false, "Invalid parameters (see /help multihome)"
- end
- end,
- })
- end
- -- Compatibility mode: deprecate
- if compat == "deprecate" then
- local msg = "Deprecated, use /multihome instead"
- local function deprecate()
- return false, msg
- end
- -- [override] /home
- minetest.override_chatcommand("home", {description = msg, func = deprecate})
- -- [override] /sethome
- minetest.override_chatcommand("sethome", {description = msg, func = deprecate})
- end
- -- Compatibility mode: override
- if compat == "override" then
- -- [override] /home
- minetest.override_chatcommand("home", {
- description = "Teleport you to one of your home points (related: /sethome, /delhome, /listhomes)",
- params = "<home name>",
- func = function(name, param)
- if param and param ~= "" then
- return multihome.go(name, param)
- else
- local home = multihome.get_default(name)
- if home then
- return multihome.go(name, home)
- end
- return false, "Invalid parameters (see /help home or /listhomes)"
- end
- end,
- })
- -- [override] /sethome
- minetest.override_chatcommand("sethome", {
- description = "Set or update one of your home points (related: /home, /delhome, /listhomes)",
- params = "<home name>",
- func = function(name, param)
- if param and param ~= "" then
- return multihome.set(name, param)
- else
- return false, "Invalid parameters (see /help sethome)"
- end
- end,
- })
- -- [chatcommand] /delhome
- minetest.register_chatcommand("delhome", {
- description = "Delete one of your home points (related: /home, /sethome, /listhomes)",
- params = "<home name>",
- privs = {creative=true},
- func = function(name, param)
- if param and param ~= "" then
- return multihome.remove(name, param)
- else
- return false, "Invalid parameters (see /help delhome or /listhomes)"
- end
- end,
- })
- -- [chatcommand] /listhomes
- minetest.register_chatcommand("listhomes", {
- description = "List all of your home points (related: /home, /sethome, /delhome)",
- privs = {creative=true},
- func = function(name)
- return multihome.list(name)
- end,
- })
- end
|