1
0
mirror of https://github.com/DonBatman/mysponge.git synced 2026-01-08 18:15:42 +01:00

Complete rewrite

This commit is contained in:
DonBatman
2026-01-04 11:32:22 -08:00
parent 9cdc8e9001
commit 2c4f592b22
5 changed files with 261 additions and 177 deletions

View File

@@ -1,13 +1,59 @@
Mysponge
Advanced Sponges for Luanti
Soak up water with this sponge.
A focused liquid management mod that introduces a high-utility sponge for clearing water, featuring immersive visual effects and unique environmental interactions.
Put the wet sponge in the furnace and get water.
Features
Leave the sponge sit out and it will dry.
Core Utility: A single, reliable sponge type designed specifically for efficient water management.
Dynamic States: Transitions between Dry, Moist, and Saturated states based on usage.
Code Licence - MIT
Media Licence - CC0
Atmospheric Effects:
Forum - https://forum.minetest.net/viewtopic.php?f=9&t=11539
Dripping: Saturated sponges placed on ceilings or walls will drip water particles.
Steam: Smelting sponges in a furnace produces steam particles.
Advanced Mechanics:
Leaf Drying: Punching leaf nodes with a dry sponge instantly dries them out, perfect for clearing dense foliage.
Manual Squeezing: Shift-click a saturated sponge with an empty bucket to reclaim water manually.
Liquid Blocking: Temporarily places "air" nodes to prevent immediate liquid backflow while clearing.
The Sponge
The primary tool for clearing flood zones and managing water levels in your builds.
Absorption Radius: 4 nodes.
Crafting: Uses standard wool and basic materials for accessibility.
Usage Guide
Clearing Water
Place a Dry Sponge near or inside water. It will instantly absorb all liquid within its 4-node radius and transition to a Saturated state.
Drying the Sponge
Saturated sponges must be dried before they can be used again:
Smelting: Place a Saturated Sponge in a furnace. This produces a Dry Sponge.
Squeezing: Hold an Empty Bucket and Shift + Right-Click a placed Saturated Sponge to empty it instantly and reclaim the water.
Environmental Interaction
Forestry: Use a Dry Sponge to "punch" leaf nodes. The leaves will turn into "Dry Leaves," allowing for quick clearing of jungles or forests.
Decor: Features a unique nodebox design that allows it to look like an industrial filter or a heavy-duty cleaning tool when placed.
Technical Details
Dependencies: default, wool
Engine Version: Compatible with Luanti 5.0.0+
Performance: Optimized node manipulation logic to ensure server stability during water clearing.

View File

@@ -1 +0,0 @@
Soak up water with a sponge.

373
init.lua
View File

