258 lines
5.4 KiB
Lua
258 lines
5.4 KiB
Lua
--[[
|
|
|
|
# Usecases
|
|
|
|
* Waterfalls, flowing going down 2+ levels
|
|
* Standing water
|
|
* Oceans
|
|
|
|
]]
|
|
|
|
local areas = AreaStore()
|
|
environment = {
|
|
_nodes = {}
|
|
}
|
|
|
|
function environment.register_node(name)
|
|
local def = minetest.registered_nodes[name]
|
|
if not def then
|
|
error("environment.register_node(\"" .. name .. "\") : no such node!")
|
|
elseif not def.sounds then
|
|
error("environment.register_node(\"" .. name .. "\") : no sound table!")
|
|
end
|
|
def.sounds.name = name
|
|
environment._nodes[minetest.get_content_id(name)] = def.sounds
|
|
|
|
print("Environment : added " .. name .. " to watch list")
|
|
end
|
|
|
|
function environment.register_node_with_sounds(name, spec)
|
|
-- Get definition
|
|
local def = minetest.registered_nodes[name]
|
|
if not def then
|
|
error("environment.register_node_with_sounds(" .. name .. ", {}) : no such node!")
|
|
end
|
|
|
|
-- Add sounds
|
|
if def.sounds then
|
|
for key, value in pairs(def.sounds) do
|
|
if not spec[key] then
|
|
spec[key] = value
|
|
end
|
|
end
|
|
end
|
|
minetest.override_item(name, {
|
|
sounds = spec
|
|
})
|
|
|
|
-- Register it
|
|
return environment.register_node(name)
|
|
end
|
|
|
|
--[[minetest.register_node("environment:test", {
|
|
tiles = {"default_stone.png"},
|
|
sounds = {
|
|
presence = {name="small_waterfall"}
|
|
}
|
|
})
|
|
environment.register_node("environment:test")]]
|
|
|
|
environment.register_node_with_sounds("default:water_source", {
|
|
presence = {name="small_waterfall"}
|
|
})
|
|
|
|
local SCAN_RANGE = 32
|
|
local MAX_SOURCES = 16
|
|
function environment.expand_fill(cid, px, py, pz, max_radius)
|
|
print("Scanning from " .. minetest.pos_to_string({
|
|
x=px, y=py, z=pz
|
|
}) .. " looking for ID " .. cid .. " with max_radius " .. max_radius)
|
|
|
|
-- Initiate areas
|
|
local watch_nodes = environment._nodes
|
|
local minp = {
|
|
x = px - max_radius,
|
|
y = py - max_radius,
|
|
z = pz - max_radius
|
|
}
|
|
local maxp = {
|
|
x = px + max_radius,
|
|
y = py + max_radius,
|
|
z = pz + max_radius
|
|
}
|
|
local ax, bx = px, px
|
|
local ay, by = py, py
|
|
local az, bz = pz, pz
|
|
|
|
-- Set up voxel manip
|
|
local vm = minetest.get_voxel_manip()
|
|
minp, maxp = vm:read_from_map(minp, maxp)
|
|
local a = VoxelArea:new{MinEdge = minp, MaxEdge = maxp}
|
|
local data = vm:get_data()
|
|
|
|
-- Expand cuboid
|
|
local c2 = 0, 0
|
|
local function expand()
|
|
local top_fine = true
|
|
local bottom_fine = true
|
|
|
|
-- Front and back faces
|
|
local front_fine = true
|
|
local back_fine = true
|
|
for x = ax, bx do
|
|
for y = ay, by do
|
|
if front_fine then
|
|
local vi = a:index(x, y, az - 1)
|
|
c2 = c2 + 1
|
|
if data[vi] ~= cid then
|
|
front_fine = false
|
|
end
|
|
end
|
|
|
|
if back_fine then
|
|
local vi = a:index(x, y, bz + 1)
|
|
c2 = c2 + 1
|
|
if data[vi] ~= cid then
|
|
back_fine = false
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if front_fine then
|
|
az = az - 1
|
|
--print("Expanded one.z to " .. az)
|
|
end
|
|
if back_fine then
|
|
bz = bz + 1
|
|
--print("Expanded two.z to " .. bz)
|
|
end
|
|
|
|
-- Left and right faces
|
|
local left_fine = true
|
|
local right_fine = true
|
|
for z = az, bz do
|
|
for y = ay, by do
|
|
if left_fine then
|
|
local vi = a:index(ax - 1, y, z)
|
|
c2 = c2 + 1
|
|
if data[vi] ~= cid then
|
|
left_fine = false
|
|
end
|
|
end
|
|
|
|
if right_fine then
|
|
local vi = a:index(bx + 1, y, z)
|
|
c2 = c2 + 1
|
|
if data[vi] ~= cid then
|
|
right_fine = false
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if left_fine then
|
|
ax = ax - 1
|
|
--print("Expanded one.x to " .. ax)
|
|
end
|
|
if right_fine then
|
|
bx = bx + 1
|
|
--print("Expanded two.x to " .. bx)
|
|
end
|
|
|
|
-- Top and bottom faces
|
|
local top_fine = true
|
|
local bottom_fine = true
|
|
for x = az, bz do
|
|
for z = ay, by do
|
|
if top_fine then
|
|
local vi = a:index(x, ay - 1, z)
|
|
c2 = c2 + 1
|
|
if data[vi] ~= cid then
|
|
top_fine = false
|
|
end
|
|
end
|
|
|
|
if bottom_fine then
|
|
local vi = a:index(x, by + 1, z)
|
|
c2 = c2 + 1
|
|
if data[vi] ~= cid then
|
|
bottom_fine = false
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if top_fine then
|
|
ay = ay - 1
|
|
--print("Expanded one.y to " .. ay)
|
|
end
|
|
if bottom_fine then
|
|
by = by + 1
|
|
--print("Expanded two.y to " .. by)
|
|
end
|
|
|
|
return front_fine or back_fine or left_fine or right_fine
|
|
end
|
|
|
|
for i = 1, max_radius do
|
|
--print("- iteration " .. i)
|
|
if not expand() then
|
|
break
|
|
end
|
|
end
|
|
|
|
local a = {x=ax, y=ay, z=az}
|
|
local b = {x=bx, y=by, z=bz}
|
|
print(minetest.pos_to_string(a) .. " to " .. minetest.pos_to_string(b))
|
|
print("Checked " .. c2 .. " nodes.")
|
|
|
|
-- Insert into AreaStore
|
|
areas:insert_area(a, b, cid)
|
|
end
|
|
|
|
function environment.scan_around_player(name)
|
|
local watch_nodes = environment._nodes
|
|
local player = minetest.get_player_by_name(name)
|
|
local pos = player:getpos()
|
|
local minp = {
|
|
x = pos.x - SCAN_RANGE,
|
|
y = pos.y - SCAN_RANGE,
|
|
z = pos.z - SCAN_RANGE
|
|
}
|
|
local maxp = {
|
|
x = pos.x + SCAN_RANGE,
|
|
y = pos.y + SCAN_RANGE,
|
|
z = pos.z + SCAN_RANGE
|
|
}
|
|
|
|
local arealist = areas:get_areas_in_area(minp, maxp, true, true, true)
|
|
for i, area in pairs(arealist) do
|
|
local source = {
|
|
x = (area.min.x + area.max.x) / 2,
|
|
y = (area.min.y + area.max.y) / 2,
|
|
z = (area.min.z + area.max.z) / 2
|
|
}
|
|
local def = watch_nodes[math.floor(tonumber(area.data))]
|
|
|
|
print("Adding source to " .. minetest.pos_to_string(source))
|
|
local handle = minetest.sound_play(def.presence, {
|
|
pos = source,
|
|
gain = def.presence.gain,
|
|
max_hear_distance = SCAN_RANGE
|
|
})
|
|
|
|
if i > 16 then
|
|
print("Bigger than 16!")
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
minetest.register_chatcommand("e", {
|
|
func = function(name)
|
|
environment.expand_fill(minetest.get_content_id("default:water_source"), 0, 0, 0, 20)
|
|
end
|
|
})
|
|
|
|
minetest.register_chatcommand("s", {
|
|
func = environment.scan_around_player
|
|
})
|