c the commit

interact directly with machine blocks when marks displayed
hold sneak and punch a block to abort interactive setup
allow removing keypad password
add place sounds for mover in normal, dig and transport modes
somewhat rework player punch in space
code maintenance
This commit is contained in:
waxtatect 2024-04-21 20:23:12 +02:00
parent f8a27cef49
commit f9431c5e09
14 changed files with 144 additions and 96 deletions

View File

@ -1,5 +1,5 @@
-- (c) 2015-2016 rnd
-- Copyright (C) 2022-2023 мтест
-- Copyright (C) 2022-2024 мтест
-- See README.md for license details
local S = basic_machines.S
@ -42,7 +42,7 @@ minetest.register_node("basic_machines:clockgen", {
local name = placer:get_player_name()
if minetest.find_node_near(pos, 15, {"basic_machines:clockgen"}) then
minetest.set_node(pos, {name = "air"})
minetest.remove_node(pos)
minetest.add_item(pos, "basic_machines:clockgen")
minetest.chat_send_player(name, S("Clock Generator: Interference from nearby clock generator detected"))
return

View File

@ -5,7 +5,7 @@
basic_machines = {
F = minetest.formspec_escape,
S = minetest.get_translator("basic_machines"),
version = "02/27/2024 (fork)",
version = "04/23/2024 (fork)",
properties = {
no_clock = false, -- if true all continuously running activities (clockgen/keypad) are disabled
machines_TTL = 16, -- time to live for signals, how many hops before signal dissipates

View File

@ -1,6 +1,6 @@
-- Make doors open/close with signal
-- (c) 2015-2016 rnd
-- Copyright (C) 2022-2023 мтест
-- Copyright (C) 2022-2024 мтест
-- See README.md for license details
-- local S = basic_machines.S
@ -154,7 +154,7 @@ if use_doors then
if count == 1 then
minetest.chat_send_player(player_name, S("@1: Punch me one more time to remove me", door))
elseif count == 2 then -- remove steel door and drop it
minetest.set_node(pos, {name = "air"})
minetest.remove_node(pos)
minetest.add_item(pos, ItemStack(dropname))
end
end

View File

@ -1,5 +1,5 @@
-- (c) 2015-2016 rnd
-- Copyright (C) 2022-2023 мтест
-- Copyright (C) 2022-2024 мтест
-- See README.md for license details
local F, S = basic_machines.F, basic_machines.S
@ -93,9 +93,8 @@ basic_machines.use_keypad = function(pos, ttl, reset, reset_msg)
end
end
-- set text on target
local text = meta:get_string("text")
if text ~= "" then
if text ~= "" then -- text operations
if text == "@" and meta:get_string("pass") ~= "" then -- keyboard mode, set text from input
text = meta:get_string("input")
meta:set_string("input", "") -- clear input
@ -113,10 +112,10 @@ basic_machines.use_keypad = function(pos, ttl, reset, reset_msg)
local pitch = tonumber(text_sub:sub(i + 1)) or 1
if pitch < 0.01 or pitch > 10 then pitch = 1 end
meta:set_string("infotext", S("Playing sound: '@1', pitch: @2", (sound_name:gsub("_", " ")), pitch))
minetest.sound_play(sound_name, {pos = pos, gain = 1, max_hear_distance = 16, pitch = pitch}, true)
minetest.sound_play({name = sound_name, pitch = pitch}, {pos = pos, max_hear_distance = 16}, true)
else
meta:set_string("infotext", S("Playing sound: '@1'", (text_sub:gsub("_", " "))))
minetest.sound_play(text_sub, {pos = pos, gain = 1, max_hear_distance = 16}, true)
minetest.sound_play(text_sub, {pos = pos, max_hear_distance = 16}, true)
end
return
end
@ -150,6 +149,7 @@ basic_machines.use_keypad = function(pos, ttl, reset, reset_msg)
end
end
-- set text on target
if signs[name] then -- update text on signs
if use_signs_lib then -- with signs_lib
if signs_lib.update_sign then
@ -191,12 +191,14 @@ basic_machines.use_keypad = function(pos, ttl, reset, reset_msg)
tmeta:set_string("text", text)
end
elseif bit == 37 then -- target keypad's text starts with '%' (ascii code 37) -> word extraction
local ttext = minetest.get_meta({x = pos.x, y = pos.y + 1, z = pos.z}):get_string("infotext")
local i = tonumber(text:sub(2, 2)) or 1 -- read the number following the '%'
-- extract i-th word from text
local j = 0
for word in ttext:gmatch("%S+") do
j = j + 1; if j == i then text = word; break end
local i = tonumber(text:sub(2, 2)) or 0 -- read the number following the '%'
if i > 0 then
-- extract i-th word from text
local ttext = minetest.get_meta({x = pos.x, y = pos.y + 1, z = pos.z}):get_string("infotext")
local j = 0
for word in ttext:gmatch("%S+") do
j = j + 1; if j == i then text = word; break end
end
end
-- set target keypad's text
@ -275,8 +277,7 @@ basic_machines.use_keypad = function(pos, ttl, reset, reset_msg)
minetest.get_meta(tpos):set_string("infotext", text:gsub("^ +$", "")) -- just set text
end
-- target activation
else
else -- target activation
if count < 2 then
meta:set_string("infotext", S("Keypad operation: @1 cycle left", count))
else

View File

@ -154,6 +154,7 @@ Light off=
Light=
DETECTOR=
DISTRIBUTOR=
KEYPAD=
MOVER=
Enter text:=
Enter password:=
@ -162,6 +163,7 @@ KEYPAD: You must be able to build to set up keypad.=
MOVER: Now punch source1, source2, end position to set up mover.=
KEYPAD: Now punch the target block.=
DETECTOR: Now punch the source block.=
@1: Aborting interactive setup.=
MOVER: Punch closer to mover. Resetting.=
MOVER: Punch something else. Aborting.=
MOVER: Source1 position for mover set. Punch again to set source2 position.=
@ -188,7 +190,7 @@ Mover block. Set up with source coordinates @1, @2, @3 -> @4, @5, @6 and target
MOVER: Battery found - displaying mark 1=
MOVER: Please put battery nearby=
Mover help=
version @1@nSetup: For interactive setup punch the mover and then punch source1, source2, target node (follow instructions). Put the mover directly next to a battery. For advanced setup right click mover. Positions are defined by (x, y, z) coordinates. Mover itself is at coordinates (0, 0, 0).=
version @1@nSetup: For interactive setup punch the mover and follow chat instructions (hold sneak and punch a block to abort setup). Put the mover directly next to a battery. For advanced setup right click mover. Positions are defined by (x, y, z) coordinates. 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); by setting 'filter' only selected node is moved, drop (drops node on ground), object (teleportation of players and objects) - distance between source1/2 defines teleport radius; by setting 'filter' you can specify move time - [0.2, 20] - for non players.@nAfter changing from/to object mode, you need to reconfigure sources position.@nInventory mode can exchange items between node inventories. You need to select inventory name for source/target from the dropdown list on the right.@n@nAdvanced:@nYou 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@nFuel consumption depends on blocks to be moved, distance and temperature. For example, stone or tree is harder to move than dirt, harvesting wheat is very cheap and and moving lava is very hard. High temperature increases fuel consumption while low temperature reduces it.@n@nUpgrade mover by moving mese blocks in upgrade inventory. Each mese block increases mover range by @1, fuel consumption is divided by number of mese blocks in upgrade. Max @2 blocks are used for upgrade.@n@nActivate mover by keypad/detector signal or mese signal through mesecon adapter (if mesecons mod).=
DISTRIBUTOR: Position @1 is protected. Aborting.=
@ -196,7 +198,7 @@ DISTRIBUTOR: All coordinates must be between @1 and @2.=
DISTRIBUTOR: Connected @1 targets.=
Distributor help=
Target: Coordinates (x, y, z) relative to the distributor.@n@nMode: -2@=only OFF, -1@=NOT input, 0/1@=input, 2@=only ON, output signal of the target.@n@nDelay: Adds delay to activations, in seconds. A negative delay activation is randomized with probability -delay/1000.=
@n@nSetup: To select a target for activation, click "Set" button then click the target.@nYou can add more targets with "Add" button. To see where the target is click "Show" button next to it.@n4 numbers in each row represent (from left to right): first 3 numbers are target coordinates (x, y, z), last number (Mode) controls how signal is passed to target.@nFor example, to only pass OFF signal use -2, to only pass ON signal use 2, -1 negates the signal, 1 passes original signal, 0 blocks signal.@n"view" button toggles view of target names, in names view there is "scan" button which automatically scans for valid targets in a box defined by first and second target.@n@nAdvanced:@nYou can use the distributor as an event handler - it listens to events like interact attempts and chat around the distributor.@nYou need to place the distributor at a position (x, y, z), with coordinates of the form (20*i, 20*j+1, 20*k) for some integers i, j, k.@nRight click holding a distributor in the hand to show a suitable position.@nThen you need to configure first row of numbers in the distributor:@nBy putting 0 as Mode it will start to listen. First number x @= 0/1 controls if node listens to failed interact attempts around it, second number y @= -1/0/1 controls listening to chat (-1 additionally mutes chat)=
@n@nSetup: To select a target for activation, click "Set" button then click the target (hold sneak and punch a block to abort setup).@nYou can add more targets with "Add" button. To see where the target is click "Show" button next to it.@n4 numbers in each row represent (from left to right): first 3 numbers are target coordinates (x, y, z), last number (Mode) controls how signal is passed to target.@nFor example, to only pass OFF signal use -2, to only pass ON signal use 2, -1 negates the signal, 1 passes original signal, 0 blocks signal.@n"view" button toggles view of target names, in names view there is "scan" button which automatically scans for valid targets in a box defined by first and second target.@n@nAdvanced:@nYou can use the distributor as an event handler - it listens to events like interact attempts and chat around the distributor.@nYou need to place the distributor at a position (x, y, z), with coordinates of the form (20*i, 20*j+1, 20*k) for some integers i, j, k.@nRight click holding a distributor in the hand to show a suitable position.@nThen you need to configure first row of numbers in the distributor:@nBy putting 0 as Mode it will start to listen. First number x @= 0/1 controls if node listens to failed interact attempts around it, second number y @= -1/0/1 controls listening to chat (-1 additionally mutes chat)=
DISTRIBUTOR: Punch the position to set target @1.=
KEYPAD: Position is protected. Aborting.=
KEYPAD: All coordinates must be between @1 and @2.=
@ -209,7 +211,7 @@ Keypad help=
Mode: 0@=IDLE, 1@=OFF, 2@=ON, 3@=TOGGLE, control the way how the target is activated.@n@nRepeat: Number to control how many times activation is repeated after initial punch.@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@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@nTarget: Coordinates (x, y, z) relative to the 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@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 similar 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.=
ACCESS DENIED. WRONG PASSWORD.=
@n@nSetup: Right click or punch (left click) the keypad, then follow instructions.@n@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:@nWhen target node is keypad, its "text" field will be set.@nWhen target is detector/mover, its "filter" field will be set. To clear "filter" set text to "@@".@nWhen target is distributor, you can change i-th target of distributor mode with "<i> <mode>".@nWhen target is autocrafter, set i-th recipe with "<itemname> [<i>]". To clear the recipe set text to "@@".=
@n@nSetup: Right click or punch (left click) the keypad, then follow chat instructions (hold sneak and punch a block to abort setup).@n@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:@nWhen target node is keypad, its "text" field will be set.@nWhen target is detector/mover, its "filter" field will be set. To clear "filter" set text to "@@".@nWhen target is distributor, you can change i-th target of distributor mode with "<i> <mode>".@nWhen target is autocrafter, set i-th recipe with "<itemname> [<i>]". To clear the recipe set text to "@@".=
@nWhen target is light, you can change the index value (a multiple of 8) with "i<index>".=
@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", optionally followed by a space and pitch value: 0.01 to 10. Can choose a sound with sounds menu.=
ACCESS GRANTED=
@ -217,7 +219,7 @@ Operation aborted by user. Punch to activate.=
DETECTOR: Position is protected. Aborting.=
DETECTOR: All coordinates must be between @1 and @2.=
Detector help=
Setup: Right click or punch and follow chat instructions. With a detector you can detect nodes, objects, players, items inside inventories, nodes information and light levels. If detector activates it will trigger machine (on or off) at target position.@n@nThere are 6 modes of operation - node/player/object/inventory/infotext/light detection. Inside detection filter write node/player/object name or infotext/light level. If you detect node/player/object you can specify a range of detection. If you want detector to activate target precisely when its not triggered set output signal to 1.@n@nFor 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 mode is inventory it will check for items in specified inventory of source node like a chest.@n@nAdvanced:@nIn inventory (must set a filter)/node detection mode, you can specify a second source and select AND/OR from the right top dropdown list to do logical operations.@nYou can also filter output signal in any modes:@n-2@=only OFF, -1@=NOT, 0/1@=normal, 2@=only ON, 3@=only if changed, 4@=if target is keypad set its text to detected object name.=
Setup: Right click or punch and follow chat instructions (hold sneak and punch a block to abort setup). With a detector you can detect nodes, objects, players, items inside inventories, nodes information and light levels. If detector activates it will trigger machine (on or off) at target position.@n@nThere are 6 modes of operation - node/player/object/inventory/infotext/light detection. Inside detection filter write node/player/object name or infotext/light level. If you detect node/player/object you can specify a range of detection. If you want detector to activate target precisely when its not triggered set output signal to 1.@n@nFor 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 mode is inventory it will check for items in specified inventory of source node like a chest.@n@nAdvanced:@nIn inventory (must set a filter)/node detection mode, you can specify a second source and select AND/OR from the right top dropdown list to do logical operations.@nYou can also filter output signal in any modes:@n-2@=only OFF, -1@=NOT, 0/1@=normal, 2@=only ON, 3@=only if changed, 4@=if target is keypad set its text to detected object name.=
MOVER: Wrong filter - must be name of existing minetest block=
Mesecon Adapter: place machine to be activated on top=
Mesecon Adapter=

View File

@ -1,5 +1,5 @@
-- (c) 2015-2016 rnd
-- Copyright (C) 2022-2023 мтест
-- Copyright (C) 2022-2024 мтест
-- See README.md for license details
local F, S = basic_machines.F, basic_machines.S
@ -52,6 +52,7 @@ local punchable_nodes = {
local description_translated = {
["DETECTOR"] = S("DETECTOR"),
["DISTRIBUTOR"] = S("DISTRIBUTOR"),
["KEYPAD"] = S("KEYPAD"),
["MOVER"] = S("MOVER")
}
@ -127,8 +128,9 @@ minetest.register_on_punchnode(function(pos, node, puncher)
local self_pos = punchset[name].pos
if minetest.get_node(self_pos).name ~= punch_node then
punchset[name] = {state = 0, node = ""}; return
if minetest.get_node(self_pos).name ~= punch_node or (puncher:get_player_control() or {}).sneak then
minetest.chat_send_player(name, S("@1: Aborting interactive setup.", description_translated[punchset_desc]))
machines.remove_markers(name, {"1", "11", "2"}); punchset[name] = {state = 0, node = ""}; return
end
@ -162,24 +164,24 @@ minetest.register_on_punchnode(function(pos, node, puncher)
punchset[name].pos1 = pos -- source1
punchset[name].state = 2
machines.mark_pos1(name, pos) -- mark pos1
machines.mark_pos1(name, pos, true) -- mark pos1
minetest.chat_send_player(name, S("MOVER: Source1 position for mover set. Punch again to set source2 position."))
elseif punch_state == 2 then
if not privs and
(abs(pos.x - self_pos.x) > range or abs(pos.y - self_pos.y) > range or abs(pos.z - self_pos.z) > range)
then
minetest.chat_send_player(name, S("MOVER: Punch closer to mover. Resetting."))
punchset[name] = {state = 0, node = ""}; return
machines.remove_markers(name, {"1"}); punchset[name] = {state = 0, node = ""}; return
end
if vector.equals(pos, self_pos) then
minetest.chat_send_player(name, S("MOVER: Punch something else. Aborting."))
punchset[name] = {state = 0, node = ""}; return
machines.remove_markers(name, {"1"}); punchset[name] = {state = 0, node = ""}; return
end
punchset[name].pos11 = pos -- source2
punchset[name].state = 3
machines.mark_pos11(name, pos) -- mark pos11
machines.mark_pos11(name, pos, true) -- mark pos11
minetest.chat_send_player(name, S("MOVER: Source2 position for mover set. Punch again to set target position."))
elseif punch_state == 3 then
local mode = meta:get_string("mode")
@ -205,7 +207,7 @@ minetest.register_on_punchnode(function(pos, node, puncher)
minetest.chat_send_player(name, S("MOVER: Elevator setup completed, upgrade level @1.", upgrade - 1))
else
minetest.chat_send_player(name, S("MOVER: Error while trying to make an elevator. Need at least @1 diamond block(s) in upgrade (1 for every 100 distance).", requirement))
punchset[name] = {state = 0, node = ""}; return
machines.remove_markers(name, {"1", "11"}); punchset[name] = {state = 0, node = ""}; return
end
end
end
@ -213,10 +215,10 @@ minetest.register_on_punchnode(function(pos, node, puncher)
(abs(pos.x - self_pos.x) > range or abs(pos.y - self_pos.y) > range or abs(pos.z - self_pos.z) > range)
then
minetest.chat_send_player(name, S("MOVER: Punch closer to mover. Aborting."))
punchset[name] = {state = 0, node = ""}; return
machines.remove_markers(name, {"1", "11"}); punchset[name] = {state = 0, node = ""}; return
end
machines.mark_pos2(name, pos) -- mark pos2
machines.mark_pos2(name, pos, true) -- mark pos2
local x0 = pos1.x - self_pos.x -- source1
local y0 = pos1.y - self_pos.y
@ -259,7 +261,7 @@ minetest.register_on_punchnode(function(pos, node, puncher)
punchset[name] = {state = 0, node = ""}; return
end
machines.mark_pos1(name, pos) -- mark pos1
machines.mark_pos1(name, pos, true) -- mark pos1
local meta = minetest.get_meta(self_pos)
meta:set_int("x" .. punch_state, x); meta:set_int("y" .. punch_state, y); meta:set_int("z" .. punch_state, z)
@ -285,11 +287,15 @@ minetest.register_on_punchnode(function(pos, node, puncher)
punchset[name] = {state = 0, node = ""}; return
end
machines.mark_pos1(name, pos) -- mark pos1
machines.mark_pos1(name, pos, true) -- mark pos1
local meta = minetest.get_meta(self_pos)
meta:set_int("x0", x); meta:set_int("y0", y); meta:set_int("z0", z)
meta:set_string("infotext", S("Punch keypad to use it."))
if meta:get_string("pass") == "" then
meta:set_string("infotext", S("Punch keypad to use it."))
else
meta:set_string("infotext", S("Punch keypad to use it. Password protected."))
end
punchset[name] = {state = 0, node = ""}
minetest.chat_send_player(name, S("KEYPAD: Target set with coordinates @1, @2, @3.", x, y, z))
@ -307,12 +313,12 @@ minetest.register_on_punchnode(function(pos, node, puncher)
if punch_state == 1 then
punchset[name].pos1 = pos
punchset[name].state = 2
machines.mark_pos1(name, pos) -- mark pos1
machines.mark_pos1(name, pos, true) -- mark pos1
minetest.chat_send_player(name, S("DETECTOR: Now punch the target machine."))
elseif punch_state == 2 then
if vector.equals(pos, self_pos) then
minetest.chat_send_player(name, S("DETECTOR: Punch something else. Aborting."))
punchset[name] = {state = 0, node = ""}; return
machines.remove_markers(name, {"1"}); punchset[name] = {state = 0, node = ""}; return
end
machines.mark_pos2(name, pos) -- mark pos2
@ -491,15 +497,15 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
elseif fields.show then -- display mover area defined by sources
local pos1 = {x = meta:get_int("x0"), y = meta:get_int("y0"), z = meta:get_int("z0")} -- source1
local pos11 = {x = meta:get_int("x1"), y = meta:get_int("y1"), z = meta:get_int("z1")} -- source2
local markerA = machines.mark_posA(name, vector.add(pos, vector.divide(vector.add(pos1, pos11), 2)))
if markerA then
markerA:set_properties({visual_size = {x = abs(pos11.x - pos1.x) + 1.11,
local markerS = machines.mark_posS(name, vector.add(pos, vector.divide(vector.add(pos1, pos11), 2)))
if markerS then
markerS:set_properties({visual_size = {x = abs(pos11.x - pos1.x) + 1.11,
y = abs(pos11.y - pos1.y) + 1.11, z = abs(pos11.z - pos1.z) + 1.11}})
end
elseif fields.help then
minetest.show_formspec(name, "basic_machines:help_mover", "formspec_version[4]size[8,9.3]textarea[0,0.35;8,8.95;help;" ..
F(S("Mover help")) .. ";" .. F(S("version @1\nSetup: For interactive setup punch the mover and then punch source1, source2, target node (follow instructions)." ..
F(S("Mover help")) .. ";" .. F(S("version @1\nSetup: For interactive setup punch the mover and follow chat instructions (hold sneak and punch a block to abort setup)." ..
" Put the mover directly next to a battery. For advanced setup right click mover." ..
" Positions are defined by (x, y, z) coordinates. Mover itself is at coordinates (0, 0, 0).", basic_machines.version)) ..
F(S("\n\nModes of operation: normal (just teleport block), dig (digs and gives you resulted node - good for harvesting farms);" ..
@ -644,7 +650,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
F(S("Distributor help")) .. ";" .. F(S("Target: Coordinates (x, y, z) relative to the distributor." ..
"\n\nMode: -2=only OFF, -1=NOT input, 0/1=input, 2=only ON, output signal of the target." ..
"\n\nDelay: Adds delay to activations, in seconds. A negative delay activation is randomized with probability -delay/1000.")) ..
F(S("\n\nSetup: To select a target for activation, click \"Set\" button then click the target.\n" ..
F(S("\n\nSetup: To select a target for activation, click \"Set\" button then click the target (hold sneak and punch a block to abort setup).\n" ..
"You can add more targets with \"Add\" button. To see where the target is click \"Show\" button next to it.\n" ..
"4 numbers in each row represent (from left to right): first 3 numbers are target coordinates (x, y, z), last number (Mode) controls how signal is passed to target.\n" ..
"For example, to only pass OFF signal use -2, to only pass ON signal use 2, -1 negates the signal, 1 passes original signal, 0 blocks signal.\n" ..
@ -729,7 +735,11 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
local pass = fields.pass or ""
if pass ~= "" then
if pass == "" then
if meta:get_string("pass") ~= "" then
meta:set_string("pass", "")
end
else
local mpass = meta:get_string("pass")
if pass ~= mpass then
if pass:len() > 16 then -- don't replace password with hash which is longer - 27 chars
@ -812,7 +822,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
"\n\nTarget: Coordinates (x, y, z) relative to the 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.")) ..
F(S("\n\nSetup: Right click or punch (left click) the keypad, then follow instructions." ..
F(S("\n\nSetup: Right click or punch (left click) the keypad, then follow chat instructions (hold sneak and punch a block to abort setup)." ..
"\n\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:\nWhen target node is keypad, its \"text\" field will be set.\n" ..
"When target is detector/mover, its \"filter\" field will be set. To clear \"filter\" set text to \"@@\".\n" ..
@ -921,7 +931,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
elseif fields.help then
minetest.show_formspec(name, "basic_machines:help_detector", "formspec_version[4]size[7.4,7.4]textarea[0,0.35;7.4,7.05;help;" ..
F(S("Detector help")) .. ";" .. F(S("Setup: Right click or punch and follow chat instructions." ..
F(S("Detector help")) .. ";" .. F(S("Setup: Right click or punch and follow chat instructions (hold sneak and punch a block to abort setup)." ..
" With a detector you can detect nodes, objects, players, items inside inventories, nodes information and light levels. " ..
"If detector activates it will trigger machine (on or off) at target position." ..
"\n\nThere are 6 modes of operation - node/player/object/inventory/infotext/light detection." ..

View File

@ -1,40 +1,61 @@
-- rnd: code borrowed from machines, mark.lua
-- Copyright (C) 2022-2023 мтест
-- Copyright (C) 2022-2024 мтест
-- See README.md for license details
-- Needed for marking
machines = {}
local machines_marks = {"1", "11", "2", "N", "S"}
for _, n in ipairs({"1", "11", "2", "N", "A"}) do
machines = {
remove_markers = function(name, marks)
marks = marks or machines_marks
for _, n in ipairs(marks) do
local markern = "marker" .. n
if machines[markern][name] then
machines[markern][name]:remove() -- remove marker
end
end
end
}
for _, n in ipairs(machines_marks) do
local markern = "marker" .. n
local posn = "machines:pos" .. n
local texturen, delay
if n == "N" then
if n == "N" then -- mover "Now" button marker
texturen = "machines_pos.png^[colorize:#ffd700"
delay = 27
elseif n == "A" then
elseif n == "S" then -- mover "Show" button marker
texturen = "machines_pos.png^[colorize:#008080"
delay = 21
else
else -- source1, source2 and target markers
texturen = "machines_pos" .. n .. ".png"
delay = 9
end
machines[markern] = {}
machines["mark_pos" .. n] = function(name, pos)
machines["mark_pos" .. n] = function(name, pos, node_is_punchable)
if machines[markern][name] then -- marker already exists
machines[markern][name]:remove() -- remove marker
end
-- add marker
machines[markern][name] = minetest.add_entity(pos, posn)
if machines[markern][name] then
machines[markern][name]:get_luaentity()._name = name
local obj = minetest.add_entity(pos, posn)
if obj then
obj:get_luaentity()._name = name
if node_is_punchable then
obj:set_properties({pointable = false})
else
local node_name = minetest.get_node(obj:get_pos()).name
if (node_name):sub(1, 15) == "basic_machines:" then
obj:set_properties({pointable = false})
end
end
machines[markern][name] = obj
end
return machines[markern][name]
return obj
end
minetest.register_entity(":" .. posn, {
@ -59,7 +80,9 @@ for _, n in ipairs({"1", "11", "2", "N", "A"}) do
end,
on_punch = function(self)
minetest.after(0.1, function()
self.object:remove()
if self and self.object then
self.object:remove()
end
end)
end,
_name = "",

View File

@ -138,8 +138,8 @@ local mover = {
["3d_armor_stand:armor_entity"] = true,
["__builtin:item"] = true,
["itemframes:item"] = true,
["machines:posA"] = true,
["machines:posN"] = true,
["machines:posS"] = true,
["painting:paintent"] = true,
["painting:picent"] = true,
["shield_frame:shield_entity"] = true,

View File

@ -1,5 +1,5 @@
-- (c) 2015-2016 rnd
-- Copyright (C) 2022-2023 мтест
-- Copyright (C) 2022-2024 мтест
-- See README.md for license details
local F, S = basic_machines.F, basic_machines.S
@ -68,7 +68,7 @@ local function dig(pos, meta, owner, prefer, pos1, node1, node1_name, source_che
prefer = prefer or meta:get_string("prefer")
source_chest = source_chest or mover_chests[node1_name]
local third_upgradetype = upgradetype == 3
local seed_planting, node_def, node1_param2, last_pos2, new_fuel_cost
local seed_planting, node_def, node1_param2, sound_def, last_pos2, new_fuel_cost
-- checks
if prefer ~= "" then -- filter check
@ -85,6 +85,7 @@ local function dig(pos, meta, owner, prefer, pos1, node1, node1_name, source_che
else
return
end
sound_def = ((plant_def or minetest.registered_nodes[prefer] or {}).sounds or {}).place -- preparing for sound_play
else -- set preferred node
node_def = minetest.registered_nodes[prefer]
if node_def then
@ -224,12 +225,15 @@ local function dig(pos, meta, owner, prefer, pos1, node1, node1_name, source_che
new_fuel_cost = fuel_cost * (1 - node2_count / length_pos2)
end
end
sound_def = (node_def.sounds or {}).place -- preparing for sound_play
minetest.bulk_set_node(pos2, node1)
else -- try to place node as the owner would
sound_def = (node_def.sounds or {}).place -- preparing for sound_play
local placer, is_placed = minetest.get_player_by_name(owner)
if placer then -- only if owner online
local on_place = (node_def or {}).on_place
local on_place = node_def.on_place
if on_place then
local _, placed_pos = on_place(node_to_stack(node1, node_def.paramtype2),
placer, {type = "node", under = pos2,
@ -384,7 +388,7 @@ local function dig(pos, meta, owner, prefer, pos1, node1, node1_name, source_che
source_neighbor = minetest.find_node_near(pos1, 1, liquiddef.source)
end
if not (source_neighbor and liquiddef.force_renew) then
minetest.set_node(pos1, {name = "air"})
minetest.remove_node(pos1)
end
--
end
@ -400,7 +404,7 @@ local function dig(pos, meta, owner, prefer, pos1, node1, node1_name, source_che
end
end
else -- remove node and put drops in chest
minetest.set_node(pos1, {name = "air"})
minetest.remove_node(pos1)
check_for_falling(pos1) -- pre 5.0.0 nodeupdate(pos1)
add_node_drops(node1_name, pos2, node1, prefer ~= "", node_def, node1_param2)
@ -408,7 +412,7 @@ local function dig(pos, meta, owner, prefer, pos1, node1, node1_name, source_che
end
end
elseif node2_name == "air" and not third_upgradetype then -- move node from pos1 to pos2
minetest.set_node(pos1, {name = "air"})
minetest.remove_node(pos1)
check_for_falling(pos1) -- pre 5.0.0 nodeupdate(pos1)
minetest.set_node(pos2, node1)
@ -417,11 +421,11 @@ local function dig(pos, meta, owner, prefer, pos1, node1, node1_name, source_che
end
end
-- play sound
local activation_count = meta:get_int("activation_count")
-- if activation_count < 16 then
-- minetest.sound_play("basic_machines_transport", {pos = last_pos2 or pos2, gain = 1, max_hear_distance = 8}, true)
-- end
if sound_def and activation_count < 16 then -- play sound
minetest.sound_play(sound_def, {pitch = 0.9, pos = last_pos2 or pos2, max_hear_distance = 12}, true)
end
return activation_count, new_fuel_cost
end

View File

@ -1,5 +1,5 @@
-- (c) 2015-2016 rnd
-- Copyright (C) 2022-2023 мтест
-- Copyright (C) 2022-2024 мтест
-- See README.md for license details
local F, S = basic_machines.F, basic_machines.S
@ -80,7 +80,7 @@ local function drop(_, meta, owner, prefer, pos1, node1, node1_name, source_ches
inv:remove_item("main", stack)
end
elseif prefer == node1_name and inv:is_empty("main") then -- remove chest only if empty
minetest.set_node(pos1, {name = "air"})
minetest.remove_node(pos1)
else
return
end
@ -90,7 +90,7 @@ local function drop(_, meta, owner, prefer, pos1, node1, node1_name, source_ches
return
end
elseif minetest.get_node(pos2).name == "air" then -- drop node
minetest.set_node(pos1, {name = "air"})
minetest.remove_node(pos1)
if prefer ~= "" then
minetest.add_item(pos2, node_to_stack(node1, nil, node1_param2))

View File

@ -1,5 +1,5 @@
-- (c) 2015-2016 rnd
-- Copyright (C) 2022-2023 мтест
-- Copyright (C) 2022-2024 мтест
-- See README.md for license details
local F, S = basic_machines.F, basic_machines.S
@ -18,7 +18,7 @@ local function normal(pos, meta, owner, prefer, pos1, node1, node1_name, source_
prefer = prefer or meta:get_string("prefer")
source_chest = source_chest or mover_chests[node1_name]
local third_upgradetype = upgradetype == 3
local node2_name, target_chest, node_def, node1_param2, new_fuel_cost, last_pos2
local node2_name, target_chest, node_def, node1_param2, new_fuel_cost, last_pos2, sound_def
-- checks
if prefer ~= "" then -- filter check
@ -117,6 +117,8 @@ local function normal(pos, meta, owner, prefer, pos1, node1, node1_name, source_
return
end
sound_def = (node_def.sounds or {}).place -- preparing for sound_play
if third_upgradetype then
if fuel_cost > 0 then
local length_pos2 = #pos2
@ -190,7 +192,7 @@ local function normal(pos, meta, owner, prefer, pos1, node1, node1_name, source_
minetest.bulk_set_node(pos1, {name = "air"})
else
minetest.set_node(pos1, {name = "air"})
minetest.remove_node(pos1)
local inv = minetest.get_meta(pos2):get_inventory()
if prefer ~= "" then
@ -201,18 +203,19 @@ local function normal(pos, meta, owner, prefer, pos1, node1, node1_name, source_
end
end
elseif node2_name == "air" and not third_upgradetype then -- move node from pos1 to pos2
minetest.set_node(pos1, {name = "air"})
sound_def = ((node_def or minetest.registered_nodes[node1_name] or {}).sounds or {}).place -- preparing for sound_play
minetest.remove_node(pos1)
minetest.set_node(pos2, node1)
else -- nothing to do
return
end
end
-- play sound
local activation_count = meta:get_int("activation_count")
-- if activation_count < 16 then
-- minetest.sound_play("basic_machines_transport", {pos = last_pos2 or pos2, gain = 1, max_hear_distance = 8}, true)
-- end
if sound_def and activation_count < 16 then -- play sound
minetest.sound_play(sound_def, {pitch = 0.9, pos = last_pos2 or pos2, max_hear_distance = 12}, true)
end
return activation_count, new_fuel_cost
end

View File

@ -1,5 +1,5 @@
-- (c) 2015-2016 rnd
-- Copyright (C) 2022-2023 мтест
-- Copyright (C) 2022-2024 мтест
-- See README.md for license details
local F, S = basic_machines.F, basic_machines.S
@ -8,11 +8,12 @@ local check_palette_index = basic_machines.check_palette_index
local function transport(pos, meta, owner, prefer, pos1, node1, node1_name, source_chest, pos2)
prefer = prefer or meta:get_string("prefer")
local node_def, sound_def
-- checks
if prefer ~= "" then -- filter check
if prefer == node1_name then -- only take preferred node
local node_def = minetest.registered_nodes[prefer]
node_def = minetest.registered_nodes[prefer]
if node_def then
if not check_palette_index(meta, node1, node_def) then -- only take preferred node with palette_index
return
@ -30,8 +31,8 @@ local function transport(pos, meta, owner, prefer, pos1, node1, node1_name, sour
local node2_name = minetest.get_node(pos2).name
-- transport items
if source_chest and mover_chests[node2_name] then -- transport all chest items from source to target
if prefer == node2_name then -- transport only with same chest type
if source_chest and mover_chests[node2_name] then -- take all items from chest to chest (filter needed)
if prefer == node2_name then -- only to same chest type
local inv2 = minetest.get_meta(pos2):get_inventory()
if inv2:is_empty("main") then
local inv1 = minetest.get_meta(pos1):get_inventory()
@ -45,19 +46,20 @@ local function transport(pos, meta, owner, prefer, pos1, node1, node1_name, sour
return
end
elseif node2_name == "air" then -- transport nodes parallel as defined by source1 and target, clone with complete metadata
sound_def = ((node_def or minetest.registered_nodes[node1_name] or {}).sounds or {}).place -- preparing for sound_play
local meta1 = minetest.get_meta(pos1):to_table()
minetest.set_node(pos2, node1)
if meta1 then minetest.get_meta(pos2):from_table(meta1) end
minetest.set_node(pos1, {name = "air"})
minetest.remove_node(pos1)
else -- nothing to do
return
end
-- play sound
local activation_count = meta:get_int("activation_count")
-- if activation_count < 16 then
-- minetest.sound_play("basic_machines_transport", {pos = pos2, gain = 1, max_hear_distance = 8}, true)
-- end
if sound_def and activation_count < 16 then -- play sound
minetest.sound_play(sound_def, {pitch = 0.9, pos = pos2, max_hear_distance = 12}, true)
end
return activation_count
end

View File

@ -1,5 +1,5 @@
-- (c) 2015-2016 rnd
-- Copyright (C) 2022-2023 мтест
-- Copyright (C) 2022-2024 мтест
-- See README.md for license details
local S = basic_machines.S
@ -10,10 +10,13 @@ local space_start_eff = basic_machines.settings.space_start_eff
local use_player_monoids = minetest.global_exists("player_monoids")
local use_basic_protect = minetest.global_exists("basic_protect")
minetest.register_on_punchplayer(function(player, hitter, _, tool_capabilities, dir)
if player:get_pos().y > space_start and hitter:is_player() then
if vector.length(player:get_velocity()) > 0 then
player:add_velocity(vector.multiply(dir, 5)) -- push player a little
minetest.register_on_punchplayer(function(player, hitter, time_from_last_punch, tool_capabilities)
if player:get_pos().y > space_start and hitter and hitter:is_player() then
if time_from_last_punch > 0.8 and vector.length(player:get_velocity()) > 0.2 then
local dir = vector.subtract(player:get_pos(), hitter:get_pos())
local unit_vector = vector.divide(dir, vector.length(dir))
local punch_vector = {x = 5, y = 0.9, z = 5}
player:add_velocity(vector.multiply(unit_vector, punch_vector)) -- push player a little
end
if tool_capabilities and ((tool_capabilities.damage_groups or {}).fleshy or 0) == 1 then
return true
@ -188,7 +191,7 @@ if basic_machines.use_default then
interval = 10,
chance = 1,
action = function(pos)
minetest.set_node(pos, {name = "air"})
minetest.remove_node(pos)
end
})
end

View File

@ -1,5 +1,5 @@
-- (c) 2015-2016 rnd
-- Copyright (C) 2022-2023 мтест
-- Copyright (C) 2022-2024 мтест
-- See README.md for license details
local F, S = basic_machines.F, basic_machines.S
@ -444,7 +444,7 @@ minetest.register_abm({
local function generator_near_found(pos, name) -- check to prevent too many generators being placed at one place
if minetest.find_node_near(pos, 15, {"basic_machines:generator"}) then
minetest.set_node(pos, {name = "air"})
minetest.remove_node(pos)
minetest.add_item(pos, "basic_machines:generator")
minetest.chat_send_player(name, S("Generator: Interference from nearby generator detected"))
return true