initial commit

Redstone-Mod for Mineclone5
copy from https://git.minetest.land/MineClone5/MineClone5.git
This commit is contained in:
Henry Behrendt 2021-08-22 18:59:49 +02:00
commit 582545ce2e
249 changed files with 8564 additions and 0 deletions

28
README Normal file
View File

@ -0,0 +1,28 @@
-- |\ /| ____ ____ ____ _____ ____ _____
-- | \ / | | | | | | | |\ | |
-- | \/ | |___ ____ |___ | | | | \ | |____
-- | | | | | | | | | \ | |
-- | | |___ ____| |___ |____ |____| | \| ____|
-- by Jeija and contributors
Credits:
Jeija: main developer
VanessaE: Awesome textures & design, coding
sfan5: coding, textures
temperest: coding, textures
Jordach: Sounds for the noteblock
minerd247: Some textures
suzenako: Piston sounds
...other contributors
This is a mod for minetest-c55.
Copy the minetest-mod-mesecons directory into you game's mod folder
(e.g. games/minetest_game/mods/minetest-mod-mesecons)
You can remove modules of this mod by deleting the mesecons_*
folders in the minetest-mod-mesecons directory.
Mod dependencies: none
Code license: LGPLv3 or later
Media license: CC BY-SA 3.0 <https://creativecommons.org/licenses/by-sa/3.0/>

359
mcl_comparators/init.lua Normal file
View File

@ -0,0 +1,359 @@
local S = minetest.get_translator(minetest.get_current_modname())
-- Functions that get the input/output rules of the comparator
local function comparator_get_output_rules(node)
local rules = {{x = -1, y = 0, z = 0, spread=true}}
for i = 0, node.param2 do
rules = mesecon.rotate_rules_left(rules)
end
return rules
end
local function comparator_get_input_rules(node)
local rules = {
-- we rely on this order in update_self below
{x = 1, y = 0, z = 0}, -- back
{x = 0, y = 0, z = -1}, -- side
{x = 0, y = 0, z = 1}, -- side
}
for i = 0, node.param2 do
rules = mesecon.rotate_rules_left(rules)
end
return rules
end
-- Functions that are called after the delay time
local function comparator_turnon(params)
local rules = comparator_get_output_rules(params.node)
mesecon.receptor_on(params.pos, rules)
end
local function comparator_turnoff(params)
local rules = comparator_get_output_rules(params.node)
mesecon.receptor_off(params.pos, rules)
end
-- Functions that set the correct node type an schedule a turnon/off
local function comparator_activate(pos, node)
local def = minetest.registered_nodes[node.name]
minetest.swap_node(pos, { name = def.comparator_onstate, param2 = node.param2 })
minetest.after(0.1, comparator_turnon , {pos = pos, node = node})
end
local function comparator_deactivate(pos, node)
local def = minetest.registered_nodes[node.name]
minetest.swap_node(pos, { name = def.comparator_offstate, param2 = node.param2 })
minetest.after(0.1, comparator_turnoff, {pos = pos, node = node})
end
-- weather pos has an inventory that contains at least one item
local function container_inventory_nonempty(pos)
local invnode = minetest.get_node(pos)
local invnodedef = minetest.registered_nodes[invnode.name]
-- Ignore stale nodes
if not invnodedef then return false end
-- Only accept containers. When a container is dug, it's inventory
-- seems to stay. and we don't want to accept the inventory of an air
-- block
if not invnodedef.groups.container then return false end
local inv = minetest.get_inventory({type="node", pos=pos})
if not inv then return false end
for listname, _ in pairs(inv:get_lists()) do
if not inv:is_empty(listname) then return true end
end
return false
end
-- weather pos has an constant signal output for the comparator
local function static_signal_output(pos)
local node = minetest.get_node(pos)
local g = minetest.get_item_group(node.name, "comparator_signal")
return g > 0
end
-- whether the comparator should be on according to its inputs
local function comparator_desired_on(pos, node)
local my_input_rules = comparator_get_input_rules(node);
local back_rule = my_input_rules[1]
local state
if back_rule then
local back_pos = vector.add(pos, back_rule)
state = mesecon.is_power_on(back_pos) or container_inventory_nonempty(back_pos) or static_signal_output(back_pos)
end
-- if back input if off, we don't need to check side inputs
if not state then return false end
-- without power levels, side inputs have no influence on output in compare
-- mode
local mode = minetest.registered_nodes[node.name].comparator_mode
if mode == "comp" then return state end
-- subtract mode, subtract max(side_inputs) from back input
local side_state = false
for ri = 2,3 do
if my_input_rules[ri] then
side_state = mesecon.is_power_on(vector.add(pos, my_input_rules[ri]))
end
if side_state then break end
end
-- state is known to be true
return not side_state
end
-- update comparator state, if needed
local function update_self(pos, node)
node = node or minetest.get_node(pos)
local old_state = mesecon.is_receptor_on(node.name)
local new_state = comparator_desired_on(pos, node)
if new_state ~= old_state then
if new_state then
comparator_activate(pos, node)
else
comparator_deactivate(pos, node)
end
end
end
-- compute tile depending on state and mode
local function get_tiles(state, mode)
local top = "mcl_comparators_"..state..".png^"..
"mcl_comparators_"..mode..".png"
local sides = "mcl_comparators_sides_"..state..".png^"..
"mcl_comparators_sides_"..mode..".png"
local ends = "mcl_comparators_ends_"..state..".png^"..
"mcl_comparators_ends_"..mode..".png"
return {
top, "mcl_stairs_stone_slab_top.png",
sides, sides.."^[transformFX",
ends, ends,
}
end
-- Given one mode, get the other mode
local function flipmode(mode)
if mode == "comp" then return "sub"
elseif mode == "sub" then return "comp"
end
end
local function make_rightclick_handler(state, mode)
local newnodename =
"mcl_comparators:comparator_"..state.."_"..flipmode(mode)
return function (pos, node, clicker)
local protname = clicker:get_player_name()
if minetest.is_protected(pos, protname) then
minetest.record_protection_violation(pos, protname)
return
end
minetest.swap_node(pos, {name = newnodename, param2 = node.param2 })
end
end
-- Register the 2 (states) x 2 (modes) comparators
local icon = "mcl_comparators_item.png"
local node_boxes = {
comp = {
{ -8/16, -8/16, -8/16,
8/16, -6/16, 8/16 }, -- the main slab
{ -1/16, -6/16, 6/16,
1/16, -4/16, 4/16 }, -- front torch
{ -4/16, -6/16, -5/16,
-2/16, -1/16, -3/16 }, -- left back torch
{ 2/16, -6/16, -5/16,
4/16, -1/16, -3/16 }, -- right back torch
},
sub = {
{ -8/16, -8/16, -8/16,
8/16, -6/16, 8/16 }, -- the main slab
{ -1/16, -6/16, 6/16,
1/16, -3/16, 4/16 }, -- front torch (active)
{ -4/16, -6/16, -5/16,
-2/16, -1/16, -3/16 }, -- left back torch
{ 2/16, -6/16, -5/16,
4/16, -1/16, -3/16 }, -- right back torch
},
}
local collision_box = {
type = "fixed",
fixed = { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 },
}
local state_strs = {
[ mesecon.state.on ] = "on",
[ mesecon.state.off ] = "off",
}
local groups = {
dig_immediate = 3,
dig_by_water = 1,
destroy_by_lava_flow = 1,
dig_by_piston = 1,
attached_node = 1,
}
local on_rotate
if minetest.get_modpath("screwdriver") then
on_rotate = screwdriver.disallow
end
for _, mode in pairs{"comp", "sub"} do
for _, state in pairs{mesecon.state.on, mesecon.state.off} do
local state_str = state_strs[state]
local nodename =
"mcl_comparators:comparator_"..state_str.."_"..mode
-- Help
local longdesc, usagehelp, use_help
if state_str == "off" and mode == "comp" then
longdesc = S("Redstone comparators are multi-purpose redstone components.").."\n"..
S("They can transmit a redstone signal, detect whether a block contains any items and compare multiple signals.")
usagehelp = S("A redstone comparator has 1 main input, 2 side inputs and 1 output. The output is in arrow direction, the main input is in the opposite direction. The other 2 sides are the side inputs.").."\n"..
S("The main input can powered in 2 ways: First, it can be powered directly by redstone power like any other component. Second, it is powered if, and only if a container (like a chest) is placed in front of it and the container contains at least one item.").."\n"..
S("The side inputs are only powered by normal redstone power. The redstone comparator can operate in two modes: Transmission mode and subtraction mode. It starts in transmission mode and the mode can be changed by using the block.").."\n\n"..
S("Transmission mode:\nThe front torch is unlit and lowered. The output is powered if, and only if the main input is powered. The two side inputs are ignored.").."\n"..
S("Subtraction mode:\nThe front torch is lit. The output is powered if, and only if the main input is powered and none of the side inputs is powered.")
else
use_help = false
end
local nodedef = {
description = S("Redstone Comparator"),
inventory_image = icon,
wield_image = icon,
_doc_items_create_entry = use_help,
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usagehelp,
drawtype = "nodebox",
tiles = get_tiles(state_str, mode),
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false,
--wield_image = "mcl_comparators_off.png",
walkable = true,
selection_box = collision_box,
collision_box = collision_box,
node_box = {
type = "fixed",
fixed = node_boxes[mode],
},
groups = groups,
paramtype = "light",
paramtype2 = "facedir",
sunlight_propagates = false,
is_ground_content = false,
drop = "mcl_comparators:comparator_off_comp",
on_construct = update_self,
on_rightclick =
make_rightclick_handler(state_str, mode),
comparator_mode = mode,
comparator_onstate = "mcl_comparators:comparator_on_"..mode,
comparator_offstate = "mcl_comparators:comparator_off_"..mode,
sounds = mcl_sounds.node_sound_stone_defaults(),
mesecons = {
receptor = {
state = state,
rules = comparator_get_output_rules,
},
effector = {
rules = comparator_get_input_rules,
action_change = update_self,
}
},
on_rotate = on_rotate,
}
if mode == "comp" and state == mesecon.state.off then
-- This is the prototype
nodedef._doc_items_create_entry = true
else
nodedef.groups = table.copy(nodedef.groups)
nodedef.groups.not_in_creative_inventory = 1
--local extra_desc = {}
if mode == "sub" or state == mesecon.state.on then
nodedef.inventory_image = nil
end
local desc = nodedef.description
if mode ~= "sub" and state == mesecon.state.on then
desc = S("Redstone Comparator (Powered)")
elseif mode == "sub" and state ~= mesecon.state.on then
desc = S("Redstone Comparator (Subtract)")
elseif mode == "sub" and state == mesecon.state.on then
desc = S("Redstone Comparator (Subtract, Powered)")
end
nodedef.description = desc
end
minetest.register_node(nodename, nodedef)
mcl_wip.register_wip_item(nodename)
end
end
-- Register recipies
local rstorch = "mesecons_torch:mesecon_torch_on"
local quartz = "mcl_nether:quartz"
local stone = "mcl_core:stone"
minetest.register_craft({
output = "mcl_comparators:comparator_off_comp",
recipe = {
{ "", rstorch, "" },
{ rstorch, quartz, rstorch },
{ stone, stone, stone },
}
})
-- Register active block handlers
minetest.register_abm({
label = "Comparator signal input check (comparator is off)",
nodenames = {
"mcl_comparators:comparator_off_comp",
"mcl_comparators:comparator_off_sub",
},
neighbors = {"group:container", "group:comparator_signal"},
interval = 1,
chance = 1,
action = update_self,
})
minetest.register_abm({
label = "Comparator signal input check (comparator is on)",
nodenames = {
"mcl_comparators:comparator_on_comp",
"mcl_comparators:comparator_on_sub",
},
-- needs to run regardless of neighbors to make sure we detect when a
-- container is dug
interval = 1,
chance = 1,
action = update_self,
})
-- Add entry aliases for the Help
if minetest.get_modpath("doc") then
doc.add_entry_alias("nodes", "mcl_comparators:comparator_off_comp",
"nodes", "mcl_comparators:comparator_off_sub")
doc.add_entry_alias("nodes", "mcl_comparators:comparator_off_comp",
"nodes", "mcl_comparators:comparator_on_comp")
doc.add_entry_alias("nodes", "mcl_comparators:comparator_off_comp",
"nodes", "mcl_comparators:comparator_on_sub")
end

View File

@ -0,0 +1,12 @@
# textdomain: mcl_comparators
Redstone comparators are multi-purpose redstone components.=Redstonekomparatoren sind Redstonekomponenten mit vielen Verwendungszwecken.
They can transmit a redstone signal, detect whether a block contains any items and compare multiple signals.=Sie können ein Redstonesignal übertragen, erkennen, ob ein Block Gegenstände enthält und mehrere Signale vergleichen.
A redstone comparator has 1 main input, 2 side inputs and 1 output. The output is in arrow direction, the main input is in the opposite direction. The other 2 sides are the side inputs.=Ein Redstonekomparator hat 1 Haupteingang, 2 Seiteneingänge und 1 Ausgang. Der Ausgang ist in Pfeilrichtung, der Haupteingang ist in der gegenüberliegenden Richtung. Die anderen 2 Seiten sind die Seiteneingänge.
The main input can powered in 2 ways: First, it can be powered directly by redstone power like any other component. Second, it is powered if, and only if a container (like a chest) is placed in front of it and the container contains at least one item.=Der Haupteingang kann auf 2 Weisen versorgt werden: Erstens, kann er direkt von Redstoneenergie wie bei jeder anderen Komponente versorgt werden. Zweitens wird er versorgt, wenn, und nur wenn ein Behälter (wie eine Truhe) vor dem Komporator platziert wurde und der Behälter mindestens einen Gegenstand enthält.
The side inputs are only powered by normal redstone power. The redstone comparator can operate in two modes: Transmission mode and subtraction mode. It starts in transmission mode and the mode can be changed by using the block.=Die Seiteneingänge akzeptieren nur normale Redstoneenergie. Der Redstonekomparator kann in zwei Modi agieren: Übertragungsmodus und Subtraktionsmodus. Er fängt im Übertragungsmodus an. Der Modus wird beim Benutzen des Blocks geändert.
Transmission mode:@nThe front torch is unlit and lowered. The output is powered if, and only if the main input is powered. The two side inputs are ignored.=Übertragungsmodus:@nDie vordere Fackel ist eingefahren und leuchtet nicht auf. Die Ausgabe gibt ein Signal, wenn, nur nur wenn der Haupteingang bestromt wird. Die zwei Seiteneingänge werden ignoriert.
Subtraction mode:@nThe front torch is lit. The output is powered if, and only if the main input is powered and none of the side inputs is powered.=Subtraktionsmodus:@nDie vordere Fackel leuchtet auf. Die Ausgabe gibt ein Signal wenn, nur nur wenn der Haupteingang versorgt wird und keiner der Seiteneingänge bestromt ist.
Redstone Comparator=Redstonekomparator
Redstone Comparator (Subtract)=Redstonekomparator (subtrahieren)
Redstone Comparator (Powered)=Redstonekomparator (bestromt)
Redstone Comparator (Subtract, Powered)=Redstonekomparator (subtrahieren, bestromt)

View File

@ -0,0 +1,12 @@
# textdomain: mcl_comparators
Redstone comparators are multi-purpose redstone components.=Los comparadores de Redstone son componentes multipropósito de redstone.
They can transmit a redstone signal, detect whether a block contains any items and compare multiple signals.=Pueden transmitir una señal de redstone, detectar si un bloque contiene algún elemento y comparar múltiples señales.
A redstone comparator has 1 main input, 2 side inputs and 1 output. The output is in arrow direction, the main input is in the opposite direction. The other 2 sides are the side inputs.=Un comparador redstone tiene 1 entrada principal, 2 entradas laterales y 1 salida. La salida está en la dirección de la flecha, la entrada principal está en la dirección opuesta. Los otros 2 lados son las entradas laterales.
The main input can powered in 2 ways: First, it can be powered directly by redstone power like any other component. Second, it is powered if, and only if a container (like a chest) is placed in front of it and the container contains at least one item.=La entrada principal puede alimentarse de 2 maneras: en primer lugar, puede alimentarse directamente mediante redstone como cualquier otro componente. En segundo lugar, se alimenta si, y solo si se coloca un contenedor (como un cofre) frente a él y el contenedor contiene al menos un elemento.
The side inputs are only powered by normal redstone power. The redstone comparator can operate in two modes: Transmission mode and subtraction mode. It starts in transmission mode and the mode can be changed by using the block.=Las entradas laterales solo están alimentadas por la alimentación normal de redstone. El comparador de redstone puede funcionar en dos modos: modo de transmisión y modo de resta. Comienza en modo de transmisión y el modo se puede cambiar usando el bloque.
Transmission mode:@nThe front torch is unlit and lowered. The output is powered if, and only if the main input is powered. The two side inputs are ignored.=Modo de transmisión: @nLa antorcha delantera está apagada y baja. La salida se alimenta solo si se alimenta la entrada principal. Las dos entradas laterales se ignoran.
Subtraction mode:@nThe front torch is lit. The output is powered if, and only if the main input is powered and none of the side inputs is powered.=Modo de resta: @nLa antorcha delantera está encendida. La salida se alimenta si, y solo si la entrada principal está alimentada y ninguna de las entradas laterales está alimentada.
Redstone Comparator=Comparador de redstone
Redstone Comparator (Subtract)=Comparador de redstone (Negativo)
Redstone Comparator (Powered)=Comparador de redstone (Motorizado)
Redstone Comparator (Subtract, Powered)=Redstonekomparator (Negativo, Motorizado)

View File

@ -0,0 +1,12 @@
# textdomain: mcl_comparators
Redstone comparators are multi-purpose redstone components.=Les comparateurs Redstone sont des composants Redstone polyvalents.
They can transmit a redstone signal, detect whether a block contains any items and compare multiple signals.=Ils peuvent transmettre un signal redstone, détecter si un bloc contient des éléments et comparer plusieurs signaux.
A redstone comparator has 1 main input, 2 side inputs and 1 output. The output is in arrow direction, the main input is in the opposite direction. The other 2 sides are the side inputs.=Un comparateur redstone a 1 entrée principale, 2 entrées latérales et 1 sortie. La sortie est dans le sens de la flèche, l'entrée principale est dans le sens opposé. Les 2 autres côtés sont les entrées latérales.
The main input can powered in 2 ways: First, it can be powered directly by redstone power like any other component. Second, it is powered if, and only if a container (like a chest) is placed in front of it and the container contains at least one item.=L'entrée principale peut être alimentée de 2 manières: Premièrement, elle peut être alimentée directement par une alimentation redstone comme n'importe quel autre composant. Deuxièmement, il est alimenté si et seulement si un conteneur (comme un coffre) est placé devant lui et que le conteneur contient au moins un article.
The side inputs are only powered by normal redstone power. The redstone comparator can operate in two modes: Transmission mode and subtraction mode. It starts in transmission mode and the mode can be changed by using the block.=Les entrées latérales sont uniquement alimentées par une alimentation Redstone normale. Le comparateur redstone peut fonctionner en deux modes: le mode de transmission et le mode de soustraction. Il démarre en mode transmission et le mode peut être changé en utilisant le bloc.
Transmission mode:@nThe front torch is unlit and lowered. The output is powered if, and only if the main input is powered. The two side inputs are ignored.=Mode de transmission: @nLa torche avant est éteinte et abaissée. La sortie est alimentée si et seulement si l'entrée principale est alimentée. Les deux entrées latérales sont ignorées.
Subtraction mode:@nThe front torch is lit. The output is powered if, and only if the main input is powered and none of the side inputs is powered.=Mode de soustraction: @nLa torche avant est allumée. La sortie est alimentée si et seulement si l'entrée principale est alimentée et qu'aucune des entrées latérales n'est alimentée.
Redstone Comparator=Comparateur Redstone
Redstone Comparator (Subtract)=Comparateur Redstone (Soustraction)
Redstone Comparator (Powered)=Comparateur Redstone (Alimenté)
Redstone Comparator (Subtract, Powered)=Comparateur Redstone (Soustraction, Alimenté)

View File

@ -0,0 +1,13 @@
# textdomain: mcl_comparators
Redstone comparators are multi-purpose redstone components.=Komparatory są wielofunkcyjnymi mechanizmami czerwienitowymi.
They can transmit a redstone signal, detect whether a block contains any items and compare multiple signals.=Mogą one przesyłać sygnał czerwienitowy, wykrywać czy blok zawiera przedmioty i porównywać wiele sygnałów.
A redstone comparator has 1 main input, 2 side inputs and 1 output. The output is in arrow direction, the main input is in the opposite direction. The other 2 sides are the side inputs.=Komparator ma jedno główne wejście, 2 wejścia poboczne i jedno wyjście. Wyjście jest wskazywane przez strzałkę, wejście jest na przeciwko. Pozostałe dwa wejścia są poboczne.
The main input can powered in 2 ways: First, it can be powered directly by redstone power like any other component. Second, it is powered if, and only if a container (like a chest) is placed in front of it and the container contains at least one item.=Główny wejście można zasilać na 2 sposoby: Może być zasilany bezpośrednio energią czerwienitową jak każdy inny komponent, lub gdy przed nim postawiony jest kontener zawierający przynajmniej jeden przedmiot.
The side inputs are only powered by normal redstone power. The redstone comparator can operate in two modes: Transmission mode and subtraction mode. It starts in transmission mode and the mode can be changed by using the block.=Wejścia poboczne są aktywowane przez zwykłą energię czerwienitową. Komparator może działać w dwóch trybach: tryb przekazywania oraz tryb odejmowania. Początkowo jest w trybie przekazywania, a tryb może być zmienione przez użycie go.
Transmission mode:@nThe front torch is unlit and lowered. The output is powered if, and only if the main input is powered. The two side inputs are ignored.=Tryb przekazywania:@nPrzednia pochodnia jest niezaświecona i obniżona. Wyjście jest zasilane wtedy i tylko wtedy gdy wejście główne jest zasilane. Wejścia boczne są ignorowane.
Subtraction mode:@nThe front torch is lit. The output is powered if, and only if the main input is powered and none of the side inputs is powered.=Tryb odejmowania:@nPrzednia pochodnia jest zaświecona. Wyjście jest zasilane wtedy i tylko gdy zasilane jest główne wejście, a wejścia boczne nie są.
Redstone Comparator=Komparator
Redstone Comparator (Subtract)=Komparator (odejmowanie)
Redstone Comparator (Powered)=Komparator (zasilony)
Redstone Comparator (Subtract, Powered)=Komparator (odejmowanie, zasilony)

View File

@ -0,0 +1,12 @@
# textdomain: mcl_comparators
Redstone comparators are multi-purpose redstone components.=Компаратор это многофункциональный элемент редстоуна.
They can transmit a redstone signal, detect whether a block contains any items and compare multiple signals.=Он может передавать сигнал редстоуна, определять, содержит ли блок какой-либо предмет, и сравнивать сигналы.
A redstone comparator has 1 main input, 2 side inputs and 1 output. The output is in arrow direction, the main input is in the opposite direction. The other 2 sides are the side inputs.=Компаратор имеет 1 основной вход, 2 боковых входа и 1 выход. Выход расположен по направлению стрелки, основной вход в противоположном направлении. Оставшиеся 2 стороны это боковые входы.
The main input can powered in 2 ways: First, it can be powered directly by redstone power like any other component. Second, it is powered if, and only if a container (like a chest) is placed in front of it and the container contains at least one item.=Основной вход можно подключать 2 способами: 1) напрямую к энергии редстоуна, как и любой другой компонент; 2) перед компаратором можно установить контейнер (например, сундук), тогда сигнал будет поступать, если в нём содержится хотя бы один предмет.
The side inputs are only powered by normal redstone power. The redstone comparator can operate in two modes: Transmission mode and subtraction mode. It starts in transmission mode and the mode can be changed by using the block.=К боковым входам можно подводить только обычную энергию редстоуна. Компаратор может работать в двух режимах: ПЕРЕДАЧА и ВЫЧИТАНИЕ. Он изначально находится в режиме передачи; режим меняется при [Использовании] данного блока.
Transmission mode:@nThe front torch is unlit and lowered. The output is powered if, and only if the main input is powered. The two side inputs are ignored.=Режим ПЕРЕДАЧИ:@nПередний индикатор погашен. На выходе появляется энергия редстоуна, только если она подаётся на основной вход. Состояние боковых входов при этом игнорируются.
Subtraction mode:@nThe front torch is lit. The output is powered if, and only if the main input is powered and none of the side inputs is powered.=Режим ВЫЧИТАНИЯ:@nПередний индикатор светится. На выходе есть сигнал только в том случае, если сигнал есть на основной входе, но при этом его нет ни на одном из боковых входов.
Redstone Comparator=Компаратор
Redstone Comparator (Subtract)=Компаратор (ВЫЧИТАНИЕ)
Redstone Comparator (Powered)=Компаратор (ВКЛЮЧЁН)
Redstone Comparator (Subtract, Powered)=Компаратор (ВЫЧИТАНИЕ, ВКЛЮЧЁН)

View File

@ -0,0 +1,12 @@
# textdomain: mcl_comparators
Redstone comparators are multi-purpose redstone components.=
They can transmit a redstone signal, detect whether a block contains any items and compare multiple signals.=
A redstone comparator has 1 main input, 2 side inputs and 1 output. The output is in arrow direction, the main input is in the opposite direction. The other 2 sides are the side inputs.=
The main input can powered in 2 ways: First, it can be powered directly by redstone power like any other component. Second, it is powered if, and only if a container (like a chest) is placed in front of it and the container contains at least one item.=
The side inputs are only powered by normal redstone power. The redstone comparator can operate in two modes: Transmission mode and subtraction mode. It starts in transmission mode and the mode can be changed by using the block.=
Transmission mode:@nThe front torch is unlit and lowered. The output is powered if, and only if the main input is powered. The two side inputs are ignored.=
Subtraction mode:@nThe front torch is lit. The output is powered if, and only if the main input is powered and none of the side inputs is powered.=
Redstone Comparator=
Redstone Comparator (Subtract)=
Redstone Comparator (Powered)=
Redstone Comparator (Subtract, Powered)=

3
mcl_comparators/mod.conf Normal file
View File

@ -0,0 +1,3 @@
name = mcl_comparators
depends = mcl_wip, mesecons, mcl_sounds
optional_depends = doc, screwdriver

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 562 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 B

27
mcl_dispensers/API.md Normal file
View File

@ -0,0 +1,27 @@
# API documentation for dispensers
The dispensers API allows you to add custom code which is called when a
particular item is dispensed.
Just add the `_on_dispense` function to the item definition.
By default, items are just thrown out as item entities.
## Additional fields for item definitions
### `_on_dispense(stack, pos, droppos, dropnode, dropdir)`
This is a function which is called when an item is dispensed by the dispenser.
These are the parameters:
* stack: Itemstack which is dispense. This is always exactly 1 item
* pos: Position of dispenser
* droppos: Position to which to dispense item
* dropnode: Node of droppos
* dropdir: Drop direction
By default (return value: `nil`), the itemstack is consumed by the dispenser afterwards.
Optionally, you can explicitly set the return value to a custom leftover itemstack.
### `_dispense_into_walkable`
By default, items will only be dispensed into non-walkable nodes.
But if this value is set If `true`, the item can be dispensed into walkable nodes.

319
mcl_dispensers/init.lua Normal file
View File

