Improved can usage
authorZefram <zefram@fysh.org>
Sun, 20 Jul 2014 23:22:47 +0000 (00:22 +0100)
committerZefram <zefram@fysh.org>
Wed, 23 Jul 2014 19:21:59 +0000 (20:21 +0100)
Make the use of cans more like the digging and placement of ordinary
nodes, and specifically make it much closer to the use of buckets.
The main change is that left-click with a can is now only used to take
liquid; placing liquid is now done with a right-click.  This makes the use
of cans a lot less error-prone, compared to the old scheme of determining
the operation based on the type of node pointed to.  Other changes are
that liquid placement is now permitted to replace any buildable_to node,
and the cans obey node protection.

technic/tools/cans.lua

index f46a401a326ad52ce3c8d8d23521eb5a9376b6b9..f12ec93e6c73408b1d06e621b60aa2d3aac4ae44 100644 (file)
@@ -12,6 +12,14 @@ local function set_can_wear(itemstack, level, max_level)
        itemstack:set_wear(temp)
 end
 
+local function get_can_level(itemstack)
+       if itemstack:get_metadata() == "" then
+               return 0
+       else
+               return tonumber(itemstack:get_metadata())
+       end
+end
+
 function technic.register_can(d)
        local data = {}
        for k, v in pairs(d) do data[k] = v end
@@ -22,46 +30,44 @@ function technic.register_can(d)
                wear_represents = "content_level",
                liquids_pointable = true,
                on_use = function(itemstack, user, pointed_thing)
-                       if pointed_thing.type ~= "node" then
+                       if pointed_thing.type ~= "node" then return end
+                       local node = minetest.get_node(pointed_thing.under)
+                       if node.name ~= data.liquid_source_name then return end
+                       local charge = get_can_level(itemstack)
+                       if charge == data.can_capacity then return end
+                       if minetest.is_protected(pointed_thing.under, user:get_player_name()) then
+                               minetest.log("action", user:get_player_name().." tried to take "..node.name.." at protected position "..minetest.pos_to_string(pointed_thing.under).." with a "..data.can_name)
                                return
                        end
-                       node = minetest.get_node(pointed_thing.under)
-
-                       local charge = nil
-                       if itemstack:get_metadata() == "" then
-                               charge = 0
-                       else
-                               charge = tonumber(itemstack:get_metadata())
+                       minetest.remove_node(pointed_thing.under)
+                       charge = charge + 1
+                       itemstack:set_metadata(tostring(charge))
+                       set_can_wear(itemstack, charge, data.can_capacity)
+                       return itemstack
+               end,
+               on_place = function(itemstack, user, pointed_thing)
+                       if pointed_thing.type ~= "node" then return end
+                       local pos = pointed_thing.under
+                       local def = minetest.registered_nodes[minetest.get_node(pos).name] or {}
+                       if def.on_rightclick and user and not user:get_player_control().sneak then
+                               return def.on_rightclick(pos, minetest.get_node(pos), user, itemstack, pointed_thing)
                        end
-                       if node.name == data.liquid_source_name then
-                               if charge < data.can_capacity then
-                                       minetest.remove_node(pointed_thing.under)
-                                       charge = charge + 1
-                                       itemstack:set_metadata(tostring(charge))
-                                       set_can_wear(itemstack, charge, data.can_capacity)
-                               end
-                               return itemstack
+                       if not def.buildable_to then
+                               pos = pointed_thing.above
+                               def = minetest.registered_nodes[minetest.get_node(pos).name] or {}
+                               if not def.buildable_to then return end
                        end
-                       if charge == 0 then
+                       local charge = get_can_level(itemstack)
+                       if charge == 0 then return end
+                       if minetest.is_protected(pos, user:get_player_name()) then
+                               minetest.log("action", user:get_player_name().." tried to place "..data.liquid_source_name.." at protected position "..minetest.pos_to_string(pos).." with a "..data.can_name)
                                return
                        end
-
-                       if node.name == data.liquid_flowing_name then
-                               minetest.set_node(pointed_thing.under, {name=data.liquid_source_name})
-                               charge = charge - 1
-                               itemstack:set_metadata(tostring(charge))
-                               set_can_wear(itemstack, charge, data.can_capacity)
-                               return itemstack
-                       end
-
-                       node = minetest.get_node(pointed_thing.above)
-                       if node.name == "air" then
-                               minetest.set_node(pointed_thing.above, {name=data.liquid_source_name})
-                               charge = charge - 1
-                               itemstack:set_metadata(tostring(charge))
-                               set_can_wear(itemstack, charge, data.can_capacity)
-                               return itemstack
-                       end             
+                       minetest.set_node(pos, {name=data.liquid_source_name})
+                       charge = charge - 1
+                       itemstack:set_metadata(tostring(charge))
+                       set_can_wear(itemstack, charge, data.can_capacity)
+                       return itemstack
                end,
                on_refill = function(stack)
                        stack:set_metadata(tostring(data.can_capacity))