diff --git a/builtin/builtin.lua b/builtin/builtin.lua index a17841fc8..f2811fa9c 100644 --- a/builtin/builtin.lua +++ b/builtin/builtin.lua @@ -22,4 +22,5 @@ dofile(minetest.get_modpath("__builtin").."/auth.lua") dofile(minetest.get_modpath("__builtin").."/chatcommands.lua") dofile(minetest.get_modpath("__builtin").."/static_spawn.lua") dofile(minetest.get_modpath("__builtin").."/detached_inventory.lua") +dofile(minetest.get_modpath("__builtin").."/falling.lua") diff --git a/builtin/falling.lua b/builtin/falling.lua new file mode 100644 index 000000000..82b360152 --- /dev/null +++ b/builtin/falling.lua @@ -0,0 +1,141 @@ +-- Minetest: builtin/item.lua + +-- +-- Falling nodes +-- + + +-- +-- Falling stuff +-- + +minetest.register_entity("__builtin:falling_node", { + initial_properties = { + physical = true, + collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5}, + visual = "wielditem", + textures = {}, + visual_size = {x=0.667, y=0.667}, + }, + + nodename = "", + + set_node = function(self, nodename) + self.nodename = nodename + local stack = ItemStack(nodename) + local itemtable = stack:to_table() + local itemname = nil + if itemtable then + itemname = stack:to_table().name + end + local item_texture = nil + local item_type = "" + if minetest.registered_items[itemname] then + item_texture = minetest.registered_items[itemname].inventory_image + item_type = minetest.registered_items[itemname].type + end + prop = { + is_visible = true, + textures = {nodename}, + } + self.object:set_properties(prop) + end, + + get_staticdata = function(self) + return self.nodename + end, + + on_activate = function(self, staticdata) + self.nodename = staticdata + self.object:set_armor_groups({immortal=1}) + --self.object:setacceleration({x=0, y=-10, z=0}) + self:set_node(self.nodename) + end, + + on_step = function(self, dtime) + -- Set gravity + self.object:setacceleration({x=0, y=-10, z=0}) + -- Turn to actual sand when collides to ground or just move + local pos = self.object:getpos() + local bcp = {x=pos.x, y=pos.y-0.7, z=pos.z} -- Position of bottom center point + local bcn = minetest.env:get_node(bcp) + -- Note: walkable is in the node definition, not in item groups + if minetest.registered_nodes[bcn.name] and + minetest.registered_nodes[bcn.name].walkable then + local np = {x=bcp.x, y=bcp.y+1, z=bcp.z} + -- Check what's here + local n2 = minetest.env:get_node(np) + -- If it's not air or liquid, remove node and replace it with + -- it's drops + if n2.name ~= "air" and (not minetest.registered_nodes[n2.name] or + minetest.registered_nodes[n2.name].liquidtype == "none") then + local drops = minetest.get_node_drops(n2.name, "") + minetest.env:remove_node(np) + -- Add dropped items + local _, dropped_item + for _, dropped_item in ipairs(drops) do + minetest.env:add_item(np, dropped_item) + end + -- Run script hook + local _, callback + for _, callback in ipairs(minetest.registered_on_dignodes) do + callback(np, n2, nil) + end + end + -- Create node and remove entity + minetest.env:add_node(np, {name=self.nodename}) + self.object:remove() + else + -- Do nothing + end + end +}) + +function spawn_falling_node(p, nodename) + obj = minetest.env:add_entity(p, "__builtin:falling_node") + obj:get_luaentity():set_node(nodename) +end + +-- +-- Some common functions +-- + +function nodeupdate_single(p) + n = minetest.env:get_node(p) + if minetest.get_node_group(n.name, "falling_node") ~= 0 then + p_bottom = {x=p.x, y=p.y-1, z=p.z} + n_bottom = minetest.env:get_node(p_bottom) + -- Note: walkable is in the node definition, not in item groups + if minetest.registered_nodes[n_bottom.name] and + not minetest.registered_nodes[n_bottom.name].walkable then + minetest.env:remove_node(p) + spawn_falling_node(p, n.name) + nodeupdate(p) + end + end +end + +function nodeupdate(p) + for x = -1,1 do + for y = -1,1 do + for z = -1,1 do + p2 = {x=p.x+x, y=p.y+y, z=p.z+z} + nodeupdate_single(p2) + end + end + end +end + +-- +-- Global callbacks +-- + +function on_placenode(p, node) + nodeupdate(p) +end +minetest.register_on_placenode(on_placenode) + +function on_dignode(p, node) + nodeupdate(p) +end +minetest.register_on_dignode(on_dignode) diff --git a/games/minimal/mods/default/init.lua b/games/minimal/mods/default/init.lua index 176fe899b..cf2805843 100644 --- a/games/minimal/mods/default/init.lua +++ b/games/minimal/mods/default/init.lua @@ -769,7 +769,7 @@ minetest.register_node("default:sand", { description = "Sand", tiles ={"default_sand.png"}, is_ground_content = true, - groups = {crumbly=3}, + groups = {crumbly=3, falling_node=1}, sounds = default.node_sound_sand_defaults(), }) @@ -777,7 +777,7 @@ minetest.register_node("default:gravel", { description = "Gravel", tiles ={"default_gravel.png"}, is_ground_content = true, - groups = {crumbly=2}, + groups = {crumbly=2, falling_node=1}, sounds = default.node_sound_dirt_defaults({ footstep = {name="default_gravel_footstep", gain=0.45}, }), @@ -1586,73 +1586,6 @@ minetest.register_alias("mapgen_stone_with_coal", "default:stone_with_coal") minetest.register_alias("mapgen_stone_with_iron", "default:stone_with_iron") minetest.register_alias("mapgen_mese", "default:mese") --- --- Some common functions --- - -default.falling_node_names = {} - -function nodeupdate_single(p) - n = minetest.env:get_node(p) - if default.falling_node_names[n.name] ~= nil then - p_bottom = {x=p.x, y=p.y-1, z=p.z} - n_bottom = minetest.env:get_node(p_bottom) - if n_bottom.name == "air" then - minetest.env:remove_node(p) - minetest.env:add_entity(p, "default:falling_"..n.name) - nodeupdate(p) - end - end -end - -function nodeupdate(p) - for x = -1,1 do - for y = -1,1 do - for z = -1,1 do - p2 = {x=p.x+x, y=p.y+y, z=p.z+z} - nodeupdate_single(p2) - end - end - end -end - --- --- Falling stuff --- - -function default.register_falling_node(nodename, texture) - default.falling_node_names[nodename] = true - -- Override naming conventions for stuff like :default:falling_default:sand - minetest.register_entity(":default:falling_"..nodename, { - -- Static definition - physical = true, - collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5}, - visual = "cube", - textures = {texture,texture,texture,texture,texture,texture}, - -- State - -- Methods - on_step = function(self, dtime) - -- Set gravity - self.object:setacceleration({x=0, y=-10, z=0}) - -- Turn to actual sand when collides to ground or just move - local pos = self.object:getpos() - local bcp = {x=pos.x, y=pos.y-0.7, z=pos.z} -- Position of bottom center point - local bcn = minetest.env:get_node(bcp) - if bcn.name ~= "air" then - -- Turn to a sand node - local np = {x=bcp.x, y=bcp.y+1, z=bcp.z} - minetest.env:add_node(np, {name=nodename}) - self.object:remove() - else - -- Do nothing - end - end - }) -end - -default.register_falling_node("default:sand", "default_sand.png") -default.register_falling_node("default:gravel", "default_gravel.png") - -- -- Global callbacks -- @@ -1665,13 +1598,11 @@ minetest.register_globalstep(on_step) function on_placenode(p, node) --print("on_placenode") - nodeupdate(p) end minetest.register_on_placenode(on_placenode) function on_dignode(p, node) --print("on_dignode") - nodeupdate(p) end minetest.register_on_dignode(on_dignode)