basic_machines/mover.lua

3319 lines
113 KiB
Lua
Raw Permalink Normal View History

2015-05-01 09:40:54 -07:00
------------------------------------------------------------------------------------------------------------------------------------
-- BASIC MACHINES MOD by rnd
-- mod with basic simple automatization for minetest. No background processing, just one abm with 5s timer (clock generator), no other lag causing background processing.
2015-05-01 09:40:54 -07:00
------------------------------------------------------------------------------------------------------------------------------------
-- *** SETTINGS *** --
2018-10-31 09:13:05 -07:00
basic_machines.timer = 5 -- main timestep
basic_machines.machines_minstep = 1 -- minimal allowed activation timestep, if faster machines overheat
basic_machines.max_range = 10 -- machines normal range of operation
basic_machines.machines_operations = 10 -- 1 coal will provide 10 mover basic operations ( moving dirt 1 block distance)
basic_machines.machines_TTL = 16 -- time to live for signals, how many hops before signal dissipates
basic_machines.version = "12/04/2018a"
2018-11-24 18:49:45 -08:00
basic_machines.clockgen = 1 -- if 0 all background continuously running activity (clockgen/keypad) repeating is disabled
-- how hard it is to move blocks, default factor 1, note fuel cost is this multiplied by distance and divided by machine_operations..
basic_machines.hardness = {
2018-11-24 18:49:45 -08:00
["default:stone"] = 4,
["default:tree"] = 2,
["default:jungletree"] = 2,
["default:pine_tree"] = 2,
["default:aspen_tree"] = 2,
["default:acacia_tree"] = 2,
["default:lava_source"] = 5950,
["default:water_source"] = 5950,
["default:river_water_source"] = 5950,
["default:obsidian"] = 20,
["bedrock2:bedrock"] = 999999,
["spawners_env:mobs_spider_spawner"] = 999999,
["spawners_env:mobs_spider_spawner_active"] = 999999,
["spawners_env:mobs_spider_spawner_waiting"] = 999999,
["spawners_env:spawners_mobs_uruk_hai_spawner"] = 999999,
["spawners_env:spawners_mobs_uruk_hai_spawner_active"] = 999999,
["spawners_env:spawners_mobs_uruk_hai_spawner_waiting"] = 999999,
["telemosaic:extender_one"] = 999999,
["telemosaic:extender_two"] = 999999,
["telemosaic:extender_three"] = 999999,
["telemosaic:beacon_off"] = 999999,
["telemosaic:beacon"] = 999999,
["telemosaic:beacon_err"] = 999999,
["farming_addons:cocoa_1"] = 999999,
["farming_addons:cocoa_2"] = 999999,
["farming_addons:cocoa_3"] = 999999,
["x_default:treasure_chest"] = 999999,
-- move machines for free
["basic_machines:mover"] = 0,
["basic_machines:keypad"] = 0,
["basic_machines:distributor"] = 0,
["basic_machines:battery"] = 0,
["basic_machines:detector"] = 0,
["basic_machines:generator"] = 0,
["basic_machines:clockgen"] = 0,
["basic_machines:ball_spawner"] = 0,
["basic_machines:light_on"] = 0,
["basic_machines:light_off"] = 0,
["farming:wheat_8"] = 1,
["farming:cotton_8"] = 1,
["farming:seed_wheat"] = 0.5,
["farming:seed_cotton"] = 0.5,
}
-- define which nodes are dug up completely, like a tree
2018-11-24 18:49:45 -08:00
basic_machines.dig_up_table = {
["default:cactus"] = true,
["default:tree"] = true,
["default:jungletree"] = true,
["default:pine_tree"] = true,
["default:acacia_tree"] = true,
["default:aspen_tree"] = true,
["default:papyrus"] = true
}
2018-11-13 19:09:03 -08:00
-- set up nodes for harvest when digging: [nodename] = {what remains after harvest, harvest result}
2016-04-18 13:41:10 -07:00
basic_machines.harvest_table = {
2016-05-04 01:46:35 -07:00
["mese_crystals:mese_crystal_ore4"] = {"mese_crystals:mese_crystal_ore1", "default:mese_crystal 3"}, -- harvesting mese crystals
["mese_crystals:mese_crystal_ore3"] = {"mese_crystals:mese_crystal_ore1", "default:mese_crystal 2"},
["mese_crystals:mese_crystal_ore2"] = {"mese_crystals:mese_crystal_ore1", "default:mese_crystal 1"},
2016-05-04 01:46:35 -07:00
["mese_crystals:mese_crystal_ore1"] = {"mese_crystals:mese_crystal_ore1", ""},
2018-11-24 18:49:45 -08:00
}
2017-12-21 09:06:15 -08:00
-- list of objects that cant be teleported with mover
basic_machines.no_teleport_table = {
["itemframes:item"] = true,
["signs:text"] = true,
["spawners_mobs:dummy_mobs_sheep_white"] = true,
["spawners_mobs:dummy_mobs_chicken"] = true,
["spawners_mobs:dummy_mobs_cow"] = true,
["spawners_mobs:dummy_mobs_oerkki"] = true,
["spawners_mobs:dummy_mobs_pumba"] = true,
["spawners_mobs:dummy_mobs_spider"] = true,
["spawners_mobs:dummy_mobs_stone_monster"] = true,
["spawners_mobs:dummy_mobs_tree_monster"] = true,
["spawners_mobs:dummy_spawners_mobs_balrog"] = true,
["spawners_mobs:dummy_spawners_mobs_bunny_evil"] = true,
["spawners_mobs:dummy_spawners_mobs_mummy"] = true,
["spawners_mobs:dummy_spawners_mobs_uruk_hai"] = true,
["spawners_ores:dummy_ore_stone_with_tin"] = true,
["spawners_ores:dummy_ore_stone_with_iron"] = true,
["spawners_ores:dummy_ore_stone_with_gold"] = true,
["spawners_ores:dummy_ore_stone_with_copper"] = true,
["spawners_env:dummy_spawners_mobs_uruk_hai"] = true,
["spawners_env:dummy_mobs_spider"] = true,
["spawners_env:dummy_spawners_mobs_balrog"] = true,
["xdecor:book_open"] = true
}
2017-12-21 09:06:15 -08:00
-- list of nodes mover cant take from in inventory mode
basic_machines.limit_inventory_table = { -- node name = {list of bad inventories to take from}
2018-11-24 18:49:45 -08:00
["basic_machines:autocrafter"] = {["recipe"] = 1, ["output"] = 1},
["basic_machines:constructor"] = {["recipe"] = 1},
["basic_machines:battery_0"] = {["upgrade"] = 1},
["basic_machines:battery_1"] = {["upgrade"] = 1},
["basic_machines:battery_2"] = {["upgrade"] = 1},
["basic_machines:generator"] = {["upgrade"] = 1},
["basic_machines:mover"] = {["upgrade"] = 1},
2018-11-24 18:49:45 -08:00
["moreblocks:circular_saw"] = {["input"] = 1, ["recycle"] = 1, ["micro"] = 1, ["output"] = 1 },
["easyvend:depositor"] = {["item"] = 1, ["gold"] = 1},
["easyvend:vendor"] = {["item"] = 1, ["gold"] = 1},
["easyvend:depositor_on"] = {["item"] = 1, ["gold"] = 1},
["easyvend:vendor_on"] = {["item"] = 1, ["gold"] = 1},
["x_default:treasure_chest"] = {["main"] = 1},
}
2016-05-04 01:46:35 -07:00
-- when activated with keypad these will be "punched" to update their text too
basic_machines.signs = {
["default:sign_wall_wood"] = true,
["signs:sign_wall_green"] = true,
["signs:sign_wall_green"] = true,
["signs:sign_wall_yellow"] = true,
["signs:sign_wall_red"] = true,
["signs:sign_wall_red"] = true,
["signs:sign_wall_white_black"] = true,
["signs:sign_yard"] = true
}
-- *** END OF SETTINGS *** --
2018-10-31 09:13:05 -07:00
local machines_timer = basic_machines.timer
local machines_minstep = basic_machines.machines_minstep
local max_range = basic_machines.max_range
local machines_operations = basic_machines.machines_operations
local machines_TTL = basic_machines.machines_TTL
2018-11-13 19:09:03 -08:00
local punchset = {}
2018-10-31 09:13:05 -07:00
2018-11-13 19:09:03 -08:00
minetest.register_on_joinplayer(function(player)
local name = player:get_player_name()
2018-11-13 19:09:03 -08:00
if name == nil then
return
end
2018-11-13 19:09:03 -08:00
punchset[name] = {}
punchset[name].state = 0
end)
local get_mover_form = function(pos,player)
2018-11-13 19:09:03 -08:00
if not player then
return
end
local meta = minetest.get_meta(pos);
2018-11-13 19:09:03 -08:00
local x0, y0, z0, x1, y1, z1, x2, y2, z2, prefer, mode, mreverse
-- pos1
x0 = meta:get_int("x0")
y0 = meta:get_int("y0")
z0 = meta:get_int("z0")
-- pos11
x1 = meta:get_int("x1")
y1 = meta:get_int("y1")
z1 = meta:get_int("z1")
-- pos2
x2 = meta:get_int("x2")
y2 = meta:get_int("y2")
z2 = meta:get_int("z2")
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.pos11[player:get_player_name()] = {x = pos.x + x1, y = pos.y + y1, z = pos.z + z1}
machines.mark_pos11(player:get_player_name()) -- mark pos11
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")
local mreverse = meta:get_int("reverse")
local list_name = "nodemeta:"..pos.x..","..pos.y..","..pos.z
local mode_list = {
["normal"] = 1,
["dig"] = 2,
["drop"] = 3,
["object"] = 4,
["inventory"] = 5,
["transport"] = 6
}
local mode_string = meta:get_string("mode") or ""
2018-12-08 21:34:43 -08:00
-- source meta
local meta1 = minetest.get_meta({x = pos.x + x0, y = pos.y + y0, z = pos.z + z0})
-- target meta
local meta2 = minetest.get_meta({x = pos.x + x2, y = pos.y + y2, z = pos.z + z2})
2018-11-13 19:09:03 -08:00
2018-11-24 18:49:45 -08:00
local inv1 = 1
local inv2 = 1
local inv1m = meta:get_string("inv1")
local inv2m = meta:get_string("inv2")
2018-11-13 19:09:03 -08:00
2018-11-24 18:49:45 -08:00
local list1 = meta1:get_inventory():get_lists()
local inv_list1 = ""
2018-12-08 21:34:43 -08:00
-- stupid dropdown requires item index but returns string on receive so we have to find index.. grrr, one other solution: invert the table: key <-> value
local j = 1
2018-11-13 19:09:03 -08:00
for i in pairs( list1) do
2018-11-24 18:49:45 -08:00
inv_list1 = inv_list1 .. i .. ","
if i == inv1m then
inv1 = j
end
j = j + 1
2017-01-09 09:59:34 -08:00
end
2018-11-24 18:49:45 -08:00
local list2 = meta2:get_inventory():get_lists()
local inv_list2 = ""
j = 1
2018-11-13 19:09:03 -08:00
if list2 then
for i in pairs( list2) do
2018-11-24 18:49:45 -08:00
inv_list2 = inv_list2 .. i .. ","
if i == inv2m then
inv2 = j
end
j = j + 1
2018-11-13 19:09:03 -08:00
end
2017-01-09 09:59:34 -08:00
end
2018-11-24 18:49:45 -08:00
local upgrade = meta:get_float("upgrade")
if upgrade > 0 then
upgrade = upgrade - 1
end
if upgrade > 10 then
upgrade = 10
meta:set_float("upgrade", 10)
2018-12-08 21:34:43 -08:00
end
2018-11-24 18:49:45 -08:00
local seltab = meta:get_int("seltab")
local form
2018-11-13 19:09:03 -08:00
2018-12-07 16:50:41 -08:00
-- MODE --
if seltab == 1 then
2017-12-20 14:05:15 -08:00
local mode_description = {
["normal"] = "This will move blocks as they are - without change.",
["dig"] = "This will transform blocks as if player digged them.",
["drop"] = "This will take block/item out of chest (you need to set filter) and will drop it",
["object"] = "make TELEPORTER/ELEVATOR. This will move any object inside sphere (with center source1 and radius defined by source2) to target position. For ELEVATOR teleport points need to be placed exactly vertically in line with mover and you need to upgrade with 1 diamondblock for every 100 height difference. ",
["inventory"] = "This will move items from inventory of any block at source position to any inventory of block at target position",
["transport"] = "This will move all blocks at source area to new area starting at target position. This mode preserves all inventories and other metadata",
2018-11-24 18:49:45 -08:00
}
local text = mode_description[mode_string] or "description"
local mode_list = {
["normal"] = 1,
["dig"] = 2,
["drop"] = 3,
["object"] = 4,
["inventory"] = 5,
["transport"] = 6
}
2018-11-13 19:09:03 -08:00
2018-11-24 18:49:45 -08:00
mode = mode_list[mode_string] or 1
2018-11-13 19:09:03 -08:00
2017-12-20 14:05:15 -08:00
form = "size[8,8.25]" .. -- width, height
--"size[6,10]" .. -- width, height
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
2017-12-20 14:05:15 -08:00
"tabheader[0,0;tabs;MODE OF OPERATION,WHERE TO MOVE;".. seltab .. ";true;true]"..
"label[0.,0;MODE selection]".."button[3,0.25;1,1;help;help]"..
"dropdown[0.,0.35;3,1;mode;normal,dig,drop,object,inventory,transport;".. mode .."]"..
"textarea[0.25,1.25;8,2.;description;;".. text.."]"..
2018-11-13 19:09:03 -08:00
2017-12-20 14:05:15 -08:00
"field[0.25,3.5;3,1;prefer;FILTER;"..prefer.."]"..
2018-11-13 19:09:03 -08:00
2017-12-20 14:05:15 -08:00
"list[nodemeta:"..pos.x..','..pos.y..','..pos.z ..";filter;3,3.4;1,1;]"..
2018-11-13 19:09:03 -08:00
"list[nodemeta:"..pos.x..','..pos.y..','..pos.z ..";upgrade;5,3.4;1,1;]".."label[4,3;UPGRADE LVL ".. upgrade .."]" ..
2017-12-20 14:05:15 -08:00
"list[current_player;main;0,4.5;8,4;]"..
"listring[nodemeta:"..pos.x..','..pos.y..','..pos.z ..";upgrade]"..
"listring[current_player;main]"..
"listring[nodemeta:"..pos.x..','..pos.y..','..pos.z ..";filter]"..
"listring[current_player;main] button_exit[5,0.25;1,1;OK;OK]"
2018-11-13 19:09:03 -08:00
2017-12-20 14:05:15 -08:00
else -- POSITIONS
2018-11-13 19:09:03 -08:00
2018-11-24 18:49:45 -08:00
local inventory_list1, inventory_list2
2017-12-20 14:05:15 -08:00
if mode_string == "inventory" then
inventory_list1 = "label[4.5,0.25;source inventory] dropdown[4.5,0.75;1.5,1;inv1;".. inv_list1 ..";" .. inv1 .."]"
inventory_list2 = "label[4.5,3.;target inventory] dropdown[4.5,3.5;1.5,1;inv2;".. inv_list2 .. ";" .. inv2 .."]"
else
2018-11-24 18:49:45 -08:00
inventory_list1 = ""
inventory_list2 = ""
2017-12-20 14:05:15 -08:00
end
2018-11-13 19:09:03 -08:00
2017-12-20 14:05:15 -08:00
form = "size[6,5.5]" .. -- width, height
--"size[6,10]" .. -- width, height
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
2017-12-20 14:05:15 -08:00
"tabheader[0,0;tabs;MODE OF OPERATION,WHERE TO MOVE;".. seltab .. ";true;true]"..
2018-11-13 19:09:03 -08:00
2017-12-25 13:06:43 -08:00
"label[0.,0;" .. minetest.colorize("lawngreen","INPUT AREA - mover will dig here").."]"..
2017-12-20 14:05:15 -08:00
"field[0.25,1.;1,1;x0;source1;"..x0.."] field[1.25,1.;1,1;y0;;"..y0.."] field[2.25,1.;1,1;z0;;"..z0.."]"..
"image[3,0.75;1,1;machines_pos1.png]"..
inventory_list1..
"field[0.25,2;1,1;x1;source2;"..x1.."] field[1.25,2;1,1;y1;;"..y1.."] field[2.25,2;1,1;z1;;"..z1.."]"..
"image[3,1.75;1,1;machines_pos11.png]"..
2018-11-13 19:09:03 -08:00
2017-12-20 14:05:15 -08:00
"label[0.,2.75;" .. minetest.colorize("red","TARGET POSITION - mover will move to here").."]"..
2018-11-13 19:09:03 -08:00
2017-12-20 14:05:15 -08:00
"field[0.25,3.75;1,1;x2;Target;"..x2.."] field[1.25,3.75;1,1;y2;;"..y2.."] field[2.25,3.75;1,1;z2;;"..z2.."]"..
"image[3,3.5;1,1;machines_pos2.png]"..
inventory_list2 ..
"label[0.,4.25;REVERSE source and target (0/1/2)]"..
"field[0.25,5;1.,1;reverse;;"..mreverse.."]" ..
"listring[current_player;main] button[4,4.75;1,1;help;help] button_exit[5,4.75;1,1;OK;OK]"
end
2017-12-25 13:06:43 -08:00
2017-01-09 09:59:34 -08:00
return form
end
local find_and_connect_battery = function(pos)
2018-11-24 18:49:45 -08:00
local r = 1
for i = 0, 2 do
local positions = minetest.find_nodes_in_area( --find battery
2018-11-24 18:49:45 -08:00
{x = pos.x - r, y = pos.y - r, z = pos.z - r},
{x = pos.x + r, y = pos.y + r, z = pos.z + r},
"basic_machines:battery_" .. i )
2018-11-24 18:49:45 -08:00
if #positions > 0 then
local meta = minetest.get_meta(pos)
local fpos = positions[1]
meta:set_int("batx", fpos.x)
meta:set_int("baty", fpos.y)
meta:set_int("batz", fpos.z)
2018-11-13 19:09:03 -08:00
return fpos
end -- pick first battery we found
end
2018-11-24 18:49:45 -08:00
return nil
end
-- MOVER --
minetest.register_node("basic_machines:mover", {
description = "Mover - universal digging/harvesting/teleporting/transporting machine, its upgradeable.",
2017-01-15 07:05:09 -08:00
tiles = {"basic_machine_mover_side.png"},
2018-11-24 18:49:45 -08:00
groups = {cracky = 3, mesecon_effector_on = 1},
sounds = default.node_sound_wood_defaults(),
2018-11-24 18:49:45 -08:00
after_place_node = function(pos, placer)
local meta = minetest.env:get_meta(pos)
meta:set_string("infotext", "Mover block. Set it up by punching or right click. Activate it by keypad signal.")
2018-11-24 18:49:45 -08:00
meta:set_string("owner", placer:get_player_name())
meta:set_int("public", 0)
meta:set_int("x0", 0)
meta:set_int("y0", -1)
-- source1
meta:set_int("z0", 0)
2018-11-24 18:49:45 -08:00
meta:set_int("x1", 0)
meta:set_int("y1", -1)
-- source2: defines cube
meta:set_int("z1", 0)
2018-11-24 18:49:45 -08:00
meta:set_int("pc", 0)
-- current cube position and dimensions
meta:set_int("dim", 1)
2018-11-24 18:49:45 -08:00
meta:set_int("pc", 0)
-- current cube position and dimensions
meta:set_int("dim", 1)
2018-11-24 18:49:45 -08:00
meta:set_int("x2", 0)
meta:set_int("y2", 1)
meta:set_int("z2", 0)
meta:set_float("fuel", 0)
meta:set_string("prefer", "")
meta:set_string("mode", "normal")
meta:set_float("upgrade", 1)
meta:set_int("seltab", 1)
local privs = minetest.get_player_privs(placer:get_player_name())
-- means operation will be for free
2018-11-24 18:49:45 -08:00
if privs.privs then
meta:set_float("upgrade", -1)
end
2018-11-24 18:49:45 -08:00
local inv = meta:get_inventory()
inv:set_size("upgrade", 1 * 1)
inv:set_size("filter", 1 * 1)
local name = placer:get_player_name()
punchset[name].state = 0
2018-11-13 19:09:03 -08:00
local text = "This machine can move anything. General idea is the following : \n\n"..
"First you need to define rectangle work area (where it takes, marked by two number 1 boxes that appear in world) and target area (where it puts, marked by one number 2 box) by punching mover then following CHAT instructions exactly.\n\n"..
"CHECK why it doesnt work: 1. did you click OK in mover after changing setting 2. does it have battery, 3. does battery have enough fuel\n\n"..
2018-11-24 18:49:45 -08:00
"IMPORTANT: Please read the help button inside machine before first use."
2018-11-13 19:09:03 -08:00
local form = "size [5.5,5.5] textarea[0,0;6,7;help;MOVER INTRODUCTION;".. text.."]"
-- minetest.show_formspec(name, "basic_machines:intro_mover", form)
end,
2018-11-13 19:09:03 -08:00
-- dont dig if upgrades inside, cause they will be destroyed
can_dig = function(pos, player)
2018-11-24 18:49:45 -08:00
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
return inv:is_empty("upgrade")
end,
2018-11-13 19:09:03 -08:00
on_rightclick = function(pos, node, player, itemstack, pointed_thing)
2018-11-24 18:49:45 -08:00
local privs = minetest.get_player_privs(player:get_player_name())
local cant_build = minetest.is_protected(pos,player:get_player_name())
-- only ppl sharing protection can setup
if not privs.privs and cant_build then
return
end
2018-11-13 19:09:03 -08:00
2018-11-24 18:49:45 -08:00
local form = get_mover_form(pos, player)
2017-12-21 09:06:15 -08:00
minetest.show_formspec(player:get_player_name(), "basic_machines:mover_"..minetest.pos_to_string(pos), form)
end,
2018-11-13 19:09:03 -08:00
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
2018-11-13 19:09:03 -08:00
2017-07-30 15:09:40 -07:00
if minetest.is_protected(pos, player:get_player_name()) then
minetest.record_protection_violation(pos, player:get_player_name())
return 0
end
2018-11-13 19:09:03 -08:00
local stack_name = stack:get_name()
if listname == "filter" then
2018-11-24 18:49:45 -08:00
local meta = minetest.get_meta(pos)
local form = get_mover_form(pos, player)
meta:set_string("prefer", stack_name)
2017-12-21 09:06:15 -08:00
minetest.show_formspec(player:get_player_name(), "basic_machines:mover_"..minetest.pos_to_string(pos), form)
2018-11-24 18:49:45 -08:00
return 1
end
2018-11-13 19:09:03 -08:00
if listname == "upgrade" then
if not (stack_name == "default:diamondblock" or stack_name == "default:mese") then
return 0
end
end
return stack:get_count()
end,
on_metadata_inventory_put = function(pos, listname, index, stack, player)
if listname == "upgrade" then
-- update upgrades
2018-11-24 18:49:45 -08:00
local meta = minetest.get_meta(pos)
local upgrade = 0
local inv = meta:get_inventory()
local stack_name = stack:get_name()
2018-11-24 18:49:45 -08:00
local upgrade_name = "default:mese"
-- check if upgrade should be for elevator
2018-11-24 18:49:45 -08:00
if meta:get_int("elevator") == 1 then
upgrade_name = "default:diamondblock"
end
2018-11-13 19:09:03 -08:00
-- add upgrades
if stack_name == upgrade_name then
upgrade = inv:get_stack(listname, index):get_count() or 0
2018-11-13 19:09:03 -08:00
2018-11-24 18:49:45 -08:00
-- not more than 10
if upgrade > 10 then
upgrade = 10
end
2018-11-13 19:09:03 -08:00
2018-11-24 18:49:45 -08:00
meta:set_float("upgrade", upgrade + 1)
2018-11-13 19:09:03 -08:00
local form = get_mover_form(pos, player)
minetest.show_formspec(player:get_player_name(), "basic_machines:mover_"..minetest.pos_to_string(pos), form)
-- reset upgrade level when switching the item
else
meta:set_float("upgrade", 1)
2018-11-24 18:49:45 -08:00
local form = get_mover_form(pos, player)
minetest.show_formspec(player:get_player_name(), "basic_machines:mover_"..minetest.pos_to_string(pos), form)
end
2018-11-13 19:09:03 -08:00
end
end,
2018-11-13 19:09:03 -08:00
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
2018-11-24 18:49:45 -08:00
local meta = minetest.get_meta(pos)
-- reset upgrade
meta:set_float("upgrade", 1)
local form = get_mover_form(pos, player)
2017-12-20 14:05:15 -08:00
minetest.show_formspec(player:get_player_name(), "basic_machines:mover_"..minetest.pos_to_string(pos), form)
2018-11-24 18:49:45 -08:00
return stack:get_count()
end,
2018-11-13 19:09:03 -08:00
mesecons = {
effector = {
action_on = function(pos, node,ttl)
if type(ttl) ~= "number" then
ttl = 1
end
2018-11-13 19:09:03 -08:00
local meta = minetest.get_meta(pos)
local fuel = meta:get_float("fuel")
local x0 = meta:get_int("x0")
local y0 = meta:get_int("y0")
local z0 = meta:get_int("z0")
local x2 = meta:get_int("x2")
local y2 = meta:get_int("y2")
local z2 = meta:get_int("z2")
local mode = meta:get_string("mode")
local mreverse = meta:get_int("reverse")
-- where to take from
local pos1 = {x = x0 + pos.x, y = y0 + pos.y, z = z0 + pos.z}
-- where to put
local pos2 = {x = x2 + pos.x, y = y2 + pos.y, z = z2 + pos.z}
local pc = meta:get_int("pc")
local dim = meta:get_int("dim")
pc = (pc+1) % dim
-- cycle position
meta:set_int("pc", pc)
-- get dimensions
local x1 = meta:get_int("x1") - x0 + 1
local y1 = meta:get_int("y1") - y0 + 1
local z1 = meta:get_int("z1") - z0 + 1
--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
-- special modes that use its own source/target positions:
if mode == "transport" and mreverse < 2 then
-- translation from pos1
pos2 = {
x = meta:get_int("x2") - x0 + pos1.x,
y = meta:get_int("y2") - y0 + pos1.y,
z = meta:get_int("z2") - z0 + pos1.z
}
end
2018-11-24 18:49:45 -08:00
-- reverse pos1, pos2
if mreverse ~= 0 and mreverse ~= 2 then
if mode == "object" then
x0 = pos2.x - pos.x
y0 = pos2.y - pos.y
z0 = pos2.z - pos.z
pos2 = {x = pos1.x, y = pos1.y, z = pos1.z}
else
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
end
2018-11-13 19:09:03 -08:00
-- PROTECTION CHECK
local owner = meta:get_string("owner")
if (minetest.is_protected(pos1, owner) or minetest.is_protected(pos2, owner)) and mode ~= "object" then
meta:set_string("infotext", "Mover block. Protection fail.")
return
end
2018-11-13 19:09:03 -08:00
local node1 = minetest.get_node(pos1)
local node2 = minetest.get_node(pos2)
local prefer = meta:get_string("prefer")
2018-11-24 18:49:45 -08:00
-- prevent mover from working when player offline and reverse seed planting is enabled
if mode == "normal" or mode == "dig" then
local placer = minetest.get_player_by_name(owner)
local tempprefer = prefer
if tempprefer == "" then
tempprefer = ":"
end
local name_parts = tempprefer:split(":")
if not placer and
not (node2.name == "default:chest" or node2.name == "default:chest_locked") and
(name_parts[1] == "farming" or name_parts[1] == "farming_addons") then
return
end
end
-- FUEL COST: calculate
local dist = math.abs(pos2.x - pos1.x) + math.abs(pos2.y - pos1.y) + math.abs(pos2.z - pos1.z)
local hardness = basic_machines.hardness[node1.name]
2018-11-13 19:09:03 -08:00
-- no free teleports from machine blocks
if hardness == 0 and mode == "object" then
hardness = 1
end
2018-11-13 19:09:03 -08:00
local fuel_cost = hardness or 1
local upgrade = meta:get_float("upgrade") or 1
-- taking items from chests/inventory move
if node1.name == "default:chest_locked" or mode == "inventory" then
fuel_cost = basic_machines.hardness[prefer] or 1
end
fuel_cost = fuel_cost * dist / machines_operations -- machines_operations=10 by default, so 10 basic operations possible with 1 coal
2018-11-13 19:09:03 -08:00
if mode == "object" then
fuel_cost = fuel_cost * 0.1
-- check if elevator mode
if x2 == 0 and z2 == 0 then
2018-12-08 21:34:43 -08:00
local requirement = math.floor(math.abs(pos2.y - pos.y) / 100) + 1
if upgrade - 1 < requirement then
meta:set_string("infotext","MOVER: Elevator error. Need at least "..requirement .. " diamond block(s) in upgrade (1 for every 100 height). ")
return
end
fuel_cost = 0
end
elseif mode == "inventory" then
fuel_cost = fuel_cost * 0.1
end
-- upgrade decreases fuel cost
fuel_cost = fuel_cost / upgrade
-- free operation for admin
if upgrade == -1 then
2018-11-13 19:09:03 -08:00
fuel_cost = 0
end
2018-11-13 19:09:03 -08:00
-- FUEL OPERATIONS
-- needs fuel to operate, find nearby battery
if fuel < fuel_cost then
local found_fuel = 0
-- cached battery position
local fpos = {
x = meta:get_int("batx"),
y = meta:get_int("baty"),
z = meta:get_int("batz")
}
2018-11-13 19:09:03 -08:00
-- check battery for power
local power_draw = fuel_cost
2018-11-13 19:09:03 -08:00
-- at least 10 one block operations with 1 refuel
if power_draw < 1 then
power_draw = 1
end
2018-11-13 19:09:03 -08:00
local supply = basic_machines.check_power(fpos, power_draw)
2018-11-13 19:09:03 -08:00
if supply > 0 then
found_fuel = supply
-- no battery at target location, try to find it!
elseif supply < 0 then
local fpos = find_and_connect_battery(pos)
2018-11-13 19:09:03 -08:00
if not fpos then
meta:set_string("infotext", "Can not find nearby battery to connect to!")
2018-11-13 19:09:03 -08:00
minetest.sound_play("default_cool_lava", {
pos = pos,
gain = 1.0,
max_hear_distance = 8
})
2018-11-13 19:09:03 -08:00
return
end
end
2018-11-13 19:09:03 -08:00
if found_fuel ~= 0 then
fuel = fuel + found_fuel
meta:set_float("fuel", fuel)
meta:set_string("infotext", "Mover block refueled. Fuel ".. fuel)
end
2015-05-11 04:20:54 -07:00
end
2018-11-13 19:09:03 -08:00
if fuel < fuel_cost then
meta:set_string("infotext", "Mover block. Energy ".. fuel ..", needed energy " .. fuel_cost .. ". Put nonempty battery next to mover.")
return
2015-05-11 04:20:54 -07:00
end
2018-11-13 19:09:03 -08:00
-- teleport objects and return
if mode == "object" then
-- if target is chest put items in it
local target_chest = false
2018-11-13 19:09:03 -08:00
if node2.name == "default:chest" or
node2.name == "default:chest_locked" then
target_chest = true
end
2018-11-13 19:09:03 -08:00
local r = math.max(math.abs(x1), math.abs(y1), math.abs(z1))
r = math.min(r, 10)
local teleport_any = false
2018-11-13 19:09:03 -08:00
-- put objects in target chest
if target_chest then
local cmeta = minetest.get_meta(pos2)
local inv = cmeta:get_inventory()
2018-11-13 19:09:03 -08:00
for _,obj in pairs(minetest.get_objects_inside_radius({x=x0+pos.x,y=y0+pos.y,z=z0+pos.z}, r)) do
local lua_entity = obj:get_luaentity()
2018-11-13 19:09:03 -08:00
if not obj:is_player() and lua_entity and lua_entity.itemstring ~= "" then
local detected_obj = lua_entity.name or ""
2018-11-13 19:09:03 -08:00
-- object on no teleport list
if not basic_machines.no_teleport_table[detected_obj] then
-- put item in chest
local stack = ItemStack(lua_entity.itemstring)
if inv:room_for_item("main", stack) then
teleport_any = true
inv:add_item("main", stack)
end
-- patch for dupe, might not be needed if future minetest object management is better
obj:setpos({x = 0, y = 0, z = 0})
obj:remove()
end
end
end
if teleport_any then
fuel = fuel - fuel_cost
meta:set_float("fuel", fuel)
meta:set_string("infotext", "Mover block. Fuel "..fuel)
minetest.sound_play("tng_transporter1", {
pos = pos2,
gain = 1.0,
max_hear_distance = 8
})
end
return
end
2018-11-13 19:09:03 -08:00
local times = basic_machines.tonumber(prefer) or 0
if times > 20 then
times = 20
elseif times < 0.2 then
times = 0
end
local velocityv
if times ~= 0 then
velocityv = {
x = pos2.x - x0 - pos.x,
y = pos2.y - y0 - pos.y,
z = pos2.z - z0 - pos.z
}
local vv = math.sqrt(velocityv.x * velocityv.x + velocityv.y * velocityv.y + velocityv.z * velocityv.z)
local velocitys = 0
if times ~= 0 then
velocitys = vv/times
else
vv = 0
end
2018-11-13 19:09:03 -08:00
if vv ~= 0 then
vv = velocitys/vv
else
vv = 0
end
2018-11-13 19:09:03 -08:00
velocityv.x = velocityv.x * vv; velocityv.y = velocityv.y * vv; velocityv.z = velocityv.z* vv
end
--minetest.chat_send_all(" times ".. times .. " v " .. minetest.pos_to_string(velocityv));
-- move objects to another location
local finalsound = true
for _, obj in pairs(minetest.get_objects_inside_radius({x=x0+pos.x,y=y0+pos.y,z=z0+pos.z}, r)) do
if obj:is_player() then
-- move player only from owners land
if not minetest.is_protected(obj:getpos(), owner) and
(prefer == "" or obj:get_player_name() == prefer) then
obj:moveto(pos2, false)
teleport_any = true
end
else
local lua_entity = obj:get_luaentity()
local detected_obj = lua_entity.name or ""
-- object on no teleport list
if not basic_machines.no_teleport_table[detected_obj] then
if times > 0 then
2018-12-08 21:34:43 -08:00
local finalmove = true
-- move objects with set velocity in target direction
obj:setvelocity(velocityv);
-- interaction with objects like carts
if obj:get_luaentity() then
if lua_entity.name then
-- move balls for free
if lua_entity.name == "basic_machines:ball" then
lua_entity.velocity = {x=velocityv.x*times,y=velocityv.y*times,z=velocityv.z*times}
finalmove = false
finalsound = false
end
-- just accelerate cart
if lua_entity.name == "carts:cart" then
lua_entity.velocity = {x=velocityv.x*times,y=velocityv.y*times,z=velocityv.z*times}
fuel = fuel - fuel_cost; meta:set_float("fuel",fuel)
meta:set_string("infotext", "Mover block. Fuel "..fuel)
return
end
end
end
-- dont move objects like balls to destination after delay
if finalmove then
minetest.after(times, function()
if obj then
obj:setvelocity({x = 0, y = 0, z = 0})
obj:moveto(pos2, false)
end
end)
end
else
obj:moveto(pos2, false)
end
end
teleport_any = true
end
end
2018-11-13 19:09:03 -08:00
if teleport_any then
fuel = fuel - fuel_cost
meta:set_float("fuel", fuel)
meta:set_string("infotext", "Mover block. Fuel "..fuel)
if finalsound then
minetest.sound_play("tng_transporter1", {
pos = pos2,
gain = 1.0,
max_hear_distance = 8
})
end
end
2018-11-13 19:09:03 -08:00
return
end
2018-11-13 19:09:03 -08:00
local dig = false
-- digs at target location
if mode == "dig" then
dig = true
end
2018-11-13 19:09:03 -08:00
local drop = false
-- drops node instead of placing it
if mode == "drop" then
drop = true
end
2018-11-13 19:09:03 -08:00
-- harvest mode for special nodes: mese crystals
local harvest = false
2018-11-13 19:09:03 -08:00
-- decide what to do if source or target are chests
local source_chest = false
2018-11-13 19:09:03 -08:00
if string.find(node1.name, "default:chest") then
source_chest = true
end
2018-11-13 19:09:03 -08:00
-- nothing to move
if node1.name == "air" then
return
end
2018-11-13 19:09:03 -08:00
local target_chest = false
2018-11-13 19:09:03 -08:00
if node2.name == "default:chest" or
node2.name == "default:chest_locked" then
target_chest = true
end
2018-11-13 19:09:03 -08:00
-- do nothing if target nonempty and not chest
if not target_chest and
not (mode == "inventory") and
minetest.get_node(pos2).name ~= "air" then
return
end
local invName1 = ""
local invName2 = ""
if mode == "inventory" then
invName1 = meta:get_string("inv1")
invName2 = meta:get_string("inv2")
-- reverse inventory names too
if mreverse == 1 then
local invNamet = invName1
invName1 = invName2
invName2 = invNamet
end
end
-- inventory mode
if mode == "inventory" then
--if prefer == "" then meta:set_string("infotext", "Mover block. must set nodes to move (filter) in inventory mode."); return; end
2018-11-13 19:09:03 -08:00
-- forbidden nodes to take from in inventory mode - to prevent abuses
if basic_machines.limit_inventory_table[node1.name] then
-- forbidden to take from this inventory
if basic_machines.limit_inventory_table[node1.name][invName1] then
2018-11-13 19:09:03 -08:00
return
end
end
2018-11-13 19:09:03 -08:00
local stack, meta1, inv1
-- if prefer == "" then just pick one item from chest to transfer
if prefer == "" then
meta1 = minetest.get_meta(pos1)
inv1 = meta1:get_inventory()
-- nothing to move
if inv1:is_empty(invName1) then
return
end
local size = inv1:get_size(invName1)
2018-11-13 19:09:03 -08:00
local found = false
2018-11-13 19:09:03 -08:00
-- find item to move in inventory
for i = 1, size do
stack = inv1:get_stack(invName1, i)
-- prevent item stacks with more than 'stack_max' items
if stack:get_count() > stack:get_stack_max() then
stack:set_count(stack:get_stack_max())
2018-11-10 17:34:36 -08:00
else
stack:set_count(stack:get_count())
end
if not stack:is_empty() then found = true break end
end
if not found then return end
end
-- can we move item to target inventory?
if prefer ~= "" then
meta1 = minetest.get_meta(pos1)
inv1 = meta1:get_inventory()
-- nothing to move
if inv1:is_empty(invName1) then
return
end
local size = inv1:get_size(invName1)
local preferstack = ItemStack(prefer)
local found = false
-- find item to move in inventory
for i = 1, size do
stack = inv1:get_stack(invName1, i)
if stack:get_name() == preferstack:get_name() then
-- prevent item stacks with more than 'stack_max' items
if preferstack:get_count() > preferstack:get_stack_max() then
stack:set_count(preferstack:get_stack_max())
2018-11-10 17:34:36 -08:00
else
stack:set_count(preferstack:get_count())
end
found = true
break
end
end
if not found then
return
end
end
local meta2 = minetest.get_meta(pos2)
local inv2 = meta2:get_inventory()
if not inv2:room_for_item(invName2, stack) then
return
end
2018-11-13 19:09:03 -08:00
-- add item to target inventory and remove item from source inventory
if prefer ~= "" then
meta1 = minetest.get_meta(pos1)
inv1 = meta1:get_inventory()
end
2018-11-13 19:09:03 -08:00
if inv1:contains_item(invName1, stack) then
inv2:add_item(invName2, stack)
inv1:remove_item(invName1, stack)
else
-- admin is owner.. just add stuff
if upgrade == -1 then
inv2:add_item(invName2, stack)
-- item not found in chest
else
return
end
end
2018-11-13 19:09:03 -08:00
minetest.sound_play("chest_inventory_move", {
pos = pos2,
gain = 1.0,
max_hear_distance = 8
})
fuel = fuel - fuel_cost
meta:set_float("fuel", fuel)
meta:set_string("infotext", "Mover block. Fuel "..fuel)
2018-11-13 19:09:03 -08:00
return
2015-10-10 04:45:43 -07:00
end
2018-11-13 19:09:03 -08:00
-- filtering
-- prefered node set
if prefer ~= "" then
-- only take prefered node or from chests/inventories
if prefer ~= node1.name and
not source_chest and
mode ~= "inventory" then
return
end
2018-11-13 19:09:03 -08:00
-- take stuff from chest
if source_chest then
local cmeta = minetest.get_meta(pos1)
local inv = cmeta:get_inventory()
local stack = ItemStack(prefer)
2018-11-13 19:09:03 -08:00
-- prevent item stacks with more than 'stack_max' items
if stack:get_count() > stack:get_stack_max() then
stack:set_count(stack:get_stack_max())
else
stack:set_count(stack:get_count())
end
2018-11-13 19:09:03 -08:00
if inv:contains_item("main", stack) then
inv:remove_item("main", stack)
else
return
end
end
2018-11-13 19:09:03 -08:00
node1 = {}
node1.name = prefer
end
2018-11-13 19:09:03 -08:00
-- doesnt know what to take out of chest/inventory
if (prefer == "" and source_chest) then
return
end
2018-11-13 19:09:03 -08:00
-- 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
-- check for cactus or tree
local count = 0
-- digs up node as a tree
local dig_up = false
if dig then
if not source_chest and
basic_machines.dig_up_table[node1.name] then
dig_up = true
end
2018-11-13 19:09:03 -08:00
2018-12-07 16:50:41 -08:00
-- do we harvest the node? (only for mese crystals)
if not source_chest then
if basic_machines.harvest_table[node1.name] ~= nil then
harvest = true
2018-11-13 19:09:03 -08:00
local remains = basic_machines.harvest_table[node1.name][1]
local result = basic_machines.harvest_table[node1.name][2]
minetest.set_node(pos1,{name = remains})
inv:add_item("main", result)
end
end
2018-11-13 19:09:03 -08:00
-- dig up to 16 nodes
if dig_up == true then
local r = 1
if node1.name == "default:cactus" or
node1.name == "default:papyrus" then
r = 0
end
2018-11-13 19:09:03 -08:00
-- acacia trees grow wider than others
if node1.name == "default:acacia_tree" then
r = 2
end
2018-11-13 19:09:03 -08:00
local positions = minetest.find_nodes_in_area({x = pos1.x - r, y = pos1.y, z = pos1.z - r}, {x = pos1.x + r, y = pos1.y + 16, z = pos1.z + r}, node1.name)
2018-11-13 19:09:03 -08:00
local def = minetest.registered_nodes[node1.name]
local distance_ok = vector.distance(pos1, pos2) <= 16
local texture = "default_dirt.png"
-- try to find a node texture
if def then
if def.tiles then
if #def.tiles > 0 then
if type(def.tiles[1]) == "string" then
texture = def.tiles[1]
end
end
end
end
for _, pos3 in ipairs(positions) do
minetest.set_node(pos3, {name = "air"})
count = count + 1
-- add particles only when not too far
if distance_ok then
minetest.add_particlespawner({
amount = math.random(1, 3),
time = 0.5,
minpos = {x=pos3.x-0.7, y=pos3.y, z=pos3.z-0.7},
maxpos = {x=pos3.x+0.7, y=pos3.y+0.75, z=pos3.z+0.7},
minvel = {x = -0.5, y = -4, z = -0.5},
maxvel = {x = 0.5, y = -2, z = 0.5},
minacc = {x = -0.5, y = -4, z = -0.5},
maxacc = {x = 0.5, y = -2, z = 0.5},
minexptime = 0.5,
maxexptime = 1,
minsize = 0.5,
maxsize = 2,
collisiondetection = true,
texture = texture
})
end
end
2018-11-13 19:09:03 -08:00
-- if tree or cactus was digged up
2018-12-07 16:50:41 -08:00
inv:add_item("main", node1.name.." "..count - 1)
end
2018-11-13 19:09:03 -08:00
-- minetest drop code emulation
if not harvest then
local table = minetest.registered_items[node1.name]
if table ~= nil then --put in chest
if table.drop ~= nil then -- drop handling
if table.drop.items then
--handle drops better, emulation of drop code
local max_items = table.drop.max_items or 0
if max_items == 0 then -- just drop all the items (taking the rarity into consideration)
max_items = #table.drop.items or 0
end
local drop = table.drop
local i = 0
for k, v in pairs(drop.items) do
if i > max_items then
break
end
i = i + 1
local rare = v.rarity or 1
if math.random(1, rare) == 1 then
node1 = {}
-- pick item randomly from list
node1.name = v.items[math.random(1, #v.items)]
inv:add_item("main",node1.name)
end
end
else
inv:add_item("main", table.drop)
end
else
inv:add_item("main", node1.name)
end
2018-11-13 19:09:03 -08:00
end
end
-- if not dig just put it in
else
inv:add_item("main", node1.name)
2015-05-11 04:20:54 -07:00
end
2015-05-01 09:40:54 -07:00
end
2018-11-13 19:09:03 -08:00
minetest.sound_play("transporter", {
pos = pos2,
gain = 1.0,
max_hear_distance = 8
})
2018-11-13 19:09:03 -08:00
-- chest to chest transport has lower cost, *0.1
if target_chest and source_chest then
fuel_cost = fuel_cost * 0.1
end
2018-11-13 19:09:03 -08:00
fuel = fuel - fuel_cost
meta:set_float("fuel", fuel)
meta:set_string("infotext", "Mover block. Fuel "..fuel)
2018-11-13 19:09:03 -08:00
-- transport nodes parallel as defined by source1 and target, clone with complete metadata
if mode == "transport" then
local meta1 = minetest.get_meta(pos1):to_table()
2018-11-13 19:09:03 -08:00
minetest.set_node(pos2, minetest.get_node(pos1))
minetest.get_meta(pos2):from_table(meta1)
minetest.set_node(pos1,{name = "air"})
minetest.get_meta(pos1):from_table(nil)
2018-11-13 19:09:03 -08:00
return
end
-- REMOVE DIGGED NODE
if not target_chest then
if not drop then
-- get node (seed) table definition
2018-12-07 16:50:41 -08:00
local def = minetest.registered_nodes[node1.name]
local name_parts = node1.name:split(":")
-- create pointed_thing table
local pointed_thing = {
type = "node",
above = {
y = pos2.y,
x = pos2.x,
z = pos2.z
},
under = {
y = pos2.y - 1,
x = pos2.x,
z = pos2.z
}
}
-- create ItemStack table
local stack = ItemStack(node1.name)
local placer = minetest.get_player_by_name(owner)
2018-12-07 16:50:41 -08:00
-- use default behaviour on_place if found in def
if def and
def.on_place and
placer ~= nil and
2018-12-03 18:47:39 -08:00
(name_parts[1] == "farming" or name_parts[1] == "farming_addons" ) then
2018-12-07 16:50:41 -08:00
def.on_place(stack, placer, pointed_thing)
-- add particles only when not too far
if vector.distance(pos1, pos2) <= 16 then
local texture = "default_dirt.png"
-- try to find a node texture
if def.tiles then
if #def.tiles > 0 then
if type(def.tiles[1]) == "string" then
texture = def.tiles[1]
end
end
2018-12-07 16:50:41 -08:00
end
minetest.add_particlespawner({
amount = math.random(3, 6),
2018-12-07 16:50:41 -08:00
time = 0.5,
2018-12-07 17:00:52 -08:00
minpos = {x=pos2.x-0.7, y=pos2.y, z=pos2.z-0.7},
maxpos = {x=pos2.x+0.7, y=pos2.y+0.75, z=pos2.z+0.7},
2018-12-07 16:50:41 -08:00
minvel = {x = -0.5, y = -4, z = -0.5},
2018-12-07 17:00:52 -08:00
maxvel = {x = 0.5, y = -2, z = 0.5},
minacc = {x = -0.5, y = -4, z = -0.5},
maxacc = {x = 0.5, y = -2, z = 0.5},
2018-12-07 16:50:41 -08:00
minexptime = 0.5,
maxexptime = 1,
2018-12-07 17:00:52 -08:00
minsize = 0.5,
2018-12-07 16:50:41 -08:00
maxsize = 2,
collisiondetection = true,
texture = texture
})
end
-- on_place not found in def - use set_node instead
else
minetest.set_node(pos2, {name = node1.name})
2018-12-07 16:50:41 -08:00
if def then
-- add particles only when not too far
if vector.distance(pos1, pos2) <= 16 then
local texture = "default_dirt.png"
2018-12-07 16:50:41 -08:00
-- try to find a node texture
if def.tiles then
if #def.tiles > 0 then
if type(def.tiles[1]) == "string" then
texture = def.tiles[1]
end
end
end
2018-12-07 16:50:41 -08:00
minetest.add_particlespawner({
amount = math.random(3, 6),
time = 0.5,
minpos = {x=pos2.x-0.7, y=pos2.y, z=pos2.z-0.7},
maxpos = {x=pos2.x+0.7, y=pos2.y+0.75, z=pos2.z+0.7},
minvel = {x = -0.5, y = -4, z = -0.5},
maxvel = {x = 0.5, y = -2, z = 0.5},
minacc = {x = -0.5, y = -4, z = -0.5},
maxacc = {x = 0.5, y = -2, z = 0.5},
minexptime = 0.5,
maxexptime = 1,
minsize = 0.5,
maxsize = 2,
collisiondetection = true,
texture = texture
})
end
2018-12-07 16:50:41 -08:00
end
end
end
2018-11-13 19:09:03 -08:00
if drop then
local stack = ItemStack(node1.name)
-- drops it
minetest.add_item(pos2,stack)
end
end
2018-11-13 19:09:03 -08:00
if not (source_chest) and not (harvest) then
if dig then
minetest.check_for_falling(pos1)
end
2018-12-08 06:39:45 -08:00
local def = minetest.registered_nodes[node1.name]
minetest.set_node(pos1, {name = "air"})
2018-12-07 16:50:41 -08:00
if def then
-- add particles only when not too far
if vector.distance(pos1, pos2) <= 16 then
local texture = "default_dirt.png"
-- try to find a node texture
if def.tiles then
if #def.tiles > 0 then
if type(def.tiles[1]) == "string" then
texture = def.tiles[1]
end
end
end
2018-12-07 16:50:41 -08:00
minetest.add_particlespawner({
amount = math.random(3, 6),
time = 0.5,
minpos = {x=pos1.x-0.5, y=pos1.y, z=pos1.z-0.5},
maxpos = {x=pos1.x+0.5, y=pos1.y+0.75, z=pos1.z+0.5},
minvel = {x = -0.5, y = -4, z = -0.5},
maxvel = {x = 0.5, y = -2, z = 0.5},
minacc = {x = -0.5, y = -4, z = -0.5},
maxacc = {x = 0.5, y = -2, z = 0.5},
minexptime = 0.5,
maxexptime = 1,
minsize = 0.5,
maxsize = 2,
collisiondetection = true,
texture = texture
})
2018-12-07 16:50:41 -08:00
end
end
2018-11-02 13:46:33 -07:00
end
end, -- /action_on - mover
2018-11-02 13:46:33 -07:00
-- this toggles reverse option of mover
action_off = function(pos, node,ttl)
if type(ttl) ~= "number" then
ttl = 1
end
2018-11-13 19:09:03 -08:00
local meta = minetest.get_meta(pos)
local mreverse = meta:get_int("reverse")
local mode = meta:get_string("mode")
2018-11-13 19:09:03 -08:00
-- reverse switching is not very helpful when auto harvest trees for example
if mode ~= "dig" then
if mreverse == 1 then
mreverse = 0
elseif mreverse == 0 then
mreverse = 1
end
meta:set_int("reverse", mreverse)
end
end
} -- /effector - mover
2015-05-01 09:40:54 -07:00
}
}) -- /mover - register_node
2015-05-01 09:40:54 -07:00
-- KEYPAD --
2017-12-21 09:06:15 -08:00
local function use_keypad(pos,ttl, again) -- position, time to live ( how many times can signal travel before vanishing to prevent infinite recursion ), do we want to activate again
2018-11-13 19:09:03 -08:00
2016-03-18 01:32:25 -07:00
if ttl<0 then return end;
2018-11-13 19:09:03 -08:00
local meta = minetest.get_meta(pos);
local t0 = meta:get_int("t");
2018-11-13 19:09:03 -08:00
local t1 = minetest.get_gametime();
local T = meta:get_int("T"); -- temperature
2018-11-13 19:09:03 -08:00
if t0>t1-machines_minstep then -- activated before natural time
T=T+1;
else
2018-11-13 19:09:03 -08:00
if T>0 then
T=T-1
2016-06-12 11:44:58 -07:00
if t1-t0>5 then T = 0 end
end
end
meta:set_int("T",T);
meta:set_int("t",t1); -- update last activation time
2018-11-13 19:09:03 -08:00
if T > 2 then -- overheat
minetest.sound_play("default_cool_lava",{pos = pos, max_hear_distance = 16, gain = 0.25})
meta:set_string("infotext","overheat: temperature ".. T)
return
end
2018-11-13 19:09:03 -08:00
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); return end
local count = meta:get_int("count") or 0; -- counts how many repeats left
2018-11-13 19:09:03 -08:00
2017-12-21 09:06:15 -08:00
local repeating = meta:get_int("repeating");
2018-11-13 19:09:03 -08:00
if repeating==1 and again~=1 then
2017-12-21 09:06:15 -08:00
-- stop it
meta:set_int("repeating",0);
meta:set_int("count", 0)
meta:set_int("T",4);
meta:set_string("infotext", "#KEYPAD: reseting. Punch again after 5s to activate")
return;
2018-11-13 19:09:03 -08:00
end
2017-12-21 09:06:15 -08:00
if count>0 then -- this is keypad repeating its activation
2018-11-13 19:09:03 -08:00
count = count - 1; meta:set_int("count",count);
2017-12-21 09:06:15 -08:00
else
2018-11-13 19:09:03 -08:00
meta:set_int("repeating",0);
--return
end
2018-11-13 19:09:03 -08:00
if count>=0 then
meta:set_string("infotext", "Keypad operation: ".. count .." cycles left")
else
meta:set_string("infotext", "Keypad operation: activation ".. -count)
end
2018-11-13 19:09:03 -08:00
if count>0 then -- only trigger repeat if count on
2017-12-21 09:06:15 -08:00
if repeating == 0 then meta:set_int("repeating",1); end-- its repeating now
if basic_machines.clockgen==0 then return end
2018-11-13 19:09:03 -08:00
minetest.after(machines_timer, function()
use_keypad(pos,machines_TTL,1)
end )
end
2018-11-13 19:09:03 -08:00
local x0,y0,z0,mode;
2015-05-01 09:40:54 -07:00
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");
-- pass the signal on to target, depending on mode
2018-11-13 19:09:03 -08:00
local tpos = {x=x0,y=y0,z=z0}; -- target position
local node = minetest.get_node(tpos);if not node.name then return end -- error
2018-11-13 19:09:03 -08:00
local text = meta:get_string("text");
if text ~= "" then -- TEXT MODE; set text on target
if text == "@" then -- keyboard mode, set text from input
text = meta:get_string("input") or "";
meta:set_string("input",""); -- clear input again
end
2018-11-13 19:09:03 -08:00
local bit = string.byte(text);
if bit == 33 then -- if text starts with !, then we send chat text to all nearby players, radius 5
text = string.sub(text,2) ; if not text or text == "" then return end
local players = minetest.get_connected_players();
for _,player in pairs(players) do
local pos1 = player:getpos();
local dist = math.sqrt((pos1.x-tpos.x)^2 + (pos1.y-tpos.y)^2 + (pos1.z-tpos.z)^2 );
if dist<=5 then
minetest.chat_send_player(player:get_player_name(), text)
end
end
return
elseif bit == 36 then-- text starts with $, play sound
text = string.sub(text,2) ; if not text or text == "" then return end
minetest.sound_play(text, {pos=pos,gain=1.0,max_hear_distance = 16,})
end
2018-11-13 19:09:03 -08:00
local tmeta = minetest.get_meta(tpos);if not tmeta then return end
2018-11-13 19:09:03 -08:00
if basic_machines.signs[node.name] then -- update text on signs with signs_lib
tmeta:set_string("infotext", text);
tmeta:set_string("text",text);
local table = minetest.registered_nodes[node.name];
if not table.on_punch then return end -- error
if signs_lib and signs_lib.update_sign then
--signs_lib.update_sign(pos)
table.on_punch(tpos, node, nil); -- warning - this can cause problems if no signs_lib installed
end
2018-11-13 19:09:03 -08:00
return
end
2018-11-13 19:09:03 -08:00
-- target is keypad, special functions: @, % that output to target keypad text
if node.name == "basic_machines:keypad" then -- special modify of target keypad text and change its target
2018-11-13 19:09:03 -08:00
x0=tmeta:get_int("x0");y0=tmeta:get_int("y0");z0=tmeta:get_int("z0");
x0=tpos.x+x0;y0=tpos.y+y0;z0=tpos.z+z0;
tpos = {x=x0,y=y0,z=z0};
2018-11-13 19:09:03 -08:00
if string.byte(text) == 64 then -- target keypad's text starts with @ ( ascii code 64) -> character replacement
text = string.sub(text,2); if not text or text == "" then return end
--read words[j] from blocks above keypad:
local j=0;
2018-11-13 19:09:03 -08:00
text = string.gsub(text, "@",
function()
j=j+1;
return minetest.get_meta({x=pos.x,y=pos.y+j,z=pos.z}):get_string("infotext")
end
) ; -- replace every @ in ttext with string on blocks above
-- set target keypad's text
--tmeta = minetest.get_meta(tpos);if not tmeta then return end
tmeta:set_string("text", text);
elseif string.byte(text) == 37 then -- target keypad's text starts with % ( ascii code 37) -> word extraction
2018-11-13 19:09:03 -08:00
local ttext = minetest.get_meta({x=pos.x,y=pos.y+1,z=pos.z}):get_string("infotext")
2018-11-13 19:09:03 -08:00
local i = basic_machines.tonumber(string.sub(text,2,2)) or 1; --read the number following the %
--extract i-th word from text
local j = 0;
for word in string.gmatch(ttext, "%S+") do
j=j+1; if j == i then text = word; break; end
end
2018-11-13 19:09:03 -08:00
-- set target keypad's target's text
--tmeta = minetest.get_meta(tpos); if not tmeta then return end
tmeta:set_string("text", text);
2018-11-13 19:09:03 -08:00
else
if string.byte(text) == 64 then -- if text starts with @ clear target keypad text
2018-11-13 19:09:03 -08:00
tmeta:set_string("text","");
return
end
-- just set text..
--tmeta = minetest.get_meta(tpos); if not tmeta then return end
tmeta:set_string("infotext", text);
end
return
end
2018-11-13 19:09:03 -08:00
if node.name == "basic_machines:detector" then -- change filter on detector
if string.byte(text) == 64 then -- if text starts with @ clear the filter
tmeta:set_string("node","");
else
-- prevent item stacks with more than 'stack_max' items
local textstack = ItemStack(text)
if textstack:get_count() > textstack:get_stack_max() then
textstack:set_count(textstack:get_stack_max())
2018-11-10 17:34:36 -08:00
else
textstack:set_count(textstack:get_count())
end
tmeta:set_string("node", textstack:to_string());
end
return
end
2018-11-13 19:09:03 -08:00
if node.name == "basic_machines:mover" then -- change filter on mover
if string.byte(text) == 64 then -- if text starts with @ clear the filter
tmeta:set_string("prefer","");
else
-- prevent item stacks with more than 'stack_max' items
local textstack = ItemStack(text)
if textstack:get_count() > textstack:get_stack_max() then
textstack:set_count(textstack:get_stack_max())
2018-11-10 17:34:36 -08:00
else
textstack:set_count(textstack:get_count())
end
tmeta:set_string("prefer", textstack:to_string());
end
return
end
2018-11-13 19:09:03 -08:00
2017-12-21 09:06:15 -08:00
if node.name == "basic_machines:distributor" then
local i = string.find(text," ");
if i then
2018-11-13 19:09:03 -08:00
local ti = basic_machines.tonumber(string.sub(text,1,i-1)) or 1;
local tm = basic_machines.tonumber(string.sub(text,i+1)) or 1;
2017-12-21 09:06:15 -08:00
if ti>=1 and ti<=16 and tm>=-2 and tm<=2 then
tmeta:set_int("active"..ti,tm)
end
end
return
end
2018-11-13 19:09:03 -08:00
tmeta:set_string("infotext", text); -- else just set text
end
2018-11-13 19:09:03 -08:00
--activate target
2015-05-01 09:40:54 -07:00
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;
2018-11-13 19:09:03 -08:00
if mode == 3 then -- keypad in toggle mode
local state = meta:get_int("state") or 0;state = 1-state; meta:set_int("state",state);
if state == 0 then mode = 1 else mode = 2 end
2017-01-06 03:07:10 -08:00
end
2017-12-19 02:59:05 -08:00
-- pass the signal on to target
2018-11-13 19:09:03 -08:00
2017-01-06 03:07:10 -08:00
if mode == 2 then -- on
if not effector.action_on then return end
effector.action_on(tpos,node,ttl-1); -- run
elseif mode == 1 then -- off
if not effector.action_off then return end
effector.action_off(tpos,node,ttl-1); -- run
end
2018-11-13 19:09:03 -08:00
2015-05-01 09:40:54 -07:00
end
local function check_keypad(pos,name,ttl) -- called only when manually activated via punch
2015-05-01 09:40:54 -07:00
local meta = minetest.get_meta(pos);
local pass = meta:get_string("pass");
2018-11-13 19:09:03 -08:00
if pass == "" then
local iter = meta:get_int("iter");
local count = meta:get_int("count");
if count<iter-1 or iter<2 then meta:set_int("active_repeats",0) end -- so that keypad can work again, at least one operation must have occured though
2017-12-21 09:06:15 -08:00
meta:set_int("count",iter); use_keypad(pos,machines_TTL,0) -- time to live set when punched
2018-11-13 19:09:03 -08:00
return
end
2015-05-05 14:34:03 -07:00
if name == "" then return end
2018-11-13 19:09:03 -08:00
if meta:get_string("text") == "@" then -- keypad works as a keyboard
2018-11-13 19:09:03 -08:00
local form =
"size[3,1]" .. -- width, height
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
"field[0.25,0.25;3,1;pass;Enter text: ;".."".."] button_exit[0.,0.5;1,1;OK;OK]";
minetest.show_formspec(name, "basic_machines:check_keypad_"..minetest.pos_to_string(pos), form)
return
end
2018-11-13 19:09:03 -08:00
2015-05-01 09:40:54 -07:00
pass = ""
2018-11-13 19:09:03 -08:00
local form =
"size[3,1.25]" .. -- width, height
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
"field[0.25,0.25;3,1;pass;Enter Password: ;".."".."] button_exit[0.,0.75;1,1;OK;OK]";
2015-05-01 09:40:54 -07:00
minetest.show_formspec(name, "basic_machines:check_keypad_"..minetest.pos_to_string(pos), form)
2017-12-21 09:06:15 -08:00
return
2015-05-01 09:40:54 -07:00
end
2015-05-05 16:16:12 -07:00
minetest.register_node("basic_machines:keypad", {
description = "Keypad - basic way to activate machines by sending signal",
2015-05-05 16:16:12 -07:00
tiles = {"keypad.png"},
2017-01-03 07:51:50 -08:00
groups = {cracky=3, mesecon_effector_on = 1},
sounds = default.node_sound_metal_defaults(),
2015-05-05 16:16:12 -07:00
after_place_node = function(pos, placer)
local meta = minetest.env:get_meta(pos)
2016-05-04 06:11:48 -07:00
meta:set_string("infotext", "Keypad. Right click to set it up or punch it. Set any password and text \"@\" to work as keyboard.")
2015-05-05 16:16:12 -07:00
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
2018-11-13 19:09:03 -08:00
meta:set_string("pass", "");meta:set_int("mode",2); -- pasword, mode of operation
meta:set_int("iter",1);meta:set_int("count",0); -- how many repeats to do, current repeat count
2015-05-06 12:10:17 -07:00
local name = placer:get_player_name();punchset[name] = {};punchset[name].state = 0
2015-05-05 16:16:12 -07:00
end,
2018-11-13 19:09:03 -08:00
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
2017-12-21 09:06:15 -08:00
use_keypad(pos,0,0) -- activate just 1 time
end
}
},
2015-05-05 16:16:12 -07:00
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());
local cant_build = minetest.is_protected(pos,player:get_player_name());
2018-11-13 19:09:03 -08:00
--meta:get_string("owner")~=player:get_player_name() and
if not privs.privs and cant_build then
return
end -- only ppl sharing protection can set up keypad
local x0,y0,z0,x1,y1,z1,pass,iter,mode;
2015-05-05 16:16:12 -07:00
x0=meta:get_int("x0");y0=meta:get_int("y0");z0=meta:get_int("z0");iter=meta:get_int("iter") or 1;
local text = meta:get_string("text") or "";
mode = meta:get_int("mode") or 1;
2018-11-13 19:09:03 -08:00
2015-05-06 05:56:42 -07:00
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
2018-11-13 19:09:03 -08:00
2015-05-05 16:16:12 -07:00
pass = meta:get_string("pass");
2018-11-13 19:09:03 -08:00
local form =
"size[4.25,3.75]" .. -- width, height
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
2018-11-13 19:09:03 -08:00
"field[2.25,0.25;2.25,1;pass;Password: ;"..pass.."]" ..
2017-12-25 13:06:43 -08:00
"field[0.25,2.5;3.25,1;text;text;".. text .."]" ..
"field[0.25,0.25;1,1;mode;mode;"..mode.."]".. "field[1.25,0.25;1,1;iter;repeat;".. iter .."]"..
2018-11-13 19:09:03 -08:00
2017-12-25 13:06:43 -08:00
"label[0.,0.75;".. minetest.colorize("lawngreen","MODE: 1=OFF/2=ON/3=TOGGLE").."]"..
"field[0.25,3.5;1,1;x0;target;"..x0.."] field[1.25,3.5;1,1;y0;;"..y0.."] field[2.25,3.5;1,1;z0;;"..z0.."]"..
"button_exit[3.25,3.25;1,1;help;help] button_exit[3.25,2.25;1,1;OK;OK]"
2018-11-13 19:09:03 -08:00
;
-- if meta:get_string("owner")==player:get_player_name() then
minetest.show_formspec(player:get_player_name(), "basic_machines:keypad_"..minetest.pos_to_string(pos), form)
-- else
-- minetest.show_formspec(player:get_player_name(), "view_only_basic_machines_keypad", form)
-- end
2015-05-05 16:16:12 -07:00
end
})
-- DETECTOR --
2015-05-01 09:40:54 -07:00
minetest.register_node("basic_machines:detector", {
description = "Detector - can detect blocks/players/objects and activate machines",
2015-05-01 09:40:54 -07:00
tiles = {"detector.png"},
2017-01-03 07:51:50 -08:00
groups = {cracky=3, mesecon_effector_on = 1},
sounds = default.node_sound_metal_defaults(),
2015-05-01 09:40:54 -07:00
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("x0",0);meta:set_int("y0",0);meta:set_int("z0",0); -- source1: read
meta:set_int("x1",0);meta:set_int("y1",0);meta:set_int("z1",0); -- source1: read
2016-04-04 14:55:10 -07:00
meta:set_int("x2",0);meta:set_int("y2",1);meta:set_int("z2",0); -- target: activate
meta:set_int("r",0)
meta:set_string("node","");meta:set_int("NOT",2);
meta:set_string("mode","node");
2015-05-05 14:34:03 -07:00
meta:set_int("public",0);
meta:set_int("state",0);
2018-11-13 19:09:03 -08:00
local inv = meta:get_inventory();inv:set_size("mode_select", 3*1)
inv:set_stack("mode_select", 1, ItemStack("default:coal_lump"))
2015-05-06 12:10:17 -07:00
local name = placer:get_player_name();punchset[name] = {}; punchset[name].node = ""; punchset[name].state = 0
2015-05-01 09:40:54 -07:00
end,
2015-05-01 09:40:54 -07:00
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());
2018-11-13 19:09:03 -08:00
local cant_build = minetest.is_protected(pos,player:get_player_name());
--meta:get_string("owner")~=player:get_player_name() and
2018-11-13 19:09:03 -08:00
if not privs.privs and cant_build then
return
end
2016-04-02 00:38:14 -07:00
local x0,y0,z0,x1,y1,z1,x2,y2,z2,r,node,NOT,mode,op;
2015-05-05 14:34:03 -07:00
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");r=meta:get_int("r");
2016-04-02 00:38:14 -07:00
mode=meta:get_string("mode"); op = meta:get_string("op");
local mode_list = {["node"]=1,["player"]=2,["object"]=3,["inventory"]=4, ["infotext"] = 5, ["light"]=6};
mode = mode_list[mode] or 1;
local op_list = {[""]=1,["AND"]=2,["OR"]=3};
2016-04-02 00:38:14 -07:00
op = op_list[op] or 1;
2018-11-13 19:09:03 -08:00
2015-05-06 05:56:42 -07:00
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.pos11[player:get_player_name()] = {x=pos.x+x1,y=pos.y+y1,z=pos.z+z1};machines.mark_pos11(player:get_player_name()) -- mark pos11
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
2015-05-06 05:56:42 -07:00
local inv1=1;
local inv1m = meta:get_string("inv1");
local meta1=minetest.get_meta({x=pos.x+x0,y=pos.y+y0,z=pos.z+z0});
local list1 = meta1:get_inventory():get_lists(); local inv_list1 = ""; local j;
j=1; -- stupid dropdown requires item index but returns string on receive so we have to find index.. grrr, one other solution: invert the table: key <-> value
2018-11-13 19:09:03 -08:00
for i in pairs( list1) do
inv_list1 = inv_list1 .. i .. ",";
if i == inv1m then inv1=j end; j=j+1;
end
2018-11-13 19:09:03 -08:00
2015-05-05 14:34:03 -07:00
node=meta:get_string("node") or "";
NOT=meta:get_int("NOT");
local list_name = "nodemeta:"..pos.x..','..pos.y..','..pos.z
2018-11-13 19:09:03 -08:00
local form =
"size[4,6.25]" .. -- width, height
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
2018-11-13 19:09:03 -08:00
"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.."]"..
"dropdown[3,0.25;1,1;op; ,AND,OR;".. op .."]"..
2018-11-13 19:09:03 -08:00
"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.."]"..
"field[0.25,3.5;2,1;node;Node/player/object: ;"..node.."]".."field[3.25,2.5;1,1;r;radius;"..r.."]"..
"dropdown[0,4.5;3,1;mode;node,player,object,inventory,infotext,light;".. mode .."]"..
"dropdown[0,5.5;3,1;inv1;"..inv_list1..";".. inv1 .."]"..
2017-12-25 13:06:43 -08:00
"label[0.,4.0;" .. minetest.colorize("lawngreen", "MODE selection") .. "]"..
"label[0.,5.2;inventory selection]"..
"field[2.25,3.5;2,1;NOT;filter out -2/-1/0/1/2/3/4;"..NOT.."]"..
"button[3.,4.4;1,1;help;help] button_exit[3.,5.4;1,1;OK;OK] "
2018-11-13 19:09:03 -08:00
--if meta:get_string("owner")==player:get_player_name() then
minetest.show_formspec(player:get_player_name(), "basic_machines:detector_"..minetest.pos_to_string(pos), form)
-- else
-- minetest.show_formspec(player:get_player_name(), "view_only_basic_machines_detector", form)
-- end
end,
2018-11-13 19:09:03 -08:00
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
2018-11-13 19:09:03 -08:00
2017-07-30 15:09:40 -07:00
if minetest.is_protected(pos, player:get_player_name()) then
minetest.record_protection_violation(pos, player:get_player_name())
return 0
end
2018-11-13 19:09:03 -08:00
return 0
end,
2018-11-13 19:09:03 -08:00
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
2018-11-13 19:09:03 -08:00
2017-07-30 15:09:40 -07:00
if minetest.is_protected(pos, player:get_player_name()) then
minetest.record_protection_violation(pos, player:get_player_name())
return 0
end
2018-11-13 19:09:03 -08:00
return 0
end,
2018-11-13 19:09:03 -08:00
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
local meta = minetest.get_meta(pos);
local mode = "node";
2018-11-13 19:09:03 -08:00
if to_index == 2 then
mode = "player";
meta:set_int("r",math.max(meta:get_int("r"),1))
end
2018-11-13 19:09:03 -08:00
if to_index == 3 then
mode = "object";
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,
2018-11-13 19:09:03 -08:00
mesecons = {effector = {
action_on = function (pos, node,ttl)
if ttl<0 then return end
2018-11-13 19:09:03 -08:00
local meta = minetest.get_meta(pos);
2018-11-13 19:09:03 -08:00
local t0 = meta:get_int("t");
2018-11-13 19:09:03 -08:00
local t1 = minetest.get_gametime();
local T = meta:get_int("T"); -- temperature
2018-11-13 19:09:03 -08:00
if t0>t1-machines_minstep then -- activated before natural time
T=T+1;
else
if T>0 then T=T-1 end
end
meta:set_int("T",T);
meta:set_int("t",t1); -- update last activation time
2018-11-13 19:09:03 -08:00
if T > 2 then -- overheat
minetest.sound_play("default_cool_lava",{pos = pos, max_hear_distance = 16, gain = 0.25})
meta:set_string("infotext","overheat: temperature ".. T)
return
2018-11-13 19:09:03 -08:00
end
local x0,y0,z0,x1,y1,z1,x2,y2,z2,r,node,NOT,mode,op;
x0=meta:get_int("x0")+pos.x;y0=meta:get_int("y0")+pos.y;z0=meta:get_int("z0")+pos.z;
x2=meta:get_int("x2")+pos.x;y2=meta:get_int("y2")+pos.y;z2=meta:get_int("z2")+pos.z;
2018-11-13 19:09:03 -08:00
r = meta:get_int("r") or 0; NOT = meta:get_int("NOT")
node=meta:get_string("node") or ""; mode=meta:get_string("mode") or ""; op = meta:get_string("op") or "";
2018-11-13 19:09:03 -08:00
local trigger = false
local detected_obj = "";
if mode == "node" then
local tnode = minetest.get_node({x=x0,y=y0,z=z0}).name; -- read node at source position
detected_obj = tnode;
2018-11-13 19:09:03 -08:00
if node~="" and string.find(tnode,"default:chest") then -- if 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
2018-11-13 19:09:03 -08:00
-- operation: AND, OR... look at other source position too
2018-11-13 19:09:03 -08:00
if op~= "" then
local trigger1 = false;
x1=meta:get_int("x1")+pos.x;y1=meta:get_int("y1")+pos.y;z1=meta:get_int("z1")+pos.z;
tnode = minetest.get_node({x=x1,y=y1,z=z1}).name; -- read node at source position
2018-11-13 19:09:03 -08:00
if node~="" and string.find(tnode,"default:chest") then -- it source is chest, look inside chest for items
local cmeta = minetest.get_meta({x=x1,y=y1,z=z1});
local inv = cmeta:get_inventory();
local stack = ItemStack(node)
if inv:contains_item("main", stack) then trigger1 = true end
else -- source not a chest
if (node=="" and tnode~="air") or node == tnode then trigger1 = 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 trigger1 = true end
end
end
2018-11-13 19:09:03 -08:00
if op == "AND" then
trigger = trigger and trigger1;
2016-04-04 05:18:26 -07:00
elseif op == "OR" then
trigger = trigger or trigger1;
end
end
elseif mode=="inventory" then
local cmeta = minetest.get_meta({x = x0, y = y0, z = z0})
local inv = cmeta:get_inventory()
local stack = ItemStack(node)
local inv1m =meta:get_string("inv1")
-- if there is item report name and trigger
if node == "" then
if inv:is_empty(inv1m) then
trigger = false
-- nonempty
else
trigger = true
local size = inv:get_size(inv1m)
-- find item to move in inventory
for i = 1, size do
local stack = inv:get_stack(inv1m, i)
if not stack:is_empty() then
detected_obj = stack:to_string()
break
end
end
end
-- node name was set
else
local stack = ItemStack(node);
if inv:contains_item(inv1m, stack) then trigger = true end
end
elseif mode == "infotext" then
local cmeta = minetest.get_meta({x=x0,y=y0,z=z0});
detected_obj = cmeta:get_string("infotext");
if detected_obj == node or node =="" then trigger = true end
elseif mode == "light" then
detected_obj=minetest.get_node_light({x=x0,y=y0,z=z0}) or 0;
2018-11-13 19:09:03 -08:00
if detected_obj>=(basic_machines.tonumber(node) or 0) or node == "" then trigger = true end
else -- players/objects
local objects = minetest.get_objects_inside_radius({x=x0,y=y0,z=z0}, r)
local player_near=false;
for _,obj in pairs(objects) do
if mode == "player" then
2018-11-13 19:09:03 -08:00
if obj:is_player() then
player_near = true
detected_obj = obj:get_player_name();
2018-11-13 19:09:03 -08:00
if (node=="" or detected_obj==node) then
trigger = true break
end
2018-11-13 19:09:03 -08:00
end;
elseif mode == "object" and not obj:is_player() then
if obj:get_luaentity() then
detected_obj = obj:get_luaentity().itemstring or "";
2018-11-13 19:09:03 -08:00
if detected_obj == "" then
detected_obj = obj:get_luaentity().name or ""
end
2018-11-13 19:09:03 -08:00
if detected_obj==node then trigger=true break end
end
if node=="" then trigger = true break end
end
end
2018-11-13 19:09:03 -08:00
if node~="" and NOT==-1 and not(trigger) and not(player_near) and mode == "player" then
trigger = true
end-- name specified, but noone around and negation -> 0
2018-11-13 19:09:03 -08:00
end
2018-11-13 19:09:03 -08:00
-- negation and output filtering
local state = meta:get_int("state");
2018-11-13 19:09:03 -08:00
if NOT == 1 then -- just go on normally
-- -2: only false, -1: NOT, 0: no signal, 1: normal signal: 2: only true
elseif NOT == -1 then trigger = not trigger -- NEGATION
elseif NOT == -2 and trigger then return -- ONLY FALSE
elseif NOT == 0 then return -- do nothing
elseif NOT == 2 and not trigger then return -- ONLY TRUE
elseif NOT == 3 and ((trigger and state == 1) or (not trigger and state == 0)) then return -- no change of state
end
2018-11-13 19:09:03 -08:00
local nstate;
if trigger then nstate = 1 else nstate=0 end -- next detector output state
if nstate~=state then meta:set_int("state",nstate) end -- update state if changed
2018-11-13 19:09:03 -08:00
local node = minetest.get_node({x=x2,y=y2,z=z2});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;
2018-11-13 19:09:03 -08:00
if trigger then -- activate target node if succesful
meta:set_string("infotext", "detector: on");
if not effector.action_on then return end
if NOT == 4 then -- set detected object name as target text (target must be keypad, if not changes infotext)
if minetest.get_node({x=x2,y=y2,z=z2}).name == "basic_machines:keypad" then
detected_obj = detected_obj or "";
local tmeta = minetest.get_meta({x=x2,y=y2,z=z2});
tmeta:set_string("text",detected_obj);
end
end
effector.action_on({x=x2,y=y2,z=z2},node,ttl-1); -- run
2018-11-13 19:09:03 -08:00
else
meta:set_string("infotext", "detector: off");
if not effector.action_off then return end
effector.action_off({x=x2,y=y2,z=z2},node,ttl-1); -- run
end
end
}
}
})
2017-12-21 12:05:43 -08:00
-- minetest.register_chatcommand("clockgen", { -- test: toggle machine running with clockgens, useful for debugging
-- -- i.e. seeing how machines running affect server performance
-- description = "",
-- privs = {
-- interact = true
-- },
-- func = function(name, param)
-- local privs = minetest.get_player_privs(name);
-- if not privs.privs then return end
-- local player = minetest.get_player_by_name(name);
-- if basic_machines.clockgen == 0 then basic_machines.clockgen = 1 else basic_machines.clockgen = 0 end
-- minetest.chat_send_player(name, "#clockgen set to " .. basic_machines.clockgen);
-- end
-- })
-- CLOCK GENERATOR : periodically activates machine on top of it
2018-11-13 19:09:03 -08:00
minetest.register_abm({
nodenames = {"basic_machines:clockgen"},
neighbors = {""},
interval = machines_timer,
chance = 1,
2018-11-13 19:09:03 -08:00
action = function(pos, node, active_object_count, active_object_count_wider)
if basic_machines.clockgen == 0 then return end
2018-11-13 19:09:03 -08:00
local meta = minetest.get_meta(pos);
local machines = meta:get_int("machines");
if machines~=1 then -- no machines privilege
if not minetest.get_player_by_name(meta:get_string("owner")) then -- owner not online
2018-11-13 19:09:03 -08:00
return
end
end
2018-11-13 19:09:03 -08:00
pos.y=pos.y+1;
2018-11-13 19:09:03 -08:00
node = minetest.get_node(pos);if not node.name or node.name == "air" then return end
local table = minetest.registered_nodes[node.name];
if table and table.mesecons and table.mesecons.effector then -- check if all elements exist, safe cause it checks from left to right
2018-11-13 19:09:03 -08:00
else return
end
local effector=table.mesecons.effector;
if effector.action_on then
2018-11-13 19:09:03 -08:00
effector.action_on(pos,node,machines_TTL);
end
end
});
minetest.register_node("basic_machines:clockgen", {
2016-04-04 14:55:10 -07:00
description = "Clock generator - use sparingly, continually activates top block",
tiles = {"basic_machine_clock_generator.png"},
2017-01-03 07:51:50 -08:00
groups = {cracky=3, mesecon_effector_on = 1},
sounds = default.node_sound_metal_defaults(),
after_place_node = function(pos, placer)
local meta = minetest.get_meta(pos);
local owner = placer:get_player_name() or "";
2016-12-24 03:34:02 -08:00
local privs = minetest.get_player_privs(owner);
if privs.machines then meta:set_int("machines",1) end
2018-11-13 19:09:03 -08:00
meta:set_string("owner",owner);
meta:set_string("infotext","clock generator (owned by " .. owner .. "): place machine to be activated on top of generator");
end
2018-11-13 19:09:03 -08:00
})
2015-05-05 14:34:03 -07:00
-- DISTRIBUTOR --
2017-12-21 09:06:15 -08:00
local get_distributor_form = function(pos,player)
if not player then return end
local meta = minetest.get_meta(pos);
local privs = minetest.get_player_privs(player:get_player_name());
local cant_build = minetest.is_protected(pos,player:get_player_name());
2018-11-13 19:09:03 -08:00
--meta:get_string("owner")~=player:get_player_name() and
if not privs.privs and cant_build then
return
end
2017-12-21 09:06:15 -08:00
local p = {}; local active = {};
local n = meta:get_int("n");
local delay = meta:get_float("delay");
for i =1,n do
p[i]={x=meta:get_int("x"..i),y=meta:get_int("y"..i),z=meta:get_int("z"..i)};
active[i]=meta:get_int("active"..i);
end
2018-11-13 19:09:03 -08:00
2017-12-21 09:06:15 -08:00
local list_name = "nodemeta:"..pos.x..','..pos.y..','..pos.z
2018-11-13 19:09:03 -08:00
local form =
2017-12-21 09:06:15 -08:00
"size[7,"..(0.75+(n)*0.75).."]" .. -- width, height
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
2017-12-25 13:06:43 -08:00
"label[0,-0.25;" .. minetest.colorize("lawngreen","target: x y z, MODE -2=only OFF, -1=NOT input/0/1=input, 2 = only ON") .. "]";
2017-12-21 09:06:15 -08:00
for i =1,n do
form = form.."field[0.25,"..(0.5+(i-1)*0.75)..";1,1;x"..i..";;"..p[i].x.."] field[1.25,"..(0.5+(i-1)*0.75)..";1,1;y"..i..";;"..p[i].y.."] field[2.25,"..(0.5+(i-1)*0.75)..";1,1;z"..i..";;"..p[i].z.."] field [ 3.25,"..(0.5+(i-1)*0.75)..";1,1;active"..i..";;" .. active[i] .. "]"
form = form .. "button[4.,"..(0.25+(i-1)*0.75)..";1.5,1;SHOW"..i..";SHOW "..i.."]".."button_exit[5.25,"..(0.25+(i-1)*0.75)..";1,1;SET"..i..";SET]".."button[6.25,"..(0.25+(i-1)*0.75)..";1,1;X"..i..";X]"
end
2018-11-13 19:09:03 -08:00
2017-12-21 09:06:15 -08:00
form=form.."button_exit[4.25,"..(0.25+(n)*0.75)..";1,1;ADD;ADD]".."button_exit[3.,"..(0.25+(n)*0.75)..";1,1;OK;OK]".."field[0.25,"..(0.5+(n)*0.75)..";1,1;delay;delay;"..delay .. "]";
form = form.."button[6.25,"..(0.25+(n)*0.75)..";1,1;help;help]";
return form
end
minetest.register_node("basic_machines:distributor", {
description = "Distributor - can forward signal up to 16 different targets",
tiles = {"distributor.png"},
2017-12-21 09:06:15 -08:00
groups = {cracky=3, 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", "Distributor. Right click/punch to set it up.")
meta:set_string("owner", placer:get_player_name()); meta:set_int("public",0);
for i=1,10 do
meta:set_int("x"..i,0);meta:set_int("y"..i,1);meta:set_int("z"..i,0);meta:set_int("active"..i,1) -- target i
end
meta:set_int("n",2); -- how many targets initially
meta:set_float("delay",0); -- delay when transmitting signal
2018-11-13 19:09:03 -08:00
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,
2018-11-13 19:09:03 -08:00
mesecons = {effector = {
2018-11-13 19:09:03 -08:00
action_on = function (pos, node,ttl)
2015-05-13 04:22:32 -07:00
if type(ttl)~="number" then ttl = 1 end
2015-05-11 03:22:07 -07:00
if not(ttl>0) then return end
local meta = minetest.get_meta(pos);
local t0 = meta:get_int("t");
2018-11-13 19:09:03 -08:00
local t1 = minetest.get_gametime();
local T = meta:get_int("T"); -- temperature
2018-11-13 19:09:03 -08:00
if t0>t1-machines_minstep then -- activated before natural time
T=T+1;
else
2018-11-13 19:09:03 -08:00
if T>0 then
T=T-1
if t1-t0>5 then T = 0 end -- reset temperature if more than 5s elapsed since last punch
end
2018-11-13 19:09:03 -08:00
end
meta:set_int("T",T);
meta:set_int("t",t1); -- update last activation time
2018-11-13 19:09:03 -08:00
if T > 2 then -- overheat
minetest.sound_play("default_cool_lava",{pos = pos, max_hear_distance = 16, gain = 0.25})
meta:set_string("infotext","overheat: temperature ".. T)
return
end
2018-11-13 19:09:03 -08:00
2017-12-19 02:59:05 -08:00
local delay = minetest.get_meta(pos):get_float("delay");
2018-11-13 19:09:03 -08:00
2017-12-21 09:06:15 -08:00
local activate = function()
local posf = {}; local active = {};
local n = meta:get_int("n");local delay = meta:get_float("delay");
for i =1,n do
posf[i]={x=meta:get_int("x"..i)+pos.x,y=meta:get_int("y"..i)+pos.y,z=meta:get_int("z"..i)+pos.z};
active[i]=meta:get_int("active"..i);
end
2018-11-13 19:09:03 -08:00
2017-12-21 09:06:15 -08:00
local table,node;
2018-11-13 19:09:03 -08:00
2017-12-21 09:06:15 -08:00
for i=1,n do
2018-11-13 19:09:03 -08:00
if active[i]~=0 then
2017-12-21 09:06:15 -08:00
node = minetest.get_node(posf[i]);if not node.name then return end -- error
table = minetest.registered_nodes[node.name];
2018-11-13 19:09:03 -08:00
2017-12-21 09:06:15 -08:00
if table and table.mesecons and table.mesecons.effector then -- check if all elements exist, safe cause it checks from left to right
-- alternative way: overkill
--ret = pcall(function() if not table.mesecons.effector then end end); -- exception handling to determine if structure exists
2018-11-13 19:09:03 -08:00
2017-12-21 09:06:15 -08:00
local effector=table.mesecons.effector;
local active_i = active[i];
2018-11-13 19:09:03 -08:00
if (active_i == 1 or active_i == 2) and effector.action_on then -- normal OR only forward input ON
2018-11-13 19:09:03 -08:00
effector.action_on(posf[i],node,ttl-1);
elseif active_i == -1 and effector.action_off then
effector.action_off(posf[i],node,ttl-1)
2016-03-18 01:32:25 -07:00
end
end
2018-11-13 19:09:03 -08:00
end
end
end
2018-11-13 19:09:03 -08:00
if delay>0 then
minetest.after(delay, activate)
elseif delay == 0 then
activate()
else -- delay <0 - do random activation: delay = -500 means 500/1000 chance to activate
if math.random(1000)<=-delay then
activate()
end
end
2018-11-13 19:09:03 -08:00
end,
2018-11-13 19:09:03 -08:00
action_off = function (pos, node,ttl)
2015-05-13 04:58:45 -07:00
if type(ttl)~="number" then ttl = 1 end
if not(ttl>0) then return end
local meta = minetest.get_meta(pos);
2018-11-13 19:09:03 -08:00
local t0 = meta:get_int("t");
2018-11-13 19:09:03 -08:00
local t1 = minetest.get_gametime();
local T = meta:get_int("T"); -- temperature
2018-11-13 19:09:03 -08:00
if t0>t1-machines_minstep then -- activated before natural time
T=T+1;
else
if T>0 then T=T-1 end
end
meta:set_int("T",T);
meta:set_int("t",t1); -- update last activation time
2018-11-13 19:09:03 -08:00
if T > 2 then -- overheat
minetest.sound_play("default_cool_lava",{pos = pos, max_hear_distance = 16, gain = 0.25})
meta:set_string("infotext","overheat: temperature ".. T)
return
end
local delay = minetest.get_meta(pos):get_float("delay");
2018-11-13 19:09:03 -08:00
2017-12-21 09:06:15 -08:00
local activate = function()
local posf = {}; local active = {};
local n = meta:get_int("n");
for i =1,n do
posf[i]={x=meta:get_int("x"..i)+pos.x,y=meta:get_int("y"..i)+pos.y,z=meta:get_int("z"..i)+pos.z};
active[i]=meta:get_int("active"..i);
end
2018-11-13 19:09:03 -08:00
2017-12-21 09:06:15 -08:00
local node, table
2018-11-13 19:09:03 -08:00
2017-12-21 09:06:15 -08:00
for i=1,n do
if active[i]~=0 then
node = minetest.get_node(posf[i]);if not node.name then return end -- error
table = minetest.registered_nodes[node.name];
2018-11-13 19:09:03 -08:00
if table and table.mesecons and table.mesecons.effector then
2017-12-21 09:06:15 -08:00
local effector=table.mesecons.effector;
if (active[i] == 1 or active[i]==-2) and effector.action_off then -- normal OR only forward input OFF
2018-11-13 19:09:03 -08:00
effector.action_off(posf[i],node,ttl-1);
elseif (active[i] == -1) and effector.action_on then
effector.action_on(posf[i],node,ttl-1);
end
end
end
end
end
2018-11-13 19:09:03 -08:00
2017-12-21 09:06:15 -08:00
if delay>0 then minetest.after(delay, activate) else activate() end
2018-11-13 19:09:03 -08:00
end
}
},
on_rightclick = function(pos, node, player, itemstack, pointed_thing)
2017-12-21 09:06:15 -08:00
local form = get_distributor_form(pos,player)
if form then minetest.show_formspec(player:get_player_name(), "basic_machines:distributor_"..minetest.pos_to_string(pos), form) end
end,
}
)
-- LIGHT --
2015-05-05 14:34:03 -07:00
minetest.register_node("basic_machines:light_off", {
description = "Light off",
tiles = {"light_off.png"},
2017-01-03 07:51:50 -08:00
groups = {cracky=3, mesecon_effector_on = 1},
sounds = default.node_sound_glass_defaults(),
mesecons = {effector = {
2018-11-13 19:09:03 -08:00
action_on = function (pos, node,ttl)
minetest.swap_node(pos,{name = "basic_machines:light_on"});
local meta = minetest.get_meta(pos);
local deactivate = meta:get_int("deactivate");
2018-11-13 19:09:03 -08:00
if deactivate > 0 then
--meta:set_int("active",0);
2018-11-13 19:09:03 -08:00
minetest.after(deactivate,
function()
--if meta:get_int("active") ~= 1 then -- was not activated again, so turn it off
minetest.swap_node(pos,{name = "basic_machines:light_off"}); -- turn off again
--meta:set_int("active",0);
--end
end
)
end
end
}
},
})
minetest.register_node("basic_machines:light_on", {
description = "Light on",
tiles = {"light.png"},
2017-01-03 07:51:50 -08:00
groups = {cracky=3, mesecon_effector_on = 1},
sounds = default.node_sound_glass_defaults(),
paramtype = "light",
light_source = LIGHT_MAX,
after_place_node = function(pos, placer)
local meta = minetest.get_meta(pos);
2018-11-13 19:09:03 -08:00
local list_name = "nodemeta:"..pos.x..','..pos.y..','..pos.z
local deactivate = meta:get_int("deactivate");
local form = "size[2,2]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
"field[0.25,0.5;2,1;deactivate;deactivate after ;"..deactivate.."]".."button_exit[0.,1;1,1;OK;OK]";
meta:set_string("formspec", form);
2018-11-13 19:09:03 -08:00
end,
on_receive_fields = function(pos, formname, fields, player)
2018-11-13 19:09:03 -08:00
if minetest.is_protected(pos, player:get_player_name()) then
minetest.record_protection_violation(pos, player:get_player_name())
return
end
2017-07-30 15:09:40 -07:00
2016-04-02 00:38:14 -07:00
if fields.deactivate then
local meta = minetest.get_meta(pos);
2018-11-13 19:09:03 -08:00
local deactivate = basic_machines.tonumber(fields.deactivate) or 0;
if deactivate <0 or deactivate > 600 then deactivate = 0 end
meta:set_int("deactivate",deactivate);
local form = "size[2,2]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
"field[0.25,0.5;2,1;deactivate;deactivate after ;"..deactivate.."]".."button_exit[0.,1;1,1;OK;OK]";
meta:set_string("formspec", form);
end
2018-11-13 19:09:03 -08:00
end,
mesecons = {effector = {
2018-11-13 19:09:03 -08:00
action_off = function (pos, node,ttl)
minetest.swap_node(pos,{name = "basic_machines:light_off"});
end,
2018-11-13 19:09:03 -08:00
action_on = function (pos, node,ttl)
local meta = minetest.get_meta(pos);
2018-11-13 19:09:03 -08:00
local count = basic_machines.tonumber(meta:get_string("infotext")) or 0;
2016-05-05 13:59:59 -07:00
meta:set_string("infotext",count+1); -- increase activate count
end
}
},
2018-11-13 19:09:03 -08:00
})
2015-05-05 14:34:03 -07:00
2015-05-06 12:10:17 -07:00
punchset.known_nodes = {["basic_machines:mover"]=true,["basic_machines:keypad"]=true,["basic_machines:detector"]=true};
2015-05-01 09:40:54 -07:00
-- SETUP BY PUNCHING
2015-05-01 09:40:54 -07:00
minetest.register_on_punchnode(function(pos, node, puncher, pointed_thing)
2018-11-13 19:09:03 -08:00
2017-12-21 09:06:15 -08:00
-- STRANGE PROBLEM: if player doesnt move it takes another punch at same block for this function to run again, and it works normally if player moved at least one block from his previous position
-- it only happens with keypad - maybe caused by formspec displayed..
2018-11-13 19:09:03 -08:00
2015-05-01 09:40:54 -07:00
local name = puncher:get_player_name(); if name==nil then return end
if punchset[name]== nil then -- set up punchstate
2018-11-13 19:09:03 -08:00
punchset[name] = {}
2015-05-01 09:40:54 -07:00
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
2018-11-13 19:09:03 -08:00
2015-05-01 09:40:54 -07:00
-- 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
2018-11-13 19:09:03 -08:00
if punchset.known_nodes[node.name] then -- check if player is suppose to be able to punch interact
if node.name~="basic_machines:keypad" then -- keypad is supposed to be punch interactive!
if minetest.is_protected(pos, name) then return end
end
2015-05-01 09:40:54 -07:00
end
2018-11-13 19:09:03 -08:00
2015-05-01 09:40:54 -07:00
if node.name == "basic_machines:mover" then -- mover init code
2018-11-13 19:09:03 -08:00
if punchset[name].state == 0 then
2015-05-05 14:34:03 -07:00
-- if not puncher:get_player_control().sneak then
-- return
-- end
minetest.chat_send_player(name, "MOVER: Now punch source1, source2, end position to set up mover.")
2015-05-01 09:40:54 -07:00
punchset[name].node = node.name;punchset[name].pos = {x=pos.x,y=pos.y,z=pos.z};
2018-11-13 19:09:03 -08:00
punchset[name].state = 1
2015-05-01 09:40:54 -07:00
return
end
end
2018-11-13 19:09:03 -08:00
2018-12-08 21:34:43 -08:00
-- mover code, not first punch
if punchset[name].node == "basic_machines:mover" then
2018-11-13 19:09:03 -08:00
if minetest.is_protected(pos,name) then
minetest.chat_send_player(name, "MOVER: Punched position is protected. aborting.")
punchset[name].node = "";
punchset[name].state = 0; return
end
2018-12-08 21:34:43 -08:00
local meta = minetest.get_meta(punchset[name].pos)
if not meta then
return
end
local range = meta:get_float("upgrade") or 1
range = range * max_range
2018-11-13 19:09:03 -08:00
if punchset[name].state == 1 then
2015-05-18 09:16:40 -07:00
local privs = minetest.get_player_privs(puncher:get_player_name());
if not privs.privs and (math.abs(punchset[name].pos.x - pos.x)>range or math.abs(punchset[name].pos.y - pos.y)>range or math.abs(punchset[name].pos.z - pos.z)>range) then
2015-05-05 14:34:03 -07:00
minetest.chat_send_player(name, "MOVER: Punch closer to mover. reseting.")
2015-05-01 09:40:54 -07:00
punchset[name].state = 0; return
end
2018-11-13 19:09:03 -08:00
if punchset[name].pos.x==pos.x and punchset[name].pos.y==pos.y and punchset[name].pos.z==pos.z then
2015-05-05 14:34:03 -07:00
minetest.chat_send_player(name, "MOVER: Punch something else. aborting.")
punchset[name].state = 0;
2018-11-13 19:09:03 -08:00
return
2015-05-05 14:34:03 -07:00
end
2018-11-13 19:09:03 -08:00
2015-05-01 09:40:54 -07:00
punchset[name].pos1 = {x=pos.x,y=pos.y,z=pos.z};punchset[name].state = 2;
2015-05-06 05:56:42 -07:00
machines.pos1[name] = punchset[name].pos1;machines.mark_pos1(name) -- mark position
minetest.chat_send_player(name, "MOVER: Source1 position for mover set. Punch again to set source2 position.")
2015-05-01 09:40:54 -07:00
return
end
2018-11-13 19:09:03 -08:00
if punchset[name].state == 2 then
local privs = minetest.get_player_privs(puncher:get_player_name());
if not privs.privs and (math.abs(punchset[name].pos.x - pos.x)>range or math.abs(punchset[name].pos.y - pos.y)>range or math.abs(punchset[name].pos.z - pos.z)>range) then
minetest.chat_send_player(name, "MOVER: Punch closer to mover. reseting.")
punchset[name].state = 0; return
end
2018-11-13 19:09:03 -08:00
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;
2018-11-13 19:09:03 -08:00
return
end
2018-11-13 19:09:03 -08:00
punchset[name].pos11 = {x=pos.x,y=pos.y,z=pos.z};punchset[name].state = 3;
machines.pos11[name] = {x=pos.x,y=pos.y,z=pos.z};
2018-12-08 21:34:43 -08:00
-- mark pos11
machines.mark_pos11(name)
minetest.chat_send_player(name, "MOVER: Source2 position for mover set. Punch again to set target position.")
return
end
2018-11-13 19:09:03 -08:00
if punchset[name].state == 3 then
2018-12-08 21:34:43 -08:00
if punchset[name].node ~= "basic_machines:mover" then
punchset[name].state = 0
return
end
2015-05-18 09:16:40 -07:00
local privs = minetest.get_player_privs(puncher:get_player_name());
2018-12-08 21:34:43 -08:00
local elevator_mode = false
local meta = minetest.get_meta(punchset[name].pos)
meta:set_int("elevator", 0)
2018-12-08 21:34:43 -08:00
-- check if elevator mode
if punchset[name].pos.x == pos.x and
punchset[name].pos.z == pos.z then
-- trying to make elevator?
if math.abs(punchset[name].pos.y - pos.y) > 3 then
local meta = minetest.get_meta(punchset[name].pos)
2018-11-13 19:09:03 -08:00
2018-12-08 21:34:43 -08:00
-- only if object mode
if meta:get_string("mode") == "object" then
-- count number of diamond blocks to determine if elevator can be set up with this height distance
local inv = meta:get_inventory()
local upgrade = 0
if inv:get_stack("upgrade", 1):get_name() == "default:diamondblock" then
2018-12-08 21:34:43 -08:00
local inv_stack = inv:get_stack("upgrade", 1)
upgrade = inv_stack:get_count()
2018-12-08 21:34:43 -08:00
if upgrade > 10 then
upgrade = 10
2018-12-08 21:34:43 -08:00
end
end
2018-11-13 19:09:03 -08:00
2018-12-08 21:34:43 -08:00
local requirement = math.floor(math.abs(punchset[name].pos.y - pos.y) / 100) + 1
if upgrade < requirement then
minetest.chat_send_player(name, "MOVER: Error while trying to make elevator. Need at least "..requirement .. " diamond block(s) in upgrade (1 for every 100 height). ")
punchset[name].state = 0
return
else
2018-12-08 21:34:43 -08:00
elevator_mode = true
meta:set_int("upgrade", upgrade + 1)
meta:set_int("elevator", 1)
minetest.chat_send_player(name, "MOVER: elevator setup completed, upgrade level " .. upgrade)
meta:set_string("infotext", "ELEVATOR, activate to use.")
end
2018-11-13 19:09:03 -08:00
end
2018-11-13 19:09:03 -08:00
end
2018-11-13 19:09:03 -08:00
end
2018-11-13 19:09:03 -08:00
2018-12-08 21:34:43 -08:00
if not privs.privs and
not elevator_mode and
(math.abs(punchset[name].pos.x - pos.x) > range or math.abs(punchset[name].pos.y - pos.y) > range or math.abs(punchset[name].pos.z - pos.z) > range) then
minetest.chat_send_player(name, "MOVER: Punch closer to mover. aborting.")
2018-12-08 21:34:43 -08:00
punchset[name].state = 0
return
2015-05-01 09:40:54 -07:00
end
2018-11-13 19:09:03 -08:00
2018-12-08 21:34:43 -08:00
punchset[name].pos2 = {x = pos.x, y = pos.y, z = pos.z}
punchset[name].state = 0
-- mark pos2
machines.pos2[name] = punchset[name].pos2
machines.mark_pos2(name)
2018-11-13 19:09:03 -08:00
2015-05-05 14:34:03 -07:00
minetest.chat_send_player(name, "MOVER: End position for mover set.")
2018-11-13 19:09:03 -08:00
2018-12-08 21:34:43 -08:00
local x0 = punchset[name].pos1.x-punchset[name].pos.x
local y0 = punchset[name].pos1.y-punchset[name].pos.y
local z0 = punchset[name].pos1.z-punchset[name].pos.z
local meta = minetest.get_meta(punchset[name].pos)
2018-11-13 19:09:03 -08:00
2018-12-08 21:34:43 -08:00
local x1 = punchset[name].pos11.x-punchset[name].pos.x
local y1 = punchset[name].pos11.y-punchset[name].pos.y
local z1 = punchset[name].pos11.z-punchset[name].pos.z
2018-11-13 19:09:03 -08:00
2018-12-08 21:34:43 -08:00
local x2 = punchset[name].pos2.x-punchset[name].pos.x
local y2 = punchset[name].pos2.y-punchset[name].pos.y
local z2 = punchset[name].pos2.z-punchset[name].pos.z
2018-11-13 19:09:03 -08:00
2018-12-08 21:34:43 -08:00
-- this ensures that x0 <= x1
if x0 > x1 then
x0, x1 = x1, x0
end
if y0 > y1 then
y0, y1 = y1, y0
end
if z0 > z1 then
z0, z1 = z1, z0
end
2018-11-13 19:09:03 -08:00
2018-12-08 21:34:43 -08:00
meta:set_int("x1", x1)
meta:set_int("y1", y1)
meta:set_int("z1", z1)
2018-12-08 21:34:43 -08:00
meta:set_int("x0", x0)
meta:set_int("y0", y0)
meta:set_int("z0", z0)
2018-11-13 19:09:03 -08:00
2018-12-08 21:34:43 -08:00
meta:set_int("x2", x2)
meta:set_int("y2", y2)
meta:set_int("z2", z2)
2018-11-13 19:09:03 -08:00
2018-12-08 21:34:43 -08:00
meta:set_int("pc", 0)
meta:set_int("dim", (x1 - x0 + 1) * (y1 - y0 + 1) * (z1 - z0 + 1))
2015-05-01 09:40:54 -07:00
return
end
end
2018-11-13 19:09:03 -08:00
2015-05-05 14:34:03 -07:00
-- KEYPAD
2015-05-01 09:40:54 -07:00
if node.name == "basic_machines:keypad" then -- keypad init/usage code
2018-11-13 19:09:03 -08:00
2015-05-01 09:40:54 -07:00
local meta = minetest.get_meta(pos);
2015-05-05 14:34:03 -07:00
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
2017-12-21 09:06:15 -08:00
punchset[name].state = 0;
return;
2015-05-05 14:34:03 -07:00
else
if minetest.is_protected(pos, name) then return minetest.chat_send_player(name, "KEYPAD: You must be able to build to set up keypad.") end
--if meta:get_string("owner")~= name then minetest.chat_send_player(name, "KEYPAD: Only owner can set up keypad.") return end
2018-11-13 19:09:03 -08:00
if punchset[name].state == 0 then
2015-05-05 14:34:03 -07:00
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};
2018-11-13 19:09:03 -08:00
punchset[name].state = 1
2015-05-05 14:34:03 -07:00
return
end
2015-05-01 09:40:54 -07:00
end
end
2018-11-13 19:09:03 -08:00
2015-05-01 09:40:54 -07:00
if punchset[name].node=="basic_machines:keypad" then -- keypad setup code
if minetest.is_protected(pos,name) then
minetest.chat_send_player(name, "KEYPAD: Punched position is protected. aborting.")
punchset[name].node = "";
punchset[name].state = 0; return
end
2018-11-13 19:09:03 -08:00
if punchset[name].state == 1 then
2015-05-01 09:40:54 -07:00
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.")
2015-05-01 09:40:54 -07:00
punchset[name].state = 0; return
end
2018-11-13 19:09:03 -08:00
machines.pos1[name] = pos;
machines.mark_pos1(name) -- mark pos1
2018-11-13 19:09:03 -08:00
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.");
2015-05-01 09:40:54 -07:00
return
end
end
2015-05-05 14:34:03 -07:00
-- DETECTOR "basic_machines:detector"
if node.name == "basic_machines:detector" then -- detector init code
local meta = minetest.get_meta(pos);
2018-11-13 19:09:03 -08:00
--meta:get_string("owner")~= name
if minetest.is_protected(pos,name) then minetest.chat_send_player(name, "DETECTOR: You must be able to build to set up detector.") return end
2018-11-13 19:09:03 -08:00
if punchset[name].state == 0 then
2015-05-05 14:34:03 -07:00
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};
2018-11-13 19:09:03 -08:00
punchset[name].state = 1
2015-05-05 14:34:03 -07:00
return
end
end
2018-11-13 19:09:03 -08:00
2015-05-05 14:34:03 -07:00
if punchset[name].node == "basic_machines:detector" then
2018-11-13 19:09:03 -08:00
if minetest.is_protected(pos,name) then
minetest.chat_send_player(name, "DETECTOR: Punched position is protected. aborting.")
punchset[name].node = "";
punchset[name].state = 0; return
end
2018-11-13 19:09:03 -08:00
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
2015-05-05 14:34:03 -07:00
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};
2015-05-06 05:56:42 -07:00
machines.pos1[name] = pos;machines.mark_pos1(name) -- mark pos1
2018-11-13 19:09:03 -08:00
punchset[name].state = 2
2015-05-05 14:34:03 -07:00
return
end
2018-11-13 19:09:03 -08:00
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
2015-05-05 14:34:03 -07:00
minetest.chat_send_player(name, "DETECTOR: Punch closer to detector. aborting.")
punchset[name].state = 0; return
end
2018-11-13 19:09:03 -08:00
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, "DETECTOR: Punch something else. aborting.")
punchset[name].state = 0; return
end
2018-11-13 19:09:03 -08:00
2015-05-05 14:34:03 -07:00
minetest.chat_send_player(name, "DETECTOR: Setup complete.")
2015-05-06 05:56:42 -07:00
machines.pos2[name] = pos;machines.mark_pos2(name) -- mark pos2
2015-05-05 14:34:03 -07:00
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("x2",x);meta:set_int("y2",y);meta:set_int("z2",z);
2018-11-13 19:09:03 -08:00
punchset[name].state = 0
2015-05-05 14:34:03 -07:00
return
end
end
2018-11-13 19:09:03 -08:00
if punchset[name].node == "basic_machines:distributor" then
2018-11-13 19:09:03 -08:00
if minetest.is_protected(pos,name) then
minetest.chat_send_player(name, "DISTRIBUTOR: Punched position is protected. aborting.")
punchset[name].node = "";
punchset[name].state = 0; return
end
2018-11-13 19:09:03 -08:00
if punchset[name].state > 0 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: target set.")
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;
local j = punchset[name].state;
2018-11-13 19:09:03 -08:00
meta:set_int("x"..j,x);meta:set_int("y"..j,y);meta:set_int("z"..j,z);
if x==0 and y==0 and z==0 then meta:set_int("active"..j,0) end
machines.pos1[name] = pos;machines.mark_pos1(name) -- mark pos1
2018-11-13 19:09:03 -08:00
punchset[name].state = 0;
return
end
2018-11-13 19:09:03 -08:00
end
2018-11-13 19:09:03 -08:00
2015-05-01 09:40:54 -07:00
end)
-- FORM PROCESSING for all machines
2015-05-01 09:40:54 -07:00
minetest.register_on_player_receive_fields(function(player,formname,fields)
2018-11-13 19:09:03 -08:00
-- MOVER
2015-05-01 09:40:54 -07:00
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 (minetest.is_protected(pos,name) and not privs.privs) or not fields then return end -- only builder can interact
2018-11-13 19:09:03 -08:00
if fields.help == "help" then
2016-04-09 09:44:56 -07:00
local text = "version " .. basic_machines.version .. "\nSETUP: For interactive setup "..
"punch the mover and then punch source1, source2, target node (follow instructions). Put charged battery within distance 1 from mover. For advanced setup right click mover. Positions are defined by x y z coordinates (see top of mover for orientation). Mover itself is at coordinates 0 0 0. "..
"\n\nMODES of operation: normal (just teleport block), dig (digs and gives you resulted node - good for harvesting farms), drop "..
"(drops node on ground), object (teleportation of player and objects. distance between source1/2 defines teleport radius). by setting filter you can specify move time for objects or names for players. "..
"By setting 'filter' only selected nodes are moved.\nInventory mode can exchange items between node inventories. You need to select inventory name for source/target from the dropdown list on the right and enter node to be moved into filter."..
"\n*advanced* You can reverse start/end position by setting reverse nonzero. This is useful for placing stuff at many locations-planting. If you put reverse=2/3 in transport mode it will disable parallel transport but will still do reverse effect with 3. If you activate mover with OFF signal it will toggle reverse." ..
"\n\n FUEL CONSUMPTION depends on blocks to be moved and distance. For example, stone or tree is harder to move than dirt, harvesting wheat is very cheap and and moving lava is very hard."..
2016-04-01 15:04:58 -07:00
"\n\n UPGRADE mover by moving mese blocks in upgrade inventory. Each mese block increases mover range by 10, fuel consumption is divided by (number of mese blocks)+1 in upgrade. Max 10 blocks are used for upgrade. Dont forget to click OK to refresh after upgrade. "..
"\n\n Activate mover by keypad/detector signal or mese signal (if mesecons mod) .";
local form = "size [6,7]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
"textarea[0,0;6.5,8.5;help;MOVER HELP;".. text.."]"
minetest.show_formspec(name, "basic_machines:help_mover", form)
return
end
2018-11-13 19:09:03 -08:00
2017-12-20 14:05:15 -08:00
if fields.tabs then
2018-11-13 19:09:03 -08:00
meta:set_int("seltab", basic_machines.tonumber(fields.tabs) or 1)
2017-12-20 14:05:15 -08:00
local form = get_mover_form(pos,player)
minetest.show_formspec(player:get_player_name(), "basic_machines:mover_"..minetest.pos_to_string(pos), form)
return
end
2018-11-13 19:09:03 -08:00
2017-12-20 14:05:15 -08:00
if fields.OK == "OK" then --yyy
2018-11-13 19:09:03 -08:00
2017-12-20 14:05:15 -08:00
local seltab = meta:get_int("seltab");
2018-11-13 19:09:03 -08:00
2017-12-20 14:05:15 -08:00
if seltab == 2 then -- POSITIONS
-- positions
2018-11-13 19:09:03 -08:00
local x0, y0, z0, x1, y1, z1, x2, y2, z2
x0 = basic_machines.tonumber(fields.x0) or 0
y0 = basic_machines.tonumber(fields.y0) or -1
z0 = basic_machines.tonumber(fields.z0) or 0
x1 = basic_machines.tonumber(fields.x1) or 0
y1 = basic_machines.tonumber(fields.y1) or -1
z1 = basic_machines.tonumber(fields.z1) or 0
x2 = basic_machines.tonumber(fields.x2) or 0
y2 = basic_machines.tonumber(fields.y2) or 1
z2 = basic_machines.tonumber(fields.z2) or 0
2017-12-20 14:05:15 -08:00
-- did the numbers change from last time?
2018-11-13 19:09:03 -08:00
if meta:get_int("x0") ~= x0 or meta:get_int("y0") ~= y0 or
meta:get_int("z0") ~= z0 or
meta:get_int("x1") ~= x1 or
meta:get_int("y1") ~= y1 or
meta:get_int("z1") ~= z1 or
meta:get_int("x2") ~= x2 or
meta:get_int("y2") ~= y2 or
meta:get_int("z2") ~= z2 then
2017-12-20 14:05:15 -08:00
-- are new numbers inside bounds?
2018-11-13 19:09:03 -08:00
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
2017-12-20 14:05:15 -08:00
minetest.chat_send_player(name,"#mover: all coordinates must be between ".. -max_range .. " and " .. max_range .. ". For increased range set up positions by punching"); return
end
2016-04-01 15:04:58 -07:00
end
2018-11-13 19:09:03 -08:00
2017-12-20 14:05:15 -08:00
--local range = meta:get_float("upgrade") or 1; range = range * max_range;
2018-11-13 19:09:03 -08:00
2017-12-20 14:05:15 -08:00
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);
2018-11-13 19:09:03 -08:00
2017-12-20 14:05:15 -08:00
if minetest.is_protected({x=pos.x+x0,y=pos.y+y0,z=pos.z+z0},name) then
minetest.chat_send_player(name, "MOVER: position is protected. aborting.")
return
end
if minetest.is_protected({x=pos.x+x1,y=pos.y+y1,z=pos.z+z1},name) then
minetest.chat_send_player(name, "MOVER: position is protected. aborting.")
return
end
2018-11-13 19:09:03 -08:00
2017-12-20 14:05:15 -08:00
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("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);
2018-11-13 19:09:03 -08:00
2017-12-20 14:05:15 -08:00
if fields.reverse then
meta:set_string("reverse",fields.reverse);
end
2018-11-13 19:09:03 -08:00
2017-12-20 14:05:15 -08:00
if fields.inv1 then
meta:set_string("inv1",fields.inv1);
2017-12-20 14:05:15 -08:00
end
2018-11-13 19:09:03 -08:00
2017-12-20 14:05:15 -08:00
if fields.inv2 then
meta:set_string("inv2",fields.inv2);
end
2018-10-31 09:13:05 -07:00
--notification
2017-12-20 14:05:15 -08:00
meta:set_string("infotext", "Mover block. Set up with source coordinates ".. x0 ..","..y0..","..z0.. " -> ".. x1 ..","..y1..","..z1.. " and target coord ".. x2 ..","..y2..",".. z2 .. ". Put charged battery next to it and start it with keypad/mese signal.");
2018-11-13 19:09:03 -08:00
2018-10-31 09:13:05 -07:00
else -- MODE 1
2018-11-13 19:09:03 -08:00
2017-12-20 14:05:15 -08:00
if fields.mode then
meta:set_string("mode",fields.mode);
end
2018-11-13 19:09:03 -08:00
2017-12-20 14:05:15 -08:00
--filter
local prefer = fields.prefer or ""
local meta_prefer = meta:get_string("prefer")
if meta_prefer ~= prefer then
meta_prefer = prefer
end
-- prevent item stacks with more than 'stack_max' items
local preferstack = ItemStack(meta_prefer)
if preferstack:get_count() > preferstack:get_stack_max() then
preferstack:set_count(preferstack:get_stack_max())
2018-11-10 17:34:36 -08:00
else
preferstack:set_count(preferstack:get_count())
2017-12-20 14:05:15 -08:00
end
meta:set_string("prefer", preferstack:to_string());
2018-10-31 09:13:05 -07:00
--notification
meta:set_string("infotext", "Mover block. Mode or filter changed.");
end
2018-11-13 19:09:03 -08:00
2015-05-01 09:40:54 -07:00
if meta:get_float("fuel")<0 then meta:set_float("fuel",0) end -- reset block
2017-12-20 14:05:15 -08:00
-- display battery
local fpos = find_and_connect_battery(pos);
2018-11-13 19:09:03 -08:00
if not fpos then
minetest.chat_send_player(name,"MOVER: please put battery nearby")
else
2018-11-13 19:09:03 -08:00
minetest.chat_send_player(name,"MOVER: battery found - displaying mark 1")
machines.pos1[name] = fpos; machines.mark_pos1(name)
end
2018-11-13 19:09:03 -08:00
2017-12-20 14:05:15 -08:00
elseif fields.mode then
meta:set_string("mode",fields.mode);
local form = get_mover_form(pos,player)
minetest.show_formspec(player:get_player_name(), "basic_machines:mover_"..minetest.pos_to_string(pos), form)
return
2015-05-01 09:40:54 -07:00
end
2018-11-13 19:09:03 -08:00
return
2015-05-01 09:40:54 -07:00
end
2018-11-13 19:09:03 -08:00
-- KEYPAD
2015-05-01 09:40:54 -07:00
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 (minetest.is_protected(pos,name) and not privs.privs) or not fields then return end -- only builder can interact
2018-11-13 19:09:03 -08:00
if fields.help then
local text = "target : represents coordinates ( x, y, z ) relative to keypad. (0,0,0) is keypad itself, (0,1,0) is one node above, (0,-1,0) one node below. X coordinate axes goes from east to west, Y from down to up, Z from south to north."..
"\n\nPassword: enter password and press OK. Password will be encrypted. Next time you use keypad you will need to enter correct password to gain access."..
"\n\nrepeat: number to control how many times activation is repeated after initial punch"..
"\n\ntext: if set then text on target node will be changed. In case target is detector/mover, filter settings will be changed. Can be used for special operations."..
"\n\n1=OFF/2=ON/3=TOGGLE control the way how target node is activated"..
"\n**************************************************\nusage\n"..
"\nJust punch ( left click ) keypad, then the target block will be activated."..
2017-12-21 09:06:15 -08:00
"\nTo set text on other nodes ( text shows when you look at node ) just target the node and set nonempty text. Upon activation text will be set. When target node is another keypad, its \"text\" field will be set. When targets is mover/detector, its \"filter\" field will be set. To clear \"filter\" set text to \"@\". When target is distributor, you can change i-th target of distributor to mode mode with \"i mode\""..
"\n\nkeyboard : to use keypad as keyboard for text input write \"@\" in \"text\" field and set any password. Next time keypad is used it will work as text input device."..
"\n\ndisplaying messages to nearby players ( up to 5 blocks around keypad's target ): set text to \"!text\". Upon activation player will see \"text\" in their chat."..
"\n\nplaying sound to nearby players : set text to \"$sound_name\""..
"\n\nadvanced: "..
"\ntext replacement : Suppose keypad A is set with text \"@some @. text @!\" and there are blocks on top of keypad A with infotext '1' and '2'. Suppose we target B with A and activate A. Then text of keypad B will be set to \"some 1. text 2!\""..
"\nword extraction: Suppose similiar setup but now keypad A is set with text \"%1\". Then upon activation text of keypad B will be set to 1.st word of infotext";
2018-11-13 19:09:03 -08:00
local form = "size[6,7]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
"textarea[0,0;6.5,8.5;help;KEYPAD HELP;".. text.."]"
minetest.show_formspec(name, "basic_machines:help_keypad", form)
return
end
2018-11-13 19:09:03 -08:00
2015-05-01 09:40:54 -07:00
if fields.OK == "OK" then
local x0,y0,z0,pass,mode;
2018-11-13 19:09:03 -08:00
x0=basic_machines.tonumber(fields.x0) or 0;y0=basic_machines.tonumber(fields.y0) or 1;z0=basic_machines.tonumber(fields.z0) or 0
pass = fields.pass or ""; mode = fields.mode or 1;
2018-11-13 19:09:03 -08:00
if minetest.is_protected({x=pos.x+x0,y=pos.y+y0,z=pos.z+z0},name) then
minetest.chat_send_player(name, "KEYPAD: position is protected. aborting.")
return
end
2018-11-13 19:09:03 -08:00
2015-05-18 08:46:26 -07:00
if not privs.privs and (math.abs(x0)>max_range or math.abs(y0)>max_range or math.abs(z0)>max_range) then
2016-04-01 15:04:58 -07:00
minetest.chat_send_player(name,"#keypad: all coordinates must be between ".. -max_range .. " and " .. max_range); return
2015-05-01 09:40:54 -07:00
end
meta:set_int("x0",x0);meta:set_int("y0",y0);meta:set_int("z0",z0);
2018-11-13 19:09:03 -08:00
if fields.pass then
2016-03-06 13:40:24 -08:00
if fields.pass~="" and string.len(fields.pass)<=16 then -- dont replace password with hash which is longer - 27 chars
pass=minetest.get_password_hash(pos.x, pass..pos.y);pass=minetest.get_password_hash(pos.y, pass..pos.z);
2018-11-13 19:09:03 -08:00
meta:set_string("pass",pass);
end
end
2018-11-13 19:09:03 -08:00
if fields.text then
meta:set_string("text", fields.text);
2018-05-11 03:29:30 -07:00
if string.find(fields.text, "!") then minetest.log("action", string.format("%s set up keypad for message display at %s", name, minetest.pos_to_string(pos))) end
end
2018-11-13 19:09:03 -08:00
meta:set_int("iter",math.min(basic_machines.tonumber(fields.iter) or 1,500));meta:set_int("mode",basic_machines.tonumber(mode) or 2);
2015-05-01 09:40:54 -07:00
meta:set_string("infotext", "Punch keypad to use it.");
2018-11-13 19:09:03 -08:00
if pass~="" then
2016-05-04 06:11:48 -07:00
if fields.text~="@" then
2018-11-13 19:09:03 -08:00
meta:set_string("infotext",meta:get_string("infotext").. ". Password protected.");
2016-05-04 06:11:48 -07:00
else
2018-11-13 19:09:03 -08:00
meta:set_string("infotext","punch keyboard to use it.");
2016-05-04 06:11:48 -07:00
end
end
2018-11-13 19:09:03 -08:00
2015-05-01 09:40:54 -07:00
end
return
end
2018-11-13 19:09:03 -08:00
2015-05-01 09:40:54 -07:00
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)
2018-11-13 19:09:03 -08:00
2015-05-01 09:40:54 -07:00
if fields.OK == "OK" then
2018-11-13 19:09:03 -08:00
2015-05-01 09:40:54 -07:00
local pass;
pass = fields.pass or "";
2018-11-13 19:09:03 -08:00
if meta:get_string("text")=="@" then -- keyboard mode
meta:set_string("input", pass);
2017-12-21 09:06:15 -08:00
meta:set_int("count",1);
use_keypad(pos,machines_TTL,0);
return
end
2018-11-13 19:09:03 -08:00
pass=minetest.get_password_hash(pos.x, pass..pos.y);pass=minetest.get_password_hash(pos.y, pass..pos.z);
2018-11-13 19:09:03 -08:00
2015-05-01 09:40:54 -07:00
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.")
2018-11-13 19:09:03 -08:00
if meta:get_int("count")<=0 then -- only accept new operation requests if idle
2018-11-13 19:09:03 -08:00
meta:set_int("count",meta:get_int("iter"));
meta:set_int("active_repeats",0);
2017-12-21 09:06:15 -08:00
use_keypad(pos,machines_TTL,0)
2018-11-13 19:09:03 -08:00
else
meta:set_int("count",0);
2017-12-21 09:06:15 -08:00
meta:set_string("infotext","operation aborted by user. punch to activate.") -- reset
end
2018-11-13 19:09:03 -08:00
2015-05-01 09:40:54 -07:00
return
end
end
2018-11-13 19:09:03 -08:00
-- DETECTOR
2015-05-05 14:34:03 -07:00
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 (minetest.is_protected(pos,name) and not privs.privs) or not fields then return end -- only builder
2018-11-13 19:09:03 -08:00
2015-05-05 14:34:03 -07:00
--minetest.chat_send_all("formname " .. formname .. " fields " .. dump(fields))
2018-11-13 19:09:03 -08:00
if fields.help == "help" then
local text = "SETUP: right click or punch and follow chat instructions. With detector you can detect nodes, objects, players, or items inside inventories."..
"If detector activates it will trigger machine at target position.\n\nThere are 4 modes of operation - node/player/object/inventory detection. Inside node/player/object "..
"write node/player/object name. If you detect players/objects you can specify range of detection. If you want detector to activate target precisely when its not triggered set NOT to 1\n\n"..
2018-11-13 19:09:03 -08:00
"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. If mode is inventory it will check for items in specified inventory of source node."..
"\n\nADVANCED: you can select second source and then select AND/OR from the right top dropdown list to do logical operations. You can also filter output signal:\n -2=only OFF,-1=NOT/0/1=normal,2=only ON, 3 only if changed"..
" 4 = if target keypad set its text to detected object name" ;
local form = "size[5.5,5.5]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
"textarea[0,0;6,7;help;DETECTOR HELP;".. text.."]"
2015-05-06 04:35:43 -07:00
minetest.show_formspec(name, "basic_machines:help_detector", form)
end
2018-11-13 19:09:03 -08:00
2015-05-05 14:34:03 -07:00
if fields.OK == "OK" then
2018-11-13 19:09:03 -08:00
2016-04-02 00:38:14 -07:00
local x0,y0,z0,x1,y1,z1,x2,y2,z2,r,node,NOT;
2018-11-13 19:09:03 -08:00
x0=basic_machines.tonumber(fields.x0) or 0;y0=basic_machines.tonumber(fields.y0) or 0;z0=basic_machines.tonumber(fields.z0) or 0
x1=basic_machines.tonumber(fields.x1) or 0;y1=basic_machines.tonumber(fields.y1) or 0;z1=basic_machines.tonumber(fields.z1) or 0
x2=basic_machines.tonumber(fields.x2) or 0;y2=basic_machines.tonumber(fields.y2) or 0;z2=basic_machines.tonumber(fields.z2) or 0
r=basic_machines.tonumber(fields.r) or 1;
NOT = basic_machines.tonumber(fields.NOT)
if minetest.is_protected({x=pos.x+x0,y=pos.y+y0,z=pos.z+z0},name) then
minetest.chat_send_player(name, "DETECTOR: position is protected. aborting.")
return
end
2016-04-02 00:38:14 -07:00
if minetest.is_protected({x=pos.x+x2,y=pos.y+y2,z=pos.z+z2},name) then
minetest.chat_send_player(name, "DETECTOR: position is protected. aborting.")
return
end
2015-05-18 08:49:49 -07:00
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
2016-04-01 15:04:58 -07:00
minetest.chat_send_player(name,"#detector: all coordinates must be between ".. -max_range .. " and " .. max_range); return
2015-05-05 14:34:03 -07:00
end
2018-11-13 19:09:03 -08:00
if fields.inv1 then
2018-11-13 19:09:03 -08:00
meta:set_string("inv1",fields.inv1);
end
2015-05-05 14:34:03 -07:00
meta:set_int("x0",x0);meta:set_int("y0",y0);meta:set_int("z0",z0);
2016-04-02 00:38:14 -07:00
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);
2018-11-13 19:09:03 -08:00
2016-04-02 00:38:14 -07:00
meta:set_int("r",math.min(r,10));
2018-07-10 15:48:03 -07:00
if NOT then
meta:set_int("NOT",NOT);
end
2015-05-05 14:34:03 -07:00
meta:set_string("node",fields.node or "");
2018-11-13 19:09:03 -08:00
local mode = fields.mode or "node";
meta:set_string("mode",mode);
local op = fields.op or "";
meta:set_string("op",op);
2015-05-05 14:34:03 -07:00
end
return
end
2018-11-13 19:09:03 -08:00
-- DISTRIBUTOR
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 (minetest.is_protected(pos,name) and not privs.privs) or not fields then return end -- only builder
--minetest.chat_send_all("formname " .. formname .. " fields " .. dump(fields))
2018-11-13 19:09:03 -08:00
if fields.OK == "OK" then
2018-11-13 19:09:03 -08:00
local posf = {}; local active = {};
local n = meta:get_int("n");
for i = 1,n do
2018-11-13 19:09:03 -08:00
posf[i]={x=basic_machines.tonumber(fields["x"..i]) or 0,y=basic_machines.tonumber(fields["y"..i]) or 0,z=basic_machines.tonumber(fields["z"..i]) or 0};
active[i]=basic_machines.tonumber(fields["active"..i]) or 0;
if (not (privs.privs) and math.abs(posf[i].x)>max_range or math.abs(posf[i].y)>max_range or math.abs(posf[i].z)>max_range) then
2018-11-13 19:09:03 -08:00
minetest.chat_send_player(name,"#distributor: all coordinates must be between ".. -max_range .. " and " .. max_range);
return
end
2018-11-13 19:09:03 -08:00
meta:set_int("x"..i,posf[i].x);meta:set_int("y"..i,posf[i].y);meta:set_int("z"..i,posf[i].z);
if posf[i].x==0 and posf[i].y==0 and posf[i].z==0 then
meta:set_int("active"..i,0); -- no point in activating itself
else
meta:set_int("active"..i,active[i]);
end
if fields.delay then
2018-11-13 19:09:03 -08:00
meta:set_float("delay", basic_machines.tonumber(fields.delay) or 0);
end
end
end
2018-11-13 19:09:03 -08:00
if fields["ADD"] then
local n = meta:get_int("n");
if n<16 then meta:set_int("n",n+1); end -- max 16 outputs
2017-12-21 09:06:15 -08:00
local form = get_distributor_form(pos,player)
minetest.show_formspec(player:get_player_name(), "basic_machines:distributor_"..minetest.pos_to_string(pos), form)
return
end
2018-11-13 19:09:03 -08:00
-- SHOWING TARGET
local j=-1;local n = meta:get_int("n");
for i = 1,n do if fields["SHOW"..i] then j = i end end
--show j-th point
2018-11-13 19:09:03 -08:00
if j>0 then
local posf={x=basic_machines.tonumber(fields["x"..j]) or 0,y=basic_machines.tonumber(fields["y"..j]) or 0,z=basic_machines.tonumber(fields["z"..j]) or 0};
machines.pos1[player:get_player_name()] = {x=posf.x+pos.x,y=posf.y+pos.y,z=posf.z+pos.z};
machines.mark_pos1(player:get_player_name())
return;
end
2018-11-13 19:09:03 -08:00
--SETUP TARGET
j=-1;
for i = 1,n do if fields["SET"..i] then j = i end end
-- set up j-th point
2018-11-13 19:09:03 -08:00
if j>0 then
punchset[name].node = "basic_machines:distributor";
punchset[name].state = j
punchset[name].pos = pos;
2018-11-13 19:09:03 -08:00
minetest.chat_send_player(name,"[DISTRIBUTOR] punch the position to set target "..j);
return;
end
2018-11-13 19:09:03 -08:00
-- REMOVE TARGET
if n>0 then
j=-1;
for i = 1,n do if fields["X"..i] then j = i end end
-- remove j-th point
2018-11-13 19:09:03 -08:00
if j>0 then
for i=j,n-1 do
meta:set_int("x"..i, meta:get_int("x"..(i+1)))
meta:set_int("y"..i, meta:get_int("y"..(i+1)))
meta:set_int("z"..i, meta:get_int("z"..(i+1)))
meta:set_int("active"..i, meta:get_int("active"..(i+1)))
end
2018-11-13 19:09:03 -08:00
meta:set_int("n",n-1);
2017-12-21 09:06:15 -08:00
local form = get_distributor_form(pos,player)
minetest.show_formspec(player:get_player_name(), "basic_machines:distributor_"..minetest.pos_to_string(pos), form)
return;
end
end
2018-11-13 19:09:03 -08:00
2016-12-05 03:48:59 -08:00
if fields.help == "help" then
local text = "SETUP: to select target nodes for activation click SET then click target node.\n"..
"You can add more targets with ADD. To see where target node is click SHOW button next to it.\n"..
"Numbers in each row represent (from left to right) : first 3 numbers are target coordinates,\n"..
"last number controls how signal is passed to target. For example, to only pass OFF signal use -2,\n"..
2017-12-21 09:06:15 -08:00
"to only pass ON use 2, -1 negates the signal, 1 = pass original signal, 0 blocks signal\n"..
"delay option adds delay to activations, in seconds. With negative delay activation is randomized with probability -delay/1000.\n\n"..
2017-12-21 09:06:15 -08:00
"ADVANCED: you can use distributor as an event handler. First you must deactivate first target by putting 0 at\n"..
2016-12-05 03:48:59 -08:00
"last place in first line. Meanings of first 2 numbers are as follows: first number 0/1 controls if node/n".. "listens to failed interact attempts around it, second number -1/1 listens to chat and can mute it";
local form = "size[5.5,5.5]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
"textarea[0,0;6,7;help;DISTRIBUTOR HELP;".. text.."]"
2016-12-05 03:48:59 -08:00
minetest.show_formspec(name, "basic_machines:help_distributor", form)
end
2018-11-13 19:09:03 -08:00
end
2018-11-13 19:09:03 -08:00
2015-05-01 09:40:54 -07:00
end)
-- CRAFTS --
2015-05-01 09:40:54 -07:00
2017-01-15 07:05:09 -08:00
minetest.register_craft({
output = "basic_machines:keypad",
recipe = {
{"default:stick"},
{"default:wood"},
}
})
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", "basic_machines:keypad", "default:stone"}
}
})
minetest.register_craft({
output = "basic_machines:detector",
recipe = {
{"default:mese_crystal", "default:mese_crystal"},
{"default:mese_crystal", "default:mese_crystal"},
{"basic_machines:keypad",""}
}
})
minetest.register_craft({
output = "basic_machines:light_on",
recipe = {
{"default:torch", "default:torch"},
{"default:torch", "default:torch"}
}
})
minetest.register_craft({
output = "basic_machines:distributor",
recipe = {
{"default:steel_ingot"},
{"default:mese_crystal"},
{"basic_machines:keypad"}
}
})
minetest.register_craft({
output = "basic_machines:clockgen",
recipe = {
{"default:diamondblock"},
{"basic_machines:keypad"}
}
})