1 local minetest,math,ipairs,vector,table = minetest,math,ipairs,vector,table
2 --exclude certain mods and nodes from being pushed and pulled to stop glitches
4 minetest.register_on_mods_loaded(function()
5 registered_nodes = minetest.registered_nodes
8 local excluded_mods = {utility=true,craftingtable=true,buildtest=true,sign=true,bed=true}
9 local excluded_nodes = {
10 ["redstone:piston_on"]=true,
11 ["redstone:sticky_piston_on"]=true,
12 ["redstone:actuator"]=true,
13 ["redstone:sticky_actuator"]=true,
14 ["redstone:inverter_on"]=true,
15 ["redstone:inverter_off"]=true,
16 ["redstone:torch_wall"]=true,
17 ["redstone:torch_floor"]=true,
18 ["redstone:lever_on"]=true,
19 ["redstone:lever_off"]=true,
20 ["redstone:button_on"]=true,
21 ["redstone:button_off"]=true,
24 excluded_nodes["redstone:dust_"..i] = true
27 excluded_nodes["redstone:repeater_on_"..i] = true
28 excluded_nodes["redstone:repeater_off_"..i] = true
31 excluded_nodes["redstone:comparator_"..i] = true
34 excluded_nodes["redstone:pressure_plate_"..i] = true
37 excluded_nodes["redstone:ore_"..i] = true
42 ███████╗██╗ ██╗███╗ ██╗ ██████╗████████╗██╗ ██████╗ ███╗ ██╗
43 ██╔════╝██║ ██║████╗ ██║██╔════╝╚══██╔══╝██║██╔═══██╗████╗ ██║
44 █████╗ ██║ ██║██╔██╗ ██║██║ ██║ ██║██║ ██║██╔██╗ ██║
45 ██╔══╝ ██║ ██║██║╚██╗██║██║ ██║ ██║██║ ██║██║╚██╗██║
46 ██║ ╚██████╔╝██║ ╚████║╚██████╗ ██║ ██║╚██████╔╝██║ ╚████║
47 ╚═╝ ╚═════╝ ╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝
50 local function push_objects(pos,dir)
52 for _,object in ipairs(minetest.get_objects_inside_radius(pos,2)) do
54 if object:is_player() and object:get_hp() > 0 then
55 local pos2 = object:get_pos()
56 local compare = vector.subtract(pos2,pos)
57 local real_y = compare.y
58 compare = vector.abs(compare)
61 if compare.y <= 0.5 and compare.x < 0.8 and compare.z < 0.8 then
62 object:move_to(vector.add(dir,pos2))
63 object:add_player_velocity(vector.multiply(dir,20))
66 elseif dir.x ~=0 or dir.z ~= 0 then
67 if real_y <= 0.5 and real_y >= -1.6 and compare.x < 0.8 and compare.z < 0.8 then
68 object:move_to(vector.add(dir,pos2))
69 object:add_player_velocity(vector.multiply(dir,19))
72 elseif not object:is_player() and object:get_luaentity().name == "__builtin:falling_node" then
73 local pos2 = object:get_pos()
74 local compare = vector.subtract(pos2,pos)
75 local real_y = compare.y
76 compare = vector.abs(compare)
77 if compare.y <= 1.5 and compare.x <= 1.5 and compare.z <= 1.5 then
78 object:move_to(vector.add(dir,pos2))
79 object:add_velocity(vector.multiply(dir,20))
81 elseif not object:is_player() and object:get_luaentity().name == "__builtin:item" then
82 local pos2 = object:get_pos()
83 local compare = vector.subtract(pos2,pos)
84 local real_y = compare.y
85 compare = vector.abs(compare)
86 if compare.y <= 1 and compare.x <= 1 and compare.z <= 1 then
87 object:move_to(vector.add(dir,pos2))
88 object:add_velocity(vector.multiply(dir,20))
89 object:get_luaentity().poll_timer = 0
95 --this is how the piston pushes nodes
104 local function push_nodes(pos,dir)
108 index_pos = vector.add(vector.multiply(dir,i),pos)
109 node = minetest.get_node(index_pos)
111 def = minetest.registered_nodes[node.name]
113 push = ((excluded_mods[def.mod_origin] ~= true) and (excluded_nodes[name] ~= true))
116 push_objects(index_pos,dir)
118 if push and name ~= "air" then
120 index.pos = index_pos
122 index.param2 = param2
123 table.insert(move_index,index)
124 elseif name == "air" then
133 --check if room to move and objects in log
134 if space == true and next(move_index) then
135 if table.getn(move_index) == 1 and minetest.get_item_group(move_index[1].name, "falling_node") > 0 then
136 for i = 1,table.getn(move_index) do
137 move_index[i].pos = vector.add(move_index[i].pos,dir)
138 minetest.set_node(move_index[i].pos,{name="air"})
140 local obj = minetest.add_entity(vector.add(move_index[i].pos,dir), "__builtin:falling_node")
141 obj:get_luaentity():set_node({name=move_index[i].name})
142 obj:set_velocity(vector.multiply(dir,19))
145 for i = 1,table.getn(move_index) do
146 if move_index[i] then
147 if move_index[i].pos then
148 move_index[i].pos = vector.add(move_index[i].pos,dir)
149 minetest.set_node(move_index[i].pos,move_index[i])
150 minetest.check_for_falling(move_index[i].pos)
151 push_objects(move_index[i].pos,dir)
160 --this is the logic of the piston
163 local piston_location
165 local function actuator_arm_function(pos)
166 --this is where the piston activates
167 facedir = minetest.get_node(pos).param2
168 dir = minetest.facedir_to_dir(facedir)
169 piston_location = vector.add(pos,dir)
170 worked = push_nodes(pos,dir)
171 local node = minetest.get_node(vector.add(pos,dir)).name
173 if worked == true then
174 minetest.sound_play("piston", {pos=pos,pitch=math.random(85,100)/100})
175 minetest.set_node(piston_location,{name="redstone:actuator",param2=facedir})
176 minetest.swap_node(pos,{name="redstone:piston_on",param2=facedir})
178 redstone.inject(pos,{
179 name = "redstone:piston_on",
188 ██████╗ ███████╗███████╗
189 ██╔═══██╗██╔════╝██╔════╝
197 minetest.register_node("redstone:piston_off", {
198 description = "Piston",
199 tiles = {"redstone_piston.png","redstone_piston.png^[transformR180","redstone_piston.png^[transformR270","redstone_piston.png^[transformR90","wood.png","stone.png"},
200 paramtype2 = "facedir",
201 groups = {stone = 1, hard = 1, pickaxe = 1, hand = 4,pathable = 1,redstone_activation=1},
202 sounds = main.stoneSound(),
203 drop = "redstone:piston_off",
205 sunlight_propagates = true,
206 --reverse the direction to face the player
207 on_construct = function(pos)
208 redstone.inject(pos,{
209 name = "redstone:piston_off",
214 on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
215 local look = clicker:get_look_dir()
216 look = vector.multiply(look,-1)
217 local dir = minetest.dir_to_facedir(look, true)
218 minetest.swap_node(pos,{name="redstone:piston_off",param2=dir})
221 after_place_node = function(pos, placer, itemstack, pointed_thing)
222 local look = placer:get_look_dir()
223 look = vector.multiply(look,-1)
224 local dir = minetest.dir_to_facedir(look, true)
225 minetest.swap_node(pos,{name="redstone:piston_off",param2=dir})
227 after_destruct = function(pos, oldnode)
228 redstone.inject(pos,nil)
233 redstone.register_activator({
234 name = "redstone:piston_off",
235 activate = function(pos)
236 minetest.after(0,function()
237 actuator_arm_function(pos)
242 minetest.register_lbm({
243 name = "redstone:piston_off",
244 nodenames = {"redstone:piston_off"},
245 run_at_every_load = true,
246 action = function(pos)
247 redstone.inject(pos,{
248 name = "redstone:piston_off",
251 --redstone needs to warm up
252 minetest.after(0,function()
268 minetest.register_node("redstone:piston_on", {
269 description = "Piston",
270 tiles = {"redstone_piston.png","redstone_piston.png^[transformR180","redstone_piston.png^[transformR270","redstone_piston.png^[transformR90","stone.png","stone.png"},
271 drawtype = "nodebox",
273 paramtype2 = "facedir",
274 groups = {stone = 1, hard = 1, pickaxe = 1, hand = 4,pathable = 1,redstone_activation=1},
275 sounds = main.stoneSound(),
276 drop = "redstone:piston_off",
280 --left front bottom right back top
281 {-0.5, -0.5, -0.5, 0.5, 0.5, 3/16},
284 after_destruct = function(pos, oldnode)
285 local facedir = oldnode.param2
286 local dir = minetest.facedir_to_dir(facedir)
287 local piston_location = vector.add(pos,dir)
288 minetest.remove_node(piston_location)
289 redstone.inject(pos,nil)
293 minetest.register_lbm({
294 name = "redstone:piston_on",
295 nodenames = {"redstone:piston_on"},
296 run_at_every_load = true,
297 action = function(pos)
298 redstone.inject(pos,{
299 name = "redstone:piston_on",
302 --redstone needs to warm up
303 minetest.after(0,function()
309 redstone.register_activator({
310 name = "redstone:piston_on",
311 deactivate = function(pos)
312 --this is where the piston deactivates
313 local facedir = minetest.get_node(pos).param2
314 local dir = minetest.facedir_to_dir(facedir)
315 local piston_location = vector.add(pos,dir)
316 minetest.remove_node(piston_location)
318 minetest.check_for_falling(piston_location)
320 minetest.swap_node(pos,{name="redstone:piston_off",param2=facedir})
321 piston_location.y = piston_location.y + 1
322 minetest.sound_play("piston", {pos=pos,pitch=math.random(85,100)/100})
323 redstone.inject(pos,{
324 name = "redstone:piston_off",
332 █████╗ ██████╗ ███╗ ███╗
333 ██╔══██╗██╔══██╗████╗ ████║
334 ███████║██████╔╝██╔████╔██║
335 ██╔══██║██╔══██╗██║╚██╔╝██║
336 ██║ ██║██║ ██║██║ ╚═╝ ██║
337 ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝
342 minetest.register_node("redstone:actuator", {
343 description = "Piston Actuator",
344 tiles = {"wood.png"},
345 drawtype = "nodebox",
347 paramtype2 = "facedir",
348 groups = {stone = 1, hard = 1, pickaxe = 1, hand = 4,pathable = 1},
349 sounds = main.stoneSound(),
350 drop = "redstone:piston_off",
354 --left front bottom right back top
355 {-0.5, -0.5, 0.2, 0.5, 0.5, 0.5}, --mover
356 {-0.15, -0.15, -0.9, 0.15, 0.15, 0.5}, --actuator
359 after_destruct = function(pos, oldnode)
360 local facedir = oldnode.param2
361 local dir = minetest.facedir_to_dir(facedir)
362 dir = vector.multiply(dir,-1)
363 local piston_location = vector.add(pos,dir)
364 minetest.remove_node(piston_location)
373 ███████╗████████╗██╗ ██████╗██╗ ██╗██╗ ██╗ ██████╗ ██╗███████╗████████╗ ██████╗ ███╗ ██╗ ██████╗ ███████╗ ██████╗ ██╗███╗ ██╗███████╗
374 ██╔════╝╚══██╔══╝██║██╔════╝██║ ██╔╝╚██╗ ██╔╝ ██╔══██╗██║██╔════╝╚══██╔══╝██╔═══██╗████╗ ██║ ██╔══██╗██╔════╝██╔════╝ ██║████╗ ██║██╔════╝
375 ███████╗ ██║ ██║██║ █████╔╝ ╚████╔╝ ██████╔╝██║███████╗ ██║ ██║ ██║██╔██╗ ██║ ██████╔╝█████╗ ██║ ███╗██║██╔██╗ ██║███████╗
376 ╚════██║ ██║ ██║██║ ██╔═██╗ ╚██╔╝ ██╔═══╝ ██║╚════██║ ██║ ██║ ██║██║╚██╗██║ ██╔══██╗██╔══╝ ██║ ██║██║██║╚██╗██║╚════██║
377 ███████║ ██║ ██║╚██████╗██║ ██╗ ██║ ██║ ██║███████║ ██║ ╚██████╔╝██║ ╚████║ ██████╔╝███████╗╚██████╔╝██║██║ ╚████║███████║
378 ╚══════╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ ╚═════╝ ╚═╝╚═╝ ╚═══╝╚══════╝
388 ███████╗██╗ ██╗███╗ ██╗ ██████╗████████╗██╗ ██████╗ ███╗ ██╗
389 ██╔════╝██║ ██║████╗ ██║██╔════╝╚══██╔══╝██║██╔═══██╗████╗ ██║
390 █████╗ ██║ ██║██╔██╗ ██║██║ ██║ ██║██║ ██║██╔██╗ ██║
391 ██╔══╝ ██║ ██║██║╚██╗██║██║ ██║ ██║██║ ██║██║╚██╗██║
392 ██║ ╚██████╔╝██║ ╚████║╚██████╗ ██║ ██║╚██████╔╝██║ ╚████║
393 ╚═╝ ╚═════╝ ╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝
398 local function sticky_push_objects(pos,dir)
400 for _,object in ipairs(minetest.get_objects_inside_radius(pos, 2)) do
401 if object:is_player() and object:get_hp() > 0 then
402 local pos2 = object:get_pos()
403 local compare = vector.subtract(pos2,pos)
404 local real_y = compare.y
405 compare = vector.abs(compare)
408 if compare.y <= 0.5 and compare.x < 0.8 and compare.z < 0.8 then
409 object:move_to(vector.add(dir,pos2))
412 elseif dir.x ~=0 or dir.z ~= 0 then
413 if real_y <= 0.5 and real_y >= -1.6 and compare.x < 0.8 and compare.z < 0.8 then
414 object:move_to(vector.add(dir,pos2))
417 elseif not object:is_player() and object:get_luaentity().name == "__builtin:falling_node" then
418 local pos2 = object:get_pos()
419 local compare = vector.subtract(pos2,pos)
420 local real_y = compare.y
421 compare = vector.abs(compare)
422 if compare.y <= 1.5 and compare.x <= 1.5 and compare.z <= 1.5 then
423 object:move_to(vector.add(dir,pos2))
425 elseif not object:is_player() and object:get_luaentity().name == "__builtin:item" then
426 local pos2 = object:get_pos()
427 local compare = vector.subtract(pos2,pos)
428 local real_y = compare.y
429 compare = vector.abs(compare)
430 if compare.y <= 1 and compare.x <= 1 and compare.z <= 1 then
431 object:move_to(vector.add(dir,pos2))
432 object:get_luaentity().poll_timer = 0
439 --this is how the piston pushes nodes
448 local function sticky_push_nodes(pos,dir)
452 index_pos = vector.add(vector.multiply(dir,i),pos)
453 node = minetest.get_node(index_pos)
455 def = minetest.registered_nodes[node.name]
457 push = ((excluded_mods[def.mod_origin] ~= true) and (excluded_nodes[name] ~= true))
459 sticky_push_objects(index_pos,dir)
461 if push and name ~= "air" then
463 index.pos = index_pos
465 index.param2 = param2
466 table.insert(move_index,index)
467 elseif name == "air" then
476 --check if room to move and objects in log
477 if space == true and next(move_index) then
479 for i = 1,table.getn(move_index) do
480 move_index[i].pos = vector.add(move_index[i].pos,dir)
481 minetest.set_node(move_index[i].pos,move_index[i])
482 minetest.check_for_falling(move_index[i].pos)
483 sticky_push_objects(move_index[i].pos,dir)
489 --this is the logic of the piston
492 local piston_location
494 local function sticky_actuator_arm_function(pos)
495 --this is where the piston activates
496 facedir = minetest.get_node(pos).param2
497 dir = minetest.facedir_to_dir(facedir)
498 piston_location = vector.add(pos,dir)
499 worked = sticky_push_nodes(pos,dir)
500 local node = minetest.get_node(vector.add(pos,dir)).name
502 if worked == true then
504 minetest.sound_play("piston", {pos=pos,pitch=math.random(85,100)/100})
505 minetest.set_node(piston_location,{name="redstone:sticky_actuator",param2=facedir})
506 minetest.swap_node(pos,{name="redstone:sticky_piston_on",param2=facedir})
508 redstone.inject(pos,{
509 name = "redstone:sticky_piston_on",
519 ██████╗ ███████╗███████╗
520 ██╔═══██╗██╔════╝██╔════╝
528 minetest.register_node("redstone:sticky_piston_off", {
529 description = "Sticky Piston",
530 tiles = {"redstone_piston.png","redstone_piston.png^[transformR180","redstone_piston.png^[transformR270","redstone_piston.png^[transformR90","sticky_piston.png","stone.png"},
531 paramtype2 = "facedir",
532 groups = {stone = 1, hard = 1, pickaxe = 1, hand = 4,pathable = 1,redstone_activation=1},
533 sounds = main.stoneSound(),
534 drop = "redstone:sticky_piston_off",
536 sunlight_propagates = true,
537 on_construct = function(pos)
538 redstone.inject(pos,{
539 name = "redstone:sticky_piston_off",
544 on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
545 local look = clicker:get_look_dir()
546 look = vector.multiply(look,-1)
547 local dir = minetest.dir_to_facedir(look, true)
548 minetest.swap_node(pos,{name="redstone:sticky_piston_off",param2=dir})
551 --reverse the direction to face the player
552 after_place_node = function(pos, placer, itemstack, pointed_thing)
553 local look = placer:get_look_dir()
554 look = vector.multiply(look,-1)
555 local dir = minetest.dir_to_facedir(look, true)
556 minetest.swap_node(pos,{name="redstone:sticky_piston_off",param2=dir})
558 after_destruct = function(pos, oldnode)
559 redstone.inject(pos,nil)
564 redstone.register_activator({
565 name = "redstone:sticky_piston_off",
566 activate = function(pos)
567 minetest.after(0,function()
568 sticky_actuator_arm_function(pos)
573 minetest.register_lbm({
574 name = "redstone:sticky_piston_off",
575 nodenames = {"redstone:sticky_piston_off"},
576 run_at_every_load = true,
577 action = function(pos)
578 redstone.inject(pos,{
579 name = "redstone:sticky_piston_off",
582 --redstone needs to warm up
583 minetest.after(0,function()
599 local function sticky_piston_pull_nodes(pos,dir)
600 local move_index = {}
601 local index_pos = vector.add(pos,dir)
603 local node = minetest.get_node(index_pos)
604 local param2 = node.param2
605 local def = minetest.registered_nodes[node.name]
606 local name = node.name
607 local pull = ((excluded_mods[def.mod_origin] ~= true) and (excluded_nodes[name] ~= true))
608 --if it can be pulled pull it
609 if pull and name ~= "air" then
610 minetest.remove_node(index_pos)
611 minetest.set_node(pos,{name=name,param2=param2})
612 minetest.check_for_falling(index_pos)
619 minetest.register_node("redstone:sticky_piston_on", {
620 description = "Sticky Piston",
621 tiles = {"redstone_piston.png","redstone_piston.png^[transformR180","redstone_piston.png^[transformR270","redstone_piston.png^[transformR90","stone.png","stone.png"},
622 drawtype = "nodebox",
624 paramtype2 = "facedir",
625 groups = {stone = 1, hard = 1, pickaxe = 1, hand = 4,pathable = 1,redstone_activation=1},
626 sounds = main.stoneSound(),
627 drop = "redstone:sticky_piston_off",
631 --left front bottom right back top
632 {-0.5, -0.5, -0.5, 0.5, 0.5, 3/16},
635 after_destruct = function(pos, oldnode)
636 local facedir = oldnode.param2
637 local dir = minetest.facedir_to_dir(facedir)
638 local piston_location = vector.add(pos,dir)
639 minetest.remove_node(piston_location)
640 redstone.inject(pos,nil)
644 minetest.register_lbm({
645 name = "redstone:sticky_piston_on",
646 nodenames = {"redstone:sticky_piston_on"},
647 run_at_every_load = true,
648 action = function(pos)
649 redstone.inject(pos,{
650 name = "redstone:sticky_piston_on",
653 --redstone needs to warm up
654 minetest.after(0,function()
660 redstone.register_activator({
661 name = "redstone:sticky_piston_on",
662 deactivate = function(pos)
663 --this is where the piston deactivates
664 local facedir = minetest.get_node(pos).param2
665 local dir = minetest.facedir_to_dir(facedir)
666 local piston_location = vector.add(pos,dir)
668 minetest.remove_node(piston_location)
670 sticky_piston_pull_nodes(piston_location,dir)
672 minetest.check_for_falling(piston_location)
674 minetest.swap_node(pos,{name="redstone:sticky_piston_off",param2=facedir})
676 minetest.sound_play("piston", {pos=pos,pitch=math.random(85,100)/100})
677 redstone.inject(pos,{
678 name = "redstone:sticky_piston_off",
686 █████╗ ██████╗ ███╗ ███╗
687 ██╔══██╗██╔══██╗████╗ ████║
688 ███████║██████╔╝██╔████╔██║
689 ██╔══██║██╔══██╗██║╚██╔╝██║
690 ██║ ██║██║ ██║██║ ╚═╝ ██║
691 ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝
696 minetest.register_node("redstone:sticky_actuator", {
697 description = "Piston Actuator",
698 tiles = {"wood.png","wood.png","wood.png","wood.png","sticky_piston.png","wood.png"},
699 drawtype = "nodebox",
701 paramtype2 = "facedir",
702 groups = {stone = 1, hard = 1, pickaxe = 1, hand = 4,pathable = 1},
703 sounds = main.stoneSound(),
704 drop = "redstone:piston_off",
708 --left front bottom right back top
709 {-0.5, -0.5, 0.2, 0.5, 0.5, 0.5}, --mover
710 {-0.15, -0.15, -0.9, 0.15, 0.15, 0.5}, --actuator
713 after_destruct = function(pos, oldnode)
714 local facedir = oldnode.param2
715 local dir = minetest.facedir_to_dir(facedir)
716 dir = vector.multiply(dir,-1)
717 local piston_location = vector.add(pos,dir)
718 minetest.remove_node(piston_location)