@ -0,0 +1,319 @@
--[[ This mod registers 3 nodes:
- One node for the horizontal-facing dispensers (mcl_dispensers:dispenser)
- One node for the upwards-facing dispensers (mcl_dispenser:dispenser_up)
- One node for the downwards-facing dispensers (mcl_dispenser:dispenser_down)
3 node definitions are needed because of the way the textures are defined.
All node definitions share a lot of code, so this is the reason why there
are so many weird tables below.
]]
local S = minetest.get_translator(minetest.get_current_modname())
-- For after_place_node
local function setup_dispenser(pos)
-- Set formspec and inventory
local form = "size[9,8.75]"..
"label[0,4.0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]"..
"list[current_player;main;0,4.5;9,3;9]"..
mcl_formspec.get_itemslot_bg(0,4.5,9,3)..
"list[current_player;main;0,7.74;9,1;]"..
mcl_formspec.get_itemslot_bg(0,7.74,9,1)..
"label[3,0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Dispenser"))).."]"..
"list[context;main;3,0.5;3,3;]"..
mcl_formspec.get_itemslot_bg(3,0.5,3,3)..
"listring[context;main]"..
"listring[current_player;main]"
local meta = minetest.get_meta(pos)
meta:set_string("formspec", form)
local inv = meta:get_inventory()
inv:set_size("main", 9)
end
local function orientate_dispenser(pos, placer)
-- Not placed by player
if not placer then return end
-- Pitch in degrees
local pitch = placer:get_look_vertical() * (180 / math.pi)
local node = minetest.get_node(pos)
if pitch > 55 then
minetest.swap_node(pos, {name="mcl_dispensers:dispenser_up", param2 = node.param2})
elseif pitch < -55 then
minetest.swap_node(pos, {name="mcl_dispensers:dispenser_down", param2 = node.param2})
end
end
local on_rotate
if minetest.get_modpath("screwdriver") then
on_rotate = screwdriver.rotate_simple
end
-- Shared core definition table
local dispenserdef = {
is_ground_content = false,
sounds = mcl_sounds.node_sound_stone_defaults(),
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
local name = player:get_player_name()
if minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
return 0
else
return count
end
end,
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
local name = player:get_player_name()
if minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
return 0
else
return stack:get_count()
end
end,
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
local name = player:get_player_name()
if minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
return 0
else
return stack:get_count()
end
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
local meta = minetest.get_meta(pos)
local meta2 = meta
meta:from_table(oldmetadata)
local inv = meta:get_inventory()
for i=1, inv:get_size("main") do
local stack = inv:get_stack("main", i)
if not stack:is_empty() then
local p = {x=pos.x+math.random(0, 10)/10-0.5, y=pos.y, z=pos.z+math.random(0, 10)/10-0.5}
minetest.add_item(p, stack)
end
end
meta:from_table(meta2:to_table())
end,
_mcl_blast_resistance = 3.5,
_mcl_hardness = 3.5,
mesecons = {
effector = {
-- Dispense random item when triggered
action_on = function(pos, node)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local droppos, dropdir
if node.name == "mcl_dispensers:dispenser" then
dropdir = vector.multiply(minetest.facedir_to_dir(node.param2), -1)
droppos = vector.add(pos, dropdir)
elseif node.name == "mcl_dispensers:dispenser_up" then
dropdir = {x=0, y=1, z=0}
droppos = {x=pos.x, y=pos.y+1, z=pos.z}
elseif node.name == "mcl_dispensers:dispenser_down" then
dropdir = {x=0, y=-1, z=0}
droppos = {x=pos.x, y=pos.y-1, z=pos.z}
end
local dropnode = minetest.get_node(droppos)
local dropnodedef = minetest.registered_nodes[dropnode.name]
local stacks = {}
for i=1,inv:get_size("main") do
local stack = inv:get_stack("main", i)
if not stack:is_empty() then
table.insert(stacks, {stack = stack, stackpos = i})
end
end
if #stacks >= 1 then
local r = math.random(1, #stacks)
local stack = stacks[r].stack
local dropitem = ItemStack(stack)
dropitem:set_count(1)
local stack_id = stacks[r].stackpos
local stackdef = stack:get_definition()
if not stackdef then
return
end
local iname = stack:get_name()
local igroups = stackdef.groups
--[===[ Dispense item ]===]
-- Hardcoded dispensions --
-- Armor, mob heads and pumpkins
if igroups.armor then
local droppos_below = {x = droppos.x, y = droppos.y - 1, z = droppos.z}
for _, objs in ipairs({minetest.get_objects_inside_radius(droppos, 1), minetest.get_objects_inside_radius(droppos_below, 1)}) do
for _, obj in ipairs(objs) do
stack = mcl_armor.equip(stack, obj)
if stack:is_empty() then
break
end
end
if stack:is_empty() then
break
end
end
-- Place head or pumpkin as node, if equipping it as armor has failed
if not stack:is_empty() then
if igroups.head or iname == "mcl_farming:pumpkin_face" then
if dropnodedef.buildable_to then
minetest.set_node(droppos, {name = iname, param2 = node.param2})
stack:take_item()
end
end
end
inv:set_stack("main", stack_id, stack)
-- Spawn Egg
elseif igroups.spawn_egg then
-- Spawn mob
if not dropnodedef.walkable then
--pointed_thing = { above = droppos, under = { x=droppos.x, y=droppos.y-1, z=droppos.z } }
minetest.add_entity(droppos, stack:get_name())
stack:take_item()
inv:set_stack("main", stack_id, stack)
end
-- Generalized dispension
elseif (not dropnodedef.walkable or stackdef._dispense_into_walkable) then
--[[ _on_dispense(stack, pos, droppos, dropnode, dropdir)
* stack: Itemstack which is dispense
* pos: Position of dispenser
* droppos: Position to which to dispense item
* dropnode: Node of droppos
* dropdir: Drop direction
_dispense_into_walkable: If true, can dispense into walkable nodes
]]
if stackdef._on_dispense then
-- Item-specific dispension (if defined)
local od_ret = stackdef._on_dispense(dropitem, pos, droppos, dropnode, dropdir)
if od_ret then
local newcount = stack:get_count() - 1
stack:set_count(newcount)
inv:set_stack("main", stack_id, stack)
if newcount == 0 then
inv:set_stack("main", stack_id, od_ret)
elseif inv:room_for_item("main", od_ret) then
inv:add_item("main", od_ret)
else
minetest.add_item(droppos, dropitem)
end
else
stack:take_item()
inv:set_stack("main", stack_id, stack)
end
else
-- Drop item otherwise
minetest.add_item(droppos, dropitem)
stack:take_item()
inv:set_stack("main", stack_id, stack)
end
end
end
end,
rules = mesecon.rules.alldirs,
},
},
on_rotate = on_rotate,
}
-- Horizontal dispenser
local horizontal_def = table.copy(dispenserdef)
horizontal_def.description = S("Dispenser")
horizontal_def._tt_help = S("9 inventory slots").."\n"..S("Launches item when powered by redstone power")
horizontal_def._doc_items_longdesc = S("A dispenser is a block which acts as a redstone component which, when powered with redstone power, dispenses an item. It has a container with 9 inventory slots.")
horizontal_def._doc_items_usagehelp = S("Place the dispenser in one of 6 possible directions. The “hole” is where items will fly out of the dispenser. Use the dispenser to access its inventory. Insert the items you wish to dispense. Supply the dispenser with redstone energy once to dispense a random item.").."\n\n"..
S("The dispenser will do different things, depending on the dispensed item:").."\n\n"..
S("• Arrows: Are launched").."\n"..
S("• Eggs and snowballs: Are thrown").."\n"..
S("• Fire charges: Are fired in a straight line").."\n"..
S("• Armor: Will be equipped to players and armor stands").."\n"..
S("• Boats: Are placed on water or are dropped").."\n"..
S("• Minecart: Are placed on rails or are dropped").."\n"..
S("• Bone meal: Is applied on the block it is facing").."\n"..
S("• Empty buckets: Are used to collect a liquid source").."\n"..
S("• Filled buckets: Are used to place a liquid source").."\n"..
S("• Heads, pumpkins: Equipped to players and armor stands, or placed as a block").."\n"..
S("• Shulker boxes: Are placed as a block").."\n"..
S("• TNT: Is placed and ignited").."\n"..
S("• Flint and steel: Is used to ignite a fire in air and to ignite TNT").."\n"..
S("• Spawn eggs: Will summon the mob they contain").."\n"..
S("• Other items: Are simply dropped")
function horizontal_def.after_place_node(pos, placer, itemstack, pointed_thing)
setup_dispenser(pos)
orientate_dispenser(pos, placer)
end
horizontal_def.tiles = {
"default_furnace_top.png", "default_furnace_bottom.png",
"default_furnace_side.png", "default_furnace_side.png",
"default_furnace_side.png", "mcl_dispensers_dispenser_front_horizontal.png"
}
horizontal_def.paramtype2 = "facedir"
horizontal_def.groups = {pickaxey=1, container=2, material_stone=1}
minetest.register_node("mcl_dispensers:dispenser", horizontal_def)
-- Down dispenser
local down_def = table.copy(dispenserdef)
down_def.description = S("Downwards-Facing Dispenser")
down_def.after_place_node = setup_dispenser
down_def.tiles = {
"default_furnace_top.png", "mcl_dispensers_dispenser_front_vertical.png",
"default_furnace_side.png", "default_furnace_side.png",
"default_furnace_side.png", "default_furnace_side.png"
}
down_def.groups = {pickaxey=1, container=2,not_in_creative_inventory=1, material_stone=1}
down_def._doc_items_create_entry = false
down_def.drop = "mcl_dispensers:dispenser"
minetest.register_node("mcl_dispensers:dispenser_down", down_def)
-- Up dispenser
-- The up dispenser is almost identical to the down dispenser , it only differs in textures
local up_def = table.copy(down_def)
up_def.description = S("Upwards-Facing Dispenser")
up_def.tiles = {
"mcl_dispensers_dispenser_front_vertical.png", "default_furnace_bottom.png",
"default_furnace_side.png", "default_furnace_side.png",
"default_furnace_side.png", "default_furnace_side.png"
}
minetest.register_node("mcl_dispensers:dispenser_up", up_def)
minetest.register_craft({
output = "mcl_dispensers:dispenser",
recipe = {
{"mcl_core:cobble", "mcl_core:cobble", "mcl_core:cobble",},
{"mcl_core:cobble", "mcl_bows:bow", "mcl_core:cobble",},
{"mcl_core:cobble", "mesecons:redstone", "mcl_core:cobble",},
}
})
-- Add entry aliases for the Help
if minetest.get_modpath("doc") then
doc.add_entry_alias("nodes", "mcl_dispensers:dispenser", "nodes", "mcl_dispensers:dispenser_down")
doc.add_entry_alias("nodes", "mcl_dispensers:dispenser", "nodes", "mcl_dispensers:dispenser_up")
end
-- Legacy
minetest.register_lbm({
label = "Update dispenser formspecs (0.60.0)",
name = "mcl_dispensers:update_formspecs_0_60_0",
nodenames = { "mcl_dispensers:dispenser", "mcl_dispensers:dispenser_down", "mcl_dispensers:dispenser_up" },
action = function(pos, node)
setup_dispenser(pos)
minetest.log("action", "[mcl_dispenser] Node formspec updated at "..minetest.pos_to_string(pos))
end,
})

View File

@ -0,0 +1,25 @@
# textdomain: mcl_dispensers
Dispenser=Werfer
A dispenser is a block which acts as a redstone component which, when powered with redstone power, dispenses an item. It has a container with 9 inventory slots.=Ein Werfer ist ein Block, der als eine Redstonekomponente fungiert, die, wenn sie mit Redstoneenergie versorgt ist, einen Gegenstand auswirft. Er hat einen Behälter mit 9 Inventarplätzen.
Place the dispenser in one of 6 possible directions. The “hole” is where items will fly out of the dispenser. Use the dispenser to access its inventory. Insert the items you wish to dispense. Supply the dispenser with redstone energy once to dispense a random item.=Platzieren Sie den Werfer in einer von 6 möglichen Richtungen. Das „Loch“ ist die Stelle, aus der Dinge aus dem Werfer fliegen. Benutzen Sie den Werfer, um auf das Inventar zuzugreifen.
The dispenser will do different things, depending on the dispensed item:=Der Werfer wird, abhängig vom geworfenem Gegenstand, unterschiedliche Dinge tun:
• Arrows: Are launched=• Pfeile: Werden gefeuert
• Eggs and snowballs: Are thrown=• Eier und Schneebälle: Werden geworfen
• Fire charges: Are fired in a straight line=• Feuerkugeln: Werden schnurgerade abgefeuert
• Armor: Will be equipped to players and armor stands=• Rüstung: Spieler und Rüstungsständer werden ausgerüstet
• Boats: Are placed on water or are dropped=• Boote: Werden auf Wasser platziert oder abgeworfen
• Minecart: Are placed on rails or are dropped=• Loren: Werden auf Schienen platziert oder abgeworfen
• Bone meal: Is applied on the block it is facing=• Knochenmehl: Wird auf den Block, auf den er zeigt, angewandt
• Empty buckets: Are used to collect a liquid source=• Leere Eimer: Sammeln Flüssigkeitsquelle auf
• Filled buckets: Are used to place a liquid source=• Volle Eimer: Platzieren eine Flüssigkeitsquelle
• Heads, pumpkins: Equipped to players and armor stands, or placed as a block=• Köpfe, Kürbisse: Spieler und Rüstungsständer werden ausgerüstet, alternativ werden diese Gegenstände als Block platziert
• Shulker boxes: Are placed as a block=• Schulkerkisten: Werden als Block platziert
• TNT: Is placed and ignited=• TNT: Wird platziert und angezündet
• Flint and steel: Is used to ignite a fire in air and to ignite TNT=• Feuerzeuge: Endzündet ein Feuer in der Luft und zündet TNT an
• Spawn eggs: Will summon the mob they contain=• Spawn-Eier: Beschwören einen Mob
• Other items: Are simply dropped=• Andere Gegenstände: Werden fallen gelassen
Downwards-Facing Dispenser=Nach unten zeigender Werfer
Upwards-Facing Dispenser=Nach oben zeigender Werfer
Inventory=Inventar
9 inventory slots=9 Inventarplätze
Launches item when powered by redstone power=Wirft Gegenstand aus, wenn mit Redstoneenergie versorgt

View File

@ -0,0 +1,22 @@
# textdomain: mcl_dispensers
Dispenser=Dispensador
A dispenser is a block which acts as a redstone component which, when powered with redstone power, dispenses an item. It has a container with 9 inventory slots.=Un dispensador es un bloque que actúa como un componente de redstone que, cuando se alimenta con energía de redstone, dispensa un artículo. Tiene un contenedor con 9 ranuras de inventario.
Place the dispenser in one of 6 possible directions. The “hole” is where items will fly out of the dispenser. Use the dispenser to access its inventory. Insert the items you wish to dispense. Supply the dispenser with redstone energy once to dispense a random item.=Coloque el dispensador en una de las 6 direcciones posibles. El "agujero" es donde los artículos saldrán volando del dispensador. Use el dispensador para acceder a su inventario. Inserte los artículos que desea dispensar. Proporcione al dispensador energía de redstone una vez para dispensar un elemento aleatorio:
• Arrows: Are launched=• Flechas: Se lanzan
• Eggs and snowballs: Are thrown=• Huevos y bolas de nieve: Son lanzados
• Fire charges: Are fired in a straight line=• Cargas de fuego: Se disparan en línea recta
• Armor: Will be equipped to players and armor stands=• Armadura: Estará equipada para jugadores y armaduras
• Boats: Are placed on water or are dropped=• Barcas: Se colocan en el agua o se dejan caer
• Minecart: Are placed on rails or are dropped=• Carro de minas: Se colocan sobre rieles o se dejan caer =
• Bone meal: Is applied on the block it is facing=• Harina de hueso: Se aplica en el bloque que está enfrentando
• Empty buckets: Are used to collect a liquid source=• Cubos vacíos: Se utilizan para recolectar una fuente líquida
• Filled buckets: Are used to place a liquid source=• Cubos llenos: Se utilizan para colocar una fuente de líquido
• Heads, pumpkins: Equipped to players and armor stands, or placed as a block=• Cabezas, calabazas: Equipadas para jugadores y armaduras, o colocadas como un bloque
• Shulker boxes: Are placed as a block=• Cajas de Shulker: Se colocan como un bloque
• TNT: Is placed and ignited=• TNT: Se coloca y se enciende
• Flint and steel: Is used to ignite a fire in air and to ignite TNT=• Mechero: Se usa para encender un fuego en el aire y para encender TNT
• Spawn eggs: Will summon the mob they contain=• Huevos de desove: Convocarán al animal que contienen
• Other items: Are simply dropped=• Otros artículos: Simplemente se dejan caer
Downwards-Facing Dispenser=Dispensador orientado hacia abajo
Upwards-Facing Dispenser=Dispensador orientado hacia arriba
Inventory=Inventario

View File

@ -0,0 +1,25 @@
# textdomain: mcl_dispensers
Dispenser=Dispenser
A dispenser is a block which acts as a redstone component which, when powered with redstone power, dispenses an item. It has a container with 9 inventory slots.=Un distributeur est un bloc qui agit comme un composant redstone qui, lorsqu'il est alimenté avec une puissance redstone, distribue un article. Il a un conteneur avec 9 emplacements d'inventaire.
Place the dispenser in one of 6 possible directions. The “hole” is where items will fly out of the dispenser. Use the dispenser to access its inventory. Insert the items you wish to dispense. Supply the dispenser with redstone energy once to dispense a random item.=Placez le distributeur dans l'une des 6 directions possibles. Le "trou" est l'endroit où les articles sortiront du distributeur. Utilisez le distributeur pour accéder à son inventaire. Insérez les articles que vous souhaitez distribuer. Fournissez au distributeur de l'énergie de redstone une fois pour distribuer un objet aléatoire.
The dispenser will do different things, depending on the dispensed item:=Le distributeur fera différentes choses, selon l'article distribué:
• Arrows: Are launched=• Flèches: Sont lancées
• Eggs and snowballs: Are thrown=• Oeufs et boules de neige: Sont jetés
• Fire charges: Are fired in a straight line=• Feu d'artifice: Sont tirés en ligne droite
• Armor: Will be equipped to players and armor stands=• Armure: Sera équipée pour les joueurs et les porte-armures
• Boats: Are placed on water or are dropped=• Bateaux: Sont placés sur l'eau ou sont lâchés
• Minecart: Are placed on rails or are dropped=• Minecart: Sont placés sur des rails ou sont lâchés
• Bone meal: Is applied on the block it is facing=• Farine d'os: Est appliquée sur le bloc auquel elle fait face
• Empty buckets: Are used to collect a liquid source=• Seaux vides: Sont utilisés pour collecter une source de liquide
• Filled buckets: Are used to place a liquid source=• Seaux remplis: Sont utilisés pour placer une source de liquide
• Heads, pumpkins: Equipped to players and armor stands, or placed as a block=• Têtes, citrouilles: Seront équipées pour les joueurs et les armures, ou placées en bloc
• Shulker boxes: Are placed as a block=• Boîtes de Shulker: Sont placées comme un bloc
• TNT: Is placed and ignited=• TNT: Est placé et allumé
• Flint and steel: Is used to ignite a fire in air and to ignite TNT=• Briquet: Sert à allumer un feu dans l'air et à allumer du TNT
• Spawn eggs: Will summon the mob they contain=• Silex et acier: Sert à allumer un feu dans l'air et à allumer du TNT
• Other items: Are simply dropped=• Autres articles: Sont simplement lâchés
Downwards-Facing Dispenser=Distributeur orienté vers le bas
Upwards-Facing Dispenser=Distributeur orienté vers le haut
Inventory=Inventaire
9 inventory slots=9 emplacements d'inventaire
Launches item when powered by redstone power=Lance un objet lorsqu'il est alimenté par la puissance Redstone

View File

@ -0,0 +1,25 @@
# textdomain: mcl_dispensers
Dispenser=Dozownik
A dispenser is a block which acts as a redstone component which, when powered with redstone power, dispenses an item. It has a container with 9 inventory slots.=Dozownik jest mechanizmem czerwienitowym, który po zasileniu wystrzeli lub wyrzuci przedmiot. Jest on pojemnikiem z 9 miejscami.
Place the dispenser in one of 6 possible directions. The “hole” is where items will fly out of the dispenser. Use the dispenser to access its inventory. Insert the items you wish to dispense. Supply the dispenser with redstone energy once to dispense a random item.=Postaw dozownik w jednym z 6 możliwych kierunków. "Dziura" wskazuje z której strony przedmioty będą dozowane. Użyj dozownika, aby zarządzać jego ekwipunkiem. Zasil dozownik czerwienitem aby wyrzucić losowy przedmiot.
The dispenser will do different things, depending on the dispensed item:=Dozownik będzie zachowywał się inaczej w zależności od przedmiotu:
• Arrows: Are launched=• Strzały: są wystrzelone
• Eggs and snowballs: Are thrown=• Jaja i śnieżki: są wyrzucane
• Fire charges: Are fired in a straight line=• Ładunki ogniowe: Są wystrzelone w linii prostej
• Armor: Will be equipped to players and armor stands=• Zbroja: będzie ekwipowana graczom, lub stojakom na zbroję
• Boats: Are placed on water or are dropped=• Łódki: Będą postawione na wodzie, lub wypuszczone
• Minecart: Are placed on rails or are dropped=• Wagoniki: będą postawione na torach, lub upuszczone
• Bone meal: Is applied on the block it is facing=• Mączka kostna: będzie zaaplikowana do bloku
• Empty buckets: Are used to collect a liquid source=• Puste wiadra: będą wykorzystane do zebrania źródła płynu
• Filled buckets: Are used to place a liquid source=• Pełne wiadra: będą wykorzystane do postawienia źródła płynu
• Heads, pumpkins: Equipped to players and armor stands, or placed as a block=• Głowy, dynie: będą ekwipowane graczom i stojakom na zbroję, lub postawione jako bloki
• Shulker boxes: Are placed as a block=Shulkerowe skrzynie: są postawione jako blok
• TNT: Is placed and ignited=• Trotyl: będzie postawiony i zapalony
• Flint and steel: Is used to ignite a fire in air and to ignite TNT=• Krzesiwo: będzie wykorzystane do rozpalenia ognia w powietrzu i zapalenia trotylu
• Spawn eggs: Will summon the mob they contain=• Jaja przywołujące: przywołają moba, którego zawierają
• Other items: Are simply dropped=• Inne przedmioty: zostaną upuszczone
Downwards-Facing Dispenser=Dozownik skierowany w dół
Upwards-Facing Dispenser=Dozownik skierowany w górę
Inventory=Ekwipunek
9 inventory slots=9 miejsc ekwipunku
Launches item when powered by redstone power=Wystrzela przedmiot gdy zasilony czerwienitem

View File

@ -0,0 +1,25 @@
# textdomain: mcl_dispensers
Dispenser=Диспенсер
A dispenser is a block which acts as a redstone component which, when powered with redstone power, dispenses an item. It has a container with 9 inventory slots.=Диспенсер это элемент редстоуна, который при подаче энергии редстоуна выбрасывает предмет. В нём есть контейнер из 9 отсеков инвентаря.
Place the dispenser in one of 6 possible directions. The “hole” is where items will fly out of the dispenser. Use the dispenser to access its inventory. Insert the items you wish to dispense. Supply the dispenser with redstone energy once to dispense a random item.=Направьте диспенсер в одном из 6 возможных направлений. Предметы будут вылетать из отверстия. [Используйте] диспенсер для доступа к его инвентарю. Загрузите туда предметы, которые должны из него выбрасываться. Подайте однократно на диспенсер энергию редстоуна, чтобы выпал случайный предмет.
The dispenser will do different things, depending on the dispensed item:=Диспенсер будет делать разные вещи, в зависимости от выдаваемых предметов:
• Arrows: Are launched=• Стрелы: выстреливают
• Eggs and snowballs: Are thrown=• Яйца и снежки: происходит бросок
• Fire charges: Are fired in a straight line=• Огненные шары: стреляют по прямой линии
• Armor: Will be equipped to players and armor stands=• Защита: экипирует игроков или стенд защиты
• Boats: Are placed on water or are dropped=• Лодки: спускаются на воду
• Minecart: Are placed on rails or are dropped=• Вагонетка: помещается на рельсы
• Bone meal: Is applied on the block it is facing=• Костная мука: применяется к блоку перед диспенсером
• Empty buckets: Are used to collect a liquid source=• Пустые вёдра: используются для набора источника жидкости
• Filled buckets: Are used to place a liquid source=• Полные вёдра: используются для размещения источника жидкости
• Heads, pumpkins: Equipped to players and armor stands, or placed as a block=• Головы, тыквы: экипирует игроков, или стенд защиты, или устанавливаются как блоки
• Shulker boxes: Are placed as a block=• Ящик шалкера: устанавливается как блок
• TNT: Is placed and ignited=• Тротил: устанавливается и поджигается
• Flint and steel: Is used to ignite a fire in air and to ignite TNT=• Огниво: используется для зажигания огня в воздухе и для подрыва тротила
• Spawn eggs: Will summon the mob they contain=• Порождающие яйца: будут вызывать мобов, содержащихся в них
• Other items: Are simply dropped=• Другие предметы: просто выдаются
Downwards-Facing Dispenser=• Диспенсер, направленный вниз
Upwards-Facing Dispenser=• Диспенсер, направленный вверх
Inventory=Инвентарь
9 inventory slots=9 отсеков инвентаря
Launches item when powered by redstone power=Выбрасывает предметы при подаче энергии редстоуна

View File

@ -0,0 +1,25 @@
# textdomain: mcl_dispensers
Dispenser=
A dispenser is a block which acts as a redstone component which, when powered with redstone power, dispenses an item. It has a container with 9 inventory slots.=
Place the dispenser in one of 6 possible directions. The “hole” is where items will fly out of the dispenser. Use the dispenser to access its inventory. Insert the items you wish to dispense. Supply the dispenser with redstone energy once to dispense a random item.=
The dispenser will do different things, depending on the dispensed item:=
• Arrows: Are launched=
• Eggs and snowballs: Are thrown=
• Fire charges: Are fired in a straight line=
• Armor: Will be equipped to players and armor stands=
• Boats: Are placed on water or are dropped=
• Minecart: Are placed on rails or are dropped=
• Bone meal: Is applied on the block it is facing=
• Empty buckets: Are used to collect a liquid source=
• Filled buckets: Are used to place a liquid source=
• Heads, pumpkins: Equipped to players and armor stands, or placed as a block=
• Shulker boxes: Are placed as a block=
• TNT: Is placed and ignited=
• Flint and steel: Is used to ignite a fire in air and to ignite TNT=
• Spawn eggs: Will summon the mob they contain=
• Other items: Are simply dropped=
Downwards-Facing Dispenser=
Upwards-Facing Dispenser=
Inventory=
9 inventory slots=
Launches item when powered by redstone power=

3
mcl_dispensers/mod.conf Normal file
View File

@ -0,0 +1,3 @@
name = mcl_dispensers
depends = mcl_init, mcl_formspec, mesecons, mcl_sounds, mcl_tnt, mcl_worlds, mcl_core, mcl_nether, mcl_armor_stand, mcl_armor
optional_depends = doc, screwdriver

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 B

221
mcl_droppers/init.lua Normal file
View File

@ -0,0 +1,221 @@
--[[ This mod registers 3 nodes:
- One node for the horizontal-facing dropper (mcl_droppers:dropper)
- One node for the upwards-facing droppers (mcl_droppers:dropper_up)
- One node for the downwards-facing droppers (mcl_droppers:dropper_down)
3 node definitions are needed because of the way the textures are defined.
All node definitions share a lot of code, so this is the reason why there
are so many weird tables below.
]]
local S = minetest.get_translator(minetest.get_current_modname())
-- For after_place_node
local function setup_dropper(pos)
-- Set formspec and inventory
local form = "size[9,8.75]"..
"label[0,4.0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]"..
"list[current_player;main;0,4.5;9,3;9]"..
mcl_formspec.get_itemslot_bg(0,4.5,9,3)..
"list[current_player;main;0,7.74;9,1;]"..
mcl_formspec.get_itemslot_bg(0,7.74,9,1)..
"label[3,0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Dropper"))).."]"..
"list[context;main;3,0.5;3,3;]"..
mcl_formspec.get_itemslot_bg(3,0.5,3,3)..
"listring[context;main]"..
"listring[current_player;main]"
local meta = minetest.get_meta(pos)
meta:set_string("formspec", form)
local inv = meta:get_inventory()
inv:set_size("main", 9)
end
local function orientate_dropper(pos, placer)
-- Not placed by player
if not placer then return end
-- Pitch in degrees
local pitch = placer:get_look_vertical() * (180 / math.pi)
if pitch > 55 then
minetest.swap_node(pos, {name="mcl_droppers:dropper_up"})
elseif pitch < -55 then
minetest.swap_node(pos, {name="mcl_droppers:dropper_down"})
end
end
local on_rotate
if minetest.get_modpath("screwdriver") then
on_rotate = screwdriver.rotate_simple
end
-- Shared core definition table
local dropperdef = {
is_ground_content = false,
sounds = mcl_sounds.node_sound_stone_defaults(),
after_dig_node = function(pos, oldnode, oldmetadata, digger)
local meta = minetest.get_meta(pos)
local meta2 = meta
meta:from_table(oldmetadata)
local inv = meta:get_inventory()
for i=1, inv:get_size("main") do
local stack = inv:get_stack("main", i)
if not stack:is_empty() then
local p = {x=pos.x+math.random(0, 10)/10-0.5, y=pos.y, z=pos.z+math.random(0, 10)/10-0.5}
minetest.add_item(p, stack)
end
end
meta:from_table(meta2:to_table())
end,
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
local name = player:get_player_name()
if minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
return 0
else
return count
end
end,
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
local name = player:get_player_name()
if minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
return 0
else
return stack:get_count()
end
end,
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
local name = player:get_player_name()
if minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
return 0
else
return stack:get_count()
end
end,
_mcl_blast_resistance = 3.5,
_mcl_hardness = 3.5,
mesecons = {effector = {
-- Drop random item when triggered
action_on = function(pos, node)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local droppos
if node.name == "mcl_droppers:dropper" then
droppos = vector.subtract(pos, minetest.facedir_to_dir(node.param2))
elseif node.name == "mcl_droppers:dropper_up" then
droppos = {x=pos.x, y=pos.y+1, z=pos.z}
elseif node.name == "mcl_droppers:dropper_down" then
droppos = {x=pos.x, y=pos.y-1, z=pos.z}
end
local dropnode = minetest.get_node(droppos)
-- Do not drop into solid nodes, unless they are containers
local dropnodedef = minetest.registered_nodes[dropnode.name]
if dropnodedef.walkable and not dropnodedef.groups.container then
return
end
local stacks = {}
for i=1,inv:get_size("main") do
local stack = inv:get_stack("main", i)
if not stack:is_empty() then
table.insert(stacks, {stack = stack, stackpos = i})
end
end
if #stacks >= 1 then
local r = math.random(1, #stacks)
local stack = stacks[r].stack
local dropitem = ItemStack(stack)
dropitem:set_count(1)
local stack_id = stacks[r].stackpos
-- If it's a container, attempt to put it into the container
local dropped = mcl_util.move_item_container(pos, droppos, nil, stack_id)
-- No container?
if not dropped and not dropnodedef.groups.container then
-- Drop item normally
minetest.add_item(droppos, dropitem)
stack:take_item()
inv:set_stack("main", stack_id, stack)
end
end
end,
rules = mesecon.rules.alldirs,
}},
on_rotate = on_rotate,
}
-- Horizontal dropper
local horizontal_def = table.copy(dropperdef)
horizontal_def.description = S("Dropper")
horizontal_def._tt_help = S("9 inventory slots").."\n"..S("Drops item when powered by redstone power")
horizontal_def._doc_items_longdesc = S("A dropper is a redstone component and a container with 9 inventory slots which, when supplied with redstone power, drops an item or puts it into a container in front of it.")
horizontal_def._doc_items_usagehelp = S("Droppers can be placed in 6 possible directions, items will be dropped out of the hole. Use the dropper to access its inventory. Supply it with redstone energy once to make the dropper drop or transfer a random item.")
function horizontal_def.after_place_node(pos, placer, itemstack, pointed_thing)
setup_dropper(pos)
orientate_dropper(pos, placer)
end
horizontal_def.tiles = {
"default_furnace_top.png", "default_furnace_bottom.png",
"default_furnace_side.png", "default_furnace_side.png",
"default_furnace_side.png", "mcl_droppers_dropper_front_horizontal.png"
}
horizontal_def.paramtype2 = "facedir"
horizontal_def.groups = {pickaxey=1, container=2, material_stone=1}
minetest.register_node("mcl_droppers:dropper", horizontal_def)
-- Down dropper
local down_def = table.copy(dropperdef)
down_def.description = S("Downwards-Facing Dropper")
down_def.after_place_node = setup_dropper
down_def.tiles = {
"default_furnace_top.png", "mcl_droppers_dropper_front_vertical.png",
"default_furnace_side.png", "default_furnace_side.png",
"default_furnace_side.png", "default_furnace_side.png"
}
down_def.groups = {pickaxey=1, container=2,not_in_creative_inventory=1, material_stone=1}
down_def._doc_items_create_entry = false
down_def.drop = "mcl_droppers:dropper"
minetest.register_node("mcl_droppers:dropper_down", down_def)
-- Up dropper
-- The up dropper is almost identical to the down dropper, it only differs in textures
local up_def = table.copy(down_def)
up_def.description = S("Upwards-Facing Dropper")
up_def.tiles = {
"mcl_droppers_dropper_front_vertical.png", "default_furnace_bottom.png",
"default_furnace_side.png", "default_furnace_side.png",
"default_furnace_side.png", "default_furnace_side.png"
}
minetest.register_node("mcl_droppers:dropper_up", up_def)
-- Ladies and gentlemen, I present to you: the crafting recipe!
minetest.register_craft({
output = "mcl_droppers:dropper",
recipe = {
{"mcl_core:cobble", "mcl_core:cobble", "mcl_core:cobble",},
{"mcl_core:cobble", "", "mcl_core:cobble",},
{"mcl_core:cobble", "mesecons:redstone", "mcl_core:cobble",},
}
})
-- Add entry aliases for the Help
if minetest.get_modpath("doc") then
doc.add_entry_alias("nodes", "mcl_droppers:dropper", "nodes", "mcl_droppers:dropper_down")
doc.add_entry_alias("nodes", "mcl_droppers:dropper", "nodes", "mcl_droppers:dropper_up")
end
-- Legacy
minetest.register_lbm({
label = "Update dropper formspecs (0.60.0)",
name = "mcl_droppers:update_formspecs_0_60_0",
nodenames = { "mcl_droppers:dropper", "mcl_droppers:dropper_down", "mcl_droppers:dropper_up" },
action = function(pos, node)
setup_dropper(pos)
minetest.log("action", "[mcl_droppers] Node formspec updated at "..minetest.pos_to_string(pos))
end,
})

220
mcl_droppers/init_new.lua Normal file
View File

@ -0,0 +1,220 @@
--[[ This mod registers 3 nodes:
- One node for the horizontal-facing dropper (mcl_droppers:dropper)
- One node for the upwards-facing droppers (mcl_droppers:dropper_up)
- One node for the downwards-facing droppers (mcl_droppers:dropper_down)
3 node definitions are needed because of the way the textures are defined.
All node definitions share a lot of code, so this is the reason why there
are so many weird tables below.
]]
local S = minetest.get_translator(minetest.get_current_modname())
-- For after_place_node
local function setup_dropper(pos)
-- Set formspec and inventory
local form = "size[9,8.75]"..
"background[-0.19,-0.25;9.41,9.49;crafting_inventory_9_slots.png]"..
"label[0,4.0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]"..
"list[current_player;main;0,4.5;9,3;9]"..
"list[current_player;main;0,7.74;9,1;]"..
"label[3,0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Dropper"))).."]"..
"list[context;main;3,0.5;3,3;]"..
"listring[context;main]"..
"listring[current_player;main]"
local meta = minetest.get_meta(pos)
meta:set_string("formspec", form)
local inv = meta:get_inventory()
inv:set_size("main", 9)
end
local function orientate_dropper(pos, placer)
-- Not placed by player
if not placer then return end
-- Pitch in degrees
local pitch = placer:get_look_vertical() * (180 / math.pi)
if pitch > 55 then
minetest.swap_node(pos, {name="mcl_droppers:dropper_up"})
elseif pitch < -55 then
minetest.swap_node(pos, {name="mcl_droppers:dropper_down"})
end
end
local on_rotate
if minetest.get_modpath("screwdriver") then
on_rotate = screwdriver.rotate_simple
end
-- Shared core definition table
local dropperdef = {
is_ground_content = false,
sounds = mcl_sounds.node_sound_stone_defaults(),
after_dig_node = function(pos, oldnode, oldmetadata, digger)
local meta = minetest.get_meta(pos)
local meta2 = meta
meta:from_table(oldmetadata)
local inv = meta:get_inventory()
for i=1, inv:get_size("main") do
local stack = inv:get_stack("main", i)
if not stack:is_empty() then
local p = {x=pos.x+math.random(0, 10)/10-0.5, y=pos.y, z=pos.z+math.random(0, 10)/10-0.5}
minetest.add_item(p, stack)
end
end
meta:from_table(meta2:to_table())
end,
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
local name = player:get_player_name()
if minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
return 0
else
return count
end
end,
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
local name = player:get_player_name()
if minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
return 0
else
return stack:get_count()
end
end,
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
local name = player:get_player_name()
if minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
return 0
else
return stack:get_count()
end
end,
_mcl_blast_resistance = 3.5,
_mcl_hardness = 3.5,
mesecons = {effector = {
-- Drop random item when triggered
action_on = function(pos, node)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local droppos
if node.name == "mcl_droppers:dropper" then
droppos = vector.subtract(pos, minetest.facedir_to_dir(node.param2))
elseif node.name == "mcl_droppers:dropper_up" then
droppos = {x=pos.x, y=pos.y+1, z=pos.z}
elseif node.name == "mcl_droppers:dropper_down" then
droppos = {x=pos.x, y=pos.y-1, z=pos.z}
end
local dropnode = minetest.get_node(droppos)
-- Do not drop into solid nodes, unless they are containers
local dropnodedef = minetest.registered_nodes[dropnode.name]
if dropnodedef.walkable and not dropnodedef.groups.container then
return
end
local stacks = {}
for i=1,inv:get_size("main") do
local stack = inv:get_stack("main", i)
if not stack:is_empty() then
table.insert(stacks, {stack = stack, stackpos = i})
end
end
if #stacks >= 1 then
local r = math.random(1, #stacks)
local stack = stacks[r].stack
local dropitem = ItemStack(stack)
dropitem:set_count(1)
local stack_id = stacks[r].stackpos
-- If it's a container, attempt to put it into the container
local dropped = mcl_util.move_item_container(pos, droppos, nil, stack_id)
-- No container?
if not dropped and not dropnodedef.groups.container then
-- Drop item normally
minetest.add_item(droppos, dropitem)
stack:take_item()
inv:set_stack("main", stack_id, stack)
end
end
end,
rules = mesecon.rules.alldirs,
}},
on_rotate = on_rotate,
}
-- Horizontal dropper
local horizontal_def = table.copy(dropperdef)
horizontal_def.description = S("Dropper")
horizontal_def._doc_items_longdesc = S("A dropper is a redstone component and a container with 9 inventory slots which, when supplied with redstone power, drops an item or puts it into a container in front of it.")
horizontal_def._doc_items_usagehelp = S("Droppers can be placed in 6 possible directions, items will be dropped out of the hole. Use the dropper to access its inventory. Supply it with redstone energy once to make the dropper drop or transfer a random item.")
function horizontal_def.after_place_node(pos, placer, itemstack, pointed_thing)
setup_dropper(pos)
orientate_dropper(pos, placer)
end
horizontal_def.tiles = {
"default_furnace_top.png", "default_furnace_bottom.png",
"default_furnace_side.png", "default_furnace_side.png",
"default_furnace_side.png", "mcl_droppers_dropper_front_horizontal.png",
}
horizontal_def.paramtype2 = "facedir"
horizontal_def.groups = {pickaxey=1, container=2, material_stone=1}
minetest.register_node("mcl_droppers:dropper", horizontal_def)
-- Down dropper
local down_def = table.copy(dropperdef)
down_def.description = S("Downwards-Facing Dropper")
down_def.after_place_node = setup_dropper
down_def.tiles = {
"default_furnace_top.png", "mcl_droppers_dropper_front_vertical.png",
"default_furnace_side.png", "default_furnace_side.png",
"default_furnace_side.png", "default_furnace_side.png",
}
down_def.groups = {pickaxey=1, container=2,not_in_creative_inventory=1, material_stone=1}
down_def._doc_items_create_entry = false
down_def.drop = "mcl_droppers:dropper"
minetest.register_node("mcl_droppers:dropper_down", down_def)
-- Up dropper
-- The up dropper is almost identical to the down dropper, it only differs in textures
local up_def = table.copy(down_def)
up_def.description = S("Upwards-Facing Dropper")
up_def.tiles = {
"mcl_droppers_dropper_front_vertical.png", "default_furnace_bottom.png",
"default_furnace_side.png", "default_furnace_side.png",
"default_furnace_side.png", "default_furnace_side.png",
}
minetest.register_node("mcl_droppers:dropper_up", up_def)
-- Ladies and gentlemen, I present to you: the crafting recipe!
minetest.register_craft({
output = "mcl_droppers:dropper",
recipe = {
{"mcl_core:cobble", "mcl_core:cobble", "mcl_core:cobble",},
{"mcl_core:cobble", "", "mcl_core:cobble",},
{"mcl_core:cobble", "mesecons:redstone", "mcl_core:cobble",},
}
})
-- Add entry aliases for the Help
if minetest.get_modpath("doc") then
doc.add_entry_alias("nodes", "mcl_droppers:dropper", "nodes", "mcl_droppers:dropper_down")
doc.add_entry_alias("nodes", "mcl_droppers:dropper", "nodes", "mcl_droppers:dropper_up")
end
minetest.register_lbm({
label = "Update dropper formspecs (0.51.0)",
name = "mcl_droppers:update_formspecs_0_51_0",
nodenames = { "mcl_droppers:dropper", "mcl_droppers:dropper_down", "mcl_droppers:dropper_up" },
action = function(pos, node)
minetest.registered_nodes[node.name].on_construct(pos)
minetest.log("action", "[mcl_droppers] Node formspec updated at "..minetest.pos_to_string(pos))
end,
})

View File

@ -0,0 +1,9 @@
# textdomain: mcl_droppers
Dropper=Spender
A dropper is a redstone component and a container with 9 inventory slots which, when supplied with redstone power, drops an item or puts it into a container in front of it.=Ein Spender ist eine Redstonekomponente und ein Behälter mit 9 Inventarplätzen. Er wird, wenn mit Redstoneenergie versorgt, einen Gegenstand abwerfen oder in einen Behälter, auf den er zeigt, ablegen.
Droppers can be placed in 6 possible directions, items will be dropped out of the hole. Use the dropper to access its inventory. Supply it with redstone energy once to make the dropper drop or transfer a random item.=Spender können in 6 mögliche Richtungen platziert werden, Gegenstände fallen aus dem Loch hinaus. Benutzen Sie den Spender, um auf sein Inventar zuzugreifen. Versorgen Sie ihn mit Redstoneenergie, um den Spender einen Gegenstand abwerfen oder in einen Behälter ablegen zu lassen.
Downwards-Facing Dropper=Nach unten zeigender Spender
Upwards-Facing Dropper=Nach oben zeigender Spender
Inventory=Inventar
9 inventory slots=9 Inventarplätze
Drops item when powered by redstone power=Gibt einen Gegenstand aus, wenn mit Redstoneenergie versorgt

View File

@ -0,0 +1,7 @@
# textdomain: mcl_droppers
Dropper=Soltador
A dropper is a redstone component and a container with 9 inventory slots which, when supplied with redstone power, drops an item or puts it into a container in front of it.=Un Soltador es un componente de redstone y un contenedor con 9 ranuras de inventario que, cuando se suministra con redstone power, deja caer un artículo o lo coloca en un contenedor frente a él.
Droppers can be placed in 6 possible directions, items will be dropped out of the hole. Use the dropper to access its inventory. Supply it with redstone energy once to make the dropper drop or transfer a random item.=Los soltadores se pueden colocar en 6 direcciones posibles, los artículos se sacarán del agujero. Usa el cuentagotas para acceder a su inventario. Proporcione energía de redstone una vez para hacer que el soltador caiga o transfiera un elemento aleatorio.
Downwards-Facing Dropper=Soltador orientado hacia abajo
Upwards-Facing Dropper=Soltador orientado hacia arriba
Inventory=Inventario

View File

@ -0,0 +1,9 @@
# textdomain: mcl_droppers
Dropper=Dropper
A dropper is a redstone component and a container with 9 inventory slots which, when supplied with redstone power, drops an item or puts it into a container in front of it.=Un dropper est un composant redstone et un conteneur avec 9 emplacements d'inventaire qui, lorsqu'ils sont alimentés en puissance redstone, déposent un objet ou le placent dans un conteneur en face de lui.
Droppers can be placed in 6 possible directions, items will be dropped out of the hole. Use the dropper to access its inventory. Supply it with redstone energy once to make the dropper drop or transfer a random item.=Les droppers peuvent être placés dans 6 directions possibles, les objets seront déposés hors du trou. Utilisez le dropper pour accéder à son inventaire. Fournissez-lui de l'énergie redstone pour faire tomber un élement ou transférer un élément aléatoire.
Downwards-Facing Dropper=Dropper orienté vers le bas
Upwards-Facing Dropper=Dropper orienté vers le haut
Inventory=Inventaire
9 inventory slots=9 emplacements d'inventaire
Drops item when powered by redstone power=Obtient un objet lorsqu'il est alimenté par la puissance Redstone

View File

@ -0,0 +1,9 @@
# textdomain: mcl_droppers
Dropper=Podajnik
A dropper is a redstone component and a container with 9 inventory slots which, when supplied with redstone power, drops an item or puts it into a container in front of it.=Podajnik jest urządzeniem czerwienitowym i pojemnikiem z 9 miejscami, który po dostarczeniu energii czerwienitowej wyrzuca przedmiot lub umieszcza go w pojemniku przed nim.
Droppers can be placed in 6 possible directions, items will be dropped out of the hole. Use the dropper to access its inventory. Supply it with redstone energy once to make the dropper drop or transfer a random item.=Podajniki mogą być skierowane w 6 możliwych kierunkach, przedmioty będą wyrzucane z dziury. Użyj podajnika aby zyskać dostęp do jego ekwipunku. Dostarcz do niego energii czerwienitowej aby sprawić by wyrzucił lub przeniósł losowy przedmiot.
Downwards-Facing Dropper=Podajnik skierowany w dół
Upwards-Facing Dropper=Podajnik skierowany w górę
Inventory=Ekwipunek
9 inventory slots=9 miejsc ekwipunku
Drops item when powered by redstone power=Wyrzuca przedmiot gdy zasilony czerwienitem

View File

@ -0,0 +1,9 @@
# textdomain: mcl_droppers
Dropper=Выбрасыватель
A dropper is a redstone component and a container with 9 inventory slots which, when supplied with redstone power, drops an item or puts it into a container in front of it.=Выбрасыватель это элемент редстоуна и контейнер с 9 отсеками инвентаря, срабатывающий по сигналу редстоуна и выбрасывающий предмет, либо выталкивающий его в контейнер, стоящий перед ним.
Droppers can be placed in 6 possible directions, items will be dropped out of the hole. Use the dropper to access its inventory. Supply it with redstone energy once to make the dropper drop or transfer a random item.=Выбрасыватель может быть установлен в 6 возможных направлениях, предметы будут выбрасываться в соответствующем направлении из отверстия. [Используйте] выбрасыватель для доступа к его инвентарю. Подайте на него энергию редстоуна однократно, чтобы заставить его выбросить либо предать один случайный предмет.
Downwards-Facing Dropper=Выбрасыватель, смотрящий вниз
Upwards-Facing Dropper=Выбрасыватель, смотрящий вверх
Inventory=Инвентарь
9 inventory slots=9 отсеков инвентаря
Drops item when powered by redstone power=Выбрасывает предмет при подаче энергии редстоуна

View File

@ -0,0 +1,9 @@
# textdomain: mcl_droppers
Dropper=
A dropper is a redstone component and a container with 9 inventory slots which, when supplied with redstone power, drops an item or puts it into a container in front of it.=
Droppers can be placed in 6 possible directions, items will be dropped out of the hole. Use the dropper to access its inventory. Supply it with redstone energy once to make the dropper drop or transfer a random item.=
Downwards-Facing Dropper=
Upwards-Facing Dropper=
Inventory=
9 inventory slots=
Drops item when powered by redstone power=

3
mcl_droppers/mod.conf Normal file
View File

@ -0,0 +1,3 @@
name = mcl_droppers
depends = mcl_init, mcl_formspec, mesecons, mcl_util
optional_depends = doc, screwdriver

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 B

470
mcl_observers/init.lua Normal file
View File

@ -0,0 +1,470 @@
local S = minetest.get_translator(minetest.get_current_modname())
mcl_observers = {}
local string = string
local get_node = minetest.get_node
-- Warning! TODO: Remove this message.
-- 'realtime' is experimental feature! It can slow down the everything!
-- Please set it to false and restart the game if something's wrong:
local realtime = true
--local realtime = false
local rules_flat = {
{ x = 0, y = 0, z = -1, spread = true },
}
local function get_rules_flat(node)
local rules = rules_flat
for i=1, node.param2 do
rules = mesecon.rotate_rules_left(rules)
end
return rules
end
local rules_down = {{ x = 0, y = 1, z = 0, spread = true }}
local rules_up = {{ x = 0, y = -1, z = 0, spread = true }}
function mcl_observers.observer_activate(pos)
minetest.after(mcl_vars.redstone_tick, function(pos)
local node = get_node(pos)
if not node then
return
end
local nn = node.name
if nn == "mcl_observers:observer_off" then
minetest.set_node(pos, {name = "mcl_observers:observer_on", param2 = node.param2})
mesecon.receptor_on(pos, get_rules_flat(node))
elseif nn == "mcl_observers:observer_down_off" then
minetest.set_node(pos, {name = "mcl_observers:observer_down_on"})
mesecon.receptor_on(pos, rules_down)
elseif nn == "mcl_observers:observer_up_off" then
minetest.set_node(pos, {name = "mcl_observers:observer_up_on"})
mesecon.receptor_on(pos, rules_up)
end
end, {x=pos.x, y=pos.y, z=pos.z})
end
-- Scan the node in front of the observer
-- and update the observer state if needed.
-- TODO: Also scan metadata changes.
-- TODO: Ignore some node changes.
local function observer_scan(pos, initialize)
local node = get_node(pos)
local front
if node.name == "mcl_observers:observer_up_off" or node.name == "mcl_observers:observer_up_on" then
front = vector.add(pos, {x=0, y=1, z=0})
elseif node.name == "mcl_observers:observer_down_off" or node.name == "mcl_observers:observer_down_on" then
front = vector.add(pos, {x=0, y=-1, z=0})
else
front = vector.add(pos, minetest.facedir_to_dir(node.param2))
end
local frontnode = get_node(front)
local meta = minetest.get_meta(pos)
local oldnode = meta:get_string("node_name")
local oldparam2 = meta:get_string("node_param2")
local meta_needs_updating = false
if oldnode ~= "" and not initialize then
if not (frontnode.name == oldnode and tostring(frontnode.param2) == oldparam2) then
-- Node state changed! Activate observer
if node.name == "mcl_observers:observer_off" then
minetest.set_node(pos, {name = "mcl_observers:observer_on", param2 = node.param2})
mesecon.receptor_on(pos, get_rules_flat(node))
elseif node.name == "mcl_observers:observer_down_off" then
minetest.set_node(pos, {name = "mcl_observers:observer_down_on"})
mesecon.receptor_on(pos, rules_down)
elseif node.name == "mcl_observers:observer_up_off" then
minetest.set_node(pos, {name = "mcl_observers:observer_up_on"})
mesecon.receptor_on(pos, rules_up)
end
meta_needs_updating = true
end
else
meta_needs_updating = true
end
if meta_needs_updating then
meta:set_string("node_name", frontnode.name)
meta:set_string("node_param2", tostring(frontnode.param2))
end
return frontnode
end
-- Vertical orientation (CURRENTLY DISABLED)
local function observer_orientate(pos, placer)
-- Not placed by player
if not placer then return end
-- Placer pitch in degrees
local pitch = placer:get_look_vertical() * (180 / math.pi)
--local node = get_node(pos)
if pitch > 55 then -- player looking upwards
-- Observer looking downwards
minetest.set_node(pos, {name="mcl_observers:observer_down_off"})
elseif pitch < -55 then -- player looking downwards
-- Observer looking upwards
minetest.set_node(pos, {name="mcl_observers:observer_up_off"})
end
end
mesecon.register_node("mcl_observers:observer", {
is_ground_content = false,
sounds = mcl_sounds.node_sound_stone_defaults(),
paramtype2 = "facedir",
on_rotate = false,
_mcl_blast_resistance = 3.5,
_mcl_hardness = 3.5,
}, {
description = S("Observer"),
_tt_help = S("Emits redstone pulse when block in front changes"),
_doc_items_longdesc = S("An observer is a redstone component which observes the block in front of it and sends a very short redstone pulse whenever this block changes."),
_doc_items_usagehelp = S("Place the observer directly in front of the block you want to observe with the “face” looking at the block. The arrow points to the side of the output, which is at the opposite side of the “face”. You can place your redstone dust or any other component here."),
groups = {pickaxey=1, material_stone=1, not_opaque=1, },
tiles = {
"mcl_observers_observer_top.png^[transformR180", "default_furnace_bottom.png",
"mcl_observers_observer_side.png", "mcl_observers_observer_side.png",
"mcl_observers_observer_front.png", "mcl_observers_observer_back.png",
},
mesecons = {
receptor = {
state = mesecon.state.off,
rules = get_rules_flat,
},
},
on_construct = function(pos)
if not realtime then
observer_scan(pos, true)
end
end,
after_place_node = observer_orientate,
}, {
_doc_items_create_entry = false,
groups = {pickaxey=1, material_stone=1, not_opaque=1, not_in_creative_inventory=1 },
tiles = {
"mcl_observers_observer_top.png^[transformR180", "default_furnace_bottom.png",
"mcl_observers_observer_side.png", "mcl_observers_observer_side.png",
"mcl_observers_observer_front.png", "mcl_observers_observer_back_lit.png",
},
mesecons = {
receptor = {
state = mesecon.state.on,
rules = get_rules_flat,
}
},
-- VERY quickly disable observer after construction
on_construct = function(pos)
local timer = minetest.get_node_timer(pos)
timer:start(mcl_vars.redstone_tick)
end,
on_timer = function(pos, elapsed)
local node = get_node(pos)
minetest.set_node(pos, {name = "mcl_observers:observer_off", param2 = node.param2})
mesecon.receptor_off(pos, get_rules_flat(node))
end,
}
)
mesecon.register_node("mcl_observers:observer_down", {
is_ground_content = false,
sounds = mcl_sounds.node_sound_stone_defaults(),
groups = {pickaxey=1, material_stone=1, not_opaque=1, not_in_creative_inventory=1 },
on_rotate = false,
_mcl_blast_resistance = 3.5,
_mcl_hardness = 3.5,
drop = "mcl_observers:observer_off",
}, {
tiles = {
"mcl_observers_observer_back.png", "mcl_observers_observer_front.png",
"mcl_observers_observer_side.png^[transformR90", "mcl_observers_observer_side.png^[transformR90",
"mcl_observers_observer_top.png", "mcl_observers_observer_top.png",
},
mesecons = {
receptor = {
state = mesecon.state.off,
rules = rules_down,
},
},
on_construct = function(pos)
if not realtime then
observer_scan(pos, true)
end
end,
}, {
_doc_items_create_entry = false,
tiles = {
"mcl_observers_observer_back_lit.png", "mcl_observers_observer_front.png",
"mcl_observers_observer_side.png^[transformR90", "mcl_observers_observer_side.png^[transformR90",
"mcl_observers_observer_top.png", "mcl_observers_observer_top.png",
},
mesecons = {
receptor = {
state = mesecon.state.on,
rules = rules_down,
},
},
-- VERY quickly disable observer after construction
on_construct = function(pos)
local timer = minetest.get_node_timer(pos)
timer:start(mcl_vars.redstone_tick)
end,
on_timer = function(pos, elapsed)
local node = get_node(pos)
minetest.set_node(pos, {name = "mcl_observers:observer_down_off", param2 = node.param2})
mesecon.receptor_off(pos, rules_down)
end,
}
)
mesecon.register_node("mcl_observers:observer_up", {
is_ground_content = false,
sounds = mcl_sounds.node_sound_stone_defaults(),
groups = {pickaxey=1, material_stone=1, not_opaque=1, not_in_creative_inventory=1 },
on_rotate = false,
_mcl_blast_resistance = 3.5,
_mcl_hardness = 3.5,
drop = "mcl_observers:observer_off",
}, {
tiles = {
"mcl_observers_observer_front.png", "mcl_observers_observer_back.png",
"mcl_observers_observer_side.png^[transformR270", "mcl_observers_observer_side.png^[transformR270",
"mcl_observers_observer_top.png^[transformR180", "mcl_observers_observer_top.png^[transformR180",
},
mesecons = {
receptor = {
state = mesecon.state.off,
rules = rules_up,
},
},
on_construct = function(pos)
if not realtime then
observer_scan(pos, true)
end
end,
}, {
_doc_items_create_entry = false,
tiles = {
"mcl_observers_observer_front.png", "mcl_observers_observer_back_lit.png",
"mcl_observers_observer_side.png^[transformR270", "mcl_observers_observer_side.png^[transformR270",
"mcl_observers_observer_top.png^[transformR180", "mcl_observers_observer_top.png^[transformR180",
},
mesecons = {
receptor = {
state = mesecon.state.on,
rules = rules_up,
},
},
-- VERY quickly disable observer after construction
on_construct = function(pos)
local timer = minetest.get_node_timer(pos)
timer:start(mcl_vars.redstone_tick)
end,
on_timer = function(pos, elapsed)
minetest.set_node(pos, {name = "mcl_observers:observer_up_off"})
mesecon.receptor_off(pos, rules_up)
end,
}
)
minetest.register_craft({
output = "mcl_observers:observer_off",
recipe = {
{ "mcl_core:cobble", "mcl_core:cobble", "mcl_core:cobble" },
{ "mcl_nether:quartz", "mesecons:redstone", "mesecons:redstone" },
{ "mcl_core:cobble", "mcl_core:cobble", "mcl_core:cobble" },
},
})
minetest.register_craft({
output = "mcl_observers:observer_off",
recipe = {
{ "mcl_core:cobble", "mcl_core:cobble", "mcl_core:cobble" },
{ "mesecons:redstone", "mesecons:redstone", "mcl_nether:quartz" },
{ "mcl_core:cobble", "mcl_core:cobble", "mcl_core:cobble" },
},
})
if realtime then
-- Override basic functions for observing:
mcl_observers.add_node = minetest.add_node
mcl_observers.set_node = minetest.set_node
mcl_observers.swap_node = minetest.swap_node
mcl_observers.remove_node = minetest.remove_node
mcl_observers.bulk_set_node = minetest.bulk_set_node
function minetest.add_node(pos,node)
mcl_observers.add_node(pos,node)
local n = get_node({x=pos.x+1,y=pos.y,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).x==-1 then
mcl_observers.observer_activate({x=pos.x+1,y=pos.y,z=pos.z})
end
n = get_node({x=pos.x-1,y=pos.y,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).x==1 then
mcl_observers.observer_activate({x=pos.x-1,y=pos.y,z=pos.z})
end
n = get_node({x=pos.x,y=pos.y,z=pos.z+1})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).z==-1 then
mcl_observers.observer_activate({x=pos.x,y=pos.y,z=pos.z+1})
end
n = get_node({x=pos.x,y=pos.y,z=pos.z-1})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).z==1 then
mcl_observers.observer_activate({x=pos.x,y=pos.y,z=pos.z-1})
end
n = get_node({x=pos.x,y=pos.y-1,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_u" then
mcl_observers.observer_activate({x=pos.x,y=pos.y-1,z=pos.z})
end
n = get_node({x=pos.x,y=pos.y+1,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_d" then
mcl_observers.observer_activate({x=pos.x,y=pos.y+1,z=pos.z})
end
end
function minetest.set_node(pos,node)
mcl_observers.set_node(pos,node)
local n = get_node({x=pos.x+1,y=pos.y,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).x==-1 then
mcl_observers.observer_activate({x=pos.x+1,y=pos.y,z=pos.z})
end
n = get_node({x=pos.x-1,y=pos.y,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).x==1 then
mcl_observers.observer_activate({x=pos.x-1,y=pos.y,z=pos.z})
end
n = get_node({x=pos.x,y=pos.y,z=pos.z+1})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).z==-1 then
mcl_observers.observer_activate({x=pos.x,y=pos.y,z=pos.z+1})
end
n = get_node({x=pos.x,y=pos.y,z=pos.z-1})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).z==1 then
mcl_observers.observer_activate({x=pos.x,y=pos.y,z=pos.z-1})
end
n = get_node({x=pos.x,y=pos.y-1,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_u" then
mcl_observers.observer_activate({x=pos.x,y=pos.y-1,z=pos.z})
end
n = get_node({x=pos.x,y=pos.y+1,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_d" then
mcl_observers.observer_activate({x=pos.x,y=pos.y+1,z=pos.z})
end
end
function minetest.swap_node(pos,node)
mcl_observers.swap_node(pos,node)
local n = get_node({x=pos.x+1,y=pos.y,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).x==-1 then
mcl_observers.observer_activate({x=pos.x+1,y=pos.y,z=pos.z})
end
n = get_node({x=pos.x-1,y=pos.y,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).x==1 then
mcl_observers.observer_activate({x=pos.x-1,y=pos.y,z=pos.z})
end
n = get_node({x=pos.x,y=pos.y,z=pos.z+1})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).z==-1 then
mcl_observers.observer_activate({x=pos.x,y=pos.y,z=pos.z+1})
end
n = get_node({x=pos.x,y=pos.y,z=pos.z-1})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).z==1 then
mcl_observers.observer_activate({x=pos.x,y=pos.y,z=pos.z-1})
end
n = get_node({x=pos.x,y=pos.y-1,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_u" then
mcl_observers.observer_activate({x=pos.x,y=pos.y-1,z=pos.z})
end
n = get_node({x=pos.x,y=pos.y+1,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_d" then
mcl_observers.observer_activate({x=pos.x,y=pos.y+1,z=pos.z})
end
end
function minetest.remove_node(pos)
mcl_observers.remove_node(pos)
local n = get_node({x=pos.x+1,y=pos.y,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).x==-1 then
mcl_observers.observer_activate({x=pos.x+1,y=pos.y,z=pos.z})
end
n = get_node({x=pos.x-1,y=pos.y,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).x==1 then
mcl_observers.observer_activate({x=pos.x-1,y=pos.y,z=pos.z})
end
n = get_node({x=pos.x,y=pos.y,z=pos.z+1})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).z==-1 then
mcl_observers.observer_activate({x=pos.x,y=pos.y,z=pos.z+1})
end
n = get_node({x=pos.x,y=pos.y,z=pos.z-1})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).z==1 then
mcl_observers.observer_activate({x=pos.x,y=pos.y,z=pos.z-1})
end
n = get_node({x=pos.x,y=pos.y-1,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_u" then
mcl_observers.observer_activate({x=pos.x,y=pos.y-1,z=pos.z})
end
n = get_node({x=pos.x,y=pos.y+1,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_d" then
mcl_observers.observer_activate({x=pos.x,y=pos.y+1,z=pos.z})
end
end
function minetest.bulk_set_node(lst, node)
mcl_observers.bulk_set_node(lst, node)
for _, pos in pairs(lst) do
local n = get_node({x=pos.x+1,y=pos.y,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).x==-1 then
mcl_observers.observer_activate({x=pos.x+1,y=pos.y,z=pos.z})
end
n = get_node({x=pos.x-1,y=pos.y,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).x==1 then
mcl_observers.observer_activate({x=pos.x-1,y=pos.y,z=pos.z})
end
n = get_node({x=pos.x,y=pos.y,z=pos.z+1})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).z==-1 then
mcl_observers.observer_activate({x=pos.x,y=pos.y,z=pos.z+1})
end
n = get_node({x=pos.x,y=pos.y,z=pos.z-1})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).z==1 then
mcl_observers.observer_activate({x=pos.x,y=pos.y,z=pos.z-1})
end
n = get_node({x=pos.x,y=pos.y-1,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_u" then
mcl_observers.observer_activate({x=pos.x,y=pos.y-1,z=pos.z})
end
n = get_node({x=pos.x,y=pos.y+1,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_d" then
mcl_observers.observer_activate({x=pos.x,y=pos.y+1,z=pos.z})
end
end
end
else -- if realtime then ^^^ else:
minetest.register_abm({
label = "Observer node check",
nodenames = {"mcl_observers:observer_off", "mcl_observers:observer_down_off", "mcl_observers:observer_up_off"},
interval = 1,
chance = 1,
action = function(pos, node)
observer_scan(pos)
end,
})
end
--[[
With the following code the observer will detect loading of areas where it is placed.
We need to restore signal generated by it before the area was unloaded.
Observer movement and atomic clock (one observer watches another) fails without this often.
But it WILL cause wrong single signal for all other cases, and I hope it's nothing.
After all, why it can't detect the loading of areas, if we haven't a better solution...
]]
minetest.register_lbm({
name = "mcl_observers:activate_lbm",
nodenames = {
"mcl_observers:observer_off",
"mcl_observers:observer_down_off",
"mcl_observers:observer_up_off",
"mcl_observers:observer_on",
"mcl_observers:observer_down_on",
"mcl_observers:observer_up_on",
},
run_at_every_load = true,
action = function(pos)
minetest.after(1, mcl_observers.observer_activate, {x=pos.x, y=pos.y, z=pos.z})
end,
})

View File

@ -0,0 +1,5 @@
# textdomain: mcl_observers
Observer=Wächter
An observer is a redstone component which observes the block in front of it and sends a very short redstone pulse whenever this block changes.=Ein Wächter ist eine Redstonekomponente, die den Block vor ihm beobachtet und einen sehr kurzen Redstoneimpuls sendet, wenn sich dieser Block ändert.
Place the observer directly in front of the block you want to observe with the “face” looking at the block. The arrow points to the side of the output, which is at the opposite side of the “face”. You can place your redstone dust or any other component here.=Platzieren Sie den Wächter direkt vor dem Block, den Sie beobachten wollen, so dass das „Gesicht“ zum Block schaut. Der Pfeil zeigt auf die Seite des Signalausgangs, der sich gegenüber vom „Gesicht“ befindet. Hier können Sie Ihren Restonestaub oder eine beliebige andere Komponente platzieren.
Emits redstone pulse when block in front changes=Macht einen Redstonepuls, wenn der Block vor ihm sich ändert

View File

@ -0,0 +1,4 @@
# textdomain: mcl_observers
Observer=Observador
An observer is a redstone component which observes the block in front of it and sends a very short redstone pulse whenever this block changes.=Un observador es un componente de redstone que observa el bloque frente a él y envía un pulso muy corto de redstone cada vez que este bloque cambia.
Place the observer directly in front of the block you want to observe with the “face” looking at the block. The arrow points to the side of the output, which is at the opposite side of the “face”. You can place your redstone dust or any other component here.=Coloque el observador directamente en frente del bloque que desea observar con la "cara" mirando el bloque. La flecha apunta al lado de la salida, que está en el lado opuesto de la "cara". Puede colocar su polvo de redstone o cualquier otro componente aquí.

View File

@ -0,0 +1,5 @@
# textdomain: mcl_observers
Observer=Observateur
An observer is a redstone component which observes the block in front of it and sends a very short redstone pulse whenever this block changes.=Un observateur est un composant de redstone qui observe le bloc en face de lui et envoie une impulsion de redstone très courte chaque fois que ce bloc change.
Place the observer directly in front of the block you want to observe with the “face” looking at the block. The arrow points to the side of the output, which is at the opposite side of the “face”. You can place your redstone dust or any other component here.=Placez l'observateur directement devant le bloc que vous souhaitez observer avec le "visage" regardant le bloc. La flèche pointe vers le côté de la sortie, qui est du côté opposé du "visage". Vous pouvez placer votre poussière de redstone ou tout autre composant ici.
Emits redstone pulse when block in front changes=Émet une impulsion de redstone lorsque le bloc à l'avant change

View File

@ -0,0 +1,6 @@
# textdomain: mcl_observers
Observer=Detektor
An observer is a redstone component which observes the block in front of it and sends a very short redstone pulse whenever this block changes.=Detektor jest mechanizmem czerwienitowym, który obserwuje blok przed sobą i wysyła krótki puls energii czerwienitowej gdy blok ten się zmienia.
Place the observer directly in front of the block you want to observe with the “face” looking at the block. The arrow points to the side of the output, which is at the opposite side of the “face”. You can place your redstone dust or any other component here.=Postaw detektor przed blokiem, który chcesz obserwować z "twarzą" wskazującą na ten blok. Strzałka wskazuje na stronę z wyjściem, która jest po przeciwnej stronie do "twarzy". Możesz postawić tutaj czerwienit lub dowolny inny komponent.
Emits redstone pulse when block in front changes=Wysyła sygnał czerwienitowy gdy blok przed nim się zmienia

View File

@ -0,0 +1,5 @@
# textdomain: mcl_observers
Observer=Наблюдатель
An observer is a redstone component which observes the block in front of it and sends a very short redstone pulse whenever this block changes.=Наблюдатель это элемент редстоуна, который следит за блоком перед собой и посылает короткий импульс редстоуна, если этот блок меняется.
Place the observer directly in front of the block you want to observe with the “face” looking at the block. The arrow points to the side of the output, which is at the opposite side of the “face”. You can place your redstone dust or any other component here.=Поместите наблюдателя прямо перед блоком, за которым хотите наблюдать, так, чтобы “лицо” смотрело на этот блок. Стрелка показывает выходную сторону, находящуюся на противоположной стороне от “лица”. Вы можете разместить там пыль редстоуна или любой другой компонент.
Emits redstone pulse when block in front changes=Генерирует импульс редстоуна при смене блока, находящегося перед ним

View File

@ -0,0 +1,5 @@
# textdomain: mcl_observers
Observer=
An observer is a redstone component which observes the block in front of it and sends a very short redstone pulse whenever this block changes.=
Place the observer directly in front of the block you want to observe with the “face” looking at the block. The arrow points to the side of the output, which is at the opposite side of the “face”. You can place your redstone dust or any other component here.=
Emits redstone pulse when block in front changes=

2
mcl_observers/mod.conf Normal file
View File

@ -0,0 +1,2 @@
name = mcl_observers
depends = mesecons, mcl_util

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 B

107
mesecons/actionqueue.lua Normal file
View File

@ -0,0 +1,107 @@
local table = table
mesecon.queue.actions={} -- contains all ActionQueue actions
function mesecon.queue:add_function(name, func)
mesecon.queue.funcs[name] = func
end
-- If add_action with twice the same overwritecheck and same position are called, the first one is overwritten
-- use overwritecheck nil to never overwrite, but just add the event to the queue
-- priority specifies the order actions are executed within one globalstep, highest first
-- should be between 0 and 1
function mesecon.queue:add_action(pos, func, params, time, overwritecheck, priority)
-- Create Action Table:
time = time or 0 -- time <= 0 --> execute, time > 0 --> wait time until execution
priority = priority or 1
local action = { pos=mesecon.tablecopy(pos),
func=func,
params=mesecon.tablecopy(params or {}),
time=time,
owcheck=(overwritecheck and mesecon.tablecopy(overwritecheck)) or nil,
priority=priority}
local toremove = nil
-- Otherwise, add the action to the queue
if overwritecheck then -- check if old action has to be overwritten / removed:
for i, ac in pairs(mesecon.queue.actions) do
if(vector.equals(pos, ac.pos)
and mesecon.cmpAny(overwritecheck, ac.owcheck)) then
toremove = i
break
end
end
end
if toremove then
table.remove(mesecon.queue.actions, toremove)
end
table.insert(mesecon.queue.actions, action)
end
-- execute the stored functions on a globalstep
-- if however, the pos of a function is not loaded (get_node_or_nil == nil), do NOT execute the function
-- this makes sure that resuming mesecons circuits when restarting minetest works fine
-- However, even that does not work in some cases, that's why we delay the time the globalsteps
-- start to be execute by 5 seconds
local function get_highest_priority(actions)
local highestp = -1
local highesti
for i, ac in ipairs(actions) do
if ac.priority > highestp then
highestp = ac.priority
highesti = i
end
end
return highesti
end
local m_time = 0
local resumetime = mesecon.setting("resumetime", 4)
minetest.register_globalstep(function (dtime)
m_time = m_time + dtime
-- don't even try if server has not been running for XY seconds; resumetime = time to wait
-- after starting the server before processing the ActionQueue, don't set this too low
if (m_time < resumetime) then return end
local actions = mesecon.tablecopy(mesecon.queue.actions)
local actions_now={}
mesecon.queue.actions = {}
-- sort actions into two categories:
-- those toexecute now (actions_now) and those to execute later (mesecon.queue.actions)
for i, ac in ipairs(actions) do
if ac.time > 0 then
ac.time = ac.time - dtime -- executed later
table.insert(mesecon.queue.actions, ac)
else
table.insert(actions_now, ac)
end
end
while(#actions_now > 0) do -- execute highest priorities first, until all are executed
local hp = get_highest_priority(actions_now)
mesecon.queue:execute(actions_now[hp])
table.remove(actions_now, hp)
end
end)
function mesecon.queue:execute(action)
-- ignore if action queue function name doesn't exist,
-- (e.g. in case the action queue savegame was written by an old mesecons version)
if mesecon.queue.funcs[action.func] then
mesecon.queue.funcs[action.func](action.pos, unpack(action.params))
end
end
-- Store and read the ActionQueue to / from a file
-- so that upcoming actions are remembered when the game
-- is restarted
mesecon.queue.actions = mesecon.file2table("mesecon_actionqueue")
minetest.register_on_shutdown(function()
mesecon.table2file("mesecon_actionqueue", mesecon.queue.actions)
end)

121
mesecons/init.lua Normal file
View File

@ -0,0 +1,121 @@
-- |\ /| ____ ____ ____ _____ ____ _____
-- | \ / | | | | | | | |\ | |
-- | \/ | |___ ____ |___ | | | | \ | |____
-- | | | | | | | | | \ | |
-- | | |___ ____| |___ |____ |____| | \| ____|
-- by Jeija, Uberi (Temperest), sfan5, VanessaE, Hawk777 and contributors
--
--
--
-- This mod adds mesecons[=minecraft redstone] and different receptors/effectors to minetest.
-- See the documentation on the forum for additional information, especially about crafting
--
--
-- For basic development resources, see http://mesecons.net/developers.html
--
--
--
--Quick draft for the mesecons array in the node's definition
--mesecons =
--{
-- receptor =
-- {
-- state = mesecon.state.on/off
-- rules = rules/get_rules
-- },
-- effector =
-- {
-- action_on = function
-- action_off = function
-- action_change = function
-- rules = rules/get_rules
-- },
-- conductor =
-- {
-- state = mesecon.state.on/off
-- offstate = opposite state (for state = on only)
-- onstate = opposite state (for state = off only)
-- rules = rules/get_rules
-- }
--}
-- PUBLIC VARIABLES
mesecon={} -- contains all functions and all global variables
mesecon.queue={} -- contains the ActionQueue
mesecon.queue.funcs={} -- contains all ActionQueue functions
-- Settings
dofile(minetest.get_modpath("mesecons").."/settings.lua")
-- Utilities like comparing positions,
-- adding positions and rules,
-- mostly things that make the source look cleaner
dofile(minetest.get_modpath("mesecons").."/util.lua");
-- Presets (eg default rules)
dofile(minetest.get_modpath("mesecons").."/presets.lua");
-- The ActionQueue
-- Saves all the actions that have to be execute in the future
dofile(minetest.get_modpath("mesecons").."/actionqueue.lua");
-- Internal stuff
-- This is the most important file
-- it handles signal transmission and basically everything else
-- It is also responsible for managing the nodedef things,
-- like calling action_on/off/change
dofile(minetest.get_modpath("mesecons").."/internal.lua");
-- API
-- these are the only functions you need to remember
mesecon.queue:add_function("receptor_on", function (pos, rules)
mesecon.vm_begin()
rules = rules or mesecon.rules.default
-- Call turnon on all linking positions
for _, rule in pairs(mesecon.flattenrules(rules)) do
local np = vector.add(pos, rule)
local rulenames = mesecon.rules_link_rule_all(pos, rule)
for _, rulename in pairs(rulenames) do
mesecon.turnon(np, rulename)
end
end
mesecon.vm_commit()
end)
function mesecon.receptor_on(pos, rules)
mesecon.queue:add_action(pos, "receptor_on", {rules}, nil, rules)
end
mesecon.queue:add_function("receptor_off", function (pos, rules)
rules = rules or mesecon.rules.default
-- Call turnoff on all linking positions
for _, rule in ipairs(mesecon.flattenrules(rules)) do
local np = vector.add(pos, rule)
local rulenames = mesecon.rules_link_rule_all(pos, rule)
for _, rulename in ipairs(rulenames) do
mesecon.vm_begin()
mesecon.changesignal(np, minetest.get_node(np), rulename, mesecon.state.off, 2)
-- Turnoff returns true if turnoff process was successful, no onstate receptor
-- was found along the way. Commit changes that were made in voxelmanip. If turnoff
-- returns true, an onstate receptor was found, abort voxelmanip transaction.
if (mesecon.turnoff(np, rulename)) then
mesecon.vm_commit()
else
mesecon.vm_abort()
end
end
end
end)
function mesecon.receptor_off(pos, rules)
mesecon.queue:add_action(pos, "receptor_off", {rules}, nil, rules)
end
--Services like turnoff receptor on dignode and so on
dofile(minetest.get_modpath("mesecons").."/services.lua");

641
mesecons/internal.lua Normal file
View File

@ -0,0 +1,641 @@
-- Internal.lua - The core of mesecons
--
-- For more practical developer resources see http://mesecons.net/developers.php
--
-- Function overview
-- mesecon.get_effector(nodename) --> Returns the mesecons.effector -specifictation in the nodedef by the nodename
-- mesecon.get_receptor(nodename) --> Returns the mesecons.receptor -specifictation in the nodedef by the nodename
-- mesecon.get_conductor(nodename) --> Returns the mesecons.conductor-specifictation in the nodedef by the nodename
-- mesecon.get_any_inputrules (node) --> Returns the rules of a node if it is a conductor or an effector
-- mesecon.get_any_outputrules (node) --> Returns the rules of a node if it is a conductor or a receptor
-- RECEPTORS
-- mesecon.is_receptor(nodename) --> Returns true if nodename is a receptor
-- mesecon.is_receptor_on(nodename --> Returns true if nodename is an receptor with state = mesecon.state.on
-- mesecon.is_receptor_off(nodename) --> Returns true if nodename is an receptor with state = mesecon.state.off
-- mesecon.receptor_get_rules(node) --> Returns the rules of the receptor (mesecon.rules.default if none specified)
-- EFFECTORS
-- mesecon.is_effector(nodename) --> Returns true if nodename is an effector
-- mesecon.is_effector_on(nodename) --> Returns true if nodename is an effector with nodedef.mesecons.effector.action_off
-- mesecon.is_effector_off(nodename) --> Returns true if nodename is an effector with nodedef.mesecons.effector.action_on
-- mesecon.effector_get_rules(node) --> Returns the input rules of the effector (mesecon.rules.default if none specified)
-- SIGNALS
-- mesecon.activate(pos, node, depth) --> Activates the effector node at the specific pos (calls nodedef.mesecons.effector.action_on), higher depths are executed later
-- mesecon.deactivate(pos, node, depth) --> Deactivates the effector node at the specific pos (calls nodedef.mesecons.effector.action_off), higher depths are executed later
-- mesecon.changesignal(pos, node, rulename, newstate, depth) --> Changes the effector node at the specific pos (calls nodedef.mesecons.effector.action_change), higher depths are executed later
-- CONDUCTORS
-- mesecon.is_conductor(nodename) --> Returns true if nodename is a conductor
-- mesecon.is_conductor_on(node --> Returns true if node is a conductor with state = mesecon.state.on
-- mesecon.is_conductor_off(node) --> Returns true if node is a conductor with state = mesecon.state.off
-- mesecon.get_conductor_on(node_off) --> Returns the onstate nodename of the conductor
-- mesecon.get_conductor_off(node_on) --> Returns the offstate nodename of the conductor
-- mesecon.conductor_get_rules(node) --> Returns the input+output rules of a conductor (mesecon.rules.default if none specified)
-- HIGH-LEVEL Internals
-- mesecon.is_power_on(pos) --> Returns true if pos emits power in any way
-- mesecon.is_power_off(pos) --> Returns true if pos does not emit power in any way
-- mesecon.is_powered(pos) --> Returns bool, spread. bool is true if pos is powered by a receptor, a conductor or an opaque block.
-- spread is true if it is powered AND also transmits its power one block further.
-- RULES ROTATION helpers
-- mesecon.rotate_rules_right(rules)
-- mesecon.rotate_rules_left(rules)
-- mesecon.rotate_rules_up(rules)
-- mesecon.rotate_rules_down(rules)
-- These functions return rules that have been rotated in the specific direction
local equals = vector.equals
local get_node_force = mesecon.get_node_force
local invertRule = mesecon.invertRule
local copy, insert = table.copy, table.insert
local registered_nodes = minetest.registered_nodes
-- General
function mesecon.get_effector(nodename)
if registered_nodes[nodename]
and registered_nodes[nodename].mesecons
and registered_nodes[nodename].mesecons.effector then
return registered_nodes[nodename].mesecons.effector
end
end
function mesecon.get_receptor(nodename)
if registered_nodes[nodename]
and registered_nodes[nodename].mesecons
and registered_nodes[nodename].mesecons.receptor then
return registered_nodes[nodename].mesecons.receptor
end
end
function mesecon.get_conductor(nodename)
if registered_nodes[nodename]
and registered_nodes[nodename].mesecons
and registered_nodes[nodename].mesecons.conductor then
return registered_nodes[nodename].mesecons.conductor
end
end
function mesecon.get_any_outputrules(node)
if not node then return nil end
if mesecon.is_conductor(node.name) then
return mesecon.conductor_get_rules(node)
elseif mesecon.is_receptor(node.name) then
return mesecon.receptor_get_rules(node)
elseif minetest.get_item_group(node.name, "opaque") == 1 then
return mesecon.rules.alldirs
end
end
function mesecon.get_any_inputrules(node)
if not node then return nil end
if mesecon.is_conductor(node.name) then
return mesecon.conductor_get_rules(node)
elseif mesecon.is_effector(node.name) then
return mesecon.effector_get_rules(node)
elseif minetest.get_item_group(node.name, "opaque") == 1 then
return mesecon.rules.alldirs
end
end
function mesecon.get_any_rules(node)
return mesecon.mergetable(mesecon.get_any_inputrules(node) or {},
mesecon.get_any_outputrules(node) or {})
end
-- Receptors
-- Nodes that can power mesecons
local function is_receptor_on(nodename)
local receptor = mesecon.get_receptor(nodename)
if receptor and receptor.state == mesecon.state.on then
return true
end
return false
end
mesecon.is_receptor_on = is_receptor_on
function mesecon.is_receptor_off(nodename)
local receptor = mesecon.get_receptor(nodename)
if receptor and receptor.state == mesecon.state.off then
return true
end
return false
end
function mesecon.is_receptor(nodename)
local receptor = mesecon.get_receptor(nodename)
if receptor then
return true
end
return false
end
local function receptor_get_rules(node)
local receptor = mesecon.get_receptor(node.name)
if receptor then
local rules = receptor.rules
if type(rules) == "function" then
return rules(node)
elseif rules then
return rules
end
end
return mesecon.rules.default
end
mesecon.receptor_get_rules = receptor_get_rules
-- Effectors
-- Nodes that can be powered by mesecons
function mesecon.is_effector_on(nodename)
local effector = mesecon.get_effector(nodename)
if effector and effector.action_off then
return true
end
return false
end
function mesecon.is_effector_off(nodename)
local effector = mesecon.get_effector(nodename)
if effector and effector.action_on then
return true
end
return false
end
function mesecon.is_effector(nodename)
local effector = mesecon.get_effector(nodename)
if effector then
return true
end
return false
end
function mesecon.effector_get_rules(node)
local effector = mesecon.get_effector(node.name)
if effector then
local rules = effector.rules
if type(rules) == "function" then
return rules(node)
elseif rules then
return rules
end
end
return mesecon.rules.default
end
-- #######################
-- # Signals (effectors) #
-- #######################
-- Activation:
mesecon.queue:add_function("activate", function (pos, rulename)
local node = get_node_force(pos)
if not node then return end
local effector = mesecon.get_effector(node.name)
if effector and effector.action_on then
effector.action_on(pos, node, rulename)
end
end)
function mesecon.activate(pos, node, rulename, depth)
if rulename == nil then
for _,rule in pairs(mesecon.effector_get_rules(node)) do
mesecon.activate(pos, node, rule, depth + 1)
end
return
end
mesecon.queue:add_action(pos, "activate", {rulename}, nil, rulename, 1 / depth)
end
-- Deactivation
mesecon.queue:add_function("deactivate", function (pos, rulename)
local node = get_node_force(pos)
if not node then return end
local effector = mesecon.get_effector(node.name)
if effector and effector.action_off then
effector.action_off(pos, node, rulename)
end
end)
function mesecon.deactivate(pos, node, rulename, depth)
if rulename == nil then
for _,rule in pairs(mesecon.effector_get_rules(node)) do
mesecon.deactivate(pos, node, rule, depth + 1)
end
return
end
mesecon.queue:add_action(pos, "deactivate", {rulename}, nil, rulename, 1 / depth)
end
-- Change
mesecon.queue:add_function("change", function (pos, rulename, changetype)
local node = get_node_force(pos)
if not node then return end
local effector = mesecon.get_effector(node.name)
if effector and effector.action_change then
effector.action_change(pos, node, rulename, changetype)
end
end)
function mesecon.changesignal(pos, node, rulename, newstate, depth)
if rulename == nil then
for _,rule in pairs(mesecon.effector_get_rules(node)) do
mesecon.changesignal(pos, node, rule, newstate, depth + 1)
end
return
end
-- Include "change" in overwritecheck so that it cannot be overwritten
-- by "active" / "deactivate" that will be called upon the node at the same time.
local overwritecheck = {"change", rulename}
mesecon.queue:add_action(pos, "change", {rulename, newstate}, nil, overwritecheck, 1 / depth)
end
-- Conductors
function mesecon.is_conductor_on(node, rulename)
if not node then return false end
local conductor = mesecon.get_conductor(node.name)
if conductor then
if conductor.state then
return conductor.state == mesecon.state.on
end
if conductor.states then
if not rulename then
return mesecon.getstate(node.name, conductor.states) ~= 1
end
local bit = mesecon.rule2bit(rulename, mesecon.conductor_get_rules(node))
local binstate = mesecon.getbinstate(node.name, conductor.states)
return mesecon.get_bit(binstate, bit)
end
end
return false
end
function mesecon.is_conductor_off(node, rulename)
if not node then return false end
local conductor = mesecon.get_conductor(node.name)
if conductor then
if conductor.state then
return conductor.state == mesecon.state.off
end
if conductor.states then
if not rulename then
return mesecon.getstate(node.name, conductor.states) == 1
end
local bit = mesecon.rule2bit(rulename, mesecon.conductor_get_rules(node))
local binstate = mesecon.getbinstate(node.name, conductor.states)
return not mesecon.get_bit(binstate, bit)
end
end
return false
end
function mesecon.is_conductor(nodename)
local conductor = mesecon.get_conductor(nodename)
if conductor then
return true
end
return false
end
function mesecon.get_conductor_on(node_off, rulename)
local conductor = mesecon.get_conductor(node_off.name)
if conductor then
if conductor.onstate then
return conductor.onstate
end
if conductor.states then
local bit = mesecon.rule2bit(rulename, mesecon.conductor_get_rules(node_off))
local binstate = mesecon.getbinstate(node_off.name, conductor.states)
binstate = mesecon.set_bit(binstate, bit, "1")
return conductor.states[tonumber(binstate,2)+1]
end
end
return conductor.offstate
end
function mesecon.get_conductor_off(node_on, rulename)
local conductor = mesecon.get_conductor(node_on.name)
if conductor then
if conductor.offstate then
return conductor.offstate
end
if conductor.states then
local bit = mesecon.rule2bit(rulename, mesecon.conductor_get_rules(node_on))
local binstate = mesecon.getbinstate(node_on.name, conductor.states)
binstate = mesecon.set_bit(binstate, bit, "0")
return conductor.states[tonumber(binstate,2)+1]
end
end
return conductor.onstate
end
function mesecon.conductor_get_rules(node)
local conductor = mesecon.get_conductor(node.name)
if conductor then
local rules = conductor.rules
if type(rules) == "function" then
return rules(node)
elseif rules then
return rules
end
end
return mesecon.rules.default
end
-- some more general high-level stuff
function mesecon.is_power_on(pos, rulename)
local node = get_node_force(pos)
if node and (mesecon.is_conductor_on(node, rulename) or is_receptor_on(node.name)) then
return true
end
return false
end
function mesecon.is_power_off(pos, rulename)
local node = get_node_force(pos)
if node and (mesecon.is_conductor_off(node, rulename) or mesecon.is_receptor_off(node.name)) then
return true
end
return false
end
-- Turn off an equipotential section starting at `pos`, which outputs in the direction of `link`.
-- Breadth-first search. Map is abstracted away in a voxelmanip.
-- Follow all all conductor paths replacing conductors that were already
-- looked at, activating / changing all effectors along the way.
function mesecon.turnon(pos, link)
local frontiers = {{pos = pos, link = link}}
local depth = 1
while frontiers[1] do
local f = table.remove(frontiers, 1)
local node = get_node_force(f.pos)
if node and mesecon.is_conductor_off(node, f.link) then
local rules = mesecon.conductor_get_rules(node)
-- Call turnon on neighbors
for _, r in pairs(mesecon.rule2meta(f.link, rules)) do
local np = vector.add(f.pos, r)
for _, l in pairs(mesecon.rules_link_rule_all(f.pos, r)) do
insert(frontiers, {pos = np, link = l})
end
end
mesecon.swap_node_force(f.pos, mesecon.get_conductor_on(node, f.link))
elseif mesecon.is_effector(node.name) then
mesecon.changesignal(f.pos, node, f.link, mesecon.state.on, depth)
if mesecon.is_effector_off(node.name) then
mesecon.activate(f.pos, node, f.link, depth)
end
end
if node and f.link.spread and minetest.get_item_group(node.name, "opaque") == 1 then
-- Call turnon on neighbors
-- Warning: A LOT of nodes need to be looked at for this to work
for _, r in pairs(mesecon.rule2meta(f.link, mesecon.rules.mcl_alldirs_spread)) do
local np = vector.add(f.pos, r)
for _, l in pairs(mesecon.rules_link_rule_all(f.pos, r)) do
local nlink = copy(l)
nlink.spread = false
insert(frontiers, {pos = np, link = nlink})
end
end
end
depth = depth + 1
end
end
-- Turn off an equipotential section starting at `pos`, which outputs in the direction of `link`.
-- Breadth-first search. Map is abstracted away in a voxelmanip.
-- Follow all all conductor paths replacing conductors that were already
-- looked at, deactivating / changing all effectors along the way.
-- In case an onstate receptor is discovered, abort the process by returning false, which will
-- cause `receptor_off` to discard all changes made in the voxelmanip.
-- Contrary to turnon, turnoff has to cache all change and deactivate signals so that they will only
-- be called in the very end when we can be sure that no conductor was found along the path.
--
-- Signal table entry structure:
-- {
-- pos = position of effector,
-- node = node descriptor (name, param1 and param2),
-- link = link the effector is connected to,
-- depth = indicates order in which signals wire fired, higher is later
-- }
function mesecon.turnoff(pos, link)
local frontiers = {{pos = pos, link = link}}
local signals = {}
local depth = 1
while frontiers[1] do
local f = table.remove(frontiers, 1)
local node = get_node_force(f.pos)
if node and mesecon.is_conductor_on(node, f.link) then
local rules = mesecon.conductor_get_rules(node)
for _, r in pairs(mesecon.rule2meta(f.link, rules)) do
local np = vector.add(f.pos, r)
-- Check if an onstate receptor is connected. If that is the case,
-- abort this turnoff process by returning false. `receptor_off` will
-- discard all the changes that we made in the voxelmanip:
for _, l in pairs(mesecon.rules_link_rule_all_inverted(f.pos, r)) do
if is_receptor_on(get_node_force(np).name) then
return false
end
end
-- Call turnoff on neighbors
for _, l in pairs(mesecon.rules_link_rule_all(f.pos, r)) do
insert(frontiers, {pos = np, link = l})
end
end
mesecon.swap_node_force(f.pos, mesecon.get_conductor_off(node, f.link))
elseif mesecon.is_effector(node.name) then
insert(signals, {
pos = f.pos,
node = node,
link = f.link,
depth = depth
})
end
if node and f.link.spread and minetest.get_item_group(node.name, "opaque") == 1 then
-- Call turnoff on neighbors
-- Warning: A LOT of nodes need to be looked at for this to work
local fpos = f.pos
for _, r in pairs(mesecon.rule2meta(f.link, mesecon.rules.mcl_alldirs_spread)) do
local np = {x=fpos.x+r.x, y=fpos.y+r.y, z=fpos.z+r.z}
local n = get_node_force(np)
if n and is_receptor_on(n.name) then
local receptorrules = receptor_get_rules(n)
for _, rr in pairs(receptorrules) do
if rr.spread and equals(invertRule(rr), r) then
return false
end
end
end
for _, l in pairs(mesecon.rules_link_rule_all(fpos, r)) do
local nlink = copy(l)
nlink.spread = false
insert(frontiers, {pos = np, link = nlink})
end
end
end
depth = depth + 1
end
for _, sig in pairs(signals) do
mesecon.changesignal(sig.pos, sig.node, sig.link, mesecon.state.off, sig.depth)
if mesecon.is_effector_on(sig.node.name) and not mesecon.is_powered(sig.pos) then
mesecon.deactivate(sig.pos, sig.node, sig.link, sig.depth)
end
end
return true
end
-- Get all linking inputrules of inputnode (effector or conductor) that is connected to
-- outputnode (receptor or conductor) at position `output` and has an output in direction `rule`
function mesecon.rules_link_rule_all(output, rule)
local input = vector.add(output, rule)
local inputnode = get_node_force(input)
local inputrules = mesecon.get_any_inputrules(inputnode)
if not inputrules then
return {}
end
local rules = {}
for _, inputrule in pairs(mesecon.flattenrules(inputrules)) do
-- Check if input accepts from output
if equals(vector.add(input, inputrule), output) then
local newrule = copy(inputrule)
newrule.spread = rule.spread
insert(rules, newrule)
end
end
return rules
end
-- Get all linking outputnodes of outputnode (receptor or conductor) that is connected to
-- inputnode (effector or conductor) at position `input` and has an input in direction `rule`
function mesecon.rules_link_rule_all_inverted(input, rule)
local output = vector.add(input, rule)
local outputnode = get_node_force(output)
local outputrules = mesecon.get_any_outputrules(outputnode)
if not outputrules then
return {}
end
local rules = {}
for _, outputrule in pairs(mesecon.flattenrules(outputrules)) do
if equals(vector.add(output, outputrule), input) then
local newrule = copy(outputrule)
newrule = invertRule(newrule)
newrule.spread = rule.spread
insert(rules, newrule)
end
end
return rules
end
function mesecon.is_powered(pos, rule, depth, sourcepos, home_pos)
if depth == nil then depth = 0 end
if depth > 1 then
return false, false
end
local node = get_node_force(pos)
local rules = mesecon.get_any_inputrules(node)
if not rules then
return false, false
end
if not home_pos then
home_pos = pos
end
-- List of nodes that send out power to pos
if sourcepos == nil then
sourcepos = {}
end
local function power_walk(pos, home_pos, sourcepos, rulenames, rule, depth)
local spread = false
for _, rname in pairs(rulenames) do
local np = vector.add(pos, rname)
local nn = get_node_force(np)
if (mesecon.is_conductor_on (nn, invertRule(rname))
or is_receptor_on (nn.name)) then
if not equals(home_pos, np) then
local rulez = mesecon.get_any_outputrules(nn)
local spread_tmp = false
for r=1, #rulez do
if equals(invertRule(rname), rulez[r]) then
if rulez[r].spread then
spread_tmp = true
end
end
end
if depth == 0 or spread_tmp then
insert(sourcepos, np)
if spread_tmp then
spread = true
end
end
end
elseif depth == 0 and minetest.get_item_group(nn.name, "opaque") == 1 then
local more_sourcepos = mesecon.is_powered(np, nil, depth + 1, sourcepos, home_pos)
if more_sourcepos and #more_sourcepos > 0 then
mesecon.mergetable(sourcepos, more_sourcepos)
end
end
end
return sourcepos, spread
end
local spread = false
if not rule then
for _, rule in pairs(mesecon.flattenrules(rules)) do
local spread_temp
local rulenames = mesecon.rules_link_rule_all_inverted(pos, rule)
sourcepos, spread_temp = power_walk(pos, home_pos, sourcepos, rulenames, rule, depth)
if spread_temp then
spread = true
end
end
else
local rulenames = mesecon.rules_link_rule_all_inverted(pos, rule)
sourcepos, spread = power_walk(pos, home_pos, sourcepos, rulenames, rule, depth)
end
-- Return FALSE if not powered, return list of sources if is powered
if (#sourcepos == 0) then
return false, false
else
return sourcepos, spread
end
end

3
mesecons/mod.conf Normal file
View File

@ -0,0 +1,3 @@
name = mesecons
depends = mcl_sounds, mcl_core
optional_depends = doc

110
mesecons/presets.lua Normal file
View File

@ -0,0 +1,110 @@
mesecon.rules = {}
mesecon.state = {}
mesecon.rules.default =
{{x=0, y=0, z=-1},
{x=1, y=0, z=0},
{x=-1, y=0, z=0},
{x=0, y=0, z=1},
{x=0, y=1, z=0},
{x=0, y=-1, z=0},
{x=1, y=1, z=0},
{x=1, y=-1, z=0},
{x=-1, y=1, z=0},
{x=-1, y=-1, z=0},
{x=0, y=1, z=1},
{x=0, y=-1, z=1},
{x=0, y=1, z=-1},
{x=0, y=-1, z=-1}}
mesecon.rules.alldirs =
{{x= 1, y= 0, z= 0},
{x=-1, y= 0, z= 0},
{x= 0, y= 1, z= 0},
{x= 0, y=-1, z= 0},
{x= 0, y= 0, z= 1},
{x= 0, y= 0, z=-1}}
mesecon.rules.pplate =
{{x = 1, y = 0, z = 0},
{x =-1, y = 0, z = 0},
{x = 0, y = 1, z = 0},
{x = 0, y =-1, z = 0, spread = true},
{x = 0, y = 0, z = 1},
{x = 0, y = 0, z =-1}}
mesecon.rules.buttonlike =
{{x = 0, y = 0, z =-1},
{x = 0, y = 0, z = 1},
{x = 0, y =-1, z = 0},
{x = 0, y = 1, z = 0},
{x =-1, y = 0, z = 0},
{x = 1, y = 0, z = 0, spread = true}}
mesecon.rules.floor =
{{x = 1, y = 0, z = 0},
{x =-1, y = 0, z = 0},
{x = 0, y = 1, z = 0},
{x = 0, y =-1, z = 0, spread = true},
{x = 0, y = 0, z = 1},
{x = 0, y = 0, z =-1}}
mesecon.rules.flat =
{{x = 1, y = 0, z = 0},
{x =-1, y = 0, z = 0},
{x = 0, y = 0, z = 1},
{x = 0, y = 0, z =-1}}
-- NOT IN ORIGNAL MESECONS
mesecon.rules.mcl_alldirs_spread =
{{x= 1, y= 0, z= 0, spread = true},
{x=-1, y= 0, z= 0, spread = true},
{x= 0, y= 1, z= 0, spread = true},
{x= 0, y=-1, z= 0, spread = true},
{x= 0, y= 0, z= 1, spread = true},
{x= 0, y= 0, z=-1, spread = true}}
-- END OF UNOFFICIAL RULES
local rules_buttonlike = {
xp = mesecon.rules.buttonlike,
xn = mesecon.rotate_rules_right(mesecon.rotate_rules_right(mesecon.rules.buttonlike)),
yp = mesecon.rotate_rules_down(mesecon.rules.buttonlike),
yn = mesecon.rotate_rules_up(mesecon.rules.buttonlike),
zp = mesecon.rotate_rules_right(mesecon.rules.buttonlike),
zn = mesecon.rotate_rules_left(mesecon.rules.buttonlike),
}
local rules_wallmounted = {
xp = mesecon.rotate_rules_down(mesecon.rules.floor),
xn = mesecon.rotate_rules_up(mesecon.rules.floor),
yp = mesecon.rotate_rules_up(mesecon.rotate_rules_up(mesecon.rules.floor)),
yn = mesecon.rules.floor,
zp = mesecon.rotate_rules_left(mesecon.rotate_rules_up(mesecon.rules.floor)),
zn = mesecon.rotate_rules_right(mesecon.rotate_rules_up(mesecon.rules.floor)),
}
local function rules_from_dir(ruleset, dir)
if dir.x == 1 then return ruleset.xp end
if dir.y == 1 then return ruleset.yp end
if dir.z == 1 then return ruleset.zp end
if dir.x == -1 then return ruleset.xn end
if dir.y == -1 then return ruleset.yn end
if dir.z == -1 then return ruleset.zn end
end
function mesecon.rules.buttonlike_get(node)
local dir = minetest.facedir_to_dir(node.param2)
return rules_from_dir(rules_buttonlike, dir)
end
function mesecon.rules.wallmounted_get(node)
local dir = minetest.wallmounted_to_dir(node.param2)
return rules_from_dir(rules_wallmounted, dir)
end
mesecon.state.on = "on"
mesecon.state.off = "off"

168
mesecons/services.lua Normal file
View File

@ -0,0 +1,168 @@
-- Dig and place services
function mesecon.on_placenode(pos, node)
mesecon.execute_autoconnect_hooks_now(pos, node)
-- Receptors: Send on signal when active
if mesecon.is_receptor_on(node.name) then
mesecon.receptor_on(pos, mesecon.receptor_get_rules(node))
end
-- Conductors: Send turnon signal when powered or replace by respective offstate conductor
-- if placed conductor is an onstate one
if mesecon.is_conductor(node.name) then
local sources = mesecon.is_powered(pos)
if sources then
-- also call receptor_on if itself is powered already, so that neighboring
-- conductors will be activated (when pushing an on-conductor with a piston)
for _, s in ipairs(sources) do
local rule = vector.subtract(pos, s)
mesecon.turnon(pos, rule)
end
mesecon.receptor_on (pos, mesecon.conductor_get_rules(node))
elseif mesecon.is_conductor_on(node) then
minetest.swap_node(pos, {name = mesecon.get_conductor_off(node)})
end
end
-- Effectors: Send changesignal and activate or deactivate
if mesecon.is_effector(node.name) then
local powered_rules = {}
local unpowered_rules = {}
-- for each input rule, check if powered
for _, r in ipairs(mesecon.effector_get_rules(node)) do
local powered = mesecon.is_powered(pos, r)
if powered then table.insert(powered_rules, r)
else table.insert(unpowered_rules, r) end
local state = powered and mesecon.state.on or mesecon.state.off
mesecon.changesignal(pos, node, r, state, 1)
end
if (#powered_rules > 0) then
for _, r in ipairs(powered_rules) do
mesecon.activate(pos, node, r, 1)
end
else
for _, r in ipairs(unpowered_rules) do
mesecon.deactivate(pos, node, r, 1)
end
end
end
if minetest.get_item_group(node.name, "opaque") == 1 then
local neighbors = mesecon.mcl_get_neighbors(pos)
local is_powered, direct_source = mesecon.is_powered(pos)
if is_powered and direct_source then
for n=1, #neighbors do
local npos = neighbors[n].pos
local nnode = minetest.get_node(npos)
if mesecon.is_conductor_off(nnode) then
mesecon.receptor_on(npos, mesecon.conductor_get_rules(nnode))
-- Redstone torch is a special case and must be ignored
elseif mesecon.is_effector_on(nnode.name) and minetest.get_item_group(nnode.name, "redstone_torch") == 0 then
mesecon.changesignal(npos, nnode, neighbors[n].link, mesecon.state.on, 1)
mesecon.activate(npos, nnode, neighbors[n].link, 1)
end
end
end
end
end
function mesecon.on_dignode(pos, node)
if mesecon.is_conductor_on(node) then
mesecon.receptor_off(pos, mesecon.conductor_get_rules(node))
elseif mesecon.is_receptor_on(node.name) then
mesecon.receptor_off(pos, mesecon.receptor_get_rules(node))
end
if minetest.get_item_group(node.name, "opaque") == 1 then
--local sources = mesecon.is_powered(pos)
local neighbors = mesecon.mcl_get_neighbors(pos)
for n=1, #neighbors do
local npos = neighbors[n].pos
local nlink = neighbors[n].link
local nnode = minetest.get_node(npos)
if mesecon.is_conductor_on(nnode) then
mesecon.receptor_off(npos, mesecon.conductor_get_rules(nnode))
-- Disable neighbor effectors unless they are in a special ignore group
elseif mesecon.is_effector_on(nnode.name) and mesecon.is_powered(npos) == false and minetest.get_item_group(nnode.name, "mesecon_ignore_opaque_dig") == 0 then
mesecon.changesignal(npos, nnode, nlink, mesecon.state.off, 1)
mesecon.deactivate(npos, nnode, nlink, 1)
end
end
end
mesecon.execute_autoconnect_hooks_queue(pos, node)
end
function mesecon.on_blastnode(pos, node)
local node = minetest.get_node(pos)
minetest.remove_node(pos)
mesecon.on_dignode(pos, node)
return minetest.get_node_drops(node.name, "")
end
minetest.register_on_placenode(mesecon.on_placenode)
minetest.register_on_dignode(mesecon.on_dignode)
-- Overheating service for fast circuits
local OVERHEAT_MAX = mesecon.setting("overheat_max", 8)
local COOLDOWN_TIME = mesecon.setting("cooldown_time", 3.0)
local COOLDOWN_STEP = mesecon.setting("cooldown_granularity", 0.5)
local COOLDOWN_MULTIPLIER = OVERHEAT_MAX / COOLDOWN_TIME
local cooldown_timer = 0.0
local object_heat = {}
-- returns true if heat is too high
function mesecon.do_overheat(pos)
local id = minetest.hash_node_position(pos)
local heat = (object_heat[id] or 0) + 1
object_heat[id] = heat
if heat >= OVERHEAT_MAX then
minetest.log("action", "Node overheats at " .. minetest.pos_to_string(pos))
object_heat[id] = nil
return true
end
return false
end
function mesecon.do_cooldown(pos)
local id = minetest.hash_node_position(pos)
object_heat[id] = nil
end
function mesecon.get_heat(pos)
local id = minetest.hash_node_position(pos)
return object_heat[id] or 0
end
function mesecon.move_hot_nodes(moved_nodes)
local new_heat = {}
for _, n in ipairs(moved_nodes) do
local old_id = minetest.hash_node_position(n.oldpos)
local new_id = minetest.hash_node_position(n.pos)
new_heat[new_id] = object_heat[old_id]
object_heat[old_id] = nil
end
for id, heat in pairs(new_heat) do
object_heat[id] = heat
end
end
local function global_cooldown(dtime)
cooldown_timer = cooldown_timer + dtime
if cooldown_timer < COOLDOWN_STEP then
return -- don't overload the CPU
end
local cooldown = COOLDOWN_MULTIPLIER * cooldown_timer
cooldown_timer = 0
for id, heat in pairs(object_heat) do
heat = heat - cooldown
if heat <= 0 then
object_heat[id] = nil -- free some RAM
else
object_heat[id] = heat
end
end
end
minetest.register_globalstep(global_cooldown)

15
mesecons/settings.lua Normal file
View File

@ -0,0 +1,15 @@
-- SETTINGS
function mesecon.setting(setting, default)
if type(default) == "boolean" then
local read = minetest.settings:get_bool("mesecon."..setting)
if read == nil then
return default
else
return read
end
elseif type(default) == "string" then
return minetest.settings:get("mesecon."..setting) or default
elseif type(default) == "number" then
return tonumber(minetest.settings:get("mesecon."..setting) or default)
end
end

461
mesecons/util.lua Normal file
View File

@ -0,0 +1,461 @@
function mesecon.move_node(pos, newpos)
local node = minetest.get_node(pos)
local meta = minetest.get_meta(pos):to_table()
minetest.remove_node(pos)
minetest.set_node(newpos, node)
minetest.get_meta(pos):from_table(meta)
end
--Rules rotation Functions:
function mesecon.rotate_rules_right(rules)
local nr = {}
for i, rule in ipairs(rules) do
table.insert(nr, {
x = -rule.z,
y = rule.y,
z = rule.x,
name = rule.name,
spread = rule.spread,})
end
return nr
end
function mesecon.rotate_rules_left(rules)
local nr = {}
for i, rule in ipairs(rules) do
table.insert(nr, {
x = rule.z,
y = rule.y,
z = -rule.x,
name = rule.name,
spread = rule.spread,})
end
return nr
end
function mesecon.rotate_rules_down(rules)
local nr = {}
for i, rule in ipairs(rules) do
table.insert(nr, {
x = -rule.y,
y = rule.x,
z = rule.z,
name = rule.name,
spread = rule.spread,})
end
return nr
end
function mesecon.rotate_rules_up(rules)
local nr = {}
for i, rule in ipairs(rules) do
table.insert(nr, {
x = rule.y,
y = -rule.x,
z = rule.z,
name = rule.name,
spread = rule.spread,})
end
return nr
end
function mesecon.flattenrules(allrules)
--[[
{
{
{xyz},
{xyz},
},
{
{xyz},
{xyz},
},
}
--]]
if allrules[1] and
allrules[1].x then
return allrules
end
local shallowrules = {}
for _, metarule in ipairs( allrules) do
for _, rule in ipairs(metarule ) do
table.insert(shallowrules, rule)
end
end
return shallowrules
--[[
{
{xyz},
{xyz},
{xyz},
{xyz},
}
--]]
end
function mesecon.rule2bit(findrule, allrules)
--get the bit of the metarule the rule is in, or bit 1
if (allrules[1] and
allrules[1].x) or
not findrule then
return 1
end
for m,metarule in ipairs( allrules) do
for _, rule in ipairs(metarule ) do
if vector.equals(findrule, rule) then
return m
end
end
end
end
function mesecon.rule2metaindex(findrule, allrules)
--get the metarule the rule is in, or allrules
if allrules[1].x then
return nil
end
if not(findrule) then
return mesecon.flattenrules(allrules)
end
for m, metarule in ipairs( allrules) do
for _, rule in ipairs(metarule ) do
if vector.equals(findrule, rule) then
return m
end
end
end
end
function mesecon.rule2meta(findrule, allrules)
if #allrules == 0 then return {} end
local index = mesecon.rule2metaindex(findrule, allrules)
if index == nil then
if allrules[1].x then
return allrules
else
return {}
end
end
return allrules[index]
end
-- Returns the 6 immediate neighbors of pos
-- (nodes which touch the sides of pos).
-- NOT PART OF ORIGINAL MESECONS!
function mesecon.mcl_get_neighbors(pos)
local r = mesecon.rules.alldirs
local e = {}
for i=1, #r do
table.insert(e, { pos = vector.add(pos, r[i]), link = r[i] })
end
return e
end
function mesecon.dec2bin(n)
local x, y = math.floor(n / 2), n % 2
if (n > 1) then
return mesecon.dec2bin(x)..y
else
return ""..y
end
end
function mesecon.getstate(nodename, states)
for state, name in ipairs(states) do
if name == nodename then
return state
end
end
error(nodename.." doesn't mention itself in "..dump(states))
end
function mesecon.getbinstate(nodename, states)
return mesecon.dec2bin(mesecon.getstate(nodename, states)-1)
end
function mesecon.get_bit(binary,bit)
bit = bit or 1
local c = binary:len()-(bit-1)
return binary:sub(c,c) == "1"
end
function mesecon.set_bit(binary,bit,value)
if value == "1" then
if not mesecon.get_bit(binary,bit) then
return mesecon.dec2bin(tonumber(binary,2)+math.pow(2,bit-1))
end
elseif value == "0" then
if mesecon.get_bit(binary,bit) then
return mesecon.dec2bin(tonumber(binary,2)-math.pow(2,bit-1))
end
end
return binary
end
function mesecon.invertRule(r)
local spread = r.spread
r = vector.multiply(r, -1)
if spread then
r.spread = true
end
return r
end
function mesecon.tablecopy(table) -- deep table copy
if type(table) ~= "table" then return table end -- no need to copy
local newtable = {}
for idx, item in pairs(table) do
if type(item) == "table" then
newtable[idx] = mesecon.tablecopy(item)
else
newtable[idx] = item
end
end
return newtable
end
function mesecon.cmpAny(t1, t2)
if type(t1) ~= type(t2) then return false end
if type(t1) ~= "table" and type(t2) ~= "table" then return t1 == t2 end
for i, e in pairs(t1) do
if not mesecon.cmpAny(e, t2[i]) then return false end
end
return true
end
-- does not overwrite values; number keys (ipairs) are appended, not overwritten
function mesecon.mergetable(source, dest)
local rval = mesecon.tablecopy(dest)
for k, v in pairs(source) do
rval[k] = dest[k] or mesecon.tablecopy(v)
end
for i, v in ipairs(source) do
table.insert(rval, mesecon.tablecopy(v))
end
return rval
end
function mesecon.register_node(name, spec_common, spec_off, spec_on)
spec_common.drop = spec_common.drop or name .. "_off"
spec_common.on_blast = spec_common.on_blast or mesecon.on_blastnode
spec_common.__mesecon_basename = name
spec_on.__mesecon_state = "on"
spec_off.__mesecon_state = "off"
spec_on = mesecon.mergetable(spec_common, spec_on);
spec_off = mesecon.mergetable(spec_common, spec_off);
minetest.register_node(name .. "_on", spec_on)
minetest.register_node(name .. "_off", spec_off)
end
-- swap onstate and offstate nodes, returns new state
function mesecon.flipstate(pos, node)
local nodedef = minetest.registered_nodes[node.name]
local newstate
if (nodedef.__mesecon_state == "on") then newstate = "off" end
if (nodedef.__mesecon_state == "off") then newstate = "on" end
minetest.swap_node(pos, {name = nodedef.__mesecon_basename .. "_" .. newstate,
param2 = node.param2})
return newstate
end
-- File writing / reading utilities
local wpath = minetest.get_worldpath()
function mesecon.file2table(filename)
local f = io.open(wpath..DIR_DELIM..filename, "r")
if f == nil then return {} end
local t = f:read("*all")
f:close()
if t == "" or t == nil then return {} end
return minetest.deserialize(t)
end
function mesecon.table2file(filename, table)
local f = io.open(wpath..DIR_DELIM..filename, "w")
f:write(minetest.serialize(table))
f:close()
end
-- Block position "hashing" (convert to integer) functions for voxelmanip cache
local BLOCKSIZE = 16
-- convert node position --> block hash
local function hash_blockpos(pos)
return minetest.hash_node_position({
x = math.floor(pos.x/BLOCKSIZE),
y = math.floor(pos.y/BLOCKSIZE),
z = math.floor(pos.z/BLOCKSIZE)
})
end
-- Maps from a hashed mapblock position (as returned by hash_blockpos) to a
-- table.
--
-- Contents of the table are:
-- “vm” → the VoxelManipulator
-- “va” → the VoxelArea
-- “data” → the data array
-- “param1” → the param1 array
-- “param2” → the param2 array
-- “dirty” → true if data has been modified
--
-- Nil if no VM-based transaction is in progress.
local vm_cache = nil
-- Starts a VoxelManipulator-based transaction.
--
-- During a VM transaction, calls to vm_get_node and vm_swap_node operate on a
-- cached copy of the world loaded via VoxelManipulators. That cache can later
-- be committed to the real map by means of vm_commit or discarded by means of
-- vm_abort.
function mesecon.vm_begin()
vm_cache = {}
end
-- Finishes a VoxelManipulator-based transaction, freeing the VMs and map data
-- and writing back any modified areas.
function mesecon.vm_commit()
for hash, tbl in pairs(vm_cache) do
if tbl.dirty then
local vm = tbl.vm
vm:set_data(tbl.data)
vm:write_to_map()
vm:update_map()
end
end
vm_cache = nil
end
-- Finishes a VoxelManipulator-based transaction, freeing the VMs and throwing
-- away any modified areas.
function mesecon.vm_abort()
vm_cache = nil
end
-- Gets the cache entry covering a position, populating it if necessary.
local function vm_get_or_create_entry(pos)
local hash = hash_blockpos(pos)
local tbl = vm_cache[hash]
if not tbl then
local vm = minetest.get_voxel_manip(pos, pos)
local min_pos, max_pos = vm:get_emerged_area()
local va = VoxelArea:new{MinEdge = min_pos, MaxEdge = max_pos}
tbl = {vm = vm, va = va, data = vm:get_data(), param1 = vm:get_light_data(), param2 = vm:get_param2_data(), dirty = false}
vm_cache[hash] = tbl
end
return tbl
end
-- Gets the node at a given position during a VoxelManipulator-based
-- transaction.
function mesecon.vm_get_node(pos)
local tbl = vm_get_or_create_entry(pos)
local index = tbl.va:indexp(pos)
local node_value = tbl.data[index]
if node_value == minetest.CONTENT_IGNORE then
return nil
else
local node_param1 = tbl.param1[index]
local node_param2 = tbl.param2[index]
return {name = minetest.get_name_from_content_id(node_value), param1 = node_param1, param2 = node_param2}
end
end
-- Sets a nodes name during a VoxelManipulator-based transaction.
--
-- Existing param1, param2, and metadata are left alone.
function mesecon.vm_swap_node(pos, name)
local tbl = vm_get_or_create_entry(pos)
local index = tbl.va:indexp(pos)
tbl.data[index] = minetest.get_content_id(name)
tbl.dirty = true
end
-- Gets the node at a given position, regardless of whether it is loaded or
-- not, respecting a transaction if one is in progress.
--
-- Outside a VM transaction, if the mapblock is not loaded, it is pulled into
-- the servers main map data cache and then accessed from there.
--
-- Inside a VM transaction, the transactions VM cache is used.
function mesecon.get_node_force(pos)
if vm_cache then
return mesecon.vm_get_node(pos)
else
local node = minetest.get_node_or_nil(pos)
if node == nil then
-- Node is not currently loaded; use a VoxelManipulator to prime
-- the mapblock cache and try again.
minetest.get_voxel_manip(pos, pos)
node = minetest.get_node_or_nil(pos)
end
return node
end
end
-- Swaps the node at a given position, regardless of whether it is loaded or
-- not, respecting a transaction if one is in progress.
--
-- Outside a VM transaction, if the mapblock is not loaded, it is pulled into
-- the servers main map data cache and then accessed from there.
--
-- Inside a VM transaction, the transactions VM cache is used.
--
-- This function can only be used to change the nodes name, not its parameters
-- or metadata.
function mesecon.swap_node_force(pos, name)
if vm_cache then
return mesecon.vm_swap_node(pos, name)
else
-- This serves to both ensure the mapblock is loaded and also hand us
-- the old node table so we can preserve param2.
local node = mesecon.get_node_force(pos)
node.name = name
minetest.swap_node(pos, node)
end
end
-- Autoconnect Hooks
-- Nodes like conductors may change their appearance and their connection rules
-- right after being placed or after being dug, e.g. the default wires use this
-- to automatically connect to linking nodes after placement.
-- After placement, the update function will be executed immediately so that the
-- possibly changed rules can be taken into account when recalculating the circuit.
-- After digging, the update function will be queued and executed after
-- recalculating the circuit. The update function must take care of updating the
-- node at the given position itself, but also all of the other nodes the given
-- position may have (had) a linking connection to.
mesecon.autoconnect_hooks = {}
-- name: A unique name for the hook, e.g. "foowire". Used to name the actionqueue function.
-- fct: The update function with parameters function(pos, node)
function mesecon.register_autoconnect_hook(name, fct)
mesecon.autoconnect_hooks[name] = fct
mesecon.queue:add_function("autoconnect_hook_"..name, fct)
end
function mesecon.execute_autoconnect_hooks_now(pos, node)
for _, fct in pairs(mesecon.autoconnect_hooks) do
fct(pos, node)
end
end
function mesecon.execute_autoconnect_hooks_queue(pos, node)
for name in pairs(mesecon.autoconnect_hooks) do
mesecon.queue:add_action(pos, "autoconnect_hook_"..name, {node})
end
end

37
mesecons_alias/init.lua Normal file
View File

@ -0,0 +1,37 @@
-- This file registers aliases for the /give /giveme commands.
minetest.register_alias("mesecons:mesecon", "mesecons:wire_00000000_off")
minetest.register_alias("mesecons:object_detector", "mesecons_detector:object_detector_off")
minetest.register_alias("mesecons:wireless_inverter", "mesecons_wireless:wireless_inverter_on")
minetest.register_alias("mesecons:wireless_receiver", "mesecons_wireless:wireless_receiver_off")
minetest.register_alias("mesecons:wireless_transmitter", "mesecons_wireless:wireless_transmitter_off")
minetest.register_alias("mesecons:switch", "mesecons_switch:mesecon_switch_off")
minetest.register_alias("mesecons:button", "mesecons_button:button_off")
minetest.register_alias("mesecons:piston", "mesecons_pistons:piston_normal_off")
minetest.register_alias("mesecons:mesecon_torch", "mesecons_torch:mesecon_torch_on")
minetest.register_alias("mesecons:torch", "mesecons_torch:mesecon_torch_on")
minetest.register_alias("mesecons:pressure_plate_stone", "mesecons_pressureplates:pressure_plate_stone_off")
minetest.register_alias("mesecons:pressure_plate_wood", "mesecons_pressureplates:pressure_plate_wood_off")
minetest.register_alias("mesecons:pressure_plate_birchwood", "mesecons_pressureplates:pressure_plate_birchwood_off")
minetest.register_alias("mesecons:pressure_plate_acaciawood", "mesecons_pressureplates:pressure_plate_acaciawood_off")
minetest.register_alias("mesecons:pressure_plate_darkwood", "mesecons_pressureplates:pressure_plate_darkwood_off")
minetest.register_alias("mesecons:pressure_plate_sprucewood", "mesecons_pressureplates:pressure_plate_sprucewood_off")
minetest.register_alias("mesecons:pressure_plate_junglewood", "mesecons_pressureplates:pressure_plate_junglewood_off")
minetest.register_alias("mesecons:mesecon_socket", "mesecons_temperest:mesecon_socket_off")
minetest.register_alias("mesecons:mesecon_inverter", "mesecons_temperest:mesecon_inverter_on")
minetest.register_alias("mesecons:noteblock", "mesecons_noteblock:noteblock")
minetest.register_alias("mesecons:delayer", "mesecons_delayer:delayer_off_1")
minetest.register_alias("mesecons:solarpanel", "mesecons_solarpanel:solar_panel_off")
--Backwards compatibility
minetest.register_alias("mesecons:mesecon_off", "mesecons:wire_00000000_off")
minetest.register_alias("mesecons_pistons:piston_sticky", "mesecons_pistons:piston_sticky_on")
minetest.register_alias("mesecons_pistons:piston_normal", "mesecons_pistons:piston_normal_on")
minetest.register_alias("mesecons_pistons:piston_up_normal", "mesecons_pistons:piston_up_normal_on")
minetest.register_alias("mesecons_pistons:piston_down_normal", "mesecons_pistons:piston_down_normal_on")
minetest.register_alias("mesecons_pistons:piston_up_sticky", "mesecons_pistons:piston_up_sticky_on")
minetest.register_alias("mesecons_pistons:piston_down_sticky", "mesecons_pistons:piston_down_sticky_on")
--MineClone 2 specials
minetest.register_alias("mesecons_materials:glue", "mcl_mobitems:slimeball")

2
mesecons_alias/mod.conf Normal file
View File

@ -0,0 +1,2 @@
name = mesecons_alias
depends = mesecons

16
mesecons_button/README.md Normal file
View File

@ -0,0 +1,16 @@
Mesecons button mod.
This mod adds the buttons for MineClone 2.
MEDIA FILE CREDITS:
`mesecons_button_push.ogg`
* Author: junggle <http://jazzy.junggle.net/>
* License: CC BY 3.0 <http://creativecommons.org/licenses/by/3.0/>
* Original name: `btn121.ogg`, created on January 16th, 2007
* Source: <https://freesound.org/people/junggle/sounds/29301/>
`mesecons_button_push_wood.ogg`
* Author: junggle <http://jazzy.junggle.net/>
* License: (CC BY 3.0 <http://creativecommons.org/licenses/by/3.0/>
* Original name: `btn314.ogg`, created on January 16th, 2007
* Sound file was modified
* Source: <https://freesound.org/people/junggle/sounds/29494/>

252
mesecons_button/init.lua Normal file
View File

@ -0,0 +1,252 @@
-- WALL BUTTON
-- A button that when pressed emits power for a short moment and then turns off again
local S = minetest.get_translator(minetest.get_current_modname())
local button_sounds = {} -- remember button push sounds
local button_get_output_rules = mesecon.rules.wallmounted_get
local boxes_off = {
type = "wallmounted",
wall_side = { -8/16, -2/16, -4/16, -6/16, 2/16, 4/16 },
wall_bottom = { -4/16, -8/16, -2/16, 4/16, -6/16, 2/16 },
wall_top = { -4/16, 6/16, -2/16, 4/16, 8/16, 2/16 },
}
local boxes_on = {
type = "wallmounted",
wall_side = { -8/16, -2/16, -4/16, -7/16, 2/16, 4/16 },
wall_bottom = { -4/16, -8/16, -2/16, 4/16, -7/16, 2/16 },
wall_top = { -4/16, 7/16, -2/16, 4/16, 8/16, 2/16 },
}
-- Push the button
function mesecon.push_button(pos, node)
-- No-op if button is already pushed
if mesecon.is_receptor_on(node) then
return
end
local def = minetest.registered_nodes[node.name]
minetest.set_node(pos, {name="mesecons_button:button_"..def._mcl_button_basename.."_on", param2=node.param2})
mesecon.receptor_on(pos, button_get_output_rules(node))
local sfx = button_sounds[node.name]
if sfx then
minetest.sound_play(sfx, {pos=pos}, true)
end
local timer = minetest.get_node_timer(pos)
timer:start(def._mcl_button_timer)
end
local function on_button_place(itemstack, placer, pointed_thing)
if pointed_thing.type ~= "node" then
-- no interaction possible with entities
return itemstack
end
local under = pointed_thing.under
local node = minetest.get_node(under)
local def = minetest.registered_nodes[node.name]
if not def then return end
local groups = def.groups
-- Check special rightclick action of pointed node
if def and def.on_rightclick then
if not placer:get_player_control().sneak then
return def.on_rightclick(under, node, placer, itemstack,
pointed_thing) or itemstack, false
end
end
-- If the pointed node is buildable, let's look at the node *behind* that node
if def.buildable_to then
local dir = vector.subtract(pointed_thing.above, pointed_thing.under)
local actual = vector.subtract(under, dir)
local actualnode = minetest.get_node(actual)
def = minetest.registered_nodes[actualnode.name]
groups = def.groups
end
-- Only allow placement on full-cube solid opaque nodes
if (not groups) or (not groups.solid) or (not groups.opaque) or (def.node_box and def.node_box.type ~= "regular") then
return itemstack
end
local above = pointed_thing.above
local idef = itemstack:get_definition()
local itemstack, success = minetest.item_place_node(itemstack, placer, pointed_thing)
if success then
if idef.sounds and idef.sounds.place then
minetest.sound_play(idef.sounds.place, {pos=above, gain=1}, true)
end
end
return itemstack
end
local buttonuse = S("Use the button to push it.")
function mesecon.register_button(basename, description, texture, recipeitem, sounds, plusgroups, button_timer, push_by_arrow, longdesc, button_sound)
local groups_off = table.copy(plusgroups)
groups_off.attached_node=1
groups_off.dig_by_water=1
groups_off.destroy_by_lava_flow=1
groups_off.dig_by_piston=1
groups_off.button=1 -- button (off)
local groups_on = table.copy(groups_off)
groups_on.not_in_creative_inventory=1
groups_on.button=2 -- button (on)
if not button_sound then
button_sound = "mesecons_button_push"
end
button_sounds["mesecons_button:button_"..basename.."_off"] = button_sound
if push_by_arrow then
groups_off.button_push_by_arrow = 1
groups_on.button_push_by_arrow = 1
end
local tt = S("Provides redstone power when pushed")
tt = tt .. "\n" .. S("Push duration: @1s", string.format("%.1f", button_timer))
if push_by_arrow then
tt = tt .. "\n" .. S("Pushable by arrow")
end
minetest.register_node("mesecons_button:button_"..basename.."_off", {
drawtype = "nodebox",
tiles = {texture},
wield_image = "mesecons_button_wield_mask.png^"..texture.."^mesecons_button_wield_mask.png^[makealpha:255,126,126",
-- FIXME: Use proper 3D inventory image
inventory_image = "mesecons_button_wield_mask.png^"..texture.."^mesecons_button_wield_mask.png^[makealpha:255,126,126",
wield_scale = { x=1, y=1, z=1},
paramtype = "light",
paramtype2 = "wallmounted",
is_ground_content = false,
walkable = false,
sunlight_propagates = true,
node_box = boxes_off,
groups = groups_off,
description = description,
_tt_help = tt,
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = buttonuse,
on_place = on_button_place,
node_placement_prediction = "",
on_rightclick = function(pos, node)
mesecon.push_button(pos, node)
end,
sounds = sounds,
mesecons = {receptor = {
state = mesecon.state.off,
rules = button_get_output_rules,
}},
_mcl_button_basename = basename,
_mcl_button_timer = button_timer,
_mcl_blast_resistance = 0.5,
_mcl_hardness = 0.5,
})
minetest.register_node("mesecons_button:button_"..basename.."_on", {
drawtype = "nodebox",
tiles = {texture},
wield_image = "mesecons_button_wield_mask.png^"..texture.."^mesecons_button_wield_mask.png^[makealpha:255,126,126",
wield_scale = { x=1, y=1, z=0.5},
paramtype = "light",
paramtype2 = "wallmounted",
is_ground_content = false,
walkable = false,
sunlight_propagates = true,
node_box = boxes_on,
groups = groups_on,
drop = "mesecons_button:button_"..basename.."_off",
_doc_items_create_entry = false,
node_placement_prediction = "",
sounds = sounds,
mesecons = {receptor = {
state = mesecon.state.on,
rules = button_get_output_rules
}},
_mcl_button_basename = basename,
_mcl_button_timer = button_timer,
on_timer = function(pos, elapsed)
local node = minetest.get_node(pos)
if node.name=="mesecons_button:button_"..basename.."_on" then --has not been dug
-- Is button pushable by arrow?
if push_by_arrow then
-- If there's an arrow stuck in the button, keep it pressed and check
-- it again later.
local objs = minetest.get_objects_inside_radius(pos, 1)
for o=1, #objs do
local entity = objs[o]:get_luaentity()
if entity and entity.name == "mcl_bows:arrow_entity" then
local timer = minetest.get_node_timer(pos)
timer:start(button_timer)
return
end
end
end
-- Normal operation: Un-press the button
minetest.set_node(pos, {name="mesecons_button:button_"..basename.."_off",param2=node.param2})
minetest.sound_play(button_sound, {pos=pos, pitch=0.9}, true)
mesecon.receptor_off(pos, button_get_output_rules(node))
end
end,
_mcl_blast_resistance = 0.5,
_mcl_hardness = 0.5,
})
minetest.register_craft({
output = "mesecons_button:button_"..basename.."_off",
recipe = {{ recipeitem }},
})
end
mesecon.register_button(
"stone",
S("Stone Button"),
"default_stone.png",
"mcl_core:stone",
mcl_sounds.node_sound_stone_defaults(),
{material_stone=1,handy=1,pickaxey=1},
1,
false,
S("A stone button is a redstone component made out of stone which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1 second."),
"mesecons_button_push")
local woods = {
{ "wood", "mcl_core:wood", "default_wood.png", S("Oak Button") },
{ "acaciawood", "mcl_core:acaciawood", "default_acacia_wood.png", S("Acacia Button") },
{ "birchwood", "mcl_core:birchwood", "mcl_core_planks_birch.png", S("Birch Button") },
{ "darkwood", "mcl_core:darkwood", "mcl_core_planks_big_oak.png", S("Dark Oak Button") },
{ "sprucewood", "mcl_core:sprucewood", "mcl_core_planks_spruce.png", S("Spruce Button") },
{ "junglewood", "mcl_core:junglewood", "default_junglewood.png", S("Jungle Button") },
}
for w=1, #woods do
mesecon.register_button(
woods[w][1],
woods[w][4],
woods[w][3],
woods[w][2],
mcl_sounds.node_sound_wood_defaults(),
{material_wood=1,handy=1,axey=1},
1.5,
true,
S("A wooden button is a redstone component made out of wood which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1.5 seconds. Wooden buttons may also be pushed by arrows."),
"mesecons_button_push_wood")
minetest.register_craft({
type = "fuel",
recipe = "mesecons_button:button_"..woods[w][1].."_off",
burntime = 5,
})
end
-- Add entry aliases for the Help
if minetest.get_modpath("doc") then
doc.add_entry_alias("nodes", "mesecons_button:button_wood_off", "nodes", "mesecons_button:button_wood_on")
doc.add_entry_alias("nodes", "mesecons_button:button_stone_off", "nodes", "mesecons_button:button_stone_on")
end

View File

@ -0,0 +1,14 @@
# textdomain: mesecons_button
Use the button to push it.=Benutzen Sie den Knopf, um ihn zu drücken.
Stone Button=Steinknopf
A stone button is a redstone component made out of stone which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1 second.=Ein Steinknopf ist eine Redstonekomponente aus Stein. Er kann gedrückt werden, um ein Redstonesignal zu senden. Im gedrückten Zustand versorgt er benachbarte Redstonekomponenten für 1 Sekunde mit Redstoneenergie.
Oak Button=Eichenknopf
Acacia Button=Akazienknopf
Birch Button=Birkenknopf
Dark Oak Button=Schwarzeichenknopf
Spruce Button=Fichtenknopf
Jungle Button=Dschungelknopf
A wooden button is a redstone component made out of wood which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1.5 seconds. Wooden buttons may also be pushed by arrows.=Ein Holzknopf ist eine Redstonekomponente aus Holz. Er kann gedrückt werden, um ein Redstonesignal zu senden. Im gedrückten Zustand versorgt er benachbarte Redstonekomponenten für 1,5 Sekunden mit Redstoneenergie. Holzknöpfe können auch von Pfeilen gedrückt werden.
Provides redstone power when pushed=Gibt Redstoneenergie, wenn gedrückt
Push duration: @1s=Druckdauer: @1s
Pushable by arrow=Drückbar von Pfeilen

View File

@ -0,0 +1,11 @@
# textdomain: mesecons_button
Use the button to push it.=Usa el botón para pulsarlo.
Stone Button=Botón de piedra
A stone button is a redstone component made out of stone which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1 second.=Un botón de piedra es un componente de redstone hecho de piedra que se puede presionar para proporcionar energía de redstone. Cuando se empuja, alimenta los componentes adyacentes de redstone durante 1 segundo.
Oak Button=Botón de roble
Acacia Button=Botón de acacia
Birch Button=Botón de abedul
Dark Oak Button=Botón de roble oscuro
Spruce Button=Botón de abeto
Jungle Button=Botón de jungla
A wooden button is a redstone component made out of wood which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1.5 seconds. Wooden buttons may also be pushed by arrows.=Ein Holzknopf ist eine Redstonekomponente aus Holz. Er kann gedrückt werden, um ein Redstonesignal zu senden. Im gedrückten Zustand versorgt er benachbarte Redstonekomponenten für 1,5 Sekunden mit Redstoneenergie. Holzknöpfe können auch von Pfeilen gedrückt werden.

View File

@ -0,0 +1,14 @@
# textdomain: mesecons_button
Use the button to push it.=Utilisez le bouton pour le pousser.
Stone Button=Bouton de pierre
A stone button is a redstone component made out of stone which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1 second.=Un bouton en pierre est un composant Redstone en pierre qui peut être poussé pour fournir de la puissance Redstone. Lorsqu'il est poussé, il alimente les composants Redstone adjacents pendant 1 seconde.
Oak Button=Bouton en Chêne
Acacia Button=Bouton en Acacia
Birch Button=Bouton en Bouleau
Dark Oak Button=Bouton en Chêne Noir
Spruce Button=Bouton en Sapin
Jungle Button=Bouton en Acajou
A wooden button is a redstone component made out of wood which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1.5 seconds. Wooden buttons may also be pushed by arrows.=Un bouton en bois est un composant de redstone en bois qui peut être poussé pour fournir une puissance de redstone. Lorsqu'il est poussé, il alimente les composants Redstone adjacents pendant 1,5 seconde. Les boutons en bois peuvent également être poussés par des flèches.
Provides redstone power when pushed=Fournit une puissance de redstone lorsqu'il est poussé
Push duration: @1s=Durée de poussée: @1s
Pushable by arrow=Poussable par une flèche

View File

@ -0,0 +1,14 @@
# textdomain: mesecons_button
Use the button to push it.=Użyj przycisku by go wcisnąć.
Stone Button=Kamienny przycisk
A stone button is a redstone component made out of stone which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1 second.=Kamienny przycisk jest mechanizmem czerwienitowym, który można nacisnąć by dostarczył on energię czerwienitową. Po naciśnięciu zasila on przyległy mechanizm czerwienitowy przez 1 sekundę.
Oak Button=Dębowy przycisk
Acacia Button=Akacjowy przycisk
Birch Button=Brzozowy przycisk
Dark Oak Button=Ciemno-dębowy przycisk
Spruce Button=Świerkowy przycisk
Jungle Button=Tropikalny przycisk
A wooden button is a redstone component made out of wood which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1.5 seconds. Wooden buttons may also be pushed by arrows.=Drewniany przycisk jest mechanizmem czerwienitowym wykonanym z drewna, który można nacisnąć by dostarczał energię czerwienitową. Po naciśnięciu zasila on przyległe mechanizmy czerwienitowe przez 1.5 sekundy. Drewniane przyciski mogą być również naciśnięte przez strzały.
Provides redstone power when pushed=Dostarcza energii czerwienitowej gdy naciśnięty
Push duration: @1s=Czas trwania naciśnięcia: @1s
Pushable by arrow=Można nacisnąć strzałą

View File

@ -0,0 +1,14 @@
# textdomain: mesecons_button
Use the button to push it.=[Используйте] кнопку, чтобы нажать её.
Stone Button=Каменная кнопка
A stone button is a redstone component made out of stone which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1 second.=Каменная кнопка это элемент редстоуна, сделанный из камня, её можно нажать, чтобы получить энергию редстоуна. При нажатии она включает соседние элементы редстоуна на 1 секунду.
Oak Button=Дубовая кнопка
Acacia Button=Акациевая кнопка
Birch Button=Берёзовая кнопка
Dark Oak Button=Кнопка из тёмного дуба
Spruce Button=Еловая кнопка
Jungle Button=Кнопка из дерева джунглей
A wooden button is a redstone component made out of wood which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1.5 seconds. Wooden buttons may also be pushed by arrows.=Деревянная кнопка это элемент редстоуна, сделанный из дерева, её можно нажать, чтобы получить энергию редстоуна. При нажатии она включает соседние элементы редстоуна на полторы секунды. Деревянные кнопки можно также активировать стрелами.
Provides redstone power when pushed=Выдаёт энергию редстоуна при нажатии
Push duration: @1s=Длительность нажатия: @1с
Pushable by arrow=Нажимается стрелами

View File

@ -0,0 +1,14 @@
# textdomain: mesecons_button
Use the button to push it.=
Stone Button=
A stone button is a redstone component made out of stone which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1 second.=
Oak Button=
Acacia Button=
Birch Button=
Dark Oak Button=
Spruce Button=
Jungle Button=
A wooden button is a redstone component made out of wood which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1.5 seconds. Wooden buttons may also be pushed by arrows.=
Provides redstone power when pushed=
Push duration: @1s=
Pushable by arrow=

3
mesecons_button/mod.conf Normal file
View File

@ -0,0 +1,3 @@
name = mesecons_button
depends = mesecons
optional_depends = doc

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 B

View File

@ -0,0 +1,324 @@
local S = minetest.get_translator(minetest.get_current_modname())
local F = minetest.formspec_escape
local tonumber = tonumber
local color_red = mcl_colors.RED
local command_blocks_activated = minetest.settings:get_bool("mcl_enable_commandblocks", true)
local msg_not_activated = S("Command blocks are not enabled on this server")
local function construct(pos)
local meta = minetest.get_meta(pos)
meta:set_string("commands", "")
meta:set_string("commander", "")
end
local function after_place(pos, placer)
if placer then
local meta = minetest.get_meta(pos)
meta:set_string("commander", placer:get_player_name())
end
end
local function resolve_commands(commands, pos)
local players = minetest.get_connected_players()
local meta = minetest.get_meta(pos)
local commander = meta:get_string("commander")
-- A non-printable character used while replacing “@@”.
local SUBSTITUTE_CHARACTER = "\26" -- ASCII SUB
-- No players online: remove all commands containing
-- problematic placeholders.
if #players == 0 then
commands = commands:gsub("[^\r\n]+", function (line)
line = line:gsub("@@", SUBSTITUTE_CHARACTER)
if line:find("@n") then return "" end
if line:find("@p") then return "" end
if line:find("@f") then return "" end
if line:find("@r") then return "" end
line = line:gsub("@c", commander)
line = line:gsub(SUBSTITUTE_CHARACTER, "@")
return line
end)
return commands
end
local nearest, farthest = nil, nil
local min_distance, max_distance = math.huge, -1
for index, player in pairs(players) do
local distance = vector.distance(pos, player:get_pos())
if distance < min_distance then
min_distance = distance
nearest = player:get_player_name()
end
if distance > max_distance then
max_distance = distance
farthest = player:get_player_name()
end
end
local random = players[math.random(#players)]:get_player_name()
commands = commands:gsub("@@", SUBSTITUTE_CHARACTER)
commands = commands:gsub("@p", nearest)
commands = commands:gsub("@n", nearest)
commands = commands:gsub("@f", farthest)
commands = commands:gsub("@r", random)
commands = commands:gsub("@c", commander)
commands = commands:gsub(SUBSTITUTE_CHARACTER, "@")
return commands
end
local function check_commands(commands, player_name)
for _, command in pairs(commands:split("\n")) do
local pos = command:find(" ")
local cmd = command
if pos then
cmd = command:sub(1, pos - 1)
end
local cmddef = minetest.chatcommands[cmd]
if not cmddef then
-- Invalid chat command
local msg = S("Error: The command “@1” does not exist; your command block has not been changed. Use the “help” chat command for a list of available commands.", cmd)
if string.sub(cmd, 1, 1) == "/" then
msg = S("Error: The command “@1” does not exist; your command block has not been changed. Use the “help” chat command for a list of available commands. Hint: Try to remove the leading slash.", cmd)
end
return false, minetest.colorize(color_red, msg)
end
if player_name then
local player_privs = minetest.get_player_privs(player_name)
for cmd_priv, _ in pairs(cmddef.privs) do
if player_privs[cmd_priv] ~= true then
local msg = S("Error: You have insufficient privileges to use the command “@1” (missing privilege: @2)! The command block has not been changed.", cmd, cmd_priv)
return false, minetest.colorize(color_red, msg)
end
end
end
end
return true
end
local function commandblock_action_on(pos, node)
if node.name ~= "mesecons_commandblock:commandblock_off" then
return
end
local meta = minetest.get_meta(pos)
local commander = meta:get_string("commander")
if not command_blocks_activated then
--minetest.chat_send_player(commander, msg_not_activated)
return
end
minetest.swap_node(pos, {name = "mesecons_commandblock:commandblock_on"})
local commands = resolve_commands(meta:get_string("commands"), pos)
for _, command in pairs(commands:split("\n")) do
local cpos = command:find(" ")
local cmd, param = command, ""
if cpos then
cmd = command:sub(1, cpos - 1)
param = command:sub(cpos + 1)
end
local cmddef = minetest.chatcommands[cmd]
if not cmddef then
-- Invalid chat command
return
end
-- Execute command in the name of commander
cmddef.func(commander, param)
end
end
local function commandblock_action_off(pos, node)
if node.name == "mesecons_commandblock:commandblock_on" then
minetest.swap_node(pos, {name = "mesecons_commandblock:commandblock_off"})
end
end
local function on_rightclick(pos, node, player, itemstack, pointed_thing)
if not command_blocks_activated then
minetest.chat_send_player(player:get_player_name(), msg_not_activated)
return
end
local can_edit = true
-- Only allow write access in Creative Mode
if not minetest.is_creative_enabled(player:get_player_name()) then
can_edit = false
end
local pname = player:get_player_name()
if minetest.is_protected(pos, pname) then
can_edit = false
end
local privs = minetest.get_player_privs(pname)
if not privs.maphack then
can_edit = false
end
local meta = minetest.get_meta(pos)
local commands = meta:get_string("commands")
if not commands then
commands = ""
end
local commander = meta:get_string("commander")
local commanderstr
if commander == "" or commander == nil then
commanderstr = S("Error: No commander! Block must be replaced.")
else
commanderstr = S("Commander: @1", commander)
end
local textarea_name, submit, textarea
-- If editing is not allowed, only allow read-only access.
-- Player can still view the contents of the command block.
if can_edit then
textarea_name = "commands"
submit = "button_exit[3.3,4.4;2,1;submit;"..F(S("Submit")).."]"
else
textarea_name = ""
submit = ""
end
if not can_edit and commands == "" then
textarea = "label[0.5,0.5;"..F(S("No commands.")).."]"
else
textarea = "textarea[0.5,0.5;8.5,4;"..textarea_name..";"..F(S("Commands:"))..";"..F(commands).."]"
end
local formspec = "size[9,5;]" ..
textarea ..
submit ..
"image_button[8,4.4;1,1;doc_button_icon_lores.png;doc;]" ..
"tooltip[doc;"..F(S("Help")).."]" ..
"label[0,4;"..F(commanderstr).."]"
minetest.show_formspec(pname, "commandblock_"..pos.x.."_"..pos.y.."_"..pos.z, formspec)
end
local function on_place(itemstack, placer, pointed_thing)
if pointed_thing.type ~= "node" then
return itemstack
end
-- Use pointed node's on_rightclick function first, if present
local new_stack = mcl_util.call_on_rightclick(itemstack, placer, pointed_thing)
if new_stack then
return new_stack
end
--local node = minetest.get_node(pointed_thing.under)
local privs = minetest.get_player_privs(placer:get_player_name())
if not privs.maphack then
minetest.chat_send_player(placer:get_player_name(), S("Placement denied. You need the “maphack” privilege to place command blocks."))
return itemstack
end
return minetest.item_place_node(itemstack, placer, pointed_thing)
end
minetest.register_node("mesecons_commandblock:commandblock_off", {
description = S("Command Block"),
_tt_help = S("Executes server commands when powered by redstone power"),
_doc_items_longdesc =
S("Command blocks are mighty redstone components which are able to alter reality itself. In other words, they cause the server to execute server commands when they are supplied with redstone power."),
_doc_items_usagehelp =
S("Everyone can activate a command block and look at its commands, but not everyone can edit and place them.").."\n\n"..
S("To view the commands in a command block, use it. To activate the command block, just supply it with redstone power. This will execute the commands once. To execute the commands again, turn the redstone power off and on again.")..
"\n\n"..
S("To be able to place a command block and change the commands, you need to be in Creative Mode and must have the “maphack” privilege. A new command block does not have any commands and does nothing. Use the command block (in Creative Mode!) to edit its commands. Read the help entry “Advanced usage > Server Commands” to understand how commands work. Each line contains a single command. You enter them like you would in the console, but without the leading slash. The commands will be executed from top to bottom.").."\n\n"..
S("All commands will be executed on behalf of the player who placed the command block, as if the player typed in the commands. This player is said to be the “commander” of the block.").."\n\n"..
S("Command blocks support placeholders, insert one of these placeholders and they will be replaced by some other text:").."\n"..
S("• “@@c”: commander of this command block").."\n"..
S("• “@@n” or “@@p”: nearest player from the command block").."\n"..
S("• “@@f” farthest player from the command block").."\n"..
S("• “@@r”: random player currently in the world").."\n"..
S("• “@@@@”: literal “@@” sign").."\n\n"..
S("Example 1:\n time 12000\nSets the game clock to 12:00").."\n\n"..
S("Example 2:\n give @@n mcl_core:apple 5\nGives the nearest player 5 apples"),
tiles = {{name="jeija_commandblock_off.png", animation={type="vertical_frames", aspect_w=32, aspect_h=32, length=2}}},
groups = {creative_breakable=1, mesecon_effector_off=1},
drop = "",
on_blast = function() end,
on_construct = construct,
is_ground_content = false,
on_place = on_place,
after_place_node = after_place,
on_rightclick = on_rightclick,
sounds = mcl_sounds.node_sound_stone_defaults(),
mesecons = {effector = {
action_on = commandblock_action_on,
rules = mesecon.rules.alldirs,
}},
_mcl_blast_resistance = 3600000,
_mcl_hardness = -1,
})
minetest.register_node("mesecons_commandblock:commandblock_on", {
tiles = {{name="jeija_commandblock_off.png", animation={type="vertical_frames", aspect_w=32, aspect_h=32, length=2}}},
groups = {creative_breakable=1, mesecon_effector_on=1, not_in_creative_inventory=1},
drop = "",
on_blast = function() end,
on_construct = construct,
is_ground_content = false,
on_place = on_place,
after_place_node = after_place,
on_rightclick = on_rightclick,
sounds = mcl_sounds.node_sound_stone_defaults(),
mesecons = {effector = {
action_off = commandblock_action_off,
rules = mesecon.rules.alldirs,
}},
_mcl_blast_resistance = 3600000,
_mcl_hardness = -1,
})
minetest.register_on_player_receive_fields(function(player, formname, fields)
if string.sub(formname, 1, 13) == "commandblock_" then
if fields.doc and minetest.get_modpath("doc") then
doc.show_entry(player:get_player_name(), "nodes", "mesecons_commandblock:commandblock_off", true)
return
end
if (not fields.submit and not fields.key_enter) or (not fields.commands) then
return
end
local privs = minetest.get_player_privs(player:get_player_name())
if not privs.maphack then
minetest.chat_send_player(player:get_player_name(), S("Access denied. You need the “maphack” privilege to edit command blocks."))
return
end
local index, _, x, y, z = string.find(formname, "commandblock_(-?%d+)_(-?%d+)_(-?%d+)")
if index and x and y and z then
local pos = {x = tonumber(x), y = tonumber(y), z = tonumber(z)}
local meta = minetest.get_meta(pos)
if not minetest.is_creative_enabled(player:get_player_name()) then
minetest.chat_send_player(player:get_player_name(), S("Editing the command block has failed! You can only change the command block in Creative Mode!"))
return
end
local check, error_message = check_commands(fields.commands, player:get_player_name())
if check == false then
-- Command block rejected
minetest.chat_send_player(player:get_player_name(), error_message)
return
else
meta:set_string("commands", fields.commands)
end
else
minetest.chat_send_player(player:get_player_name(), S("Editing the command block has failed! The command block is gone."))
end
end
end)
-- Add entry alias for the Help
if minetest.get_modpath("doc") then
doc.add_entry_alias("nodes", "mesecons_commandblock:commandblock_off", "nodes", "mesecons_commandblock:commandblock_on")
end

View File

@ -0,0 +1,30 @@
# textdomain: mesecons_commandblock
Error: The command “@1” does not exist; your command block has not been changed. Use the “help” chat command for a list of available commands.=Fehler: Der Befehl „@1“ existiert nicht; Ihr Befehlsblock bleibt unverändert. Benutzen Sie den Chatbefehl „help“ für eine Liste der verfügbaren Befehle.
Error: The command “@1” does not exist; your command block has not been changed. Use the “help” chat command for a list of available commands. Hint: Try to remove the leading slash.=Fehler: Der Befehl „@1“ existiert nicht; Ihr Befehlsblock bleibt unverändert. Benutzen Sie den Chatbefehl „help“ für eine Liste der verfügbaren Befehle. Tipp: Versuchen Sie, den Schrägstrich am Anfang zu entfernen.
Error: You have insufficient privileges to use the command “@1” (missing privilege: @2)! The command block has not been changed.=Fehler: Sie haben nicht die ausreichenden Privilegien, um den Befehl „@1“ zu benutzen (fehlendes Privileg: @2)! Der Befehlsblock bleibt unverändert.
Error: No commander! Block must be replaced.=Fehler: Kein Kommandant! Block muss ersetzt werden.
Commander: @1=Kommandant: @1
Submit=OK
No commands.=Keine Befehle.
Commands:=Befehle:
Help=Hilfe
Placement denied. You need the “maphack” privilege to place command blocks.=Platzierung fehlgeschlagen. Sie brauchen das „maphack“-Privileg, um Befehlsblöcke platzieren zu können.
Command Block=Befehlsblock
Command blocks are mighty redstone components which are able to alter reality itself. In other words, they cause the server to execute server commands when they are supplied with redstone power.=Befehlsblöcke sind mächtige Redstonekomponenten, die das Gefüge der Realität selbst verändern können. Mit anderen Worten, sie lassen den Server Serverbefehle ausführen, wenn sie mit Redstoneenergie versorgt werden.
Everyone can activate a command block and look at its commands, but not everyone can edit and place them.=Jeder kann einen Befehlsblock aktivieren und sich seine Befehle ansehen, aber nicht jeder kann sie bearbeiten und platzieren.
To view the commands in a command block, use it. To activate the command block, just supply it with redstone power. This will execute the commands once. To execute the commands again, turn the redstone power off and on again.=Um die Befehle in einem Befehlsblock zu betrachten, benutzen Sie ihn. Um ihn zu aktivieren, versorgen Sie ihn einfach mit Redstoneenergie. Das wird die Befehle einmalig ausführen. Um sie erneut auszuführen, schalten Sie die Redstoneenergie aus und wieder ein.
To be able to place a command block and change the commands, you need to be in Creative Mode and must have the “maphack” privilege. A new command block does not have any commands and does nothing. Use the command block (in Creative Mode!) to edit its commands. Read the help entry “Advanced usage > Server Commands” to understand how commands work. Each line contains a single command. You enter them like you would in the console, but without the leading slash. The commands will be executed from top to bottom.=Um einen Befehlsblock platzieren und die Befehle ändern zu können, müssen Sie im Kreativmodus sein und das „maphack“-Privileg haben. Ein neuer Befehlsblock hat keine Befehle und tut gar nichts. Benutzen Sie den Befehlsblock (im Kreativmodus!), um seine Befehle zu bearbeiten. Lesen Sie den Hilfeeintrag „Fortgeschrittenes > Serverbefehle“, um zu verstehen, wie Befehle funktionieren. Jede Zeile enthält einen einzigen Befehl. Sie geben Sie wie in der Konsole ein, aber ohne den Schrägstrich am Anfang.
All commands will be executed on behalf of the player who placed the command block, as if the player typed in the commands. This player is said to be the “commander” of the block.=Alle Befehle werden im Namen des Spielers, der den Befehlsblock platziert hat, ausgeführt, als ob der Spieler die Befehle eingegeben hätte. Diesen Spieler nennen wir den „Kommandanten“ des Blocks.
Command blocks support placeholders, insert one of these placeholders and they will be replaced by some other text:=Befehlsblöcke unterstützen Platzhalter. Geben Sie einen dieser Platzhalter ein und sie werden durch einen anderen Text ersetzt:
• “@@c”: commander of this command block=• „@@c“: Kommandant dieses Befehlsblocks
• “@@n” or “@@p”: nearest player from the command block=• „@@n“ oder „@@p“: Nächster Spieler am Befehlsblock
• “@@f” farthest player from the command block=• „@@f“: Der vom Befehlsblock am weitesten entfernte Spieler
• “@@r”: random player currently in the world=• „@@r“: Zufälliger Spieler in der Welt
• “@@@@”: literal “@@” sign=• „@@@@“: Nur das „@@“-Zeichen
Example 1:@n time 12000@nSets the game clock to 12:00=1. Beispiel:@n time 12000@nSetzt die Spieluhr auf 12:00 Uhr
Example 2:@n give @@n mcl_core:apple 5@nGives the nearest player 5 apples=2. Beispiel:@n give @@n mcl_core:apple 5@nGibt dem nächsten Spieler 5 Äpfel
Access denied. You need the “maphack” privilege to edit command blocks.=Zugriff verweigert. Sie brauchen das „maphack“-Privileg, um Befehlsblöcke zu bearbeiten.
Editing the command block has failed! You can only change the command block in Creative Mode!=Bearbeitung des Befehlsblocks fehlgeschlagen! Sie können den Befehlsblock nur im Kreativmodus ändern!
Editing the command block has failed! The command block is gone.=Bearbeiten des Befehlsblocks fehlgeschlagen! Der Befehlsblock ist verschwunden.
Executes server commands when powered by redstone power=Führt Serverbefehle aus, wenn mit Redstoneenergie versorgt
Command blocks are not enabled on this server=

View File

@ -0,0 +1,31 @@
# textdomain: mesecons_commandblock
Error: The command “@1” does not exist; your command block has not been changed. Use the “help” chat command for a list of available commands.=Error: el comando "@1" no existe; su bloque de comando no ha sido cambiado. Utilice el comando de chat "help" para obtener una lista de los comandos disponibles.
Error: The command “@1” does not exist; your command block has not been changed. Use the “help” chat command for a list of available commands. Hint: Try to remove the leading slash.=Error: el comando "@1" no existe; su bloque de comando no ha sido cambiado. Utilice el comando de chat "help" para obtener una lista de los comandos disponibles. Sugerencia: intente eliminar la barra diagonal inicial.
Error: You have insufficient privileges to use the command “@1” (missing privilege: @2)! The command block has not been changed.=Error: ¡No tiene suficientes privilegios para usar el comando “@ 1” (faltan privilegios: @ 2)! El bloque de comando no ha sido cambiado.
Error: No commander! Block must be replaced.=Error: ¡Sin dueño! El bloque debe ser reemplazado.
Commander: @1=Dueño: @1
Submit=Aceptar
No commands.=Sin comandos.
Commands:=Comandos:
Help=Ayuda
Placement denied. You need the “maphack” privilege to place command blocks.=Colocación denegada. Necesita el privilegio "maphack" para colocar bloques de comandos.
Command Block=Bloque de comandos
Command blocks are mighty redstone components which are able to alter reality itself. In other words, they cause the server to execute server commands when they are supplied with redstone power.=Los bloques de comandos son poderosos componentes de redstone que pueden alterar la realidad misma. En otras palabras, hacen que el servidor ejecute comandos del servidor cuando se les suministra energía redstone.
Everyone can activate a command block and look at its commands, but not everyone can edit and place them.=Todos pueden activar un bloque de comandos y ver sus comandos, pero no todos pueden editarlos y colocarlos.
To view the commands in a command block, use it. To activate the command block, just supply it with redstone power. This will execute the commands once. To execute the commands again, turn the redstone power off and on again.=Para ver los comandos en un bloque de comandos, úselo. Para activar el bloque de comando, solo suminístrelo con redstone power. Esto ejecutará los comandos una vez. Para ejecutar los comandos nuevamente, apague y vuelva a encender la redstone.
To be able to place a command block and change the commands, you need to be in Creative Mode and must have the “maphack” privilege. A new command block does not have any commands and does nothing. Use the command block (in Creative Mode!) to edit its commands. Read the help entry “Advanced usage > Server Commands” to understand how commands work. Each line contains a single command. You enter them like you would in the console, but without the leading slash. The commands will be executed from top to bottom.=
# ^ OLD TRANSLATION: Para poder colocar un bloque de comandos y cambiar los comandos, debe estar en modo creativo y debe tener el privilegio de "maphack". Un nuevo bloque de comandos no tiene ningún comando y no hace nada. Use el bloque de comandos (en modo creativo) para editar sus comandos. Lea la entrada de ayuda "Temas avanzados> Comandos del servidor" para comprender cómo funcionan los comandos. Cada línea contiene un solo comando. Los ingresas como lo harías en la consola, pero sin la barra inclinada. Los comandos se ejecutarán de arriba a abajo.
All commands will be executed on behalf of the player who placed the command block, as if the player typed in the commands. This player is said to be the “commander” of the block.=Todos los comandos se ejecutarán en el nombre del jugador que colocó el bloque de comandos, como si el jugador tecleara los comandos. Se dice que este jugador es el "dueño" del bloque.
Command blocks support placeholders, insert one of these placeholders and they will be replaced by some other text:=Los bloques de comando admiten marcadores de posición, inserte uno de estos marcadores de posición y serán reemplazados por otro texto:
• “@@c”: commander of this command block=• "@@c“: dueño de este bloque de comandos
• “@@n” or “@@p”: nearest player from the command block=• "@@n“ o "@@p“: jugador más cercano del bloque de comandos
• “@@f” farthest player from the command block=• "@@f“: jugador más alejado del bloque de comandos
• “@@r”: random player currently in the world=• "@@r“: jugador aleatorio actualmente en el mundo
• “@@@@”: literal “@@” sign=• „@@@@“: literal "@@“ firmado
Example 1:@n time 12000@nSets the game clock to 12:00=1. Ejemplo:@n time 12000@nConfigura el reloj del juego a las 12:00
Example 2:@n give @@n mcl_core:apple 5@nGives the nearest player 5 apples=2. Beispiel:@n give @@n mcl_core:apple 5@nDa al jugador más cercano a 5 manzanas
Access denied. You need the “maphack” privilege to edit command blocks.=Acceso denegado. Necesita el privilegio "maphack" para editar bloques de comandos.
Editing the command block has failed! You can only change the command block in Creative Mode!=¡La edición del bloque de comando ha fallado! ¡Solo puede cambiar el bloque de comandos en modo creativo!
Editing the command block has failed! The command block is gone.=¡La edición del bloque de comando ha fallado! El bloque de comando se ha ido.
Command blocks are not enabled on this server=

View File

@ -0,0 +1,30 @@
# textdomain: mesecons_commandblock
Error: The command “@1” does not exist; your command block has not been changed. Use the “help” chat command for a list of available commands.=Erreur: la commande "@1" n'existe pas; votre bloc de commande n'a pas été modifié. Utilisez la commande de discussion "help" pour obtenir la liste des commandes disponibles.
Error: The command “@1” does not exist; your command block has not been changed. Use the “help” chat command for a list of available commands. Hint: Try to remove the leading slash.=Erreur: la commande "@1" n'existe pas; votre bloc de commande n'a pas été modifié. Utilisez la commande de discussion "help" pour obtenir la liste des commandes disponibles. Astuce: essayez de supprimer la barre oblique principale.
Error: You have insufficient privileges to use the command “@1” (missing privilege: @2)! The command block has not been changed.=Erreur: vous ne disposez pas de privilèges suffisants pour utiliser la commande "@1" (privilège manquant: @2)! Le bloc de commandes n'a pas été modifié.
Error: No commander! Block must be replaced.=Erreur: pas de commandant! Le bloc doit être remplacé.
Commander: @1=Commandant: @1
Submit=Soumettre
No commands.=Aucune commande.
Commands:=Commandes:
Help=Aide
Placement denied. You need the “maphack” privilege to place command blocks.=Placement refusé. Vous avez besoin du privilège "maphack" pour placer des blocs de commande.
Command Block=Bloc de Commande
Command blocks are mighty redstone components which are able to alter reality itself. In other words, they cause the server to execute server commands when they are supplied with redstone power.=Les blocs de commande sont des composants redstone puissants qui sont capables de modifier la réalité elle-même. En d'autres termes, ils obligent le serveur à exécuter des commandes serveur lorsqu'ils sont alimentés en redstone.
Everyone can activate a command block and look at its commands, but not everyone can edit and place them.=Tout le monde peut activer un bloc de commandes et consulter ses commandes, mais tout le monde ne peut pas les modifier et les placer.
To view the commands in a command block, use it. To activate the command block, just supply it with redstone power. This will execute the commands once. To execute the commands again, turn the redstone power off and on again.=Pour afficher les commandes dans un bloc de commandes, utilisez-le. Pour activer le bloc de commande, il suffit de l'alimenter en redstone. Cela exécutera les commandes une fois. Pour exécuter à nouveau les commandes, éteignez puis rallumez le Redstone.
To be able to place a command block and change the commands, you need to be in Creative Mode and must have the “maphack” privilege. A new command block does not have any commands and does nothing. Use the command block (in Creative Mode!) to edit its commands. Read the help entry “Advanced usage > Server Commands” to understand how commands work. Each line contains a single command. You enter them like you would in the console, but without the leading slash. The commands will be executed from top to bottom.=Pour pouvoir placer un bloc de commande et modifier les commandes, vous devez être en mode créatif et avoir le privilège "maphack". Un nouveau bloc de commande n'a aucune commande et ne fait rien. Utilisez le bloc de commande (en mode créatif!) Pour modifier ses commandes. Lisez l'entrée d'aide "Utilisation avancée> Commandes du serveur" pour comprendre le fonctionnement des commandes. Chaque ligne contient une seule commande. Vous les entrez comme vous le feriez dans la console, mais sans la barre oblique principale. Les commandes seront exécutées de haut en bas.
All commands will be executed on behalf of the player who placed the command block, as if the player typed in the commands. This player is said to be the “commander” of the block.=Toutes les commandes seront exécutées au nom du joueur qui a placé le bloc de commande, comme si le joueur avait tapé les commandes. Ce joueur est appelé le "commandant" du bloc.
Command blocks support placeholders, insert one of these placeholders and they will be replaced by some other text:=Les blocs de commande prennent en charge les espaces réservés, insérez l'un de ces espaces réservés et ils seront remplacés par un autre texte:
• “@@c”: commander of this command block=• “@@c”: commandant de ce bloc que commande
• “@@n” or “@@p”: nearest player from the command block=• “@@n” or “@@p”: joueur le plus proche du bloc de commande
• “@@f” farthest player from the command block=• “@@f” : joueur le plus éloigné du bloc de commande
• “@@r”: random player currently in the world=• “@@r”: joueur aléatoire actuellement dans le monde
• “@@@@”: literal “@@” sign= • “@@@@”: literalement le symbole “@@”
Example 1:@n time 12000@nSets the game clock to 12:00=Exemple 1:@n time 12000@nRègle l'horloge du jeu sur 12:00
Example 2:@n give @@n mcl_core:apple 5@nGives the nearest player 5 apples=Exemple 2:@n give @@n mcl_core:apple 5@nDonne au joueur le plus proche 5 pommes
Access denied. You need the “maphack” privilege to edit command blocks.=Accès refusé. Vous avez besoin du privilège "maphack" pour modifier les blocs de commande.
Editing the command block has failed! You can only change the command block in Creative Mode!=La modification du bloc de commandes a échoué! Vous ne pouvez modifier le bloc de commandes qu'en mode créatif!
Editing the command block has failed! The command block is gone.=La modification du bloc de commandes a échoué! Le bloc de commande a disparu.
Executes server commands when powered by redstone power=Exécute les commandes du serveur lorsqu'il est alimenté par l'alimentation Redstone
Command blocks are not enabled on this server=Les blocks de commandes ne sont pas activés sur ce serveur

View File

@ -0,0 +1,31 @@
# textdomain: mesecons_commandblock
Error: The command “@1” does not exist; your command block has not been changed. Use the “help” chat command for a list of available commands.=Błąd: Komenda "@1" nie istnieje; twój blok komend nie został zmieniony. Użyj komendy "help" aby zobaczyć listę dostępnych komend.
Error: The command “@1” does not exist; your command block has not been changed. Use the “help” chat command for a list of available commands. Hint: Try to remove the leading slash.=Błąd: Komenda "@1" nie istnieje; twój blok komend nie został zmieniony. Użyj komendy "help" aby zobaczyć listę dostępnych komend. Wskazówka: Spróbuj usunąć poprzedzający slesz.
Error: You have insufficient privileges to use the command “@1” (missing privilege: @2)! The command block has not been changed.=Błąd: Masz niewystarczające uprawnienia by użyć komendy "@1" (brakujący przywilej: @2)! Blok komend nie został zmieniony.
Error: No commander! Block must be replaced.=Blok: Brak komendanta! Blok musi zostać zamieniony.
Commander: @1=Komendant: @1
Submit=Zatwierdź
No commands.=Brak komend.
Commands:=Komendy:
Help=Pomoc
Placement denied. You need the “maphack” privilege to place command blocks.=Odmówiono postawienia. Potrzebujesz przywileju "maphack" aby stawiać bloki komend.
Command Block=Blok komend
Command blocks are mighty redstone components which are able to alter reality itself. In other words, they cause the server to execute server commands when they are supplied with redstone power.=Bloki komend są potężnymi mechanizmami czerwienitowymi, które są w stanie zmieniać samą rzeczywistość. Innymi słowy powodują one, że serwer wykonuje komendy gdy dostarczy się im energię czerwienitową.
Everyone can activate a command block and look at its commands, but not everyone can edit and place them.=Każdy może aktywować blok komend i patrzeć na ich komendy, ale nie wszyscy mogą edytować i kłaść je.
To view the commands in a command block, use it. To activate the command block, just supply it with redstone power. This will execute the commands once. To execute the commands again, turn the redstone power off and on again.=Aby zobaczyć komendy w bloku komend, kliknij użyj na nim. Aby aktywować blok komend zasil go energią czerwienitową. To wykona komendy raz. Aby wykonać je ponownie wyłącz, a następnie włącz energię.
To be able to place a command block and change the commands, you need to be in Creative Mode and must have the “maphack” privilege. A new command block does not have any commands and does nothing. Use the command block (in Creative Mode!) to edit its commands. Read the help entry “Advanced usage > Server Commands” to understand how commands work. Each line contains a single command. You enter them like you would in the console, but without the leading slash. The commands will be executed from top to bottom.=Aby być w stanie kłaść bloki komend i zmieniać ich komendy musisz być w trybie kreatywnym i posiadać przywilej "maphack". Nowy blok komend nie posiada żadnych komend i nie robi nic. Użyj bloku komend (w trybie kreatywnym!) aby zmienić jego komendy. Przeczytaj wpis w pomocy "Zaawansowane użycie > Komendy serwera" aby dowiedzieć się jak komendy działają. Każda linia zawiera pojedynczą komendę. Wprowadzasz je tak jak w konsoli, ale bez poprzedzającego slesza. Komendy będą wykonywane od góry do dołu.
All commands will be executed on behalf of the player who placed the command block, as if the player typed in the commands. This player is said to be the “commander” of the block.=Wszystkie komendy będą formalnie wykonane przez gracza, który postawił blok komend, jakby to ten gracz wpisał komendę. Ten gracz nazywany jest komendantem bloku.
Command blocks support placeholders, insert one of these placeholders and they will be replaced by some other text:=Bloki komend wspierają zamienniki, wstaw jeden z nich a zostaną one zastąpione przez jakiś inny tekst:
• “@@c”: commander of this command block=• "@@c": komendant tego bloku komend
• “@@n” or “@@p”: nearest player from the command block=• "@@n" lub "@@p": gracz najbliżej tego bloku komend
• “@@f” farthest player from the command block=• "@@f": gracz najdalej od tego bloku komend
• “@@r”: random player currently in the world=• "@@r": losowy gracz znajdujący się w świecie
• “@@@@”: literal “@@” sign=• "@@@@": dosłowny znak "@@"
Example 1:@n time 12000@nSets the game clock to 12:00=Przykład 1:@n time 12000@nUstawia zegar gry na 12:00
Example 2:@n give @@n mcl_core:apple 5@nGives the nearest player 5 apples=Przykład 2:@n give @@n mcl_core:apple 5@nDaje najbliższemu graczowi 5 jabłek
Access denied. You need the “maphack” privilege to edit command blocks.=Odmowa dostępu. Potrzebujesz przywileju "maphack" by zmieniać bloki komend.
Editing the command block has failed! You can only change the command block in Creative Mode!=Edycja bloku komend nieudana! Możesz zmieniać bloki komend tylko w trybie kreatywnym.
Editing the command block has failed! The command block is gone.=Edycja bloku komend nieudana! Bloku komend już nie ma.
Executes server commands when powered by redstone power=Wykonuje komendy serwera gdy jest zasilany energią czerwienitową
Command blocks are not enabled on this server=Bloki komend nie są włączone na tym serwerze

View File

@ -0,0 +1,30 @@
# textdomain: mesecons_commandblock
Error: The command “@1” does not exist; your command block has not been changed. Use the “help” chat command for a list of available commands.=Ошибка: Команда “@1” не существует; ваш командный блок не был изменён. Используйте чат-команду “help” для поучения списка доступных команд.
Error: The command “@1” does not exist; your command block has not been changed. Use the “help” chat command for a list of available commands. Hint: Try to remove the leading slash.=Ошибка: Команда “@1” не существует; ваш командный блок не был изменён. Используйте чат-команду “help” для поучения списка доступных команд. Подсказка: Попробуйте убрать ведущий слэш.
Error: You have insufficient privileges to use the command “@1” (missing privilege: @2)! The command block has not been changed.=Ошибка: Вы не имеете привилегий для использования команды “@1” (отсутствует привилегия: @2)! Командный блок не был изменён.
Error: No commander! Block must be replaced.=Ошибка: Нет командующего! Блок следует заменить.
Commander: @1=Командующий: @1
Submit=Отправить
No commands.=Нет команд.
Commands:=Команды:
Help=Помощь
Placement denied. You need the “maphack” privilege to place command blocks.=Установка запрещена. Для установки командных блоков нужно иметь привилегию “maphack”.
Command Block=Командный блок
Command blocks are mighty redstone components which are able to alter reality itself. In other words, they cause the server to execute server commands when they are supplied with redstone power.=Командные блоки это мощнейшие компоненты редстоуна, способные изменять реальность сами по себе. Другими словами, они могут заставлять сервер выполнять серверные команды, если подать на них энергию редстоуна.
Everyone can activate a command block and look at its commands, but not everyone can edit and place them.=Каждый может активировать командный блок и увидеть его команды, но не все могут редактировать и устанавливать его.
To view the commands in a command block, use it. To activate the command block, just supply it with redstone power. This will execute the commands once. To execute the commands again, turn the redstone power off and on again.=Чтобы увидеть команды в командном блоке, [используйте] его. Чтобы активировать блок, просто подайте на него энергию редстоуна. При этом команды выполнятся однократно. Чтобы выполнить их вновь, выключите и снова включите энергию редстоуна.
To be able to place a command block and change the commands, you need to be in Creative Mode and must have the “maphack” privilege. A new command block does not have any commands and does nothing. Use the command block (in Creative Mode!) to edit its commands. Read the help entry “Advanced usage > Server Commands” to understand how commands work. Each line contains a single command. You enter them like you would in the console, but without the leading slash. The commands will be executed from top to bottom.=Чтобы иметь возможность устанавливать командные блоки и изменять их команды, вы должны находиться в творческом режиме и иметь привилегию “maphack”. Новый командный блок не содержит команд и ничего не делает. [Используйте] командный блок (в творческом режиме!) для редактирования его команд. Изучите справочную запись “Продвинутое использование > Серверные команды”, чтобы понять, как они работают. Каждая строка содержит одну команду. Вы вводите их так, как вводили бы в консоли, но без ведущих символов слэш. Команды выполняются сверху вниз.
All commands will be executed on behalf of the player who placed the command block, as if the player typed in the commands. This player is said to be the “commander” of the block.=Все команды будут выполняться от имени игрока, разместившего командный блок, как будто если бы игрок сам их набирал. Этот игрок является так называемым “командиром” блока.
Command blocks support placeholders, insert one of these placeholders and they will be replaced by some other text:=Командные блоки поддерживаю шаблоны, вставляйте один из них - и они будут заменены на нужный вам текст:
• “@@c”: commander of this command block=• “@@c”: командир данного командного блока
• “@@n” or “@@p”: nearest player from the command block=• “@@n” или “@@p”: игрок, находящийся ближе всего к данному командному блоку
• “@@f” farthest player from the command block=• “@@f” игрок, находящийся дальше всего от данного командного блока
• “@@r”: random player currently in the world=• “@@r”: случайный игрок, в данный момент присутствующий в мире
• “@@@@”: literal “@@” sign=• “@@@@”: если нужно использовать символ “@@” сам по себе
Example 1:@n time 12000@nSets the game clock to 12:00=Пример 1:@n time 12000@nУстанавливает игровые часы на 12:00
Example 2:@n give @@n mcl_core:apple 5@nGives the nearest player 5 apples=Пример 2:@n give @@n mcl_core:apple 5@nДаёт ближайшему игроку 5 яблок
Access denied. You need the “maphack” privilege to edit command blocks.=Доступ запрещён. Вам нужно иметь привилегию “maphack”, чтобы редактировать командные блоки.
Editing the command block has failed! You can only change the command block in Creative Mode!=Попытка редактирования командного блока потерпела неудачу. Вы можете изменять командные блоки только в творческом режиме!
Editing the command block has failed! The command block is gone.=Попытка редактирования командного блока потерпела неудачу. Командный блок исчез.
Executes server commands when powered by redstone power=При подаче энергии редстоуна выполняет серверные команды
Command blocks are not enabled on this server=

View File

@ -0,0 +1,30 @@
# textdomain: mesecons_commandblock
Error: The command “@1” does not exist; your command block has not been changed. Use the “help” chat command for a list of available commands.=
Error: The command “@1” does not exist; your command block has not been changed. Use the “help” chat command for a list of available commands. Hint: Try to remove the leading slash.=
Error: You have insufficient privileges to use the command “@1” (missing privilege: @2)! The command block has not been changed.=
Error: No commander! Block must be replaced.=
Commander: @1=
Submit=
No commands.=
Commands:=
Help=
Placement denied. You need the “maphack” privilege to place command blocks.=
Command Block=
Command blocks are mighty redstone components which are able to alter reality itself. In other words, they cause the server to execute server commands when they are supplied with redstone power.=
Everyone can activate a command block and look at its commands, but not everyone can edit and place them.=
To view the commands in a command block, use it. To activate the command block, just supply it with redstone power. This will execute the commands once. To execute the commands again, turn the redstone power off and on again.=
To be able to place a command block and change the commands, you need to be in Creative Mode and must have the “maphack” privilege. A new command block does not have any commands and does nothing. Use the command block (in Creative Mode!) to edit its commands. Read the help entry “Advanced usage > Server Commands” to understand how commands work. Each line contains a single command. You enter them like you would in the console, but without the leading slash. The commands will be executed from top to bottom.=
All commands will be executed on behalf of the player who placed the command block, as if the player typed in the commands. This player is said to be the “commander” of the block.=
Command blocks support placeholders, insert one of these placeholders and they will be replaced by some other text:=
• “@@c”: commander of this command block=
• “@@n” or “@@p”: nearest player from the command block=
• “@@f” farthest player from the command block=
• “@@r”: random player currently in the world=
• “@@@@”: literal “@@” sign=
Example 1:@n time 12000@nSets the game clock to 12:00=
Example 2:@n give @@n mcl_core:apple 5@nGives the nearest player 5 apples=
Access denied. You need the “maphack” privilege to edit command blocks.=
Editing the command block has failed! You can only change the command block in Creative Mode!=
Editing the command block has failed! The command block is gone.=
Executes server commands when powered by redstone power=
Command blocks are not enabled on this server=

View File

@ -0,0 +1,3 @@
name = mesecons_commandblock
depends = mesecons, mcl_colors, mcl_util
optional_depends = doc, doc_items

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 B

504
mesecons_delayer/init.lua Normal file
View File

@ -0,0 +1,504 @@
local S = minetest.get_translator(minetest.get_current_modname())
local DELAYS = { 0.1, 0.2, 0.3, 0.4 }
local DEFAULT_DELAY = DELAYS[1]
-- Function that get the input/output rules of the delayer
local function delayer_get_output_rules(node)
local rules = {{x = -1, y = 0, z = 0, spread=true}}
for i = 0, node.param2 do
rules = mesecon.rotate_rules_left(rules)
end
return rules
end
local function delayer_get_input_rules(node)
local rules = {{x = 1, y = 0, z = 0}}
for i = 0, node.param2 do
rules = mesecon.rotate_rules_left(rules)
end
return rules
end
-- Return the sides of a delayer.
-- Those are used to toggle the lock state.
local function delayer_get_sides(node)
local rules = {
{x = 0, y = 0, z = -1},
{x = 0, y = 0, z = 1},
}
for i = 0, node.param2 do
rules = mesecon.rotate_rules_left(rules)
end
return rules
end
-- Make the repeater at pos try to lock any repeater it faces.
-- Returns true if a repeater was locked.
local function check_lock_repeater(pos, node)
-- Check the repeater at pos and look if it faces
-- a repeater placed sideways.
-- If yes, lock the second repeater.
local r = delayer_get_output_rules(node)[1]
local lpos = vector.add(pos, r)
local lnode = minetest.get_node(lpos)
local ldef = minetest.registered_nodes[lnode.name]
local g = minetest.get_item_group(lnode.name, "redstone_repeater")
if g >= 1 and g <= 4 then
local lrs = delayer_get_input_rules(lnode)
local fail = false
for _, lr in pairs(lrs) do
if lr.x == r.x or lr.z == r.z then
fail = true
break
end
end
if not fail then
minetest.set_node(lpos, {name=ldef.delayer_lockstate, param2=lnode.param2})
local meta = minetest.get_meta(lpos)
-- Metadata: delay. Used to remember the delay for locked repeaters.
-- The number is the torch position (1-4).
meta:set_int("delay", g)
return true
end
end
return false
end
-- Make the repeater at pos try to unlock any repeater it faces.
-- Returns true if a repeater was unlocked.
local function check_unlock_repeater(pos, node)
-- Check the repeater at pos and look if it faces
-- a repeater placed sideways.
-- If yes, also check if the second repeater doesn't receive
-- a locking signal on the other side. If not, unlock the second repeater.
local r = delayer_get_output_rules(node)[1]
local lpos = vector.add(pos, r)
local lnode = minetest.get_node(lpos)
local ldef = minetest.registered_nodes[lnode.name]
local g = minetest.get_item_group(lnode.name, "redstone_repeater")
-- Are we facing a locked repeater?
if g == 5 then
-- First check the orientation of the faced repeater
local lrs = delayer_get_input_rules(lnode)
for _, lr in pairs(lrs) do
if lr.x == r.x or lr.z == r.z then
-- Invalid orientation. Do nothing
return false
end
end
-- Now we check if there's a powered repeater on the other side of the
-- locked repeater.
-- To get to the other side, we just take another step in the direction which we already face.
local other_side = vector.add(lpos, r)
local other_node = minetest.get_node(other_side)
if minetest.get_item_group(other_node.name, "redstone_repeater") ~= 0 and mesecon.is_receptor_on(other_node.name) then
-- Final check: The other repeater must also face the right way
local other_face = delayer_get_output_rules(other_node)[1]
local other_facing_pos = vector.add(other_side, other_face)
if vector.equals(other_facing_pos, lpos) then
-- Powered repeater found AND it's facing the locked repeater. Do NOT unlock!
return false
end
end
local lmeta = minetest.get_meta(lpos)
local ldelay = lmeta:get_int("delay")
if tonumber(ldelay) == nil or ldelay < 1 or ldelay > 4 then
ldelay = 1
end
if mesecon.is_powered(lpos, delayer_get_input_rules(lnode)[1]) then
minetest.set_node(lpos, {name="mesecons_delayer:delayer_on_"..ldelay, param2=lnode.param2})
mesecon.queue:add_action(lpos, "receptor_on", {delayer_get_output_rules(lnode)}, ldef.delayer_time, nil)
else
minetest.set_node(lpos, {name="mesecons_delayer:delayer_off_"..ldelay, param2=lnode.param2})
mesecon.queue:add_action(lpos, "receptor_off", {delayer_get_output_rules(lnode)}, ldef.delayer_time, nil)
end
return true
end
return false
end
-- Functions that are called after the delay time
local function delayer_activate(pos, node)
local def = minetest.registered_nodes[node.name]
local time = def.delayer_time
minetest.set_node(pos, {name=def.delayer_onstate, param2=node.param2})
mesecon.queue:add_action(pos, "receptor_on", {delayer_get_output_rules(node)}, time, nil)
check_lock_repeater(pos, node)
end
local function delayer_deactivate(pos, node)
local def = minetest.registered_nodes[node.name]
local time = def.delayer_time
minetest.set_node(pos, {name=def.delayer_offstate, param2=node.param2})
mesecon.queue:add_action(pos, "receptor_off", {delayer_get_output_rules(node)}, time, nil)
check_unlock_repeater(pos, node)
end
local on_rotate
if minetest.get_modpath("screwdriver") then
on_rotate = screwdriver.disallow
end
-- Register the 2 (states) x 4 (delay times) delayers
for i = 1, 4 do
local groups
if i == 1 then
groups = {dig_immediate=3,dig_by_water=1,destroy_by_lava_flow=1,dig_by_piston=1,attached_node=1,redstone_repeater=i}
else
groups = {dig_immediate=3,dig_by_water=1,destroy_by_lava_flow=1,dig_by_piston=1,attached_node=1,redstone_repeater=i,not_in_creative_inventory=1}
end
local delaytime = DELAYS[i]
local boxes
if i == 1 then
boxes = {
{ -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 }, -- the main slab
{ -1/16, -6/16, 6/16, 1/16, -1/16, 4/16}, -- still torch
{ -1/16, -6/16, 0/16, 1/16, -1/16, 2/16}, -- moved torch
}
elseif i == 2 then
boxes = {
{ -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 }, -- the main slab
{ -1/16, -6/16, 6/16, 1/16, -1/16, 4/16}, -- still torch
{ -1/16, -6/16, -2/16, 1/16, -1/16, 0/16}, -- moved torch
}
elseif i == 3 then
boxes = {
{ -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 }, -- the main slab
{ -1/16, -6/16, 6/16, 1/16, -1/16, 4/16}, -- still torch
{ -1/16, -6/16, -4/16, 1/16, -1/16, -2/16}, -- moved torch
}
elseif i == 4 then
boxes = {
{ -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 }, -- the main slab
{ -1/16, -6/16, 6/16, 1/16, -1/16, 4/16}, -- still torch
{ -1/16, -6/16, -6/16, 1/16, -1/16, -4/16}, -- moved torch
}
end
local help, tt, longdesc, usagehelp, icon, on_construct
if i == 1 then
help = true
tt = S("Transmits redstone power only in one direction").."\n"..
S("Delays signal").."\n"..
S("Output locks when getting active redstone repeater signal from the side")
longdesc = S("Redstone repeaters are versatile redstone components with multiple purposes: 1. They only allow signals to travel in one direction. 2. They delay the signal. 3. Optionally, they can lock their output in one state.")
usagehelp = S("To power a redstone repeater, send a signal in “arrow” direction (the input). The signal goes out on the opposite side (the output) with a delay. To change the delay, use the redstone repeater. The delay is between 0.1 and 0.4 seconds long and can be changed in steps of 0.1 seconds. It is indicated by the position of the moving redstone torch.").."\n"..
S("To lock a repeater, send a signal from an adjacent repeater into one of its sides. While locked, the moving redstone torch disappears, the output doesn't change and the input signal is ignored.")
icon = "mesecons_delayer_item.png"
-- Check sides of constructed repeater and lock it, if required
on_construct = function(pos)
local node = minetest.get_node(pos)
local sides = delayer_get_sides(node)
for s=1, #sides do
local spos = vector.add(pos, sides[s])
local snode = minetest.get_node(spos)
-- Is there a powered repeater at one of our sides?
local g = minetest.get_item_group(snode.name, "redstone_repeater")
if g ~= 0 and mesecon.is_receptor_on(snode.name) then
-- The other repeater must also face towards the constructed node
local sface = delayer_get_output_rules(snode)[1]
local sface_pos = vector.add(spos, sface)
if vector.equals(sface_pos, pos) then
-- Repeater is facing towards us! Now we just need to lock the costructed node
if mesecon.is_powered(pos, delayer_get_input_rules(node)[1]) ~= false then
local newnode = {name="mesecons_delayer:delayer_on_locked", param2 = node.param2}
minetest.set_node(pos, newnode)
mesecon.queue:add_action(pos, "receptor_on", {delayer_get_output_rules(newnode)}, DEFAULT_DELAY, nil)
else
minetest.set_node(pos, {name="mesecons_delayer:delayer_off_locked", param2 = node.param2})
end
break
end
end
end
end
else
help = false
end
local desc_off
if i == 1 then
desc_off = S("Redstone Repeater")
else
desc_off = S("Redstone Repeater (Delay @1)", i)
end
minetest.register_node("mesecons_delayer:delayer_off_"..tostring(i), {
description = desc_off,
inventory_image = icon,
wield_image = icon,
_tt_help = tt,
_doc_items_create_entry = help,
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usagehelp,
drawtype = "nodebox",
tiles = {
"mesecons_delayer_off.png",
"mcl_stairs_stone_slab_top.png",
"mesecons_delayer_sides_off.png",
"mesecons_delayer_sides_off.png",
"mesecons_delayer_ends_off.png",
"mesecons_delayer_ends_off.png",
},
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false,
--wield_image = "mesecons_delayer_off.png",
walkable = true,
selection_box = {
type = "fixed",
fixed = { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 },
},
collision_box = {
type = "fixed",
fixed = { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 },
},
node_box = {
type = "fixed",
fixed = boxes
},
groups = groups,
paramtype = "light",
paramtype2 = "facedir",
sunlight_propagates = false,
is_ground_content = false,
drop = "mesecons_delayer:delayer_off_1",
on_rightclick = function(pos, node, clicker)
local protname = clicker:get_player_name()
if minetest.is_protected(pos, protname) then
minetest.record_protection_violation(pos, protname)
return
end
if node.name=="mesecons_delayer:delayer_off_1" then
minetest.set_node(pos, {name="mesecons_delayer:delayer_off_2", param2=node.param2})
elseif node.name=="mesecons_delayer:delayer_off_2" then
minetest.set_node(pos, {name="mesecons_delayer:delayer_off_3", param2=node.param2})
elseif node.name=="mesecons_delayer:delayer_off_3" then
minetest.set_node(pos, {name="mesecons_delayer:delayer_off_4", param2=node.param2})
elseif node.name=="mesecons_delayer:delayer_off_4" then
minetest.set_node(pos, {name="mesecons_delayer:delayer_off_1", param2=node.param2})
end
end,
on_construct = on_construct,
delayer_time = delaytime,
delayer_onstate = "mesecons_delayer:delayer_on_"..tostring(i),
delayer_lockstate = "mesecons_delayer:delayer_off_locked",
sounds = mcl_sounds.node_sound_stone_defaults(),
mesecons = {
receptor = {
state = mesecon.state.off,
rules = delayer_get_output_rules,
},
effector = {
rules = delayer_get_input_rules,
action_on = delayer_activate,
},
},
on_rotate = on_rotate,
})
minetest.register_node("mesecons_delayer:delayer_on_"..tostring(i), {
description = S("Redstone Repeater (Delay @1, Powered)", i),
_doc_items_create_entry = false,
drawtype = "nodebox",
tiles = {
"mesecons_delayer_on.png",
"mcl_stairs_stone_slab_top.png",
"mesecons_delayer_sides_on.png",
"mesecons_delayer_sides_on.png",
"mesecons_delayer_ends_on.png",
"mesecons_delayer_ends_on.png",
},
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false,
walkable = true,
selection_box = {
type = "fixed",
fixed = { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 },
},
collision_box = {
type = "fixed",
fixed = { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 },
},
node_box = {
type = "fixed",
fixed = boxes
},
groups = {dig_immediate = 3, dig_by_water=1,destroy_by_lava_flow=1, dig_by_piston=1, attached_node=1, redstone_repeater=i, not_in_creative_inventory = 1},
paramtype = "light",
paramtype2 = "facedir",
sunlight_propagates = false,
is_ground_content = false,
drop = "mesecons_delayer:delayer_off_1",
on_rightclick = function(pos, node, clicker)
local protname = clicker:get_player_name()
if minetest.is_protected(pos, protname) then
minetest.record_protection_violation(pos, protname)
return
end
--HACK! we already know the node name, so we should generate the function to avoid multiple checks
if node.name=="mesecons_delayer:delayer_on_1" then
minetest.set_node(pos, {name="mesecons_delayer:delayer_on_2",param2=node.param2})
elseif node.name=="mesecons_delayer:delayer_on_2" then
minetest.set_node(pos, {name="mesecons_delayer:delayer_on_3",param2=node.param2})
elseif node.name=="mesecons_delayer:delayer_on_3" then
minetest.set_node(pos, {name="mesecons_delayer:delayer_on_4",param2=node.param2})
elseif node.name=="mesecons_delayer:delayer_on_4" then
minetest.set_node(pos, {name="mesecons_delayer:delayer_on_1",param2=node.param2})
end
end,
after_dig_node = function(pos, oldnode)
check_unlock_repeater(pos, oldnode)
end,
delayer_time = delaytime,
delayer_offstate = "mesecons_delayer:delayer_off_"..tostring(i),
delayer_lockstate = "mesecons_delayer:delayer_on_locked",
sounds = mcl_sounds.node_sound_stone_defaults(),
mesecons = {
receptor = {
state = mesecon.state.on,
rules = delayer_get_output_rules,
},
effector = {
rules = delayer_get_input_rules,
action_off = delayer_deactivate,
},
},
on_rotate = on_rotate,
})
end
-- Locked repeater
minetest.register_node("mesecons_delayer:delayer_off_locked", {
description = S("Redstone Repeater (Locked)"),
_doc_items_create_entry = false,
drawtype = "nodebox",
-- FIXME: Textures of torch and the lock bar overlap. Nodeboxes are (sadly) not suitable for this.
-- So this needs to be turned into a mesh.
tiles = {
"mesecons_delayer_locked_off.png",
"mcl_stairs_stone_slab_top.png",
"mesecons_delayer_sides_locked_off.png",
"mesecons_delayer_sides_locked_off.png",
"mesecons_delayer_front_locked_off.png",
"mesecons_delayer_end_locked_off.png",
},
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false,
wield_image = "mesecons_delayer_locked_off.png",
walkable = true,
selection_box = {
type = "fixed",
fixed = { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 },
},
collision_box = {
type = "fixed",
fixed = { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 },
},
node_box = {
type = "fixed",
fixed = {
{ -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 }, -- the main slab
{ -1/16, -6/16, 6/16, 1/16, -1/16, 4/16}, -- still torch
{ -6/16, -6/16, -1/16, 6/16, -4/16, 1/16}, -- lock
}
},
groups = {dig_immediate = 3, dig_by_water=1,destroy_by_lava_flow=1, dig_by_piston=1, attached_node=1, redstone_repeater=5, not_in_creative_inventory = 1},
paramtype = "light",
paramtype2 = "facedir",
sunlight_propagates = false,
is_ground_content = false,
drop = "mesecons_delayer:delayer_off_1",
delayer_time = DEFAULT_DELAY,
sounds = mcl_sounds.node_sound_stone_defaults(),
mesecons = {
receptor =
{
state = mesecon.state.off,
rules = delayer_get_output_rules
},
effector =
{
rules = delayer_get_input_rules,
}
},
on_rotate = on_rotate,
})
minetest.register_node("mesecons_delayer:delayer_on_locked", {
description = S("Redstone Repeater (Locked, Powered)"),
_doc_items_create_entry = false,
drawtype = "nodebox",
tiles = {
"mesecons_delayer_locked_on.png",
"mcl_stairs_stone_slab_top.png",
"mesecons_delayer_sides_locked_on.png",
"mesecons_delayer_sides_locked_on.png",
"mesecons_delayer_front_locked_on.png",
"mesecons_delayer_end_locked_on.png",
},
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false,
walkable = true,
selection_box = {
type = "fixed",
fixed = { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 },
},
collision_box = {
type = "fixed",
fixed = { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 },
},
node_box = {
type = "fixed",
fixed = {
{ -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 }, -- the main slab
{ -1/16, -6/16, 6/16, 1/16, -1/16, 4/16}, -- still torch
{ -6/16, -6/16, -1/16, 6/16, -4/16, 1/16}, -- lock
}
},
after_dig_node = function(pos, oldnode)
check_unlock_repeater(pos, oldnode)
end,
groups = {dig_immediate = 3, dig_by_water=1,destroy_by_lava_flow=1, dig_by_piston=1, attached_node=1, redstone_repeater=5, not_in_creative_inventory = 1},
paramtype = "light",
paramtype2 = "facedir",
sunlight_propagates = false,
is_ground_content = false,
drop = "mesecons_delayer:delayer_off_1",
delayer_time = DEFAULT_DELAY,
sounds = mcl_sounds.node_sound_stone_defaults(),
mesecons = {
receptor =
{
state = mesecon.state.on,
rules = delayer_get_output_rules
},
effector =
{
rules = delayer_get_input_rules,
}
},
on_rotate = on_rotate,
})
minetest.register_craft({
output = "mesecons_delayer:delayer_off_1",
recipe = {
{"mesecons_torch:mesecon_torch_on", "mesecons:redstone", "mesecons_torch:mesecon_torch_on"},
{"mcl_core:stone","mcl_core:stone", "mcl_core:stone"},
}
})
-- Add entry aliases for the Help
if minetest.get_modpath("doc") then
doc.add_entry_alias("nodes", "mesecons_delayer:delayer_off_1", "nodes", "mesecons_delayer:delayer_off_2")
doc.add_entry_alias("nodes", "mesecons_delayer:delayer_off_1", "nodes", "mesecons_delayer:delayer_off_3")
doc.add_entry_alias("nodes", "mesecons_delayer:delayer_off_1", "nodes", "mesecons_delayer:delayer_off_4")
doc.add_entry_alias("nodes", "mesecons_delayer:delayer_off_1", "nodes", "mesecons_delayer:delayer_off_locked")
doc.add_entry_alias("nodes", "mesecons_delayer:delayer_off_1", "nodes", "mesecons_delayer:delayer_on_1")
doc.add_entry_alias("nodes", "mesecons_delayer:delayer_off_1", "nodes", "mesecons_delayer:delayer_on_2")
doc.add_entry_alias("nodes", "mesecons_delayer:delayer_off_1", "nodes", "mesecons_delayer:delayer_on_3")
doc.add_entry_alias("nodes", "mesecons_delayer:delayer_off_1", "nodes", "mesecons_delayer:delayer_on_4")
doc.add_entry_alias("nodes", "mesecons_delayer:delayer_off_1", "nodes", "mesecons_delayer:delayer_on_locked")
end

View File

@ -0,0 +1,13 @@
# textdomain: mesecons_delayer
Redstone repeaters are versatile redstone components with multiple purposes: 1. They only allow signals to travel in one direction. 2. They delay the signal. 3. Optionally, they can lock their output in one state.=Redstoneverstärker sind vielseitige Komponenten mit den folgenden Verwendungszwecken: 1.: Sie lassen Signale nur in eine Richtung durch. 2.: Sie verzögern das Signal. 3.: Sie können optional ihr Ausgangssignal sperren
To power a redstone repeater, send a signal in “arrow” direction (the input). The signal goes out on the opposite side (the output) with a delay. To change the delay, use the redstone repeater. The delay is between 0.1 and 0.4 seconds long and can be changed in steps of 0.1 seconds. It is indicated by the position of the moving redstone torch.=Um einen Redstoneverstärker zu versorgen, senden Sie ein Signal in „Pfeilrichtung“ (dem Eingang). Das Signal geht aus der gegenüberliegenden Seite (dem Ausgang) mit einer Verzögerung hinaus. Um die Verzögerung zu ändern, benutzen Sie den Redstoneverstärker. Die Verzögerung ist zwischen 0,1 bis 0,4 Sekunden lang und kann in Schritten von 0,1 Sekunden geändert werden. Das wird mit der Position der verschiebbaren Redstonefackel angezeigt.
To lock a repeater, send a signal from an adjacent repeater into one of its sides. While locked, the moving redstone torch disappears, the output doesn't change and the input signal is ignored.=Um einen Verstärker zu sperren, senden Sie ein Signal eines benachbarten Verstärkers in eines der Seiten. Im gesperrten Zustand verschwindet die verschiebbare Redstonefackel, die Ausgabe ändert sich nicht mehr und der Eingang wird ignoriert.
Redstone Repeater=Redstoneverstärker
Redstone Repeater (Powered)=Redstoneverstärker (bestromt)
Redstone Repeater (Locked)=Redstoneverstärker (gesperrt)
Redstone Repeater (Locked, Powered)=Redstoneverstärker (gesperrt, bestromt)
Redstone Repeater (Delay @1)=Redstoneverstärker (Verzögerung @1)
Redstone Repeater (Delay @1, Powered)=Redstoneverstärker (Verzögerung @1, bestromt)
Transmits redstone power only in one direction=Überträgt Redstoneenergie in nur eine Richtung
Delays signal=Verzögert Signal
Output locks when getting active redstone repeater signal from the side=Ausgangssignal wird gesperrt, wenn Signal von aktivem Redstoneverstärker an der Seite erhalten

View File

@ -0,0 +1,10 @@
# textdomain: mesecons_delayer
Redstone repeaters are versatile redstone components with multiple purposes: 1. They only allow signals to travel in one direction. 2. They delay the signal. 3. Optionally, they can lock their output in one state.=Los repetidores Redstone son componentes versátiles de redstone con múltiples propósitos: 1. Solo permiten que las señales viajen en una dirección. 2. Retrasan la señal. 3. Opcionalmente, pueden bloquear su salida en un estado.
To power a redstone repeater, send a signal in “arrow” direction (the input). The signal goes out on the opposite side (the output) with a delay. To change the delay, use the redstone repeater. The delay is between 0.1 and 0.4 seconds long and can be changed in steps of 0.1 seconds. It is indicated by the position of the moving redstone torch.=Para alimentar un repetidor de redstone, envíe una señal en la dirección de "flecha" (la entrada). La señal se apaga en el lado opuesto (la salida) con un retraso. Para cambiar el retraso, use el repetidor de redstone. El retraso es de entre 0.1 y 0.4 segundos y se puede cambiar en pasos de 0.1 segundos. Está indicado por la posición de la antorcha de redstone en movimiento.
To lock a repeater, send a signal from an adjacent repeater into one of its sides. While locked, the moving redstone torch disappears, the output doesn't change and the input signal is ignored.=Para bloquear un repetidor, envíe una señal desde un repetidor adyacente a uno de sus lados. Mientras está bloqueado, la antorcha de redstone en movimiento desaparece, la salida no cambia y la señal de entrada se ignora.
Redstone Repeater=Repetidor de redstone
Redstone Repeater (Powered)=Repetidor de redstone (Motorizado)
Redstone Repeater (Locked)=Repetidor de redstone (Bloqueado)
Redstone Repeater (Locked, Powered)=Repetidor de redstone (Bloqueado, Motorizado)
Redstone Repeater (Delay @1)=Repetidor de redstone (Retardar @1)
Redstone Repeater (Delay @1, Powered)=Repetidor de redstone (Retardar @1, Motorizado)

View File

@ -0,0 +1,13 @@
# textdomain: mesecons_delayer
Redstone repeaters are versatile redstone components with multiple purposes: 1. They only allow signals to travel in one direction. 2. They delay the signal. 3. Optionally, they can lock their output in one state.=Les répéteurs Redstone sont des composants Redstone polyvalents à usages multiples: 1. Ils ne permettent aux signaux de voyager que dans une seule direction. 2. Ils retardent le signal. 3. En option, ils peuvent verrouiller leur sortie dans un état.
To power a redstone repeater, send a signal in “arrow” direction (the input). The signal goes out on the opposite side (the output) with a delay. To change the delay, use the redstone repeater. The delay is between 0.1 and 0.4 seconds long and can be changed in steps of 0.1 seconds. It is indicated by the position of the moving redstone torch.=Pour alimenter un répéteur redstone, envoyez un signal dans le sens de la «flèche» (l'entrée). Le signal s'éteint du côté opposé (la sortie) avec un retard. Pour modifier le délai, utilisez le répéteur redstone. Le délai est compris entre 0,1 et 0,4 seconde et peut être modifié par incréments de 0,1 seconde. Elle est indiquée par la position de la torche en pierre rouge en mouvement.
To lock a repeater, send a signal from an adjacent repeater into one of its sides. While locked, the moving redstone torch disappears, the output doesn't change and the input signal is ignored.=Pour verrouiller un répéteur, envoyez un signal d'un répéteur adjacent à l'un de ses côtés. Lorsqu'elle est verrouillée, la torche Redstone en mouvement disparaît, la sortie ne change pas et le signal d'entrée est ignoré.
Redstone Repeater=Répéteur Redstone
Redstone Repeater (Powered)=Répéteur Redstone (Alimenté)
Redstone Repeater (Locked)=Répéteur Redstone (Bloqué)
Redstone Repeater (Locked, Powered)=Répéteur Redstone (Bloqué, Alimenté)
Redstone Repeater (Delay @1)=Répéteur Redstone (Délai @1)
Redstone Repeater (Delay @1, Powered)=Répéteur Redstone (Délai @1, Alimenté)
Transmits redstone power only in one direction=Transmet la puissance de redstone seulement dans une direction
Delays signal=Retard du signal
Output locks when getting active redstone repeater signal from the side=La sortie se verrouille lorsque le signal du répéteur Redstone est actif sur le côté

View File

@ -0,0 +1,13 @@
# textdomain: mesecons_delayer
Redstone repeaters are versatile redstone components with multiple purposes: 1. They only allow signals to travel in one direction. 2. They delay the signal. 3. Optionally, they can lock their output in one state.=Przekaźniki są wszechstronnymi mechanizmami czerwienitowym z kilkoma funkcjami: 1. Pozwalają by sygnał podróżował tylko w jednym kierunku. 2. Opóźniają sygnał. 3. Opcjonalnie mogą zablokować swój output w jednym stanie.
To power a redstone repeater, send a signal in “arrow” direction (the input). The signal goes out on the opposite side (the output) with a delay. To change the delay, use the redstone repeater. The delay is between 0.1 and 0.4 seconds long and can be changed in steps of 0.1 seconds. It is indicated by the position of the moving redstone torch.=Aby zasilić przekaźnik dostarcz sygnał w kierunku "strzałki" (wejście). Sygnał wyjściowy pojawi się po przeciwnej stronie z opóźnieniem. Aby zmienić opóźnienie kliknij użyj na przekaźniku. Możliwe opóźnienia są pomiędzy 0.1 a 0.4 sekundy i może być zmieniony używając przekaźnik co zmienia go o 0.1 sekundy. Opóźnienie jest oznaczone przez pozycję przesuwającej się pochodni.
To lock a repeater, send a signal from an adjacent repeater into one of its sides. While locked, the moving redstone torch disappears, the output doesn't change and the input signal is ignored.=Aby zablokować przekaźnik wyślij sygnał z przyległego przekaźnika w jeden z jego boków. Gdy jest zablokowany poruszająca się pochodnia znika, sygnał wyjściowy się nie zmienia, a sygnał wejściowy jest ignorowany.
Redstone Repeater=Przekaźnik czerwienitowy
Redstone Repeater (Powered)=Przekaźnik czerwienitowy (zasilony)
Redstone Repeater (Locked)=Przekaźnik czerwienitowy (zablokowany)
Redstone Repeater (Locked, Powered)=Przekaźnik czerwienitowy (zablokowany, zasilony)
Redstone Repeater (Delay @1)=Przekaźnik czerwienitowy (opóźnienie @1)
Redstone Repeater (Delay @1, Powered)=Przekaźnik czerwienitowy (opóźnienie @1, zasilony)
Transmits redstone power only in one direction=Przesyła energię czerwienitową w jednym kierunku
Delays signal=Opóźnia sygnał
Output locks when getting active redstone repeater signal from the side=Wyjście się blokuje przy otrzymywaniu zasilonego sygnału z przekaźnika z boku

View File

@ -0,0 +1,13 @@
# textdomain: mesecons_delayer
Redstone repeaters are versatile redstone components with multiple purposes: 1. They only allow signals to travel in one direction. 2. They delay the signal. 3. Optionally, they can lock their output in one state.=Повторители это универсальные компоненты, выполняющие много задач: 1. Разрешают сигналам проходить только в одном направлении. 2. Задерживают сигнал. 3. Опционально они могут зафиксировать свой выходной сигнал в одном состоянии.
To power a redstone repeater, send a signal in “arrow” direction (the input). The signal goes out on the opposite side (the output) with a delay. To change the delay, use the redstone repeater. The delay is between 0.1 and 0.4 seconds long and can be changed in steps of 0.1 seconds. It is indicated by the position of the moving redstone torch.=Чтобы подключить повторитель, подайте сигнал в направлении “стрелки” (на вход). Сигнал выйдет с противоположной стороны (с выхода) с задержкой. Чтобы изменить задержку, [используйте] повторитель. Время задержки лежит между 0.1 и 0.4 секунды и может изменяться с шагом 0.1 секунды. Его отражает положение передвигающегося факела редстоуна.
To lock a repeater, send a signal from an adjacent repeater into one of its sides. While locked, the moving redstone torch disappears, the output doesn't change and the input signal is ignored.=Чтобы зафиксировать повторитель, подайте сигнал от соседнего повторителя на одну из его сторон. При фиксации передвижной факел редстоуна исчезает, выходной сигнал не меняется, а входной сигнал игнорируется.
Redstone Repeater=Повторитель
Redstone Repeater (Powered)=Повторитель (подключённый)
Redstone Repeater (Locked)=Повторитель (зафиксированный)
Redstone Repeater (Locked, Powered)=Повторитель (зафиксированный, подключённый)
Redstone Repeater (Delay @1)=Повторитель (задержка @1)
Redstone Repeater (Delay @1, Powered)=Повторитель (задержка @1, подключённый)
Transmits redstone power only in one direction=Передаёт энергию редстоуна только в одном направлении
Delays signal=Задерживает сигнал
Output locks when getting active redstone repeater signal from the side=Выход фиксируется при наличии активного сигнала сбоку

View File

@ -0,0 +1,13 @@
# textdomain: mesecons_delayer
Redstone repeaters are versatile redstone components with multiple purposes: 1. They only allow signals to travel in one direction. 2. They delay the signal. 3. Optionally, they can lock their output in one state.=
To power a redstone repeater, send a signal in “arrow” direction (the input). The signal goes out on the opposite side (the output) with a delay. To change the delay, use the redstone repeater. The delay is between 0.1 and 0.4 seconds long and can be changed in steps of 0.1 seconds. It is indicated by the position of the moving redstone torch.=
To lock a repeater, send a signal from an adjacent repeater into one of its sides. While locked, the moving redstone torch disappears, the output doesn't change and the input signal is ignored.=
Redstone Repeater=
Redstone Repeater (Powered)=
Redstone Repeater (Locked)=
Redstone Repeater (Locked, Powered)=
Redstone Repeater (Delay @1)=
Redstone Repeater (Delay @1, Powered)=
Transmits redstone power only in one direction=
Delays signal=
Output locks when getting active redstone repeater signal from the side=

View File

@ -0,0 +1,3 @@
name = mesecons_delayer
depends = mesecons
optional_depends = doc, screwdriver

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

Some files were not shown because too many files have changed in this diff Show More