2016-09-11 10:50:15 -07:00
-- basic vote by rnd, 2015
2016-01-26 06:26:26 -08:00
local basic_vote = { } ;
2016-08-26 04:09:16 -07:00
-- SETTINGS ----------------------------------------------------------------------
2016-01-26 06:26:26 -08:00
-- DEFINE VOTE TYPES
2016-10-07 05:46:48 -07:00
basic_vote.types = { -- [type] = { description , votes_needed , timeout, command, help_description}
[ 1 ] = { " ban %s for 2 minutes " , - 3 , 30 , " ban " , " Ban player for 2 minutes " } , -- -3 means strictly more than 3 players need to vote ( so 4 or more)
[ 2 ] = { " remove interact of %s " , 0.5 , 120 , " remove_interact " , " Remove 'interact' privilege from player " } , -- 0.5 means at least 50% need to vote
[ 3 ] = { " give interact to %s " , 0.5 , 120 , " give_interact " , " Give 'interact' privilege to player " } ,
[ 4 ] = { " kill %s " , - 3 , 30 , " kill " , " Kill player " } ,
[ 5 ] = { " poison %s " , - 3 , 30 , " poison " , " Poison player " } ,
[ 6 ] = { " teleport %s to vote starter " , - 3 , 30 , " teleport " , " Teleport player to you " } ,
[ 7 ] = { " change name color of %s " , - 2 , 30 , " name color " , " Change name of player " } ,
[ 8 ] = { " mutelate %s " , - 2 , 30 , " mutelate " , " Mute and kill player when talking " } ,
[ 9 ] = { " unmutelate " , - 2 , 30 , " unmutelate " , " Undo effects of mutelate " } ,
2016-10-08 11:00:47 -07:00
[ 10 ] = { " ask " , 1.0 , 30 , " ask " , " put a question up for voting " }
2016-08-26 04:09:16 -07:00
} ;
2016-09-13 12:44:18 -07:00
basic_vote.modreq = 2 ; -- more that this number of moderators from "anticheat" mod must vote for mod to succeed
2016-01-26 06:26:26 -08:00
2016-09-11 10:50:15 -07:00
-- needed for poison vote
local vote_poison_state = { } ;
2016-09-11 11:14:35 -07:00
basic_vote_poison = function ( name )
local player = minetest.get_player_by_name ( name ) ;
2016-09-11 10:50:15 -07:00
if not vote_poison_state [ name ] then
vote_poison_state [ name ] = 60 ;
end
vote_poison_state [ name ] = vote_poison_state [ name ] - 1 ;
if vote_poison_state [ name ] <= 0 then
vote_poison_state [ name ] = nil ; return ;
end
2016-09-11 11:14:35 -07:00
if player then
if player : get_hp ( ) > 0 then
player : set_hp ( player : get_hp ( ) - 4 ) ;
end
2016-09-11 10:50:15 -07:00
end
2016-09-11 11:14:35 -07:00
minetest.after ( 2 , function ( ) basic_vote_poison ( name ) end )
2016-09-11 10:50:15 -07:00
end
2016-09-13 12:44:18 -07:00
basic_vote.kicklist = { } ;
2016-10-02 04:16:06 -07:00
basic_vote.talklist = { } ;
2016-10-02 06:13:37 -07:00
basic_vote.huds = { } ;
2016-10-02 04:16:06 -07:00
-- for hud votes
local hud_definition =
{
hud_elem_type = " image " ,
scale = { x =- 50 , y =- 50 } ,
text = " default_stone.png " ,
size = { x = 50 , y = 50 } ,
offset = { x = 0 , y = 0 } ,
}
2016-09-11 10:50:15 -07:00
2016-01-26 06:26:26 -08:00
-- DEFINE WHAT HAPPENS WHEN VOTE SUCCEEDS
basic_vote.execute = function ( type , name , reason )
2016-10-07 07:05:00 -07:00
if type == 1 then
2016-09-13 12:44:18 -07:00
local ip = tostring ( minetest.get_player_ip ( name ) ) ;
basic_vote.kicklist [ ip ] = minetest.get_gametime ( ) ; -- remembers start time
2016-08-26 04:09:16 -07:00
minetest.kick_player ( name , reason )
2016-10-07 07:05:00 -07:00
elseif type == 2 then
2016-08-26 04:09:16 -07:00
local privs = core.get_player_privs ( name ) ; privs.interact = false
core.set_player_privs ( name , privs ) ; minetest.auth_reload ( )
2016-10-07 07:05:00 -07:00
elseif type == 3 then
2016-08-26 04:09:16 -07:00
local privs = core.get_player_privs ( name ) ; privs.interact = true ;
core.set_player_privs ( name , privs ) ; minetest.auth_reload ( )
2016-10-07 07:05:00 -07:00
elseif type == 4 then
2016-08-26 04:09:16 -07:00
local player = minetest.get_player_by_name ( name ) ; if not player then return end
player : set_hp ( 0 ) ;
2016-10-07 07:05:00 -07:00
elseif type == 5 then
2016-09-11 10:50:15 -07:00
local player = minetest.get_player_by_name ( name ) ; if not player then return end
if not vote_poison_state [ name ] then
2016-09-11 11:14:35 -07:00
basic_vote_poison ( name ) ;
2016-09-11 10:50:15 -07:00
end
2016-10-07 07:05:00 -07:00
elseif type == 6 then
2016-09-11 10:50:15 -07:00
local player = minetest.get_player_by_name ( name ) ; if not player then return end
local vname = basic_vote.vote . voter ; local vplayer = minetest.get_player_by_name ( vname ) ;
if not vplayer then return end
player : setpos ( vplayer : getpos ( ) ) ;
2016-10-07 07:05:00 -07:00
elseif type == 7 then
2016-10-02 04:16:06 -07:00
local player = minetest.get_player_by_name ( name ) ; if not player then return end
player : set_nametag_attributes ( { color = basic_vote.vote . reason } ) ;
2016-10-07 07:05:00 -07:00
elseif type == 8 then
2016-10-02 04:16:06 -07:00
local player = minetest.get_player_by_name ( name ) ; if not player then return end
basic_vote.talklist [ name ] = 1 ;
2016-10-07 07:05:00 -07:00
elseif type == 9 then
2016-10-02 04:16:06 -07:00
local player = minetest.get_player_by_name ( name ) ; if not player then return end
basic_vote.talklist [ name ] = nil ;
2016-10-07 07:05:00 -07:00
elseif type == 10 then
2016-10-02 06:13:37 -07:00
--basic_vote.huds[name]=player:hud_add(hud_definition);
2016-10-02 04:16:06 -07:00
2016-08-26 04:09:16 -07:00
end
2016-01-26 06:26:26 -08:00
end
2016-10-02 04:16:06 -07:00
-- for ban vote
2016-09-13 12:44:18 -07:00
minetest.register_on_prejoinplayer (
function ( name , ip )
local name ;
if basic_vote.kicklist [ ip ] then
local t = minetest.get_gametime ( ) ;
t = t - basic_vote.kicklist [ ip ] ;
if t > 120 then
basic_vote.kicklist [ ip ] = nil ;
else
2016-10-07 05:46:48 -07:00
return " You have been temporarily banned from the server. "
2016-09-13 12:44:18 -07:00
end
end
end
)
2016-10-02 04:16:06 -07:00
-- for talking votes
minetest.register_on_chat_message (
function ( name , message )
if basic_vote.talklist [ name ] then
if basic_vote.talklist [ name ] == 1 then -- kill
local player = minetest.get_player_by_name ( name ) ;
if not player then return end
if not player : get_inventory ( ) : is_empty ( " main " ) then
2016-10-02 06:13:37 -07:00
local p = player : getpos ( ) ;
p.x = math.floor ( p.x ) ; p.y = math.floor ( p.y ) ; p.z = math.floor ( p.z ) ;
minetest.chat_send_all ( " < " .. name .. " > please come get my bones at " .. minetest.pos_to_string ( p ) )
2016-10-02 04:16:06 -07:00
end
player : set_hp ( 0 ) ;
return true
end
end
end
)
2016-09-13 12:44:18 -07:00
2016-09-11 10:50:15 -07:00
2016-08-26 04:09:16 -07:00
-- END OF SETTINGS ---------------------------------------------------------------
basic_vote.votes = 0 ; -- vote count
2016-09-13 12:44:18 -07:00
basic_vote.modscore = 0 ; -- how many moderators voted - need 3 for vote to succeed
2016-08-26 04:09:16 -07:00
basic_vote.voters = { } ; -- who voted already
basic_vote.state = 0 ; -- 0 no vote, 1 vote in progress,2 timeout
2016-10-07 05:46:48 -07:00
basic_vote.vote = { time = 0 , type = 0 , name = " " , reason = " " , votes_needed = 0 , timeout = 0 , } ; -- description of current vote
2016-08-26 04:09:16 -07:00
basic_vote.requirements = { [ 0 ] = 0 }
2016-10-07 05:46:48 -07:00
basic_vote.vote_desc = " "
for i = 1 , # basic_vote.types do
basic_vote.vote_desc = basic_vote.vote_desc .. " Type " .. i .. " ( " .. basic_vote.types [ i ] [ 4 ] .. " ): " .. basic_vote.types [ i ] [ 5 ] .. " \n "
end
2016-08-26 04:09:16 -07:00
2016-10-07 05:46:48 -07:00
local function get_description ( vote )
local type_str = string.format ( basic_vote.types [ basic_vote.vote . type ] [ 1 ] , basic_vote.vote . name )
local timeout = math.max ( 0 , vote.timeout - os.difftime ( os.time ( ) , vote.time_start ) )
if vote.reason == nil or vote.reason == " " then
return string.format ( " ## VOTE by %s to %s. Timeout in %ds. " , vote.voter , type_str , timeout )
else
return string.format ( " ## VOTE by %s to %s with reason: '%s'. Timeout in %ds. " , vote.voter , type_str , vote.reason , timeout )
end
end
2016-01-26 06:26:26 -08:00
2016-09-13 12:44:18 -07:00
-- starts a new vote
2016-01-26 06:26:26 -08:00
minetest.register_chatcommand ( " vote " , {
privs = {
interact = true
} ,
2016-10-07 05:46:48 -07:00
params = " [[<type> <name> [<reason>]] | types] " ,
description = " Start a vote. '/vote types' for a list of types, '/vote' without arguments to see current voting progress " ,
2016-01-26 06:26:26 -08:00
func = function ( name , param )
2016-08-26 04:09:16 -07:00
if basic_vote.state ~= 0 then
2016-10-07 05:46:48 -07:00
minetest.chat_send_player ( name , " Vote already in progress: " )
minetest.chat_send_player ( name , get_description ( basic_vote.vote ) ) ;
2016-08-26 04:09:16 -07:00
return
2016-10-07 05:46:48 -07:00
elseif param == " " then
minetest.chat_send_player ( name , " No vote in progress. " )
return
2016-08-26 04:09:16 -07:00
end
2016-01-26 06:26:26 -08:00
local player = minetest.get_player_by_name ( name ) ;
-- split string param into parameters
local paramt = string.split ( param , " " )
for i = # paramt + 1 , 3 do paramt [ i ] = " " end
2016-10-07 05:46:48 -07:00
if paramt [ 1 ] == " types " then minetest.chat_send_player ( name , basic_vote.vote_desc ) return end
2016-01-26 06:26:26 -08:00
basic_vote.vote . time = minetest.get_gametime ( ) ;
basic_vote.vote . type = tonumber ( paramt [ 1 ] ) ;
2016-10-07 05:46:48 -07:00
-- check for text-based types
2016-10-08 11:00:47 -07:00
-- if basic_vote.vote.type == nil then
-- for i=1,#basic_vote.types do
-- if paramt[1] == basic_vote.types[i][4] then
-- basic_vote.vote.type = i
-- end
-- end
-- end
if not basic_vote.types [ basic_vote.vote . type ] then
minetest.chat_send_player ( name , " Error: Invalid syntax or type. Use '/help vote' for help. " )
return
2016-10-07 05:46:48 -07:00
end
2016-10-08 11:00:47 -07:00
-- if not basic_vote.vote.type then minetest.chat_send_player(name,"Error: Invalid syntax or type. Use '/help vote' for help.") return end
2016-10-07 05:46:48 -07:00
basic_vote.vote . name = paramt [ 2 ] or " an unknown player " ;
2016-09-11 10:50:15 -07:00
basic_vote.vote . voter = name ;
2016-10-07 05:46:48 -07:00
basic_vote.vote . reason = string.match ( param , " %w+ [%w_-]+ (.+) " )
2016-10-08 11:00:47 -07:00
basic_vote.vote . votes_needed = basic_vote.types [ basic_vote.vote . type ] [ 2 ] ;
2016-08-26 04:09:16 -07:00
basic_vote.vote . timeout = basic_vote.types [ basic_vote.vote . type ] [ 3 ] ;
2016-10-07 05:46:48 -07:00
basic_vote.vote . time_start = os.time ( ) ;
2016-08-26 04:09:16 -07:00
--check if target valid player
2016-10-07 05:46:48 -07:00
if basic_vote.vote . name == " " then
minetest.chat_send_player ( name , " Error: No player specified. " )
return
elseif not minetest.get_player_by_name ( basic_vote.vote . name ) and basic_vote.vote . type ~= 1 then
minetest.chat_send_player ( name , " Error: The specified player is currently not connected. " )
return
end
2016-09-12 06:39:35 -07:00
-- check anticheat db
local ip = tostring ( minetest.get_player_ip ( basic_vote.vote . name ) ) ;
2016-09-12 07:52:38 -07:00
if anticheatdb and anticheatdb [ ip ] then -- #anticheat mod: makes detected cheater more succeptible to voting
if anticheatsettings.moderators [ name ] then -- moderator must call vote
basic_vote.vote . votes_needed = 0 ; -- just need 1 vote
2016-10-07 05:46:48 -07:00
name = " an anonymous player " ; -- so cheater does not see who voted - anonymous vote
2016-09-12 07:52:38 -07:00
end
2016-08-27 01:28:31 -07:00
end
2016-01-26 06:26:26 -08:00
2016-09-13 12:44:18 -07:00
basic_vote.votes = 0 ; basic_vote.modscore = 0 ; basic_vote.voters = { } ;
2016-08-26 04:09:16 -07:00
2016-10-07 05:46:48 -07:00
local type_str = string.format ( basic_vote.types [ basic_vote.vote . type ] [ 1 ] , basic_vote.vote . name )
if basic_vote.vote . reason == nil or basic_vote.vote . reason == " " then
minetest.chat_send_all ( string.format ( " ## VOTE started (by %s to %s). \n Say '/y' to vote 'yes'. Timeout in %ds. " , name , type_str , basic_vote.vote . timeout ) )
else
minetest.chat_send_all ( string.format ( " ## VOTE started (by %s to %s) with reason: '%s'. \n Say '/y' to vote 'yes'. Timeout in %ds. " , name , type_str , basic_vote.vote . reason , basic_vote.vote . timeout ) )
end
2016-08-26 04:09:16 -07:00
basic_vote.state = 1 ; minetest.after ( basic_vote.vote . timeout , function ( )
2016-01-26 06:26:26 -08:00
if basic_vote.state == 1 then basic_vote.state = 2 ; basic_vote.update ( ) ; end
end )
end
}
)
2016-09-13 12:44:18 -07:00
-- check if enough votes for vote to succeed or fail vote if timeout
2016-01-26 06:26:26 -08:00
basic_vote.update = function ( )
local players = minetest.get_connected_players ( ) ;
local count = # players ;
2016-08-26 04:09:16 -07:00
local votes_needed ;
2016-09-13 12:44:18 -07:00
2016-08-26 04:09:16 -07:00
if basic_vote.vote . votes_needed > 0 then
votes_needed = basic_vote.vote . votes_needed * count ; -- percent of all players
if basic_vote.vote . votes_needed >= 0.5 then -- more serious vote, to prevent ppl voting serious stuff with few players on server, at least 6 votes needed
if votes_needed < 6 then votes_needed = 6 end
end
else
votes_needed = - basic_vote.vote . votes_needed ; -- number instead
end
2016-01-26 06:26:26 -08:00
if basic_vote.state == 2 then -- timeout
2016-10-07 05:46:48 -07:00
minetest.chat_send_all ( " ## VOTE failed. " .. basic_vote.votes .. " voted (needed more than " .. votes_needed .. " ). " ) ;
2016-01-26 06:26:26 -08:00
basic_vote.state = 0 ; basic_vote.vote = { time = 0 , type = 0 , name = " " , reason = " " } ; return
end
if basic_vote.state ~= 1 then return end -- no vote in progress
2016-09-13 12:44:18 -07:00
-- check if enough votes
if basic_vote.modscore > basic_vote.modreq then -- enough moderators voted for vote to succeed
basic_vote.votes = votes_needed + 1 ;
end
if basic_vote.votes > votes_needed then -- enough voters
2016-10-07 05:46:48 -07:00
minetest.chat_send_all ( " ## VOTE succeded. " .. basic_vote.votes .. " voted. " ) ;
2016-01-26 06:26:26 -08:00
local type = basic_vote.vote . type ;
basic_vote.execute ( basic_vote.vote . type , basic_vote.vote . name , basic_vote.vote . reason )
basic_vote.state = 0 ; basic_vote.vote = { time = 0 , type = 0 , name = " " , reason = " " } ;
end
end
2016-09-13 12:44:18 -07:00
local cast_vote = function ( name , param )
2016-10-07 05:46:48 -07:00
if basic_vote.state ~= 1 then
-- vote not in progress
minetest.chat_send_player ( name , " Error: No vote in progress. " ) ;
return
end
2016-09-12 06:39:35 -07:00
local ip = tostring ( minetest.get_player_ip ( name ) ) ;
2016-10-07 05:46:48 -07:00
if basic_vote.voters [ ip ] then
minetest.chat_send_player ( name , " Error: You already voted. " ) ;
return
else
-- mark as already voted
basic_vote.voters [ ip ] = true
end
2016-09-13 12:44:18 -07:00
basic_vote.votes = basic_vote.votes + 1 ;
if anticheatsettings and anticheatsettings.moderators [ name ] then -- moderator from anticheat mod
basic_vote.modscore = basic_vote.modscore + 1 ;
end
local privs = core.get_player_privs ( name ) ; if privs.kick then basic_vote.votes = 100 ; end
2016-10-07 05:46:48 -07:00
basic_vote.update ( ) ; minetest.chat_send_player ( name , " Vote received. " ) ;
2016-09-13 12:44:18 -07:00
end
2016-01-26 06:26:26 -08:00
2016-09-13 12:44:18 -07:00
minetest.register_chatcommand ( " y " , {
2016-01-26 06:26:26 -08:00
privs = {
interact = true
} ,
2016-10-07 05:46:48 -07:00
params = " " ,
description = " Vote 'Yes.' in the current vote (see vote command) " ,
2016-01-26 06:26:26 -08:00
func = function ( name , param )
2016-09-13 12:44:18 -07:00
cast_vote ( name , param )
2016-01-26 06:26:26 -08:00
end
}
2016-10-07 05:46:48 -07:00
)