Initial commit
Woohoooooo
This commit is contained in:
parent
a5e28e936b
commit
3eaec6d460
20
README.md
Normal file
20
README.md
Normal file
@ -0,0 +1,20 @@
|
||||
# am_afk
|
||||
|
||||
|
||||
|
||||
This mod automatically put costume on afk player and kick after some time.
|
||||
Everything is customizable, see config file :)
|
||||
|
||||
Available chatcommand:
|
||||
`/afk`
|
||||
|
||||
Dependencies:
|
||||
`player_api`
|
||||
|
||||
License:
|
||||
code - GNU General Public License v3.0
|
||||
media - CC by SA 3.0, for more details: http://creativecommons.org/licenses/by-sa/3.0/
|
||||
|
||||
|
||||
Preview:
|
||||

|
183
afk.lua
Normal file
183
afk.lua
Normal file
@ -0,0 +1,183 @@
|
||||
local current_modname = minetest.get_current_modname()
|
||||
local path = minetest.get_modpath(current_modname)
|
||||
|
||||
local mod_util = dofile(path.."/utils/mod.lua")
|
||||
local mod = mod_util.import.from(current_modname)
|
||||
mod.players = {}
|
||||
|
||||
local controller = dofile(path.."/controller/cone.lua")
|
||||
local formspec_util = dofile(path.."/utils/formspec.lua")
|
||||
|
||||
local get_initial_state = function(player)
|
||||
return {
|
||||
timer = 0,
|
||||
afk = false,
|
||||
pos = player:get_pos(),
|
||||
look_dir = player:get_look_dir()
|
||||
}
|
||||
end
|
||||
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
local name = player:get_player_name()
|
||||
mod.players[name] = get_initial_state(player)
|
||||
end)
|
||||
|
||||
local is_afk = function(player)
|
||||
local name = player:get_player_name()
|
||||
return mod.players[name].afk
|
||||
end
|
||||
|
||||
local set_back = function(player)
|
||||
local name = player:get_player_name()
|
||||
mod.players[name].afk = false
|
||||
mod.players[name].timer = 0
|
||||
|
||||
controller.remove(player)
|
||||
|
||||
if mod.config.chat_output then
|
||||
minetest.chat_send_all("Player "..name.." is back")
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_on_chat_message(function(name, message)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if not player then
|
||||
return
|
||||
end
|
||||
|
||||
if is_afk(player) then
|
||||
set_back(player)
|
||||
else
|
||||
mod.players[name].timer = 0
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_on_dieplayer(function(player, reason)
|
||||
if is_afk(player) then
|
||||
controller.remove(player)
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
local name = player:get_player_name()
|
||||
mod.players[name] = nil
|
||||
|
||||
controller.remove(player)
|
||||
end)
|
||||
|
||||
local formspec_name = formspec_util.get_formspec_name()
|
||||
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
if formname ~= formspec_name then
|
||||
return
|
||||
end
|
||||
set_back(player)
|
||||
end)
|
||||
|
||||
local afk_handler = function(player, moving)
|
||||
local name = player:get_player_name()
|
||||
mod.players[name].afk = true
|
||||
|
||||
if not moving then
|
||||
local anim_table = player_api.get_animation(player)
|
||||
if anim_table.animation == "stand" then
|
||||
controller.attach(player)
|
||||
end
|
||||
end
|
||||
|
||||
if mod.config.chat_output then
|
||||
minetest.chat_send_all("Player "..name.." is AFK")
|
||||
end
|
||||
|
||||
formspec_util.show_formspec(player, mod.config.formspec.title,
|
||||
mod.config.formspec.button)
|
||||
end
|
||||
|
||||
local set_moving_afk = function(player)
|
||||
afk_handler(player, true)
|
||||
end
|
||||
|
||||
local set_afk = function(player)
|
||||
afk_handler(player, false)
|
||||
end
|
||||
|
||||
minetest.register_chatcommand("afk", {
|
||||
privs = {},
|
||||
func = function(name, param)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if player then
|
||||
set_afk(player)
|
||||
end
|
||||
return true
|
||||
end,
|
||||
})
|
||||
|
||||
local activity_state = {
|
||||
inactive = 0,
|
||||
active = 1,
|
||||
moving = 2,
|
||||
}
|
||||
|
||||
local get_activity_state = function(player)
|
||||
if player:get_player_control_bits() ~= 0 then
|
||||
return activity_state.active
|
||||
end
|
||||
|
||||
local dir = player:get_look_dir()
|
||||
local name = player:get_player_name()
|
||||
if vector.distance(dir, mod.players[name].look_dir) ~= 0 then
|
||||
mod.players[name].look_dir = dir
|
||||
return activity_state.active
|
||||
end
|
||||
|
||||
local pos = player:get_pos()
|
||||
if vector.distance(pos, mod.players[name].pos) ~= 0 then
|
||||
-- falling, drowning, attached to entity, etc.
|
||||
mod.players[name].pos = pos
|
||||
return activity_state.moving
|
||||
end
|
||||
|
||||
return activity_state.inactive
|
||||
end
|
||||
|
||||
local second_counter = 0
|
||||
local get_elapsed_seconds = function(dtime)
|
||||
local elapsed_time = second_counter + dtime
|
||||
second_counter = elapsed_time % 1
|
||||
return math.floor(elapsed_time)
|
||||
end
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
local connected_players = minetest.get_connected_players()
|
||||
local seconds = get_elapsed_seconds(dtime)
|
||||
|
||||
if seconds == 0 then
|
||||
return
|
||||
end
|
||||
|
||||
for _,player in ipairs(connected_players) do
|
||||
local name = player:get_player_name()
|
||||
if not mod.config.ignore[name] then
|
||||
local state = get_activity_state(player)
|
||||
if state == activity_state.active then
|
||||
mod.players[name].timer = 0
|
||||
elseif not mod.players[name].afk then
|
||||
mod.players[name].timer = mod.players[name].timer + seconds
|
||||
if mod.players[name].timer >= mod.config.afk_inactivity_time then
|
||||
if state == activity_state.moving then
|
||||
set_moving_afk(player)
|
||||
else
|
||||
set_afk(player)
|
||||
end
|
||||
end
|
||||
elseif mod.config.kick_inactivity_time > 0 then
|
||||
mod.players[name].timer = mod.players[name].timer + seconds
|
||||
if mod.players[name].timer >= mod.config.kick_inactivity_time then
|
||||
local reason = mod.config.kick_inactivity_reason or ''
|
||||
reason = reason ~= '' and reason or "Inactivity is reason, you are still welcome :)"
|
||||
minetest.kick_player(name, reason)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
18
config.lua
Normal file
18
config.lua
Normal file
@ -0,0 +1,18 @@
|
||||
return {
|
||||
ignore = {
|
||||
singleplayer = true,
|
||||
ADMIN = true,
|
||||
},
|
||||
allow_chat_command = true,
|
||||
chat_output = true,
|
||||
afk_inactivity_time = 300,
|
||||
|
||||
-- set 0 seconds to disable kick feature
|
||||
kick_inactivity_time = 3600,
|
||||
kick_inactivity_reason = '',
|
||||
|
||||
formspec = {
|
||||
title = "Hey you, you're finally awake",
|
||||
button = "Yes I am!",
|
||||
},
|
||||
}
|
35
controller/cone.lua
Normal file
35
controller/cone.lua
Normal file
@ -0,0 +1,35 @@
|
||||
local current_modname = minetest.get_current_modname()
|
||||
local path = minetest.get_modpath(current_modname)
|
||||
|
||||
local cone_name = dofile(path.."/entities/cone.lua")
|
||||
|
||||
local controller = {}
|
||||
|
||||
local attached_cone = {}
|
||||
|
||||
local force_stop_animation = function(player)
|
||||
player_api.set_animation(player, "walk")
|
||||
player_api.set_animation(player, "stand", 0)
|
||||
end
|
||||
|
||||
controller.attach = function(player)
|
||||
local cone = minetest.add_entity(player:get_pos(), cone_name)
|
||||
local player_yaw = player:get_look_horizontal()
|
||||
cone:set_rotation({x=0,y=player_yaw,z=0})
|
||||
cone:set_attach(player, "", {x=0, y=0, z=0}, {x=0, y=0, z=0})
|
||||
force_stop_animation(player)
|
||||
|
||||
local name = player:get_player_name()
|
||||
attached_cone[name] = cone
|
||||
end
|
||||
|
||||
controller.remove = function(player)
|
||||
local name = player:get_player_name()
|
||||
local cone = attached_cone[name]
|
||||
if cone then
|
||||
cone:remove()
|
||||
player_api.set_animation(player, "stand")
|
||||
end
|
||||
end
|
||||
|
||||
return controller
|
1
depends.txt
Normal file
1
depends.txt
Normal file
@ -0,0 +1 @@
|
||||
player_api
|
23
entities/cone.lua
Normal file
23
entities/cone.lua
Normal file
@ -0,0 +1,23 @@
|
||||
local current_modname = minetest.get_current_modname()
|
||||
|
||||
local entity_name = current_modname..":cone"
|
||||
|
||||
minetest.register_entity(entity_name, {
|
||||
initial_properties = {
|
||||
physical = false,
|
||||
collide_with_objects = false,
|
||||
pointable = false,
|
||||
visual = "mesh",
|
||||
visual_size = {x=1.05, y=1},
|
||||
mesh = "afk_cone.obj",
|
||||
textures = {"afk_board.png", "afk_cone.png"},
|
||||
use_texture_alpha = true,
|
||||
backface_culling = false,
|
||||
glow = 4,
|
||||
static_save = false,
|
||||
shaded = true,
|
||||
show_on_minimap = false,
|
||||
}
|
||||
})
|
||||
|
||||
return entity_name
|
9
init.lua
Normal file
9
init.lua
Normal file
@ -0,0 +1,9 @@
|
||||
local current_modname = minetest.get_current_modname()
|
||||
local path = minetest.get_modpath(current_modname)
|
||||
|
||||
local mod_util = dofile(path.."/utils/mod.lua")
|
||||
local mod = mod_util.export({}).from(current_modname)
|
||||
|
||||
mod.config = dofile(path.."/config.lua")
|
||||
|
||||
dofile(path.."/afk.lua")
|
99
models/afk_cone.obj
Normal file
99
models/afk_cone.obj
Normal file
@ -0,0 +1,99 @@
|
||||
# Blender v2.78 (sub 0) OBJ File: 'stop_reading_please.blend'
|
||||
# www.blender.org
|
||||
# made for Minetest by AspireMint
|
||||
g Plane.001
|
||||
v -2.346000 17.055759 2.345999
|
||||
v 2.346000 17.055759 2.345999
|
||||
v -2.346000 17.055759 -2.346000
|
||||
v 2.346000 17.055759 -2.346000
|
||||
v -0.293250 22.135761 0.293250
|
||||
v 0.293250 22.135761 0.293250
|
||||
v -0.293250 22.135761 -0.293250
|
||||
v 0.293250 22.135761 -0.293250
|
||||
v -1.759500 17.055759 1.759500
|
||||
v 1.759500 17.055759 1.759500
|
||||
v -1.759500 17.055759 -1.759500
|
||||
v 1.759500 17.055759 -1.759500
|
||||
v -2.346000 16.712000 2.345999
|
||||
v 2.346000 16.712000 2.345999
|
||||
v -2.346000 16.712000 -2.346000
|
||||
v 2.346000 16.712000 -2.346000
|
||||
v -3.150000 12.610003 -1.050000
|
||||
v 3.150000 12.610001 -1.050000
|
||||
v -3.150003 0.439336 -4.311120
|
||||
v 3.149998 0.439336 -4.311120
|
||||
v -3.150000 12.610003 1.049999
|
||||
v 3.150000 12.610001 1.050000
|
||||
v -3.150003 0.439337 4.311119
|
||||
v 3.149998 0.439337 4.311119
|
||||
vt -0.0000 0.0000
|
||||
vt 1.0000 0.4615
|
||||
vt 1.0000 0.0000
|
||||
vt 0.0000 0.5385
|
||||
vt 1.0000 0.5385
|
||||
vt 0.0000 1.0000
|
||||
vt 0.0000 0.4615
|
||||
vt 1.0000 1.0000
|
||||
vt 0.0000 1.0000
|
||||
vt 0.1250 0.1250
|
||||
vt 0.1250 0.8750
|
||||
vt 0.4375 0.5625
|
||||
vt 0.5625 0.4375
|
||||
vt 0.5625 0.5625
|
||||
vt 0.8750 0.1250
|
||||
vt 0.0000 0.0000
|
||||
vt 1.0000 0.0000
|
||||
vt 0.4375 0.4375
|
||||
vt 0.8750 0.8750
|
||||
vt 1.0000 0.0000
|
||||
vt 1.0000 1.0000
|
||||
vt 0.0000 1.0000
|
||||
vt 0.0000 0.0000
|
||||
vt 1.0000 1.0000
|
||||
vn 0.0000 -0.2588 -0.9659
|
||||
vn -0.0000 -1.0000 0.0000
|
||||
vn -0.0000 -0.2588 0.9659
|
||||
vn 0.0000 1.0000 0.0000
|
||||
vn 0.9608 0.2773 0.0000
|
||||
vn 0.0000 0.2773 -0.9608
|
||||
vn -0.9608 0.2773 0.0000
|
||||
vn 0.0000 0.2773 0.9608
|
||||
vn 0.0000 0.0000 -1.0000
|
||||
vn 0.0000 0.0000 1.0000
|
||||
vn 1.0000 0.0000 0.0000
|
||||
vn -1.0000 0.0000 0.0000
|
||||
g Plane.001_Plane.001_None
|
||||
s off
|
||||
f 23/1/1 22/2/1 24/3/1
|
||||
f 22/2/2 17/4/2 18/5/2
|
||||
f 19/6/3 18/5/3 17/4/3
|
||||
f 23/1/1 21/7/1 22/2/1
|
||||
f 22/2/2 21/7/2 17/4/2
|
||||
f 19/6/3 20/8/3 18/5/3
|
||||
g Plane.001_Plane.001_None_afk_cone.png
|
||||
f 2/9/4 12/10/4 10/11/4
|
||||
f 6/12/4 7/13/4 5/14/4
|
||||
f 11/15/4 4/16/4 3/17/4
|
||||
f 10/11/5 8/18/5 6/12/5
|
||||
f 12/10/6 7/13/6 8/18/6
|
||||
f 7/13/7 9/19/7 5/14/7
|
||||
f 9/19/8 6/12/8 5/14/8
|
||||
f 4/16/9 15/20/9 3/17/9
|
||||
f 1/21/10 14/22/10 2/9/10
|
||||
f 2/9/11 16/23/11 4/16/11
|
||||
f 3/17/12 13/24/12 1/21/12
|
||||
f 9/19/4 1/21/4 2/9/4
|
||||
f 2/9/4 4/16/4 12/10/4
|
||||
f 10/11/4 9/19/4 2/9/4
|
||||
f 6/12/4 8/18/4 7/13/4
|
||||
f 1/21/4 9/19/4 11/15/4
|
||||
f 11/15/4 12/10/4 4/16/4
|
||||
f 3/17/4 1/21/4 11/15/4
|
||||
f 10/11/5 12/10/5 8/18/5
|
||||
f 12/10/6 11/15/6 7/13/6
|
||||
f 7/13/7 11/15/7 9/19/7
|
||||
f 9/19/8 10/11/8 6/12/8
|
||||
f 4/16/9 16/23/9 15/20/9
|
||||
f 1/21/10 13/24/10 14/22/10
|
||||
f 2/9/11 14/22/11 16/23/11
|
||||
f 3/17/12 15/20/12 13/24/12
|
BIN
preview.png
Normal file
BIN
preview.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 950 KiB |
BIN
textures/afk_board.png
Normal file
BIN
textures/afk_board.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.2 KiB |
BIN
textures/afk_board_template.png
Normal file
BIN
textures/afk_board_template.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 154 B |
BIN
textures/afk_cone.png
Normal file
BIN
textures/afk_cone.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 153 B |
26
utils/formspec.lua
Normal file
26
utils/formspec.lua
Normal file
@ -0,0 +1,26 @@
|
||||
local current_modname = minetest.get_current_modname()
|
||||
|
||||
local util = {}
|
||||
|
||||
local formspec_name = current_modname..":confirm_awake"
|
||||
|
||||
local create_formspec = function(title, button)
|
||||
local formspec = {
|
||||
"formspec_version[4]",
|
||||
"size[4,2.375]",
|
||||
"label[0.375,0.75;", minetest.formspec_escape(title), "]",
|
||||
"button_exit[0.375,1.125;3.25,0.8;confirm;", minetest.formspec_escape(button), "]"
|
||||
}
|
||||
return table.concat(formspec, "")
|
||||
end
|
||||
|
||||
util.show_formspec = function(player, title, button)
|
||||
local name = player:get_player_name()
|
||||
minetest.show_formspec(name, formspec_name, create_formspec(title, button))
|
||||
end
|
||||
|
||||
util.get_formspec_name = function()
|
||||
return formspec_name
|
||||
end
|
||||
|
||||
return util
|
45
utils/mod.lua
Normal file
45
utils/mod.lua
Normal file
@ -0,0 +1,45 @@
|
||||
local util = {}
|
||||
|
||||
local conf = {
|
||||
prefix_from = 'from_',
|
||||
prefix_as = ''
|
||||
}
|
||||
|
||||
local get_mod_name = function(prefix, name)
|
||||
return (prefix or '')..name
|
||||
end
|
||||
|
||||
util.export = function(t)
|
||||
if not t or type(t) ~= 'table' then
|
||||
error('Failed to export')
|
||||
end
|
||||
|
||||
local fn = function(G, mod_name, prefix)
|
||||
local export_name = get_mod_name(prefix, mod_name)
|
||||
G = G or _G
|
||||
G[export_name] = t
|
||||
return t, export_name
|
||||
end
|
||||
|
||||
return {
|
||||
from = function(mod_name, G)
|
||||
return fn(G, mod_name, conf.prefix_from)
|
||||
end,
|
||||
as = function(mod_name, G)
|
||||
return fn(G, mod_name, conf.prefix_as)
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
util.import = {
|
||||
from = function(mod_name, G)
|
||||
G = G or _G
|
||||
return G[get_mod_name(conf.prefix_from, mod_name)]
|
||||
end,
|
||||
as = function(mod_name, G)
|
||||
G = G or _G
|
||||
return G[get_mod_name(conf.prefix_as, mod_name)]
|
||||
end
|
||||
}
|
||||
|
||||
return util
|
Loading…
x
Reference in New Issue
Block a user