Page 1 of 1

Water flow push items

PostPosted: Sun Sep 23, 2012 03:40
by jordan4ibanez
I've worked almost 25 hours on this code doing a lot of experiments and such, and this is what i've come up 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
    on_step = function(self, dtime)
       
       
        local p = self.object:getpos()
        local nn = minetest.env:get_node(p).name

       
        if nn == "default:lava_source" or nn == "default:lava_flowing" then
            self.object:remove()
           -- minetest.sound_play("hiss")
        end

        if minetest.registered_nodes[nn].walkable then
            leaniancy = 0.3
            negative_lean = -0.3
            blockx = math.floor(p.x+0.5)
            blockz = math.floor(p.z+0.5)
            blocky = math.floor(p.y+0.5)
            --test x inside of block
            if p.x - blockx >= leaniancy then
                setx = blockx + 0.7
            end
            if p.x - blockx <= negative_lean then
                setx = blockx - 0.7
            end
            if p.x - blockx < leaniancy and p.x - blockx > negative_lean then
                setx = blockx
            end
            --test z inside of block
            if p.z - blockz >= leaniancy then
                setz = blockz + 0.7
            end
            if p.z - blockz <= negative_lean then
                setz = blockz - 0.7
            end
            if p.z - blockz < leaniancy and p.z - blockz > negative_lean then
                setz = blockz
            end
            --if setz and sety is the same as the block position, push the blocks up, otherwise don't change y
            if setz == blockz and setx == blockx then
                sety = blocky + 0.7
            end
            if setz ~= blockz or setx ~= blockx then
                sety = blocky
            end
            self.object:setacceleration({x=0,y=0,z=0})
            self.object:setvelocity({x=0,y=0,z=0})
            self.object:setpos({x=setx,y=sety,z=setz})
           
        end
       
        --BEGINNING OF MASSIVE FLOW TEST
       
        --X + 1
        local node_param2 = minetest.env:get_node(p).param2
       
        local check_below = {x=p.x, y=p.y - 1, z=p.z}
       
        local see_if_solid_below = minetest.env:get_node(check_below).name
       
        --print(see_if_solid_below)
       
        local in_front_x = {x=p.x + 1, y=p.y, z=p.z}
       
        local next_to_x = {x=p.x + 0.35, y=p.y, z=p.z}
       
        local test_if_less_x = minetest.env:get_node(in_front_x).param2
       
        local see_if_water_x = minetest.env:get_node(in_front_x).name
       
        local check_to_stop_x = minetest.env:get_node(next_to_x).name
       
        --if the flowing water block's param2 is lower than the current one, set the acceleration for +x
        if nn == "default:water_flowing" and test_if_less_x < node_param2 then
            if nn == "default:water_flowing" and see_if_water_x == "default:water_flowing" then
                self.object:setacceleration({x=1,y=0,z=0})
            end
        end
       
        --if the item is inside of flowing water then check if there is a solid block in front of it or if it is in air, check if tehre is more air below it
        if check_to_stop_x ~= "default:water_flowing" and nn == "default:water_flowing" or check_to_stop_x == "air" and see_if_solid_below == "air" then
            self.object:setacceleration({x=0,y=-10,z=0})
        end



        -- If node is not registered or node is walkably solid and stop it from stopping flowing items
        noder = minetest.env:get_node(p).name
        p.y = p.y - 0.3
        local nn = minetest.env:get_node(p).name
        if not minetest.registered_nodes[nn] or minetest.registered_nodes[nn].walkable and noder ~= "default:water_flowing" then
            if self.physical_state then
                print("stopping")
                self.object:setvelocity({x=0, y=0, z=0})
                self.object:setacceleration({x=0, y=0, z=0})
                self.physical_state = false
                self.object:set_properties({
                    physical = false
                })
            end
        else
            if not self.physical_state then
                self.object:setvelocity({x=0,y=0,z=0})
                self.object:setacceleration({x=0, y=-10, z=0})
                self.physical_state = true
                self.object:set_properties({
                    physical = true
                })
            end
        end
    end,


There are a few bugs:
  • There is no checking if the node next to it is walkable when pushing the items out of blocks, so if the item pusher pushes it into another block, it will keep passing them back in forth (EXAMPLE) instead should just push them +1 on the y axis
  • This actually only goes + on the X axis right now, but it works sort of well so far
  • If you throw an item directly on the edge of a walkable node, then it will just slide across it (EXAMPLE)

Idea: Water source makes items float

CODERS! i need your help! we can finally have flowing water pushing items around in minetest!

PostPosted: Sun Sep 23, 2012 06:05
by sfan5
+777

PostPosted: Sun Sep 23, 2012 06:41
by Topywo
jordan4ibanez wrote:There are a few bugs:

There is no checking if the node next to it is walkable when pushing the items out of blocks, so if the item pusher pushes it into another block, it will keep passing them back in forth


