257 lines
7.8 KiB
Lua
257 lines
7.8 KiB
Lua
-- LUALOCALS < ---------------------------------------------------------
|
|
local error, math, minetest, pairs, string, type
|
|
= error, math, minetest, pairs, string, type
|
|
local math_ceil, math_random, string_format, string_gsub, string_lower,
|
|
string_sub
|
|
= math.ceil, math.random, string.format, string.gsub, string.lower,
|
|
string.sub
|
|
-- LUALOCALS > ---------------------------------------------------------
|
|
|
|
local modname = minetest.get_current_modname()
|
|
local modstore = minetest.get_mod_storage()
|
|
|
|
local closed = modstore:get_string("closed") ~= ""
|
|
|
|
local function conf(k, n)
|
|
return minetest.settings[k](minetest.settings, modname .. "_" .. n)
|
|
end
|
|
|
|
local motddesc = conf("get", "desc") or "terms"
|
|
|
|
local limitsoft = conf("get", "limitsoft") or 3
|
|
local limithard = conf("get", "limithard") or math_ceil(limitsoft * 1.5)
|
|
if limithard < limitsoft then error("hard limit cannot be less than soft limit") end
|
|
local limitmsg = conf("get", "limitmsg") or "There are too many new players"
|
|
.. " right now; please try again in a few minutes."
|
|
|
|
local cmdname = conf("get", "cmdname") or "agree"
|
|
local cmdparam = conf("get", "cmdparam") or ("to " .. motddesc)
|
|
local cmdinstruct = conf("get", "cmdinstruct")
|
|
or "Please use the /motd chat command for instructions."
|
|
|
|
local grantprivs = conf("get", "grant") or "interact"
|
|
local purge = conf("get_bool", "purge")
|
|
|
|
local hudline1 = conf("get", "hudline1")
|
|
or ("You must agree to the " .. motddesc .. " to participate.")
|
|
local hudline2 = conf("get", "hudline2") or cmdinstruct
|
|
|
|
local hudclosed1 = conf("get", "hudclosed1")
|
|
or "New player registrations are currently disabled."
|
|
local hudclosed2 = conf("get", "hudclosed2") or hudline2
|
|
|
|
local already = conf("get", "already")
|
|
or ("You have already agreed and privileges were"
|
|
.. " already granted. If you have lost them, then they can"
|
|
.. " only be restored by an admin or moderator.")
|
|
|
|
local notice = conf("get", "notice") or ("*** %s agreed to " .. motddesc)
|
|
local noticeclosed = conf("get", "noticeclosed") or (notice
|
|
.. " ... but registration currently is closed.")
|
|
notice = notice .. "."
|
|
|
|
local jointag = conf("get", "jointag") or " [new]"
|
|
local purgetag = conf("get", "purgetag") or " [gone]"
|
|
|
|
local phashkey = minetest.settings:get("szutil_motd_hashkey") or ""
|
|
local function phash(pname)
|
|
if #phashkey < 1 then return "0000" end
|
|
return string_sub(minetest.sha1(phashkey .. pname .. phashkey .. pname), 1, 4)
|
|
end
|
|
local function phsub(line, pname)
|
|
return string_gsub(line, "<phash>", phash(pname))
|
|
end
|
|
|
|
local function tagmsg(func, suff)
|
|
return function(pname, ...)
|
|
if minetest.check_player_privs(pname, modname) then
|
|
return func(pname, ...)
|
|
end
|
|
local oldsend = minetest.chat_send_all
|
|
function minetest.chat_send_all(text, ...)
|
|
minetest.chat_send_all = oldsend
|
|
return oldsend(text .. suff, ...)
|
|
end
|
|
local function helper(...)
|
|
minetest.chat_send_all = oldsend
|
|
return ...
|
|
end
|
|
return helper(func(pname, ...))
|
|
end
|
|
end
|
|
|
|
if jointag and jointag ~= "" then
|
|
minetest.send_join_message = tagmsg(minetest.send_join_message, jointag)
|
|
end
|
|
|
|
if limitsoft >= 0 and limithard > 0 then
|
|
local emerging = {}
|
|
local function now() return minetest.get_us_time() / 1000000 end
|
|
minetest.register_on_prejoinplayer(function(name)
|
|
if minetest.check_player_privs(name, modname) then return end
|
|
local lobby = 0
|
|
for _, p in pairs(minetest.get_connected_players()) do
|
|
local pname = p:get_player_name()
|
|
emerging[pname] = nil
|
|
if not minetest.check_player_privs(p:get_player_name(), modname)
|
|
then lobby = lobby + 1 end
|
|
end
|
|
for _, t in pairs(emerging) do
|
|
if now() < t + 60 then lobby = lobby + 1 end
|
|
end
|
|
if lobby > math_random(limitsoft, limithard) then return limitmsg end
|
|
emerging[name] = now()
|
|
end)
|
|
end
|
|
|
|
local invitepriv = modname .. "_invite"
|
|
|
|
local huds = {}
|
|
local function dohud(player, id, offset, text)
|
|
if not id then
|
|
return player:hud_add({
|
|
hud_elem_type = "text",
|
|
position = {x = 0.5, y = 0.5},
|
|
text = text,
|
|
number = 0xFFC000,
|
|
alignment = {x = 0, y = offset},
|
|
offset = {x = 0, y = offset}
|
|
})
|
|
end
|
|
player:hud_change(id, "text", text)
|
|
return id
|
|
end
|
|
local function hudcheck(pname)
|
|
pname = type(pname) == "string" and pname or pname:get_player_name()
|
|
minetest.after(0, function()
|
|
local player = minetest.get_player_by_name(pname)
|
|
if not player then return end
|
|
|
|
local phud = huds[pname]
|
|
|
|
if minetest.check_player_privs(player, modname) then
|
|
player:hud_set_flags({crosshair = true})
|
|
if phud then
|
|
for _, id in pairs(phud) do
|
|
player:hud_remove(id)
|
|
end
|
|
end
|
|
huds[pname] = nil
|
|
return
|
|
end
|
|
|
|
player:hud_set_flags({crosshair = false})
|
|
if not phud then
|
|
phud = {}
|
|
huds[pname] = phud
|
|
end
|
|
local myclosed = closed and not minetest.check_player_privs(
|
|
player, invitepriv)
|
|
phud[1] = dohud(player, phud[1], -1, phsub(
|
|
myclosed and hudclosed1 or hudline1, pname))
|
|
phud[2] = dohud(player, phud[2], 1, phsub(
|
|
myclosed and hudclosed2 or hudline2, pname))
|
|
end)
|
|
end
|
|
minetest.register_on_leaveplayer(function(player)
|
|
huds[player:get_player_name()] = nil
|
|
end)
|
|
minetest.register_on_joinplayer(hudcheck)
|
|
|
|
minetest.register_privilege(modname, {
|
|
description = "agreed to " .. motddesc,
|
|
give_to_singleplayer = false,
|
|
give_to_admin = false,
|
|
on_grant = hudcheck,
|
|
on_revoke = hudcheck
|
|
})
|
|
minetest.register_privilege(invitepriv, {
|
|
description = "can agree to " .. motddesc .. " even when closed",
|
|
give_to_singleplayer = false,
|
|
give_to_admin = false,
|
|
on_grant = hudcheck,
|
|
on_revoke = hudcheck
|
|
})
|
|
|
|
minetest.register_chatcommand(cmdname, {
|
|
description = cmdinstruct,
|
|
func = function(pname, param)
|
|
if param ~= phsub(cmdparam, pname) then return false, cmdinstruct end
|
|
if minetest.check_player_privs(pname, modname) then
|
|
return false, already
|
|
end
|
|
if closed and not minetest.check_player_privs(pname, invitepriv) then
|
|
return minetest.chat_send_all(string_format(noticeclosed, pname))
|
|
end
|
|
minetest.chat_send_all(string_format(notice, pname))
|
|
local grant = minetest.string_to_privs(grantprivs)
|
|
grant[modname] = true
|
|
local privs = minetest.get_player_privs(pname)
|
|
for priv in pairs(grant) do
|
|
privs[priv] = true
|
|
minetest.run_priv_callbacks(pname, priv, pname, "grant")
|
|
end
|
|
minetest.set_player_privs(pname, privs)
|
|
hudcheck(pname)
|
|
end
|
|
})
|
|
|
|
local function setclosed(val)
|
|
if closed == val then return end
|
|
closed = val
|
|
modstore:set_string("closed", closed and "1" or "")
|
|
for _, p in pairs(minetest.get_connected_players()) do
|
|
hudcheck(p)
|
|
end
|
|
end
|
|
minetest.register_chatcommand(modname, {
|
|
description = "Toggle new player registrations by /" .. cmdname,
|
|
params = "[on|off]",
|
|
privs = {ban = true},
|
|
func = function(_, param)
|
|
if string_lower(param) == "on" then
|
|
setclosed(false)
|
|
elseif string_lower(param) == "off" then
|
|
setclosed(true)
|
|
elseif param ~= "" then
|
|
return false, "Use on/off to enable/disable registration,"
|
|
.. " or blank to query current state"
|
|
end
|
|
return true, "New player registrations "
|
|
.. (closed and "DISALLOWED" or "ALLOWED")
|
|
end
|
|
})
|
|
|
|
if purge then
|
|
local s = modstore:get_string("purge")
|
|
local cache = s and s ~= "" and minetest.deserialize(s) or {}
|
|
local function save() modstore:set_string("purge", minetest.serialize(cache)) end
|
|
|
|
local function processqueue()
|
|
minetest.after(1 + math_random(), processqueue)
|
|
local keep = {}
|
|
for _, p in pairs(minetest.get_connected_players()) do
|
|
keep[p:get_player_name()] = true
|
|
end
|
|
for k in pairs(cache) do
|
|
if not keep[k] then
|
|
minetest.remove_player(k)
|
|
minetest.remove_player_auth(k)
|
|
end
|
|
cache[k] = nil
|
|
end
|
|
save()
|
|
end
|
|
minetest.after(0, processqueue)
|
|
|
|
minetest.register_on_leaveplayer(function(player)
|
|
local pname = player:get_player_name()
|
|
if minetest.check_player_privs(pname, modname) then return end
|
|
cache[pname] = true
|
|
end)
|
|
|
|
if purgetag and purgetag ~= "" then
|
|
minetest.send_leave_message = tagmsg(minetest.send_leave_message, purgetag)
|
|
end
|
|
end
|