Add vote and ctf_match
This commit is contained in:
parent
948e2586e0
commit
07f2973337
10 changed files with 669 additions and 5 deletions
|
@ -9,9 +9,11 @@ ctf.allocate_mode = 3
|
|||
ctf.diplomacy = false
|
||||
ctf.players_can_change_team = false
|
||||
ctf.node_ownership = false
|
||||
ctf.newgame.teams = red, red, 15, 7, 39; blue, blue, -9, 9, -43
|
||||
ctf.newgame.clear_inv = true
|
||||
ctf.endgame.destroy_team = true
|
||||
ctf.endgame.reset_on_winner = true
|
||||
ctf.match = true
|
||||
ctf.match.teams = red, red, 15, 7, 39; blue, blue, -9, 9, -43
|
||||
ctf.match.clear_inv = true
|
||||
ctf.match.destroy_team = true
|
||||
ctf.match.reset_on_winner = true
|
||||
ctf.remove_player_on_leave = true
|
||||
ctf.autoalloc_on_joinplayer = true
|
||||
ctf.matchmap_reset_limit = 160
|
||||
|
|
9
mods/ctf_match/chat.lua
Normal file
9
mods/ctf_match/chat.lua
Normal file
|
@ -0,0 +1,9 @@
|
|||
minetest.register_chatcommand("ctf_next", {
|
||||
description = "Skip to the next match",
|
||||
privs = {
|
||||
ctf_admin = true
|
||||
},
|
||||
func = function(name, param)
|
||||
ctf_match.next()
|
||||
end
|
||||
})
|
3
mods/ctf_match/depends.txt
Normal file
3
mods/ctf_match/depends.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
ctf
|
||||
ctf_flag
|
||||
vote
|
154
mods/ctf_match/init.lua
Normal file
154
mods/ctf_match/init.lua
Normal file
|
@ -0,0 +1,154 @@
|
|||
ctf.register_on_init(function()
|
||||
ctf._set("match", false)
|
||||
ctf._set("match.destroy_team", false)
|
||||
ctf._set("match.break_alliances", true)
|
||||
ctf._set("match.teams", "")
|
||||
ctf._set("match.clear_inv", false)
|
||||
ctf._set("match.map_reset_limit", 0)
|
||||
end)
|
||||
|
||||
ctf_match = {}
|
||||
|
||||
-- Load next match
|
||||
function ctf_match.next()
|
||||
local r = ctf.setting("match.map_reset_limit")
|
||||
if r > 0 then
|
||||
minetest.chat_send_all("Resetting the map, this may take a few moments...")
|
||||
minetest.after(0.5, function()
|
||||
minetest.delete_area(vector.new(-r, -r, -r), vector.new(r, r, r))
|
||||
|
||||
minetest.after(1, function()
|
||||
ctf.reset()
|
||||
end)
|
||||
end)
|
||||
else
|
||||
ctf.reset()
|
||||
end
|
||||
|
||||
-- Note: ctf.reset calls register_on_new_game, below.
|
||||
end
|
||||
|
||||
-- Check for winner
|
||||
function ctf_match.check_for_winner()
|
||||
local winner
|
||||
for name, team in pairs(ctf.teams) do
|
||||
if winner then
|
||||
return
|
||||
end
|
||||
winner = name
|
||||
end
|
||||
|
||||
-- There is a winner!
|
||||
ctf.action("match", winner .. " won!")
|
||||
minetest.chat_send_all("Team " .. winner .. " won!")
|
||||
if ctf.setting("match") then
|
||||
ctf_match.next()
|
||||
end
|
||||
end
|
||||
|
||||
ctf.register_on_new_game(function()
|
||||
local function safe_place(pos, node)
|
||||
ctf.log("match", "attempting to place...")
|
||||
minetest.get_voxel_manip(pos, { x = pos.x + 1, y = pos.y + 1, z = pos.z + 1})
|
||||
minetest.set_node(pos, node)
|
||||
if minetest.get_node(pos).name ~= node.name then
|
||||
ctf.error("match", "failed to place node, retrying...")
|
||||
minetest.after(0.5, function()
|
||||
safe_place(pos, node)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
local teams = ctf.setting("match.teams")
|
||||
if teams:trim() == "" then
|
||||
return
|
||||
end
|
||||
ctf.log("match", "Setting up new game!")
|
||||
|
||||
teams = teams:split(";")
|
||||
local pos = {}
|
||||
for i, v in pairs(teams) do
|
||||
local team = v:split(",")
|
||||
if #team == 5 then
|
||||
local name = team[1]:trim()
|
||||
local color = team[2]:trim()
|
||||
local x = tonumber(team[3]:trim())
|
||||
local y = tonumber(team[4]:trim())
|
||||
local z = tonumber(team[5]:trim())
|
||||
pos[name] = {
|
||||
x = x,
|
||||
y = y,
|
||||
z = z
|
||||
}
|
||||
|
||||
ctf.team({
|
||||
name = name,
|
||||
color = color,
|
||||
add_team = true
|
||||
})
|
||||
|
||||
ctf_flag.add(name, pos[name])
|
||||
else
|
||||
ctf.warning("match", "Invalid team setup: " .. dump(v))
|
||||
end
|
||||
end
|
||||
|
||||
minetest.after(0, function()
|
||||
for name, p in pairs(pos) do
|
||||
safe_place(p, {name = "ctf_flag:flag"})
|
||||
ctf_flag.update(p)
|
||||
end
|
||||
end)
|
||||
|
||||
for i, player in pairs(minetest.get_connected_players()) do
|
||||
local name = player:get_player_name()
|
||||
local alloc_mode = tonumber(ctf.setting("allocate_mode"))
|
||||
local team = ctf.autoalloc(name, alloc_mode)
|
||||
|
||||
if alloc_mode ~= 0 and team then
|
||||
ctf.log("autoalloc", name .. " was allocated to " .. team)
|
||||
ctf.join(name, team)
|
||||
end
|
||||
|
||||
team = ctf.player(name).team
|
||||
if ctf.team(team) then
|
||||
local spawn = ctf.get_spawn(team)
|
||||
if spawn then
|
||||
player:moveto(spawn, false)
|
||||
end
|
||||
end
|
||||
|
||||
if ctf.setting("match.clear_inv") then
|
||||
local inv = player:get_inventory()
|
||||
inv:set_list("main", {})
|
||||
inv:set_list("craft", {})
|
||||
give_initial_stuff(player)
|
||||
end
|
||||
|
||||
player:set_hp(20)
|
||||
end
|
||||
minetest.chat_send_all("Next round!")
|
||||
end)
|
||||
|
||||
ctf_flag.register_on_capture(function(attname, flag)
|
||||
if not ctf.setting("match.destroy_team") then
|
||||
return
|
||||
end
|
||||
|
||||
local fl_team = ctf.team(flag.team)
|
||||
if fl_team and #fl_team.flags == 0 then
|
||||
ctf.action("match", flag.team .. " was defeated.")
|
||||
ctf.remove_team(flag.team)
|
||||
minetest.chat_send_all(flag.team .. " has been defeated!")
|
||||
end
|
||||
|
||||
ctf_match.check_for_winner()
|
||||
end)
|
||||
|
||||
local claimed = ctf_flag.collect_claimed()
|
||||
for i, flag in pairs(claimed) do
|
||||
flag.claimed = nil
|
||||
end
|
||||
|
||||
dofile(minetest.get_modpath("ctf_match") .. "/chat.lua")
|
||||
dofile(minetest.get_modpath("ctf_match") .. "/vote.lua")
|
28
mods/ctf_match/vote.lua
Normal file
28
mods/ctf_match/vote.lua
Normal file
|
@ -0,0 +1,28 @@
|
|||
minetest.register_chatcommand("vote_next", {
|
||||
privs = {
|
||||
interact = true
|
||||
},
|
||||
func = function(name, param)
|
||||
vote.new_vote(name, {
|
||||
description = "Skip to next map",
|
||||
help = "/yes, /no or /abstain",
|
||||
duration = 60,
|
||||
perc_needed = 0.5,
|
||||
unanimous = 5,
|
||||
|
||||
on_result = function(self, result, results)
|
||||
if result == "yes" then
|
||||
ctf_match.next()
|
||||
else
|
||||
minetest.chat_send_all("Vote to skip map failed, " ..
|
||||
#results.yes .. " to " .. #results.no)
|
||||
end
|
||||
end,
|
||||
|
||||
on_vote = function(self, name, value)
|
||||
minetest.chat_send_all(name .. " voted " .. value .. " to '" ..
|
||||
self.description .. "'")
|
||||
end
|
||||
})
|
||||
end
|
||||
})
|
|
@ -1 +1 @@
|
|||
Subproject commit 9d159917682aae47239b8df8292fde927c3ba871
|
||||
Subproject commit 17e7a2b529e1a10c866a2b588f0971daf7931946
|
96
mods/vote/README.md
Normal file
96
mods/vote/README.md
Normal file
|
@ -0,0 +1,96 @@
|
|||
# Vote
|
||||
A mod for Minetest adding an API to allow voting on servers.
|
||||
|
||||
Version 0.1
|
||||
|
||||
Created by [rubenwardy](http://rubenwardy.com)
|
||||
Copyright (c) 2015, no rights reserved
|
||||
Licensed under WTFPL or CC0 (you choose)
|
||||
|
||||
# Settings
|
||||
|
||||
* vote.maximum_active - maximum votes running at a time, votes are queued if it
|
||||
reaches this. Defaults to 1.
|
||||
|
||||
# Example
|
||||
|
||||
```lua
|
||||
minetest.register_chatcommand("vote_kick", {
|
||||
privs = {
|
||||
interact = true
|
||||
},
|
||||
func = function(name, param)
|
||||
if not minetest.get_player_by_name(param) then
|
||||
minetest.chat_send_player(name, "There is no player called '" ..
|
||||
param .. "'")
|
||||
end
|
||||
|
||||
vote.new_vote(name, {
|
||||
description = "Kick player " .. param,
|
||||
help = "/yes, /no or /abstain",
|
||||
name = param,
|
||||
duration = 60,
|
||||
|
||||
on_result = function(self, result, results)
|
||||
if result == "yes" then
|
||||
minetest.chat_send_all("Vote passed, " ..
|
||||
#results.yes .. " to " .. #results.no .. ", " ..
|
||||
self.name .. " will be kicked.")
|
||||
minetest.kick_player(self.name, "The vote to kick you passed")
|
||||
else
|
||||
minetest.chat_send_all("Vote failed, " ..
|
||||
#results.yes .. " to " .. #results.no .. ", " ..
|
||||
self.name .. " remains ingame.")
|
||||
end
|
||||
end,
|
||||
|
||||
on_vote = function(self, name, value)
|
||||
minetest.chat_send_all(name .. " voted " .. value .. " to '" ..
|
||||
self.description .. "'")
|
||||
end
|
||||
})
|
||||
end
|
||||
})
|
||||
```
|
||||
|
||||
# API
|
||||
|
||||
## Results
|
||||
|
||||
* voted - a key-value table. voted[name] = true if a player called name voted.
|
||||
* abstain - a list of the names of players who abstained.
|
||||
* <option> - a list of the names of players who voted for this option.
|
||||
|
||||
For example:
|
||||
|
||||
```lua
|
||||
results = {
|
||||
voted = {
|
||||
one = true,
|
||||
two = true,
|
||||
three = true,
|
||||
four = true
|
||||
}
|
||||
yes = {"one", "three"},
|
||||
no = {"two"}
|
||||
abstain = {"four"}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Values
|
||||
|
||||
* description - required.
|
||||
* help - recommended. How to respond to the vote.
|
||||
* duration - the duration of the vote, before it expires.
|
||||
* perc_needed - if yes/no, this is the percentage needed to pass.
|
||||
* options - a list of possible options. (not fully supported yet)
|
||||
|
||||
## Methods
|
||||
|
||||
* can_vote(self, name) - return true if player `name` can vote on this issue.
|
||||
* on_start(self) - called when vote starts. Return false to cancel.
|
||||
* on_decide(self, results) - see results section. Return the winning result.
|
||||
* on_result(self, result, results) - when vote ends, result is the winning result
|
||||
* on_vote(self, name, value) - called when a player casts a vote
|
||||
* on_abstain(self, name) - called when a player abstains
|
48
mods/vote/hudkit.lua
Normal file
48
mods/vote/hudkit.lua
Normal file
|
@ -0,0 +1,48 @@
|
|||
-- HudKit, by rubenwardy
|
||||
-- License: Either WTFPL or CC0, you can choose.
|
||||
|
||||
local function hudkit()
|
||||
return {
|
||||
players = {},
|
||||
|
||||
add = function(self, player, id, def)
|
||||
local name = player:get_player_name()
|
||||
local elements = self.players[name]
|
||||
|
||||
if not elements then
|
||||
self.players[name] = {}
|
||||
elements = self.players[name]
|
||||
end
|
||||
|
||||
elements[id] = player:hud_add(def)
|
||||
end,
|
||||
|
||||
exists = function(self, player, id)
|
||||
local elements = self.players[player:get_player_name()]
|
||||
return elements and elements[id]
|
||||
end,
|
||||
|
||||
change = function(self, player, id, stat, value)
|
||||
local elements = self.players[player:get_player_name()]
|
||||
if not elements or not elements[id] then
|
||||
return false
|
||||
end
|
||||
|
||||
player:hud_change(elements[id], stat, value)
|
||||
return true
|
||||
end,
|
||||
|
||||
remove = function(self, player, id)
|
||||
local elements = self.players[player:get_player_name()]
|
||||
if not elements or not elements[id] then
|
||||
return false
|
||||
end
|
||||
|
||||
player:hud_remove(elements[id])
|
||||
elements[id] = nil
|
||||
return true
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
return hudkit
|
324
mods/vote/init.lua
Normal file
324
mods/vote/init.lua
Normal file
|
@ -0,0 +1,324 @@
|
|||
vote = {
|
||||
active = {},
|
||||
queue = {}
|
||||
}
|
||||
|
||||
function vote.new_vote(creator, voteset)
|
||||
local max_votes = tonumber(minetest.setting_get("vote.maximum_active")) or 1
|
||||
|
||||
if #vote.active < max_votes then
|
||||
vote.start_vote(voteset)
|
||||
else
|
||||
table.insert(vote.queue, voteset)
|
||||
if creator then
|
||||
minetest.chat_send_player(creator,
|
||||
"Vote queued until there is less then " .. max_votes ..
|
||||
" votes active.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function vote.start_vote(voteset)
|
||||
minetest.log("action", "Vote started: " .. voteset.description)
|
||||
|
||||
table.insert(vote.active, voteset)
|
||||
|
||||
-- Build results table
|
||||
voteset.results = {
|
||||
abstain = {},
|
||||
voted = {}
|
||||
}
|
||||
if voteset.options then
|
||||
for _, option in pairs(voteset.options) do
|
||||
voteset.results[option] = {}
|
||||
print(" - " .. option)
|
||||
end
|
||||
else
|
||||
voteset.results.yes = {}
|
||||
voteset.results.no = {}
|
||||
end
|
||||
|
||||
-- Run start callback
|
||||
if voteset.on_start then
|
||||
voteset:on_start()
|
||||
end
|
||||
|
||||
-- Timer for end
|
||||
if voteset.duration or voteset.time then
|
||||
minetest.after(voteset.duration + 0.1, function()
|
||||
vote.end_vote(voteset)
|
||||
end)
|
||||
end
|
||||
|
||||
-- Show HUD a.s.a.p.
|
||||
vote.update_all_hud()
|
||||
end
|
||||
|
||||
function vote.end_vote(voteset)
|
||||
local removed = false
|
||||
for i, voteset2 in pairs(vote.active) do
|
||||
if voteset == voteset2 then
|
||||
table.remove(vote.active, i, 1)
|
||||
removed = true
|
||||
end
|
||||
end
|
||||
if not removed then
|
||||
return
|
||||
end
|
||||
|
||||
local result = nil
|
||||
if voteset.on_decide then
|
||||
result = voteset:on_decide(voteset.results)
|
||||
elseif voteset.results.yes and voteset.results.no then
|
||||
local total = #voteset.results.yes + #voteset.results.no
|
||||
local perc_needed = voteset.perc_needed or 0.5
|
||||
local unanimous = voteset.unanimous or 0
|
||||
|
||||
if total <= unanimous then
|
||||
if #voteset.results.no == 0 then
|
||||
result = "yes"
|
||||
else
|
||||
result = "no"
|
||||
end
|
||||
else
|
||||
if #voteset.results.yes / total > perc_needed then
|
||||
result = "yes"
|
||||
else
|
||||
result = "no"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
minetest.log("action", "Vote '" .. voteset.description ..
|
||||
"' ended with result '" .. result .. "'.")
|
||||
|
||||
if voteset.on_result then
|
||||
voteset:on_result(result, voteset.results)
|
||||
end
|
||||
|
||||
local max_votes = tonumber(minetest.setting_get("vote.maximum_active")) or 1
|
||||
if #vote.active < max_votes and #vote.queue > 0 then
|
||||
local nextvote = table.remove(vote.queue, 1)
|
||||
vote.start_vote(nextvote)
|
||||
else
|
||||
-- Update HUD a.s.a.p.
|
||||
vote.update_all_hud()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function vote.get_next_vote(name)
|
||||
for _, voteset in pairs(vote.active) do
|
||||
if not voteset.results.voted[name] then
|
||||
return voteset
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function vote.check_vote(voteset)
|
||||
local all_players_voted = true
|
||||
local players = minetest.get_connected_players()
|
||||
for _, player in pairs(players) do
|
||||
local name = player:get_player_name()
|
||||
if not voteset.results.voted[name] then
|
||||
all_players_voted = false
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if all_players_voted then
|
||||
vote.end_vote(voteset)
|
||||
end
|
||||
end
|
||||
|
||||
function vote.vote(voteset, name, value)
|
||||
if not voteset.results[value] then
|
||||
return
|
||||
end
|
||||
|
||||
minetest.log("action", name .. " voted '" .. value .. "' to '"
|
||||
.. voteset.description .. "'")
|
||||
|
||||
table.insert(voteset.results[value], name)
|
||||
voteset.results.voted[name] = true
|
||||
if voteset.on_vote then
|
||||
voteset:on_vote(name, value)
|
||||
end
|
||||
vote.check_vote(voteset)
|
||||
end
|
||||
|
||||
local hudkit = dofile(minetest.get_modpath("vote") .. "/hudkit.lua")
|
||||
vote.hud = hudkit()
|
||||
function vote.update_hud(player)
|
||||
local name = player:get_player_name()
|
||||
local voteset = vote.get_next_vote(name)
|
||||
if not voteset then
|
||||
vote.hud:remove(player, "vote:desc")
|
||||
vote.hud:remove(player, "vote:bg")
|
||||
vote.hud:remove(player, "vote:help")
|
||||
return
|
||||
end
|
||||
|
||||
if not vote.hud:exists(player, "vote:bg") then
|
||||
vote.hud:add(player, "vote:bg", {
|
||||
hud_elem_type = "image",
|
||||
position = {x = 1, y = 0.5},
|
||||
scale = {x = 1, y = 1},
|
||||
text = "vote_background.png",
|
||||
offset = {x=-100, y = 10},
|
||||
number = 0xFFFFFF
|
||||
})
|
||||
end
|
||||
|
||||
if vote.hud:exists(player, "vote:desc") then
|
||||
vote.hud:change(player, "vote:desc", "text", voteset.description .. "?")
|
||||
else
|
||||
vote.hud:add(player, "vote:desc", {
|
||||
hud_elem_type = "text",
|
||||
position = {x = 1, y = 0.5},
|
||||
scale = {x = 100, y = 100},
|
||||
text = voteset.description .. "?",
|
||||
offset = {x=-100, y = 0},
|
||||
number = 0xFFFFFF
|
||||
})
|
||||
end
|
||||
|
||||
if voteset.help then
|
||||
if vote.hud:exists(player, "vote:help") then
|
||||
vote.hud:change(player, "vote:help", "text", voteset.help)
|
||||
else
|
||||
vote.hud:add(player, "vote:help", {
|
||||
hud_elem_type = "text",
|
||||
position = {x = 1, y = 0.5},
|
||||
scale = {x = 100, y = 100},
|
||||
text = voteset.help,
|
||||
offset = {x=-100, y = 20},
|
||||
number = 0xFFFFFF
|
||||
})
|
||||
end
|
||||
else
|
||||
vote.hud:remove(player, "vote:help")
|
||||
end
|
||||
end
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
vote.hud.players[player:get_player_name()] = nil
|
||||
end)
|
||||
function vote.update_all_hud()
|
||||
local players = minetest.get_connected_players()
|
||||
for _, player in pairs(players) do
|
||||
vote.update_hud(player)
|
||||
end
|
||||
minetest.after(5, vote.update_all_hud)
|
||||
end
|
||||
minetest.after(5, vote.update_all_hud)
|
||||
|
||||
minetest.register_chatcommand("yes", {
|
||||
privs = {
|
||||
interact = true
|
||||
},
|
||||
func = function(name, params)
|
||||
local voteset = vote.get_next_vote(name)
|
||||
if not voteset then
|
||||
minetest.chat_send_player(name,
|
||||
"There is no vote currently running!")
|
||||
return
|
||||
elseif not voteset.results.yes then
|
||||
minetest.chat_send_player(name, "The vote is not a yes/no one.")
|
||||
return
|
||||
elseif voteset.can_vote and not voteset:can_vote(name) then
|
||||
minetest.chat_send_player(name,
|
||||
"You can't vote in the currently active vote!")
|
||||
return
|
||||
end
|
||||
|
||||
vote.vote(voteset, name, "yes")
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("no", {
|
||||
privs = {
|
||||
interact = true
|
||||
},
|
||||
func = function(name, params)
|
||||
local voteset = vote.get_next_vote(name)
|
||||
if not voteset then
|
||||
minetest.chat_send_player(name,
|
||||
"There is no vote currently running!")
|
||||
return
|
||||
elseif not voteset.results.no then
|
||||
minetest.chat_send_player(name, "The vote is not a yes/no one.")
|
||||
return
|
||||
elseif voteset.can_vote and not voteset:can_vote(name) then
|
||||
minetest.chat_send_player(name,
|
||||
"You can't vote in the currently active vote!")
|
||||
return
|
||||
end
|
||||
|
||||
vote.vote(voteset, name, "no")
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("abstain", {
|
||||
privs = {
|
||||
interact = true
|
||||
},
|
||||
func = function(name, params)
|
||||
local voteset = vote.get_next_vote(name)
|
||||
if not voteset then
|
||||
minetest.chat_send_player(name,
|
||||
"There is no vote currently running!")
|
||||
return
|
||||
elseif voteset.can_vote and not voteset:can_vote(name) then
|
||||
minetest.chat_send_player(name,
|
||||
"You can't vote in the currently active vote!")
|
||||
return
|
||||
end
|
||||
|
||||
table.insert(voteset.results.abstain, name)
|
||||
voteset.results.voted[name] = true
|
||||
if voteset.on_abstain then
|
||||
voteset:on_abstain(name)
|
||||
end
|
||||
vote.check_vote(voteset)
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("vote_kick", {
|
||||
privs = {
|
||||
interact = true
|
||||
},
|
||||
func = function(name, param)
|
||||
if not minetest.get_player_by_name(param) then
|
||||
minetest.chat_send_player(name, "There is no player called '" ..
|
||||
param .. "'")
|
||||
return
|
||||
end
|
||||
|
||||
vote.new_vote(name, {
|
||||
description = "Kick " .. param,
|
||||
help = "/yes, /no or /abstain",
|
||||
name = param,
|
||||
duration = 60,
|
||||
perc_needed = 0.8,
|
||||
|
||||
on_result = function(self, result, results)
|
||||
if result == "yes" then
|
||||
minetest.chat_send_all("Vote passed, " ..
|
||||
#results.yes .. " to " .. #results.no .. ", " ..
|
||||
self.name .. " will be kicked.")
|
||||
minetest.kick_player(self.name, "The vote to kick you passed")
|
||||
else
|
||||
minetest.chat_send_all("Vote failed, " ..
|
||||
#results.yes .. " to " .. #results.no .. ", " ..
|
||||
self.name .. " remains ingame.")
|
||||
end
|
||||
end,
|
||||
|
||||
on_vote = function(self, name, value)
|
||||
minetest.chat_send_all(name .. " voted " .. value .. " to '" ..
|
||||
self.description .. "'")
|
||||
end
|
||||
})
|
||||
end
|
||||
})
|
BIN
mods/vote/textures/vote_background.png
Normal file
BIN
mods/vote/textures/vote_background.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 278 B |
Loading…
Reference in a new issue