mirror of
https://github.com/DonBatman/mysponge.git
synced 2026-01-08 18:15:42 +01:00
Complete rewrite
This commit is contained in:
60
Readme.md
60
Readme.md
@@ -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.
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Soak up water with a sponge.
|
||||
373
init.lua
373
init.lua
@@ -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"},
|
||||
},
|
||||
})
|
||||
|
||||
4
mod.conf
4
mod.conf
@@ -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
BIN
textures/mysponge_drop.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 216 B |
Reference in New Issue
Block a user