Update helptext of obsidian
[MineClone/MineClone2.git] / mods / ENTITIES / mcl_minecarts / init.lua
blobdc617281b3dc035bba36bae2c275bf33218a20b0
1 local S = minetest.get_translator("mcl_minecarts")
3 mcl_minecarts = {}
4 mcl_minecarts.modpath = minetest.get_modpath("mcl_minecarts")
5 mcl_minecarts.speed_max = 10
6 mcl_minecarts.check_float_time = 15
8 dofile(mcl_minecarts.modpath.."/functions.lua")
9 dofile(mcl_minecarts.modpath.."/rails.lua")
11 local function detach_driver(self)
12 if not self._driver then
13 return
14 end
15 mcl_player.player_attached[self._driver] = nil
16 local player = minetest.get_player_by_name(self._driver)
17 self._driver = nil
18 self._start_pos = nil
19 if player then
20 player:set_detach()
21 player:set_eye_offset({x=0, y=0, z=0},{x=0, y=0, z=0})
22 mcl_player.player_set_animation(player, "stand" , 30)
23 end
24 end
26 local function activate_tnt_minecart(self, timer)
27 if self._boomtimer then
28 return
29 end
30 self.object:set_armor_groups({immortal=1})
31 if timer then
32 self._boomtimer = timer
33 else
34 self._boomtimer = tnt.BOOMTIMER
35 end
36 self.object:set_properties({textures = {
37 "mcl_tnt_blink.png",
38 "mcl_tnt_blink.png",
39 "mcl_tnt_blink.png",
40 "mcl_tnt_blink.png",
41 "mcl_tnt_blink.png",
42 "mcl_tnt_blink.png",
43 "mcl_minecarts_minecart.png",
44 }})
45 self._blinktimer = tnt.BLINKTIMER
46 minetest.sound_play("tnt_ignite", {pos = self.object:get_pos(), gain = 1.0, max_hear_distance = 15}, true)
47 end
49 local activate_normal_minecart = detach_driver
51 -- Table for item-to-entity mapping. Keys: itemstring, Values: Corresponding entity ID
52 local entity_mapping = {}
54 local function register_entity(entity_id, mesh, textures, drop, on_rightclick, on_activate_by_rail)
55 local cart = {
56 physical = false,
57 collisionbox = {-10/16., -0.5, -10/16, 10/16, 0.25, 10/16},
58 visual = "mesh",
59 mesh = mesh,
60 visual_size = {x=1, y=1},
61 textures = textures,
63 on_rightclick = on_rightclick,
65 _driver = nil, -- player who sits in and controls the minecart (only for minecart!)
66 _punched = false, -- used to re-send _velocity and position
67 _velocity = {x=0, y=0, z=0}, -- only used on punch
68 _start_pos = nil, -- Used to calculate distance for “On A Rail” achievement
69 _last_float_check = nil, -- timestamp of last time the cart was checked to be still on a rail
70 _fueltime = nil, -- how many seconds worth of fuel is left. Only used by minecart with furnace
71 _boomtimer = nil, -- how many seconds are left before exploding
72 _blinktimer = nil, -- how many seconds are left before TNT blinking
73 _blink = false, -- is TNT blink texture active?
74 _old_dir = {x=0, y=0, z=0},
75 _old_pos = nil,
76 _old_vel = {x=0, y=0, z=0},
77 _old_switch = 0,
78 _railtype = nil,
81 function cart:on_activate(staticdata, dtime_s)
82 -- Initialize
83 local data = minetest.deserialize(staticdata)
84 if type(data) == "table" then
85 self._railtype = data._railtype
86 end
87 self.object:set_armor_groups({immortal=1})
89 -- Activate cart if on activator rail
90 if self.on_activate_by_rail then
91 local pos = self.object:get_pos()
92 local node = minetest.get_node(vector.floor(pos))
93 if node.name == "mcl_minecarts:activator_rail_on" then
94 self:on_activate_by_rail()
95 end
96 end
97 end
99 function cart:on_punch(puncher, time_from_last_punch, tool_capabilities, direction)
100 local pos = self.object:get_pos()
101 if not self._railtype then
102 local node = minetest.get_node(vector.floor(pos)).name
103 self._railtype = minetest.get_item_group(node, "connect_to_raillike")
106 if not puncher or not puncher:is_player() then
107 local cart_dir = mcl_minecarts:get_rail_direction(pos, {x=1, y=0, z=0}, nil, nil, self._railtype)
108 if vector.equals(cart_dir, {x=0, y=0, z=0}) then
109 return
111 self._velocity = vector.multiply(cart_dir, 3)
112 self._old_pos = nil
113 self._punched = true
114 return
117 -- Punch+sneak: Pick up minecart (unless TNT was ignited)
118 if puncher:get_player_control().sneak and not self._boomtimer then
119 if self._driver then
120 if self._old_pos then
121 self.object:set_pos(self._old_pos)
123 detach_driver(self)
126 -- Disable detector rail
127 local rou_pos = vector.round(pos)
128 local node = minetest.get_node(rou_pos)
129 if node.name == "mcl_minecarts:detector_rail_on" then
130 local newnode = {name="mcl_minecarts:detector_rail", param2 = node.param2}
131 minetest.swap_node(rou_pos, newnode)
132 mesecon.receptor_off(rou_pos)
135 -- Drop items and remove cart entity
136 if not minetest.is_creative_enabled(puncher:get_player_name()) then
137 for d=1, #drop do
138 minetest.add_item(self.object:get_pos(), drop[d])
140 elseif puncher and puncher:is_player() then
141 local inv = puncher:get_inventory()
142 for d=1, #drop do
143 if not inv:contains_item("main", drop[d]) then
144 inv:add_item("main", drop[d])
149 self.object:remove()
150 return
153 local vel = self.object:get_velocity()
154 if puncher:get_player_name() == self._driver then
155 if math.abs(vel.x + vel.z) > 7 then
156 return
160 local punch_dir = mcl_minecarts:velocity_to_dir(puncher:get_look_dir())
161 punch_dir.y = 0
162 local cart_dir = mcl_minecarts:get_rail_direction(pos, punch_dir, nil, nil, self._railtype)
163 if vector.equals(cart_dir, {x=0, y=0, z=0}) then
164 return
167 time_from_last_punch = math.min(time_from_last_punch, tool_capabilities.full_punch_interval)
168 local f = 3 * (time_from_last_punch / tool_capabilities.full_punch_interval)
170 self._velocity = vector.multiply(cart_dir, f)
171 self._old_pos = nil
172 self._punched = true
175 cart.on_activate_by_rail = on_activate_by_rail
177 function cart:on_step(dtime)
178 local vel = self.object:get_velocity()
179 local update = {}
180 if self._last_float_check == nil then
181 self._last_float_check = 0
182 else
183 self._last_float_check = self._last_float_check + dtime
185 local pos, rou_pos, node
186 -- Drop minecart if it isn't on a rail anymore
187 if self._last_float_check >= mcl_minecarts.check_float_time then
188 pos = self.object:get_pos()
189 rou_pos = vector.round(pos)
190 node = minetest.get_node(rou_pos)
191 local g = minetest.get_item_group(node.name, "connect_to_raillike")
192 if g ~= self._railtype and self._railtype ~= nil then
193 local player
194 -- Detach driver
195 if self._driver then
196 if self._old_pos then
197 self.object:set_pos(self._old_pos)
199 mcl_player.player_attached[self._driver] = nil
200 player = minetest.get_player_by_name(self._driver)
201 if player then
202 player:set_detach()
203 player:set_eye_offset({x=0, y=0, z=0},{x=0, y=0, z=0})
207 -- Explode if already ignited
208 if self._boomtimer then
209 self.object:remove()
210 mcl_explosions.explode(pos, 4, { drop_chance = 1.0 })
211 return
214 -- Drop items and remove cart entity
215 local pname = ""
216 if player then
217 pname = player:get_player_name()
219 if not minetest.is_creative_enabled(pname) then
220 for d=1, #drop do
221 minetest.add_item(self.object:get_pos(), drop[d])
225 self.object:remove()
226 return
228 self._last_float_check = 0
231 -- Update furnace stuff
232 if self._fueltime and self._fueltime > 0 then
233 self._fueltime = self._fueltime - dtime
234 if self._fueltime <= 0 then
235 self.object:set_properties({textures =
237 "default_furnace_top.png",
238 "default_furnace_top.png",
239 "default_furnace_front.png",
240 "default_furnace_side.png",
241 "default_furnace_side.png",
242 "default_furnace_side.png",
243 "mcl_minecarts_minecart.png",
245 self._fueltime = 0
248 local has_fuel = self._fueltime and self._fueltime > 0
250 -- Update TNT stuff
251 if self._boomtimer then
252 -- Explode
253 self._boomtimer = self._boomtimer - dtime
254 local pos = self.object:get_pos()
255 if self._boomtimer <= 0 then
256 self.object:remove()
257 mcl_explosions.explode(pos, 4, { drop_chance = 1.0 })
258 return
259 else
260 tnt.smoke_step(pos)
263 if self._blinktimer then
264 self._blinktimer = self._blinktimer - dtime
265 if self._blinktimer <= 0 then
266 self._blink = not self._blink
267 if self._blink then
268 self.object:set_properties({textures =
270 "default_tnt_top.png",
271 "default_tnt_bottom.png",
272 "default_tnt_side.png",
273 "default_tnt_side.png",
274 "default_tnt_side.png",
275 "default_tnt_side.png",
276 "mcl_minecarts_minecart.png",
278 else
279 self.object:set_properties({textures =
281 "mcl_tnt_blink.png",
282 "mcl_tnt_blink.png",
283 "mcl_tnt_blink.png",
284 "mcl_tnt_blink.png",
285 "mcl_tnt_blink.png",
286 "mcl_tnt_blink.png",
287 "mcl_minecarts_minecart.png",
290 self._blinktimer = tnt.BLINKTIMER
294 if self._punched then
295 vel = vector.add(vel, self._velocity)
296 self.object:set_velocity(vel)
297 self._old_dir.y = 0
298 elseif vector.equals(vel, {x=0, y=0, z=0}) and (not has_fuel) then
299 return
302 local dir, last_switch = nil, nil
303 if not pos then
304 pos = self.object:get_pos()
306 if self._old_pos and not self._punched then
307 local flo_pos = vector.floor(pos)
308 local flo_old = vector.floor(self._old_pos)
309 if vector.equals(flo_pos, flo_old) and (not has_fuel) then
310 return
311 -- Prevent querying the same node over and over again
314 if not rou_pos then
315 rou_pos = vector.round(pos)
317 local rou_old = vector.round(self._old_pos)
318 if not node then
319 node = minetest.get_node(rou_pos)
321 local node_old = minetest.get_node(rou_old)
323 -- Update detector rails
324 if node.name == "mcl_minecarts:detector_rail" then
325 local newnode = {name="mcl_minecarts:detector_rail_on", param2 = node.param2}
326 minetest.swap_node(rou_pos, newnode)
327 mesecon.receptor_on(rou_pos)
329 if node_old.name == "mcl_minecarts:detector_rail_on" then
330 local newnode = {name="mcl_minecarts:detector_rail", param2 = node_old.param2}
331 minetest.swap_node(rou_old, newnode)
332 mesecon.receptor_off(rou_old)
334 -- Activate minecart if on activator rail
335 if node_old.name == "mcl_minecarts:activator_rail_on" and self.on_activate_by_rail then
336 self:on_activate_by_rail()
340 local ctrl, player = nil, nil
341 if self._driver then
342 player = minetest.get_player_by_name(self._driver)
343 if player then
344 ctrl = player:get_player_control()
348 -- Stop cart if velocity vector flips
349 if self._old_vel and self._old_vel.y == 0 and
350 (self._old_vel.x * vel.x < 0 or self._old_vel.z * vel.z < 0) then
351 self._old_vel = {x = 0, y = 0, z = 0}
352 self._old_pos = pos
353 self.object:set_velocity(vector.new())
354 self.object:set_acceleration(vector.new())
355 return
357 self._old_vel = vector.new(vel)
359 if self._old_pos then
360 local diff = vector.subtract(self._old_pos, pos)
361 for _,v in ipairs({"x","y","z"}) do
362 if math.abs(diff[v]) > 1.1 then
363 local expected_pos = vector.add(self._old_pos, self._old_dir)
364 dir, last_switch = mcl_minecarts:get_rail_direction(pos, self._old_dir, ctrl, self._old_switch, self._railtype)
365 if vector.equals(dir, {x=0, y=0, z=0}) then
366 dir = false
367 pos = vector.new(expected_pos)
368 update.pos = true
370 break
375 if vel.y == 0 then
376 for _,v in ipairs({"x", "z"}) do
377 if vel[v] ~= 0 and math.abs(vel[v]) < 0.9 then
378 vel[v] = 0
379 update.vel = true
384 local cart_dir = mcl_minecarts:velocity_to_dir(vel)
385 local max_vel = mcl_minecarts.speed_max
386 if not dir then
387 dir, last_switch = mcl_minecarts:get_rail_direction(pos, cart_dir, ctrl, self._old_switch, self._railtype)
390 local new_acc = {x=0, y=0, z=0}
391 if vector.equals(dir, {x=0, y=0, z=0}) and not has_fuel then
392 vel = {x=0, y=0, z=0}
393 update.vel = true
394 else
395 -- If the direction changed
396 if dir.x ~= 0 and self._old_dir.z ~= 0 then
397 vel.x = dir.x * math.abs(vel.z)
398 vel.z = 0
399 pos.z = math.floor(pos.z + 0.5)
400 update.pos = true
402 if dir.z ~= 0 and self._old_dir.x ~= 0 then
403 vel.z = dir.z * math.abs(vel.x)
404 vel.x = 0
405 pos.x = math.floor(pos.x + 0.5)
406 update.pos = true
408 -- Up, down?
409 if dir.y ~= self._old_dir.y then
410 vel.y = dir.y * math.abs(vel.x + vel.z)
411 pos = vector.round(pos)
412 update.pos = true
415 -- Slow down or speed up
416 local acc = dir.y * -1.8
418 local speed_mod = minetest.registered_nodes[minetest.get_node(pos).name]._rail_acceleration
419 if has_fuel then
420 acc = acc + 0.2
421 elseif speed_mod and speed_mod ~= 0 then
422 acc = acc + speed_mod
423 else
424 acc = acc - 0.4
427 new_acc = vector.multiply(dir, acc)
430 self.object:set_acceleration(new_acc)
431 self._old_pos = vector.new(pos)
432 self._old_dir = vector.new(dir)
433 self._old_switch = last_switch
435 -- Limits
436 for _,v in ipairs({"x","y","z"}) do
437 if math.abs(vel[v]) > max_vel then
438 vel[v] = mcl_minecarts:get_sign(vel[v]) * max_vel
439 new_acc[v] = 0
440 update.vel = true
444 -- Give achievement when player reached a distance of 1000 nodes from the start position
445 if self._driver and (vector.distance(self._start_pos, pos) >= 1000) then
446 awards.unlock(self._driver, "mcl:onARail")
450 if update.pos or self._punched then
451 local yaw = 0
452 if dir.x < 0 then
453 yaw = 0.5
454 elseif dir.x > 0 then
455 yaw = 1.5
456 elseif dir.z < 0 then
457 yaw = 1
459 self.object:set_yaw(yaw * math.pi)
462 if self._punched then
463 self._punched = false
466 if not (update.vel or update.pos) then
467 return
471 local anim = {x=0, y=0}
472 if dir.y == -1 then
473 anim = {x=1, y=1}
474 elseif dir.y == 1 then
475 anim = {x=2, y=2}
477 self.object:set_animation(anim, 1, 0)
479 self.object:set_velocity(vel)
480 if update.pos then
481 self.object:set_pos(pos)
483 update = nil
486 function cart:get_staticdata()
487 return minetest.serialize({_railtype = self._railtype})
490 minetest.register_entity(entity_id, cart)
493 -- Place a minecart at pointed_thing
494 mcl_minecarts.place_minecart = function(itemstack, pointed_thing, placer)
495 if not pointed_thing.type == "node" then
496 return
499 local railpos, node
500 if mcl_minecarts:is_rail(pointed_thing.under) then
501 railpos = pointed_thing.under
502 node = minetest.get_node(pointed_thing.under)
503 elseif mcl_minecarts:is_rail(pointed_thing.above) then
504 railpos = pointed_thing.above
505 node = minetest.get_node(pointed_thing.above)
506 else
507 return
510 -- Activate detector rail
511 if node.name == "mcl_minecarts:detector_rail" then
512 local newnode = {name="mcl_minecarts:detector_rail_on", param2 = node.param2}
513 minetest.swap_node(railpos, newnode)
514 mesecon.receptor_on(railpos)
517 local entity_id = entity_mapping[itemstack:get_name()]
518 local cart = minetest.add_entity(railpos, entity_id)
519 local railtype = minetest.get_item_group(node.name, "connect_to_raillike")
520 local le = cart:get_luaentity()
521 if le ~= nil then
522 le._railtype = railtype
524 local cart_dir = mcl_minecarts:get_rail_direction(railpos, {x=1, y=0, z=0}, nil, nil, railtype)
525 cart:set_yaw(minetest.dir_to_yaw(cart_dir))
527 local pname = ""
528 if placer then
529 pname = placer:get_player_name()
531 if not minetest.is_creative_enabled(pname) then
532 itemstack:take_item()
534 return itemstack
538 local register_craftitem = function(itemstring, entity_id, description, tt_help, longdesc, usagehelp, icon, creative)
539 entity_mapping[itemstring] = entity_id
541 local groups = { minecart = 1, transport = 1 }
542 if creative == false then
543 groups.not_in_creative_inventory = 1
545 local def = {
546 stack_max = 1,
547 on_place = function(itemstack, placer, pointed_thing)
548 if not pointed_thing.type == "node" then
549 return
552 -- Call on_rightclick if the pointed node defines it
553 local node = minetest.get_node(pointed_thing.under)
554 if placer and not placer:get_player_control().sneak then
555 if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then
556 return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, placer, itemstack) or itemstack
560 return mcl_minecarts.place_minecart(itemstack, pointed_thing, placer)
561 end,
562 _on_dispense = function(stack, pos, droppos, dropnode, dropdir)
563 -- Place minecart as entity on rail. If there's no rail, just drop it.
564 local placed
565 if minetest.get_item_group(dropnode.name, "rail") ~= 0 then
566 -- FIXME: This places minecarts even if the spot is already occupied
567 local pointed_thing = { under = droppos, above = { x=droppos.x, y=droppos.y+1, z=droppos.z } }
568 placed = mcl_minecarts.place_minecart(stack, pointed_thing)
570 if placed == nil then
571 -- Drop item
572 minetest.add_item(droppos, stack)
574 end,
575 groups = groups,
577 def.description = description
578 def._tt_help = tt_help
579 def._doc_items_longdesc = longdesc
580 def._doc_items_usagehelp = usagehelp
581 def.inventory_image = icon
582 def.wield_image = icon
583 minetest.register_craftitem(itemstring, def)
586 --[[
587 Register a minecart
588 * itemstring: Itemstring of minecart item
589 * entity_id: ID of minecart entity
590 * description: Item name / description
591 * longdesc: Long help text
592 * usagehelp: Usage help text
593 * mesh: Minecart mesh
594 * textures: Minecart textures table
595 * icon: Item icon
596 * drop: Dropped items after destroying minecart
597 * on_rightclick: Called after rightclick
598 * on_activate_by_rail: Called when above activator rail
599 * creative: If false, don't show in Creative Inventory
601 local function register_minecart(itemstring, entity_id, description, tt_help, longdesc, usagehelp, mesh, textures, icon, drop, on_rightclick, on_activate_by_rail, creative)
602 register_entity(entity_id, mesh, textures, drop, on_rightclick, on_activate_by_rail)
603 register_craftitem(itemstring, entity_id, description, tt_help, longdesc, usagehelp, icon, creative)
604 if minetest.get_modpath("doc_identifier") ~= nil then
605 doc.sub.identifier.register_object(entity_id, "craftitems", itemstring)
609 -- Minecart
610 register_minecart(
611 "mcl_minecarts:minecart",
612 "mcl_minecarts:minecart",
613 S("Minecart"),
614 S("Vehicle for fast travel on rails"),
615 S("Minecarts can be used for a quick transportion on rails.") .. "\n" ..
616 S("Minecarts only ride on rails and always follow the tracks. At a T-junction with no straight way ahead, they turn left. The speed is affected by the rail type."),
617 S("You can place the minecart on rails. Right-click it to enter it. Punch it to get it moving.") .. "\n" ..
618 S("To obtain the minecart, punch it while holding down the sneak key.") .. "\n" ..
619 S("If it moves over a powered activator rail, you'll get ejected."),
620 "mcl_minecarts_minecart.b3d",
621 {"mcl_minecarts_minecart.png"},
622 "mcl_minecarts_minecart_normal.png",
623 {"mcl_minecarts:minecart"},
624 function(self, clicker)
625 local name = clicker:get_player_name()
626 if not clicker or not clicker:is_player() then
627 return
629 local player_name = clicker:get_player_name()
630 if self._driver and player_name == self._driver then
631 detach_driver(self)
632 elseif not self._driver then
633 self._driver = player_name
634 self._start_pos = self.object:get_pos()
635 mcl_player.player_attached[player_name] = true
636 clicker:set_attach(self.object, "", {x=0, y=-1.75, z=-2}, {x=0, y=0, z=0})
637 mcl_player.player_attached[name] = true
638 minetest.after(0.2, function(name)
639 local player = minetest.get_player_by_name(name)
640 if player then
641 mcl_player.player_set_animation(player, "sit" , 30)
642 player:set_eye_offset({x=0, y=-5.5, z=0},{x=0, y=-4, z=0})
644 end, name)
646 end, activate_normal_minecart
649 -- Minecart with Chest
650 register_minecart(
651 "mcl_minecarts:chest_minecart",
652 "mcl_minecarts:chest_minecart",
653 S("Minecart with Chest"),
654 nil, nil, nil,
655 "mcl_minecarts_minecart_chest.b3d",
656 { "mcl_chests_normal.png", "mcl_minecarts_minecart.png" },
657 "mcl_minecarts_minecart_chest.png",
658 {"mcl_minecarts:minecart", "mcl_chests:chest"},
659 nil, nil, false)
661 -- Minecart with Furnace
662 register_minecart(
663 "mcl_minecarts:furnace_minecart",
664 "mcl_minecarts:furnace_minecart",
665 S("Minecart with Furnace"),
666 nil,
667 S("A minecart with furnace is a vehicle that travels on rails. It can propel itself with fuel."),
668 S("Place it on rails. If you give it some coal, the furnace will start burning for a long time and the minecart will be able to move itself. Punch it to get it moving.") .. "\n" ..
669 S("To obtain the minecart and furnace, punch them while holding down the sneak key."),
671 "mcl_minecarts_minecart_block.b3d",
673 "default_furnace_top.png",
674 "default_furnace_top.png",
675 "default_furnace_front.png",
676 "default_furnace_side.png",
677 "default_furnace_side.png",
678 "default_furnace_side.png",
679 "mcl_minecarts_minecart.png",
681 "mcl_minecarts_minecart_furnace.png",
682 {"mcl_minecarts:minecart", "mcl_furnaces:furnace"},
683 -- Feed furnace with coal
684 function(self, clicker)
685 if not clicker or not clicker:is_player() then
686 return
688 if not self._fueltime then
689 self._fueltime = 0
691 local held = clicker:get_wielded_item()
692 if minetest.get_item_group(held:get_name(), "coal") == 1 then
693 self._fueltime = self._fueltime + 180
695 if not minetest.is_creative_enabled(clicker:get_player_name()) then
696 held:take_item()
697 local index = clicker:get_wield_index()
698 local inv = clicker:get_inventory()
699 inv:set_stack("main", index, held)
701 self.object:set_properties({textures =
703 "default_furnace_top.png",
704 "default_furnace_top.png",
705 "default_furnace_front_active.png",
706 "default_furnace_side.png",
707 "default_furnace_side.png",
708 "default_furnace_side.png",
709 "mcl_minecarts_minecart.png",
712 end, nil, false
715 -- Minecart with Command Block
716 register_minecart(
717 "mcl_minecarts:command_block_minecart",
718 "mcl_minecarts:command_block_minecart",
719 S("Minecart with Command Block"),
720 nil, nil, nil,
721 "mcl_minecarts_minecart_block.b3d",
723 "jeija_commandblock_off.png^[verticalframe:2:0",
724 "jeija_commandblock_off.png^[verticalframe:2:0",
725 "jeija_commandblock_off.png^[verticalframe:2:0",
726 "jeija_commandblock_off.png^[verticalframe:2:0",
727 "jeija_commandblock_off.png^[verticalframe:2:0",
728 "jeija_commandblock_off.png^[verticalframe:2:0",
729 "mcl_minecarts_minecart.png",
731 "mcl_minecarts_minecart_command_block.png",
732 {"mcl_minecarts:minecart"},
733 nil, nil, false
736 -- Minecart with Hopper
737 register_minecart(
738 "mcl_minecarts:hopper_minecart",
739 "mcl_minecarts:hopper_minecart",
740 S("Minecart with Hopper"),
741 nil, nil, nil,
742 "mcl_minecarts_minecart_hopper.b3d",
744 "mcl_hoppers_hopper_inside.png",
745 "mcl_minecarts_minecart.png",
746 "mcl_hoppers_hopper_outside.png",
747 "mcl_hoppers_hopper_top.png",
749 "mcl_minecarts_minecart_hopper.png",
750 {"mcl_minecarts:minecart", "mcl_hoppers:hopper"},
751 nil, nil, false
754 -- Minecart with TNT
755 register_minecart(
756 "mcl_minecarts:tnt_minecart",
757 "mcl_minecarts:tnt_minecart",
758 S("Minecart with TNT"),
759 S("Vehicle for fast travel on rails").."\n"..S("Can be ignited by tools or powered activator rail"),
760 S("A minecart with TNT is an explosive vehicle that travels on rail."),
761 S("Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.") .. "\n" ..
762 S("To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited."),
763 "mcl_minecarts_minecart_block.b3d",
765 "default_tnt_top.png",
766 "default_tnt_bottom.png",
767 "default_tnt_side.png",
768 "default_tnt_side.png",
769 "default_tnt_side.png",
770 "default_tnt_side.png",
771 "mcl_minecarts_minecart.png",
773 "mcl_minecarts_minecart_tnt.png",
774 {"mcl_minecarts:minecart", "mcl_tnt:tnt"},
775 -- Ingite
776 function(self, clicker)
777 if not clicker or not clicker:is_player() then
778 return
780 if self._boomtimer then
781 return
783 local held = clicker:get_wielded_item()
784 if held:get_name() == "mcl_fire:flint_and_steel" then
785 if not minetest.is_creative_enabled(clicker:get_player_name()) then
786 held:add_wear(65535/65) -- 65 uses
787 local index = clicker:get_wield_index()
788 local inv = clicker:get_inventory()
789 inv:set_stack("main", index, held)
791 activate_tnt_minecart(self)
793 end, activate_tnt_minecart)
796 minetest.register_craft({
797 output = "mcl_minecarts:minecart",
798 recipe = {
799 {"mcl_core:iron_ingot", "", "mcl_core:iron_ingot"},
800 {"mcl_core:iron_ingot", "mcl_core:iron_ingot", "mcl_core:iron_ingot"},
804 minetest.register_craft({
805 output = "mcl_minecarts:tnt_minecart",
806 recipe = {
807 {"mcl_tnt:tnt"},
808 {"mcl_minecarts:minecart"},
812 -- TODO: Re-enable crafting of special minecarts when they have been implemented
813 if false then
815 minetest.register_craft({
816 output = "mcl_minecarts:furnace_minecart",
817 recipe = {
818 {"mcl_furnaces:furnace"},
819 {"mcl_minecarts:minecart"},
823 minetest.register_craft({
824 output = "mcl_minecarts:hopper_minecart",
825 recipe = {
826 {"mcl_hoppers:hopper"},
827 {"mcl_minecarts:minecart"},
831 minetest.register_craft({
832 output = "mcl_minecarts:chest_minecart",
833 recipe = {
834 {"mcl_chests:chest"},
835 {"mcl_minecarts:minecart"},