Cristiano Magro
2020-10-11 3190d2bb510017613914907ca632cdd325cc51e7
commit | author | age
08b09a 1 -- Configuration
CM 2
3190d2 3 local xnotreetap_max_charge      = 30000 -- Maximum charge of the saw
08b09a 4 -- Gives 2500 nodes on a single charge (about 50 complete normal trees)
3190d2 5 local xnotreetap_charge_per_node = 12
08b09a 6 -- Cut down tree leaves.  Leaf decay may cause slowness on large trees
CM 7 -- if this is disabled.
3190d2 8 local xnotreetap_leaves = true
08b09a 9
CM 10 -- First value is node name; second is whether the node is considered even if chainsaw_leaves is false.
11 local nodes = {
0fb44d 12   -- Rubber trees from moretrees or technic_worldgen if moretrees isn't installed
CM 13   {"moretrees:rubber_tree_trunk_empty", true},
14   {"moretrees:rubber_tree_trunk", true},
15   {"moretrees:rubber_tree_leaves", false},
08b09a 16 }
0fb44d 17
08b09a 18
CM 19 local timber_nodenames = {}
20 for _, node in pairs(nodes) do
0fb44d 21   if chainsaw_leaves or node[2] then
CM 22     timber_nodenames[node[1]] = true
23   end
08b09a 24 end
CM 25
482cb1 26
CM 27 local S = technic.getter
28
08b09a 29 technic.register_power_tool("technic:xnotreetap", xnotreetap_max_charge)
3190d2 30
CM 31 local mesecons_materials = minetest.get_modpath("mesecons_materials")
32
08b09a 33
CM 34 -- This function checks if the specified node should be sawed
35 local function check_if_node_sawed(pos)
0fb44d 36   local node_name = minetest.get_node(pos).name
CM 37   if timber_nodenames[node_name]
38     or (xnotreetap_leaves and minetest.get_item_group(node_name, "leaves") ~= 0)
39     or minetest.get_item_group(node_name, "tree") ~= 0 then
40     return true
41   end
08b09a 42
0fb44d 43   return false
08b09a 44 end
CM 45
46 -- Table for saving what was sawed down
47 local produced = {}
48
49 -- Save the items sawed down so that we can drop them in a nice single stack
50 local function handle_drops(drops)
0fb44d 51   for _, item in ipairs(drops) do
CM 52     local stack = ItemStack(item)
53     local name = stack:get_name()
54     local p = produced[name]
55     if not p then
56       produced[name] = stack
57     else
58       p:set_count(p:get_count() + stack:get_count())
59     end
60   end
08b09a 61 end
CM 62
63 --- Iterator over positions to try to saw around a sawed node.
64 -- This returns positions in a 3x1x3 area around the position, plus the
65 -- position above it.  This does not return the bottom position to prevent
66 -- the chainsaw from cutting down nodes below the cutting position.
67 -- @param pos Sawing position.
68 local function iterSawTries(pos)
0fb44d 69   -- Copy position to prevent mangling it
CM 70   local pos = vector.new(pos)
71   local i = 0
08b09a 72
0fb44d 73   return function()
CM 74     i = i + 1
75     -- Given a (top view) area like so (where 5 is the starting position):
76     -- X -->
77     -- Z 123
78     -- | 456
79     -- V 789
80     -- This will return positions 1, 4, 7, 2, 8 (skip 5), 3, 6, 9,
81     -- and the position above 5.
82     if i == 1 then
83       -- Move to starting position
84       pos.x = pos.x - 1
85       pos.z = pos.z - 1
86     elseif i == 4 or i == 7 then
87       -- Move to next X and back to start of Z when we reach
88       -- the end of a Z line.
89       pos.x = pos.x + 1
90       pos.z = pos.z - 2
91     elseif i == 5 then
92       -- Skip the middle position (we've already run on it)
93       -- and double-increment the counter.
94       pos.z = pos.z + 2
95       i = i + 1
96     elseif i <= 9 then
97       -- Go to next Z.
98       pos.z = pos.z + 1
99     elseif i == 10 then
100       -- Move back to center and up.
101       -- The Y+ position must be last so that we don't dig
102       -- straight upward and not come down (since the Y-
103       -- position isn't checked).
104       pos.x = pos.x - 1
105       pos.z = pos.z - 1
106       pos.y = pos.y + 1
107     else
108       return nil
109     end
110     return pos
111   end
08b09a 112 end
CM 113
114
115
116
117 -- This function does all the hard work. Recursively we dig the node at hand
118 -- if it is in the table and then search the surroundings for more stuff to dig.
119 local function recursive_dig(pos, remaining_charge)
0fb44d 120   if remaining_charge < xnotreetap_charge_per_node then
CM 121     return remaining_charge
122   end
123   local node = minetest.get_node(pos)
08b09a 124
0fb44d 125   if not check_if_node_sawed(pos) then
CM 126     return remaining_charge
127   end
08b09a 128
CM 129
0fb44d 130   if node.name == "moretrees:rubber_tree_trunk" then
CM 131     --raccolta gomma
132     node.name = "moretrees:rubber_tree_trunk_empty"
133     minetest.swap_node(pos, node)
134     minetest.handle_node_drops(pointed_thing.above, {"technic:raw_latex"}, user)
135     remaining_charge = remaining_charge - xnotreetap_charge_per_node
136
137     -- Wood found - cut it
138     handle_drops(minetest.get_node_drops(node.name, ""))
139     minetest.remove_node(pos)
140     remaining_charge = remaining_charge - xnotreetap_charge_per_node
141
142     if not technic.creative_mode then
143       local item_wear = tonumber(itemstack:get_wear())
144       item_wear = item_wear + 819
145       if item_wear > 65535 then
146         itemstack:clear()
147         return itemstack
148       end
149       itemstack:set_wear(item_wear)
150     end
151   end
152
153   -- Check surroundings and run recursively if any charge left
154   for npos in iterSawTries(pos) do
155     if remaining_charge < xnotreetap_charge_per_node then
156       break
157     end
158     if check_if_node_sawed(npos) then
159       remaining_charge = recursive_dig(npos, remaining_charge)
160     else
161       minetest.check_for_falling(npos)
162     end
163   end
164   return remaining_charge
08b09a 165 end
CM 166
167 -- Function to randomize positions for new node drops
168 local function get_drop_pos(pos)
0fb44d 169   local drop_pos = {}
08b09a 170
0fb44d 171   for i = 0, 8 do
CM 172     -- Randomize position for a new drop
173     drop_pos.x = pos.x + math.random(-3, 3)
174     drop_pos.y = pos.y - 1
175     drop_pos.z = pos.z + math.random(-3, 3)
08b09a 176
0fb44d 177     -- Move the randomized position upwards until
CM 178     -- the node is air or unloaded.
179     for y = drop_pos.y, drop_pos.y + 5 do
180       drop_pos.y = y
181       local node = minetest.get_node_or_nil(drop_pos)
08b09a 182
0fb44d 183       if not node then
CM 184         -- If the node is not loaded yet simply drop
185         -- the item at the original digging position.
186         return pos
187       elseif node.name == "air" then
188         -- Add variation to the entity drop position,
189         -- but don't let drops get too close to the edge
190         drop_pos.x = drop_pos.x + (math.random() * 0.8) - 0.5
191         drop_pos.z = drop_pos.z + (math.random() * 0.8) - 0.5
192         return drop_pos
193       end
194     end
195   end
08b09a 196
0fb44d 197   -- Return the original position if this takes too long
CM 198   return pos
08b09a 199 end
CM 200
201 -- Chainsaw entry point
202 local function xnotreetap_dig(pos, current_charge)
0fb44d 203   -- Start sawing things down
CM 204   local remaining_charge = recursive_dig(pos, current_charge)
205   minetest.sound_play("chainsaw", {pos = pos, gain = 1.0,
206     max_hear_distance = 10})
08b09a 207
0fb44d 208   -- Now drop items for the player
CM 209   for name, stack in pairs(produced) do
210     -- Drop stacks of stack max or less
211     local count, max = stack:get_count(), stack:get_stack_max()
212     stack:set_count(max)
213     while count > max do
214       minetest.add_item(get_drop_pos(pos), stack)
215       count = count - max
216     end
217     stack:set_count(count)
218     minetest.add_item(get_drop_pos(pos), stack)
219   end
08b09a 220
0fb44d 221   -- Clean up
CM 222   produced = {}
08b09a 223
0fb44d 224   return remaining_charge
08b09a 225 end
CM 226
482cb1 227 minetest.register_tool("technic:xnotreetap", {
0fb44d 228   description = S("Xno Tree Tap"),
CM 229   inventory_image = "technic_tree_tap.png",
3190d2 230
0fb44d 231   stack_max = 1,
3190d2 232   
0fb44d 233   wear_represents = "technic_RE_charge",
CM 234   on_refill = technic.refill_RE_charge,
3190d2 235
0fb44d 236   on_use = function(itemstack, user, pointed_thing)
CM 237     if pointed_thing.type ~= "node" then
238       return itemstack
239     end
08b09a 240
0fb44d 241     --check tool charge
CM 242     local meta = minetest.deserialize(itemstack:get_metadata())
243     if not meta or not meta.charge or
244       meta.charge < xnotreetap_charge_per_node then
245       return
246     end
08b09a 247
0fb44d 248     --check node protection
CM 249     local pos = pointed_thing.under
250     if minetest.is_protected(pos, user:get_player_name()) then
251       minetest.record_protection_violation(pos, user:get_player_name())
252       return
253     end
08b09a 254
CM 255
0fb44d 256     --can collect only from rubber
CM 257     local node = minetest.get_node(pos)
258     local node_name = node.name
259     if node_name ~= "moretrees:rubber_tree_trunk" then
260       return
261     end
08b09a 262
0fb44d 263     --raccolta gomma
CM 264     --        node.name = "moretrees:rubber_tree_trunk_empty"
265     --        minetest.swap_node(pos, node)
266     --        minetest.handle_node_drops(pointed_thing.above, {"technic:raw_latex"}, user)
267     --
268     --        if not technic.creative_mode then
269     --            local item_wear = tonumber(itemstack:get_wear())
270     --            item_wear = item_wear + 819
271     --            if item_wear > 65535 then
272     --                itemstack:clear()
273     --                return itemstack
274     --            end
275     --            itemstack:set_wear(item_wear)
276     --        end
277     --        return itemstack
08b09a 278
0fb44d 279     -- Send current charge to digging function so that the
CM 280     -- chainsaw will stop after digging a number of nodes
281     meta.charge = xnotreetap_dig(pointed_thing.under, meta.charge)
282     if not technic.creative_mode then
283       technic.set_RE_wear(itemstack, meta.charge, xnotreetap_max_charge)
284       itemstack:set_metadata(minetest.serialize(meta))
285     end
286     return itemstack
08b09a 287
0fb44d 288   end,
482cb1 289 })
CM 290
291 minetest.register_craft({
0fb44d 292   output = "technic:xnotreetap",
CM 293   recipe = {
294     {"pipeworks:tube_1", "group:wood",    "default:stick"},
295     {"technic:battery",  "default:stick", "default:stick"},
296     {"technic:battery",  "default:stick", "default:stick"},
297   },
482cb1 298 })
CM 299
3190d2 300 --minetest.register_abm({
CM 301 --  label = "Tools: xno tree tap",
302 --  nodenames = {"moretrees:rubber_tree_trunk_empty"},
303 --  interval = 60,
304 --  chance = 15,
305 --  action = function(pos, node)
306 --    if minetest.find_node_near(pos, (moretrees and moretrees.leafdecay_radius) or 5, {"moretrees:rubber_tree_leaves"}) then
307 --      node.name = "moretrees:rubber_tree_trunk"
308 --      minetest.swap_node(pos, node)
309 --    end
310 --  end
311 --})
482cb1 312
08b09a 313
CM 314
315
316
317