merging master

master
Nathan Salapat 2022-05-16 21:51:41 -05:00
commit 40d5f5ce5c
4 changed files with 262 additions and 97 deletions

View File

@ -303,6 +303,10 @@ minetest.register_node('lobby:button_1', {
lobby.corpses[map_id] = {}
for i=1,player_count do
minetest.chat_send_player(map_players[i], 'Hold tight, loading the level.')
local player = minetest.get_player_by_name(map_players[i])
local player_attributes = player:get_meta()
player_attributes:set_string('voting', 'false')
player_attributes:set_string('mode', 'player')
lobby.voted[map_players[i]] = true
if i == traitor then
minetest.chat_send_player(map_players[i], 'You\'re the imposter. Try to kill all the other players.')
@ -313,11 +317,8 @@ minetest.register_node('lobby:button_1', {
minetest.after(10, function()
player_inv:add_item('main', 'lobby:shank')
end)
player_attributes:set_string('mode', 'traitor')
end
local player = minetest.get_player_by_name(map_players[i])
local player_attributes = player:get_meta()
player_attributes:set_string('voting', 'false')
player_attributes:set_string('mode', 'player')
local privs = minetest.get_player_privs(map_players[i])
local player_inv = player:get_inventory()
player_inv:set_list('main', {})

View File

@ -33,10 +33,12 @@ This is set anytime a player goes to a level they have build access on.
player_attributes:set_string('mode', 'player')
This is set when a player is playing a level with other people, as it's meant to be played.
player_attributes:set_string('mode', 'traitor')
This is set when a player is playing a level with other people, and is the traitor.
player_attributes:set_string('mode', 'solo')
This is set when a player plays a level solo, usually to earn XP, but could also be to explore levels.
player_attributes:set_string('mode', 'ghost')
This is set when a player, playing with others, dies on a level.
]]

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,157 @@ 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
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
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 s, t, b, c, w, p, m
if privs.server then s = 's' else s = '-' end
if privs.traitor_dev then t = 't' else t = '-' end
if privs.builder then b = 'b' else b = '-' end
if privs.creative then c = 'c' else c = '-' end
if privs.worldeditor then w = 'w' else w = '-' end
if privs.pro_player then p = 'p' else p = '-' end
if privs.multihome then m = 'm' else m = '-' end
return table.concat({s, t, b, c, w, p, m})
end
-- tdc.actions: enumerates the possible /td commands
-- tdc.actions = { cmd_1 = def_1, cmd_2 = def_2, ... }
@ -131,20 +229,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 +258,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 +289,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 +303,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 +331,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 +345,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,54 +358,88 @@ 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,
},
-- CMD: /td fix (corpses|map) <map>
--[[
fix corpses: call lobby.corpse_removal(<map>), then reset its poslist
fix corpses: call lobby.corpse_removal(<map>), then reset its poslist
fix maps: set lobby.map[<map>] = 0, then call lobby.update_maps(<map>)
--]]
fix = {
@ -326,31 +458,63 @@ 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
end,
}
},
--CMD: /td mode(mode)
mode = {
info = 'Switch your play mode',
help = function()
local msgtab = {
_info('Usage /td mode <mode>'),
'Changes your playing mode.',
'Params:',
TAB .. '<mode> One of the following:',
TAB .. 'builder, ghost, player, solo, traitor'
}
return table.concat(msgtab, '\n')
end,
exec = function(td_user, params)
local helpcmd = 'type "/td help mode" for help.'
if not params then
minetest.chat_send_player(td_user, _info('Missing arguments, ' .. helpcmd))
else
local modes = 'builder, ghost, player, solo, traitor'
if string.find(modes, params) then
local player = minetest.get_player_by_name(td_user)
local player_attributes = player:get_meta()
player_attributes:set_string('mode', params)
minetest.chat_send_player(td_user, _info('Switched you to '..params..' mode.'))
else
minetest.chat_send_player(td_user, _info('Missing or bad arguments, ' .. helpcmd))
end
end
end,
}
}
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 +533,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
@ -387,4 +551,3 @@ minetest.register_chatcommand('td', {
description = 'Traitor debugging commands. Type "/td help" for a list of possible commands.',
func = tdc.exec
})

@ -1 +0,0 @@
Subproject commit b6fbd71be1ceaa590b3ac4f84219aaeeb5c464c6