347 lines
8.5 KiB
Lua
347 lines
8.5 KiB
Lua
--[[
|
|
|
|
jail mod (C) shivajiva101@hotmail.com 2019
|
|
|
|
This file is part of gamehub.
|
|
|
|
gamehub is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
gamehub is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with gamehub. If not, see <https://www.gnu.org/licenses/>.
|
|
]]
|
|
|
|
local target, mode
|
|
local filename = minetest.get_modpath("jail") .. "/schems/jail.mts"
|
|
local t_units = {
|
|
s = 1, S=1, m = 60, h = 3600, H = 3600,
|
|
d = 86400, D = 86400, w = 604800, W = 604800,
|
|
M = 2592000, y = 31104000, Y = 31104000, [""] = 1
|
|
}
|
|
|
|
jail = {}
|
|
|
|
-- Insert physical jail if not present
|
|
if not gamehub.settings.jail then
|
|
minetest.after(5, function()
|
|
local pos = minetest.setting_get_pos("jail") or {x=0,y=-1000,z=0}
|
|
minetest.place_schematic(pos, filename, nil, nil, true)
|
|
gamehub.settings.jail = {x=7,y=-998,z=7}
|
|
gamehub.new_settings_data()
|
|
end)
|
|
end
|
|
|
|
-- Jailer entity registration
|
|
minetest.register_entity("jail:jailer", {
|
|
physical = true,
|
|
collisionbox = {-0.01,-0.01,-0.01, 0.01,0.01,0.01},
|
|
visual = "sprite",
|
|
visual_size = {x=0, y=0},
|
|
textures = {"jailer.png"},
|
|
is_visible = false,
|
|
makes_footstep_sound = false,
|
|
on_activate = function(self, staticdata)
|
|
self.object:set_armor_groups({immortal = 1})
|
|
if not target or not mode or self.trapped then return end
|
|
local prisoner = minetest.get_player_by_name(target)
|
|
if not prisoner then return end
|
|
if mode == "attach" then
|
|
prisoner:set_attach(self.object, "", {x=0,y=0,z=0}, {x=0,y=0,z=0})
|
|
self.trapped = target
|
|
minetest.sound_play("jail_door", {
|
|
to_player = target,
|
|
gain = 0.2,
|
|
loop = false
|
|
})
|
|
target, mode = nil, nil
|
|
end
|
|
end,
|
|
on_step = function(self,dtime)
|
|
if not target or not mode then return end
|
|
if mode == "detach" and target == self.trapped then
|
|
local player = minetest.get_player_by_name(target)
|
|
if not player then return end
|
|
player:set_detach()
|
|
gamehub.jail.delete_record(target)
|
|
minetest.log("action", target.." released from jail!")
|
|
minetest.chat_send_all("NEWSFLASH..." .. target ..
|
|
" has been released from jail!")
|
|
-- initiate action before removing object
|
|
minetest.after(0.2, gamehub.enter_world, target)
|
|
target, mode = nil, nil
|
|
self.object:remove()
|
|
end
|
|
end,
|
|
})
|
|
|
|
--[[
|
|
-----------------------------
|
|
Internal Functions
|
|
-----------------------------
|
|
]]
|
|
|
|
-- Initialises player target
|
|
-- @param name: player name string
|
|
-- @param mode: attach or detach string
|
|
local function target_player(name, mode_string)
|
|
target = name
|
|
mode = mode_string
|
|
end
|
|
|
|
|
|
-- Convert UTC to a readable format
|
|
-- @param t: UTC integer
|
|
-- @return formatted string
|
|
local function hrdf(t)
|
|
if type(t) == "number" then
|
|
return (t and os.date("%c", t))
|
|
end
|
|
end
|
|
|
|
|
|
-- Parse duration string converting to seconds
|
|
-- @param str: duration string
|
|
-- @return seconds integer
|
|
local parse_time = function(str)
|
|
local s = 0
|
|
for n, u in str:gmatch("(%d+)([smhdwyDMY]?)") do
|
|
s = s + (tonumber(n) * (t_units[u] or 1))
|
|
end
|
|
return s
|
|
end
|
|
|
|
-- Preprocess attachment event
|
|
-- @param name: player name
|
|
-- @return nothing
|
|
local attach = function(name)
|
|
|
|
minetest.set_player_privs(name, {})
|
|
target_player(name, "attach")
|
|
|
|
local player = minetest.get_player_by_name(name)
|
|
-- minimise stacking
|
|
local adj = math.random(-2,2)
|
|
local pos = gamehub.settings.jail
|
|
|
|
pos.x = pos.x + adj
|
|
pos.z = pos.z + adj
|
|
pos.y = pos.y + 0.5
|
|
|
|
player:set_pos(pos)
|
|
|
|
minetest.add_entity(pos, "jail:jailer")
|
|
end
|
|
|
|
-- Preprocess detachment event
|
|
-- @param name: player name
|
|
-- @return nothing
|
|
local detach = function(name)
|
|
target_player(name, "detach")
|
|
end
|
|
|
|
-- Expiry timer
|
|
-- @return nothing
|
|
local function tmr()
|
|
local ts = os.time()
|
|
for name,v in pairs(gamehub.jail.roll) do
|
|
if ts >= v.expires then
|
|
local player = minetest.get_player_by_name(name)
|
|
if player then
|
|
detach(name)
|
|
else
|
|
gamehub.jail.delete_record(name)
|
|
minetest.chat_send_all("Notice: " .. name ..
|
|
" was released from jail!")
|
|
end
|
|
end
|
|
end
|
|
minetest.after(60, tmr)
|
|
end
|
|
tmr() -- start
|
|
|
|
-----------------------------
|
|
--- API Functions ---
|
|
-----------------------------
|
|
|
|
jail.jail = function(caller, name, duration, reason)
|
|
|
|
if not (caller and name and duration and reason) then
|
|
return false, 'missing paramter...'
|
|
elseif gamehub.jail.roll[name] then
|
|
return false, name .. 'is already in jail!'
|
|
elseif name == owner then
|
|
return false, 'Insufficient privileges!'
|
|
end
|
|
|
|
duration = parse_time(duration)
|
|
if duration < 60 then
|
|
return false, 'You must jail for > 60 seconds'
|
|
end
|
|
|
|
local expires = os.time() + duration
|
|
|
|
gamehub.jail.new_record(name, reason, caller, expires)
|
|
|
|
if minetest.get_player_by_name(name) then
|
|
attach(name)
|
|
end
|
|
|
|
minetest.log('info', name .. ' was jailed by ' .. caller .. ' for '..reason)
|
|
return true, name .. ' was jailed by '..caller..' until ' .. hrdf(expires)
|
|
end
|
|
|
|
jail.unjail = function(caller, name)
|
|
|
|
if not gamehub.jail.roll[name] then
|
|
return false, name .. " isn't in jail!"
|
|
end
|
|
local player = minetest.get_player_by_name(name)
|
|
if player then
|
|
detach(name)
|
|
else
|
|
gamehub.jail.delete_record(target)
|
|
minetest.log("action", target.." released from jail by " .. caller)
|
|
end
|
|
|
|
return true, name .. ' released from jail'
|
|
end
|
|
|
|
------------------------------
|
|
-- Register Callbacks --
|
|
------------------------------
|
|
|
|
minetest.register_on_joinplayer(function(player)
|
|
|
|
local name = player:get_player_name()
|
|
|
|
if gamehub.jail.roll[name] then
|
|
if os.time() > gamehub.jail.roll[name].expires then
|
|
gamehub.jail.delete_record(name)
|
|
else
|
|
minetest.after(1, attach, name)
|
|
end
|
|
end
|
|
end)
|
|
|
|
minetest.register_on_leaveplayer(function(player)
|
|
|
|
local name = player:get_player_name()
|
|
|
|
if gamehub.jail.roll[name] then
|
|
detach(name)
|
|
end
|
|
end)
|
|
|
|
-- respawn
|
|
minetest.register_on_respawnplayer(function(player)
|
|
if not player then return true end
|
|
local name = player:get_player_name()
|
|
if gamehub.jail.roll[name] then
|
|
return true -- return as handled
|
|
end
|
|
end)
|
|
------------------------------
|
|
-- Register Commands --
|
|
------------------------------
|
|
|
|
minetest.register_chatcommand('jail', {
|
|
description = 'jail player',
|
|
params = '<name> <duration> <reason>',
|
|
func = function(name, param)
|
|
-- secure
|
|
if not gamehub.privs[name].hub_mod then
|
|
return false, "Insufficient privs!"
|
|
end
|
|
|
|
local pname, duration, reason = param:match("(%S+)%s+(%S+)%s+(.+)")
|
|
|
|
if not (pname and duration and reason) then
|
|
return false, "Usage: /jail <player> <time> <reason>"
|
|
elseif gamehub.jail.roll[pname] then
|
|
return false, pname .. " is already in jail!"
|
|
elseif pname == owner then
|
|
-- protect owner account
|
|
return false, "Insufficient privileges!"
|
|
end
|
|
|
|
duration = parse_time(duration)
|
|
if duration < 3600 then
|
|
return false, "You must jail for > 60 mins"
|
|
end
|
|
|
|
local expires = os.time() + duration
|
|
|
|
gamehub.jail.new_record(pname, reason, name, expires)
|
|
|
|
if minetest.get_player_by_name(name) then
|
|
attach(pname)
|
|
end
|
|
|
|
return true, pname .. " was jailed until " .. hrdf(expires)
|
|
end
|
|
})
|
|
|
|
minetest.register_chatcommand('unjail', {
|
|
params = '<player>',
|
|
description = 'release player from jail',
|
|
func = function(name, param)
|
|
if not gamehub.privs[name].hub_mod then
|
|
return false, 'Insufficient privs!'
|
|
end
|
|
if not param then
|
|
return false, 'Usage: /unjail <player>'
|
|
end
|
|
|
|
if not gamehub.jail.roll[param] then
|
|
return false, param .. "isn't in jail!"
|
|
end
|
|
|
|
detach(param)
|
|
|
|
return true, param .. ' released from jail'
|
|
end,
|
|
})
|
|
|
|
minetest.register_chatcommand('jail_info', {
|
|
description = 'view jail records',
|
|
func = function(name)
|
|
-- secure
|
|
if not gamehub.privs[name].hub_mod then
|
|
return false, 'Insufficient privs!'
|
|
end
|
|
|
|
local info = {}
|
|
for k,v in pairs(gamehub.jail.roll) do
|
|
info[#info+1] =('%s jailed by %s on %s for %s until %s'):format(
|
|
k,v.source,hrdf(v.created),v.reason,hrdf(v.expires))
|
|
end
|
|
if #info == 0 then
|
|
info[#info+1] = 'No jail records found...'
|
|
end
|
|
return true, table.concat(info,"\n")
|
|
|
|
end
|
|
})
|
|
|
|
minetest.register_chatcommand('jail_visit', {
|
|
description = 'visit jail',
|
|
func = function(name)
|
|
-- secure
|
|
if not gamehub.privs[name].hub_mod then
|
|
return false, 'Insufficient privs!'
|
|
end
|
|
|
|
local player = minetest.get_player_by_name(name)
|
|
player:set_pos(gamehub.settings.jail)
|
|
return true
|
|
|
|
end
|
|
})
|