-- Licensed under the MIT license, written by appgurueu. local players = {} local blocks_per_second = 4 local resend_notification_seconds = 10 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", 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", value = "Placing too fast!", }) placements.last_notification_sent = time end minetest.set_node(pos, oldnode) return true end table.insert(placements, 1, time) end)