Page 1 of 1

minetest.env:get_node issue

PostPosted: Thu Apr 25, 2013 20:57
by Jonathan
Since I have not been able to solve this, I have not been able to finish my map http://forum.minetest.net/viewtopic.php?id=5723.

Here is the code I'm having an issue with:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
local timer = 0
minetest.register_globalstep(function(dtime)
    timer = timer + dtime;
    --Place bombs around every 20 seconds.
    if timer >= 20 then
        timer = 0
        if math.random(0,11) >= 0.5 then
            minetest.chat_send_all("Bombs Away!")
        else
            minetest.chat_send_all("Look Out!")
        end
        local playerlist = minetest.get_connected_players()
        --Bomb every player in map.
        for _,player in ipairs(playerlist) do
            local tpos = player:getpos()
--            local testpos = player:getpos()

            --Check each block within a radius of 15 blocks of the player.
            for dx=-15,15 do
                for dz=-15,15 do
                    for dy=15,-15,-1 do
                        tpos.x = tpos.x+dx
                        tpos.y = tpos.y+dy
                        tpos.z = tpos.z+dz
                        --Around a 10% chance of placing tnt in valid node.
                        if math.random(0,100) > 90 then
                            local check = true
                             local setpos = {x = tpos.x, y = tpos.y - 6, z = tpos.z}
                             
                            --Checking if valid node.
                            if minetest.env:get_node({x = tpos.x, y = tpos.y - 7, z = tpos.z}).name ~= "air" and minetest.env:get_node(tpos).name == "air" then
--                                For testing purposes only:
--                                minetest.env:set_node({x = testpos.x, y = testpos.y + 7, z = testpos.z}, {name = "tnt:tnt"})
--                                minetest.env:punch_node({x = testpos.x, y = testpos.y + 7, z = testpos.z})
                               
                                for t=1,6,1 do
                                    if minetest.env:get_node({x = tpos.x, y = tpos.y - t, z = tpos.z}).name ~= "air" then
                                        check = false
                                    end
                                end

                                --If valid node... bombs away!!!
                                if check == true then
                                    minetest.env:set_node(setpos, {name = "tnt:tnt"})
                                    minetest.env:punch_node(setpos)
                                end
                            end
                        end
                    end       
                end
            end
        end
    end
end)


The problem is with the minetest.env:get_node(...).name functions. When I check a radius like 15 it almost always returns "ignore" whereas if I check only a radius of 2 it seems to work fine almost all the time, and will identify even more blocks than checking a range of 15! I'm not sure what is going on.

PostPosted: Fri Apr 26, 2013 04:13
by prestidigitator
First off, the bigger you make you radius, the more likely you are to run into a block of nodes that has not been created via map generation and/or loaded from the database. Second, notice that you are setting 'tpos' relative to itself instead of relative to one fixed starting point. This means you will, for example, execute this line:

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
tpos.x = tpos.x+dx


31 times, with offsets from the original player position of {-15, -29, -42, -54, -65, -75, -84, -92, -99, -105, -110, -114, -117, -119, -120, -120, -119, -117, -114, -110, -105, -99, -92, -84, -75, -65, -54, -42, -29, -15, 0}. With an offset of 120 in each direction from the player's original location, it shouldn't be surprising that you'll find an unloaded/ungenerated map block.

PostPosted: Fri Apr 26, 2013 05:07
by sfan5
If minetest.env:get_node(...).name is "ignore" that means the world is not loaded at that place.

PostPosted: Fri Apr 26, 2013 12:18
by Jonathan
prestidigitator wrote:First off, the bigger you make you radius, the more likely you are to run into a block of nodes that has not been created via map generation and/or loaded from the database. Second, notice that you are setting 'tpos' relative to itself instead of relative to one fixed starting point. This means you will, for example, execute this line:

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
tpos.x = tpos.x+dx


31 times, with offsets from the original player position of {-15, -29, -42, -54, -65, -75, -84, -92, -99, -105, -110, -114, -117, -119, -120, -120, -119, -117, -114, -110, -105, -99, -92, -84, -75, -65, -54, -42, -29, -15, 0}. With an offset of 120 in each direction from the player's original location, it shouldn't be surprising that you'll find an unloaded/ungenerated map block.


Thank you very much for pointing that out :). I did not realize I had set it up incorrectly. I was wanting to have it set up to check the same distance in every direction (In this case 15 nodes in every direction from the player). So I think it should look more like:

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
for dx=-15,15 do
    tpos.x = tpos.x+dx
    for dz=-15,15 do
        tpos.z = tpos.z+dz
        for dy=15,-15,-1 do
            tpos.y = tpos.y+dy



sfan5 wrote:If minetest.env:get_node(...).name is "ignore" that means the world is not loaded at that place.


Do you know by chance how far out from the player the world is loaded?

By the way thank you guys for the help.

PostPosted: Fri Apr 26, 2013 13:00
by Jonathan
Jonathan wrote:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
for dx=-15,15 do
    tpos.x = tpos.x+dx
    for dz=-15,15 do
        tpos.z = tpos.z+dz
        for dy=15,-15,-1 do
            tpos.y = tpos.y+dy



LOL, that is not right either. I am going to have to think about this one for a little while.

By the way, after you saw the mistakes I made, if I ever want to modify the minetest engine, no one should probably let me lol :P.

PostPosted: Fri Apr 26, 2013 13:29
by Nore
No, it should be something like:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
local npos = {}
for dx=-15,15 do
    npos.x = tpos.x+dx
    for dz=-15,15 do
        npos.z = tpos.z+dz
        for dy=15,-15,-1 do
            npos.y = tpos.y+dy

and use npos instead of tpos in your code

PostPosted: Fri Apr 26, 2013 13:34
by Jonathan
Ok I figured out how to do it:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
        for _,player in ipairs(playerlist) do
            local spos = player:getpos()

            --Check each block within a radius of 10 blocks of the player.
            for dx=-10,10 do
                for dz=-10,10 do
                    for dy=10,-10,-1 do
                        local tpos = {x = spos.x + dx, y = spos.y + dy, z = spos.z + dz}


Thanks again for the help :) I have a couple more things to tweak, and modify the map some. Then I should be done!

PostPosted: Fri Apr 26, 2013 13:37
by Jonathan
Nore wrote:No, it should be something like:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
local npos = {}
for dx=-15,15 do
    npos.x = tpos.x+dx
    for dz=-15,15 do
        npos.z = tpos.z+dz
        for dy=15,-15,-1 do
            npos.y = tpos.y+dy

and use npos instead of tpos in your code


Thanks for the suggestion, I saw it right after I posted my solution :)

PostPosted: Fri Apr 26, 2013 13:50
by PilzAdam
sfan5 wrote:If minetest.env:get_node(...).name is "ignore" that means the world is not loaded at that place.

Try using minetest.env:get_node_or_nil(pos), it returns nil instead of CONTENT_IGNORE when the area is not loaded. You can catch it then.

PostPosted: Fri Apr 26, 2013 14:02
by Jonathan
PilzAdam wrote:
sfan5 wrote:If minetest.env:get_node(...).name is "ignore" that means the world is not loaded at that place.

Try using minetest.env:get_node_or_nil(pos), it returns nil instead of CONTENT_IGNORE when the area is not loaded. You can catch it then.


The TNT is now placed like I want it to, all the "ignores" I was getting was due to me setting up the nested "for" loops incorrectly lol. Besides, I am not sure how to "catch it" in lua (I am not the best progammer).