Use AreaStore

master
rubenwardy 2015-08-12 18:02:16 +01:00
parent 38fe40c49c
commit f64ecdf764
2 changed files with 191 additions and 142 deletions

View File

@ -5,3 +5,21 @@ Adds environmental sounds to Minetest
Created by rubenwardy.
License: LGPL 2.1 or later.
# Work in Progress
This project is a Work in Progress
* environment.expand_fill(cid, px, py, pz, max_radius)
* Combines multiple nodes of the same type into a cubic AreaStore entry.
* Good for large surfaces of water.
* TODO:
* Check for collisions with existing stores.
* environment.scan_around_player(name)
* Scans for sound sources and plays them.
* TODO:
* don't just play sounds for the center of an area,
play from edge if outside.
* water sounds should come from surface.
* TODO:
* run environment.expand_fill on mapgen somehow.

315
init.lua
View File

@ -8,6 +8,7 @@
]]
local areas = AreaStore()
environment = {
_nodes = {}
}
@ -48,32 +49,169 @@ function environment.register_node_with_sounds(name, spec)
return environment.register_node(name)
end
minetest.register_node("environment:test",{
--[[minetest.register_node("environment:test", {
tiles = {"default_stone.png"},
sounds = {
presence = {name="small_waterfall"}
}
})
environment.register_node("environment:test")
environment.register_node("environment:test")]]
--[[environment.register_node_with_sounds("default:water_source", {
environment.register_node_with_sounds("default:water_source", {
presence = {name="small_waterfall"}
})]]
})
local SCAN_RANGE = 32
local MAX_SOURCES = 16
function environment.scan_around_player(name)
-- Small Optimisations
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
-- Get player
-- 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)
print("Starting scan...")
-- Get range
local pos = player:getpos()
pos = vector.round(pos)
local px, py, pz = pos.x, pos.y, pos.z
local minp = {
x = pos.x - SCAN_RANGE,
y = pos.y - SCAN_RANGE,
@ -85,142 +223,35 @@ function environment.scan_around_player(name)
z = pos.z + SCAN_RANGE
}
-- 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()
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))]
-- Loop through
local count = 0
local radius = 1
local c2 = 0
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
})
(function()
local function handle_source(def, x, y, z)
print("Adding source to (" .. x .. ", " .. y .. ", " .. z .. ")")
minetest.sound_play(def.presence, {
pos = {x=x, y=y, z=z},
gain = def.presence.gain,
max_hear_distance = SCAN_RANGE
})
if i > 16 then
print("Bigger than 16!")
break
end
-- Check center
--[[local vi = a:index(px, py, pz)
local def = watch_nodes[data[vi] ]
if def then
handle_source(def, px, py, pz)
count = count + 1
end
c2 = c2 + 1]]
print("Scanning from " .. minetest.pos_to_string(pos) .. " with range " .. SCAN_RANGE)
while radius < SCAN_RANGE do
print(" - radius " .. radius)
-- Front and back faces
for x = -radius, radius do
for y = -radius, radius do
local vi = a:index(px + x, py + y, pz + radius)
local def = watch_nodes[data[vi]]
if def then
handle_source(def, px + x, py + y, pz + radius)
count = count + 1
if count >= MAX_SOURCES then
c2 = c2 + 1
return
end
end
local vi = a:index(px + x, py + y, pz - radius)
local def = watch_nodes[data[vi]]
if def then
handle_source(def, px + x, py + y, pz - radius)
count = count + 1
if count >= MAX_SOURCES then
c2 = c2 + 2
return
end
end
c2 = c2 + 1
end
end
-- Left and right
for z = -radius, radius do
for y = -radius, radius do
local vi = a:index(px + radius, py + y, pz + z)
local def = watch_nodes[data[vi]]
if def then
handle_source(def, px + radius, py + y, pz + z)
count = count + 1
if count >= MAX_SOURCES then
c2 = c2 + 1
return
end
end
local vi = a:index(px - radius, py + y, pz + z)
local def = watch_nodes[data[vi]]
if def then
handle_source(def, px - radius, py + y, pz + z)
count = count + 1
if count >= MAX_SOURCES then
c2 = c2 + 2
return
end
end
c2 = c2 + 2
end
end
-- Top and bottom
for x = -radius, radius do
for z = -radius, radius do
local vi = a:index(px + x, py + radius, pz + z)
local def = watch_nodes[data[vi]]
if def then
handle_source(def, px + x, py + radius, pz + z)
count = count + 1
if count >= MAX_SOURCES then
c2 = c2 + 1
return
end
end
local vi = a:index(px + x, py - radius, pz + z)
local def = watch_nodes[data[vi]]
if def then
handle_source(def, px + x, py - radius, pz + z)
count = count + 1
if count >= MAX_SOURCES then
c2 = c2 + 2
return
end
end
c2 = c2 + 2
end
end
radius = radius + 1
end
end)()
print("End of scan. Found " .. count .. " sources out of " .. c2 .. " nodes.")
local err = radius * radius * radius - c2
if err > 0 then
print("Error! Missing " .. err .. " nodes!")
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
})