diff options
Diffstat (limited to 'builtin/common')
-rw-r--r-- | builtin/common/after.lua | 33 | ||||
-rw-r--r-- | builtin/common/chatcommands.lua | 112 | ||||
-rw-r--r-- | builtin/common/filterlist.lua | 3 | ||||
-rw-r--r-- | builtin/common/misc_helpers.lua | 106 | ||||
-rw-r--r-- | builtin/common/serialize.lua | 4 | ||||
-rw-r--r-- | builtin/common/strict.lua | 5 | ||||
-rw-r--r-- | builtin/common/vector.lua | 5 |
7 files changed, 256 insertions, 12 deletions
diff --git a/builtin/common/after.lua b/builtin/common/after.lua new file mode 100644 index 000000000..cdfaaab86 --- /dev/null +++ b/builtin/common/after.lua @@ -0,0 +1,33 @@ +local jobs = {} +local time = 0.0 + +core.register_globalstep(function(dtime) + time = time + dtime + + if #jobs < 1 then + return + end + + -- Iterate backwards so that we miss any new timers added by + -- a timer callback, and so that we don't skip the next timer + -- in the list if we remove one. + for i = #jobs, 1, -1 do + local job = jobs[i] + if time >= job.expire then + core.set_last_run_mod(job.mod_origin) + job.func(unpack(job.arg)) + table.remove(jobs, i) + end + end +end) + +function core.after(after, func, ...) + assert(tonumber(after) and type(func) == "function", + "Invalid core.after invocation") + jobs[#jobs + 1] = { + func = func, + expire = time + after, + arg = {...}, + mod_origin = core.get_last_run_mod() + } +end diff --git a/builtin/common/chatcommands.lua b/builtin/common/chatcommands.lua new file mode 100644 index 000000000..e8955c6b4 --- /dev/null +++ b/builtin/common/chatcommands.lua @@ -0,0 +1,112 @@ +-- Minetest: builtin/common/chatcommands.lua + +core.registered_chatcommands = {} + +function core.register_chatcommand(cmd, def) + def = def or {} + def.params = def.params or "" + def.description = def.description or "" + def.privs = def.privs or {} + def.mod_origin = core.get_current_modname() or "??" + core.registered_chatcommands[cmd] = def +end + +function core.unregister_chatcommand(name) + if core.registered_chatcommands[name] then + core.registered_chatcommands[name] = nil + else + core.log("warning", "Not unregistering chatcommand " ..name.. + " because it doesn't exist.") + end +end + +function core.override_chatcommand(name, redefinition) + local chatcommand = core.registered_chatcommands[name] + assert(chatcommand, "Attempt to override non-existent chatcommand "..name) + for k, v in pairs(redefinition) do + rawset(chatcommand, k, v) + end + 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 msg = core.colorize("#00ffff", cmd_marker .. cmd) + if def.params and def.params ~= "" then + msg = msg .. " " .. def.params + end + if def.description and def.description ~= "" then + msg = msg .. ": " .. def.description + end + return msg + end + if param == "" then + local cmds = {} + for cmd, def in pairs(core.registered_chatcommands) do + if INIT == "client" or core.check_player_privs(name, def.privs) then + cmds[#cmds + 1] = cmd + 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) + elseif param == "all" then + local cmds = {} + for cmd, def in pairs(core.registered_chatcommands) do + if INIT == "client" or core.check_player_privs(name, def.privs) then + cmds[#cmds + 1] = format_help_line(cmd, def) + end + end + table.sort(cmds) + return true, gettext("Available commands:").."\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") + else + local cmd = param + local def = core.registered_chatcommands[cmd] + if not def then + return false, gettext("Command not available: ")..cmd + else + return true, format_help_line(cmd, def) + end + end +end + +if INIT == "client" then + core.register_chatcommand("help", { + params = gettext("[all/<cmd>]"), + description = 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", + func = do_help_cmd, + }) +end diff --git a/builtin/common/filterlist.lua b/builtin/common/filterlist.lua index 2a62362e3..562231192 100644 --- a/builtin/common/filterlist.lua +++ b/builtin/common/filterlist.lua @@ -289,6 +289,9 @@ function sort_mod_list(self) table.sort(self.m_processed_list, function(a, b) -- Show game mods at bottom if a.typ ~= b.typ then + if b.typ == "game" then + return a.typ ~= "game_mod" + end return b.typ == "game_mod" end -- If in same or no modpack, sort by name diff --git a/builtin/common/misc_helpers.lua b/builtin/common/misc_helpers.lua index c2dc7514d..68481f7c8 100644 --- a/builtin/common/misc_helpers.lua +++ b/builtin/common/misc_helpers.lua @@ -197,16 +197,17 @@ assert(table.indexof({"foo", "bar"}, "foo") == 1) assert(table.indexof({"foo", "bar"}, "baz") == -1) -------------------------------------------------------------------------------- -function file_exists(filename) - local f = io.open(filename, "r") - if f == nil then - return false - else - f:close() - return true +if INIT ~= "client" then + function file_exists(filename) + local f = io.open(filename, "r") + if f == nil then + return false + else + f:close() + return true + end end end - -------------------------------------------------------------------------------- function string:trim() return (self:gsub("^%s*(.-)%s*$", "%1")) @@ -307,7 +308,7 @@ function core.formspec_escape(text) end -function core.splittext(text,charlimit) +function core.wrap_text(text, charlimit) local retval = {} local current_idx = 1 @@ -462,7 +463,7 @@ if INIT == "game" then core.rotate_node = function(itemstack, placer, pointed_thing) core.rotate_and_place(itemstack, placer, pointed_thing, - core.setting_getbool("creative_mode"), + core.settings:get_bool("creative_mode"), {invert_wall = placer:get_player_control().sneak}) return itemstack end @@ -606,7 +607,9 @@ if INIT == "mainmenu" then return nil end +end +if INIT == "client" or INIT == "mainmenu" then function fgettext_ne(text, ...) text = core.gettext(text) local arg = {n=select('#', ...), ...} @@ -637,3 +640,86 @@ if INIT == "mainmenu" then end end +local ESCAPE_CHAR = string.char(0x1b) + +-- Client-side mods don't have access to settings +if core.settings and core.settings:get_bool("disable_escape_sequences") then + + function core.get_color_escape_sequence(color) + return "" + end + + function core.get_background_escape_sequence(color) + return "" + end + + function core.colorize(color, message) + return message + end + +else + + function core.get_color_escape_sequence(color) + return ESCAPE_CHAR .. "(c@" .. color .. ")" + end + + function core.get_background_escape_sequence(color) + return ESCAPE_CHAR .. "(b@" .. color .. ")" + end + + function core.colorize(color, message) + local lines = tostring(message):split("\n", true) + local color_code = core.get_color_escape_sequence(color) + + for i, line in ipairs(lines) do + lines[i] = color_code .. line + end + + return table.concat(lines, "\n") .. core.get_color_escape_sequence("#ffffff") + end + +end + +function core.strip_foreground_colors(str) + return (str:gsub(ESCAPE_CHAR .. "%(c@[^)]+%)", "")) +end + +function core.strip_background_colors(str) + return (str:gsub(ESCAPE_CHAR .. "%(b@[^)]+%)", "")) +end + +function core.strip_colors(str) + return (str:gsub(ESCAPE_CHAR .. "%([bc]@[^)]+%)", "")) +end + +-------------------------------------------------------------------------------- +-- Returns the exact coordinate of a pointed surface +-------------------------------------------------------------------------------- +function core.pointed_thing_to_face_pos(placer, pointed_thing) + local eye_offset_first = placer:get_eye_offset() + local node_pos = pointed_thing.under + local camera_pos = placer:get_pos() + local pos_off = vector.multiply( + vector.subtract(pointed_thing.above, node_pos), 0.5) + local look_dir = placer:get_look_dir() + local offset, nc + local oc = {} + + for c, v in pairs(pos_off) do + if nc or v == 0 then + oc[#oc + 1] = c + else + offset = v + nc = c + end + end + + local fine_pos = {[nc] = node_pos[nc] + offset} + camera_pos.y = camera_pos.y + 1.625 + eye_offset_first.y / 10 + local f = (node_pos[nc] + offset - camera_pos[nc]) / look_dir[nc] + + for i = 1, #oc do + fine_pos[oc[i]] = camera_pos[oc[i]] + look_dir[oc[i]] * f + end + return fine_pos +end diff --git a/builtin/common/serialize.lua b/builtin/common/serialize.lua index b2165648e..692ddd5f0 100644 --- a/builtin/common/serialize.lua +++ b/builtin/common/serialize.lua @@ -186,6 +186,10 @@ local safe_env = { } function core.deserialize(str, safe) + if type(str) ~= "string" then + return nil, "Cannot deserialize type '"..type(str) + .."'. Argument must be a string." + end if str:byte(1) == 0x1B then return nil, "Bytecode prohibited" end diff --git a/builtin/common/strict.lua b/builtin/common/strict.lua index 23ba3d727..ccde9676b 100644 --- a/builtin/common/strict.lua +++ b/builtin/common/strict.lua @@ -3,6 +3,7 @@ -- This ignores mod namespaces (variables with the same name as the current mod). local WARN_INIT = false +local getinfo = debug.getinfo function core.global_exists(name) if type(name) ~= "string" then @@ -18,7 +19,7 @@ local declared = {} local warned = {} function meta:__newindex(name, value) - local info = debug.getinfo(2, "Sl") + local info = getinfo(2, "Sl") local desc = ("%s:%d"):format(info.short_src, info.currentline) if not declared[name] then local warn_key = ("%s\0%d\0%s"):format(info.source, @@ -42,7 +43,7 @@ end function meta:__index(name) - local info = debug.getinfo(2, "Sl") + local info = getinfo(2, "Sl") local warn_key = ("%s\0%d\0%s"):format(info.source, info.currentline, name) if not declared[name] and not warned[warn_key] and info.what ~= "C" then core.log("warning", ("Undeclared global variable %q accessed at %s:%s") diff --git a/builtin/common/vector.lua b/builtin/common/vector.lua index 90ba3cc8b..0549f9a56 100644 --- a/builtin/common/vector.lua +++ b/builtin/common/vector.lua @@ -138,3 +138,8 @@ function vector.divide(a, b) z = a.z / b} end end + +function vector.sort(a, b) + return {x = math.min(a.x, b.x), y = math.min(a.y, b.y), z = math.min(a.z, b.z)}, + {x = math.max(a.x, b.x), y = math.max(a.y, b.y), z = math.max(a.z, b.z)} +end |