diff --git a/README.md b/README.md index 22418f1..8f0a658 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Minetest Sponge mod ## Water-removing sponges for Minetest. -Created by Benjie/fiftysix/56 2018-08-27 - Last updated 2023-02-20 +Created by Benjie/fiftysix/56 2018-08-27 - Last updated 2023-02-21 Copyright Benjie 2018-2023 [Forum topic](https://forum.minetest.net/viewtopic.php?f=9&t=20729) @@ -13,12 +13,14 @@ They will hold the water away until they are removed. This will cause them to become soggy, so to use them again they have to be cooked. ### How it works: -* Sponges create a 9x9x9 cube of air-like nodes that water can't flow through (checks for protection). +* Sponges create a diameter 9 sphere of air-like nodes that water can't flow through (checks for protection). * If sponges have cleared more than 3 nodes of liquid, they become soggy sponges. -* Removing a sponge or soggy sponge will turn a 9x9x9 cube of air-like nodes back into air, as long as they are not in the area of another sponge. +* Removing a sponge or soggy sponge will turn a diameter 9 sphere of air-like nodes back into air, as long as they are not in the area of another sponge. *(Air-like nodes can be removed in protection by removing a sponge outside the protection, they are not meant to be permanent)* ### Options: +The mod should be most enjoyable by leaving all options at their default values. + **Replace air nodes** (sponge_replace_air_nodes): boolean, default true Causes sponges not to replace air with water blocking airlike nodes. Disabling this may cause unusual behaviour with flowing water. @@ -29,3 +31,13 @@ See "Group list type" (sponge_group_list_type) for the behaviour of this list. **Group list type** (sponge_group_list_type): multi-choice, default whitelist_source If the groups in the group list should be treated as a whitelist or blacklist for removing liquids. The *_source variants will remove all flowing liquids regardless of the list. + +**Radius** (sponge_radius): number, default 4.5 +Radius of the sphere or cube of liquid that gets removed. + +**Sphere shape** (sponge_shape_sphere): boolean, default true +Whether to use a sphere shape to remove liquids. + +**Replace with air** (sponge_replace_with_air): boolean, default false +Replace liquids with air instead of liquid blocking nodes. +This causes water to flow back immediately after placing the sponge. diff --git a/init.lua b/init.lua index 3641dff..3925284 100644 --- a/init.lua +++ b/init.lua @@ -1,30 +1,31 @@ --[[ - Minetest Sponge mod - Water removing sponges for Minetest - - Created by Benjie/fiftysix/56 2018-08-27 - Last updated 2023-02-20 + - Created by Benjie/fiftysix/56 2018-08-27 - Last updated 2023-02-21 - Copyright Benjie 2018-2023 Soggy sponges can rarely be found deep in the sea where the darkness begins. -These can be cooked into dry sponges, and then placed near a liquid to remove the surrounding cube of it +These can be cooked into dry sponges, and then placed near a liquid to remove the surrounding sphere of it They will hold the water away until they are removed. This will cause them to become soggy, so to use them again they have to be cooked. -Sponges create a 9x9x9 cube of air-like nodes that water can't flow through (checks for protection) +Sponges create a diameter 9 sphere of air-like nodes that water can't flow through (checks for protection) If sponges have cleared more than 3 nodes of liquid, they become soggy sponges -removing a sponge or soggy sponge will turn a 9x9x9 cube of air-like nodes back into air +removing a sponge or soggy sponge will turn a diameter 9 sphere of air-like nodes back into air (air-like nodes can be removed in protection by removing a sponge outside the protection, they are not meant to be permanent) ]]-- local modname = minetest.get_current_modname() -local area = 4 -- The "radius" (of the cube) to clear water local keep_dry = 3 -- The maximum amount of water cleared where the sponge doesn't turn soggy - -- Load configurable options local replace_air_nodes = minetest.settings:get_bool("sponge_replace_air_nodes", true) local group_list = minetest.settings:get("sponge_group_list", false) or "water" local group_list_type = minetest.settings:get("sponge_group_list_type") or "whitelist_source" +local radius = tonumber(minetest.settings:get("sponge_radius") or 4.5) +local shape_sphere = minetest.settings:get_bool("sponge_shape_sphere", true) +local replace_with_air = minetest.settings:get_bool("sponge_replace_with_air", false) -- returns true if groups contains anything in list local compare_groups = function(list, groups) @@ -39,10 +40,15 @@ end -- called by after_destruct() local destruct = function(pos) -- removing the air-like nodes + -- if air was used, there is nothing to remove + if replace_with_air then return end + + local edge_distance = math.floor(radius) - -- find all sponges that intersect with this sponge's area + -- find all sponges that intersect with this sponge's radius local sponge_info = minetest.find_nodes_in_area( - {x=pos.x-area*2, y=pos.y-area*2, z=pos.z-area*2}, {x=pos.x+area*2, y=pos.y+area*2, z=pos.z+area*2}, + vector.new(pos.x-edge_distance*2, pos.y-edge_distance*2, pos.z-edge_distance*2), + vector.new(pos.x+edge_distance*2, pos.y+edge_distance*2, pos.z+edge_distance*2), {modname..":soggy_sponge", modname..":sponge"}, true ) local sponges = {} @@ -53,23 +59,31 @@ local destruct = function(pos) -- removing the air-like nodes end end - for x = pos.x-area, pos.x+area do - for y = pos.y-area, pos.y+area do - for z = pos.z-area, pos.z+area do - local n = minetest.get_node({x=x, y=y, z=z}).name - if n == modname..":liquid_stop" then - - -- check if position intersects with another sponge - local intersect = false - for _, s_pos in pairs(sponges) do - if math.abs(s_pos.x-x) <= area and math.abs(s_pos.y-y) <= area and math.abs(s_pos.z-z) <= area then - intersect = true - break + for x = pos.x-edge_distance, pos.x+edge_distance do + for y = pos.y-edge_distance, pos.y+edge_distance do + for z = pos.z-edge_distance, pos.z+edge_distance do + local p = vector.new(x, y, z) + if (not shape_sphere or p:distance(pos) <= radius) then + local n = minetest.get_node(p).name + if n == modname..":liquid_stop" then + + -- check if position intersects with another sponge + local intersect = false + for _, s_pos in pairs(sponges) do + if ( + (shape_sphere and p:distance(s_pos) <= radius) or + (not shape_sphere and + math.abs(s_pos.x-x) <= radius and math.abs(s_pos.y-y) <= radius and math.abs(s_pos.z-z) <= radius) + ) then + + intersect = true + break + end + end + + if not intersect then + minetest.remove_node(p) end - end - - if not intersect then - minetest.remove_node({x=x, y=y, z=z}) end end end @@ -84,49 +98,57 @@ local construct = function(pos, placer, itemstack, pointed_thing) if not minetest.is_protected(pos, playername) then local count = 0 - for x = pos.x-area, pos.x+area do - for y = pos.y-area, pos.y+area do - for z = pos.z-area, pos.z+area do - local p = {x=x, y=y, z=z} - - local n = minetest.get_node(p).name - local def = minetest.registered_nodes[n] - local replace = false - if def == nil or minetest.is_protected(p, playername) then - -- replace = false - elseif replace_air_nodes and n == "air" then - replace = true - elseif def["drawtype"] == "flowingliquid" then - if group_list_type == "whitelist" then - if compare_groups(group_list, def.groups or {}) then - replace = true - end - elseif group_list_type == "blacklist" then - if not compare_groups(group_list, def.groups or {}) then - replace = true - end - else - replace = true - end - elseif def["drawtype"] == "liquid" then - if group_list_type == "whitelist" or group_list_type == "whitelist_source" then - if compare_groups(group_list, def.groups or {}) then - replace = true - end - elseif group_list_type == "blacklist" or group_list_type == "blacklist_source" then - if not compare_groups(group_list, def.groups or {}) then - replace = true - end - else - replace = true - end - end + local edge_distance = math.floor(radius) + for x = pos.x-edge_distance, pos.x+edge_distance do + for y = pos.y-edge_distance, pos.y+edge_distance do + for z = pos.z-edge_distance, pos.z+edge_distance do + local p = vector.new(x, y, z) - if replace then - if n ~= "air" then - count = count + 1 -- counting liquids + if (not shape_sphere or p:distance(pos) <= radius) then + + local n = minetest.get_node(p).name + local def = minetest.registered_nodes[n] + local replace = false + if def == nil or minetest.is_protected(p, playername) then + -- replace = false + elseif replace_air_nodes and n == "air" then + replace = true + elseif def["drawtype"] == "flowingliquid" then + if group_list_type == "whitelist" then + if compare_groups(group_list, def.groups or {}) then + replace = true + end + elseif group_list_type == "blacklist" then + if not compare_groups(group_list, def.groups or {}) then + replace = true + end + else + replace = true + end + elseif def["drawtype"] == "liquid" then + if group_list_type == "whitelist" or group_list_type == "whitelist_source" then + if compare_groups(group_list, def.groups or {}) then + replace = true + end + elseif group_list_type == "blacklist" or group_list_type == "blacklist_source" then + if not compare_groups(group_list, def.groups or {}) then + replace = true + end + else + replace = true + end + end + + if replace then + if n ~= "air" then + count = count + 1 -- counting liquids + end + if replace_with_air then + minetest.remove_node(p) + else + minetest.set_node(p, {name=modname..":liquid_stop"}) + end end - minetest.set_node(p, {name=modname..":liquid_stop"}) end end end @@ -138,19 +160,22 @@ local construct = function(pos, placer, itemstack, pointed_thing) end end - -minetest.register_node(modname..":liquid_stop", { -- air-like node - description = "liquid blocker for sponges", - drawtype = "airlike", - drop = {max_items=0, items={}}, - groups = {not_in_creative_inventory=1}, - pointable = false, - walkable = false, - floodable = false, - sunlight_propagates = true, - paramtype = "light", - buildable_to = true, -}) +if replace_with_air then + minetest.register_alias(modname..":liquid_stop", "air") +else + minetest.register_node(modname..":liquid_stop", { -- air-like node + description = "liquid blocker for sponges", + drawtype = "airlike", + drop = {max_items=0, items={}}, + groups = {not_in_creative_inventory=1}, + pointable = false, + walkable = false, + floodable = false, + sunlight_propagates = true, + paramtype = "light", + buildable_to = true, + }) +end minetest.register_node(modname..":sponge", { -- dry sponge diff --git a/settingtypes.txt b/settingtypes.txt index 40d9192..1525970 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -8,3 +8,13 @@ sponge_group_list (Group list) string water # If the groups in the group list should be treated as a whitelist or blacklist for removing liquids. # The *_source variants will remove all flowing liquids regardless of the list. sponge_group_list_type (Group list type) enum whitelist_source whitelist,whitelist_source,blacklist,blacklist_source,ignored + +# Radius of sphere or cube of liquid that gets removed +sponge_radius (Radius) float 4.5 1 39.9 + +# Whether to use a sphere shape to remove liquids +sponge_shape_sphere (Sphere shape) bool true + +# Replace liquids with air instead of liquid blocking nodes. +# This causes water to flow back immediately after placing the sponge +sponge_replace_with_air (Replace with air) bool false