Essentials core, repair, tpa, back, top, spawn, setspawn

This commit is contained in:
Evert Prants 2019-11-10 22:12:29 +02:00
commit 28f0114b7b
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
13 changed files with 700 additions and 0 deletions

15
ess/init.lua Normal file
View File

@ -0,0 +1,15 @@
local modpath = minetest.get_modpath(minetest.get_current_modname())
-- Register base module
ess.register_module("ess", "Essential commands for server management")
-- Tools related commands
dofile(modpath.."/tools.lua")
-- Teleportation related commands
dofile(modpath.."/teleport.lua")
dofile(modpath.."/warp.lua")
-- Player related commands
dofile(modpath.."/player.lua")

3
ess/mod.conf Normal file
View File

@ -0,0 +1,3 @@
name=ess
description=Essential commands for server management
depends=ess_core

0
ess/player.lua Normal file
View File

195
ess/teleport.lua Normal file
View File

@ -0,0 +1,195 @@
local tpask = {
requests = {},
muted = {},
timeout = 120,
}
local function cmd_top(name)
local curr_pos = minetest.get_player_by_name(name):getpos()
curr_pos.y = math.ceil(curr_pos.y) + 0.5
while minetest.get_node(curr_pos).name ~= "ignore" do
curr_pos.y = curr_pos.y + 1
end
curr_pos.y = curr_pos.y - 0.5
while minetest.get_node(curr_pos).name == "air" do
curr_pos.y = curr_pos.y - 1
end
curr_pos.y = curr_pos.y + 0.5
minetest.get_player_by_name(name):set_pos(curr_pos)
return true, "Teleported to top."
end
local function cmd_back(name)
local pos = minetest.string_to_pos(ess.get_player_meta(name, "position"))
if not pos then
return false, "Could not return to previous position."
end
minetest.get_player_by_name(name):set_pos(pos)
return true, "Teleported back."
end
local function cmd_tpcommon(name,tname,direction)
if name == tname then
return false, "Cannot teleport to self."
end
local target = minetest.get_player_by_name(tname)
if not target then
return false, "Could not find player."
end
if tpask.requests[tname] and tpask.requests[tname].when > minetest.get_us_time() - tpask.timeout * 100000 then
return false, "There are currently pending requests regarding this player. Please wait."
end
if not tpask.muted[tname] then
local message = "to teleport to you"
if direction == 2 then
message = "you to teleport to them"
end
minetest.chat_send_player(tname, name .. " has requested "..message..".")
minetest.chat_send_player(tname, "Run /tpaccept to accept or /tpadeny to deny.")
if tpask.timeout > 0 then
minetest.chat_send_player(tname, "You have "..tpask.timeout.." seconds to respond.")
end
tpask.requests[tname] = {when = minetest.get_us_time()}
if direction == 1 then
tpask.requests[tname].who = name
else
tpask.requests[tname].to = name
end
end
return true, "Teleport request sent to " .. tname .. ".."
end
local function cmd_tpask(name,tname)
return cmd_tpcommon(name,tname,1)
end
local function cmd_tpaskhere(name,tname)
return cmd_tpcommon(name,tname,2)
end
local function cmd_tpaconfirm(name)
local reqs = tpask.requests[name]
local me = minetest.get_player_by_name(name)
if not reqs or (tpask.timeout > 0 and tpask.requests[name].when < minetest.get_us_time() - tpask.timeout * 100000) then
return false, "You have no pending teleport requests."
end
local who = reqs.to or reqs.who
local whoplayer = minetest.get_player_by_name(who)
if not whoplayer then
tpask.requests[name] = nil
return false, "You have no pending teleport requests."
end
if reqs.to then
minetest.chat_send_player(name, "Teleporting..")
me:set_pos(whoplayer:get_pos())
else
minetest.chat_send_player(who, "Teleporting..")
whoplayer:set_pos(me:get_pos())
end
tpask.requests[name] = nil
return true
end
local function cmd_tpadeny(name)
local reqs = tpask.requests[name]
if not reqs or tpask.requests[name].when < minetest.get_us_time() - tpask.timeout * 1000 then
return false, "You have no pending teleport requests."
end
tpask.requests[name] = nil
return true, "Declined teleport request successfully. Use /tpmute to silence teleport requests."
end
local function cmd_tpamute(name)
if tpask.muted[name] then
tpask.muted[name] = nil
return true, "Unmuted teleport requests successfully."
end
tpask.muted[name] = "*"
return true, "Muted teleport requests successfully."
end
-- Use builtin tele
local cmd_teleport = minetest.registered_chatcommands["teleport"].func
local commands = {
["tpask"] = {
description = "Request to teleport to the specified player.",
params = "<player>",
aliases = {"tpa"},
privs = {
["ess.teleport.tpa"] = true,
},
save_player_pos = true,
func = cmd_tpask,
},
["tpaskhere"] = {
description = "Request to teleport the specified player to you.",
params = "<player>",
aliases = {"tpahere"},
privs = {
["ess.teleport.tpahere"] = true,
},
save_player_pos = true,
func = cmd_tpaskhere,
},
["tpaccept"] = {
description = "Accept a teleport request.",
aliases = {"tpayes"},
func = cmd_tpaconfirm,
save_player_pos = true,
},
["tpdeny"] = {
description = "Reject a teleport request.",
aliases = {"tpno"},
func = cmd_tpadeny,
},
["tpmute"] = {
description = "Silence/unsilence teleport requests.",
func = cmd_tpamute,
},
["back"] = {
description = "Teleports you to your location prior to tp/spawn/warp.",
aliases = {"return"},
privs = true,
save_player_pos = true,
func = cmd_back,
},
["top"] = {
description = "Teleport to the highest node at your current position.",
privs = true,
save_player_pos = true,
func = cmd_top,
},
["teleport"] = {
description = "Teleport to position or player",
aliases = {"tp", "tele", "tp2p"},
params = "<X>,<Y>,<Z> | <to_name> | (<name> <X>,<Y>,<Z>) | (<name> <to_name>)",
privs = {
["teleport"] = true,
["ess.teleport"] = true,
},
override = true,
save_player_pos = true,
func = cmd_teleport,
}
}
ess.autoregister(commands, "teleport")

