auouymous
2021-02-06 0f7810e53895f5742ab577559584539e6533a0dc
commit | author | age
8e03d7 1 -- Configuration
R 2
9019eb 3 local chainsaw_max_charge      = 30000 -- Maximum charge of the saw
S 4 -- Gives 2500 nodes on a single charge (about 50 complete normal trees)
5 local chainsaw_charge_per_node = 12
6 -- Cut down tree leaves.  Leaf decay may cause slowness on large trees
7 -- if this is disabled.
8 local chainsaw_leaves = true
9
e66bb2 10 -- First value is node name; second is whether the node is considered even if chainsaw_leaves is false.
C 11 local nodes = {
12     -- The default trees
13     {"default:acacia_tree", true},
14     {"default:aspen_tree", true},
15     {"default:jungletree", true},
16     {"default:papyrus", true},
17     {"default:cactus", true},
18     {"default:tree", true},
19     {"default:apple", true},
20     {"default:pine_tree", true},
21     {"default:acacia_leaves", false},
22     {"default:aspen_leaves", false},
23     {"default:leaves", false},
24     {"default:jungleleaves", false},
25     {"default:pine_needles", false},
26
31a052 27     -- The default bushes
D 28     {"default:acacia_bush_stem", true},
29     {"default:bush_stem", true},
30     {"default:pine_bush_stem", true},
31     {"default:acacia_bush_leaves", false},
32     {"default:blueberry_bush_leaves", false},
33     {"default:blueberry_bush_leaves_with_berries", false},
34     {"default:bush_leaves", false},
35     {"default:pine_bush_needles", false},
36
e66bb2 37     -- Rubber trees from moretrees or technic_worldgen if moretrees isn't installed
C 38     {"moretrees:rubber_tree_trunk_empty", true},
39     {"moretrees:rubber_tree_trunk", true},
40     {"moretrees:rubber_tree_leaves", false},
41
31a052 42     -- Support moretrees (trunk)
e66bb2 43     {"moretrees:acacia_trunk", true},
C 44     {"moretrees:apple_tree_trunk", true},
45     {"moretrees:beech_trunk", true},
46     {"moretrees:birch_trunk", true},
31a052 47     {"moretrees:cedar_trunk", true},
D 48     {"moretrees:date_palm_ffruit_trunk", true},
49     {"moretrees:date_palm_fruit_trunk", true},
50     {"moretrees:date_palm_mfruit_trunk", true},
51     {"moretrees:date_palm_trunk", true},
e66bb2 52     {"moretrees:fir_trunk", true},
31a052 53     {"moretrees:jungletree_trunk", true},
e66bb2 54     {"moretrees:oak_trunk", true},
C 55     {"moretrees:palm_trunk", true},
31a052 56     {"moretrees:palm_fruit_trunk", true},
D 57     {"moretrees:palm_fruit_trunk_gen", true},
e66bb2 58     {"moretrees:pine_trunk", true},
31a052 59     {"moretrees:poplar_trunk", true},
e66bb2 60     {"moretrees:sequoia_trunk", true},
C 61     {"moretrees:spruce_trunk", true},
62     {"moretrees:willow_trunk", true},
31a052 63     -- Support moretrees (leaves)
e66bb2 64     {"moretrees:acacia_leaves", false},
C 65     {"moretrees:apple_tree_leaves", false},
31a052 66     {"moretrees:beech_leaves", false},
D 67     {"moretrees:birch_leaves", false},
68     {"moretrees:cedar_leaves", false},
69     {"moretrees:date_palm_leaves", false},
e66bb2 70     {"moretrees:fir_leaves", false},
C 71     {"moretrees:fir_leaves_bright", false},
72     {"moretrees:jungletree_leaves_green", false},
73     {"moretrees:jungletree_leaves_yellow", false},
74     {"moretrees:jungletree_leaves_red", false},
31a052 75     {"moretrees:oak_leaves", false},
D 76     {"moretrees:palm_leaves", false},
e66bb2 77     {"moretrees:poplar_leaves", false},
31a052 78     {"moretrees:pine_leaves", false},
D 79     {"moretrees:sequoia_leaves", false},
80     {"moretrees:spruce_leaves", false},
81     {"moretrees:willow_leaves", false},
82     -- Support moretrees (fruit)
83     {"moretrees:acorn", false},
84     {"moretrees:apple_blossoms", false},
85     {"moretrees:cedar_cone", false},
86     {"moretrees:coconut", false},
87     {"moretrees:coconut_0", false},
88     {"moretrees:coconut_1", false},
89     {"moretrees:coconut_2", false},
90     {"moretrees:coconut_3", false},
91     {"moretrees:dates_f0", false},
92     {"moretrees:dates_f1", false},
93     {"moretrees:dates_f2", false},
94     {"moretrees:dates_f3", false},
95     {"moretrees:dates_f4", false},
96     {"moretrees:dates_fn", false},
97     {"moretrees:dates_m0", false},
98     {"moretrees:dates_n", false},
99     {"moretrees:fir_cone", false},
100     {"moretrees:pine_cone", false},
101     {"moretrees:spruce_cone", false},
e66bb2 102
C 103     -- Support growing_trees
104     {"growing_trees:trunk", true},
105     {"growing_trees:medium_trunk", true},
106     {"growing_trees:big_trunk", true},
107     {"growing_trees:trunk_top", true},
108     {"growing_trees:trunk_sprout", true},
109     {"growing_trees:branch_sprout", true},
110     {"growing_trees:branch", true},
111     {"growing_trees:branch_xmzm", true},
112     {"growing_trees:branch_xpzm", true},
113     {"growing_trees:branch_xmzp", true},
114     {"growing_trees:branch_xpzp", true},
115     {"growing_trees:branch_zz", true},
116     {"growing_trees:branch_xx", true},
117     {"growing_trees:leaves", false},
118
119     -- Support cool_trees
120     {"bamboo:trunk", true},
121     {"bamboo:leaves", false},
122     {"birch:trunk", true},
123     {"birch:leaves", false},
124     {"cherrytree:trunk", true},
125     {"cherrytree:blossom_leaves", false},
126     {"cherrytree:leaves", false},
127     {"chestnuttree:trunk", true},
128     {"chestnuttree:leaves", false},
129     {"clementinetree:trunk", true},
130     {"clementinetree:leaves", false},
131     {"ebony:trunk", true},
132     {"ebony:creeper", false},
133     {"ebony:creeper_leaves", false},
134     {"ebony:leaves", false},
135     {"jacaranda:trunk", true},
136     {"jacaranda:blossom_leaves", false},
137     {"larch:trunk", true},
138     {"larch:leaves", false},
139     {"lemontree:trunk", true},
140     {"lemontree:leaves", false},
141     {"mahogany:trunk", true},
142     {"mahogany:leaves", false},
143     {"palm:trunk", true},
144     {"palm:leaves", false},
145
146     -- Support growing_cactus
147     {"growing_cactus:sprout", true},
148     {"growing_cactus:branch_sprout_vertical", true},
149     {"growing_cactus:branch_sprout_vertical_fixed", true},
150     {"growing_cactus:branch_sprout_xp", true},
151     {"growing_cactus:branch_sprout_xm", true},
152     {"growing_cactus:branch_sprout_zp", true},
153     {"growing_cactus:branch_sprout_zm", true},
154     {"growing_cactus:trunk", true},
155     {"growing_cactus:branch_trunk", true},
156     {"growing_cactus:branch", true},
157     {"growing_cactus:branch_xp", true},
158     {"growing_cactus:branch_xm", true},
159     {"growing_cactus:branch_zp", true},
160     {"growing_cactus:branch_zm", true},
161     {"growing_cactus:branch_zz", true},
162     {"growing_cactus:branch_xx", true},
163
164     -- Support farming_plus
165     {"farming_plus:banana_leaves", false},
166     {"farming_plus:banana", false},
167     {"farming_plus:cocoa_leaves", false},
168     {"farming_plus:cocoa", false},
169
170     -- Support nature
171     {"nature:blossom", false},
172
173     -- Support snow
174     {"snow:needles", false},
175     {"snow:needles_decorated", false},
176     {"snow:star", false},
177
178     -- Support vines (also generated by moretrees if available)
179     {"vines:vines", false},
180
181     {"trunks:moss", false},
182     {"trunks:moss_fungus", false},
183     {"trunks:treeroot", false},
b9f89a 184
A 185     -- Support ethereal
186     {"ethereal:bamboo", true},
187     {"ethereal:bamboo_leaves", false},
188     {"ethereal:banana_trunk", true},
189     {"ethereal:bananaleaves", false},
190     {"ethereal:banana", false},
191     {"ethereal:birch_trunk", true},
192     {"ethereal:birch_leaves", false},
193     {"ethereal:frost_tree", true},
194     {"ethereal:frost_leaves", false},
195     {"ethereal:mushroom_trunk", true},
196     {"ethereal:mushroom", false},
197     {"ethereal:mushroom_pore", true},
198     {"ethereal:orangeleaves", false},
199     {"ethereal:orange", false},
200     {"ethereal:palm_trunk", true},
201     {"ethereal:palmleaves", false},
202     {"ethereal:coconut", false},
203     {"ethereal:redwood_trunk", true},
204     {"ethereal:redwood_leaves", false},
205     {"ethereal:sakura_trunk", true},
206     {"ethereal:sakura_leaves", false},
207     {"ethereal:sakura_leaves2", false},
208     {"ethereal:scorched_tree", true},
209     {"ethereal:willow_trunk", true},
210     {"ethereal:willow_twig", false},
211     {"ethereal:yellow_trunk", true},
212     {"ethereal:yellowleaves", false},
213     {"ethereal:golden_apple", false},
8e03d7 214 }
82cba9 215
e66bb2 216 local timber_nodenames = {}
C 217 for _, node in pairs(nodes) do
218     if chainsaw_leaves or node[2] then
219         timber_nodenames[node[1]] = true
72d541 220     end
T 221 end
222
5cf765 223 local S = technic.getter
S 224
225 technic.register_power_tool("technic:chainsaw", chainsaw_max_charge)
226
31a052 227 -- This function checks if the specified node should be sawed
D 228 local function check_if_node_sawed(pos)
229     local node_name = minetest.get_node(pos).name
230     if timber_nodenames[node_name]
231             or (chainsaw_leaves and minetest.get_item_group(node_name, "leaves") ~= 0)
232             or minetest.get_item_group(node_name, "tree") ~= 0 then
233         return true
234     end
235
236     return false
237 end
238
8e03d7 239 -- Table for saving what was sawed down
9019eb 240 local produced = {}
8e03d7 241
9019eb 242 -- Save the items sawed down so that we can drop them in a nice single stack
S 243 local function handle_drops(drops)
244     for _, item in ipairs(drops) do
245         local stack = ItemStack(item)
246         local name = stack:get_name()
247         local p = produced[name]
248         if not p then
249             produced[name] = stack
c63658 250         else
9019eb 251             p:set_count(p:get_count() + stack:get_count())
c63658 252         end
9019eb 253     end
S 254 end
255
256 --- Iterator over positions to try to saw around a sawed node.
ec069a 257 -- This returns positions in a 3x1x3 area around the position, plus the
S 258 -- position above it.  This does not return the bottom position to prevent
259 -- the chainsaw from cutting down nodes below the cutting position.
16302c 260 -- @param pos Sawing position.
9019eb 261 local function iterSawTries(pos)
16302c 262     -- Copy position to prevent mangling it
S 263     local pos = vector.new(pos)
ec069a 264     local i = 0
9019eb 265
S 266     return function()
ec069a 267         i = i + 1
S 268         -- Given a (top view) area like so (where 5 is the starting position):
269         -- X -->
270         -- Z 123
271         -- | 456
272         -- V 789
273         -- This will return positions 1, 4, 7, 2, 8 (skip 5), 3, 6, 9,
274         -- and the position above 5.
275         if i == 1 then
276             -- Move to starting position
277             pos.x = pos.x - 1
278             pos.z = pos.z - 1
279         elseif i == 4 or i == 7 then
280             -- Move to next X and back to start of Z when we reach
281             -- the end of a Z line.
9019eb 282             pos.x = pos.x + 1
ec069a 283             pos.z = pos.z - 2
S 284         elseif i == 5 then
285             -- Skip the middle position (we've already run on it)
286             -- and double-increment the counter.
287             pos.z = pos.z + 2
288             i = i + 1
289         elseif i <= 9 then
290             -- Go to next Z.
291             pos.z = pos.z + 1
292         elseif i == 10 then
293             -- Move back to center and up.
294             -- The Y+ position must be last so that we don't dig
295             -- straight upward and not come down (since the Y-
296             -- position isn't checked).
297             pos.x = pos.x - 1
298             pos.z = pos.z - 1
299             pos.y = pos.y + 1
9019eb 300         else
ec069a 301             return nil
9019eb 302         end
S 303         return pos
c63658 304     end
8e03d7 305 end
R 306
307 -- This function does all the hard work. Recursively we dig the node at hand
308 -- if it is in the table and then search the surroundings for more stuff to dig.
9019eb 309 local function recursive_dig(pos, remaining_charge)
S 310     if remaining_charge < chainsaw_charge_per_node then
c63658 311         return remaining_charge
P 312     end
9019eb 313     local node = minetest.get_node(pos)
S 314
31a052 315     if not check_if_node_sawed(pos) then
9019eb 316         return remaining_charge
S 317     end
318
ec069a 319     -- Wood found - cut it
9019eb 320     handle_drops(minetest.get_node_drops(node.name, ""))
S 321     minetest.remove_node(pos)
322     remaining_charge = remaining_charge - chainsaw_charge_per_node
323
324     -- Check surroundings and run recursively if any charge left
16302c 325     for npos in iterSawTries(pos) do
9019eb 326         if remaining_charge < chainsaw_charge_per_node then
S 327             break
328         end
31a052 329         if check_if_node_sawed(npos) then
16302c 330             remaining_charge = recursive_dig(npos, remaining_charge)
31a052 331         else
D 332             minetest.check_for_falling(npos)
9019eb 333         end
S 334     end
c63658 335     return remaining_charge
P 336 end
337
338 -- Function to randomize positions for new node drops
339 local function get_drop_pos(pos)
340     local drop_pos = {}
341
342     for i = 0, 8 do
343         -- Randomize position for a new drop
344         drop_pos.x = pos.x + math.random(-3, 3)
345         drop_pos.y = pos.y - 1
346         drop_pos.z = pos.z + math.random(-3, 3)
347
348         -- Move the randomized position upwards until
349         -- the node is air or unloaded.
350         for y = drop_pos.y, drop_pos.y + 5 do
351             drop_pos.y = y
352             local node = minetest.get_node_or_nil(drop_pos)
353
354             if not node then
355                 -- If the node is not loaded yet simply drop
356                 -- the item at the original digging position.
357                 return pos
358             elseif node.name == "air" then
9019eb 359                 -- Add variation to the entity drop position,
S 360                 -- but don't let drops get too close to the edge
361                 drop_pos.x = drop_pos.x + (math.random() * 0.8) - 0.5
362                 drop_pos.z = drop_pos.z + (math.random() * 0.8) - 0.5
c63658 363                 return drop_pos
P 364             end
365         end
366     end
367
368     -- Return the original position if this takes too long
369     return pos
e23f87 370 end
19c9a0 371
9019eb 372 -- Chainsaw entry point
S 373 local function chainsaw_dig(pos, current_charge)
374     -- Start sawing things down
375     local remaining_charge = recursive_dig(pos, current_charge)
376     minetest.sound_play("chainsaw", {pos = pos, gain = 1.0,
377             max_hear_distance = 10})
5cf765 378
9019eb 379     -- Now drop items for the player
S 380     for name, stack in pairs(produced) do
381         -- Drop stacks of stack max or less
382         local count, max = stack:get_count(), stack:get_stack_max()
383         stack:set_count(max)
384         while count > max do
385             minetest.add_item(get_drop_pos(pos), stack)
386             count = count - max
c63658 387         end
9019eb 388         stack:set_count(count)
S 389         minetest.add_item(get_drop_pos(pos), stack)
390     end
391
392     -- Clean up
393     produced = {}
394
395     return remaining_charge
5cf765 396 end
S 397
398
399 minetest.register_tool("technic:chainsaw", {
400     description = S("Chainsaw"),
401     inventory_image = "technic_chainsaw.png",
402     stack_max = 1,
99fd5d 403     wear_represents = "technic_RE_charge",
00d7c9 404     on_refill = technic.refill_RE_charge,
5cf765 405     on_use = function(itemstack, user, pointed_thing)
S 406         if pointed_thing.type ~= "node" then
407             return itemstack
408         end
9019eb 409
5cf765 410         local meta = minetest.deserialize(itemstack:get_metadata())
9019eb 411         if not meta or not meta.charge or
S 412                 meta.charge < chainsaw_charge_per_node then
5cf765 413             return
S 414         end
415
9019eb 416         local name = user:get_player_name()
51c02e 417         if minetest.is_protected(pointed_thing.under, name) then
S 418             minetest.record_protection_violation(pointed_thing.under, name)
419             return
9019eb 420         end
S 421
422         -- Send current charge to digging function so that the
423         -- chainsaw will stop after digging a number of nodes
424         meta.charge = chainsaw_dig(pointed_thing.under, meta.charge)
b8c902 425         if not technic.creative_mode then
M 426             technic.set_RE_wear(itemstack, meta.charge, chainsaw_max_charge)
427             itemstack:set_metadata(minetest.serialize(meta))
428         end
5cf765 429         return itemstack
S 430     end,
431 })
432
e4c34c 433 local mesecons_button = minetest.get_modpath("mesecons_button")
T 434 local trigger = mesecons_button and "mesecons_button:button_off" or "default:mese_crystal_fragment"
435
5cf765 436 minetest.register_craft({
9019eb 437     output = "technic:chainsaw",
c63658 438     recipe = {
e4c34c 439         {"technic:stainless_steel_ingot", trigger,                      "technic:battery"},
44cb8d 440         {"basic_materials:copper_wire",      "basic_materials:motor",              "technic:battery"},
5e4a87 441         {"",                              "",                           "technic:stainless_steel_ingot"},
44cb8d 442     },
VD 443     replacements = { {"basic_materials:copper_wire", "basic_materials:empty_spool"}, },
444
5cf765 445 })
9019eb 446