This bug may offer some decoration possibilities.

PostPosted: Sun Sep 23, 2012 09:16
by PilzAdam
jordan4ibanez wrote:CODERS! i need your help! we can finally have flowing water pushing items around in minetest!

I will see if i can get it to work.

PostPosted: Sun Sep 23, 2012 10:25
by PilzAdam
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
    on_step = function(self, dtime)
        local p = self.object:getpos()
       
        local name = minetest.env:get_node(p).name
        if name == "default:lava_flowing" or name == "default:lava_source" then
            self.object:remove()
            return
        end
       
        if name == "default:water_flowing" then
            get_flowing_dir = function(self)
                local pos = self.object:getpos()
                local param2 = minetest.env:get_node(pos).param2
                for i,d in ipairs({-1, 1, -1, 1}) do
                    if i<3 then
                        pos.x = pos.x+d
                    else
                        pos.z = pos.z+d
                    end
                   
                    local name = minetest.env:get_node(pos).name
                    local par2 = minetest.env:get_node(pos).param2
                    if name == "default:water_flowing" and par2 < param2 then
                        return pos
                    end
                   
                    if i<3 then
                        pos.x = pos.x-d
                    else
                        pos.z = pos.z-d
                    end
                end
            end
           
            local vec = get_flowing_dir(self)
            if vec and vec.x-p.x > 0 then
                self.object:setvelocity({x=1,y=0,z=0})
                self.object:setacceleration({x=0, y=-10, z=0})
                self.physical_state = true
                self.object:set_properties({
                    physical = true
                })
                return
            elseif vec and vec.x-p.x < 0 then
                self.object:setvelocity({x=-1,y=0,z=0})
                self.object:setacceleration({x=0, y=-10, z=0})
                self.physical_state = true
                self.object:set_properties({
                    physical = true
                })
                return
            elseif vec and vec.z-p.z > 0 then
                self.object:setvelocity({x=0,y=0,z=1})
                self.object:setacceleration({x=0, y=-10, z=0})
                self.physical_state = true
                self.object:set_properties({
                    physical = true
                })
                return
            elseif vec and vec.z-p.z < 0 then
                self.object:setvelocity({x=0,y=0,z=-1})
                self.object:setacceleration({x=0, y=-10, z=0})
                self.physical_state = true
                self.object:set_properties({
                    physical = true
                })
                return
            end
        end
       
        p.y = p.y - 0.3
        local nn = minetest.env:get_node(p).name
        -- If node is not registered or node is walkably solid
        if not minetest.registered_nodes[nn] or minetest.registered_nodes[nn].walkable then
            if self.physical_state then
                self.object:setvelocity({x=0,y=0,z=0})
                self.object:setacceleration({x=0, y=0, z=0})
                self.physical_state = false
                self.object:set_properties({
                    physical = false
                })
            end
        else
            if not self.physical_state then
                self.object:setvelocity({x=0,y=0,z=0})
                self.object:setacceleration({x=0, y=-10, z=0})
                self.physical_state = true
                self.object:set_properties({
                    physical = true
                })
            end
        end
    end,

This works quite well.

PostPosted: Sun Sep 23, 2012 12:16
by rubenwardy
cool! that was very quick!

EDIT: there is an error: line 93: unexpected symbol near '<eof>'

get rid of the ',' on the last line


EDIT: is this supposed to go in the defualt mod? you failed to specify ANY install instructions

EDIT: it replaces the on_step near line 85 in builtin/items_entity.lua

PostPosted: Sun Sep 23, 2012 12:53
by rubenwardy
It would be cool if a few new groups are defined for this:

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
floaty  //Stays at the top of the water aways
sinky //sinks to the bottom and stops straight away


by default dropped items should float until they stop moving in the water and then sink.
So they get dropped into moving water, carried along until it ends, and then sinks.




Also,
I am not sure about this in minetest,
but in Minecraft, when water runs over rails, ladders, torches, etc it is turned into dropped form.
What do you think?

PostPosted: Sun Sep 23, 2012 14:16
by Mito551
rubenwardy wrote:Also,
I am not sure about this in minetest,
but in Minecraft, when water runs over rails, ladders, torches, etc it is turned into dropped form.
What do you think?


i have implemented this for torches in my dwarves game.

PostPosted: Thu Oct 04, 2012 06:35
by CTMN
Nice idea, so we could have huge boats.

Re: Water flow push items

PostPosted: Thu Oct 02, 2014 01:27
by sloantothebone
Uh what file does this go into?

Re: Water flow push items

PostPosted: Thu Oct 02, 2014 01:29
by Evergreen
sloantothebone wrote:Uh what file does this go into?

Please don't bump old topics.

Re: Water flow push items

PostPosted: Thu Oct 02, 2014 18:15
by Krock
sloantothebone wrote:Uh what file does this go into?

There's a mod for it: viewtopic.php?t=3188