1144 lines
48 KiB
Lua
1144 lines
48 KiB
Lua
------------------------------------------------------------------------------------------------------------------------------------
|
|
-- BASIC MACHINES MOD by rnd
|
|
-- mod with basic simple automatization for minetest. No background processing, just one abm with 5s timer, no other lag causing background processing.
|
|
------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
-- MOVER: universal moving machine, requires coal in nearby chest to operate
|
|
-- can take item from chest and place it in chest or as a node outside at ranges -5,+5
|
|
-- it can be used for filtering by setting "filter". if set to "object" it will teleport all objects at start location.
|
|
-- if set to "drop" it will drop node at target location, if set to "dig" it will dig out nodes and return appropriate drops.
|
|
|
|
-- input is: where to take and where to put
|
|
-- to operate mese power is needed
|
|
|
|
-- KEYPAD: can serve as a button to activate machines ( partially mesecons compatible ). Can be password protected. Can serve as a
|
|
-- replacement for mesecons blinky plant, limited to max 100 operations.
|
|
-- As a simple example it can be used to open doors, which close automatically after 5 seconds.
|
|
|
|
local punchset = {};
|
|
|
|
local max_range = 10; -- machines range of operation
|
|
local machines_timer = 5 -- timestep
|
|
local machines_TTL = 4; -- time to live for signals
|
|
|
|
|
|
MOVER_FUEL_STORAGE_CAPACITY = 5; -- how many operations from one coal lump - base unit
|
|
|
|
minetest.register_node("basic_machines:mover", {
|
|
description = "Mover",
|
|
tiles = {"compass_top.png","default_furnace_top.png"},
|
|
groups = {oddly_breakable_by_hand=2,mesecon_effector_on = 1},
|
|
sounds = default.node_sound_wood_defaults(),
|
|
after_place_node = function(pos, placer)
|
|
local meta = minetest.env:get_meta(pos)
|
|
meta:set_string("infotext", "Mover block. Right click to set it up. Or set positions by punching it.")
|
|
meta:set_string("owner", placer:get_player_name()); meta:set_int("public",0);
|
|
meta:set_int("x0",0);meta:set_int("y0",-1);meta:set_int("z0",0); -- source1
|
|
meta:set_int("x1",0);meta:set_int("y1",-1);meta:set_int("z1",0); -- source2: defines cube
|
|
meta:set_int("pc",0); meta:set_int("dim",1);-- current cube position and dimensions
|
|
meta:set_int("x2",0);meta:set_int("y2",1);meta:set_int("z2",0);
|
|
meta:set_float("fuel",0)
|
|
meta:set_string("prefer", "");
|
|
local inv = meta:get_inventory();inv:set_size("mode", 5*1)
|
|
inv:set_stack("mode", 1, ItemStack("default:coal_lump"))
|
|
|
|
local name = placer:get_player_name(); punchset[name].state = 0
|
|
end,
|
|
|
|
on_rightclick = function(pos, node, player, itemstack, pointed_thing)
|
|
local meta = minetest.get_meta(pos);
|
|
local privs = minetest.get_player_privs(player:get_player_name());
|
|
if meta:get_string("owner")~=player:get_player_name() and not privs.privs then return end -- only owner can set up mover
|
|
|
|
local x0,y0,z0,x1,y1,z1,x2,y2,z2,prefer,mode;
|
|
x0=meta:get_int("x0");y0=meta:get_int("y0");z0=meta:get_int("z0");
|
|
x1=meta:get_int("x1");y1=meta:get_int("y1");z1=meta:get_int("z1");
|
|
x2=meta:get_int("x2");y2=meta:get_int("y2");z2=meta:get_int("z2");
|
|
|
|
machines.pos1[player:get_player_name()] = {x=pos.x+x1,y=pos.y+y1,z=pos.z+z1};
|
|
machines.mark_pos1(player:get_player_name()) -- mark pos1
|
|
machines.pos2[player:get_player_name()] = {x=pos.x+x2,y=pos.y+y2,z=pos.z+z2};
|
|
machines.mark_pos2(player:get_player_name()) -- mark pos2
|
|
|
|
prefer = meta:get_string("prefer");mode = meta:get_string("mode");
|
|
local list_name = "nodemeta:"..pos.x..','..pos.y..','..pos.z
|
|
local form =
|
|
"size[5,5.5]" .. -- width, height
|
|
--"size[6,10]" .. -- width, height
|
|
"field[0.25,0.5;1,1;x0;source1;"..x0.."] field[1.25,0.5;1,1;y0;;"..y0.."] field[2.25,0.5;1,1;z0;;"..z0.."]"..
|
|
"field[0.25,1.5;1,1;x1;source2;"..x1.."] field[1.25,1.5;1,1;y1;;"..y1.."] field[2.25,1.5;1,1;z1;;"..z1.."]"..
|
|
"field[0.25,2.5;1,1;x2;Target;"..x2.."] field[1.25,2.5;1,1;y2;;"..y2.."] field[2.25,2.5;1,1;z2;;"..z2.."]"..
|
|
"button_exit[3,3.25;1,1;OK;OK] field[0.25,3.5;3,1;prefer;filter only block;"..prefer.."]"..
|
|
"button[3,2.25;1,1;help;help]"..
|
|
"label[0.,4.0;MODE: normal,dig,drop,reverse,object]"..
|
|
"list["..list_name..";mode;0.,4.5;6,1;]"--..
|
|
--"field[0.25,4.5;2,1;mode;mode;"..mode.."]";
|
|
minetest.show_formspec(player:get_player_name(), "basic_machines:mover_"..minetest.pos_to_string(pos), form)
|
|
end,
|
|
|
|
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
|
|
return 0
|
|
end,
|
|
|
|
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
|
|
return 0
|
|
end,
|
|
|
|
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
|
--minetest.chat_send_all("mover inventory: moved from pos ".. from_index .. " to pos " .. to_index )
|
|
local meta = minetest.get_meta(pos);
|
|
local mode = "";
|
|
if to_index == 1 then
|
|
meta:set_string("mode","")
|
|
elseif to_index==2 then mode = "dig"
|
|
elseif to_index==3 then mode = "drop"
|
|
elseif to_index==4 then mode = "reverse"
|
|
elseif to_index==5 then mode = "object"
|
|
end
|
|
meta:set_string("mode",mode)
|
|
if mode == "" then mode = "normal" end; minetest.chat_send_player(player:get_player_name(), "MOVER: Mode of operation set to: "..mode)
|
|
return count
|
|
end,
|
|
|
|
mesecons = {effector = {
|
|
action_on = function (pos, node,ttl)
|
|
|
|
if type(ttl)~="number" then ttl = 1 end
|
|
local meta = minetest.get_meta(pos);
|
|
local fuel = meta:get_float("fuel");
|
|
|
|
--minetest.chat_send_all("mover mesecons: runnning with pos " .. pos.x .. " " .. pos.y .. " " .. pos.z)
|
|
|
|
local x0,y0,z0,x1,y1,z1;
|
|
x0=meta:get_int("x0");y0=meta:get_int("y0");z0=meta:get_int("z0");
|
|
local pos1 = {x=x0+pos.x,y=y0+pos.y,z=z0+pos.z}; -- where to take from
|
|
local pos2 = {x=meta:get_int("x2")+pos.x,y=meta:get_int("y2")+pos.y,z=meta:get_int("z2")+pos.z}; -- where to put
|
|
|
|
local pc = meta:get_int("pc"); local dim = meta:get_int("dim"); pc = (pc+1) % dim;meta:set_int("pc",pc) -- cycle position
|
|
x1=meta:get_int("x1")-x0+1;y1=meta:get_int("y1")-y0+1;z1=meta:get_int("z1")-z0+1; -- get dimensions
|
|
|
|
--pc = z*a*b+x*b+y, from x,y,z to pc
|
|
-- set current input position
|
|
pos1.y = y0 + (pc % y1); pc = (pc - (pc % y1))/y1;
|
|
pos1.x = x0 + (pc % x1); pc = (pc - (pc % x1))/x1;
|
|
pos1.z = z0 + pc;
|
|
pos1.x = pos.x+pos1.x;pos1.y = pos.y+pos1.y;pos1.z = pos.z+pos1.z;
|
|
|
|
if fuel<=0 then -- needs fuel to operate, find nearby open chest with fuel within radius 1
|
|
|
|
local found_fuel = nil;
|
|
|
|
local r = 1;local positions = minetest.find_nodes_in_area( --find furnace with fuel
|
|
{x=pos.x-r, y=pos.y-r, z=pos.z-r},
|
|
{x=pos.x+r, y=pos.y+r, z=pos.z+r},
|
|
"default:chest_locked")
|
|
local fpos = nil;
|
|
for _, p in ipairs(positions) do
|
|
-- dont take coal from source or target location
|
|
if (p.x ~= pos1.x or p.y~=pos1.y or p.z ~= pos1.z) and (p.x ~= pos2.x or p.y~=pos2.y or p.z ~= pos2.z) then
|
|
fpos = p;
|
|
end
|
|
end
|
|
|
|
if not fpos then return end -- no chest found
|
|
local cmeta = minetest.get_meta(fpos);
|
|
local inv = cmeta:get_inventory();
|
|
--fuels and their caloric value: 1 = 5 uses
|
|
local fuels = {["default:coal_lump"]=1,["default:cactus"]=0.75,["default:coalblock"]=10,["default:lava_source"]=40};
|
|
local stack;
|
|
for i,v in pairs(fuels) do
|
|
stack = ItemStack({name=i})
|
|
if inv:contains_item("main", stack) then found_fuel = v break end
|
|
end
|
|
-- check for this fuel
|
|
if found_fuel~=nil then
|
|
--minetest.chat_send_all(" refueled ")
|
|
inv:remove_item("main", stack)
|
|
meta:set_float("fuel", fuel+MOVER_FUEL_STORAGE_CAPACITY*found_fuel);
|
|
fuel = fuel+MOVER_FUEL_STORAGE_CAPACITY*found_fuel;
|
|
meta:set_string("infotext", "Mover block refueled. Fuel "..MOVER_FUEL_STORAGE_CAPACITY);
|
|
else meta:set_string("infotext", "Mover block. Out of fuel. Put fuel chest so that it touches mover.");return
|
|
end
|
|
--check fuel
|
|
if fuel == 0 then return end
|
|
end
|
|
|
|
local owner = meta:get_string("owner");
|
|
|
|
-- check protections
|
|
if minetest.is_protected(pos1, owner) or minetest.is_protected(pos2, owner) then
|
|
meta:set_float("fuel", -1);
|
|
meta:set_string("infotext", "Mover block. Protection fail. Deactivated.")
|
|
return end
|
|
|
|
local prefer = meta:get_string("prefer"); local mode = meta:get_string("mode");
|
|
|
|
if mode == "reverse" then -- reverse pos1, pos2
|
|
local post = {x=pos1.x,y=pos1.y,z=pos1.z};
|
|
pos1 = {x=pos2.x,y=pos2.y,z=pos2.z};
|
|
pos2 = {x=post.x,y=post.y,z=post.z};
|
|
end
|
|
local node1 = minetest.get_node(pos1);local node2 = minetest.get_node(pos2);
|
|
|
|
if mode == "object" then -- teleport objects, for free
|
|
for _,obj in pairs(minetest.get_objects_inside_radius(pos1, 2)) do
|
|
obj:moveto(pos2, false)
|
|
end
|
|
minetest.sound_play("transporter", {pos=pos2,gain=1.0,max_hear_distance = 32,})
|
|
--meta:set_float("fuel", fuel - 1);
|
|
return
|
|
end
|
|
|
|
local dig=false; if mode == "dig" then dig = true; end -- digs at target location
|
|
local drop = false; if mode == "drop" then drop = true; end -- drops node instead of placing it
|
|
|
|
-- decide what to do if source or target are chests
|
|
local source_chest=false; if string.find(node1.name,"default:chest") then source_chest=true end
|
|
if node1.name == "air" then return end -- nothing to move
|
|
|
|
local target_chest = false
|
|
if node2.name == "default:chest" or node2.name == "default:chest_locked" then
|
|
target_chest = true
|
|
end
|
|
if not target_chest and minetest.get_node(pos2).name ~= "air" then return end -- do nothing if target nonempty and not chest
|
|
|
|
-- filtering
|
|
if prefer~="" then -- prefered node set
|
|
if prefer~=node1.name and not source_chest then return end -- only take prefered node or from chests
|
|
if source_chest then -- take stuff from chest
|
|
--minetest.chat_send_all(" source chest detected")
|
|
local cmeta = minetest.get_meta(pos1);
|
|
local inv = cmeta:get_inventory();
|
|
local stack = ItemStack(prefer)
|
|
if inv:contains_item("main", stack) then
|
|
inv:remove_item("main", stack);
|
|
else return
|
|
end
|
|
end
|
|
node1 = {}; node1.name = prefer;
|
|
end
|
|
|
|
if source_chest and prefer == "" then return end -- doesnt know what to take out of chest
|
|
--minetest.chat_send_all(" moving ")
|
|
|
|
-- if target chest put in chest
|
|
if target_chest then
|
|
local cmeta = minetest.get_meta(pos2);
|
|
local inv = cmeta:get_inventory();
|
|
|
|
-- dig tree or cactus
|
|
local count = 0;-- check for cactus or tree
|
|
local dig_up = false;
|
|
if dig then
|
|
-- define which nodes are dug up completely, like a tree
|
|
local dig_up_table = {["default:cactus"]=true,["default:tree"]=true,["default:jungletree"]=true,["default:papyrus"]=true};
|
|
|
|
if not source_chest and dig_up_table[node1.name] then dig_up = true end
|
|
|
|
if dig_up == true then -- dig up to height 10, break sooner if needed
|
|
for i=0,10 do
|
|
local pos3 = {x=pos1.x,y=pos1.y+i,z=pos1.z};
|
|
local dname= minetest.get_node(pos3).name;
|
|
if dname ~=node1.name then break end
|
|
minetest.set_node(pos3,{name="air"}); count = count+1;
|
|
end
|
|
end
|
|
|
|
-- read what to drop, if none just keep original node
|
|
local table = minetest.registered_items[node1.name];
|
|
if table~=nil then
|
|
if table.drop~= nil and table.drop~="" then
|
|
node1={}; node1.name = table.drop;
|
|
end
|
|
end
|
|
end
|
|
|
|
local stack = ItemStack(node1.name)
|
|
|
|
if dig_up then
|
|
stack = ItemStack(node1.name .. " " .. count) -- if tree or cactus was digged up
|
|
end
|
|
|
|
if inv:room_for_item("main", stack) then
|
|
inv:add_item("main", stack);
|
|
end
|
|
end
|
|
|
|
minetest.sound_play("transporter", {pos=pos2,gain=1.0,max_hear_distance = 32,})
|
|
if not(target_chest and source_chest) then -- chest to chest transport is free
|
|
fuel = fuel -1; meta:set_float("fuel", fuel); -- burn fuel
|
|
end
|
|
meta:set_string("infotext", "Mover block. Fuel "..fuel);
|
|
|
|
|
|
if not target_chest then
|
|
if not drop then minetest.set_node(pos2, {name = node1.name}); end
|
|
if drop then
|
|
local stack = ItemStack(node1.name);minetest.add_item(pos2,stack) -- drops it
|
|
end
|
|
end
|
|
if not source_chest then
|
|
if dig then nodeupdate(pos1) end
|
|
minetest.set_node(pos1, {name = "air"});
|
|
end
|
|
end
|
|
}
|
|
}
|
|
})
|
|
|
|
-- KEYPAD
|
|
|
|
local function use_keypad(pos,ttl) -- position, time to live ( how many times can signal travel before vanishing to prevent infinite recursion )
|
|
|
|
local meta = minetest.get_meta(pos);
|
|
local name = meta:get_string("owner");
|
|
if minetest.is_protected(pos,name) then meta:set_string("infotext", "Protection fail. reset."); meta:set_int("count",0) end
|
|
local count = meta:get_int("count") or 0;
|
|
|
|
if count<=0 and ttl<0 then return end;
|
|
|
|
count = count - 1; meta:set_int("count",count);
|
|
|
|
if count>=0 then
|
|
meta:set_string("infotext", "Keypad operation: ".. count .." cycles left")
|
|
else
|
|
meta:set_string("infotext", "Keypad operation: activation ".. -count)
|
|
end
|
|
|
|
if count>0 then -- only trigger repeat if count on
|
|
minetest.after(machines_timer, function() use_keypad(pos,machines_TTL) end ) -- repeat operation as many times as set with "iter"
|
|
end
|
|
|
|
|
|
local x0,y0,z0,mode;
|
|
x0=meta:get_int("x0");y0=meta:get_int("y0");z0=meta:get_int("z0");
|
|
x0=pos.x+x0;y0=pos.y+y0;z0=pos.z+z0;
|
|
mode = meta:get_int("mode");
|
|
--minetest.chat_send_all("KEYPAD USED. TARGET ".. x0 .. " " .. y0 .. " " .. z0);
|
|
|
|
-- pass the signal on to target, depending on mode
|
|
|
|
local tpos = {x=x0,y=y0,z=z0};
|
|
local node = minetest.get_node(tpos);if not node.name then return end -- error
|
|
|
|
local table = minetest.registered_nodes[node.name];
|
|
if not table then return end -- error
|
|
if not table.mesecons then return end -- error
|
|
if not table.mesecons.effector then return end -- error
|
|
local effector=table.mesecons.effector;
|
|
-- pass the signal on to target
|
|
if mode == 1 then
|
|
if not effector.action_on then return end
|
|
effector.action_on(tpos,node,ttl-1); -- run
|
|
else
|
|
if not effector.action_off then return end
|
|
effector.action_off(tpos,node,ttl-1); -- run
|
|
end
|
|
--minetest.chat_send_all("MESECONS RUN")
|
|
|
|
end
|
|
|
|
local function check_keypad(pos,name,ttl) -- called only when manually activated via punch
|
|
local meta = minetest.get_meta(pos);
|
|
local pass = meta:get_string("pass");
|
|
if pass == "" then
|
|
meta:set_int("count",meta:get_int("iter")); use_keypad(pos,machines_TTL) -- time to live is 3 when punched
|
|
return
|
|
end
|
|
if name == "" then return end
|
|
pass = ""
|
|
local form =
|
|
"size[3,1]" .. -- width, height
|
|
"button[0.,0.5;1,1;OK;OK] field[0.25,0.25;3,1;pass;Enter Password: ;".."".."]";
|
|
minetest.show_formspec(name, "basic_machines:check_keypad_"..minetest.pos_to_string(pos), form)
|
|
|
|
end
|
|
|
|
minetest.register_node("basic_machines:keypad", {
|
|
description = "Keypad",
|
|
tiles = {"keypad.png"},
|
|
groups = {oddly_breakable_by_hand=2},
|
|
sounds = default.node_sound_wood_defaults(),
|
|
after_place_node = function(pos, placer)
|
|
local meta = minetest.env:get_meta(pos)
|
|
meta:set_string("infotext", "Keypad. Right click to set it up or punch it.")
|
|
meta:set_string("owner", placer:get_player_name()); meta:set_int("public",1);
|
|
meta:set_int("x0",0);meta:set_int("y0",0);meta:set_int("z0",0); -- target
|
|
|
|
meta:set_string("pass", "");meta:set_int("mode",1); -- pasword, mode of operation
|
|
meta:set_int("iter",1);meta:set_int("count",0); -- max repeats, repeat count
|
|
local name = placer:get_player_name();punchset[name] = {};punchset[name].state = 0
|
|
end,
|
|
|
|
mesecons = {effector = {
|
|
action_on = function (pos, node,ttl)
|
|
if type(ttl)~="number" then ttl = 1 end
|
|
if ttl<0 then return end -- machines_TTL prevents infinite recursion
|
|
use_keypad(pos,ttl-1);
|
|
end
|
|
}
|
|
},
|
|
on_rightclick = function(pos, node, player, itemstack, pointed_thing)
|
|
local meta = minetest.get_meta(pos);
|
|
local privs = minetest.get_player_privs(player:get_player_name());
|
|
if meta:get_string("owner")~= player:get_player_name() and not privs.privs then return end -- only owner can setup keypad
|
|
local x0,y0,z0,x1,y1,z1,pass,iter,mode;
|
|
x0=meta:get_int("x0");y0=meta:get_int("y0");z0=meta:get_int("z0");iter=meta:get_int("iter") or 1;
|
|
mode = meta:get_int("mode") or 1;
|
|
|
|
machines.pos1[player:get_player_name()] = {x=pos.x+x0,y=pos.y+y0,z=pos.z+z0};machines.mark_pos1(player:get_player_name()) -- mark pos1
|
|
|
|
pass = meta:get_string("pass");
|
|
local form =
|
|
"size[3,2.75]" .. -- width, height
|
|
"field[0.25,0.5;1,1;x0;target;"..x0.."] field[1.25,0.5;1,1;y0;;"..y0.."] field[2.25,0.5;1,1;z0;;"..z0.."]"..
|
|
"button_exit[0.,2.25;1,1;OK;OK] field[0.25,1.5;2,1;pass;Password: ;"..pass.."]" .. "field[1.25,2.5;2,1;iter;Repeat;".. iter .."]"..
|
|
"field[2.25,1.5;1,1;mode;ON/OFF: ;"..mode.."]"
|
|
minetest.show_formspec(player:get_player_name(), "basic_machines:keypad_"..minetest.pos_to_string(pos), form)
|
|
end
|
|
})
|
|
|
|
|
|
|
|
-- DETECTOR
|
|
|
|
minetest.register_node("basic_machines:detector", {
|
|
description = "Detector",
|
|
tiles = {"detector.png"},
|
|
groups = {oddly_breakable_by_hand=2},
|
|
sounds = default.node_sound_wood_defaults(),
|
|
after_place_node = function(pos, placer)
|
|
local meta = minetest.env:get_meta(pos)
|
|
meta:set_string("infotext", "Detector. Right click/punch to set it up.")
|
|
meta:set_string("owner", placer:get_player_name()); meta:set_int("public",0);
|
|
meta:set_int("x1",0);meta:set_int("y1",0);meta:set_int("z0",0); -- source: read
|
|
meta:set_int("x2",0);meta:set_int("y2",0);meta:set_int("z2",0); -- target: activate
|
|
meta:set_int("r",0)
|
|
meta:set_string("node","");meta:set_int("NOT",0);meta:set_string("mode","node");
|
|
meta:set_int("public",0);
|
|
local inv = meta:get_inventory();inv:set_size("mode_select", 2*1)
|
|
inv:set_stack("mode_select", 1, ItemStack("default:coal_lump"))
|
|
local name = placer:get_player_name();punchset[name] = {}; punchset[name].node = ""; punchset[name].state = 0
|
|
end,
|
|
|
|
mesecons = {effector = {
|
|
action_on = function (pos, node,ttl)
|
|
if type(ttl)~="number" then ttl = 1 end
|
|
if ttl<0 then return end -- prevent infinite recursion
|
|
local meta = minetest.get_meta(pos);
|
|
-- not yet defined ... ???
|
|
end
|
|
}
|
|
},
|
|
on_rightclick = function(pos, node, player, itemstack, pointed_thing)
|
|
local meta = minetest.get_meta(pos);
|
|
local privs = minetest.get_player_privs(player:get_player_name());
|
|
if meta:get_string("owner")~= player:get_player_name() and not privs.privs then return end -- only owner can setup keypad
|
|
local x0,y0,z0,x1,y1,z1,r,node,NOT;
|
|
x0=meta:get_int("x0");y0=meta:get_int("y0");z0=meta:get_int("z0");
|
|
x1=meta:get_int("x1");y1=meta:get_int("y1");z1=meta:get_int("z1");r=meta:get_int("r");
|
|
|
|
machines.pos1[player:get_player_name()] = {x=pos.x+x0,y=pos.y+y0,z=pos.z+z0};machines.mark_pos1(player:get_player_name()) -- mark pos1
|
|
machines.pos2[player:get_player_name()] = {x=pos.x+x1,y=pos.y+y1,z=pos.z+z1};machines.mark_pos2(player:get_player_name()) -- mark pos2
|
|
|
|
node=meta:get_string("node") or "";
|
|
NOT=meta:get_int("NOT");
|
|
local list_name = "nodemeta:"..pos.x..','..pos.y..','..pos.z
|
|
local form =
|
|
"size[4,4.25]" .. -- width, height
|
|
"field[0.25,0.5;1,1;x0;source;"..x0.."] field[1.25,0.5;1,1;y0;;"..y0.."] field[2.25,0.5;1,1;z0;;"..z0.."]"..
|
|
"field[0.25,1.5;1,1;x1;target;"..x1.."] field[1.25,1.5;1,1;y1;;"..y1.."] field[2.25,1.5;1,1;z1;;"..z1.."]"..
|
|
"button[3.,3.25;1,1;OK;OK] field[0.25,2.5;2,1;node;Node/player: ;"..node.."]".."field[3.25,1.5;1,1;r;radius;"..r.."]"..
|
|
"button[3.,0.25;1,1;help;help]"..
|
|
"label[0.,3.0;MODE: node,player]".. "list["..list_name..";mode_select;0.,3.5;3,1;]"..
|
|
"field[3.25,2.5;1,1;NOT;NOT 0/1;"..NOT.."]"
|
|
|
|
minetest.show_formspec(player:get_player_name(), "basic_machines:detector_"..minetest.pos_to_string(pos), form)
|
|
end,
|
|
|
|
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
|
|
return 0
|
|
end,
|
|
|
|
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
|
|
return 0
|
|
end,
|
|
|
|
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
|
--minetest.chat_send_all("mover inventory: moved from pos ".. from_index .. " to pos " .. to_index )
|
|
local meta = minetest.get_meta(pos);
|
|
local mode = "node";
|
|
if to_index == 2 then
|
|
mode = "player";
|
|
meta:set_int("r",math.max(meta:get_int("r"),1))
|
|
end
|
|
meta:set_string("mode",mode)
|
|
minetest.chat_send_player(player:get_player_name(), "DETECTOR: Mode of operation set to: "..mode)
|
|
return count
|
|
end,
|
|
|
|
})
|
|
|
|
|
|
minetest.register_abm({
|
|
nodenames = {"basic_machines:detector"},
|
|
neighbors = {""},
|
|
interval = machines_timer,
|
|
chance = 1,
|
|
action = function(pos, node, active_object_count, active_object_count_wider)
|
|
local meta = minetest.get_meta(pos);
|
|
local x0,y0,z0,x1,y1,z1,r,node,NOT,mode;
|
|
x0=meta:get_int("x0")+pos.x;y0=meta:get_int("y0")+pos.y;z0=meta:get_int("z0")+pos.z;
|
|
x1=meta:get_int("x1")+pos.x;y1=meta:get_int("y1")+pos.y;z1=meta:get_int("z1")+pos.z;
|
|
r = meta:get_int("r") or 0; NOT = meta:get_int("NOT")
|
|
node=meta:get_string("node") or ""; mode=meta:get_string("mode") or "";
|
|
|
|
local trigger = false
|
|
if mode == "node" then
|
|
local tnode = minetest.get_node({x=x0,y=y0,z=z0}).name; -- read node at source position
|
|
|
|
if node~="" and string.find(tnode,"default:chest") then -- it source is chest, look inside chest for items
|
|
local cmeta = minetest.get_meta({x=x0,y=y0,z=z0});
|
|
local inv = cmeta:get_inventory();
|
|
local stack = ItemStack(node)
|
|
if inv:contains_item("main", stack) then trigger = true end
|
|
else -- source not a chest
|
|
if (node=="" and tnode~="air") or node == tnode then trigger = true end
|
|
if r>0 and node~="" then
|
|
local found_node = minetest.find_node_near({x=x0, y=y0, z=z0}, r, {node})
|
|
if node ~= "" and found_node then trigger = true end
|
|
end
|
|
end
|
|
if NOT == 1 then trigger = not trigger end
|
|
else
|
|
local objects = minetest.get_objects_inside_radius({x=x0,y=y0,z=z0}, r)
|
|
for _,obj in pairs(objects) do
|
|
if obj:is_player() and (node=="" or obj:get_player_name()==node) then trigger = true break end
|
|
end
|
|
if NOT == 1 then trigger = not trigger end
|
|
end
|
|
|
|
local node = minetest.get_node({x=x1,y=y1,z=z1});if not node.name then return end -- error
|
|
local table = minetest.registered_nodes[node.name];
|
|
if not table then return end -- error
|
|
if not table.mesecons then return end -- error
|
|
if not table.mesecons.effector then return end -- error
|
|
local effector=table.mesecons.effector;
|
|
|
|
if trigger then -- activate target node if succesful
|
|
meta:set_string("infotext", "detector: on");
|
|
if not effector.action_on then return end
|
|
effector.action_on({x=x1,y=y1,z=z1},node,3); -- run
|
|
|
|
else
|
|
meta:set_string("infotext", "detector: idle");
|
|
if not effector.action_off then return end
|
|
effector.action_off({x=x1,y=y1,z=z1},node,3); -- run
|
|
end
|
|
|
|
end,
|
|
})
|
|
|
|
-- DISTRIBUTOR: spreads one signal to two outputs
|
|
|
|
minetest.register_node("basic_machines:distributor", {
|
|
description = "Distributor",
|
|
tiles = {"distributor.png"},
|
|
groups = {oddly_breakable_by_hand=2},
|
|
sounds = default.node_sound_wood_defaults(),
|
|
after_place_node = function(pos, placer)
|
|
local meta = minetest.env:get_meta(pos)
|
|
meta:set_string("infotext", "Distributor. Right click/punch to set it up.")
|
|
meta:set_string("owner", placer:get_player_name()); meta:set_int("public",0);
|
|
meta:set_int("x1",0);meta:set_int("y1",0);meta:set_int("z0",0);meta:set_int("active1",1) -- target1
|
|
meta:set_int("x2",0);meta:set_int("y2",0);meta:set_int("z2",0);meta:set_int("active2",0) -- target2
|
|
meta:set_int("public",0); -- can other ppl set it up?
|
|
local name = placer:get_player_name();punchset[name] = {}; punchset[name].node = ""; punchset[name].state = 0
|
|
end,
|
|
|
|
mesecons = {effector = {
|
|
action_on = function (pos, node,ttl)
|
|
if type(ttl)~="number" then ttl = 1 end
|
|
if not(ttl>0) then return end
|
|
local meta = minetest.get_meta(pos);
|
|
local x1,y1,z1,x2,y2,z2,active1,active2
|
|
x1=meta:get_int("x1")+pos.x;y1=meta:get_int("y1")+pos.y;z1=meta:get_int("z1")+pos.z;active1=meta:get_int("active1");
|
|
x2=meta:get_int("x2")+pos.x;y2=meta:get_int("y2")+pos.y;z2=meta:get_int("z2")+pos.z;active2=meta:get_int("active2");
|
|
|
|
local node, table
|
|
|
|
if active1~=0 then
|
|
node = minetest.get_node({x=x1,y=y1,z=z1});if not node.name then return end -- error
|
|
table = minetest.registered_nodes[node.name];
|
|
if not table then return end -- error
|
|
if not table.mesecons then return end -- error
|
|
if not table.mesecons.effector then return end -- error
|
|
local effector=table.mesecons.effector;
|
|
|
|
if active1 == 1 and effector.action_on then effector.action_on({x=x1,y=y1,z=z1},node,ttl-1);
|
|
elseif active1 == -1 and effector.action_off then effector.action_off({x=x1,y=y1,z=z1},node,ttl-1);
|
|
end
|
|
|
|
end
|
|
|
|
if active2~=0 then
|
|
node = minetest.get_node({x=x2,y=y2,z=z2});if not node.name then return end -- error
|
|
table = minetest.registered_nodes[node.name];
|
|
if not table then return end -- error
|
|
if not table.mesecons then return end -- error
|
|
if not table.mesecons.effector then return end -- error
|
|
local effector=table.mesecons.effector;
|
|
|
|
if active2 == 1 and effector.action_on then effector.action_on({x=x2,y=y2,z=z2},node,ttl-1);
|
|
elseif active2 == -1 and effector.action_off then effector.action_off({x=x2,y=y2,z=z2},node,ttl-1);
|
|
end
|
|
end
|
|
end,
|
|
|
|
action_off = function (pos, node,ttl)
|
|
|
|
if type(ttl)~="number" then ttl = 1 end
|
|
if ttl<0 then return end
|
|
local meta = minetest.get_meta(pos);
|
|
local x1,y1,z1,x2,y2,z2,active1,active2
|
|
x1=meta:get_int("x1")+pos.x;y1=meta:get_int("y1")+pos.y;z1=meta:get_int("z1")+pos.z;active1=meta:get_int("active1");
|
|
x2=meta:get_int("x2")+pos.x;y2=meta:get_int("y2")+pos.y;z2=meta:get_int("z2")+pos.z;active2=meta:get_int("active2");
|
|
|
|
local node, table
|
|
node = nil;
|
|
|
|
if active1~=0 then
|
|
node = minetest.get_node({x=x1,y=y1,z=z1});if not node.name then return end -- error
|
|
table = minetest.registered_nodes[node.name];
|
|
if not table then return end -- error
|
|
if not table.mesecons then return end -- error
|
|
if not table.mesecons.effector then return end -- error
|
|
local effector=table.mesecons.effector;
|
|
|
|
if active1 == 1 and effector.action_off then effector.action_off({x=x1,y=y1,z=z1},node,ttl-1);
|
|
elseif active1 == -1 and effector.action_on then effector.action_on({x=x1,y=y1,z=z1},node,ttl-1);
|
|
end
|
|
|
|
end
|
|
|
|
if active2~=0 then
|
|
node = minetest.get_node({x=x2,y=y2,z=z2});if not node.name then return end -- error
|
|
table = minetest.registered_nodes[node.name];
|
|
if not table then return end -- error
|
|
if not table.mesecons then return end -- error
|
|
if not table.mesecons.effector then return end -- error
|
|
local effector=table.mesecons.effector;
|
|
|
|
if active2 == 1 and effector.action_off then effector.action_off({x=x2,y=y2,z=z2},node,ttl-1);
|
|
elseif active2 == -1 and effector.action_on then effector.action_on({x=x2,y=y2,z=z2},node,ttl-1);
|
|
end
|
|
end
|
|
end
|
|
}
|
|
},
|
|
on_rightclick = function(pos, node, player, itemstack, pointed_thing)
|
|
local meta = minetest.get_meta(pos);
|
|
local privs = minetest.get_player_privs(player:get_player_name());
|
|
if meta:get_string("owner")~= player:get_player_name() and not privs.privs then return end -- only owner can setup keypad
|
|
local x1,y1,z1,x2,y2,z2,active1,active2
|
|
|
|
x1=meta:get_int("x1");y1=meta:get_int("y1");z1=meta:get_int("z1");active1=meta:get_int("active1");
|
|
x2=meta:get_int("x2");y2=meta:get_int("y2");z2=meta:get_int("z2");active2=meta:get_int("active2");
|
|
|
|
machines.pos1[player:get_player_name()] = {x=pos.x+x1,y=pos.y+y1,z=pos.z+z1};machines.mark_pos1(player:get_player_name()) -- mark pos1
|
|
machines.pos2[player:get_player_name()] = {x=pos.x+x2,y=pos.y+y2,z=pos.z+z2};machines.mark_pos2(player:get_player_name()) -- mark pos2
|
|
|
|
|
|
local list_name = "nodemeta:"..pos.x..','..pos.y..','..pos.z
|
|
local form =
|
|
"size[4,2.5]" .. -- width, height
|
|
"label[0,-0.25;target1: x y z, Active -1/0/1]"..
|
|
"field[0.25,0.5;1,1;x1;;"..x1.."] field[1.25,0.5;1,1;y1;;"..y1.."] field[2.25,0.5;1,1;z1;;"..z1.."] field [ 3.25,0.5;1,1;active1;;" .. active1 .. "]"..
|
|
"field[0.25,1.5;1,1;x2;target2;"..x2.."] field[1.25,1.5;1,1;y2;;"..y2.."] field[2.25,1.5;1,1;z2;;"..z2.."] field [ 3.25,1.5;1,1;active2;;" .. active2 .. "]"..
|
|
"button[3.,2;1,1;OK;OK]";
|
|
|
|
minetest.show_formspec(player:get_player_name(), "basic_machines:distributor_"..minetest.pos_to_string(pos), form)
|
|
end,
|
|
}
|
|
)
|
|
|
|
|
|
-- LIGHT
|
|
|
|
minetest.register_node("basic_machines:light_off", {
|
|
description = "Light off",
|
|
tiles = {"light_off.png"},
|
|
groups = {oddly_breakable_by_hand=2},
|
|
mesecons = {effector = {
|
|
action_on = function (pos, node,ttl)
|
|
if type(ttl)~="number" then ttl = 1 end
|
|
minetest.set_node(pos,{name = "basic_machines:light_on"});
|
|
end
|
|
}
|
|
},
|
|
})
|
|
|
|
|
|
minetest.register_node("basic_machines:light_on", {
|
|
description = "Light off",
|
|
tiles = {"light.png"},
|
|
groups = {oddly_breakable_by_hand=2},
|
|
light_source = LIGHT_MAX,
|
|
mesecons = {effector = {
|
|
action_off = function (pos, node,ttl)
|
|
minetest.set_node(pos,{name = "basic_machines:light_off"});
|
|
end
|
|
}
|
|
},
|
|
})
|
|
|
|
|
|
|
|
punchset.known_nodes = {["basic_machines:mover"]=true,["basic_machines:keypad"]=true,["basic_machines:detector"]=true,["basic_machines:distributor"]=true};
|
|
|
|
-- handles set up punches
|
|
minetest.register_on_punchnode(function(pos, node, puncher, pointed_thing)
|
|
|
|
local name = puncher:get_player_name(); if name==nil then return end
|
|
if punchset[name]== nil then -- set up punchstate
|
|
punchset[name] = {}
|
|
punchset[name].node = ""
|
|
punchset[name].pos1 = {x=0,y=0,z=0};punchset[name].pos2 = {x=0,y=0,z=0};punchset[name].pos = {x=0,y=0,z=0};
|
|
punchset[name].state = 0; -- 0 ready for punch, 1 ready for start position, 2 ready for end position
|
|
return
|
|
end
|
|
|
|
--minetest.chat_send_all("debug: PUNCH, state: " .. punchset[name].state .. " set node " .. punchset[name].node)
|
|
|
|
-- check for known node names in case of first punch
|
|
if punchset[name].state == 0 and not punchset.known_nodes[node.name] then return end
|
|
-- from now on only punches with mover/keypad/... or setup punches
|
|
|
|
if punchset.known_nodes[node.name] then -- check if owner of machine is punching or if machine public
|
|
local meta = minetest.get_meta(pos);
|
|
if not (meta:get_int("public") == 1) then
|
|
if meta:get_string("owner")~= name then return end
|
|
end
|
|
end
|
|
|
|
if node.name == "basic_machines:mover" then -- mover init code
|
|
if punchset[name].state == 0 then
|
|
-- if not puncher:get_player_control().sneak then
|
|
-- return
|
|
-- end
|
|
minetest.chat_send_player(name, "MOVER: Now punch starting and end position to set up mover.")
|
|
punchset[name].node = node.name;punchset[name].pos = {x=pos.x,y=pos.y,z=pos.z};
|
|
punchset[name].state = 1
|
|
return
|
|
end
|
|
end
|
|
|
|
if punchset[name].node == "basic_machines:mover" then -- mover code
|
|
if punchset[name].state == 1 then
|
|
|
|
if math.abs(punchset[name].pos.x - pos.x)>max_range or math.abs(punchset[name].pos.y - pos.y)>max_range or math.abs(punchset[name].pos.z - pos.z)>max_range then
|
|
minetest.chat_send_player(name, "MOVER: Punch closer to mover. reseting.")
|
|
punchset[name].state = 0; return
|
|
end
|
|
|
|
if punchset[name].pos.x==pos.x and punchset[name].pos.y==pos.y and punchset[name].pos.z==pos.z then
|
|
minetest.chat_send_player(name, "MOVER: Punch something else. aborting.")
|
|
punchset[name].state = 0;
|
|
return
|
|
end
|
|
|
|
punchset[name].pos1 = {x=pos.x,y=pos.y,z=pos.z};punchset[name].state = 2;
|
|
machines.pos1[name] = punchset[name].pos1;machines.mark_pos1(name) -- mark position
|
|
minetest.chat_send_player(name, "MOVER: Start position for mover set. Punch again to set end position.")
|
|
return
|
|
end
|
|
|
|
if punchset[name].state == 2 then
|
|
if punchset[name].node~="basic_machines:mover" then punchset[name].state = 0 return end
|
|
if math.abs(punchset[name].pos.x - pos.x)>max_range or math.abs(punchset[name].pos.y - pos.y)>max_range or math.abs(punchset[name].pos.z - pos.z)>max_range then
|
|
minetest.chat_send_player(name, "MOVER: Punch closer to mover. aborting.")
|
|
punchset[name].state = 0; return
|
|
end
|
|
|
|
punchset[name].pos2 = {x=pos.x,y=pos.y,z=pos.z}; punchset[name].state = 0;
|
|
machines.pos2[name] = punchset[name].pos2;machines.mark_pos2(name) -- mark pos2
|
|
|
|
minetest.chat_send_player(name, "MOVER: End position for mover set.")
|
|
local x = punchset[name].pos1.x-punchset[name].pos.x;
|
|
local y = punchset[name].pos1.y-punchset[name].pos.y;
|
|
local z = punchset[name].pos1.z-punchset[name].pos.z;
|
|
local meta = minetest.get_meta(punchset[name].pos);
|
|
meta:set_int("x0",x);meta:set_int("y0",y);meta:set_int("z0",z);
|
|
meta:set_int("x1",x);meta:set_int("y1",y);meta:set_int("z1",z);
|
|
x = punchset[name].pos2.x-punchset[name].pos.x;
|
|
y = punchset[name].pos2.y-punchset[name].pos.y;
|
|
z = punchset[name].pos2.z-punchset[name].pos.z;
|
|
meta:set_int("x2",x);meta:set_int("y2",y);meta:set_int("z2",z);
|
|
meta:set_int("pc",0); meta:set_int("dim",1);
|
|
return
|
|
end
|
|
end
|
|
|
|
-- KEYPAD
|
|
if node.name == "basic_machines:keypad" then -- keypad init/usage code
|
|
local meta = minetest.get_meta(pos);
|
|
if not (meta:get_int("x0")==0 and meta:get_int("y0")==0 and meta:get_int("z0")==0) then -- already configured
|
|
check_keypad(pos,name)-- not setup, just standard operation
|
|
else
|
|
if meta:get_string("owner")~= name then minetest.chat_send_player(name, "KEYPAD: Only owner can set up keypad.") return end
|
|
if punchset[name].state == 0 then
|
|
minetest.chat_send_player(name, "KEYPAD: Now punch the target block.")
|
|
punchset[name].node = node.name;punchset[name].pos = {x=pos.x,y=pos.y,z=pos.z};
|
|
punchset[name].state = 1
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
if punchset[name].node=="basic_machines:keypad" then -- keypad setup code
|
|
if punchset[name].state == 1 then
|
|
local meta = minetest.get_meta(punchset[name].pos);
|
|
local x = pos.x-punchset[name].pos.x;
|
|
local y = pos.y-punchset[name].pos.y;
|
|
local z = pos.z-punchset[name].pos.z;
|
|
if math.abs(x)>max_range or math.abs(y)>max_range or math.abs(z)>max_range then
|
|
minetest.chat_send_player(name, "KEYPAD: Punch closer to keypad. reseting.")
|
|
punchset[name].state = 0; return
|
|
end
|
|
|
|
machines.pos1[name] = pos;
|
|
machines.mark_pos1(name) -- mark pos1
|
|
|
|
meta:set_int("x0",x);meta:set_int("y0",y);meta:set_int("z0",z);
|
|
punchset[name].state = 0
|
|
minetest.chat_send_player(name, "KEYPAD: Keypad target set with coordinates " .. x .. " " .. y .. " " .. z)
|
|
meta:set_string("infotext", "Punch keypad to use it.");
|
|
return
|
|
end
|
|
end
|
|
|
|
-- DETECTOR "basic_machines:detector"
|
|
if node.name == "basic_machines:detector" then -- detector init code
|
|
local meta = minetest.get_meta(pos);
|
|
if meta:get_string("owner")~= name then minetest.chat_send_player(name, "DETECTOR: Only owner can set up detector.") return end
|
|
if punchset[name].state == 0 then
|
|
minetest.chat_send_player(name, "DETECTOR: Now punch the source block.")
|
|
punchset[name].node = node.name;
|
|
punchset[name].pos = {x=pos.x,y=pos.y,z=pos.z};
|
|
punchset[name].state = 1
|
|
return
|
|
end
|
|
end
|
|
|
|
if punchset[name].node == "basic_machines:detector" then
|
|
if punchset[name].state == 1 then
|
|
if math.abs(punchset[name].pos.x - pos.x)>max_range or math.abs(punchset[name].pos.y - pos.y)>max_range or math.abs(punchset[name].pos.z - pos.z)>max_range then
|
|
minetest.chat_send_player(name, "DETECTOR: Punch closer to detector. aborting.")
|
|
punchset[name].state = 0; return
|
|
end
|
|
minetest.chat_send_player(name, "DETECTOR: Now punch the target machine.")
|
|
punchset[name].pos1 = {x=pos.x,y=pos.y,z=pos.z};
|
|
machines.pos1[name] = pos;machines.mark_pos1(name) -- mark pos1
|
|
punchset[name].state = 2
|
|
return
|
|
end
|
|
|
|
if minetest.is_protected(pos,name) then
|
|
minetest.chat_send_player(name, "DETECTOR: Target position is protected. aborting.")
|
|
punchset[name].state = 0; return
|
|
end
|
|
|
|
if punchset[name].state == 2 then
|
|
if math.abs(punchset[name].pos.x - pos.x)>max_range or math.abs(punchset[name].pos.y - pos.y)>max_range or math.abs(punchset[name].pos.z - pos.z)>max_range then
|
|
minetest.chat_send_player(name, "DETECTOR: Punch closer to detector. aborting.")
|
|
punchset[name].state = 0; return
|
|
end
|
|
minetest.chat_send_player(name, "DETECTOR: Setup complete.")
|
|
machines.pos2[name] = pos;machines.mark_pos2(name) -- mark pos2
|
|
local x = punchset[name].pos1.x-punchset[name].pos.x;
|
|
local y = punchset[name].pos1.y-punchset[name].pos.y;
|
|
local z = punchset[name].pos1.z-punchset[name].pos.z;
|
|
local meta = minetest.get_meta(punchset[name].pos);
|
|
meta:set_int("x0",x);meta:set_int("y0",y);meta:set_int("z0",z);
|
|
x=pos.x-punchset[name].pos.x;y=pos.y-punchset[name].pos.y;z=pos.z-punchset[name].pos.z;
|
|
meta:set_int("x1",x);meta:set_int("y1",y);meta:set_int("z1",z);
|
|
punchset[name].state = 0
|
|
return
|
|
end
|
|
end
|
|
|
|
-- Distributor "basic_machines:distributor"
|
|
if node.name == "basic_machines:distributor" then -- distributor init code
|
|
local meta = minetest.get_meta(pos);
|
|
if meta:get_string("owner")~= name then minetest.chat_send_player(name, "DISTRIBUTOR: Only owner can set up distributor.") return end
|
|
if punchset[name].state == 0 then
|
|
minetest.chat_send_player(name, "DISTRIBUTOR: Now punch target1 machine.")
|
|
punchset[name].node = node.name;
|
|
punchset[name].pos = {x=pos.x,y=pos.y,z=pos.z};
|
|
punchset[name].state = 1
|
|
return
|
|
end
|
|
end
|
|
|
|
if punchset[name].node == "basic_machines:distributor" then
|
|
if punchset[name].state == 1 then
|
|
if math.abs(punchset[name].pos.x - pos.x)>max_range or math.abs(punchset[name].pos.y - pos.y)>max_range or math.abs(punchset[name].pos.z - pos.z)>max_range then
|
|
minetest.chat_send_player(name, "DISTRIBUTOR: Punch closer to distributor. aborting.")
|
|
punchset[name].state = 0; return
|
|
end
|
|
minetest.chat_send_player(name, "DISTRIBUTOR: Now punch target2 machine.")
|
|
punchset[name].pos1 = {x=pos.x,y=pos.y,z=pos.z};
|
|
machines.pos1[name] = pos;machines.mark_pos1(name) -- mark pos1
|
|
punchset[name].state = 2
|
|
return
|
|
end
|
|
|
|
if minetest.is_protected(pos,name) then
|
|
minetest.chat_send_player(name, "DISTRIBUTOR: Target position is protected. aborting.")
|
|
punchset[name].state = 0; return
|
|
end
|
|
|
|
if punchset[name].state == 2 then
|
|
if math.abs(punchset[name].pos.x - pos.x)>max_range or math.abs(punchset[name].pos.y - pos.y)>max_range or math.abs(punchset[name].pos.z - pos.z)>max_range then
|
|
minetest.chat_send_player(name, "DISTRIBUTOR: Punch closer to distributor. aborting.")
|
|
punchset[name].state = 0; return
|
|
end
|
|
minetest.chat_send_player(name, "DISTRIBUTOR: Setup complete.")
|
|
machines.pos2[name] = pos;machines.mark_pos2(name) -- mark pos2
|
|
local x = punchset[name].pos1.x-punchset[name].pos.x;
|
|
local y = punchset[name].pos1.y-punchset[name].pos.y;
|
|
local z = punchset[name].pos1.z-punchset[name].pos.z;
|
|
local meta = minetest.get_meta(punchset[name].pos);
|
|
meta:set_int("x1",x);meta:set_int("y1",y);meta:set_int("z1",z);
|
|
x=pos.x-punchset[name].pos.x;y=pos.y-punchset[name].pos.y;z=pos.z-punchset[name].pos.z;
|
|
meta:set_int("x2",x);meta:set_int("y2",y);meta:set_int("z2",z);
|
|
punchset[name].state = 0
|
|
return
|
|
end
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
end)
|
|
|
|
|
|
-- handles forms processing for all machines
|
|
minetest.register_on_player_receive_fields(function(player,formname,fields)
|
|
|
|
-- MOVER
|
|
local fname = "basic_machines:mover_"
|
|
if string.sub(formname,0,string.len(fname)) == fname then
|
|
local pos_s = string.sub(formname,string.len(fname)+1); local pos = minetest.string_to_pos(pos_s)
|
|
local name = player:get_player_name(); if name==nil then return end
|
|
local meta = minetest.get_meta(pos)
|
|
local privs = minetest.get_player_privs(name);
|
|
if (name ~= meta:get_string("owner") and not privs.privs) or not fields then return end -- only owner can interact
|
|
--minetest.chat_send_all("formname " .. formname .. " fields " .. dump(fields))
|
|
if fields.help == "help" then
|
|
local text = "SETUP: right click and define box where to dig from and where to put. Positions are defined by x y z coordinates (see top of mover). Mover has coordinates 0 0 0. If you prefer interactive setup "..
|
|
"punch the mover and then punch source and target node. Put chest with fuel right next to it. "..
|
|
"\n\nMODES of operation: normal ( just teleport), dig ( digs and gives you resulted node), drop "..
|
|
"( drops node on ground), reverse(takes from target position, places on source positions - good for planting a farm), object (teleportation of player and objects). "..
|
|
"\n\nBy setting 'filter only block' only selected nodes are moved. Activate it by keypad signal or mese signal (if mesecons mod) .";
|
|
local form = "size [5,5] textarea[0,0;5.5,6.5;help;MOVER HELP;".. text.."]"
|
|
minetest.show_formspec(name, "basic_machines:help_mover", form)
|
|
end
|
|
|
|
if fields.OK == "OK" then
|
|
local x0,y0,z0,x1,y1,z1,x2,y2,z2;
|
|
x0=tonumber(fields.x0) or 0;y0=tonumber(fields.y0) or -1;z0=tonumber(fields.z0) or 0
|
|
x1=tonumber(fields.x1) or 0;y1=tonumber(fields.y1) or -1;z1=tonumber(fields.z1) or 0
|
|
x2=tonumber(fields.x2) or 0;y2=tonumber(fields.y2) or 1;z2=tonumber(fields.z2) or 0;
|
|
if not privs.privs and (math.abs(x1)>max_range or math.abs(y1)>max_range or math.abs(z1)>max_range or math.abs(x2)>max_range or math.abs(y2)>max_range or math.abs(z2)>max_range) then
|
|
minetest.chat_send_player(name,"all coordinates must be between ".. -max_range .. " and " .. max_range); return
|
|
end
|
|
|
|
local x = x0; x0 = math.min(x,x1); x1 = math.max(x,x1);
|
|
local y = y0; y0 = math.min(y,y1); y1 = math.max(y,y1);
|
|
local z = z0; z0 = math.min(z,z1); z1 = math.max(z,z1);
|
|
|
|
|
|
meta:set_int("x0",x0);meta:set_int("y0",y0);meta:set_int("z0",z0);
|
|
meta:set_int("x1",x1);meta:set_int("y1",y1);meta:set_int("z1",z1);
|
|
meta:set_int("pc",0); meta:set_int("dim",(x1-x0+1)*(y1-y0+1)*(z1-z0+1))
|
|
meta:set_int("x2",x2);meta:set_int("y2",y2);meta:set_int("z2",z2);
|
|
meta:set_string("prefer",fields.prefer or "");
|
|
meta:set_string("infotext", "Mover block. Set up with source coordinates ".. x0 ..","..y0..","..z0.. " -> ".. x1 ..","..y1..","..z1.. " and target coord ".. x2 ..","..y2..",".. z2 .. ". Put locked chest with fuel next to it and start it with keypad/mese signal.");
|
|
if meta:get_float("fuel")<0 then meta:set_float("fuel",0) end -- reset block
|
|
end
|
|
return
|
|
end
|
|
|
|
-- KEYPAD
|
|
fname = "basic_machines:keypad_"
|
|
if string.sub(formname,0,string.len(fname)) == fname then
|
|
local pos_s = string.sub(formname,string.len(fname)+1); local pos = minetest.string_to_pos(pos_s)
|
|
local name = player:get_player_name(); if name==nil then return end
|
|
local meta = minetest.get_meta(pos)
|
|
local privs = minetest.get_player_privs(player:get_player_name());
|
|
if (name ~= meta:get_string("owner") and not privs.privs) or not fields then return end -- only owner can interact
|
|
|
|
if fields.OK == "OK" then
|
|
local x0,y0,z0,pass,mode;
|
|
x0=tonumber(fields.x0) or 0;y0=tonumber(fields.y0) or 1;z0=tonumber(fields.z0) or 0
|
|
pass = fields.pass or ""; mode = fields.mode or 1;
|
|
|
|
if not privs.privs and (math.abs(x0)>max_range or math.abs(y0)>max_range or math.abs(z0)>max_range) then
|
|
minetest.chat_send_player(name,"all coordinates must be between ".. -max_range .. " and " .. max_range); return
|
|
end
|
|
meta:set_int("x0",x0);meta:set_int("y0",y0);meta:set_int("z0",z0);meta:set_string("pass",pass);
|
|
meta:set_int("iter",math.min(tonumber(fields.iter) or 1,100));meta:set_int("mode",mode);
|
|
meta:set_string("infotext", "Punch keypad to use it.");
|
|
if pass~="" then meta:set_string("infotext",meta:get_string("infotext").. ". Password protected."); end
|
|
end
|
|
return
|
|
end
|
|
|
|
fname = "basic_machines:check_keypad_"
|
|
if string.sub(formname,0,string.len(fname)) == fname then
|
|
local pos_s = string.sub(formname,string.len(fname)+1); local pos = minetest.string_to_pos(pos_s)
|
|
local name = player:get_player_name(); if name==nil then return end
|
|
local meta = minetest.get_meta(pos)
|
|
|
|
if fields.OK == "OK" then
|
|
local pass;
|
|
pass = fields.pass or "";
|
|
if pass~=meta:get_string("pass") then
|
|
minetest.chat_send_player(name,"ACCESS DENIED. WRONG PASSWORD.")
|
|
return
|
|
end
|
|
minetest.chat_send_player(name,"ACCESS GRANTED.")
|
|
|
|
if meta:get_int("count")<=0 then -- only accept new operation requests if idle
|
|
meta:set_int("count",meta:get_int("iter")); use_keypad(pos,machines_TTL)
|
|
else meta:set_int("count",0); meta:set_string("infotext","operation aborted by user. punch to activate.") -- reset
|
|
end
|
|
|
|
return
|
|
end
|
|
end
|
|
|
|
-- MOVER
|
|
local fname = "basic_machines:detector_"
|
|
if string.sub(formname,0,string.len(fname)) == fname then
|
|
local pos_s = string.sub(formname,string.len(fname)+1); local pos = minetest.string_to_pos(pos_s)
|
|
local name = player:get_player_name(); if name==nil then return end
|
|
local meta = minetest.get_meta(pos)
|
|
local privs = minetest.get_player_privs(player:get_player_name());
|
|
if (name ~= meta:get_string("owner") and not privs.privs) or not fields then return end -- only owner can interact
|
|
--minetest.chat_send_all("formname " .. formname .. " fields " .. dump(fields))
|
|
|
|
if fields.help == "help" then
|
|
local text = "SETUP: right click or punch and follow chat instructions. Detector checks area around source position inside specified radius."..
|
|
"If detector activates it will trigger machine at target position.\n\n There are 2 modes of operation - node or player detection. Inside node/player "..
|
|
"write node/player name. If you want detector to activate target precisely when its not triggered set NOT to 1\n\n"..
|
|
"For example, to detect empty space write air, to detect tree write default:tree, to detect ripe wheat write farming:wheat_8, for flowing water write default:water_flowing ... "..
|
|
"If source position is chest it will look into it and check if there are items inside. For example to check if there is at least 2 dirt write default:dirt 2"
|
|
local form = "size [5,5] textarea[0,0;5.5,6.5;help;DETECTOR HELP;".. text.."]"
|
|
minetest.show_formspec(name, "basic_machines:help_detector", form)
|
|
end
|
|
|
|
if fields.OK == "OK" then
|
|
local x0,y0,z0,x1,y1,z1,r,node,NOT;
|
|
x0=tonumber(fields.x0) or 0;y0=tonumber(fields.y0) or 0;z0=tonumber(fields.z0) or 0
|
|
x1=tonumber(fields.x1) or 0;y1=tonumber(fields.y1) or 0;z1=tonumber(fields.z1) or 0
|
|
r=tonumber(fields.r) or 1;
|
|
NOT = tonumber(fields.NOT)
|
|
|
|
if not privs.privs and(math.abs(x0)>max_range or math.abs(y0)>max_range or math.abs(z0)>max_range or math.abs(x1)>max_range or math.abs(y1)>max_range or math.abs(z1)>max_range) then
|
|
minetest.chat_send_player(name,"all coordinates must be between ".. -max_range .. " and " .. max_range); return
|
|
end
|
|
|
|
meta:set_int("x0",x0);meta:set_int("y0",y0);meta:set_int("z0",z0);
|
|
meta:set_int("x1",x1);meta:set_int("y1",y1);meta:set_int("z1",z1);meta:set_int("r",math.min(r,5));
|
|
meta:set_int("NOT",NOT);
|
|
meta:set_string("node",fields.node or "");
|
|
|
|
end
|
|
return
|
|
end
|
|
|
|
local fname = "basic_machines:distributor_"
|
|
if string.sub(formname,0,string.len(fname)) == fname then
|
|
local pos_s = string.sub(formname,string.len(fname)+1); local pos = minetest.string_to_pos(pos_s)
|
|
local name = player:get_player_name(); if name==nil then return end
|
|
local meta = minetest.get_meta(pos)
|
|
local privs = minetest.get_player_privs(player:get_player_name());
|
|
if (name ~= meta:get_string("owner") and not privs.privs) or not fields then return end -- only owner can interact
|
|
--minetest.chat_send_all("formname " .. formname .. " fields " .. dump(fields))
|
|
|
|
if fields.OK == "OK" then
|
|
local x1,y1,z1,x2,y2,z2,active1,active2
|
|
x1=tonumber(fields.x1) or 0;y1=tonumber(fields.y1) or 0;z1=tonumber(fields.z1) or 0
|
|
x2=tonumber(fields.x2) or 0;y2=tonumber(fields.y2) or 0; z2=tonumber(fields.z2) or 0
|
|
active1=tonumber(fields.active1) or 0;active2=tonumber(fields.active2) or 0
|
|
|
|
if not privs.privs and (math.abs(x1)>max_range or math.abs(y1)>max_range or math.abs(z1)>max_range or math.abs(x2)>max_range or math.abs(y2)>max_range or math.abs(z2)>max_range) then
|
|
minetest.chat_send_player(name,"all coordinates must be between ".. -max_range .. " and " .. max_range); return
|
|
end
|
|
|
|
meta:set_int("x1",x1);meta:set_int("y1",y1);meta:set_int("z1",z1);
|
|
meta:set_int("x2",x2);meta:set_int("y2",y2);meta:set_int("z2",z2);
|
|
meta:set_int("active1",active1);meta:set_int("active2",active2);
|
|
end
|
|
return
|
|
end
|
|
|
|
|
|
|
|
end)
|
|
|
|
-- CRAFTS
|
|
|
|
minetest.register_craft({
|
|
output = "basic_machines:mover",
|
|
recipe = {
|
|
{"default:mese_crystal", "default:mese_crystal","default:mese_crystal"},
|
|
{"default:mese_crystal", "default:mese_crystal","default:mese_crystal"},
|
|
{"default:stone", "default:wood", "default:stone"}
|
|
}
|
|
})
|
|
|
|
minetest.register_craft({
|
|
output = "basic_machines:detector",
|
|
recipe = {
|
|
{"default:mese_crystal", "default:mese_crystal"},
|
|
{"default:mese_crystal", "default:mese_crystal"}
|
|
}
|
|
})
|
|
|
|
minetest.register_craft({
|
|
output = "basic_machines:light_on",
|
|
recipe = {
|
|
{"default:torch", "default:torch"},
|
|
{"default:torch", "default:torch"}
|
|
}
|
|
})
|
|
|
|
|
|
minetest.register_craft({
|
|
output = "basic_machines:keypad",
|
|
recipe = {
|
|
{"default:stick"},
|
|
{"default:wood"},
|
|
}
|
|
})
|
|
|
|
minetest.register_craft({
|
|
output = "basic_machines:distributor",
|
|
recipe = {
|
|
{"default:steel_ingot"},
|
|
{"default:mese_crystal"},
|
|
}
|
|
}) |