73
ess/tools.lua Normal file
View File

@ -0,0 +1,73 @@
-- Repair command
local function cmd_repair(name, params, splitparams)
local player = minetest.get_player_by_name(name)
local commit = 0
if splitparams[1] == name and splitparams[2] == "all" then
splitparams[1] = "all"
end
if splitparams[1] == "all" then
if not ess.priv_match(name, "ess.tools.repairall") then
return ess.reject_permission()
end
-- Repair all tools
commit = 2
elseif splitparams[2] == "all" and minetest.get_player_by_name(splitparams[1]) then
if not ess.priv_match(name, "ess.tools.repairall.other") then
return ess.reject_permission()
end
player = minetest.get_player_by_name(splitparams[1])
-- Repair all of a player's tools
commit = 2
elseif splitparams[1] ~= name and minetest.get_player_by_name(splitparams[1]) then
if not ess.priv_match(name, "ess.tools.repair.other") then
return ess.reject_permission()
end
player = minetest.get_player_by_name(splitparams[1])
-- Repair a player's held tool
commit = 1
else
-- Repair my own tool
commit = 1
end
if commit == 1 and player then
local held = player:get_wielded_item()
if held:get_wear() > 0 then
held:set_wear(0)
end
player:set_wielded_item(held)
return true, "Successfully repaired the held tool!"
elseif commit == 2 and player then
local inv = player:get_inventory()
local list = inv:get_list("main")
for _,stack in pairs(list) do
if stack:get_wear() > 0 then
stack:set_wear(0)
end
end
inv:set_list("main", list)
return true, "Successfully repaired all tools!"
end
return false,"Invalid parameters."
end
local commands = {
["repair"] = {
description = "Repair currently held tool.",
aliases = {"fix"},
privs = {
["ess.tools.repair"] = true,
["ess.tools.repair.other"] = true,
["ess.tools.repairall"] = true,
["ess.tools.repairall.other"] = true,
},
params = "[<playername>] [all]",
func = cmd_repair
}
}
ess.autoregister(commands, "tools")

3
ess/warp.lua Normal file
View File

@ -0,0 +1,3 @@
local commands = {}
ess.autoregister(commands, "warp")

5
ess_chat/init.lua Normal file
View File

@ -0,0 +1,5 @@
local modpath = minetest.get_modpath(minetest.get_current_modname())
-- Register base module
ess.register_module("ess_chat", "Chat overhaul library")

3
ess_chat/mod.conf Normal file
View File

@ -0,0 +1,3 @@
name=ess_chat
description=Chat overhaul library
depends=ess_core

354
ess_core/init.lua Normal file
View File

