-- This mod disallows changing blocks in certain game modes. -- In Editor mode, out-of-bounds blocks cannot be changed. -- This can be bypassed with the server or protection_bypass privileges. -- This also disallows taking blocks in the game when the inventory is full. -- How many seconds to flash the hotbar if the inventory was full local HOTBAR_FLASH_TIME = 0.5 -- Checks if the player would have room for the given node -- in inventory and returns true. Or false if inventory has -- no room left. Exception: -- When player wields a non-digging tool, always returns -- true. local function has_room_for_node_drops(player, node) local tool = player:get_wielded_item() local tooldef = tool:get_definition() -- This is not a digging tool as it would do -- something else on dig if tooldef.on_use then return true end local inv = player:get_inventory() local def = minetest.registered_nodes[node.name] -- This assumes drops aren't random (which wouldn't -- make sense in this game anyway) local drops = minetest.get_node_drops(node, tool) for d=1, #drops do local drop = drops[d] if not inv:room_for_item("main", drop) then return false end end return true end local old_is_protected = minetest.is_protected minetest.is_protected = function(pos, name) local state = lzr_gamestate.get_state() -- Can't dig if inventory is full! (unless in editor) if state ~= lzr_gamestate.EDITOR then local player = minetest.get_player_by_name(name) local node = minetest.get_node(pos) if not has_room_for_node_drops(player, node) then return true end end if minetest.check_player_privs(name, { server = true, protection_bypass = true }) then return false end if state == lzr_gamestate.LEVEL_COMPLETE or state == lzr_gamestate.MENU then return true elseif state == lzr_gamestate.EDITOR then return not lzr_editor.is_in_level_bounds(pos) end return old_is_protected(pos, name) end local flash_jobs = {} minetest.register_on_protection_violation(function(pos, name) local state = lzr_gamestate.get_state() if state ~= lzr_gamestate.EDITOR then local player = minetest.get_player_by_name(name) local node = minetest.get_node(pos) if not has_room_for_node_drops(player, node) then -- If there is already a job running, cancel it if flash_jobs[name] then flash_jobs[name]:cancel() flash_jobs[name] = nil end -- Play warning sound and highlight the hotbar minetest.sound_play({name = "lzr_protection_inventory_full", gain = 0.3}, {to_player=name}, true) lzr_gui.set_hotbar_highlight(player, true) -- Disable flashing after a brief moment local job = minetest.after(HOTBAR_FLASH_TIME, function(player) if player and player:is_player() then lzr_gui.set_hotbar_highlight(player, false) end end, player) -- Remember this 'after' job flash_jobs[name] = job end end end) minetest.register_on_leaveplayer(function(player) local pname = player:get_player_name() if flash_jobs[pname] then flash_jobs[pname]:cancel() flash_jobs[pname] = nil end end)