This commit is contained in:
philipmi 2021-03-29 15:04:23 +02:00
commit 16c31aa273
6 changed files with 119 additions and 37 deletions

View file

@ -6,6 +6,16 @@ function ctf_match.register_on_skip_map(func)
table.insert(ctf_match.registered_on_skip_map, func) table.insert(ctf_match.registered_on_skip_map, func)
end end
function skip()
for i = 1, #ctf_match.registered_on_skip_map do
ctf_match.registered_on_skip_map[i]()
end
ctf_match.next()
end
local can_vote_skip = false
local voted_skip = false
local flags_hold = 0
function ctf_match.vote_next(name) function ctf_match.vote_next(name)
local tcolor = ctf_colors.get_color(ctf.player(name)).css or "#FFFFFFFF" local tcolor = ctf_colors.get_color(ctf.player(name)).css or "#FFFFFFFF"
minetest.chat_send_all(minetest.colorize("#FFAA11", "Vote started by ") .. minetest.chat_send_all(minetest.colorize("#FFAA11", "Vote started by ") ..
@ -22,10 +32,12 @@ function ctf_match.vote_next(name)
if result == "yes" then if result == "yes" then
minetest.chat_send_all("Vote to skip match passed, " .. minetest.chat_send_all("Vote to skip match passed, " ..
#results.yes .. " to " .. #results.no) #results.yes .. " to " .. #results.no)
for i = 1, #ctf_match.registered_on_skip_map do
ctf_match.registered_on_skip_map[i]() can_vote_skip = false
voted_skip = true
if flags_hold <= 0 then
skip()
end end
ctf_match.next()
else else
minetest.chat_send_all("Vote to skip match failed, " .. minetest.chat_send_all("Vote to skip match failed, " ..
#results.no .. " to " .. #results.yes) #results.no .. " to " .. #results.yes)
@ -53,9 +65,8 @@ minetest.register_chatcommand("vote", {
local matchskip_time local matchskip_time
local matchskip_timer = 0 local matchskip_timer = 0
local can_skip = false
minetest.register_globalstep(function(dtime) minetest.register_globalstep(function(dtime)
if not can_skip then return end if not can_vote_skip then return end
matchskip_timer = matchskip_timer + dtime matchskip_timer = matchskip_timer + dtime
@ -68,18 +79,25 @@ minetest.register_globalstep(function(dtime)
end end
end) end)
local function prevent_autoskip() ctf.register_on_new_game(function()
can_skip = false can_vote_skip = false
end voted_skip = false
flags_hold = 0
ctf.register_on_new_game(prevent_autoskip) end)
ctf_flag.register_on_pick_up(prevent_autoskip) ctf_flag.register_on_pick_up(function()
flags_hold = flags_hold + 1
end)
ctf_flag.register_on_drop(function() ctf_flag.register_on_drop(function()
can_skip = true flags_hold = flags_hold - 1
if voted_skip and flags_hold <= 0 then
minetest.after(5, function()
skip()
end)
end
end) end)
ctf_match.register_on_build_time_end(function() ctf_match.register_on_build_time_end(function()
can_skip = true can_vote_skip = true
matchskip_timer = 0 matchskip_timer = 0
-- Set to initial vote time -- Set to initial vote time
matchskip_time = tonumber(minetest.settings:get("ctf_match.auto_skip_delay")) or 50 * 60 matchskip_time = tonumber(minetest.settings:get("ctf_match.auto_skip_delay")) or 50 * 60

View file

@ -188,27 +188,6 @@ function _doors.door_toggle(pos, node, clicker)
end end
local function on_place_node(place_to, newnode,
placer, oldnode, itemstack, pointed_thing)
-- Run script hook
for _, callback in ipairs(minetest.registered_on_placenodes) do
-- Deepcopy pos, node and pointed_thing because callback can modify them
local place_to_copy = {x = place_to.x, y = place_to.y, z = place_to.z}
local newnode_copy =
{name = newnode.name, param1 = newnode.param1, param2 = newnode.param2}
local oldnode_copy =
{name = oldnode.name, param1 = oldnode.param1, param2 = oldnode.param2}
local pointed_thing_copy = {
type = pointed_thing.type,
above = vector.new(pointed_thing.above),
under = vector.new(pointed_thing.under),
ref = pointed_thing.ref,
}
callback(place_to_copy, newnode_copy, placer,
oldnode_copy, itemstack, pointed_thing_copy)
end
end
local function can_dig_door(pos, digger) local function can_dig_door(pos, digger)
replace_old_owner_information(pos) replace_old_owner_information(pos)
if default.can_interact_with_node(digger, pos) then if default.can_interact_with_node(digger, pos) then
@ -362,15 +341,19 @@ function doors.register(name, def)
meta:set_string("owner_team", tname) meta:set_string("owner_team", tname)
end end
local copy = table.copy
local newnode = minetest.get_node(pos)
for _, on_placenode in ipairs(minetest.registered_on_placenodes) do
if on_placenode(copy(pos), copy(newnode), placer, copy(node), ItemStack(itemstack), copy(pointed_thing)) then
return itemstack
end
end
if not (creative and creative.is_enabled_for and creative.is_enabled_for(pn)) then if not (creative and creative.is_enabled_for and creative.is_enabled_for(pn)) then
itemstack:take_item() itemstack:take_item()
end end
minetest.sound_play(def.sounds.place, {pos = pos}) minetest.sound_play(def.sounds.place, {pos = pos})
on_place_node(pos, minetest.get_node(pos),
placer, node, itemstack, pointed_thing)
return itemstack return itemstack
end end
}) })

View file

@ -0,0 +1,19 @@
Copyright (c) 2021 appgurueu
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,8 @@
# `place_limit`
Fixes two things related to node placement:
* Ratelimits node placement
* Disallows building to non-pointable nodes (anticheat + race condition fix)
Licensed under the MIT license, written by appgurueu.

View file

@ -0,0 +1,51 @@
-- Licensed under the MIT license, written by appgurueu.
local players = {}
local blocks_per_second = 5
local resend_notification_seconds = 10
-- Bootstrap 4 "warning" color
local warning_color = 0xFFC107
minetest.register_on_joinplayer(function(player)
-- player has to wait after join before they can place a node
players[player:get_player_name()] = {
last_notification_sent = -math.huge
}
end)
minetest.register_on_leaveplayer(function(player)
players[player:get_player_name()] = nil
end)
minetest.register_on_placenode(function(pos, _newnode, placer, oldnode, _itemstack, pointed_thing)
local name = placer:get_player_name()
if not ItemStack(minetest.get_node(pointed_thing.under).name):get_definition().pointable then
-- This should happen rarely
hud_event.new(name, {
name = "place_limit:unpointable",
color = warning_color,
value = "Block not pointable (dug/replaced)!",
})
minetest.set_node(pos, oldnode)
return true
end
local time = minetest.get_us_time()
local placements = players[name]
for i = #placements, 1, -1 do
if time - placements[i] > 1e6 then
placements[i] = nil
end
end
if #placements >= blocks_per_second then
if (time - placements.last_notification_sent) / 1e6 >= resend_notification_seconds then
hud_event.new(name, {
name = "place_limit:speed",
color = warning_color,
value = "Placing too fast!",
})
placements.last_notification_sent = time
end
minetest.set_node(pos, oldnode)
return true
end
table.insert(placements, 1, time)
end)

View file

@ -0,0 +1,3 @@
name = place_limit
description = Limits block placement
depends = hud_events