@ -0,0 +1,354 @@
-- IcyEssentials Core Registration Framework
local storage = minetest.get_mod_storage()
ess = {
commands = {},
privileges = {},
modules = {},
player_meta = {},
world_meta = nil,
}
---------------------
-- PLAYER METADATA --
---------------------
-- Load player metadata
local function playerdata_load(name)
local decoded = minetest.deserialize(storage:get_string(name))
if not decoded then
ess.player_meta[name] = {}
return {}
end
ess.player_meta[name] = decoded
return decoded
end
-- Save player metadata
local function playerdata_save(name)
if not ess.player_meta[name] then return end
local encoded = minetest.serialize(ess.player_meta[name])
storage:set_string(name, encoded)
end
-- Set a player metadata value
function ess.set_player_meta(player, flag, value)
if not ess.player_meta[player] then
playerdata_load(player)
end
ess.player_meta[player][flag] = value
playerdata_save(player)
end
-- Get a player's metadata value
function ess.get_player_meta(player, flag)
if not ess.player_meta[player] then
playerdata_load(player)
end
return ess.player_meta[player][flag]
end
--------------------
-- WORLD METADATA --
--------------------
-- Load player metadata
local function worlddata_load()
local decoded = minetest.deserialize(storage:get_string("_data"))
if not decoded then
ess.world_meta = {}
return {}
end
ess.world_meta = decoded
return decoded
end
-- Save player metadata
local function worlddata_save()
if not ess.world_meta then return end
local encoded = minetest.serialize(ess.world_meta)
storage:set_string("_data", encoded)
end
-- Set a player metadata value
function ess.set_world_meta(player, flag, value)
if not ess.world_meta then worlddata_load() end
ess.world_meta[flag] = value
worlddata_save()
end
-- Get a player's metadata value
function ess.get_world_meta(flag)
if not ess.world_meta then worlddata_load() end
return ess.world_meta[flag]
end
-------------
-- UTILITY --
-------------
-- Just return a (TODO: translated) string that rejects permission
function ess.reject_permission()
return false, "You don't have permission to run this command."
end
-- Match a single privilege
function ess.priv_match(name, priv)
return minetest.check_player_privs(name, {[priv] = true})
end
-- Save a player's position for use with /back
local function save_player_pos(player, commit)
local pobj = minetest.get_player_by_name(player)
if not pobj then return end
local pos = pobj:get_pos()
if commit then
ess.set_player_meta(player, "position", minetest.pos_to_string(commit))
end
return pos
end
----------------
-- PRIVILEGES --
----------------
local function handle_command_privileges(privileges, description, default)
local perms = {}
for perm in pairs(privileges) do
local parts = string.split(perm, ".")
if ess.modules[parts[1]] and not ess.privileges[perm] then
minetest.register_privilege(perm, {
description = description,
give_to_singleplayer = default,
})
ess.privileges[perm] = true
end
perms[perm] = true
if #parts > 1 then
for i,p in ipairs(parts) do
if i == 1 then
local a = p .. ".all"
if not ess.privileges[a] then
minetest.register_privilege(a, {
description = "icyess all commands in module " .. p,
give_to_singleplayer = false,
give_to_admin = false
})
ess.privileges[a] = true
end
perms[a] = true
elseif i == 2 then
local a = parts[1] .. "." .. p .. ".all"
if not ess.privileges[a] then
minetest.register_privilege(a, {
description = "icyess all commands in module " .. p .. " category "..p,
give_to_singleplayer = false,
give_to_admin = false
})
ess.privileges[a] = true
end
perms[a] = true
end
end
end
end
perms["ess.all"] = true
return perms
end
------------------
-- CHATCOMMANDS --
------------------
local function register_chatcommand(command, def)
if def.privs then
def.privs = handle_command_privileges(def.privs, def.description, def.default == true)
end
local function fn (name, params)
local privileges_met = false
-- Check for any of the privileges
if def.privs then
for priv in pairs(def.privs) do
if ess.priv_match(name, priv) then
privileges_met = true
break
end
end
else
privileges_met = true
end
if not privileges_met then
return ess.reject_permission()
end
-- If this command is a teleport, save the player position
local player_pos
if def.save_player_pos then
player_pos = save_player_pos(name)
end
local splitparams = string.split(params, " ")
-- Run the chat command function
local ret,mesg = def.func(name, params, splitparams)
-- If we saved player position and the command succeeded, commit the last position save
if ret and player_pos then
save_player_pos(name, player_pos)
end
return ret,mesg
end
-- Clean-up the command definition
local pd = table.copy(def)
pd.privs = {}
pd.module = nil
pd.category = nil
pd.default = nil
pd.override = nil
pd.override_aliases = nil
pd.save_player_pos = nil
pd.func = fn
-- If this command is overriding, check if a command like this already exists and override it
if def.override and minetest.registered_chatcommands[command] then
minetest.override_chatcommand(command, pd)
else
minetest.register_chatcommand(command, pd)
end
end
--[[
IcyEss Module registration
Registers a module.
]]
function ess.register_module(modname, description)
ess.modules[modname] = { mod = minetest.get_current_modname(), description = description }
return {
register_chatcommand = function (root, cmddef)
cmddef.module = modname
return ess.register_chatcommand(root, cmddef)
end
}
end
--[[
IcyEss Command registration
{
-- Command aliases (optional)
-- All of these will be registered as separate commands with the same
-- privileges and execute function
aliases = {},
-- Optional module name, such as "ess-chat" or "protect".
-- This will be used in privilege generation and grouping.
module = "ess",
-- Optional command category, such as "time" or "item".
-- This will be used in privilege generation and grouping.
category = "item",
-- Command privileges (optional)
-- Set to true to generate privilege based on the command name
privs = true,
-- Set privileges a table in order to optionally require one of these privileges
-- If the privilege starts with the module name, they will automatically be
-- registered, if they don't already exist.
privs = {
"ess.item.repair" = true,
"ess.item.repair.other" = true,
},
-- Command execution (required)
func = function (name, params),
-- If command like this exists, do we override it?
override = false,
-- If aliases exist, do we override them?
override_aliases = false,
-- If this command is given to singleplayer
default = false,
-- If this command modifies player's position in some way,
-- save their current position before running the command
save_player_pos = false
}
]]
function ess.register_chatcommand(root, cmddef)
assert(type(cmddef) == "table", "command definition is not a table")
assert(cmddef.description ~= nil, "command is missing a description")
assert(cmddef.func ~= nil, "command definition is missing a function")
assert(type(cmddef.func) == "function", "command definition is missing a function")
if ess.commands[root] and not cmddef.override then return end
if not cmddef.privs and cmddef.privileges then
cmddef.privs = table.copy(cmddef.privileges)
cmddef.privileges = nil
end
local privs = cmddef.privs
if not privs then privs = {} end
-- Set default module
if not cmddef.module then
cmddef.module = "ess"
end
-- Generate privilege
if privs == true then
local a = ""
if cmddef.module then
a = a .. cmddef.module .. "."
end
if cmddef.category then
a = a .. cmddef.category .. "."
end
privs = {[a .. root] = true}
end
-- No privileges required
local plen = 0
for _ in pairs(privs) do
plen = plen + 1
end
if plen == 0 then
privs = nil
end
cmddef.privs = privs
ess.commands[root] = cmddef
register_chatcommand(root, cmddef)
if not cmddef.aliases or #cmddef.aliases == 0 then return end
local aliasdef = table.copy(cmddef)
aliasdef.func = cmddef.func
aliasdef.override = cmddef.override_aliases == true
aliasdef.override_aliases = nil
aliasdef.description = cmddef.description .. " (alias to "..root..")"
for _,a in pairs(cmddef.aliases) do
register_chatcommand(a,aliasdef)
end
end
function ess.autoregister(list, category)
for cmd,def in pairs(list) do
def.category = category
ess.register_chatcommand(cmd, def)
end
end

