diff options
Diffstat (limited to 'builtin')
28 files changed, 1588 insertions, 820 deletions
diff --git a/builtin/client/chatcommands.lua b/builtin/client/chatcommands.lua index 0e8d4dd03..a563a6627 100644 --- a/builtin/client/chatcommands.lua +++ b/builtin/client/chatcommands.lua @@ -1,6 +1,5 @@ -- Minetest: builtin/client/chatcommands.lua - core.register_on_sending_chat_message(function(message) if message:sub(1,2) == ".." then return false @@ -8,7 +7,7 @@ core.register_on_sending_chat_message(function(message) local first_char = message:sub(1,1) if first_char == "/" or first_char == "." then - core.display_chat_message(core.gettext("issued command: ") .. message) + core.display_chat_message(core.gettext("Issued command: ") .. message) end if first_char ~= "." then @@ -19,7 +18,7 @@ core.register_on_sending_chat_message(function(message) param = param or "" if not cmd then - core.display_chat_message(core.gettext("-!- Empty command")) + core.display_chat_message("-!- " .. core.gettext("Empty command.")) return true end @@ -36,7 +35,7 @@ core.register_on_sending_chat_message(function(message) core.display_chat_message(result) end else - core.display_chat_message(core.gettext("-!- Invalid command: ") .. cmd) + core.display_chat_message("-!- " .. core.gettext("Invalid command: ") .. cmd) end return true @@ -66,7 +65,7 @@ core.register_chatcommand("clear_chat_queue", { description = core.gettext("Clear the out chat queue"), func = function(param) core.clear_out_chat_queue() - return true, core.gettext("The out chat queue is now empty") + return true, core.gettext("The out chat queue is now empty.") end, }) diff --git a/builtin/client/death_formspec.lua b/builtin/client/death_formspec.lua index e755ac5c1..7df0cbd75 100644 --- a/builtin/client/death_formspec.lua +++ b/builtin/client/death_formspec.lua @@ -2,7 +2,7 @@ -- handled by the engine. core.register_on_death(function() - core.display_chat_message("You died.") + core.display_chat_message(core.gettext("You died.")) local formspec = "size[11,5.5]bgcolor[#320000b4;true]" .. "label[4.85,1.35;" .. fgettext("You died") .. "]button_exit[4,3;3,0.5;btn_respawn;".. fgettext("Respawn") .."]" diff --git a/builtin/common/chatcommands.lua b/builtin/common/chatcommands.lua index 52edda659..c945e7bdb 100644 --- a/builtin/common/chatcommands.lua +++ b/builtin/common/chatcommands.lua @@ -1,5 +1,9 @@ -- Minetest: builtin/common/chatcommands.lua +-- For server-side translations (if INIT == "game") +-- Otherwise, use core.gettext +local S = core.get_translator("__builtin") + core.registered_chatcommands = {} function core.register_chatcommand(cmd, def) @@ -29,25 +33,12 @@ function core.override_chatcommand(name, redefinition) core.registered_chatcommands[name] = chatcommand end -local cmd_marker = "/" - -local function gettext(...) - return ... -end - -local function gettext_replace(text, replace) - return text:gsub("$1", replace) -end - - -if INIT == "client" then - cmd_marker = "." - gettext = core.gettext - gettext_replace = fgettext_ne -end - local function do_help_cmd(name, param) local function format_help_line(cmd, def) + local cmd_marker = "/" + if INIT == "client" then + cmd_marker = "." + end local msg = core.colorize("#00ffff", cmd_marker .. cmd) if def.params and def.params ~= "" then msg = msg .. " " .. def.params @@ -65,9 +56,21 @@ local function do_help_cmd(name, param) end end table.sort(cmds) - return true, gettext("Available commands: ") .. table.concat(cmds, " ") .. "\n" - .. gettext_replace("Use '$1help <cmd>' to get more information," - .. " or '$1help all' to list everything.", cmd_marker) + local msg + if INIT == "game" then + msg = S("Available commands: @1", + table.concat(cmds, " ")) .. "\n" + .. S("Use '/help <cmd>' to get more " + .. "information, or '/help all' to list " + .. "everything.") + else + msg = core.gettext("Available commands: ") + .. table.concat(cmds, " ") .. "\n" + .. core.gettext("Use '.help <cmd>' to get more " + .. "information, or '.help all' to list " + .. "everything.") + end + return true, msg elseif param == "all" then local cmds = {} for cmd, def in pairs(core.registered_chatcommands) do @@ -76,19 +79,31 @@ local function do_help_cmd(name, param) end end table.sort(cmds) - return true, gettext("Available commands:").."\n"..table.concat(cmds, "\n") + local msg + if INIT == "game" then + msg = S("Available commands:") + else + msg = core.gettext("Available commands:") + end + return true, msg.."\n"..table.concat(cmds, "\n") elseif INIT == "game" and param == "privs" then local privs = {} for priv, def in pairs(core.registered_privileges) do privs[#privs + 1] = priv .. ": " .. def.description end table.sort(privs) - return true, "Available privileges:\n"..table.concat(privs, "\n") + return true, S("Available privileges:").."\n"..table.concat(privs, "\n") else local cmd = param local def = core.registered_chatcommands[cmd] if not def then - return false, gettext("Command not available: ")..cmd + local msg + if INIT == "game" then + msg = S("Command not available: @1", cmd) + else + msg = core.gettext("Command not available: ") .. cmd + end + return false, msg else return true, format_help_line(cmd, def) end @@ -97,16 +112,16 @@ end if INIT == "client" then core.register_chatcommand("help", { - params = gettext("[all | <cmd>]"), - description = gettext("Get help for commands"), + params = core.gettext("[all | <cmd>]"), + description = core.gettext("Get help for commands"), func = function(param) return do_help_cmd(nil, param) end, }) else core.register_chatcommand("help", { - params = "[all | privs | <cmd>]", - description = "Get help for commands or list privileges", + params = S("[all | privs | <cmd>]"), + description = S("Get help for commands or list privileges"), func = do_help_cmd, }) end diff --git a/builtin/common/information_formspecs.lua b/builtin/common/information_formspecs.lua index 8afa5bc87..e814b4c43 100644 --- a/builtin/common/information_formspecs.lua +++ b/builtin/common/information_formspecs.lua @@ -20,7 +20,8 @@ local LIST_FORMSPEC_DESCRIPTION = [[ button_exit[5,7;3,1;quit;%s] ]] -local formspec_escape = core.formspec_escape +local F = core.formspec_escape +local S = core.get_translator("__builtin") local check_player_privs = core.check_player_privs @@ -51,22 +52,23 @@ core.after(0, load_mod_command_tree) local function build_chatcommands_formspec(name, sel, copy) local rows = {} - rows[1] = "#FFF,0,Command,Parameters" + rows[1] = "#FFF,0,"..F(S("Command"))..","..F(S("Parameters")) - local description = "For more information, click on any entry in the list.\n" .. - "Double-click to copy the entry to the chat history." + local description = S("For more information, click on " + .. "any entry in the list.").. "\n" .. + S("Double-click to copy the entry to the chat history.") for i, data in ipairs(mod_cmds) do - rows[#rows + 1] = COLOR_BLUE .. ",0," .. formspec_escape(data[1]) .. "," + rows[#rows + 1] = COLOR_BLUE .. ",0," .. F(data[1]) .. "," for j, cmds in ipairs(data[2]) do local has_priv = check_player_privs(name, cmds[2].privs) rows[#rows + 1] = ("%s,1,%s,%s"):format( has_priv and COLOR_GREEN or COLOR_GRAY, - cmds[1], formspec_escape(cmds[2].params)) + cmds[1], F(cmds[2].params)) if sel == #rows then description = cmds[2].description if copy then - core.chat_send_player(name, ("Command: %s %s"):format( + core.chat_send_player(name, S("Command: @1 @2", core.colorize("#0FF", "/" .. cmds[1]), cmds[2].params)) end end @@ -74,9 +76,9 @@ local function build_chatcommands_formspec(name, sel, copy) end return LIST_FORMSPEC_DESCRIPTION:format( - "Available commands: (see also: /help <cmd>)", + F(S("Available commands: (see also: /help <cmd>)")), table.concat(rows, ","), sel or 0, - description, "Close" + F(description), F(S("Close")) ) end @@ -91,19 +93,19 @@ local function build_privs_formspec(name) table.sort(privs, function(a, b) return a[1] < b[1] end) local rows = {} - rows[1] = "#FFF,0,Privilege,Description" + rows[1] = "#FFF,0,"..F(S("Privilege"))..","..F(S("Description")) local player_privs = core.get_player_privs(name) for i, data in ipairs(privs) do rows[#rows + 1] = ("%s,0,%s,%s"):format( player_privs[data[1]] and COLOR_GREEN or COLOR_GRAY, - data[1], formspec_escape(data[2].description)) + data[1], F(data[2].description)) end return LIST_FORMSPEC:format( - "Available privileges:", + F(S("Available privileges:")), table.concat(rows, ","), - "Close" + F(S("Close")) ) end @@ -115,7 +117,7 @@ core.register_on_player_receive_fields(function(player, formname, fields) return end - local event = minetest.explode_table_event(fields.list) + local event = core.explode_table_event(fields.list) if event.type ~= "INV" then local name = player:get_player_name() core.show_formspec(name, "__builtin:help_cmds", diff --git a/builtin/fstk/tabview.lua b/builtin/fstk/tabview.lua index 3715e231b..424d329fb 100644 --- a/builtin/fstk/tabview.lua +++ b/builtin/fstk/tabview.lua @@ -58,26 +58,20 @@ end -------------------------------------------------------------------------------- local function get_formspec(self) - local formspec = "" + if self.hidden or (self.parent ~= nil and self.parent.hidden) then + return "" + end + local tab = self.tablist[self.last_tab_index] - if not self.hidden and (self.parent == nil or not self.parent.hidden) then + local content, prepend = tab.get_formspec(self, tab.name, tab.tabdata, tab.tabsize) - if self.parent == nil then - local tsize = self.tablist[self.last_tab_index].tabsize or - {width=self.width, height=self.height} - formspec = formspec .. - string.format("size[%f,%f,%s]",tsize.width,tsize.height, - dump(self.fixed_size)) - end - formspec = formspec .. self:tab_header() - formspec = formspec .. - self.tablist[self.last_tab_index].get_formspec( - self, - self.tablist[self.last_tab_index].name, - self.tablist[self.last_tab_index].tabdata, - self.tablist[self.last_tab_index].tabsize - ) + if self.parent == nil and not prepend then + local tsize = tab.tabsize or {width=self.width, height=self.height} + prepend = string.format("size[%f,%f,%s]", tsize.width, tsize.height, + dump(self.fixed_size)) end + + local formspec = (prepend or "") .. self:tab_header() .. content return formspec end @@ -97,14 +91,9 @@ local function handle_buttons(self,fields) return true end - if self.tablist[self.last_tab_index].button_handler ~= nil then - return - self.tablist[self.last_tab_index].button_handler( - self, - fields, - self.tablist[self.last_tab_index].name, - self.tablist[self.last_tab_index].tabdata - ) + local tab = self.tablist[self.last_tab_index] + if tab.button_handler ~= nil then + return tab.button_handler(self, fields, tab.name, tab.tabdata) end return false @@ -122,14 +111,9 @@ local function handle_events(self,event) return true end - if self.tablist[self.last_tab_index].evt_handler ~= nil then - return - self.tablist[self.last_tab_index].evt_handler( - self, - event, - self.tablist[self.last_tab_index].name, - self.tablist[self.last_tab_index].tabdata - ) + local tab = self.tablist[self.last_tab_index] + if tab.evt_handler ~= nil then + return tab.evt_handler(self, event, tab.name, tab.tabdata) end return false diff --git a/builtin/game/chat.lua b/builtin/game/chat.lua index 945707623..bf2d7851e 100644 --- a/builtin/game/chat.lua +++ b/builtin/game/chat.lua @@ -1,5 +1,7 @@ -- Minetest: builtin/game/chat.lua +local S = core.get_translator("__builtin") + -- Helper function that implements search and replace without pattern matching -- Returns the string and a boolean indicating whether or not the string was modified local function safe_gsub(s, replace, with) @@ -45,6 +47,8 @@ end core.chatcommands = core.registered_chatcommands -- BACKWARDS COMPATIBILITY +local msg_time_threshold = + tonumber(core.settings:get("chatcommand_msg_time_threshold")) or 0.1 core.register_on_chat_message(function(name, message) if message:sub(1,1) ~= "/" then return @@ -52,7 +56,7 @@ core.register_on_chat_message(function(name, message) local cmd, param = string.match(message, "^/([^ ]+) *(.*)") if not cmd then - core.chat_send_player(name, "-!- Empty command") + core.chat_send_player(name, "-!- "..S("Empty command.")) return true end @@ -65,15 +69,17 @@ core.register_on_chat_message(function(name, message) local cmd_def = core.registered_chatcommands[cmd] if not cmd_def then - core.chat_send_player(name, "-!- Invalid command: " .. cmd) + core.chat_send_player(name, "-!- "..S("Invalid command: @1", cmd)) return true end local has_privs, missing_privs = core.check_player_privs(name, cmd_def.privs) if has_privs then core.set_last_run_mod(cmd_def.mod_origin) + local t_before = minetest.get_us_time() local success, result = cmd_def.func(name, param) + local delay = (minetest.get_us_time() - t_before) / 1000000 if success == false and result == nil then - core.chat_send_player(name, "-!- Invalid command usage") + core.chat_send_player(name, "-!- "..S("Invalid command usage.")) local help_def = core.registered_chatcommands["help"] if help_def then local _, helpmsg = help_def.func(name, cmd) @@ -81,13 +87,26 @@ core.register_on_chat_message(function(name, message) core.chat_send_player(name, helpmsg) end end - elseif result then - core.chat_send_player(name, result) + else + if delay > msg_time_threshold then + -- Show how much time it took to execute the command + if result then + result = result .. + minetest.colorize("#f3d2ff", " (%.5g s)"):format(delay) + else + result = minetest.colorize("#f3d2ff", + "Command execution took %.5f s"):format(delay) + end + end + if result then + core.chat_send_player(name, result) + end end else - core.chat_send_player(name, "You don't have permission" - .. " to run this command (missing privileges: " - .. table.concat(missing_privs, ", ") .. ")") + core.chat_send_player(name, + S("You don't have permission to run this command " + .. "(missing privileges: @1).", + table.concat(missing_privs, ", "))) end return true -- Handled chat message end) @@ -107,12 +126,13 @@ local function parse_range_str(player_name, str) if args[1] == "here" then p1, p2 = core.get_player_radius_area(player_name, tonumber(args[2])) if p1 == nil then - return false, "Unable to get player " .. player_name .. " position" + return false, S("Unable to get position of player @1.", player_name) end else p1, p2 = core.string_to_area(str) if p1 == nil then - return false, "Incorrect area format. Expected: (x1,y1,z1) (x2,y2,z2)" + return false, S("Incorrect area format. " + .. "Expected: (x1,y1,z1) (x2,y2,z2)") end end @@ -123,9 +143,9 @@ end -- Chat commands -- core.register_chatcommand("me", { - params = "<action>", - description = "Show chat action (e.g., '/me orders a pizza' displays" - .. " '<player name> orders a pizza')", + params = S("<action>"), + description = S("Show chat action (e.g., '/me orders a pizza' " + .. "displays '<player name> orders a pizza')"), privs = {shout=true}, func = function(name, param) core.chat_send_all("* " .. name .. " " .. param) @@ -134,43 +154,44 @@ core.register_chatcommand("me", { }) core.register_chatcommand("admin", { - description = "Show the name of the server owner", + description = S("Show the name of the server owner"), func = function(name) local admin = core.settings:get("name") if admin then - return true, "The administrator of this server is " .. admin .. "." + return true, S("The administrator of this server is @1.", admin) else - return false, "There's no administrator named in the config file." + return false, S("There's no administrator named " + .. "in the config file.") end end, }) core.register_chatcommand("privs", { - params = "[<name>]", - description = "Show privileges of yourself or another player", + params = S("[<name>]"), + description = S("Show privileges of yourself or another player"), func = function(caller, param) param = param:trim() local name = (param ~= "" and param or caller) if not core.player_exists(name) then - return false, "Player " .. name .. " does not exist." + return false, S("Player @1 does not exist.", name) end - return true, "Privileges of " .. name .. ": " - .. core.privs_to_string( - core.get_player_privs(name), ", ") + return true, S("Privileges of @1: @2", name, + core.privs_to_string( + core.get_player_privs(name), ", ")) end, }) core.register_chatcommand("haspriv", { - params = "<privilege>", - description = "Return list of all online players with privilege.", + params = S("<privilege>"), + description = S("Return list of all online players with privilege"), privs = {basic_privs = true}, func = function(caller, param) param = param:trim() if param == "" then - return false, "Invalid parameters (see /help haspriv)" + return false, S("Invalid parameters (see /help haspriv).") end if not core.registered_privileges[param] then - return false, "Unknown privilege!" + return false, S("Unknown privilege!") end local privs = core.string_to_privs(param) local players_with_priv = {} @@ -180,19 +201,20 @@ core.register_chatcommand("haspriv", { table.insert(players_with_priv, player_name) end end - return true, "Players online with the \"" .. param .. "\" privilege: " .. - table.concat(players_with_priv, ", ") + return true, S("Players online with the \"@1\" privilege: @2", + param, + table.concat(players_with_priv, ", ")) end }) local function handle_grant_command(caller, grantname, grantprivstr) local caller_privs = core.get_player_privs(caller) if not (caller_privs.privs or caller_privs.basic_privs) then - return false, "Your privileges are insufficient." + return false, S("Your privileges are insufficient.") end if not core.get_auth_handler().get_auth(grantname) then - return false, "Player " .. grantname .. " does not exist." + return false, S("Player @1 does not exist.", grantname) end local grantprivs = core.string_to_privs(grantprivstr) if grantprivstr == "all" then @@ -204,10 +226,10 @@ local function handle_grant_command(caller, grantname, grantprivstr) core.string_to_privs(core.settings:get("basic_privs") or "interact,shout") for priv, _ in pairs(grantprivs) do if not basic_privs[priv] and not caller_privs.privs then - return false, "Your privileges are insufficient." + return false, S("Your privileges are insufficient.") end if not core.registered_privileges[priv] then - privs_unknown = privs_unknown .. "Unknown privilege: " .. priv .. "\n" + privs_unknown = privs_unknown .. S("Unknown privilege: @1", priv) .. "\n" end privs[priv] = true end @@ -221,33 +243,33 @@ local function handle_grant_command(caller, grantname, grantprivstr) core.set_player_privs(grantname, privs) core.log("action", caller..' granted ('..core.privs_to_string(grantprivs, ', ')..') privileges to '..grantname) if grantname ~= caller then - core.chat_send_player(grantname, caller - .. " granted you privileges: " - .. core.privs_to_string(grantprivs, ' ')) + core.chat_send_player(grantname, + S("@1 granted you privileges: @2", caller, + core.privs_to_string(grantprivs, ' '))) end - return true, "Privileges of " .. grantname .. ": " - .. core.privs_to_string( - core.get_player_privs(grantname), ' ') + return true, S("Privileges of @1: @2", grantname, + core.privs_to_string( + core.get_player_privs(grantname), ' ')) end core.register_chatcommand("grant", { - params = "<name> (<privilege> | all)", - description = "Give privileges to player", + params = S("<name> (<privilege> | all)"), + description = S("Give privileges to player"), func = function(name, param) local grantname, grantprivstr = string.match(param, "([^ ]+) (.+)") if not grantname or not grantprivstr then - return false, "Invalid parameters (see /help grant)" + return false, S("Invalid parameters (see /help grant).") end return handle_grant_command(name, grantname, grantprivstr) end, }) core.register_chatcommand("grantme", { - params = "<privilege> | all", - description = "Grant privileges to yourself", + params = S("<privilege> | all"), + description = S("Grant privileges to yourself"), func = function(name, param) if param == "" then - return false, "Invalid parameters (see /help grantme)" + return false, S("Invalid parameters (see /help grantme).") end return handle_grant_command(name, name, param) end, @@ -256,11 +278,11 @@ core.register_chatcommand("grantme", { local function handle_revoke_command(caller, revokename, revokeprivstr) local caller_privs = core.get_player_privs(caller) if not (caller_privs.privs or caller_privs.basic_privs) then - return false, "Your privileges are insufficient." + return false, S("Your privileges are insufficient.") end if not core.get_auth_handler().get_auth(revokename) then - return false, "Player " .. revokename .. " does not exist." + return false, S("Player @1 does not exist.", revokename) end local revokeprivs = core.string_to_privs(revokeprivstr) @@ -269,7 +291,7 @@ local function handle_revoke_command(caller, revokename, revokeprivstr) core.string_to_privs(core.settings:get("basic_privs") or "interact,shout") for priv, _ in pairs(revokeprivs) do if not basic_privs[priv] and not caller_privs.privs then - return false, "Your privileges are insufficient." + return false, S("Your privileges are insufficient.") end end @@ -292,43 +314,43 @@ local function handle_revoke_command(caller, revokename, revokeprivstr) ..core.privs_to_string(revokeprivs, ', ') ..') privileges from '..revokename) if revokename ~= caller then - core.chat_send_player(revokename, caller - .. " revoked privileges from you: " - .. core.privs_to_string(revokeprivs, ' ')) + core.chat_send_player(revokename, + S("@1 revoked privileges from you: @2", caller, + core.privs_to_string(revokeprivs, ' '))) end - return true, "Privileges of " .. revokename .. ": " - .. core.privs_to_string( - core.get_player_privs(revokename), ' ') + return true, S("Privileges of @1: @2", revokename, + core.privs_to_string( + core.get_player_privs(revokename), ' ')) end core.register_chatcommand("revoke", { - params = "<name> (<privilege> | all)", - description = "Remove privileges from player", + params = S("<name> (<privilege> | all)"), + description = S("Remove privileges from player"), privs = {}, func = function(name, param) local revokename, revokeprivstr = string.match(param, "([^ ]+) (.+)") if not revokename or not revokeprivstr then - return false, "Invalid parameters (see /help revoke)" + return false, S("Invalid parameters (see /help revoke).") end return handle_revoke_command(name, revokename, revokeprivstr) end, }) core.register_chatcommand("revokeme", { - params = "<privilege> | all", - description = "Revoke privileges from yourself", + params = S("<privilege> | all"), + description = S("Revoke privileges from yourself"), privs = {}, func = function(name, param) if param == "" then - return false, "Invalid parameters (see /help revokeme)" + return false, S("Invalid parameters (see /help revokeme).") end return handle_revoke_command(name, name, param) end, }) core.register_chatcommand("setpassword", { - params = "<name> <password>", - description = "Set player's password", + params = S("<name> <password>"), + description = S("Set player's password"), privs = {password=true}, func = function(name, param) local toname, raw_password = string.match(param, "^([^ ]+) +(.+)$") @@ -338,207 +360,197 @@ core.register_chatcommand("setpassword", { end if not toname then - return false, "Name field required" + return false, S("Name field required.") end - local act_str_past, act_str_pres + local msg_chat, msg_log, msg_ret if not raw_password then core.set_player_password(toname, "") - act_str_past = "cleared" - act_str_pres = "clears" + msg_chat = S("Your password was cleared by @1.", name) + msg_log = name .. " clears password of " .. toname .. "." + msg_ret = S("Password of player \"@1\" cleared.", toname) else core.set_player_password(toname, core.get_password_hash(toname, raw_password)) - act_str_past = "set" - act_str_pres = "sets" + msg_chat = S("Your password was set by @1.", name) + msg_log = name .. " sets password of " .. toname .. "." + msg_ret = S("Password of player \"@1\" set.", toname) end if toname ~= name then - core.chat_send_player(toname, "Your password was " - .. act_str_past .. " by " .. name) + core.chat_send_player(toname, msg_chat) end - core.log("action", name .. " " .. act_str_pres .. - " password of " .. toname .. ".") + core.log("action", msg_log) - return true, "Password of player \"" .. toname .. "\" " .. act_str_past + return true, msg_ret end, }) core.register_chatcommand("clearpassword", { - params = "<name>", - description = "Set empty password for a player", + params = S("<name>"), + description = S("Set empty password for a player"), privs = {password=true}, func = function(name, param) local toname = param if toname == "" then - return false, "Name field required" + return false, S("Name field required.") end core.set_player_password(toname, '') core.log("action", name .. " clears password of " .. toname .. ".") - return true, "Password of player \"" .. toname .. "\" cleared" + return true, S("Password of player \"@1\" cleared.", toname) end, }) core.register_chatcommand("auth_reload", { params = "", - description = "Reload authentication data", + description = S("Reload authentication data"), privs = {server=true}, func = function(name, param) local done = core.auth_reload() - return done, (done and "Done." or "Failed.") + return done, (done and S("Done.") or S("Failed.")) end, }) core.register_chatcommand("remove_player", { - params = "<name>", - description = "Remove a player's data", + params = S("<name>"), + description = S("Remove a player's data"), privs = {server=true}, func = function(name, param) local toname = param if toname == "" then - return false, "Name field required" + return false, S("Name field required.") end local rc = core.remove_player(toname) if rc == 0 then core.log("action", name .. " removed player data of " .. toname .. ".") - return true, "Player \"" .. toname .. "\" removed." + return true, S("Player \"@1\" removed.", toname) elseif rc == 1 then - return true, "No such player \"" .. toname .. "\" to remove." + return true, S("No such player \"@1\" to remove.", toname) elseif rc == 2 then - return true, "Player \"" .. toname .. "\" is connected, cannot remove." + return true, S("Player \"@1\" is connected, cannot remove.", toname) end - return false, "Unhandled remove_player return code " .. rc .. "" + return false, S("Unhandled remove_player return code @1.", tostring(rc)) end, }) -core.register_chatcommand("teleport", { - params = "<X>,<Y>,<Z> | <to_name> | (<name> <X>,<Y>,<Z>) | (<name> <to_name>)", - description = "Teleport to position or player", - privs = {teleport=true}, - func = function(name, param) - -- Returns (pos, true) if found, otherwise (pos, false) - local function find_free_position_near(pos) - local tries = { - {x=1,y=0,z=0}, - {x=-1,y=0,z=0}, - {x=0,y=0,z=1}, - {x=0,y=0,z=-1}, - } - for _, d in ipairs(tries) do - local p = {x = pos.x+d.x, y = pos.y+d.y, z = pos.z+d.z} - local n = core.get_node_or_nil(p) - if n and n.name then - local def = core.registered_nodes[n.name] - if def and not def.walkable then - return p, true - end - end + +-- pos may be a non-integer position +local function find_free_position_near(pos) + local tries = { + {x=1, y=0, z=0}, + {x=-1, y=0, z=0}, + {x=0, y=0, z=1}, + {x=0, y=0, z=-1}, + } + for _, d in ipairs(tries) do + local p = vector.add(pos, d) + local n = core.get_node_or_nil(p) + if n then + local def = core.registered_nodes[n.name] + if def and not def.walkable then + return p end - return pos, false end + end + return pos +end + +-- Teleports player <name> to <p> if possible +local function teleport_to_pos(name, p) + local lm = 31000 + if p.x < -lm or p.x > lm or p.y < -lm or p.y > lm + or p.z < -lm or p.z > lm then + return false, S("Cannot teleport out of map bounds!") + end + local teleportee = core.get_player_by_name(name) + if not teleportee then + return false, S("Cannot get player with name @1.", name) + end + if teleportee:get_attach() then + return false, S("Cannot teleport, @1 " .. + "is attached to an object!", name) + end + teleportee:set_pos(p) + return true, S("Teleporting @1 to @2.", name, core.pos_to_string(p, 1)) +end + +-- Teleports player <name> next to player <target_name> if possible +local function teleport_to_player(name, target_name) + if name == target_name then + return false, S("One does not teleport to oneself.") + end + local teleportee = core.get_player_by_name(name) + if not teleportee then + return false, S("Cannot get teleportee with name @1.", name) + end + if teleportee:get_attach() then + return false, S("Cannot teleport, @1 " .. + "is attached to an object!", name) + end + local target = core.get_player_by_name(target_name) + if not target then + return false, S("Cannot get target player with name @1.", target_name) + end + local p = find_free_position_near(target:get_pos()) + teleportee:set_pos(p) + return true, S("Teleporting @1 to @2 at @3.", name, target_name, + core.pos_to_string(p, 1)) +end +core.register_chatcommand("teleport", { + params = S("<X>,<Y>,<Z> | <to_name> | <name> <X>,<Y>,<Z> | <name> <to_name>"), + description = S("Teleport to position or player"), + privs = {teleport=true}, + func = function(name, param) local p = {} - p.x, p.y, p.z = string.match(param, "^([%d.-]+)[, ] *([%d.-]+)[, ] *([%d.-]+)$") - p.x = tonumber(p.x) - p.y = tonumber(p.y) - p.z = tonumber(p.z) + p.x, p.y, p.z = param:match("^([%d.-]+)[, ] *([%d.-]+)[, ] *([%d.-]+)$") + p = vector.apply(p, tonumber) if p.x and p.y and p.z then - - local lm = 31000 - if p.x < -lm or p.x > lm or p.y < -lm or p.y > lm or p.z < -lm or p.z > lm then - return false, "Cannot teleport out of map bounds!" - end - local teleportee = core.get_player_by_name(name) - if teleportee then - if teleportee:get_attach() then - return false, "Can't teleport, you're attached to an object!" - end - teleportee:set_pos(p) - return true, "Teleporting to "..core.pos_to_string(p) - end + return teleport_to_pos(name, p) end local target_name = param:match("^([^ ]+)$") - local teleportee = core.get_player_by_name(name) - - p = nil if target_name then - local target = core.get_player_by_name(target_name) - if target then - p = target:get_pos() - end - end - - if teleportee and p then - if teleportee:get_attach() then - return false, "Can't teleport, you're attached to an object!" - end - p = find_free_position_near(p) - teleportee:set_pos(p) - return true, "Teleporting to " .. target_name - .. " at "..core.pos_to_string(p) + return teleport_to_player(name, target_name) end - if not core.check_player_privs(name, {bring=true}) then - return false, "You don't have permission to teleport other players (missing bring privilege)" - end + local has_bring_priv = core.check_player_privs(name, {bring=true}) + local missing_bring_msg = S("You don't have permission to teleport " .. + "other players (missing privilege: @1).", "bring") - teleportee = nil - p = {} local teleportee_name teleportee_name, p.x, p.y, p.z = param:match( "^([^ ]+) +([%d.-]+)[, ] *([%d.-]+)[, ] *([%d.-]+)$") - p.x, p.y, p.z = tonumber(p.x), tonumber(p.y), tonumber(p.z) - if teleportee_name then - teleportee = core.get_player_by_name(teleportee_name) - end - if teleportee and p.x and p.y and p.z then - if teleportee:get_attach() then - return false, "Can't teleport, player is attached to an object!" + p = vector.apply(p, tonumber) + if teleportee_name and p.x and p.y and p.z then + if not has_bring_priv then + return false, missing_bring_msg end - teleportee:set_pos(p) - return true, "Teleporting " .. teleportee_name - .. " to " .. core.pos_to_string(p) + return teleport_to_pos(teleportee_name, p) end - teleportee = nil - p = nil teleportee_name, target_name = string.match(param, "^([^ ]+) +([^ ]+)$") - if teleportee_name then - teleportee = core.get_player_by_name(teleportee_name) - end - if target_name then - local target = core.get_player_by_name(target_name) - if target then - p = target:get_pos() + if teleportee_name and target_name then + if not has_bring_priv then + return false, missing_bring_msg end - end - if teleportee and p then - if teleportee:get_attach() then - return false, "Can't teleport, player is attached to an object!" - end - p = find_free_position_near(p) - teleportee:set_pos(p) - return true, "Teleporting " .. teleportee_name - .. " to " .. target_name - .. " at " .. core.pos_to_string(p) + return teleport_to_player(teleportee_name, target_name) end - return false, 'Invalid parameters ("' .. param - .. '") or player not found (see /help teleport)' + return false end, }) core.register_chatcommand("set", { - params = "([-n] <name> <value>) | <name>", - description = "Set or read server configuration setting", + params = S("([-n] <name> <value>) | <name>"), + description = S("Set or read server configuration setting"), privs = {server=true}, func = function(name, param) local arg, setname, setvalue = string.match(param, "(-[n]) ([^ ]+) (.+)") @@ -550,22 +562,23 @@ core.register_chatcommand("set", { setname, setvalue = string.match(param, "([^ ]+) (.+)") if setname and setvalue then if not core.settings:get(setname) then - return false, "Failed. Use '/set -n <name> <value>' to create a new setting." + return false, S("Failed. Use '/set -n <name> <value>' " + .. "to create a new setting.") end core.settings:set(setname, setvalue) - return true, setname .. " = " .. setvalue + return true, S("@1 = @2", setname, setvalue) end setname = string.match(param, "([^ ]+)") if setname then setvalue = core.settings:get(setname) if not setvalue then - setvalue = "<not set>" + setvalue = S("<not set>") end - return true, setname .. " = " .. setvalue + return true, S("@1 = @2", setname, setvalue) end - return false, "Invalid parameters (see /help set)." + return false, S("Invalid parameters (see /help set).") end, }) @@ -578,26 +591,27 @@ local function emergeblocks_callback(pos, action, num_calls_remaining, ctx) if ctx.current_blocks == ctx.total_blocks then core.chat_send_player(ctx.requestor_name, - string.format("Finished emerging %d blocks in %.2fms.", - ctx.total_blocks, (os.clock() - ctx.start_time) * 1000)) + S("Finished emerging @1 blocks in @2ms.", + ctx.total_blocks, + string.format("%.2f", (os.clock() - ctx.start_time) * 1000))) end end local function emergeblocks_progress_update(ctx) if ctx.current_blocks ~= ctx.total_blocks then core.chat_send_player(ctx.requestor_name, - string.format("emergeblocks update: %d/%d blocks emerged (%.1f%%)", + S("emergeblocks update: @1/@2 blocks emerged (@3%)", ctx.current_blocks, ctx.total_blocks, - (ctx.current_blocks / ctx.total_blocks) * 100)) + string.format("%.1f", (ctx.current_blocks / ctx.total_blocks) * 100))) core.after(2, emergeblocks_progress_update, ctx) end end core.register_chatcommand("emergeblocks", { - params = "(here [<radius>]) | (<pos1> <pos2>)", - description = "Load (or, if nonexistent, generate) map blocks " - .. "contained in area pos1 to pos2 (<pos1> and <pos2> must be in parentheses)", + params = S("(here [<radius>]) | (<pos1> <pos2>)"), + description = S("Load (or, if nonexistent, generate) map blocks contained in " + .. "area pos1 to pos2 (<pos1> and <pos2> must be in parentheses)"), privs = {server=true}, func = function(name, param) local p1, p2 = parse_range_str(name, param) @@ -615,15 +629,15 @@ core.register_chatcommand("emergeblocks", { core.emerge_area(p1, p2, emergeblocks_callback, context) core.after(2, emergeblocks_progress_update, context) - return true, "Started emerge of area ranging from " .. - core.pos_to_string(p1, 1) .. " to " .. core.pos_to_string(p2, 1) + return true, S("Started emerge of area ranging from @1 to @2.", + core.pos_to_string(p1, 1), core.pos_to_string(p2, 1)) end, }) core.register_chatcommand("deleteblocks", { - params = "(here [<radius>]) | (<pos1> <pos2>)", - description = "Delete map blocks contained in area pos1 to pos2 " - .. "(<pos1> and <pos2> must be in parentheses)", + params = S("(here [<radius>]) | (<pos1> <pos2>)"), + description = S("Delete map blocks contained in area pos1 to pos2 " + .. "(<pos1> and <pos2> must be in parentheses)"), privs = {server=true}, func = function(name, param) local p1, p2 = parse_range_str(name, param) @@ -632,18 +646,20 @@ core.register_chatcommand("deleteblocks", { end if core.delete_area(p1, p2) then - return true, "Successfully cleared area ranging from " .. - core.pos_to_string(p1, 1) .. " to " .. core.pos_to_string(p2, 1) + return true, S("Successfully cleared area " + .. "ranging from @1 to @2.", + core.pos_to_string(p1, 1), core.pos_to_string(p2, 1)) else - return false, "Failed to clear one or more blocks in area" + return false, S("Failed to clear one or more " + .. "blocks in area.") end end, }) core.register_chatcommand("fixlight", { - params = "(here [<radius>]) | (<pos1> <pos2>)", - description = "Resets lighting in the area between pos1 and pos2 " - .. "(<pos1> and <pos2> must be in parentheses)", + params = S("(here [<radius>]) | (<pos1> <pos2>)"), + description = S("Resets lighting in the area between pos1 and pos2 " + .. "(<pos1> and <pos2> must be in parentheses)"), privs = {server = true}, func = function(name, param) local p1, p2 = parse_range_str(name, param) @@ -652,17 +668,18 @@ core.register_chatcommand("fixlight", { end if core.fix_light(p1, p2) then - return true, "Successfully reset light in the area ranging from " .. - core.pos_to_string(p1, 1) .. " to " .. core.pos_to_string(p2, 1) + return true, S("Successfully reset light in the area " + .. "ranging from @1 to @2.", + core.pos_to_string(p1, 1), core.pos_to_string(p2, 1)) else - return false, "Failed to load one or more blocks in area" + return false, S("Failed to load one or more blocks in area.") end end, }) core.register_chatcommand("mods", { params = "", - description = "List mods installed on the server", + description = S("List mods installed on the server"), privs = {}, func = function(name, param) return true, table.concat(core.get_modnames(), ", ") @@ -674,117 +691,136 @@ local function handle_give_command(cmd, giver, receiver, stackstring) .. ', stackstring="' .. stackstring .. '"') local itemstack = ItemStack(stackstring) if itemstack:is_empty() then - return false, "Cannot give an empty item" + return false, S("Cannot give an empty item.") elseif (not itemstack:is_known()) or (itemstack:get_name() == "unknown") then - return false, "Cannot give an unknown item" + return false, S("Cannot give an unknown item.") -- Forbid giving 'ignore' due to unwanted side effects elseif itemstack:get_name() == "ignore" then - return false, "Giving 'ignore' is not allowed" + return false, S("Giving 'ignore' is not allowed.") end local receiverref = core.get_player_by_name(receiver) if receiverref == nil then - return false, receiver .. " is not a known player" + return false, S("@1 is not a known player.", receiver) end local leftover = receiverref:get_inventory():add_item("main", itemstack) local partiality if leftover:is_empty() then - partiality = "" + partiality = nil elseif leftover:get_count() == itemstack:get_count() then - partiality = "could not be " + partiality = false else - partiality = "partially " + partiality = true end -- The actual item stack string may be different from what the "giver" -- entered (e.g. big numbers are always interpreted as 2^16-1). stackstring = itemstack:to_string() + local msg + if partiality == true then + msg = S("@1 partially added to inventory.", stackstring) + elseif partiality == false then + msg = S("@1 could not be added to inventory.", stackstring) + else + msg = S("@1 added to inventory.", stackstring) + end if giver == receiver then - local msg = "%q %sadded to inventory." - return true, msg:format(stackstring, partiality) + return true, msg else - core.chat_send_player(receiver, ("%q %sadded to inventory.") - :format(stackstring, partiality)) - local msg = "%q %sadded to %s's inventory." - return true, msg:format(stackstring, partiality, receiver) + core.chat_send_player(receiver, msg) + local msg_other + if partiality == true then + msg_other = S("@1 partially added to inventory of @2.", + stackstring, receiver) + elseif partiality == false then + msg_other = S("@1 could not be added to inventory of @2.", + stackstring, receiver) + else + msg_other = S("@1 added to inventory of @2.", + stackstring, receiver) + end + return true, msg_other end end core.register_chatcommand("give", { - params = "<name> <ItemString> [<count> [<wear>]]", - description = "Give item to player", + params = S("<name> <ItemString> [<count> [<wear>]]"), + description = S("Give item to player"), privs = {give=true}, func = function(name, param) local toname, itemstring = string.match(param, "^([^ ]+) +(.+)$") if not toname or not itemstring then - return false, "Name and ItemString required" + return false, S("Name and ItemString required.") end return handle_give_command("/give", name, toname, itemstring) end, }) core.register_chatcommand("giveme", { - params = "<ItemString> [<count> [<wear>]]", - description = "Give item to yourself", + params = S("<ItemString> [<count> [<wear>]]"), + description = S("Give item to yourself"), privs = {give=true}, func = function(name, param) local itemstring = string.match(param, "(.+)$") if not itemstring then - return false, "ItemString required" + return false, S("ItemString required.") end return handle_give_command("/giveme", name, name, itemstring) end, }) core.register_chatcommand("spawnentity", { - params = "<EntityName> [<X>,<Y>,<Z>]", - description = "Spawn entity at given (or your) position", + params = S("<EntityName> [<X>,<Y>,<Z>]"), + description = S("Spawn entity at given (or your) position"), privs = {give=true, interact=true}, func = function(name, param) local entityname, p = string.match(param, "^([^ ]+) *(.*)$") if not entityname then - return false, "EntityName required" + return false, S("EntityName required.") end core.log("action", ("%s invokes /spawnentity, entityname=%q") :format(name, entityname)) local player = core.get_player_by_name(name) if player == nil then core.log("error", "Unable to spawn entity, player is nil") - return false, "Unable to spawn entity, player is nil" + return false, S("Unable to spawn entity, player is nil.") end if not core.registered_entities[entityname] then - return false, "Cannot spawn an unknown entity" + return false, S("Cannot spawn an unknown entity.") end if p == "" then p = player:get_pos() else p = core.string_to_pos(p) if p == nil then - return false, "Invalid parameters ('" .. param .. "')" + return false, S("Invalid parameters (@1).", param) end end p.y = p.y + 1 local obj = core.add_entity(p, entityname) - local msg = obj and "%q spawned." or "%q failed to spawn." - return true, msg:format(entityname) + if obj then + return true, S("@1 spawned.", entityname) + else + return true, S("@1 failed to spawn.", entityname) + end end, }) core.register_chatcommand("pulverize", { params = "", - description = "Destroy item in hand", + description = S("Destroy item in hand"), func = function(name, param) local player = core.get_player_by_name(name) if not player then core.log("error", "Unable to pulverize, no player.") - return false, "Unable to pulverize, no player." + return false, S("Unable to pulverize, no player.") end local wielded_item = player:get_wielded_item() if wielded_item:is_empty() then - return false, "Unable to pulverize, no item in hand." + return false, S("Unable to pulverize, no item in hand.") end core.log("action", name .. " pulverized \"" .. wielded_item:get_name() .. " " .. wielded_item:get_count() .. "\"") player:set_wielded_item(nil) - return true, "An item was pulverized." + return true, S("An item was pulverized.") end, }) @@ -800,14 +836,15 @@ core.register_on_punchnode(function(pos, node, puncher) end) core.register_chatcommand("rollback_check", { - params = "[<range>] [<seconds>] [<limit>]", - description = "Check who last touched a node or a node near it" - .. " within the time specified by <seconds>. Default: range = 0," - .. " seconds = 86400 = 24h, limit = 5. Set <seconds> to inf for no time limit", + params = S("[<range>] [<seconds>] [<limit>]"), + description = S("Check who last touched a node or a node near it " + .. "within the time specified by <seconds>. " + .. "Default: range = 0, seconds = 86400 = 24h, limit = 5. " + .. "Set <seconds> to inf for no time limit"), privs = {rollback=true}, func = function(name, param) if not core.settings:get_bool("enable_rollback_recording") then - return false, "Rollback functions are disabled." + return false, S("Rollback functions are disabled.") end local range, seconds, limit = param:match("(%d+) *(%d*) *(%d*)") @@ -815,30 +852,30 @@ core.register_chatcommand("rollback_check", { seconds = tonumber(seconds) or 86400 limit = tonumber(limit) or 5 if limit > 100 then - return false, "That limit is too high!" + return false, S("That limit is too high!") end core.rollback_punch_callbacks[name] = function(pos, node, puncher) local name = puncher:get_player_name() - core.chat_send_player(name, "Checking " .. core.pos_to_string(pos) .. "...") + core.chat_send_player(name, S("Checking @1 ...", core.pos_to_string(pos))) local actions = core.rollback_get_node_actions(pos, range, seconds, limit) if not actions then - core.chat_send_player(name, "Rollback functions are disabled") + core.chat_send_player(name, S("Rollback functions are disabled.")) return end local num_actions = #actions if num_actions == 0 then - core.chat_send_player(name, "Nobody has touched" - .. " the specified location in " - .. seconds .. " seconds") + core.chat_send_player(name, + S("Nobody has touched the specified " + .. "location in @1 seconds.", + seconds)) return end local time = os.time() for i = num_actions, 1, -1 do local action = actions[i] core.chat_send_player(name, - ("%s %s %s -> %s %d seconds ago.") - :format( + S("@1 @2 @3 -> @4 @5 seconds ago.", core.pos_to_string(action.pos), action.actor, action.oldnode.name, @@ -847,110 +884,123 @@ core.register_chatcommand("rollback_check", { end end - return true, "Punch a node (range=" .. range .. ", seconds=" - .. seconds .. "s, limit=" .. limit .. ")" + return true, S("Punch a node (range=@1, seconds=@2, limit=@3).", + range, seconds, limit) end, }) core.register_chatcommand("rollback", { - params = "(<name> [<seconds>]) | (:<actor> [<seconds>])", - description = "Revert actions of a player. Default for <seconds> is 60. Set <seconds> to inf for no time limit", + params = S("(<name> [<seconds>]) | (:<actor> [<seconds>])"), + description = S("Revert actions of a player. " + .. "Default for <seconds> is 60. " + .. "Set <seconds> to inf for no time limit"), privs = {rollback=true}, func = function(name, param) if not core.settings:get_bool("enable_rollback_recording") then - return false, "Rollback functions are disabled." + return false, S("Rollback functions are disabled.") end local target_name, seconds = string.match(param, ":([^ ]+) *(%d*)") + local rev_msg if not target_name then local player_name player_name, seconds = string.match(param, "([^ ]+) *(%d*)") if not player_name then - return false, "Invalid parameters. See /help rollback" - .. " and /help rollback_check." + return false, S("Invalid parameters. " + .. "See /help rollback and " + .. "/help rollback_check.") end + seconds = tonumber(seconds) or 60 target_name = "player:"..player_name + rev_msg = S("Reverting actions of player '@1' since @2 seconds.", + player_name, seconds) + else + seconds = tonumber(seconds) or 60 + rev_msg = S("Reverting actions of @1 since @2 seconds.", + target_name, seconds) end - seconds = tonumber(seconds) or 60 - core.chat_send_player(name, "Reverting actions of " - .. target_name .. " since " - .. seconds .. " seconds.") + core.chat_send_player(name, rev_msg) local success, log = core.rollback_revert_actions_by( target_name, seconds) local response = "" if #log > 100 then - response = "(log is too long to show)\n" + response = S("(log is too long to show)").."\n" else for _, line in pairs(log) do response = response .. line .. "\n" end end - response = response .. "Reverting actions " - .. (success and "succeeded." or "FAILED.") + if success then + response = response .. S("Reverting actions succeeded.") + else + response = response .. S("Reverting actions FAILED.") + end return success, response end, }) core.register_chatcommand("status", { - description = "Show server status", + description = S("Show server status"), func = function(name, param) local status = core.get_server_status(name, false) if status and status ~= "" then return true, status end - return false, "This command was disabled by a mod or game" + return false, S("This command was disabled by a mod or game.") end, }) core.register_chatcommand("time", { - params = "[<0..23>:<0..59> | <0..24000>]", - description = "Show or set time of day", + params = S("[<0..23>:<0..59> | <0..24000>]"), + description = S("Show or set time of day"), privs = {}, func = function(name, param) if param == "" then local current_time = math.floor(core.get_timeofday() * 1440) local minutes = current_time % 60 local hour = (current_time - minutes) / 60 - return true, ("Current time is %d:%02d"):format(hour, minutes) + return true, S("Current time is @1:@2.", + string.format("%d", hour), + string.format("%02d", minutes)) end local player_privs = core.get_player_privs(name) if not player_privs.settime then - return false, "You don't have permission to run this command " .. - "(missing privilege: settime)." + return false, S("You don't have permission to run " + .. "this command (missing privilege: @1).", "settime") end local hour, minute = param:match("^(%d+):(%d+)$") if not hour then local new_time = tonumber(param) if not new_time then - return false, "Invalid time." + return false, S("Invalid time.") end -- Backward compatibility. core.set_timeofday((new_time % 24000) / 24000) core.log("action", name .. " sets time to " .. new_time) - return true, "Time of day changed." + return true, S("Time of day changed.") end hour = tonumber(hour) minute = tonumber(minute) if hour < 0 or hour > 23 then - return false, "Invalid hour (must be between 0 and 23 inclusive)." + return false, S("Invalid hour (must be between 0 and 23 inclusive).") elseif minute < 0 or minute > 59 then - return false, "Invalid minute (must be between 0 and 59 inclusive)." + return false, S("Invalid minute (must be between 0 and 59 inclusive).") end core.set_timeofday((hour * 60 + minute) / 1440) core.log("action", ("%s sets time to %d:%02d"):format(name, hour, minute)) - return true, "Time of day changed." + return true, S("Time of day changed.") end, }) core.register_chatcommand("days", { - description = "Show day count since world creation", + description = S("Show day count since world creation"), func = function(name, param) - return true, "Current day is " .. core.get_day_count() + return true, S("Current day is @1.", core.get_day_count()) end }) core.register_chatcommand("shutdown", { - params = "[<delay_in_seconds> | -1] [reconnect] [<message>]", - description = "Shutdown server (-1 cancels a delayed shutdown)", + params = S("[<delay_in_seconds> | -1] [reconnect] [<message>]"), + description = S("Shutdown server (-1 cancels a delayed shutdown)"), privs = {server=true}, func = function(name, param) local delay, reconnect, message @@ -963,7 +1013,7 @@ core.register_chatcommand("shutdown", { if delay == 0 then core.log("action", name .. " shuts down server") - core.chat_send_all("*** Server shutting down (operator request).") + core.chat_send_all("*** "..S("Server shutting down (operator request).")) end core.request_shutdown(message:trim(), core.is_yes(reconnect), delay) return true @@ -971,65 +1021,65 @@ core.register_chatcommand("shutdown", { }) core.register_chatcommand("ban", { - params = "[<name>]", - description = "Ban the IP of a player or show the ban list", + params = S("[<name>]"), + description = S("Ban the IP of a player or show the ban list"), privs = {ban=true}, func = function(name, param) if param == "" then local ban_list = core.get_ban_list() if ban_list == "" then - return true, "The ban list is empty." + return true, S("The ban list is empty.") else - return true, "Ban list: " .. ban_list + return true, S("Ban list: @1", ban_list) end end if not core.get_player_by_name(param) then - return false, "Player is not online." + return false, S("Player is not online.") end if not core.ban_player(param) then - return false, "Failed to ban player." + return false, S("Failed to ban player.") end local desc = core.get_ban_description(param) core.log("action", name .. " bans " .. desc .. ".") - return true, "Banned " .. desc .. "." + return true, S("Banned @1.", desc) end, }) core.register_chatcommand("unban", { - params = "<name> | <IP_address>", - description = "Remove IP ban belonging to a player/IP", + params = S("<name> | <IP_address>"), + description = S("Remove IP ban belonging to a player/IP"), privs = {ban=true}, func = function(name, param) if not core.unban_player_or_ip(param) then - return false, "Failed to unban player/IP." + return false, S("Failed to unban player/IP.") end core.log("action", name .. " unbans " .. param) - return true, "Unbanned " .. param + return true, S("Unbanned @1.", param) end, }) core.register_chatcommand("kick", { - params = "<name> [<reason>]", - description = "Kick a player", + params = S("<name> [<reason>]"), + description = S("Kick a player"), privs = {kick=true}, func = function(name, param) local tokick, reason = param:match("([^ ]+) (.+)") tokick = tokick or param if not core.kick_player(tokick, reason) then - return false, "Failed to kick player " .. tokick + return false, S("Failed to kick player @1.", tokick) end local log_reason = "" if reason then log_reason = " with reason \"" .. reason .. "\"" end core.log("action", name .. " kicks " .. tokick .. log_reason) - return true, "Kicked " .. tokick + return true, S("Kicked @1.", tokick) end, }) core.register_chatcommand("clearobjects", { - params = "[full | quick]", - description = "Clear all objects in world", + params = S("[full | quick]"), + description = S("Clear all objects in world"), privs = {server=true}, func = function(name, param) local options = {} @@ -1038,45 +1088,44 @@ core.register_chatcommand("clearobjects", { elseif param == "full" then options.mode = "full" else - return false, "Invalid usage, see /help clearobjects." + return false, S("Invalid usage, see /help clearobjects.") end - core.log("action", name .. " clears all objects (" + core.log("action", name .. " clears objects (" .. options.mode .. " mode).") - core.chat_send_all("Clearing all objects. This may take a long time." - .. " You may experience a timeout. (by " - .. name .. ")") + if options.mode == "full" then + core.chat_send_all(S("Clearing all objects. This may take a long time. " + .. "You may experience a timeout. (by @1)", name)) + end core.clear_objects(options) core.log("action", "Object clearing done.") - core.chat_send_all("*** Cleared all objects.") + core.chat_send_all("*** "..S("Cleared all objects.")) return true end, }) core.register_chatcommand("msg", { - params = "<name> <message>", - description = "Send a direct message to a player", + params = S("<name> <message>"), + description = S("Send a direct message to a player"), privs = {shout=true}, func = function(name, param) local sendto, message = param:match("^(%S+)%s(.+)$") if not sendto then - return false, "Invalid usage, see /help msg." + return false, S("Invalid usage, see /help msg.") end if not core.get_player_by_name(sendto) then - return false, "The player " .. sendto - .. " is not online." + return false, S("The player @1 is not online.", sendto) end core.log("action", "DM from " .. name .. " to " .. sendto .. ": " .. message) - core.chat_send_player(sendto, "DM from " .. name .. ": " - .. message) - return true, "Message sent." + core.chat_send_player(sendto, S("DM from @1: @2", name, message)) + return true, S("Message sent.") end, }) core.register_chatcommand("last-login", { - params = "[<name>]", - description = "Get the last login time of a player or yourself", + params = S("[<name>]"), + description = S("Get the last login time of a player or yourself"), func = function(name, param) if param == "" then param = name @@ -1084,25 +1133,27 @@ core.register_chatcommand("last-login", { local pauth = core.get_auth_handler().get_auth(param) if pauth and pauth.last_login and pauth.last_login ~= -1 then -- Time in UTC, ISO 8601 format - return true, param.."'s last login time was " .. - os.date("!%Y-%m-%dT%H:%M:%SZ", pauth.last_login) + return true, S("@1's last login time was @2.", + param, + os.date("!%Y-%m-%dT%H:%M:%SZ", pauth.last_login)) end - return false, param.."'s last login time is unknown" + return false, S("@1's last login time is unknown.", param) end, }) core.register_chatcommand("clearinv", { - params = "[<name>]", - description = "Clear the inventory of yourself or another player", + params = S("[<name>]"), + description = S("Clear the inventory of yourself or another player"), func = function(name, param) local player if param and param ~= "" and param ~= name then if not core.check_player_privs(name, {server=true}) then - return false, "You don't have permission" - .. " to clear another player's inventory (missing privilege: server)" + return false, S("You don't have permission to " + .. "clear another player's inventory " + .. "(missing privilege: @1).", "server") end player = core.get_player_by_name(param) - core.chat_send_player(param, name.." cleared your inventory.") + core.chat_send_player(param, S("@1 cleared your inventory.", name)) else player = core.get_player_by_name(name) end @@ -1112,25 +1163,25 @@ core.register_chatcommand("clearinv", { player:get_inventory():set_list("craft", {}) player:get_inventory():set_list("craftpreview", {}) core.log("action", name.." clears "..player:get_player_name().."'s inventory") - return true, "Cleared "..player:get_player_name().."'s inventory." + return true, S("Cleared @1's inventory.", player:get_player_name()) else - return false, "Player must be online to clear inventory!" + return false, S("Player must be online to clear inventory!") end end, }) local function handle_kill_command(killer, victim) if core.settings:get_bool("enable_damage") == false then - return false, "Players can't be killed, damage has been disabled." + return false, S("Players can't be killed, damage has been disabled.") end local victimref = core.get_player_by_name(victim) if victimref == nil then - return false, string.format("Player %s is not online.", victim) + return false, S("Player @1 is not online.", victim) elseif victimref:get_hp() <= 0 then if killer == victim then - return false, "You are already dead." + return false, S("You are already dead.") else - return false, string.format("%s is already dead.", victim) + return false, S("@1 is already dead.", victim) end end if not killer == victim then @@ -1138,12 +1189,12 @@ local function handle_kill_command(killer, victim) end -- Kill victim victimref:set_hp(0) - return true, string.format("%s has been killed.", victim) + return true, S("@1 has been killed.", victim) end core.register_chatcommand("kill", { - params = "[<name>]", - description = "Kill player or yourself", + params = S("[<name>]"), + description = S("Kill player or yourself"), privs = {server=true}, func = function(name, param) return handle_kill_command(name, param == "" and name or param) diff --git a/builtin/game/item.lua b/builtin/game/item.lua index 881aff52e..b68177c22 100644 --- a/builtin/game/item.lua +++ b/builtin/game/item.lua @@ -678,7 +678,7 @@ end -- Item definition defaults -- -local default_stack_max = tonumber(minetest.settings:get("default_stack_max")) or 99 +local default_stack_max = tonumber(core.settings:get("default_stack_max")) or 99 core.nodedef_default = { -- Item properties diff --git a/builtin/game/knockback.lua b/builtin/game/knockback.lua index b5c4cbc5a..a937aa186 100644 --- a/builtin/game/knockback.lua +++ b/builtin/game/knockback.lua @@ -42,5 +42,5 @@ core.register_on_punchplayer(function(player, hitter, time_from_last_punch, tool return -- barely noticeable, so don't even send end - player:add_player_velocity(kdir) + player:add_velocity(kdir) end) diff --git a/builtin/game/misc.lua b/builtin/game/misc.lua index b8c5e16a9..fcb86146d 100644 --- a/builtin/game/misc.lua +++ b/builtin/game/misc.lua @@ -1,5 +1,7 @@ -- Minetest: builtin/misc.lua +local S = core.get_translator("__builtin") + -- -- Misc. API functions -- @@ -42,15 +44,15 @@ end function core.send_join_message(player_name) if not core.is_singleplayer() then - core.chat_send_all("*** " .. player_name .. " joined the game.") + core.chat_send_all("*** " .. S("@1 joined the game.", player_name)) end end function core.send_leave_message(player_name, timed_out) - local announcement = "*** " .. player_name .. " left the game." + local announcement = "*** " .. S("@1 left the game.", player_name) if timed_out then - announcement = announcement .. " (timed out)" + announcement = "*** " .. S("@1 left the game (timed out).", player_name) end core.chat_send_all(announcement) end diff --git a/builtin/game/privileges.lua b/builtin/game/privileges.lua index c7417d2f4..aee32a34e 100644 --- a/builtin/game/privileges.lua +++ b/builtin/game/privileges.lua @@ -1,5 +1,7 @@ -- Minetest: builtin/privileges.lua +local S = core.get_translator("__builtin") + -- -- Privileges -- @@ -15,7 +17,7 @@ function core.register_privilege(name, param) def.give_to_admin = def.give_to_singleplayer end if def.description == nil then - def.description = "(no description)" + def.description = S("(no description)") end end local def @@ -28,69 +30,69 @@ function core.register_privilege(name, param) core.registered_privileges[name] = def end -core.register_privilege("interact", "Can interact with things and modify the world") -core.register_privilege("shout", "Can speak in chat") -core.register_privilege("basic_privs", "Can modify 'shout' and 'interact' privileges") -core.register_privilege("privs", "Can modify privileges") +core.register_privilege("interact", S("Can interact with things and modify the world")) +core.register_privilege("shout", S("Can speak in chat")) +core.register_privilege("basic_privs", S("Can modify 'shout' and 'interact' privileges")) +core.register_privilege("privs", S("Can modify privileges")) core.register_privilege("teleport", { - description = "Can teleport self", + description = S("Can teleport self"), give_to_singleplayer = false, }) core.register_privilege("bring", { - description = "Can teleport other players", + description = S("Can teleport other players"), give_to_singleplayer = false, }) core.register_privilege("settime", { - description = "Can set the time of day using /time", + description = S("Can set the time of day using /time"), give_to_singleplayer = false, }) core.register_privilege("server", { - description = "Can do server maintenance stuff", + description = S("Can do server maintenance stuff"), give_to_singleplayer = false, give_to_admin = true, }) core.register_privilege("protection_bypass", { - description = "Can bypass node protection in the world", + description = S("Can bypass node protection in the world"), give_to_singleplayer = false, }) core.register_privilege("ban", { - description = "Can ban and unban players", + description = S("Can ban and unban players"), give_to_singleplayer = false, give_to_admin = true, }) core.register_privilege("kick", { - description = "Can kick players", + description = S("Can kick players"), give_to_singleplayer = false, give_to_admin = true, }) core.register_privilege("give", { - description = "Can use /give and /giveme", + description = S("Can use /give and /giveme"), give_to_singleplayer = false, }) core.register_privilege("password", { - description = "Can use /setpassword and /clearpassword", + description = S("Can use /setpassword and /clearpassword"), give_to_singleplayer = false, give_to_admin = true, }) core.register_privilege("fly", { - description = "Can use fly mode", + description = S("Can use fly mode"), give_to_singleplayer = false, }) core.register_privilege("fast", { - description = "Can use fast mode", + description = S("Can use fast mode"), give_to_singleplayer = false, }) core.register_privilege("noclip", { - description = "Can fly through solid nodes using noclip mode", + description = S("Can fly through solid nodes using noclip mode"), give_to_singleplayer = false, }) core.register_privilege("rollback", { - description = "Can use the rollback functionality", + description = S("Can use the rollback functionality"), give_to_singleplayer = false, }) core.register_privilege("debug", { - description = "Allows enabling various debug options that may affect gameplay", + description = S("Allows enabling various debug options that may affect gameplay"), give_to_singleplayer = false, give_to_admin = true, }) diff --git a/builtin/game/register.lua b/builtin/game/register.lua index b006957e9..c07535855 100644 --- a/builtin/game/register.lua +++ b/builtin/game/register.lua @@ -1,5 +1,7 @@ -- Minetest: builtin/misc_register.lua +local S = core.get_translator("__builtin") + -- -- Make raw registration functions inaccessible to anyone except this file -- @@ -118,10 +120,6 @@ function core.register_item(name, itemdef) end itemdef.name = name - -- default short_description to first line of description - itemdef.short_description = itemdef.short_description or - (itemdef.description or ""):gsub("\n.*","") - -- Apply defaults and add to registered_* table if itemdef.type == "node" then -- Use the nodebox as selection box if it's not set manually @@ -330,7 +328,7 @@ end core.register_item(":unknown", { type = "none", - description = "Unknown Item", + description = S("Unknown Item"), inventory_image = "unknown_item.png", on_place = core.item_place, on_secondary_use = core.item_secondary_use, @@ -340,7 +338,7 @@ core.register_item(":unknown", { }) core.register_node(":air", { - description = "Air", + description = S("Air"), inventory_image = "air.png", wield_image = "air.png", drawtype = "airlike", @@ -357,7 +355,7 @@ core.register_node(":air", { }) core.register_node(":ignore", { - description = "Ignore", + description = S("Ignore"), inventory_image = "ignore.png", wield_image = "ignore.png", drawtype = "airlike", @@ -370,11 +368,12 @@ core.register_node(":ignore", { air_equivalent = true, drop = "", groups = {not_in_creative_inventory=1}, + node_placement_prediction = "", on_place = function(itemstack, placer, pointed_thing) core.chat_send_player( placer:get_player_name(), core.colorize("#FF0000", - "You can't place 'ignore' nodes!")) + S("You can't place 'ignore' nodes!"))) return "" end, }) diff --git a/builtin/game/statbars.lua b/builtin/game/statbars.lua index d192029c5..db5087a16 100644 --- a/builtin/game/statbars.lua +++ b/builtin/game/statbars.lua @@ -84,8 +84,8 @@ local function update_builtin_statbars(player) end if hud.id_breathbar and (not show_breathbar or breath == breath_max) then - minetest.after(1, function(player_name, breath_bar) - local player = minetest.get_player_by_name(player_name) + core.after(1, function(player_name, breath_bar) + local player = core.get_player_by_name(player_name) if player then player:hud_remove(breath_bar) end diff --git a/builtin/init.lua b/builtin/init.lua index 75bb3db85..89b1fdc64 100644 --- a/builtin/init.lua +++ b/builtin/init.lua @@ -39,9 +39,20 @@ if INIT == "game" then assert(not core.get_http_api) elseif INIT == "mainmenu" then local mm_script = core.settings:get("main_menu_script") + local custom_loaded = false if mm_script and mm_script ~= "" then - dofile(mm_script) - else + local testfile = io.open(mm_script, "r") + if testfile then + testfile:close() + dofile(mm_script) + custom_loaded = true + core.log("info", "Loaded custom main menu script: "..mm_script) + else + core.log("error", "Failed to load custom main menu script: "..mm_script) + core.log("info", "Falling back to default main menu script") + end + end + if not custom_loaded then dofile(core.get_mainmenu_path() .. DIR_DELIM .. "init.lua") end elseif INIT == "async" then diff --git a/builtin/locale/__builtin.de.tr b/builtin/locale/__builtin.de.tr new file mode 100644 index 000000000..eaadf611b --- /dev/null +++ b/builtin/locale/__builtin.de.tr @@ -0,0 +1,225 @@ +# textdomain: __builtin +Empty command.=Leerer Befehl. +Invalid command: @1=Ungültiger Befehl: @1 +Invalid command usage.=Ungültige Befehlsverwendung. +You don't have permission to run this command (missing privileges: @1).=Sie haben keine Erlaubnis, diesen Befehl auszuführen (fehlende Privilegien: @1). +Unable to get position of player @1.=Konnte Position vom Spieler @1 nicht ermitteln. +Incorrect area format. Expected: (x1,y1,z1) (x2,y2,z2)=Ungültiges Gebietsformat. Erwartet: (x1,y1,z1) (x2,y2,z2) +<action>=<Aktion> +Show chat action (e.g., '/me orders a pizza' displays '<player name> orders a pizza')=Chataktion zeigen (z.B. wird „/me isst Pizza“ zu „<Spielername> isst Pizza“) +Show the name of the server owner=Den Namen des Servereigentümers zeigen +The administrator of this server is @1.=Der Administrator dieses Servers ist @1. +There's no administrator named in the config file.=In der Konfigurationsdatei wurde kein Administrator angegeben. +[<name>]=[<Name>] +Show privileges of yourself or another player=Ihre eigenen Privilegien oder die eines anderen Spielers anzeigen +Player @1 does not exist.=Spieler @1 existiert nicht. +Privileges of @1: @2=Privilegien von @1: @2 +<privilege>=<Privileg> +Return list of all online players with privilege=Liste aller Spieler mit einem Privileg ausgeben +Invalid parameters (see /help haspriv).=Ungültige Parameter (siehe „/help haspriv“). +Unknown privilege!=Unbekanntes Privileg! +Players online with the "@1" privilege: @2=Derzeit online spielende Spieler mit dem „@1“-Privileg: @2 +Your privileges are insufficient.=Ihre Privilegien sind unzureichend. +Unknown privilege: @1=Unbekanntes Privileg: @1 +@1 granted you privileges: @2=@1 gewährte Ihnen Privilegien: @2 +<name> (<privilege> | all)=<Name> (<Privileg> | all) +Give privileges to player=Privileg an Spieler vergeben +Invalid parameters (see /help grant).=Ungültige Parameter (siehe „/help grant“). +<privilege> | all=<Privileg> | all +Grant privileges to yourself=Privilegien an Ihnen selbst vergeben +Invalid parameters (see /help grantme).=Ungültige Parameter (siehe „/help grantme“). +@1 revoked privileges from you: @2=@1 entfernte Privilegien von Ihnen: @2 +Remove privileges from player=Privilegien von Spieler entfernen +Invalid parameters (see /help revoke).=Ungültige Parameter (siehe „/help revoke“). +Revoke privileges from yourself=Privilegien von Ihnen selbst entfernen +Invalid parameters (see /help revokeme).=Ungültige Parameter (siehe „/help revokeme“). +<name> <password>=<Name> <Passwort> +Set player's password=Passwort von Spieler setzen +Name field required.=Namensfeld benötigt. +Your password was cleared by @1.=Ihr Passwort wurde von @1 geleert. +Password of player "@1" cleared.=Passwort von Spieler „@1“ geleert. +Your password was set by @1.=Ihr Passwort wurde von @1 gesetzt. +Password of player "@1" set.=Passwort von Spieler „@1“ gesetzt. +<name>=<Name> +Set empty password for a player=Leeres Passwort für einen Spieler setzen +Reload authentication data=Authentifizierungsdaten erneut laden +Done.=Fertig. +Failed.=Fehlgeschlagen. +Remove a player's data=Daten eines Spielers löschen +Player "@1" removed.=Spieler „@1“ gelöscht. +No such player "@1" to remove.=Es gibt keinen Spieler „@1“, der gelöscht werden könnte. +Player "@1" is connected, cannot remove.=Spieler „@1“ ist verbunden, er kann nicht gelöscht werden. +Unhandled remove_player return code @1.=Nicht berücksichtigter remove_player-Rückgabewert @1. +Cannot teleport out of map bounds!=Eine Teleportation außerhalb der Kartengrenzen ist nicht möglich! +Cannot get player with name @1.=Spieler mit Namen @1 kann nicht gefunden werden. +Cannot teleport, @1 is attached to an object!=Teleportation nicht möglich, @1 ist an einem Objekt befestigt! +Teleporting @1 to @2.=Teleportation von @1 nach @2 +One does not teleport to oneself.=Man teleportiert sich doch nicht zu sich selbst. +Cannot get teleportee with name @1.=Der zu teleportierende Spieler mit Namen @1 kann nicht gefunden werden. +Cannot get target player with name @1.=Zielspieler mit Namen @1 kann nicht gefunden werden. +Teleporting @1 to @2 at @3.=Teleportation von @1 zu @2 bei @3 +<X>,<Y>,<Z> | <to_name> | <name> <X>,<Y>,<Z> | <name> <to_name>=<X>,<Y>,<Z> | <zu_Name> | <Name> <X>,<Y>,<Z> | <Name> <zu_Name> +Teleport to position or player=Zu Position oder Spieler teleportieren +You don't have permission to teleport other players (missing privilege: @1).=Sie haben nicht die Erlaubnis, andere Spieler zu teleportieren (fehlendes Privileg: @1). +([-n] <name> <value>) | <name>=([-n] <Name> <Wert>) | <Name> +Set or read server configuration setting=Serverkonfigurationseinstellung setzen oder lesen +Failed. Use '/set -n <name> <value>' to create a new setting.=Fehlgeschlagen. Benutzen Sie „/set -n <Name> <Wert>“, um eine neue Einstellung zu erstellen. +@1 @= @2=@1 @= @2 +<not set>=<nicht gesetzt> +Invalid parameters (see /help set).=Ungültige Parameter (siehe „/help set“). +Finished emerging @1 blocks in @2ms.=Fertig mit Erzeugung von @1 Blöcken in @2 ms. +emergeblocks update: @1/@2 blocks emerged (@3%)=emergeblocks-Update: @1/@2 Kartenblöcke geladen (@3%) +(here [<radius>]) | (<pos1> <pos2>)=(here [<Radius>]) | (<Pos1> <Pos2>) +Load (or, if nonexistent, generate) map blocks contained in area pos1 to pos2 (<pos1> and <pos2> must be in parentheses)=Lade (oder, wenn nicht existent, generiere) Kartenblöcke im Gebiet zwischen Pos1 und Pos2 (<Pos1> und <Pos2> müssen in Klammern stehen) +Started emerge of area ranging from @1 to @2.=Start des Ladevorgangs des Gebiets zwischen @1 und @2. +Delete map blocks contained in area pos1 to pos2 (<pos1> and <pos2> must be in parentheses)=Kartenblöcke innerhalb des Gebiets zwischen Pos1 und Pos2 löschen (<Pos1> und <Pos2> müssen in Klammern stehen) +Successfully cleared area ranging from @1 to @2.=Gebiet zwischen @1 und @2 erfolgreich geleert. +Failed to clear one or more blocks in area.=Fehlgeschlagen: Ein oder mehrere Kartenblöcke im Gebiet konnten nicht geleert werden. +Resets lighting in the area between pos1 and pos2 (<pos1> and <pos2> must be in parentheses)=Setzt das Licht im Gebiet zwischen Pos1 und Pos2 zurück (<Pos1> und <Pos2> müssen in Klammern stehen) +Successfully reset light in the area ranging from @1 to @2.=Das Licht im Gebiet zwischen @1 und @2 wurde erfolgreich zurückgesetzt. +Failed to load one or more blocks in area.=Fehlgeschlagen: Ein oder mehrere Kartenblöcke im Gebiet konnten nicht geladen werden. +List mods installed on the server=Installierte Mods auf dem Server auflisten +Cannot give an empty item.=Ein leerer Gegenstand kann nicht gegeben werden. +Cannot give an unknown item.=Ein unbekannter Gegenstand kann nicht gegeben werden. +Giving 'ignore' is not allowed.=„ignore“ darf nicht gegeben werden. +@1 is not a known player.=@1 ist kein bekannter Spieler. +@1 partially added to inventory.=@1 teilweise ins Inventar eingefügt. +@1 could not be added to inventory.=@1 konnte nicht ins Inventar eingefügt werden. +@1 added to inventory.=@1 zum Inventar hinzugefügt. +@1 partially added to inventory of @2.=@1 teilweise ins Inventar von @2 eingefügt. +@1 could not be added to inventory of @2.=@1 konnte nicht ins Inventar von @2 eingefügt werden. +@1 added to inventory of @2.=@1 ins Inventar von @2 eingefügt. +<name> <ItemString> [<count> [<wear>]]=<Name> <ItemString> [<Anzahl> [<Abnutzung>]] +Give item to player=Gegenstand an Spieler geben +Name and ItemString required.=Name und ItemString benötigt. +<ItemString> [<count> [<wear>]]=<ItemString> [<Anzahl> [<Abnutzung>]] +Give item to yourself=Gegenstand Ihnen selbst geben +ItemString required.=ItemString benötigt. +<EntityName> [<X>,<Y>,<Z>]=<EntityName> [<X>,<Y>,<Z>] +Spawn entity at given (or your) position=Entity an angegebener (oder Ihrer eigenen) Position spawnen +EntityName required.=EntityName benötigt. +Unable to spawn entity, player is nil.=Entity konnte nicht gespawnt werden, Spieler ist nil. +Cannot spawn an unknown entity.=Ein unbekanntes Entity kann nicht gespawnt werden. +Invalid parameters (@1).=Ungültige Parameter (@1). +@1 spawned.=@1 gespawnt. +@1 failed to spawn.=@1 konnte nicht gespawnt werden. +Destroy item in hand=Gegenstand in der Hand zerstören +Unable to pulverize, no player.=Konnte nicht pulverisieren, kein Spieler. +Unable to pulverize, no item in hand.=Konnte nicht pulverisieren, kein Gegenstand in der Hand. +An item was pulverized.=Ein Gegenstand wurde pulverisiert. +[<range>] [<seconds>] [<limit>]=[<Reichweite>] [<Sekunden>] [<Limit>] +Check who last touched a node or a node near it within the time specified by <seconds>. Default: range @= 0, seconds @= 86400 @= 24h, limit @= 5. Set <seconds> to inf for no time limit=Überprüfen, wer als letztes einen Node oder einen Node in der Nähe innerhalb der in <Sekunden> angegebenen Zeitspanne angefasst hat. Standard: Reichweite @= 0, Sekunden @= 86400 @= 24h, Limit @= 5. <Sekunden> auf „inf“ setzen, um Zeitlimit zu deaktivieren. +Rollback functions are disabled.=Rollback-Funktionen sind deaktiviert. +That limit is too high!=Dieses Limit ist zu hoch! +Checking @1 ...=Überprüfe @1 ... +Nobody has touched the specified location in @1 seconds.=Niemand hat die angegebene Position seit @1 Sekunden angefasst. +@1 @2 @3 -> @4 @5 seconds ago.=@1 @2 @3 -> @4 vor @5 Sekunden. +Punch a node (range@=@1, seconds@=@2, limit@=@3).=Hauen Sie einen Node (Reichweite@=@1, Sekunden@=@2, Limit@=@3). +(<name> [<seconds>]) | (:<actor> [<seconds>])=(<Name> [<Sekunden>]) | (:<Akteur> [<Sekunden>]) +Revert actions of a player. Default for <seconds> is 60. Set <seconds> to inf for no time limit=Aktionen eines Spielers zurückrollen. Standard für <Sekunden> ist 60. <Sekunden> auf „inf“ setzen, um Zeitlimit zu deaktivieren +Invalid parameters. See /help rollback and /help rollback_check.=Ungültige Parameter. Siehe /help rollback und /help rollback_check. +Reverting actions of player '@1' since @2 seconds.=Die Aktionen des Spielers „@1“ seit @2 Sekunden werden rückgängig gemacht. +Reverting actions of @1 since @2 seconds.=Die Aktionen von @1 seit @2 Sekunden werden rückgängig gemacht. +(log is too long to show)=(Protokoll ist zu lang für die Anzeige) +Reverting actions succeeded.=Die Aktionen wurden erfolgreich rückgängig gemacht. +Reverting actions FAILED.=FEHLGESCHLAGEN: Die Aktionen konnten nicht rückgängig gemacht werden. +Show server status=Serverstatus anzeigen +This command was disabled by a mod or game.=Dieser Befehl wurde von einer Mod oder einem Spiel deaktiviert. +[<0..23>:<0..59> | <0..24000>]=[<0..23>:<0..59> | <0..24000>] +Show or set time of day=Tageszeit anzeigen oder setzen +Current time is @1:@2.=Es ist jetzt @1:@2 Uhr. +You don't have permission to run this command (missing privilege: @1).=Sie haben nicht die Erlaubnis, diesen Befehl auszuführen (fehlendes Privileg: @1). +Invalid time.=Ungültige Zeit. +Time of day changed.=Tageszeit geändert. +Invalid hour (must be between 0 and 23 inclusive).=Ungültige Stunde (muss zwischen 0 und 23 inklusive liegen). +Invalid minute (must be between 0 and 59 inclusive).=Ungültige Minute (muss zwischen 0 und 59 inklusive liegen). +Show day count since world creation=Anzahl Tage seit der Erschaffung der Welt anzeigen +Current day is @1.=Aktueller Tag ist @1. +[<delay_in_seconds> | -1] [reconnect] [<message>]=[<Verzögerung_in_Sekunden> | -1] [reconnect] [<Nachricht>] +Shutdown server (-1 cancels a delayed shutdown)=Server herunterfahren (-1 bricht einen verzögerten Abschaltvorgang ab) +Server shutting down (operator request).=Server wird heruntergefahren (Betreiberanfrage). +Ban the IP of a player or show the ban list=Die IP eines Spielers verbannen oder die Bannliste anzeigen +The ban list is empty.=Die Bannliste ist leer. +Ban list: @1=Bannliste: @1 +Player is not online.=Spieler ist nicht online. +Failed to ban player.=Konnte Spieler nicht verbannen. +Banned @1.=@1 verbannt. +<name> | <IP_address>=<Name> | <IP_Adresse> +Remove IP ban belonging to a player/IP=Einen IP-Bann auf einen Spieler zurücknehmen +Failed to unban player/IP.=Konnte Bann auf Spieler/IP nicht zurücknehmen. +Unbanned @1.=Bann auf @1 zurückgenommen. +<name> [<reason>]=<Name> [<Grund>] +Kick a player=Spieler hinauswerfen +Failed to kick player @1.=Spieler @1 konnte nicht hinausgeworfen werden. +Kicked @1.=@1 hinausgeworfen. +[full | quick]=[full | quick] +Clear all objects in world=Alle Objekte in der Welt löschen +Invalid usage, see /help clearobjects.=Ungültige Verwendung, siehe /help clearobjects. +Clearing all objects. This may take a long time. You may experience a timeout. (by @1)=Lösche alle Objekte. Dies kann eine lange Zeit dauern. Eine Netzwerkzeitüberschreitung könnte für Sie auftreten. (von @1) +Objects cleared.=Objekte gelöscht. +Cleared all objects.=Alle Objekte gelöscht. +<name> <message>=<Name> <Nachricht> +Send a direct message to a player=Eine Direktnachricht an einen Spieler senden +Invalid usage, see /help msg.=Ungültige Verwendung, siehe /help msg. +The player @1 is not online.=Der Spieler @1 ist nicht online. +DM from @1: @2=DN von @1: @2 +Message sent.=Nachricht gesendet. +Get the last login time of a player or yourself=Den letzten Loginzeitpunkt eines Spielers oder Ihren eigenen anfragen +@1's last login time was @2.=Letzter Loginzeitpunkt von @1 war @2. +@1's last login time is unknown.=Letzter Loginzeitpunkt von @1 ist unbekannt. +Clear the inventory of yourself or another player=Das Inventar von Ihnen oder einem anderen Spieler leeren +You don't have permission to clear another player's inventory (missing privilege: @1).=Sie haben nicht die Erlaubnis, das Inventar eines anderen Spielers zu leeren (fehlendes Privileg: @1). +@1 cleared your inventory.=@1 hat Ihr Inventar geleert. +Cleared @1's inventory.=Inventar von @1 geleert. +Player must be online to clear inventory!=Spieler muss online sein, um das Inventar leeren zu können! +Players can't be killed, damage has been disabled.=Spieler können nicht getötet werden, Schaden ist deaktiviert. +Player @1 is not online.=Spieler @1 ist nicht online. +You are already dead.=Sie sind schon tot. +@1 is already dead.=@1 ist bereits tot. +@1 has been killed.=@1 wurde getötet. +Kill player or yourself=Einen Spieler oder Sie selbst töten +Available commands: @1=Verfügbare Befehle: @1 +Use '/help <cmd>' to get more information, or '/help all' to list everything.=„/help <Befehl>“ benutzen, um mehr Informationen zu erhalten, oder „/help all“, um alles aufzulisten. +Available commands:=Verfügbare Befehle: +Command not available: @1=Befehl nicht verfügbar: @1 +[all | privs | <cmd>]=[all | privs | <Befehl>] +Get help for commands or list privileges=Hilfe für Befehle erhalten oder Privilegien auflisten +Available privileges:=Verfügbare Privilegien: +Command=Befehl +Parameters=Parameter +For more information, click on any entry in the list.=Für mehr Informationen klicken Sie auf einen beliebigen Eintrag in der Liste. +Double-click to copy the entry to the chat history.=Doppelklicken, um den Eintrag in die Chathistorie einzufügen. +Command: @1 @2=Befehl: @1 @2 +Available commands: (see also: /help <cmd>)=Verfügbare Befehle: (siehe auch: /help <Befehl>) +Close=Schließen +Privilege=Privileg +Description=Beschreibung +print [<filter>] | dump [<filter>] | save [<format> [<filter>]] | reset=print [<Filter>] | dump [<Filter>] | save [<Format> [<Filter>]] +Handle the profiler and profiling data=Den Profiler und Profilingdaten verwalten +Statistics written to action log.=Statistiken zum Aktionsprotokoll geschrieben. +Statistics were reset.=Statistiken wurden zurückgesetzt. +Usage: @1=Verwendung: @1 +Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change).=Format kann entweder „txt“, „csv“, „lua“, „json“ oder „json_pretty“ sein (die Struktur kann sich in Zukunft ändern). +(no description)=(keine Beschreibung) +Can interact with things and modify the world=Kann mit Dingen interagieren und die Welt verändern +Can speak in chat=Kann im Chat sprechen +Can modify 'shout' and 'interact' privileges=Kann die „shout“- und „interact“-Privilegien anpassen +Can modify privileges=Kann Privilegien anpassen +Can teleport self=Kann sich selbst teleportieren +Can teleport other players=Kann andere Spieler teleportieren +Can set the time of day using /time=Kann die Tageszeit mit /time setzen +Can do server maintenance stuff=Kann Serverwartungsdinge machen +Can bypass node protection in the world=Kann den Schutz auf Blöcken in der Welt umgehen +Can ban and unban players=Kann Spieler verbannen und entbannen +Can kick players=Kann Spieler hinauswerfen +Can use /give and /giveme=Kann /give und /giveme benutzen +Can use /setpassword and /clearpassword=Kann /setpassword und /clearpassword benutzen +Can use fly mode=Kann den Flugmodus benutzen +Can use fast mode=Kann den Schnellmodus benutzen +Can fly through solid nodes using noclip mode=Kann durch feste Blöcke mit dem Geistmodus fliegen +Can use the rollback functionality=Kann die Rollback-Funktionalität benutzen +Allows enabling various debug options that may affect gameplay=Erlaubt die Aktivierung diverser Debugoptionen, die das Spielgeschehen beeinflussen könnten +Unknown Item=Unbekannter Gegenstand +Air=Luft +Ignore=Ignorieren +You can't place 'ignore' nodes!=Sie können keine „ignore“-Blöcke platzieren! diff --git a/builtin/locale/__builtin.it.tr b/builtin/locale/__builtin.it.tr new file mode 100644 index 000000000..94bc870c8 --- /dev/null +++ b/builtin/locale/__builtin.it.tr @@ -0,0 +1,224 @@ +# textdomain: __builtin +Empty command.=Comando vuoto. +Invalid command: @1=Comando non valido: @1 +Invalid command usage.=Utilizzo del comando non valido. +You don't have permission to run this command (missing privileges: @1).=Non hai il permesso di eseguire questo comando (privilegi mancanti: @1). +Unable to get position of player @1.=Impossibile ottenere la posizione del giocatore @1. +Incorrect area format. Expected: (x1,y1,z1) (x2,y2,z2)=Formato dell'area non corretto. Richiesto: (x1,y1,z1) (x2,y2,z2) +<action>=<azione> +Show chat action (e.g., '/me orders a pizza' displays '<player name> orders a pizza')=Mostra un'azione in chat (es. `/me ordina una pizza` mostra `<nome giocatore> ordina una pizza`) +Show the name of the server owner=Mostra il nome del proprietario del server +The administrator of this server is @1.=L'amministratore di questo server è @1. +There's no administrator named in the config file.=Non c'è nessun amministratore nel file di configurazione. +[<name>]=[<nome>] +Show privileges of yourself or another player=Mostra i privilegi propri o di un altro giocatore +Player @1 does not exist.=Il giocatore @1 non esiste. +Privileges of @1: @2=Privilegi di @1: @2 +<privilege>=<privilegio> +Return list of all online players with privilege=Ritorna una lista di tutti i giocatori connessi col tale privilegio +Invalid parameters (see /help haspriv).=Parametri non validi (vedi /help haspriv). +Unknown privilege!=Privilegio sconosciuto! +Players online with the "@1" privilege: @2=Giocatori connessi con il privilegio "@1": @2 +Your privileges are insufficient.=I tuoi privilegi sono insufficienti. +Unknown privilege: @1=Privilegio sconosciuto: @1 +@1 granted you privileges: @2=@1 ti ha assegnato i seguenti privilegi: @2 +<name> (<privilege> | all)=<nome> (<privilegio> | all) +Give privileges to player=Dà privilegi al giocatore +Invalid parameters (see /help grant).=Parametri non validi (vedi /help grant). +<privilege> | all=<privilegio> | all +Grant privileges to yourself=Assegna dei privilegi a te stessǝ +Invalid parameters (see /help grantme).=Parametri non validi (vedi /help grantme). +@1 revoked privileges from you: @2=@1 ti ha revocato i seguenti privilegi: @2 +Remove privileges from player=Rimuove privilegi dal giocatore +Invalid parameters (see /help revoke).=Parametri non validi (vedi /help revoke). +Revoke privileges from yourself=Revoca privilegi a te stessǝ +Invalid parameters (see /help revokeme).=Parametri non validi (vedi /help revokeme). +<name> <password>=<nome> <password> +Set player's password=Imposta la password del giocatore +Name field required.=Campo "nome" richiesto. +Your password was cleared by @1.=La tua password è stata resettata da @1. +Password of player "@1" cleared.=Password del giocatore "@1" resettata. +Your password was set by @1.=La tua password è stata impostata da @1. +Password of player "@1" set.=Password del giocatore "@1" impostata. +<name>=<nome> +Set empty password for a player=Imposta una password vuota a un giocatore +Reload authentication data=Ricarica i dati d'autenticazione +Done.=Fatto. +Failed.=Errore. +Remove a player's data=Rimuove i dati di un giocatore +Player "@1" removed.=Giocatore "@1" rimosso. +No such player "@1" to remove.=Non è presente nessun giocatore "@1" da rimuovere. +Player "@1" is connected, cannot remove.=Il giocatore "@1" è connesso, non può essere rimosso. +Unhandled remove_player return code @1.=Codice ritornato da remove_player non gestito (@1). +Cannot teleport out of map bounds!=Non ci si può teletrasportare fuori dai limiti della mappa! +Cannot get player with name @1.=Impossibile trovare il giocatore chiamato @1. +Cannot teleport, @1 is attached to an object!=Impossibile teletrasportare, @1 è attaccato a un oggetto! +Teleporting @1 to @2.=Teletrasportando @1 da @2. +One does not teleport to oneself.=Non ci si può teletrasportare su se stessi. +Cannot get teleportee with name @1.=Impossibile trovare il giocatore chiamato @1 per il teletrasporto +Cannot get target player with name @1.=Impossibile trovare il giocatore chiamato @1 per il teletrasporto +Teleporting @1 to @2 at @3.=Teletrasportando @1 da @2 a @3 +<X>,<Y>,<Z> | <to_name> | <name> <X>,<Y>,<Z> | <name> <to_name>=<X>,<Y>,<Z> | <da_nome> | <nome> <X>,<Y>,<Z> | <nome> <da_nome> +Teleport to position or player=Teletrasporta a una posizione o da un giocatore +You don't have permission to teleport other players (missing privilege: @1).=Non hai il permesso di teletrasportare altri giocatori (privilegio mancante: @1). +([-n] <name> <value>) | <name>=([-n] <nome> <valore>) | <nome> +Set or read server configuration setting=Imposta o ottieni le configurazioni del server +Failed. Use '/set -n <name> <value>' to create a new setting.=Errore. Usa 'set -n <nome> <valore>' per creare una nuova impostazione +@1 @= @2=@1 @= @2 +<not set>=<non impostato> +Invalid parameters (see /help set).=Parametri non validi (vedi /help set). +Finished emerging @1 blocks in @2ms.=Finito di emergere @1 blocchi in @2ms +emergeblocks update: @1/@2 blocks emerged (@3%)=aggiornamento emergeblocks: @1/@2 blocchi emersi (@3%) +(here [<radius>]) | (<pos1> <pos2>)=(here [<raggio>]) | (<pos1> <pos2>) +Load (or, if nonexistent, generate) map blocks contained in area pos1 to pos2 (<pos1> and <pos2> must be in parentheses)=Carica (o, se non esiste, genera) blocchi mappa contenuti nell'area tra pos1 e pos2 (<pos1> e <pos2> vanno tra parentesi) +Started emerge of area ranging from @1 to @2.=Iniziata emersione dell'area tra @1 e @2. +Delete map blocks contained in area pos1 to pos2 (<pos1> and <pos2> must be in parentheses)=Cancella i blocchi mappa contenuti nell'area tra pos1 e pos2 (<pos1> e <pos2> vanno tra parentesi) +Successfully cleared area ranging from @1 to @2.=Area tra @1 e @2 ripulita con successo. +Failed to clear one or more blocks in area.=Errore nel ripulire uno o più blocchi mappa nell'area +Resets lighting in the area between pos1 and pos2 (<pos1> and <pos2> must be in parentheses)=Reimposta l'illuminazione nell'area tra pos1 e po2 (<pos1> e <pos2> vanno tra parentesi) +Successfully reset light in the area ranging from @1 to @2.=Luce nell'area tra @1 e @2 reimpostata con successo. +Failed to load one or more blocks in area.=Errore nel caricare uno o più blocchi mappa nell'area. +List mods installed on the server=Elenca le mod installate nel server +Cannot give an empty item.=Impossibile dare un oggetto vuoto. +Cannot give an unknown item.=Impossibile dare un oggetto sconosciuto. +Giving 'ignore' is not allowed.=Non è permesso dare 'ignore'. +@1 is not a known player.=@1 non è un giocatore conosciuto. +@1 partially added to inventory.=@1 parzialmente aggiunto all'inventario. +@1 could not be added to inventory.=@1 non può essere aggiunto all'inventario. +@1 added to inventory.=@1 aggiunto all'inventario. +@1 partially added to inventory of @2.=@1 parzialmente aggiunto all'inventario di @2. +@1 could not be added to inventory of @2.=Non è stato possibile aggiungere @1 all'inventario di @2. +@1 added to inventory of @2.=@1 aggiunto all'inventario di @2. +<name> <ItemString> [<count> [<wear>]]=<nome> <NomeOggetto> [<quantità> [<usura>]] +Give item to player=Dà oggetti ai giocatori +Name and ItemString required.=Richiesti nome e NomeOggetto. +<ItemString> [<count> [<wear>]]=<NomeOggetto> [<quantità> [<usura>]] +Give item to yourself=Dà oggetti a te stessǝ +ItemString required.=Richiesto NomeOggetto. +<EntityName> [<X>,<Y>,<Z>]=<NomeEntità> [<X>,<Y>,<Z>] +Spawn entity at given (or your) position=Genera un'entità alla data coordinata (o la tua) +EntityName required.=Richiesto NomeEntità +Unable to spawn entity, player is nil.=Impossibile generare l'entità, il giocatore è nil. +Cannot spawn an unknown entity.=Impossibile generare un'entità sconosciuta. +Invalid parameters (@1).=Parametri non validi (@1). +@1 spawned.=Generata entità @1. +@1 failed to spawn.=Errore nel generare @1 +Destroy item in hand=Distrugge l'oggetto in mano +Unable to pulverize, no player.=Impossibile polverizzare, nessun giocatore. +Unable to pulverize, no item in hand.=Impossibile polverizzare, nessun oggetto in mano. +An item was pulverized.=Un oggetto è stato polverizzato. +[<range>] [<seconds>] [<limit>]=[<raggio>] [<secondi>] [<limite>] +Check who last touched a node or a node near it within the time specified by <seconds>. Default: range @= 0, seconds @= 86400 @= 24h, limit @= 5. Set <seconds> to inf for no time limit=Controlla chi è l'ultimo giocatore che ha toccato un nodo o un nodo nelle sue vicinanze, negli ultimi secondi indicati. Di base: raggio @= 0, secondi @= 86400 @= 24h, limite @= 5. +Rollback functions are disabled.=Le funzioni di rollback sono disabilitate. +That limit is too high!=Il limite è troppo alto! +Checking @1 ...=Controllando @1 ... +Nobody has touched the specified location in @1 seconds.=Nessuno ha toccato il punto specificato negli ultimi @1 secondi. +@1 @2 @3 -> @4 @5 seconds ago.=@1 @2 @3 -> @4 @5 secondi fa. +Punch a node (range@=@1, seconds@=@2, limit@=@3).=Colpisce un nodo (raggio@=@1, secondi@=@2, limite@=@3) +(<name> [<seconds>]) | (:<actor> [<seconds>])=(<nome> [<secondi>]) | (:<attore> [<secondi>]) +Revert actions of a player. Default for <seconds> is 60. Set <seconds> to inf for no time limit=Riavvolge le azioni di un giocatore. Di base, <secondi> è 60. Imposta <secondi> a inf per nessun limite di tempo +Invalid parameters. See /help rollback and /help rollback_check.=Parametri non validi. Vedi /help rollback e /help rollback_check. +Reverting actions of player '@1' since @2 seconds.=Riavvolge le azioni del giocatore '@1' avvenute negli ultimi @2 secondi. +Reverting actions of @1 since @2 seconds.=Riavvolge le azioni di @1 avvenute negli ultimi @2 secondi. +(log is too long to show)=(il log è troppo lungo per essere mostrato) +Reverting actions succeeded.=Riavvolgimento azioni avvenuto con successo. +Reverting actions FAILED.=Errore nel riavvolgere le azioni. +Show server status=Mostra lo stato del server +This command was disabled by a mod or game.=Questo comando è stato disabilitato da una mod o dal gioco. +[<0..23>:<0..59> | <0..24000>]=[<0..23>:<0..59> | <0..24000>] +Show or set time of day=Mostra o imposta l'orario della giornata +Current time is @1:@2.=Orario corrente: @1:@2. +You don't have permission to run this command (missing privilege: @1).=Non hai il permesso di eseguire questo comando (privilegio mancante: @1) +Invalid time.=Orario non valido. +Time of day changed.=Orario della giornata cambiato. +Invalid hour (must be between 0 and 23 inclusive).=Ora non valida (deve essere tra 0 e 23 inclusi) +Invalid minute (must be between 0 and 59 inclusive).=Minuto non valido (deve essere tra 0 e 59 inclusi) +Show day count since world creation=Mostra il conteggio dei giorni da quando il mondo è stato creato +Current day is @1.=Giorno attuale: @1. +[<delay_in_seconds> | -1] [reconnect] [<message>]=[<ritardo_in_secondi> | -1] [reconnect] [<messaggio>] +Shutdown server (-1 cancels a delayed shutdown)=Arresta il server (-1 annulla un arresto programmato) +Server shutting down (operator request).=Arresto del server in corso (per richiesta dell'operatore) +Ban the IP of a player or show the ban list=Bandisce l'IP del giocatore o mostra la lista di quelli banditi +The ban list is empty.=La lista banditi è vuota. +Ban list: @1=Lista banditi: @1 +Player is not online.=Il giocatore non è connesso. +Failed to ban player.=Errore nel bandire il giocatore. +Banned @1.=@1 banditǝ. +<name> | <IP_address>=<nome> | <indirizzo_IP> +Remove IP ban belonging to a player/IP=Perdona l'IP appartenente a un giocatore/IP +Failed to unban player/IP.=Errore nel perdonare il giocatore/IP +Unbanned @1.=@1 perdonatǝ +<name> [<reason>]=<nome> [<ragione>] +Kick a player=Caccia un giocatore +Failed to kick player @1.=Errore nel cacciare il giocatore @1. +Kicked @1.=@1 cacciatǝ. +[full | quick]=[full | quick] +Clear all objects in world=Elimina tutti gli oggetti/entità nel mondo +Invalid usage, see /help clearobjects.=Uso incorretto, vedi /help clearobjects. +Clearing all objects. This may take a long time. You may experience a timeout. (by @1)=Eliminando tutti gli oggetti/entità. Questo potrebbe richiedere molto tempo e farti eventualmente crashare. (di @1) +Cleared all objects.=Tutti gli oggetti sono stati eliminati. +<name> <message>=<nome> <messaggio> +Send a direct message to a player=Invia un messaggio privato al giocatore +Invalid usage, see /help msg.=Uso incorretto, vedi /help msg +The player @1 is not online.=Il giocatore @1 non è connesso. +DM from @1: @2=Messaggio privato da @1: @2 +Message sent.=Messaggio inviato. +Get the last login time of a player or yourself=Ritorna l'ultimo accesso di un giocatore o di te stessǝ +@1's last login time was @2.=L'ultimo accesso di @1 è avvenuto il @2 +@1's last login time is unknown.=L'ultimo accesso di @1 non è conosciuto +Clear the inventory of yourself or another player=Svuota l'inventario tuo o di un altro giocatore +You don't have permission to clear another player's inventory (missing privilege: @1).=Non hai il permesso di svuotare l'inventario di un altro giocatore (privilegio mancante: @1). +@1 cleared your inventory.=@1 ha svuotato il tuo inventario. +Cleared @1's inventory.=L'inventario di @1 è stato svuotato. +Player must be online to clear inventory!=Il giocatore deve essere connesso per svuotarne l'inventario! +Players can't be killed, damage has been disabled.=I giocatori non possono essere uccisi, il danno è disabilitato. +Player @1 is not online.=Il giocatore @1 non è connesso. +You are already dead.=Sei già mortǝ. +@1 is already dead.=@1 è già mortǝ. +@1 has been killed.=@1 è stato uccisǝ. +Kill player or yourself=Uccide un giocatore o te stessǝ +Available commands: @1=Comandi disponibili: @1 +Use '/help <cmd>' to get more information, or '/help all' to list everything.=Usa '/help <comando>' per ottenere più informazioni, o '/help all' per elencare tutti i comandi. +Available commands:=Comandi disponibili: +Command not available: @1=Comando non disponibile: @1 +[all | privs | <cmd>]=[all | privs | <comando>] +Get help for commands or list privileges=Richiama la finestra d'aiuto dei comandi o dei privilegi +Available privileges:=Privilegi disponibili: +Command=Comando +Parameters=Parametri +For more information, click on any entry in the list.=Per più informazioni, clicca su una qualsiasi voce dell'elenco. +Double-click to copy the entry to the chat history.=Doppio click per copiare la voce nella cronologia della chat. +Command: @1 @2=Comando: @1 @2 +Available commands: (see also: /help <cmd>)=Comandi disponibili: (vedi anche /help <comando>) +Close=Chiudi +Privilege=Privilegio +Description=Descrizione +print [<filter>] | dump [<filter>] | save [<format> [<filter>]] | reset=print [<filtro>] | dump [<filtro>] | save [<formato> [<filtro>]] | reset +Handle the profiler and profiling data=Gestisce il profiler e i dati da esso elaborati +Statistics written to action log.=Statistiche scritte nel log delle azioni. +Statistics were reset.=Le statistiche sono state resettate. +Usage: @1=Utilizzo: @1 +Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change).=I formati supportati sono txt, csv, lua, json e json_pretty (le strutture potrebbero essere soggetti a cambiamenti). +(no description)=(nessuna descrizione) +Can interact with things and modify the world=Si può interagire con le cose e modificare il mondo +Can speak in chat=Si può parlare in chat +Can modify 'shout' and 'interact' privileges=Si possono modificare i privilegi 'shout' e 'interact' +Can modify privileges=Si possono modificare i privilegi +Can teleport self=Si può teletrasportare se stessз +Can teleport other players=Si possono teletrasportare gli altri giocatori +Can set the time of day using /time=Si può impostate l'orario della giornata tramite /time +Can do server maintenance stuff=Si possono eseguire operazioni di manutenzione del server +Can bypass node protection in the world=Si può aggirare la protezione dei nodi nel mondo +Can ban and unban players=Si possono bandire e perdonare i giocatori +Can kick players=Si possono cacciare i giocatori +Can use /give and /giveme=Si possono usare /give e /give me +Can use /setpassword and /clearpassword=Si possono usare /setpassword e /clearpassword +Can use fly mode=Si può usare la modalità volo +Can use fast mode=Si può usare la modalità rapida +Can fly through solid nodes using noclip mode=Si può volare attraverso i nodi solidi con la modalità incorporea +Can use the rollback functionality=Si può usare la funzione di rollback +Allows enabling various debug options that may affect gameplay=Permette di abilitare varie opzioni di debug che potrebbero influenzare l'esperienza di gioco +Unknown Item=Oggetto sconosciuto +Air=Aria +Ignore=Ignora +You can't place 'ignore' nodes!=Non puoi piazzare nodi 'ignore'! diff --git a/builtin/locale/template.txt b/builtin/locale/template.txt new file mode 100644 index 000000000..c5ace1a2f --- /dev/null +++ b/builtin/locale/template.txt @@ -0,0 +1,224 @@ +# textdomain: __builtin +Empty command.= +Invalid command: @1= +Invalid command usage.= +You don't have permission to run this command (missing privileges: @1).= +Unable to get position of player @1.= +Incorrect area format. Expected: (x1,y1,z1) (x2,y2,z2)= +<action>= +Show chat action (e.g., '/me orders a pizza' displays '<player name> orders a pizza')= +Show the name of the server owner= +The administrator of this server is @1.= +There's no administrator named in the config file.= +[<name>]= +Show privileges of yourself or another player= +Player @1 does not exist.= +Privileges of @1: @2= +<privilege>= +Return list of all online players with privilege= +Invalid parameters (see /help haspriv).= +Unknown privilege!= +Players online with the "@1" privilege: @2= +Your privileges are insufficient.= +Unknown privilege: @1= +@1 granted you privileges: @2= +<name> (<privilege> | all)= +Give privileges to player= +Invalid parameters (see /help grant).= +<privilege> | all= +Grant privileges to yourself= +Invalid parameters (see /help grantme).= +@1 revoked privileges from you: @2= +Remove privileges from player= +Invalid parameters (see /help revoke).= +Revoke privileges from yourself= +Invalid parameters (see /help revokeme).= +<name> <password>= +Set player's password= +Name field required.= +Your password was cleared by @1.= +Password of player "@1" cleared.= +Your password was set by @1.= +Password of player "@1" set.= +<name>= +Set empty password for a player= +Reload authentication data= +Done.= +Failed.= +Remove a player's data= +Player "@1" removed.= +No such player "@1" to remove.= +Player "@1" is connected, cannot remove.= +Unhandled remove_player return code @1.= +Cannot teleport out of map bounds!= +Cannot get player with name @1.= +Cannot teleport, @1 is attached to an object!= +Teleporting @1 to @2.= +One does not teleport to oneself.= +Cannot get teleportee with name @1.= +Cannot get target player with name @1.= +Teleporting @1 to @2 at @3.= +<X>,<Y>,<Z> | <to_name> | <name> <X>,<Y>,<Z> | <name> <to_name>= +Teleport to position or player= +You don't have permission to teleport other players (missing privilege: @1).= +([-n] <name> <value>) | <name>= +Set or read server configuration setting= +Failed. Use '/set -n <name> <value>' to create a new setting.= +@1 @= @2= +<not set>= +Invalid parameters (see /help set).= +Finished emerging @1 blocks in @2ms.= +emergeblocks update: @1/@2 blocks emerged (@3%)= +(here [<radius>]) | (<pos1> <pos2>)= +Load (or, if nonexistent, generate) map blocks contained in area pos1 to pos2 (<pos1> and <pos2> must be in parentheses)= +Started emerge of area ranging from @1 to @2.= +Delete map blocks contained in area pos1 to pos2 (<pos1> and <pos2> must be in parentheses)= +Successfully cleared area ranging from @1 to @2.= +Failed to clear one or more blocks in area.= +Resets lighting in the area between pos1 and pos2 (<pos1> and <pos2> must be in parentheses)= +Successfully reset light in the area ranging from @1 to @2.= +Failed to load one or more blocks in area.= +List mods installed on the server= +Cannot give an empty item.= +Cannot give an unknown item.= +Giving 'ignore' is not allowed.= +@1 is not a known player.= +@1 partially added to inventory.= +@1 could not be added to inventory.= +@1 added to inventory.= +@1 partially added to inventory of @2.= +@1 could not be added to inventory of @2.= +@1 added to inventory of @2.= +<name> <ItemString> [<count> [<wear>]]= +Give item to player= +Name and ItemString required.= +<ItemString> [<count> [<wear>]]= +Give item to yourself= +ItemString required.= +<EntityName> [<X>,<Y>,<Z>]= +Spawn entity at given (or your) position= +EntityName required.= +Unable to spawn entity, player is nil.= +Cannot spawn an unknown entity.= +Invalid parameters (@1).= +@1 spawned.= +@1 failed to spawn.= +Destroy item in hand= +Unable to pulverize, no player.= +Unable to pulverize, no item in hand.= +An item was pulverized.= +[<range>] [<seconds>] [<limit>]= +Check who last touched a node or a node near it within the time specified by <seconds>. Default: range @= 0, seconds @= 86400 @= 24h, limit @= 5. Set <seconds> to inf for no time limit= +Rollback functions are disabled.= +That limit is too high!= +Checking @1 ...= +Nobody has touched the specified location in @1 seconds.= +@1 @2 @3 -> @4 @5 seconds ago.= +Punch a node (range@=@1, seconds@=@2, limit@=@3).= +(<name> [<seconds>]) | (:<actor> [<seconds>])= +Revert actions of a player. Default for <seconds> is 60. Set <seconds> to inf for no time limit= +Invalid parameters. See /help rollback and /help rollback_check.= +Reverting actions of player '@1' since @2 seconds.= +Reverting actions of @1 since @2 seconds.= +(log is too long to show)= +Reverting actions succeeded.= +Reverting actions FAILED.= +Show server status= +This command was disabled by a mod or game.= +[<0..23>:<0..59> | <0..24000>]= +Show or set time of day= +Current time is @1:@2.= +You don't have permission to run this command (missing privilege: @1).= +Invalid time.= +Time of day changed.= +Invalid hour (must be between 0 and 23 inclusive).= +Invalid minute (must be between 0 and 59 inclusive).= +Show day count since world creation= +Current day is @1.= +[<delay_in_seconds> | -1] [reconnect] [<message>]= +Shutdown server (-1 cancels a delayed shutdown)= +Server shutting down (operator request).= +Ban the IP of a player or show the ban list= +The ban list is empty.= +Ban list: @1= +Player is not online.= +Failed to ban player.= +Banned @1.= +<name> | <IP_address>= +Remove IP ban belonging to a player/IP= +Failed to unban player/IP.= +Unbanned @1.= +<name> [<reason>]= +Kick a player= +Failed to kick player @1.= +Kicked @1.= +[full | quick]= +Clear all objects in world= +Invalid usage, see /help clearobjects.= +Clearing all objects. This may take a long time. You may experience a timeout. (by @1)= +Cleared all objects.= +<name> <message>= +Send a direct message to a player= +Invalid usage, see /help msg.= +The player @1 is not online.= +DM from @1: @2= +Message sent.= +Get the last login time of a player or yourself= +@1's last login time was @2.= +@1's last login time is unknown.= +Clear the inventory of yourself or another player= +You don't have permission to clear another player's inventory (missing privilege: @1).= +@1 cleared your inventory.= +Cleared @1's inventory.= +Player must be online to clear inventory!= +Players can't be killed, damage has been disabled.= +Player @1 is not online.= +You are already dead.= +@1 is already dead.= +@1 has been killed.= +Kill player or yourself= +Available commands: @1= +Use '/help <cmd>' to get more information, or '/help all' to list everything.= +Available commands:= +Command not available: @1= +[all | privs | <cmd>]= +Get help for commands or list privileges= +Available privileges:= +Command= +Parameters= +For more information, click on any entry in the list.= +Double-click to copy the entry to the chat history.= +Command: @1 @2= +Available commands: (see also: /help <cmd>)= +Close= +Privilege= +Description= +print [<filter>] | dump [<filter>] | save [<format> [<filter>]] | reset= +Handle the profiler and profiling data= +Statistics written to action log.= +Statistics were reset.= +Usage: @1= +Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change).= +(no description)= +Can interact with things and modify the world= +Can speak in chat= +Can modify 'shout' and 'interact' privileges= +Can modify privileges= +Can teleport self= +Can teleport other players= +Can set the time of day using /time= +Can do server maintenance stuff= +Can bypass node protection in the world= +Can ban and unban players= +Can kick players= +Can use /give and /giveme= +Can use /setpassword and /clearpassword= +Can use fly mode= +Can use fast mode= +Can fly through solid nodes using noclip mode= +Can use the rollback functionality= +Allows enabling various debug options that may affect gameplay= +Unknown Item= +Air= +Ignore= +You can't place 'ignore' nodes!= diff --git a/builtin/mainmenu/common.lua b/builtin/mainmenu/common.lua index cd896f9ec..6db351048 100644 --- a/builtin/mainmenu/common.lua +++ b/builtin/mainmenu/common.lua @@ -14,14 +14,11 @@ --You should have received a copy of the GNU Lesser General Public License along --with this program; if not, write to the Free Software Foundation, Inc., --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. --------------------------------------------------------------------------------- + -- Global menu data --------------------------------------------------------------------------------- menudata = {} --------------------------------------------------------------------------------- -- Local cached values --------------------------------------------------------------------------------- local min_supp_proto, max_supp_proto function common_update_cached_supp_proto() @@ -29,14 +26,12 @@ function common_update_cached_supp_proto() max_supp_proto = core.get_max_supp_proto() end common_update_cached_supp_proto() --------------------------------------------------------------------------------- + -- Menu helper functions --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- local function render_client_count(n) - if n > 99 then return '99+' - elseif n >= 0 then return tostring(n) + if n > 999 then return '99+' + elseif n >= 0 then return tostring(n) else return '?' end end @@ -50,21 +45,7 @@ local function configure_selected_world_params(idx) end end --------------------------------------------------------------------------------- -function image_column(tooltip, flagname) - return "image,tooltip=" .. core.formspec_escape(tooltip) .. "," .. - "0=" .. core.formspec_escape(defaulttexturedir .. "blank.png") .. "," .. - "1=" .. core.formspec_escape(defaulttexturedir .. - (flagname and "server_flags_" .. flagname .. ".png" or "blank.png")) .. "," .. - "2=" .. core.formspec_escape(defaulttexturedir .. "server_ping_4.png") .. "," .. - "3=" .. core.formspec_escape(defaulttexturedir .. "server_ping_3.png") .. "," .. - "4=" .. core.formspec_escape(defaulttexturedir .. "server_ping_2.png") .. "," .. - "5=" .. core.formspec_escape(defaulttexturedir .. "server_ping_1.png") -end - - --------------------------------------------------------------------------------- -function render_serverlist_row(spec, is_favorite) +function render_serverlist_row(spec) local text = "" if spec.name then text = text .. core.formspec_escape(spec.name:trim()) @@ -75,31 +56,29 @@ function render_serverlist_row(spec, is_favorite) end end - local grey_out = not is_server_protocol_compat(spec.proto_min, spec.proto_max) + local grey_out = not spec.is_compatible - local details - if is_favorite then - details = "1," - else - details = "0," - end + local details = {} - if spec.ping then - local ping = spec.ping * 1000 - if ping <= 50 then - details = details .. "2," - elseif ping <= 100 then - details = details .. "3," - elseif ping <= 250 then - details = details .. "4," + if spec.lag or spec.ping then + local lag = (spec.lag or 0) * 1000 + (spec.ping or 0) * 250 + if lag <= 125 then + table.insert(details, "1") + elseif lag <= 175 then + table.insert(details, "2") + elseif lag <= 250 then + table.insert(details, "3") else - details = details .. "5," + table.insert(details, "4") end else - details = details .. "0," + table.insert(details, "0") end - if spec.clients and spec.clients_max then + table.insert(details, ",") + + local color = (grey_out and "#aaaaaa") or ((spec.is_favorite and "#ddddaa") or "#ffffff") + if spec.clients and (spec.clients_max or 0) > 0 then local clients_percent = 100 * spec.clients / spec.clients_max -- Choose a color depending on how many clients are connected @@ -110,38 +89,35 @@ function render_serverlist_row(spec, is_favorite) elseif clients_percent <= 60 then clients_color = '#a1e587' -- 0-60%: green elseif clients_percent <= 90 then clients_color = '#ffdc97' -- 60-90%: yellow elseif clients_percent == 100 then clients_color = '#dd5b5b' -- full server: red (darker) - else clients_color = '#ffba97' -- 90-100%: orange + else clients_color = '#ffba97' -- 90-100%: orange end - details = details .. clients_color .. ',' .. - render_client_count(spec.clients) .. ',/,' .. - render_client_count(spec.clients_max) .. ',' - - elseif grey_out then - details = details .. '#aaaaaa,?,/,?,' + table.insert(details, clients_color) + table.insert(details, render_client_count(spec.clients) .. " / " .. + render_client_count(spec.clients_max)) else - details = details .. ',?,/,?,' + table.insert(details, color) + table.insert(details, "?") end if spec.creative then - details = details .. "1," - else - details = details .. "0," - end - - if spec.damage then - details = details .. "1," + table.insert(details, "1") -- creative icon else - details = details .. "0," + table.insert(details, "0") end if spec.pvp then - details = details .. "1," + table.insert(details, "2") -- pvp icon + elseif spec.damage then + table.insert(details, "1") -- heart icon else - details = details .. "0," + table.insert(details, "0") end - return details .. (grey_out and '#aaaaaa,' or ',') .. text + table.insert(details, color) + table.insert(details, text) + + return table.concat(details, ",") end -------------------------------------------------------------------------------- @@ -150,14 +126,13 @@ os.tempfolder = function() return temp .. DIR_DELIM .. "MT_" .. math.random(0, 10000) end --------------------------------------------------------------------------------- os.tmpname = function() local path = os.tempfolder() io.open(path, "w"):close() return path end - -------------------------------------------------------------------------------- + function menu_render_worldlist() local retval = "" local current_worldlist = menudata.worldlist:get_list() @@ -171,7 +146,6 @@ function menu_render_worldlist() return retval end --------------------------------------------------------------------------------- function menu_handle_key_up_down(fields, textlist, settingname) local oldidx, newidx = core.get_textlist_index(textlist), 1 if fields.key_up or fields.key_down then @@ -188,7 +162,6 @@ function menu_handle_key_up_down(fields, textlist, settingname) return false end --------------------------------------------------------------------------------- function text2textlist(xpos, ypos, width, height, tl_name, textlen, text, transparency) local textlines = core.wrap_text(text, textlen, true) local retval = "textlist[" .. xpos .. "," .. ypos .. ";" .. width .. @@ -206,7 +179,6 @@ function text2textlist(xpos, ypos, width, height, tl_name, textlen, text, transp return retval end --------------------------------------------------------------------------------- function is_server_protocol_compat(server_proto_min, server_proto_max) if (not server_proto_min) or (not server_proto_max) then -- There is no info. Assume the best and act as if we would be compatible. @@ -214,7 +186,7 @@ function is_server_protocol_compat(server_proto_min, server_proto_max) end return min_supp_proto <= server_proto_max and max_supp_proto >= server_proto_min end --------------------------------------------------------------------------------- + function is_server_protocol_compat_or_error(server_proto_min, server_proto_max) if not is_server_protocol_compat(server_proto_min, server_proto_max) then local server_prot_ver_info, client_prot_ver_info @@ -242,7 +214,7 @@ function is_server_protocol_compat_or_error(server_proto_min, server_proto_max) return true end --------------------------------------------------------------------------------- + function menu_worldmt(selected, setting, value) local world = menudata.worldlist:get_list()[selected] if world then diff --git a/builtin/mainmenu/dlg_config_world.lua b/builtin/mainmenu/dlg_config_world.lua index 2cf70c9c9..9bdf92a74 100644 --- a/builtin/mainmenu/dlg_config_world.lua +++ b/builtin/mainmenu/dlg_config_world.lua @@ -74,7 +74,7 @@ local function get_formspec(data) "label[1.75,0;" .. data.worldspec.name .. "]" if mod.is_modpack or mod.type == "game" then - local info = minetest.formspec_escape( + local info = core.formspec_escape( core.get_content_info(mod.path).description) if info == "" then if mod.is_modpack then diff --git a/builtin/mainmenu/dlg_contentstore.lua b/builtin/mainmenu/dlg_contentstore.lua index 7328f3358..b0736a4fd 100644 --- a/builtin/mainmenu/dlg_contentstore.lua +++ b/builtin/mainmenu/dlg_contentstore.lua @@ -15,7 +15,7 @@ --with this program; if not, write to the Free Software Foundation, Inc., --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -if not minetest.get_http_api then +if not core.get_http_api then function create_store_dlg() return messagebox("store", fgettext("ContentDB is not available when Minetest was compiled without cURL")) @@ -27,7 +27,7 @@ end -- before the package list is ordered based on installed state. local store = { packages = {}, packages_full = {}, packages_full_unordered = {} } -local http = minetest.get_http_api() +local http = core.get_http_api() -- Screenshot local screenshot_dir = core.get_cache_path() .. DIR_DELIM .. "cdb" @@ -152,7 +152,7 @@ local function start_install(package) end local function queue_download(package) - local max_concurrent_downloads = tonumber(minetest.settings:get("contentdb_max_concurrent_downloads")) + local max_concurrent_downloads = tonumber(core.settings:get("contentdb_max_concurrent_downloads")) if number_downloading < max_concurrent_downloads then start_install(package) else @@ -320,7 +320,7 @@ function install_dialog.get_formspec() selected_game_idx = i end - games[i] = minetest.formspec_escape(games[i].name) + games[i] = core.formspec_escape(games[i].name) end local selected_game = pkgmgr.games[selected_game_idx] @@ -331,7 +331,7 @@ function install_dialog.get_formspec() local formatted_deps = {} for _, dep in pairs(install_dialog.dependencies) do formatted_deps[#formatted_deps + 1] = "#fff" - formatted_deps[#formatted_deps + 1] = minetest.formspec_escape(dep.name) + formatted_deps[#formatted_deps + 1] = core.formspec_escape(dep.name) if dep.installed then formatted_deps[#formatted_deps + 1] = "#ccf" formatted_deps[#formatted_deps + 1] = fgettext("Already installed") @@ -402,7 +402,7 @@ function install_dialog.handle_submit(this, fields) end if fields.will_install_deps ~= nil then - install_dialog.will_install_deps = minetest.is_yes(fields.will_install_deps) + install_dialog.will_install_deps = core.is_yes(fields.will_install_deps) return true end @@ -553,7 +553,7 @@ function store.load() end end - local timeout = tonumber(minetest.settings:get("curl_file_download_timeout")) + local timeout = tonumber(core.settings:get("curl_file_download_timeout")) local response = http.fetch_sync({ url = url, timeout = timeout }) if not response.succeeded then return @@ -793,8 +793,8 @@ function store.get_formspec(dlgdata) -- title formspec[#formspec + 1] = "label[1.875,0.1;" formspec[#formspec + 1] = core.formspec_escape( - minetest.colorize(mt_color_green, package.title) .. - minetest.colorize("#BFBFBF", " by " .. package.author)) + core.colorize(mt_color_green, package.title) .. + core.colorize("#BFBFBF", " by " .. package.author)) formspec[#formspec + 1] = "]" -- buttons diff --git a/builtin/mainmenu/dlg_create_world.lua b/builtin/mainmenu/dlg_create_world.lua index 5931496c1..1938747fe 100644 --- a/builtin/mainmenu/dlg_create_world.lua +++ b/builtin/mainmenu/dlg_create_world.lua @@ -443,7 +443,7 @@ local function create_world_buttonhandler(this, fields) end if fields["mgv6_biomes"] then - local entry = minetest.formspec_escape(fields["mgv6_biomes"]) + local entry = core.formspec_escape(fields["mgv6_biomes"]) for b=1, #mgv6_biomes do if entry == mgv6_biomes[b][1] then local ftable = core.settings:get_flags("mgv6_spflags") diff --git a/builtin/mainmenu/pkgmgr.lua b/builtin/mainmenu/pkgmgr.lua index bfb5d269a..787936e31 100644 --- a/builtin/mainmenu/pkgmgr.lua +++ b/builtin/mainmenu/pkgmgr.lua @@ -90,7 +90,7 @@ local function load_texture_packs(txtpath, retval) retval[#retval + 1] = { name = item, author = conf:get("author"), - release = tonumber(conf:get("release") or "0"), + release = tonumber(conf:get("release")) or 0, list_name = name, type = "txp", path = path, @@ -135,7 +135,7 @@ function get_mods(path,retval,modpack) -- Read from config toadd.name = name toadd.author = mod_conf.author - toadd.release = tonumber(mod_conf.release or "0") + toadd.release = tonumber(mod_conf.release) or 0 toadd.path = prefix toadd.type = "mod" @@ -413,18 +413,7 @@ function pkgmgr.is_modpack_entirely_enabled(data, name) end ---------- toggles or en/disables a mod or modpack and its dependencies -------- -function pkgmgr.enable_mod(this, toset) - local list = this.data.list:get_list() - local mod = list[this.data.selected_mod] - - -- Game mods can't be enabled or disabled - if mod.is_game_content then - return - end - - local toggled_mods = {} - - local enabled_mods = {} +local function toggle_mod_or_modpack(list, toggled_mods, enabled_mods, toset, mod) if not mod.is_modpack then -- Toggle or en/disable the mod if toset == nil then @@ -443,23 +432,29 @@ function pkgmgr.enable_mod(this, toset) -- interleaved unsupported for i = 1, #list do if list[i].modpack == mod.name then - if toset == nil then - toset = not list[i].enabled - end - if list[i].enabled ~= toset then - list[i].enabled = toset - toggled_mods[#toggled_mods+1] = list[i].name - end - if toset then - enabled_mods[list[i].name] = true - end + toggle_mod_or_modpack(list, toggled_mods, enabled_mods, toset, list[i]) end end end +end + +function pkgmgr.enable_mod(this, toset) + local list = this.data.list:get_list() + local mod = list[this.data.selected_mod] + + -- Game mods can't be enabled or disabled + if mod.is_game_content then + return + end + + local toggled_mods = {} + local enabled_mods = {} + toggle_mod_or_modpack(list, toggled_mods, enabled_mods, toset, mod) + if not toset then -- Mod(s) were disabled, so no dependencies need to be enabled table.sort(toggled_mods) - minetest.log("info", "Following mods were disabled: " .. + core.log("info", "Following mods were disabled: " .. table.concat(toggled_mods, ", ")) return end @@ -496,7 +491,7 @@ function pkgmgr.enable_mod(this, toset) enabled_mods[name] = true local mod_to_enable = list[mod_ids[name]] if not mod_to_enable then - minetest.log("warning", "Mod dependency \"" .. name .. + core.log("warning", "Mod dependency \"" .. name .. "\" not found!") else if mod_to_enable.enabled == false then @@ -517,7 +512,7 @@ function pkgmgr.enable_mod(this, toset) -- Log the list of enabled mods table.sort(toggled_mods) - minetest.log("info", "Following mods were enabled: " .. + core.log("info", "Following mods were enabled: " .. table.concat(toggled_mods, ", ")) end diff --git a/builtin/mainmenu/serverlistmgr.lua b/builtin/mainmenu/serverlistmgr.lua index d98736e54..9876d8ac5 100644 --- a/builtin/mainmenu/serverlistmgr.lua +++ b/builtin/mainmenu/serverlistmgr.lua @@ -47,6 +47,15 @@ function serverlistmgr.sync() }} end + local serverlist_url = core.settings:get("serverlist_url") or "" + if not core.get_http_api or serverlist_url == "" then + serverlistmgr.servers = {{ + name = fgettext("Public server list is disabled"), + description = "" + }} + return + end + if public_downloading then return end diff --git a/builtin/mainmenu/tab_content.lua b/builtin/mainmenu/tab_content.lua index 336730bf4..fb7f121f8 100644 --- a/builtin/mainmenu/tab_content.lua +++ b/builtin/mainmenu/tab_content.lua @@ -146,10 +146,25 @@ local function get_formspec(tabview, name, tabdata) end -------------------------------------------------------------------------------- +local function handle_doubleclick(pkg) + if pkg.type == "txp" then + if core.settings:get("texture_path") == pkg.path then + core.settings:set("texture_path", "") + else + core.settings:set("texture_path", pkg.path) + end + packages = nil + end +end + +-------------------------------------------------------------------------------- local function handle_buttons(tabview, fields, tabname, tabdata) if fields["pkglist"] ~= nil then local event = core.explode_table_event(fields["pkglist"]) tabdata.selected_pkg = event.row + if event.type == "DCL" then + handle_doubleclick(packages:get_list()[tabdata.selected_pkg]) + end return true end diff --git a/builtin/mainmenu/tab_credits.lua b/builtin/mainmenu/tab_credits.lua index 075274798..a34dd58bb 100644 --- a/builtin/mainmenu/tab_credits.lua +++ b/builtin/mainmenu/tab_credits.lua @@ -23,28 +23,37 @@ local core_developers = { "Nathanaël Courant (Nore/Ekdohibs) <nore@mesecons.net>", "Loic Blot (nerzhul/nrz) <loic.blot@unix-experience.fr>", "paramat", - "Auke Kok (sofar) <sofar@foo-projects.org>", "Andrew Ward (rubenwardy) <rw@rubenwardy.com>", "Krock/SmallJoker <mk939@ymail.com>", "Lars Hofhansl <larsh@apache.org>", + "Pierre-Yves Rollo <dev@pyrollo.com>", + "v-rob <robinsonvincent89@gmail.com>", } +-- For updating active/previous contributors, see the script in ./util/gather_git_credits.py + local active_contributors = { - "Hugues Ross [Formspecs]", + "Wuzzy [devtest game, visual corrections]", + "Zughy [Visual improvements, various fixes]", "Maksim (MoNTE48) [Android]", - "DS [Formspecs]", - "pyrollo [Formspecs: Hypertext]", - "v-rob [Formspecs]", - "Jordach [set_sky]", - "random-geek [Formspecs]", - "Wuzzy [Pathfinder, builtin, translations]", - "ANAND (ClobberXD) [Fixes, per-player FOV]", - "Warr1024 [Fixes]", - "Paul Ouellette (pauloue) [Fixes, Script API]", - "Jean-Patrick G (kilbith) <jeanpatrick.guerrero@gmail.com> [Audiovisuals]", - "HybridDog [Script API]", + "numzero [Graphics and rendering]", + "appgurueu [Various internal fixes]", + "Desour [Formspec and vector API changes]", + "HybridDog [Rendering fixes and documentation]", + "Hugues Ross [Graphics-related improvements]", + "ANAND (ClobberXD) [Mouse buttons rebinding]", + "luk3yx [Fixes]", + "hecks [Audiovisuals, Lua API]", + "LoneWolfHT [Object crosshair, documentation fixes]", + "Lejo [Server-related improvements]", + "EvidenceB [Compass HUD element]", + "Paul Ouellette (pauloue) [Lua API, documentation]", + "TheTermos [Collision detection, physics]", + "David CARLIER [Unix & Haiku build fixes]", "dcbrwn [Object shading]", - "srifqi [Fixes]", + "Elias Fleckenstein [API features/fixes]", + "Jean-Patrick Guerrero (kilbith) [model element, visual fixes]", + "k.h.lai [Memory leak fixes, documentation]", } local previous_core_developers = { @@ -60,30 +69,23 @@ local previous_core_developers = { "sapier", "Zeno", "ShadowNinja <shadowninja@minetest.net>", + "Auke Kok (sofar) <sofar@foo-projects.org>", } local previous_contributors = { "Nils Dagsson Moskopp (erlehmann) <nils@dieweltistgarnichtso.net> [Minetest Logo]", - "Dániel Juhász (juhdanad) <juhdanad@gmail.com>", "red-001 <red-001@outlook.ie>", - "numberZero [Audiovisuals: meshgen]", "Giuseppe Bilotta", + "Dániel Juhász (juhdanad) <juhdanad@gmail.com>", "MirceaKitsune <mirceakitsune@gmail.com>", "Constantin Wenger (SpeedProg)", "Ciaran Gultnieks (CiaranG)", "stujones11 [Android UX improvements]", - "Jeija <jeija@mesecons.net> [HTTP, particles]", - "Vincent Glize (Dumbeldor) [Cleanups, CSM APIs]", - "Ben Deutsch [Rendering, Fixes, SQLite auth]", - "TeTpaAka [Hand overriding, nametag colors]", - "Rui [Sound Pitch]", - "Duane Robertson <duane@duanerobertson.com> [MGValleys]", - "Raymoo [Tool Capabilities]", "Rogier <rogier777@gmail.com> [Fixes]", "Gregory Currie (gregorycu) [optimisation]", - "TriBlade9 <triblade9@mail.com> [Audiovisuals]", - "T4im [Profiler]", - "Jurgen Doser (doserj) <jurgen.doser@gmail.com>", + "srifqi [Fixes]", + "JacobF", + "Jeija <jeija@mesecons.net> [HTTP, particles]", } local function buildCreditList(source) diff --git a/builtin/mainmenu/tab_online.lua b/builtin/mainmenu/tab_online.lua index e6748ed88..fb7409864 100644 --- a/builtin/mainmenu/tab_online.lua +++ b/builtin/mainmenu/tab_online.lua @@ -15,17 +15,50 @@ --with this program; if not, write to the Free Software Foundation, Inc., --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. --------------------------------------------------------------------------------- +local function get_sorted_servers() + local servers = { + fav = {}, + public = {}, + incompatible = {} + } + + local favs = serverlistmgr.get_favorites() + local taken_favs = {} + local result = menudata.search_result or serverlistmgr.servers + for _, server in ipairs(result) do + server.is_favorite = false + for index, fav in ipairs(favs) do + if server.address == fav.address and server.port == fav.port then + taken_favs[index] = true + server.is_favorite = true + break + end + end + server.is_compatible = is_server_protocol_compat(server.proto_min, server.proto_max) + if server.is_favorite then + table.insert(servers.fav, server) + elseif server.is_compatible then + table.insert(servers.public, server) + else + table.insert(servers.incompatible, server) + end + end + + if not menudata.search_result then + for index, fav in ipairs(favs) do + if not taken_favs[index] then + table.insert(servers.fav, fav) + end + end + end + + return servers +end + local function get_formspec(tabview, name, tabdata) -- Update the cached supported proto info, -- it may have changed after a change by the settings menu. common_update_cached_supp_proto() - local selected - if menudata.search_result then - selected = menudata.search_result[tabdata.selected] - else - selected = serverlistmgr.servers[tabdata.selected] - end if not tabdata.search_for then tabdata.search_for = "" @@ -33,128 +66,221 @@ local function get_formspec(tabview, name, tabdata) local retval = -- Search - "field[0.15,0.075;5.91,1;te_search;;" .. core.formspec_escape(tabdata.search_for) .. "]" .. - "image_button[5.63,-.165;.83,.83;" .. core.formspec_escape(defaulttexturedir .. "search.png") .. ";btn_mp_search;]" .. - "image_button[6.3,-.165;.83,.83;" .. core.formspec_escape(defaulttexturedir .. "clear.png") .. ";btn_mp_clear;]" .. - "image_button[6.97,-.165;.83,.83;" .. core.formspec_escape(defaulttexturedir .. "refresh.png") - .. ";btn_mp_refresh;]" .. + "field[0.25,0.25;7,0.75;te_search;;" .. core.formspec_escape(tabdata.search_for) .. "]" .. + "container[7.25,0.25]" .. + "image_button[0,0;0.75,0.75;" .. core.formspec_escape(defaulttexturedir .. "search.png") .. ";btn_mp_search;]" .. + "image_button[0.75,0;0.75,0.75;" .. core.formspec_escape(defaulttexturedir .. "clear.png") .. ";btn_mp_clear;]" .. + "image_button[1.5,0;0.75,0.75;" .. core.formspec_escape(defaulttexturedir .. "refresh.png") .. ";btn_mp_refresh;]" .. + "tooltip[btn_mp_clear;" .. fgettext("Clear") .. "]" .. + "tooltip[btn_mp_search;" .. fgettext("Search") .. "]" .. + "tooltip[btn_mp_refresh;" .. fgettext("Refresh") .. "]" .. + "container_end[]" .. + + "container[9.75,0]" .. + "box[0,0;5.75,7;#666666]" .. -- Address / Port - "label[7.75,-0.25;" .. fgettext("Address / Port") .. "]" .. - "field[8,0.65;3.25,0.5;te_address;;" .. + "label[0.25,0.35;" .. fgettext("Address") .. "]" .. + "label[4.25,0.35;" .. fgettext("Port") .. "]" .. + "field[0.25,0.5;4,0.75;te_address;;" .. core.formspec_escape(core.settings:get("address")) .. "]" .. - "field[11.1,0.65;1.4,0.5;te_port;;" .. + "field[4.25,0.5;1.25,0.75;te_port;;" .. core.formspec_escape(core.settings:get("remote_port")) .. "]" .. -- Name / Password - "label[7.75,0.95;" .. fgettext("Name / Password") .. "]" .. - "field[8,1.85;2.9,0.5;te_name;;" .. + "label[0.25,1.55;" .. fgettext("Name") .. "]" .. + "label[3,1.55;" .. fgettext("Password") .. "]" .. + "field[0.25,1.75;2.75,0.75;te_name;;" .. core.formspec_escape(core.settings:get("name")) .. "]" .. - "pwdfield[10.73,1.85;1.77,0.5;te_pwd;]" .. + "pwdfield[3,1.75;2.5,0.75;te_pwd;]" .. -- Description Background - "box[7.73,2.25;4.25,2.6;#999999]".. + "label[0.25,2.75;" .. fgettext("Server Description") .. "]" .. + "box[0.25,3;5.25,2.75;#999999]".. -- Connect - "button[9.88,4.9;2.3,1;btn_mp_connect;" .. fgettext("Connect") .. "]" + "button[3,6;2.5,0.75;btn_mp_connect;" .. fgettext("Connect") .. "]" - if tabdata.selected and selected then + if tabdata.selected then if gamedata.fav then - retval = retval .. "button[7.73,4.9;2.3,1;btn_delete_favorite;" .. + retval = retval .. "button[0.25,6;2.5,0.75;btn_delete_favorite;" .. fgettext("Del. Favorite") .. "]" end - if selected.description then - retval = retval .. "textarea[8.1,2.3;4.23,2.9;;;" .. - core.formspec_escape((gamedata.serverdescription or ""), true) .. "]" + if gamedata.serverdescription then + retval = retval .. "textarea[0.25,3;5.25,2.75;;;" .. + core.formspec_escape(gamedata.serverdescription) .. "]" end end - --favorites + retval = retval .. "container_end[]" + + -- Table retval = retval .. "tablecolumns[" .. - image_column(fgettext("Favorite"), "favorite") .. ";" .. - image_column(fgettext("Ping")) .. ",padding=0.25;" .. - "color,span=3;" .. - "text,align=right;" .. -- clients - "text,align=center,padding=0.25;" .. -- "/" - "text,align=right,padding=0.25;" .. -- clients_max - image_column(fgettext("Creative mode"), "creative") .. ",padding=1;" .. - image_column(fgettext("Damage enabled"), "damage") .. ",padding=0.25;" .. - --~ PvP = Player versus Player - image_column(fgettext("PvP enabled"), "pvp") .. ",padding=0.25;" .. + "image,tooltip=" .. fgettext("Ping") .. "," .. + "0=" .. core.formspec_escape(defaulttexturedir .. "blank.png") .. "," .. + "1=" .. core.formspec_escape(defaulttexturedir .. "server_ping_4.png") .. "," .. + "2=" .. core.formspec_escape(defaulttexturedir .. "server_ping_3.png") .. "," .. + "3=" .. core.formspec_escape(defaulttexturedir .. "server_ping_2.png") .. "," .. + "4=" .. core.formspec_escape(defaulttexturedir .. "server_ping_1.png") .. "," .. + "5=" .. core.formspec_escape(defaulttexturedir .. "server_favorite.png") .. "," .. + "6=" .. core.formspec_escape(defaulttexturedir .. "server_public.png") .. "," .. + "7=" .. core.formspec_escape(defaulttexturedir .. "server_incompatible.png") .. ";" .. "color,span=1;" .. - "text,padding=1]" .. - "table[-0.15,0.6;7.75,5.15;favorites;" - - if menudata.search_result then - local favs = serverlistmgr.get_favorites() - for i = 1, #menudata.search_result do - local server = menudata.search_result[i] - for fav_id = 1, #favs do - if server.address == favs[fav_id].address and - server.port == favs[fav_id].port then - server.is_favorite = true - end - end - - if i ~= 1 then - retval = retval .. "," - end - - retval = retval .. render_serverlist_row(server, server.is_favorite) - end - elseif #serverlistmgr.servers > 0 then - local favs = serverlistmgr.get_favorites() - if #favs > 0 then - for i = 1, #favs do - for j = 1, #serverlistmgr.servers do - if serverlistmgr.servers[j].address == favs[i].address and - serverlistmgr.servers[j].port == favs[i].port then - table.insert(serverlistmgr.servers, i, table.remove(serverlistmgr.servers, j)) - end - end - if favs[i].address ~= serverlistmgr.servers[i].address then - table.insert(serverlistmgr.servers, i, favs[i]) - end + "text,align=inline;".. + "color,span=1;" .. + "text,align=inline,width=4.25;" .. + "image,tooltip=" .. fgettext("Creative mode") .. "," .. + "0=" .. core.formspec_escape(defaulttexturedir .. "blank.png") .. "," .. + "1=" .. core.formspec_escape(defaulttexturedir .. "server_flags_creative.png") .. "," .. + "align=inline,padding=0.25,width=1.5;" .. + --~ PvP = Player versus Player + "image,tooltip=" .. fgettext("Damage / PvP") .. "," .. + "0=" .. core.formspec_escape(defaulttexturedir .. "blank.png") .. "," .. + "1=" .. core.formspec_escape(defaulttexturedir .. "server_flags_damage.png") .. "," .. + "2=" .. core.formspec_escape(defaulttexturedir .. "server_flags_pvp.png") .. "," .. + "align=inline,padding=0.25,width=1.5;" .. + "color,align=inline,span=1;" .. + "text,align=inline,padding=1]" .. + "table[0.25,1;9.25,5.75;servers;" + + local servers = get_sorted_servers() + + local dividers = { + fav = "5,#ffff00," .. fgettext("Favorites") .. ",,,0,0,,", + public = "6,#4bdd42," .. fgettext("Public Servers") .. ",,,0,0,,", + incompatible = "7,"..mt_color_grey.."," .. fgettext("Incompatible Servers") .. ",,,0,0,," + } + local order = {"fav", "public", "incompatible"} + + tabdata.lookup = {} -- maps row number to server + local rows = {} + for _, section in ipairs(order) do + local section_servers = servers[section] + if next(section_servers) ~= nil then + rows[#rows + 1] = dividers[section] + for _, server in ipairs(section_servers) do + tabdata.lookup[#rows + 1] = server + rows[#rows + 1] = render_serverlist_row(server) end end - - retval = retval .. render_serverlist_row(serverlistmgr.servers[1], (#favs > 0)) - for i = 2, #serverlistmgr.servers do - retval = retval .. "," .. render_serverlist_row(serverlistmgr.servers[i], (i <= #favs)) - end end + retval = retval .. table.concat(rows, ",") + if tabdata.selected then retval = retval .. ";" .. tabdata.selected .. "]" else retval = retval .. ";0]" end - return retval + return retval, "size[15.5,7,false]real_coordinates[true]" end -------------------------------------------------------------------------------- -local function main_button_handler(tabview, fields, name, tabdata) - local serverlist = menudata.search_result or serverlistmgr.servers +local function search_server_list(input) + menudata.search_result = nil + if #serverlistmgr.servers < 2 then + return + end + + -- setup the keyword list + local keywords = {} + for word in input:gmatch("%S+") do + word = word:gsub("(%W)", "%%%1") + table.insert(keywords, word) + end + + if #keywords == 0 then + return + end + + menudata.search_result = {} + + -- Search the serverlist + local search_result = {} + for i = 1, #serverlistmgr.servers do + local server = serverlistmgr.servers[i] + local found = 0 + for k = 1, #keywords do + local keyword = keywords[k] + if server.name then + local sername = server.name:lower() + local _, count = sername:gsub(keyword, keyword) + found = found + count * 4 + end + + if server.description then + local desc = server.description:lower() + local _, count = desc:gsub(keyword, keyword) + found = found + count * 2 + end + end + if found > 0 then + local points = (#serverlistmgr.servers - i) / 5 + found + server.points = points + table.insert(search_result, server) + end + end + + if #search_result == 0 then + return + end + + table.sort(search_result, function(a, b) + return a.points > b.points + end) + menudata.search_result = search_result +end + +local function set_selected_server(tabdata, idx, server) + -- reset selection + if idx == nil or server == nil then + tabdata.selected = nil + + core.settings:set("address", "") + core.settings:set("remote_port", "30000") + return + end + + local address = server.address + local port = server.port + gamedata.serverdescription = server.description + + gamedata.fav = false + for _, fav in ipairs(serverlistmgr.get_favorites()) do + if address == fav.address and port == fav.port then + gamedata.fav = true + break + end + end + + if address and port then + core.settings:set("address", address) + core.settings:set("remote_port", port) + end + tabdata.selected = idx +end + +local function main_button_handler(tabview, fields, name, tabdata) if fields.te_name then gamedata.playername = fields.te_name core.settings:set("name", fields.te_name) end - if fields.favorites then - local event = core.explode_table_event(fields.favorites) - local fav = serverlist[event.row] + if fields.servers then + local event = core.explode_table_event(fields.servers) + local server = tabdata.lookup[event.row] - if event.type == "DCL" then - if event.row <= #serverlist then + if server then + if event.type == "DCL" then if not is_server_protocol_compat_or_error( - fav.proto_min, fav.proto_max) then + server.proto_min, server.proto_max) then return true end - gamedata.address = fav.address - gamedata.port = fav.port + gamedata.address = server.address + gamedata.port = server.port gamedata.playername = fields.te_name gamedata.selected_world = 0 @@ -162,84 +288,32 @@ local function main_button_handler(tabview, fields, name, tabdata) gamedata.password = fields.te_pwd end - gamedata.servername = fav.name - gamedata.serverdescription = fav.description + gamedata.servername = server.name + gamedata.serverdescription = server.description if gamedata.address and gamedata.port then core.settings:set("address", gamedata.address) core.settings:set("remote_port", gamedata.port) core.start() end + return true end - return true - end - - if event.type == "CHG" then - if event.row <= #serverlist then - gamedata.fav = false - local favs = serverlistmgr.get_favorites() - local address = fav.address - local port = fav.port - gamedata.serverdescription = fav.description - - for i = 1, #favs do - if fav.address == favs[i].address and - fav.port == favs[i].port then - gamedata.fav = true - end - end - - if address and port then - core.settings:set("address", address) - core.settings:set("remote_port", port) - end - tabdata.selected = event.row - end - return true - end - end - - if fields.key_up or fields.key_down then - local fav_idx = core.get_table_index("favorites") - local fav = serverlist[fav_idx] - - if fav_idx then - if fields.key_up and fav_idx > 1 then - fav_idx = fav_idx - 1 - elseif fields.key_down and fav_idx < #serverlistmgr.servers then - fav_idx = fav_idx + 1 + if event.type == "CHG" then + set_selected_server(tabdata, event.row, server) + return true end - else - fav_idx = 1 - end - - if not serverlistmgr.servers or not fav then - tabdata.selected = 0 - return true - end - - local address = fav.address - local port = fav.port - gamedata.serverdescription = fav.description - if address and port then - core.settings:set("address", address) - core.settings:set("remote_port", port) end - - tabdata.selected = fav_idx - return true end if fields.btn_delete_favorite then - local current_favorite = core.get_table_index("favorites") - if not current_favorite then return end - - serverlistmgr.delete_favorite(serverlistmgr.servers[current_favorite]) - serverlistmgr.sync() - tabdata.selected = nil - - core.settings:set("address", "") - core.settings:set("remote_port", "30000") + local idx = core.get_table_index("servers") + if not idx then return end + local server = tabdata.lookup[idx] + if not server then return end + + serverlistmgr.delete_favorite(server) + -- the server at [idx+1] will be at idx once list is refreshed + set_selected_server(tabdata, idx, tabdata.lookup[idx+1]) return true end @@ -250,63 +324,13 @@ local function main_button_handler(tabview, fields, name, tabdata) end if fields.btn_mp_search or fields.key_enter_field == "te_search" then - tabdata.selected = 1 - local input = fields.te_search:lower() tabdata.search_for = fields.te_search - - if #serverlistmgr.servers < 2 then - return true - end - - menudata.search_result = {} - - -- setup the keyword list - local keywords = {} - for word in input:gmatch("%S+") do - word = word:gsub("(%W)", "%%%1") - table.insert(keywords, word) + search_server_list(fields.te_search:lower()) + if menudata.search_result then + -- first server in row 2 due to header + set_selected_server(tabdata, 2, menudata.search_result[1]) end - if #keywords == 0 then - menudata.search_result = nil - return true - end - - -- Search the serverlist - local search_result = {} - for i = 1, #serverlistmgr.servers do - local server = serverlistmgr.servers[i] - local found = 0 - for k = 1, #keywords do - local keyword = keywords[k] - if server.name then - local sername = server.name:lower() - local _, count = sername:gsub(keyword, keyword) - found = found + count * 4 - end - - if server.description then - local desc = server.description:lower() - local _, count = desc:gsub(keyword, keyword) - found = found + count * 2 - end - end - if found > 0 then - local points = (#serverlistmgr.servers - i) / 5 + found - server.points = points - table.insert(search_result, server) - end - end - if #search_result > 0 then - table.sort(search_result, function(a, b) - return a.points > b.points - end) - menudata.search_result = search_result - local first_server = search_result[1] - core.settings:set("address", first_server.address) - core.settings:set("remote_port", first_server.port) - gamedata.serverdescription = first_server.description - end return true end @@ -322,20 +346,22 @@ local function main_button_handler(tabview, fields, name, tabdata) gamedata.address = fields.te_address gamedata.port = tonumber(fields.te_port) gamedata.selected_world = 0 - local fav_idx = core.get_table_index("favorites") - local fav = serverlist[fav_idx] - if fav_idx and fav_idx <= #serverlist and - fav.address == gamedata.address and - fav.port == gamedata.port then + local idx = core.get_table_index("servers") + local server = idx and tabdata.lookup[idx] + + set_selected_server(tabdata) - serverlistmgr.add_favorite(fav) + if server and server.address == gamedata.address and + server.port == gamedata.port then - gamedata.servername = fav.name - gamedata.serverdescription = fav.description + serverlistmgr.add_favorite(server) + + gamedata.servername = server.name + gamedata.serverdescription = server.description if not is_server_protocol_compat_or_error( - fav.proto_min, fav.proto_max) then + server.proto_min, server.proto_max) then return true end else @@ -354,6 +380,7 @@ local function main_button_handler(tabview, fields, name, tabdata) core.start() return true end + return false end @@ -362,7 +389,6 @@ local function on_change(type, old_tab, new_tab) serverlistmgr.sync() end --------------------------------------------------------------------------------- return { name = "online", caption = fgettext("Join Game"), diff --git a/builtin/profiler/init.lua b/builtin/profiler/init.lua index a0033d752..7f63dfaea 100644 --- a/builtin/profiler/init.lua +++ b/builtin/profiler/init.lua @@ -15,6 +15,8 @@ --with this program; if not, write to the Free Software Foundation, Inc., --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +local S = core.get_translator("__builtin") + local function get_bool_default(name, default) local val = core.settings:get_bool(name) if val == nil then @@ -40,9 +42,9 @@ function profiler.init_chatcommand() instrumentation.init_chatcommand() end - local param_usage = "print [filter] | dump [filter] | save [format [filter]] | reset" + local param_usage = S("print [<filter>] | dump [<filter>] | save [<format> [<filter>]] | reset") core.register_chatcommand("profiler", { - description = "handle the profiler and profiling data", + description = S("Handle the profiler and profiling data"), params = param_usage, privs = { server=true }, func = function(name, param) @@ -51,21 +53,19 @@ function profiler.init_chatcommand() if command == "dump" then core.log("action", reporter.print(sampler.profile, arg0)) - return true, "Statistics written to action log" + return true, S("Statistics written to action log.") elseif command == "print" then return true, reporter.print(sampler.profile, arg0) elseif command == "save" then return reporter.save(sampler.profile, args[1] or "txt", args[2]) elseif command == "reset" then sampler.reset() - return true, "Statistics were reset" + return true, S("Statistics were reset.") end - return false, string.format( - "Usage: %s\n" .. - "Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change).", - param_usage - ) + return false, + S("Usage: @1", param_usage) .. "\n" .. + S("Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change).") end }) diff --git a/builtin/profiler/reporter.lua b/builtin/profiler/reporter.lua index fed47a36b..5928a3718 100644 --- a/builtin/profiler/reporter.lua +++ b/builtin/profiler/reporter.lua @@ -15,6 +15,10 @@ --with this program; if not, write to the Free Software Foundation, Inc., --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +local S = core.get_translator("__builtin") +-- Note: In this file, only messages are translated +-- but not the table itself, to keep it simple. + local DIR_DELIM, LINE_DELIM = DIR_DELIM, "\n" local table, unpack, string, pairs, io, os = table, unpack, string, pairs, io, os local rep, sprintf, tonumber = string.rep, string.format, tonumber @@ -104,11 +108,11 @@ local TxtFormatter = Formatter:new { end, format = function(self, filter) local profile = self.profile - self:print("Values below show absolute/relative times spend per server step by the instrumented function.") - self:print("A total of %d samples were taken", profile.stats_total.samples) + self:print(S("Values below show absolute/relative times spend per server step by the instrumented function.")) + self:print(S("A total of @1 sample(s) were taken.", profile.stats_total.samples)) if filter then - self:print("The output is limited to '%s'", filter) + self:print(S("The output is limited to '@1'.", filter)) end self:print() @@ -259,19 +263,18 @@ function reporter.save(profile, format, filter) local output, io_err = io.open(path, "w") if not output then - return false, "Saving of profile failed with: " .. io_err + return false, S("Saving of profile failed: @1", io_err) end local content, err = serialize_profile(profile, format, filter) if not content then output:close() - return false, "Saving of profile failed with: " .. err + return false, S("Saving of profile failed: @1", err) end output:write(content) output:close() - local logmessage = "Profile saved to " .. path - core.log("action", logmessage) - return true, logmessage + core.log("action", "Profile saved to " .. path) + return true, S("Profile saved to @1", path) end return reporter diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 8b6227b37..75efe64da 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -75,7 +75,7 @@ free_move (Flying) bool false # If enabled, makes move directions relative to the player's pitch when flying or swimming. pitch_move (Pitch move mode) bool false -# Fast movement (via the "special" key). +# Fast movement (via the "Aux1" key). # This requires the "fast" privilege on the server. fast_move (Fast movement) bool false @@ -99,14 +99,14 @@ invert_mouse (Invert mouse) bool false # Mouse sensitivity multiplier. mouse_sensitivity (Mouse sensitivity) float 0.2 -# If enabled, "special" key instead of "sneak" key is used for climbing down and +# If enabled, "Aux1" key instead of "Sneak" key is used for climbing down and # descending. -aux1_descends (Special key for climbing/descending) bool false +aux1_descends (Aux1 key for climbing/descending) bool false # Double-tapping the jump key toggles fly mode. doubletap_jump (Double tap jump for fly) bool false -# If disabled, "special" key is used to fly fast if both fly and fast mode are +# If disabled, "Aux1" key is used to fly fast if both fly and fast mode are # enabled. always_fly_fast (Always fly and fast) bool true @@ -135,9 +135,9 @@ touchscreen_threshold (Touch screen threshold) int 20 0 100 # If disabled, virtual joystick will center to first-touch's position. fixed_virtual_joystick (Fixed virtual joystick) bool false -# (Android) Use virtual joystick to trigger "aux" button. -# If enabled, virtual joystick will also tap "aux" button when out of main circle. -virtual_joystick_triggers_aux (Virtual joystick triggers aux button) bool false +# (Android) Use virtual joystick to trigger "Aux1" button. +# If enabled, virtual joystick will also tap "Aux1" button when out of main circle. +virtual_joystick_triggers_aux1 (Virtual joystick triggers Aux1 button) bool false # Enable joysticks enable_joysticks (Enable joysticks) bool false @@ -199,7 +199,7 @@ keymap_inventory (Inventory key) key KEY_KEY_I # Key for moving fast in fast mode. # See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 -keymap_special1 (Special key) key KEY_KEY_E +keymap_aux1 (Aux1 key) key KEY_KEY_E # Key for opening the chat window. # See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 @@ -451,6 +451,10 @@ keymap_decrease_viewing_range_min (View range decrease key) key - [**Basic] +# Whether nametag backgrounds should be shown by default. +# Mods may still set a background. +show_nametag_backgrounds (Show nametag backgrounds by default) bool true + # Enable vertex buffer objects. # This should greatly improve graphics performance. enable_vbo (VBO) bool true @@ -1132,6 +1136,10 @@ enable_rollback_recording (Rollback recording) bool false # @name, @message, @timestamp (optional) chat_message_format (Chat message format) string <@name> @message +# If the execution of a chat command takes longer than this specified time in +# seconds, add the time information to the chat command message +chatcommand_msg_time_threshold (Chat command time message threshold) float 0.1 + # A message to be displayed to all clients when the server shuts down. kick_msg_shutdown (Shutdown message) string Server shutting down. |