diff --git a/peoplecantplant/init.lua b/peoplecantplant/init.lua index 7b7d82e..d787f5c 100644 --- a/peoplecantplant/init.lua +++ b/peoplecantplant/init.lua @@ -1,13 +1,8 @@ --- peoplecantplant - Plant saplings when touching the ground --- Contains code fragments from builtin/game/item_entity.lua +-- peoplecantplant - Plant saplings when they touch the ground -- Function that gets called when the builtin item stops -function builtin_item_stopped(self, pos_below, node) - if minetest.get_item_group(node.name, "soil") == 0 then - return -- Not soil - end - +function builtin_item_stopped(self) local stack = ItemStack(self.itemstring) if stack:get_count() > 1 then return -- Obviously dropped by someone (more than 1 item on the stack) @@ -18,82 +13,54 @@ function builtin_item_stopped(self, pos_below, node) return -- It is not a sapling end - if minetest.is_protected(pos_below, ":nobody") then + local pos = vector.round(self.object:get_pos()) + local pos_below = vector.new(pos) + pos_below.y = pos_below.y - 1 + + if minetest.is_protected(pos, ":nobody") then return -- The area is protected by someone end + local node_below = minetest.get_node(pos_below) + if minetest.get_item_group(node_below.name, "soil") == 0 then + return -- Not soil + end + if minetest.find_node_near(pos_below, 3, {"group:sapling", "group:tree"}) then return -- There's another tree around, prevent jungle end - -- Using 'pos = pos_below' would not allow us to modify the tables seperately, - -- thus make a copy of it with vector.new - local pos = vector.new(pos_below) - pos.y = pos.y + 1 - - if minetest.get_node(pos).name ~= "air" then + local node = minetest.get_node(pos).name + -- Get node definition to decide whether to replace or not + -- fallback to empty table when it's an unknown node + local nodedef = minetest.registered_nodes[node] or {} + if not nodedef.buildable_to then return end minetest.set_node(pos, {name = item}) self.itemstring = "" self.object:remove() - return true -- Success! end --- Lifespan of an entity, default it to 900 on fail -local time_to_live = tonumber(minetest.setting_get("item_entity_ttl")) or 900 - -- Overwrite "on_step" in the entity that's used for dropped items -minetest.registered_entities["__builtin:item"].on_step = function(self, dtime) - self.age = self.age + dtime - if time_to_live > 0 and self.age > time_to_live then - -- Item expired, remove it - self.itemstring = "" - self.object:remove() - return +local entity_def = minetest.registered_entities["__builtin:item"] +local old_step = entity_def.on_step +entity_def.on_step = function(self, dtime) + local old_acc = self.object:get_acceleration() + old_step(self, dtime) + + if self.itemstring == "" then + return -- Item removed + end + if vector.equals(old_acc, {x=0, y=0, z=0}) then + return -- No motion change end - local p = self.object:getpos() - p.y = p.y - 0.5 - local node = minetest.get_node(p) - local def = minetest.registered_nodes[node.name] - -- Ignore is walkable, so let it stop until the stuff below loaded - local entity_fall = (def and not def.walkable) - - if self.physical_state == entity_fall then - return -- State didn't change, don't do anything + -- Acceleration defines in this case whether it's moving or not + local new_acc = self.object:get_acceleration() + if vector.equals(new_acc, {x=0, y=0, z=0}) then + -- Not moving: Try to place on node below + builtin_item_stopped(self) end - - -- Different to previous state - resetting the velocity doesn't hurt anything - self.object:setvelocity({x=0, y=0, z=0}) - if entity_fall then - -- Entity is falling: downwards acceleration of earth - self.object:setacceleration({x=0, y=-9.81, z=0}) - else - -- Entity stopped, call our magic planting function - local success = builtin_item_stopped(self, vector.round(p), node) - if success then - return -- The entity doesn't exist anymore when our function was successful - end - - -- Code from the original __builtin:item, get surrounding objects - local own_stack = ItemStack(self.itemstring) - for _, object in ipairs(minetest.get_objects_inside_radius(p, 0.8)) do - local obj = object:get_luaentity() - if obj and obj.name == "__builtin:item" - and obj.physical_state == false then - -- Try to merge the items around with this one - if self:try_merge_with(own_stack, object, obj) then - return -- Item was removed/replaced - end - end - end - self.object:setacceleration({x=0, y=0, z=0}) - end - - self.physical_state = entity_fall - self.object:set_properties({ - physical = entity_fall - }) end \ No newline at end of file