@@ -1,199 +1,238 @@
local mysponge_table = { -- item, ,desc, image, scale, nodegroup, bright
{"sponge_dry", "Dry Sponge", "mysponge_sponge.png", "0.5", {dig_immediate=1, oddly_breakable_by_hand=1, flammable=1}},
{"sponge_moist", "Moist Sponge", "mysponge_sponge2.png", "0.7", {dig_immediate=1, oddly_breakable_by_hand=1, not_in_creative_inventory=1}},
{"sponge_wet", "Wet Sponge", "mysponge_sponge3.png", "1", {dig_immediate=1, oddly_breakable_by_hand=1, not_in_creative_inventory=1 }},
{"sponge_soaked","Soaked Sponge", "mysponge_sponge3.png", "1", {dig_immediate=1, oddly_breakable_by_hand=1, not_in_creative_inventory=1}},
local modname = minetest.get_current_modname()
local mysponge_table = {
{"sponge_dry", "Dry Sponge", "mysponge_sponge.png", 0.5, {dig_immediate=2, flammable=1}, 3},
{"sponge_moist", "Moist Sponge", "mysponge_sponge2.png", 0.7, {dig_immediate=2, not_in_creative_inventory=1}, 2},
{"sponge_wet", "Wet Sponge", "mysponge_sponge3.png", 0.85, {dig_immediate=2, not_in_creative_inventory=1}, 1},
{"sponge_soaked", "Soaked Sponge", "mysponge_sponge3.png", 1.0, {dig_immediate=2, not_in_creative_inventory=1}, 0},
}
for i in ipairs(mysponge_table) do
local item = mysponge_table[i][1]
local desc = mysponge_table[i][2]
local image = mysponge_table[i][3]
local scale = mysponge_table[i][4]
local nodegroup = mysponge_table[i][5]
local function absorb_water(pos, current_item)
local radius = 0
for _, data in ipairs(mysponge_table) do
if data[1] == current_item then
radius = data[6]
break
end
end
minetest.register_node("mysponge:"..item,{
description = desc,
tiles = {image},
drawtype = "nodebox",
visual_scale = scale,
paramtype = "light",
groups = nodegroup,
node_box = {
type = "fixed",
fixed = {
{-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
}
if radius <= 0 and current_item ~= "sponge_soaked" then radius = 0 end
if current_item == "sponge_soaked" then return false end
local adjacent_min = {x = pos.x - 1, y = pos.y - 1, z = pos.z - 1}
local adjacent_max = {x = pos.x + 1, y = pos.y + 1, z = pos.z + 1}
local trigger_nodes = minetest.find_nodes_in_area(adjacent_min, adjacent_max, {"group:water"})
if #trigger_nodes > 0 then
local soak_min = {x = pos.x - radius, y = pos.y - radius, z = pos.z - radius}
local soak_max = {x = pos.x + radius, y = pos.y + radius, z = pos.z + radius}
local all_water = minetest.find_nodes_in_area(soak_min, soak_max, {"group:water"})
for _, wpos in ipairs(all_water) do
minetest.set_node(wpos, {name = "mysponge:air1"})
end
minetest.set_node(pos, {name = "mysponge:sponge_soaked"})
minetest.sound_play("default_water_footstep", {pos = pos, gain = 0.5})
return true
end
return false
end
for _, data in ipairs(mysponge_table) do
local item, desc, image, scale, nodegroup = unpack(data)
local half_width = scale / 2
local height_top = -0.5 + scale
minetest.register_node(modname .. ":" .. item, {
description = desc,
tiles = {image},
drawtype = "nodebox",
paramtype = "light",
groups = nodegroup,
node_box = {
type = "fixed",
fixed = {-half_width, -0.5, -half_width, half_width, height_top, half_width},
},
selection_box = {
type = "fixed",
fixed = {
{-0.25, -0.25, -0.25, 0.25, 0.25, 0.25},
}
}
})
selection_box = {
type = "fixed",
fixed = {-half_width, -0.5, -half_width, half_width, height_top, half_width},
},
after_place_node = function(pos, placer, itemstack, pointed_thing)
absorb_water(pos, item)
end,
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
if itemstack:get_name() == "bucket:bucket_empty" and node.name ~= modname .. ":sponge_dry" then
local inv = clicker:get_inventory()
local leftover = inv:add_item("main", "bucket:bucket_water")
if not leftover:is_empty() then
minetest.add_item(clicker:get_pos(), leftover)
end
itemstack:take_item()
minetest.add_particlespawner({
amount = 20,
time = 0.1,
minpos = {x=pos.x-0.2, y=pos.y, z=pos.z-0.2},
maxpos = {x=pos.x+0.2, y=pos.y+0.2, z=pos.z+0.2},
minvel = {x=-3, y=1, z=-3}, maxvel = {x=3, y=4, z=3},
minacc = {x=0, y=-9.8, z=0}, maxacc = {x=0, y=-9.8, z=0},
minexptime = 0.4, maxexptime = 0.8,
minsize = 1, maxsize = 3,
texture = "mysponge_drop.png",
})
minetest.set_node(pos, {name = modname .. ":sponge_dry"})
minetest.sound_play("default_water_footstep", {pos = pos, gain = 0.8})
return itemstack
end
end,
})
end
local air_nodes = {
{"air1"},
{"air2"},
{"air3"},
}
for i in ipairs(air_nodes) do
local airnode = air_nodes[i][1]
minetest.register_node("mysponge:"..airnode,{
description = "Air",
inventory_image = "unknown_node.png",
tiles = {"mysponge_air.png"},
drawtype = "allfaces",
walkable = false,
pointable = false,
paramtype = "light",
drop = "",
groups = {not_in_creative_inventory=1}
minetest.register_abm({
label = "Sponge Particles",
nodenames = {modname .. ":sponge_soaked", modname .. ":sponge_wet", modname .. ":sponge_moist"},
interval = 1.0,
chance = 1,
action = function(pos, node)
if node.name == modname .. ":sponge_soaked" or node.name == modname .. ":sponge_wet" then
local below = {x=pos.x, y=pos.y-1, z=pos.z}
local b_node = minetest.get_node(below)
local def = minetest.registered_nodes[b_node.name]
if def and (not def.walkable or b_node.name == "air") then
minetest.add_particlespawner({
amount = 3,
time = 1,
minpos = {x = pos.x - 0.3, y = pos.y - 0.45, z = pos.z - 0.3},
maxpos = {x = pos.x + 0.3, y = pos.y - 0.5, z = pos.z + 0.3},
minvel = {x = 0, y = -1, z = 0},
maxvel = {x = 0, y = -2, z = 0},
minacc = {x = 0, y = -9.8, z = 0},
maxacc = {x = 0, y = -9.8, z = 0},
minexptime = 1, maxexptime = 2,
minsize = 1.5, maxsize = 2.5,
texture = "mysponge_drop.png",
vertical = true,
})
end
elseif node.name == modname .. ":sponge_moist" then
minetest.add_particlespawner({
amount = 2,
time = 1,
minpos = {x = pos.x - 0.2, y = pos.y + 0.1, z = pos.z - 0.2},
maxpos = {x = pos.x + 0.2, y = pos.y + 0.4, z = pos.z + 0.2},
minvel = {x = -0.1, y = 0.1, z = -0.1},
maxvel = {x = 0.1, y = 0.3, z = 0.1},
minexptime = 1.5, maxexptime = 2.5,
minsize = 1, maxsize = 2,
texture = "mysponge_drop.png^[opacity:80",
})
end
end,
})
local air_nodes = {"air1", "air2", "air3"}
for i, airnode in ipairs(air_nodes) do
local next_node = air_nodes[i+1] and (modname .. ":" .. air_nodes[i+1]) or "air"
minetest.register_node(modname .. ":" .. airnode, {
description = "Air",
drawtype = "airlike",
walkable = false,
pointable = false,
buildable_to = true,
paramtype = "light",
sunlight_propagates = true,
groups = {not_in_creative_inventory = 1},
on_construct = function(pos)
minetest.get_node_timer(pos):start(0.5)
end,
on_timer = function(pos)
minetest.set_node(pos, {name = next_node})
end,
})
end
minetest.register_node("mysponge:dry_leaves",{
minetest.register_node(modname .. ":dry_leaves", {
description = "Dry Leaves",
tiles = {"mysponge_dry_leaves.png"},
drawtype = "allfaces_optional",
paramtype = "light",
groups = {dig_immediate=1, oddly_breakable_by_hand=1}
groups = {dig_immediate = 2, oddly_breakable_by_hand = 1, leaves = 1},
})
-------------------------------------------------------------------------
--ABMs
-------------------------------------------------------------------------
--Set Air
--Air 1
minetest.register_abm({
nodenames = {"group:water"},
neighbors = {"mysponge:sponge_dry"},
interval = 0.2,
chance = 1,
action = function(pos)
minetest.set_node(pos, {name="mysponge:air1"})
end
label = "Sponge Leaf Drying",
nodenames = {"group:leaves"},
neighbors = {modname .. ":sponge_dry"},
interval = 5.0,
chance = 2,
action = function(pos, node)
local below = {x=pos.x, y=pos.y-1, z=pos.z}
local b_node = minetest.get_node(below)
if b_node.name == modname .. ":sponge_dry" and node.name ~= modname .. ":dry_leaves" then
minetest.set_node(pos, {name = modname .. ":dry_leaves"})
minetest.set_node(below, {name = modname .. ":sponge_moist"})
minetest.sound_play("default_dry_grass_footstep", {pos = pos, gain = 0.5})
end
end,
})
--Air 2
minetest.register_abm({
nodenames = {"group:water"},
neighbors = {"mysponge:air1"},
interval = 0.2,
chance = 1,
action = function(pos)
minetest.set_node(pos, {name="mysponge:air2"})
end
})
--Air 3
minetest.register_abm({
nodenames = {"group:water"},
neighbors = {"mysponge:air2"},
interval = 0.2,
chance = 1,
action = function(pos)
minetest.set_node(pos, {name="mysponge:air3"})
end
})
-------------------------------------------------------------------------
--Set default Air
-------------------------------------------------------------------------
minetest.register_abm({
nodenames = {"mysponge:air1","mysponge:air2","mysponge:air3"},
interval = 4,
chance = 1,
action = function(pos)
minetest.set_node(pos, {name="air"})
end
})
-------------------------------------------------------------------------
--Set Sponge
-------------------------------------------------------------------------
minetest.register_abm({
nodenames = {"mysponge:sponge_dry"},
label = "Sponge Water Absorption",
nodenames = {modname .. ":sponge_dry", modname .. ":sponge_moist", modname .. ":sponge_wet"},
neighbors = {"group:water"},
interval = 1,
interval = 1.0,
chance = 1,
action = function(pos)
minetest.set_node(pos, {name="mysponge:sponge_soaked"})
end
})
------------------------------------------------------------------------------------------------
--Shrink Sponge in Air
------------------------------------------------------------------------------------------------
minetest.register_abm({
nodenames = {"mysponge:sponge_soaked"},
neighbors = {"air"},
interval = 60,
chance = 1,
action = function(pos)
minetest.set_node(pos, {name="mysponge:sponge_wet"})
end,
})
minetest.register_abm({
nodenames = {"mysponge:sponge_wet"},
neighbors = {"air"},
interval = 60,
chance = 1,
action = function(pos)
minetest.set_node(pos, {name="mysponge:sponge_moist"})
end,
})
minetest.register_abm({
nodenames = {"mysponge:sponge_moist"},
neighbors = {"air"},
interval = 60,
chance = 1,
action = function(pos)
minetest.set_node(pos, {name="mysponge:sponge_dry"})
action = function(pos, node)
local item_name = node.name:split(":")[2]
absorb_water(pos, item_name)
end,
})
local drying_chain = {
[modname .. ":sponge_soaked"] = modname .. ":sponge_wet",
[modname .. ":sponge_wet"] = modname .. ":sponge_moist",
[modname .. ":sponge_moist"] = modname .. ":sponge_dry",
}
-------------------------------------------------------------------------------------------------
--Craft
minetest.register_abm({
label = "Sponge Drying",
nodenames = {modname .. ":sponge_soaked", modname .. ":sponge_wet", modname .. ":sponge_moist"},
neighbors = {"air"},
interval = 45,
chance = 1,
action = function(pos, node)
local next_stage = drying_chain[node.name]
if next_stage then
minetest.set_node(pos, {name = next_stage})
end
end,
})
minetest.register_craft({
local function register_sponge_drying(input_item, water_yield)
minetest.register_craft({
type = "cooking",
output = "default:water_source 3",
recipe = "mysponge:sponge_soaked",
output = "default:water_source " .. tostring(water_yield),
recipe = input_item,
cooktime = 5,
replacements = {{"mysponge:sponge_soaked", "mysponge:sponge_dry"}},
})
minetest.register_craft({
type = "cooking",
output = "default:water_source 2",
recipe = "mysponge:sponge_wet",
cooktime = 5,
replacements = {{"mysponge:sponge_wet", "mysponge:sponge_dry"}},
})
minetest.register_craft({
type = "cooking",
output = "mysponge:dry_leaves",
recipe = "group:leaves",
cooktime = 3,
})
minetest.register_craft({
output = "mysponge:sponge_dry 1",
recipe = {
{"default:mese_crystal_fragment","mysponge:dry_leaves","default:mese_crystal_fragment"},
{"mysponge:dry_leaves","default:mese_crystal_fragment","mysponge:dry_leaves"},
{"default:mese_crystal_fragment","mysponge:dry_leaves","default:mese_crystal_fragment"},
},
cooktime = 3,
replacements = {{input_item, modname .. ":sponge_dry"}},
})
end
register_sponge_drying(modname .. ":sponge_soaked", 3)
register_sponge_drying(modname .. ":sponge_wet", 2)
register_sponge_drying(modname .. ":sponge_moist", 1)
minetest.register_craft({
output = modname .. ":sponge_dry 1",
recipe = {
{"farming:string", "wool:yellow", "farming:string"},
{"wool:yellow", "default:mese_crystal_fragment", "wool:yellow"},
{"farming:string", "wool:yellow", "farming:string"},
},
})

View File

@@ -1,5 +1,5 @@
name = mysponge
description = A sponge that soaks up water
depends = default
author = Don Michaud
depends = default, wool
author = Don
title = My Sponge

BIN
textures/mysponge_drop.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 B