2
ess_core/mod.conf Normal file
View File

@ -0,0 +1,2 @@
name=ess_core
description=Command registration framework with better privileges

42
ess_spawn/init.lua Normal file
View File

@ -0,0 +1,42 @@
local modpath = minetest.get_modpath(minetest.get_current_modname())
-- Register base module
local spawn = ess.register_module("spawn", "Spawnpoint management")
spawn.register_chatcommand("spawn", {
description = "Teleport to spawnpoint.",
privs = {
spawn = true,
["spawn.all"] = true,
},
save_player_pos = true,
override = true,
func = function (name)
local spawnpoint = minetest.setting_get_pos("static_spawnpoint")
if not spawnpoint then
return false, "There is no defined spawnpoint for this world."
end
minetest.get_player_by_name(name):set_pos(spawnpoint)
return true, "Teleported to spawn."
end
})
spawn.register_chatcommand("setspawn", {
description = "Set a spawnpoint for the world.",
privs = {
["spawn.set"] = true,
["spawn.all"] = true,
},
override = true,
func = function (name)
if minetest.is_singleplayer() then
return false, "There is no point in setting a spawnpoint for a singleplayer world! Use /sethome instead."
end
local pos = minetest.get_player_by_name(name):get_pos(spawnpoint)
local str = minetest.pos_to_string(pos)
minetest.settings:set("static_spawnpoint", str)
minetest.settings:save()
return true, "Set the world's spawn point to " .. str
end
})

3
ess_spawn/mod.conf Normal file
View File

@ -0,0 +1,3 @@
name=ess_spawn
description=Spawnpoint management
depends=ess_core

2
modpack.conf Normal file
View File

@ -0,0 +1,2 @@
name=icyessentials
description=IcyEssentials is a collection of essential commands for server administation and moderation.