Rename subcommand "player" to "players" and extend its functionality

master
whats_his_face 2022-05-12 14:46:42 -05:00
parent 4e0861ddce
commit 1b13e8a9a1
1 changed files with 221 additions and 88 deletions

View File

@ -13,6 +13,10 @@ local function _info(msg)
return minetest.colorize('#ffff80', msg)
end
local function _stdout(msg)
return minetest.colorize('#80ddee', msg)
end
local function _lsitem(item)
return TAB .. '- ' .. item
end
@ -47,63 +51,158 @@ local function list_corpses(ctab)
end
tdc = {
fix_corpses = function(plr_name, map)
local pmap = map or '*'
local count = 0
--[[ -------------------- tdc namespace -------------------- ]]--
tdc = {}
for mapid, cplist in pairs(lobby.corpses) do
if pmap == '*' then
function tdc.fix_corpses(td_user, map)
local pmap = map or '*'
local count = 0
for mapid, cplist in pairs(lobby.corpses) do
if pmap == '*' then
lobby.corpse_removal(mapid)
lobby.corpses[mapid] = {}
count = count + 1
else
if mapid:find(pmap) then
lobby.corpse_removal(mapid)
lobby.corpses[mapid] = {}
count = count + 1
else
if mapid:find(pmap) then
lobby.corpse_removal(mapid)
lobby.corpses[mapid] = {}
count = count + 1
minetest.chat_send_player(plr_name,
_info('Corpses in ' .. _keyw(mapid) .. ' fixed.'))
break
end
minetest.chat_send_player(td_user,
_info('Corpses in ' .. _keyw(mapid) .. ' fixed.'))
break
end
end
if count == 0 then
minetest.chat_send_player(plr_name, _info('No maps found'))
elseif pmap == '*' then
minetest.chat_send_player(plr_name,
_info('Corpses in ' .. tostring(count) .. ' map(s) fixed.'))
end
end,
end
if count == 0 then
minetest.chat_send_player(td_user, _info('No maps found'))
elseif pmap == '*' then
minetest.chat_send_player(td_user,
_info('Corpses in ' .. tostring(count) .. ' map(s) fixed.'))
end
end
fix_map = function(plr_name, map)
local pmap = map or '*'
local count = 0
function tdc.fix_map(td_user, map)
local pmap = map or '*'
local count = 0
for mapid, count in pairs(lobby.map) do
if pmap == '*' then
for mapid, count in pairs(lobby.map) do
if pmap == '*' then
lobby.map[mapid] = 0
lobby.update_maps(mapid)
count = count + 1
else
if mapid:find(pmap) then
lobby.map[mapid] = 0
lobby.update_maps(mapid)
count = count + 1
else
if mapid:find(pmap) then
lobby.map[mapid] = 0
lobby.update_maps(mapid)
count = count + 1
minetest.chat_send_player(plr_name,
_info('Map status of ' .. _keyw(mapid) .. ' fixed.'))
break
end
minetest.chat_send_player(td_user,
_info('Map status of ' .. _keyw(mapid) .. ' fixed.'))
break
end
end
if count == 0 then
minetest.chat_send_player(plr_name, _info('No maps found'))
elseif pmap == '*' then
minetest.chat_send_player(plr_name,
_info('Status data for ' .. tostring(count) .. ' map(s) fixed.'))
end
if count == 0 then
minetest.chat_send_player(td_user, _info('No maps found'))
elseif pmap == '*' then
minetest.chat_send_player(td_user,
_info('Status data for ' .. tostring(count) .. ' map(s) fixed.'))
end
end
-- Return active players whose player name matches `expr`
function tdc.active_players_matching(expr)
local players = {}
for _, player in pairs(minetest.get_connected_players()) do
local pl_name = player:get_player_name()
if pl_name:find(expr) then
table.insert(players, player)
end
end,
}
end
return players
end
-- Return active map ids matching `expr`
function tdc.active_mapids_matching(expr)
local mapids = {}
for mapid, count in pairs(lobby.map) do
minetest.log('action', 'map "' .. mapid .. '": ' .. tostring(count))
if mapid:find(expr) and count ~= nil and count > 0 then
mapids[mapid] = true
end
end
-- The lobby itself never gets into lobby.map, so we insert it manually,
-- since we want to treat it just like a map.
local mapid_lobby = 'lobby'
if mapid_lobby:find(expr) then mapids[mapid_lobby] = true end
return mapids
end
-- Return players currently visiting a map whose id is in the list `mapids`
function tdc.players_visiting(mapids)
local players = {}
for pl_name, mapid in pairs(lobby.game) do
local mid = mapid
if mapid:find("_solo$") then
mid = mapid:sub(1, -6)
elseif mapid:find("_ghost$") then
mid = mapid:sub(1, -7)
end
minetest.log('action', pl_name .. ' in map ' .. mid)
if mapids[mid] then
table.insert(players, minetest.get_player_by_name(pl_name))
end
end
return players
end
-- For each player in the `players` list, create an entry in the `index` table,
-- having `player:get_player_name()` as keyword.
function tdc.index_by_name(players, index)
if players == nil or index == nil then return end
for _, player in ipairs(players) do
local pl_name = player:get_player_name()
index[pl_name] = player
end
end
-- Return a list of currently active players where either the player name
-- or the map id they're currently visiting matches `expr`.
function tdc.list_players_matching(expr)
local players = tdc.active_players_matching(expr)
local mapids = tdc.active_mapids_matching(expr)
local visitors = tdc.players_visiting(mapids)
local matches = {}
-- index all matching players by their name
tdc.index_by_name(players, matches)
tdc.index_by_name(visitors, matches)
return matches
end
-- Return a footprint representation of the player privileges `privs`
function tdc.privs_footprint(privs)
local p = ''
if privs.server then p = p .. 's' else p = p .. '-' end
if privs.traitor_dev then p = p .. 't' else p = p .. '-' end
if privs.builder then p = p .. 'b' else p = p .. '-' end
if privs.creative then p = p .. 'c' else p = p .. '-' end
if privs.worldeditor then p = p .. 'w' else p = p .. '-' end
if privs.pro_player then p = p .. 'p' else p = p .. '-' end
if privs.multihome then p = p .. 'm' else p = p .. '-' end
return p
end
-- tdc.actions: enumerates the possible /td commands
-- tdc.actions = { cmd_1 = def_1, cmd_2 = def_2, ... }
@ -131,20 +230,20 @@ tdc.actions = {
table.insert(msgtab, 'Type "' .. _keyw('/td help <cmd>') .. '" to get help for a specific command.')
return table.concat(msgtab, '\n')
end,
exec = function(plr_name, params)
exec = function(td_user, params)
if params then
local par1 = params:match('[%w_]+')
if par1 and tdc.actions[par1] then
minetest.chat_send_player(plr_name, tdc.actions[par1].help())
minetest.chat_send_player(td_user, tdc.actions[par1].help())
elseif par1 then
-- TODO: find par1 as cmd prefix in tdc.actions
local msg = _info('Unknown command "' .. par1 .. '"\n') .. list_actions()
minetest.chat_send_player(plr_name, msg)
minetest.chat_send_player(td_user, msg)
else
minetest.chat_send_player(plr_name, tdc.actions['help'].help())
minetest.chat_send_player(td_user, tdc.actions['help'].help())
end
else
minetest.chat_send_player(plr_name, tdc.actions['help'].help())
minetest.chat_send_player(td_user, tdc.actions['help'].help())
end
end,
},
@ -160,7 +259,7 @@ tdc.actions = {
}
return table.concat(msgtab, '\n')
end,
exec = function(plr_name, params)
exec = function(td_user, params)
local map = params:match('[%w_]+') or '*'
local hdr, msg, ccount, clist
if params == '' then
@ -191,7 +290,7 @@ tdc.actions = {
else
msg = _info('No corpses yet.')
end
minetest.chat_send_player(plr_name, msg)
minetest.chat_send_player(td_user, msg)
minetest.log('action', minetest.strip_colors(msg))
end,
},
@ -205,7 +304,7 @@ tdc.actions = {
}
return table.concat(msgtab, '\n')
end,
exec = function(plr_name, params)
exec = function(td_user, params)
local msgtab = {_info('Active maps:')}
local plr_count = 0
local msg
@ -233,7 +332,7 @@ tdc.actions = {
table.insert(msgtab, _lsitem('lobby: ' .. tostring(clobby) .. ' player(s)'))
end
msg = table.concat(msgtab, '\n')
minetest.chat_send_player(plr_name, msg)
minetest.chat_send_player(td_user, msg)
minetest.log('action', minetest.strip_colors(msg))
end,
},
@ -247,7 +346,7 @@ tdc.actions = {
}
return table.concat(msgtab, '\n')
end,
exec = function(plr_name, params)
exec = function(td_user, params)
local msg = ''
for mapid, traitor in pairs(lobby.traitors) do
-- table value could be nil if entry is to be GC'd
@ -260,47 +359,81 @@ tdc.actions = {
else
msg = _info('Active traitors:\n') .. msg
end
minetest.chat_send_player(plr_name, msg)
minetest.chat_send_player(td_user, msg)
minetest.log('action', minetest.strip_colors(msg))
end,
},
-- CMD: /td player <id>
player = {
-- CMD: /td players <id>
players = {
info = 'Show player attributes',
help = function()
local msgtab = {
_info('Usage: /td player <id>'),
'List some player metadata.',
_info('Usage: /td players <expr>'),
'Show metadata of one or more players.',
'Params:',
TAB .. '<id> player name (substring suffices).',
'\nNote: <id> is restricted to alphanumeric chars and "_", for the sake of security.'
TAB .. '<expr> Part of a player name or map ID used as search expression.',
TAB .. ' Any matching player name will be included in the result list.',
TAB .. ' If <expr> is part of a map ID, lists all players currently',
TAB .. ' visiting that map.',
'\nNote: <expr> is restricted to alphanumeric chars and "_", for the sake of security.',
'\nThe metadata of matching players is listed in a table with the following columns:',
TAB .. 'Player displays the player\'s login name',
TAB .. 'Map shows the map id the player is currently visiting',
TAB .. 'Privs shows the state of some more widely used traitor privileges, which is',
TAB .. ' a short string where each letter symbolizes a certain privilege',
TAB .. ' (' ..
_stdout('s') .. 'erver, ' ..
_stdout('t') .. 'raitor_dev, ' ..
_stdout('b') .. 'uilder, ' ..
_stdout('c') .. 'reative, ' ..
_stdout('w') .. 'orldeditor, ' ..
_stdout('p') .. 'ro_player, ' ..
_stdout('m') .. 'ultihome)',
TAB .. ' If a player does not have a certain privilege, the privilege\'s letter',
TAB .. ' is replaced by a \'-\' instead.',
TAB .. 'Mode displays the player mode',
TAB .. 'Tone shows the player\'s current tone color',
TAB .. 'Spawn prints the player\'s current spawn position (if any)',
}
return table.concat(msgtab, '\n')
end,
exec = function(plr_name, params)
exec = function(td_user, params)
if not params or not params:find("[%w_]+") then
minetest.chat_send_player(plr_name, 'Missing argument, type "/td help player" for help.')
minetest.chat_send_player(td_user, 'Missing argument, type "/td help players" for help.')
else
local p1, p2, plid = params:find('([%w_]+)')
local p1, p2, expr = params:find('([%w_]+)')
local matches = tdc.list_players_matching(expr)
local count = 0
local mtab = {
_info('Player Map Privs Mode Tone Spawn'),
'--------------------------------------------------------------------------------------',
}
-- sort list by player name
local sorted = {}
for name in pairs(matches) do table.insert(sorted, name) end
table.sort(sorted)
for _, player in pairs(minetest.get_connected_players()) do
local pname = player:get_player_name()
for _, name in pairs(sorted) do
count = count + 1
local player = matches[name]
local attr = player:get_meta()
local pl_name = _keyw(name)
local padding = 20 - name:len()
local pl_padding = string.rep(' ', padding)
local pl_map = lobby.game[name] or '<nil>'
local pl_privs = tdc.privs_footprint(minetest.get_player_privs(name))
local pl_mode = attr:get_string('mode') or '<nil>'
local pl_tone = attr:get_int('tone')
local pl_spawn = attr:get_string('spawn_pos') or '<nil>'
if pname:find(plid) then
count = count + 1
local attr = player:get_meta()
local mtab = {
_info('Attributes of ') .. _keyw(pname) .. ':',
TAB .. 'ghost: ' .. (attr:get_string('ghost') or 'false'),
TAB .. 'spawn: ' .. (attr:get_string('spawn_pos') or '<nil>'),
TAB .. 'voting: ' .. (attr:get_string('voting') or 'false')
}
minetest.chat_send_player(plr_name, table.concat(mtab, '\n'))
end
table.insert(mtab, string.format('%s%s %-20s %-7s %-7s %5d %-20s',
pl_name, pl_padding, pl_map, pl_privs, pl_mode, pl_tone, pl_spawn)
)
end
if count == 0 then
minetest.chat_send_player(plr_name, _info('No matching player'))
minetest.chat_send_player(td_user, _info('No match'))
else
minetest.chat_send_player(td_user, table.concat(mtab, '\n'))
end
end
end,
@ -326,23 +459,23 @@ tdc.actions = {
}
return table.concat(msgtab, '\n')
end,
exec = function(plr_name, params)
exec = function(td_user, params)
local helpcmd = 'type "/td help fix" for help.'
if not params then
minetest.chat_send_player(plr_name, _info('Missing arguments, ' .. helpcmd))
minetest.chat_send_player(td_user, _info('Missing arguments, ' .. helpcmd))
else
local p1, p2, fix, map
p1, p2, fix, map = params:find('(%w+)%s+([%w_*]+)')
if not fix or not map then
minetest.chat_send_player(plr_name, _info('Missing arguments, ' .. helpcmd))
minetest.chat_send_player(td_user, _info('Missing arguments, ' .. helpcmd))
else
if string.find('corpses', fix) then
tdc.fix_corpses(plr_name, map)
tdc.fix_corpses(td_user, map)
elseif string.find('map', fix) then
tdc.fix_map(plr_name, map)
tdc.fix_map(td_user, map)
else
minetest.chat_send_player(plr_name, _info('Unknown fix action, ' .. helpcmd))
minetest.chat_send_player(td_user, _info('Unknown fix action, ' .. helpcmd))
end
end
end
@ -350,7 +483,7 @@ tdc.actions = {
}
}
function tdc.exec(plr_name, params)
function tdc.exec(td_user, params)
local cmd = nil
if params and params ~= '' then
local par1 = params:match('[%w_]+')
@ -369,14 +502,14 @@ function tdc.exec(plr_name, params)
end
end
if cname then
minetest.log('action', plr_name .. ' runs "/td ' .. cname .. parN .. '"')
cmd.exec(plr_name, parN)
minetest.log('action', td_user .. ' runs "/td ' .. cname .. parN .. '"')
cmd.exec(td_user, parN)
else
minetest.chat_send_player(plr_name,
minetest.chat_send_player(td_user,
_info('Unknown command "' .. par1 .. '", type "/td help" for possible commands.'))
end
else
minetest.chat_send_player(plr_name, list_actions())
minetest.chat_send_player(td_user, list_actions())
end
return true
end