commit 582545ce2e1b55216a4b2df6e34272440814a349 Author: Henry Behrendt Date: Sun Aug 22 18:59:49 2021 +0200 initial commit Redstone-Mod for Mineclone5 copy from https://git.minetest.land/MineClone5/MineClone5.git diff --git a/README b/README new file mode 100644 index 0000000..779cfa4 --- /dev/null +++ b/README @@ -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 diff --git a/mcl_comparators/init.lua b/mcl_comparators/init.lua new file mode 100644 index 0000000..3517e09 --- /dev/null +++ b/mcl_comparators/init.lua @@ -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 diff --git a/mcl_comparators/locale/mcl_comparators.de.tr b/mcl_comparators/locale/mcl_comparators.de.tr new file mode 100644 index 0000000..d9f6eb4 --- /dev/null +++ b/mcl_comparators/locale/mcl_comparators.de.tr @@ -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) diff --git a/mcl_comparators/locale/mcl_comparators.es.tr b/mcl_comparators/locale/mcl_comparators.es.tr new file mode 100644 index 0000000..581c0ab --- /dev/null +++ b/mcl_comparators/locale/mcl_comparators.es.tr @@ -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) diff --git a/mcl_comparators/locale/mcl_comparators.fr.tr b/mcl_comparators/locale/mcl_comparators.fr.tr new file mode 100644 index 0000000..38a03d3 --- /dev/null +++ b/mcl_comparators/locale/mcl_comparators.fr.tr @@ -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é) diff --git a/mcl_comparators/locale/mcl_comparators.pl.tr b/mcl_comparators/locale/mcl_comparators.pl.tr new file mode 100644 index 0000000..e20d253 --- /dev/null +++ b/mcl_comparators/locale/mcl_comparators.pl.tr @@ -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) + diff --git a/mcl_comparators/locale/mcl_comparators.ru.tr b/mcl_comparators/locale/mcl_comparators.ru.tr new file mode 100644 index 0000000..39a845d --- /dev/null +++ b/mcl_comparators/locale/mcl_comparators.ru.tr @@ -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)=Компаратор (ВЫЧИТАНИЕ, ВКЛЮЧЁН) diff --git a/mcl_comparators/locale/template.txt b/mcl_comparators/locale/template.txt new file mode 100644 index 0000000..d22d017 --- /dev/null +++ b/mcl_comparators/locale/template.txt @@ -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)= diff --git a/mcl_comparators/mod.conf b/mcl_comparators/mod.conf new file mode 100644 index 0000000..100e428 --- /dev/null +++ b/mcl_comparators/mod.conf @@ -0,0 +1,3 @@ +name = mcl_comparators +depends = mcl_wip, mesecons, mcl_sounds +optional_depends = doc, screwdriver diff --git a/mcl_comparators/textures/mcl_comparators_comp.png b/mcl_comparators/textures/mcl_comparators_comp.png new file mode 100644 index 0000000..9967cf5 Binary files /dev/null and b/mcl_comparators/textures/mcl_comparators_comp.png differ diff --git a/mcl_comparators/textures/mcl_comparators_ends_comp.png b/mcl_comparators/textures/mcl_comparators_ends_comp.png new file mode 100644 index 0000000..3b8e747 Binary files /dev/null and b/mcl_comparators/textures/mcl_comparators_ends_comp.png differ diff --git a/mcl_comparators/textures/mcl_comparators_ends_off.png b/mcl_comparators/textures/mcl_comparators_ends_off.png new file mode 100644 index 0000000..02ccb50 Binary files /dev/null and b/mcl_comparators/textures/mcl_comparators_ends_off.png differ diff --git a/mcl_comparators/textures/mcl_comparators_ends_on.png b/mcl_comparators/textures/mcl_comparators_ends_on.png new file mode 100644 index 0000000..33505b3 Binary files /dev/null and b/mcl_comparators/textures/mcl_comparators_ends_on.png differ diff --git a/mcl_comparators/textures/mcl_comparators_ends_sub.png b/mcl_comparators/textures/mcl_comparators_ends_sub.png new file mode 100644 index 0000000..f069746 Binary files /dev/null and b/mcl_comparators/textures/mcl_comparators_ends_sub.png differ diff --git a/mcl_comparators/textures/mcl_comparators_item.png b/mcl_comparators/textures/mcl_comparators_item.png new file mode 100644 index 0000000..7febe57 Binary files /dev/null and b/mcl_comparators/textures/mcl_comparators_item.png differ diff --git a/mcl_comparators/textures/mcl_comparators_off.png b/mcl_comparators/textures/mcl_comparators_off.png new file mode 100644 index 0000000..b7affc2 Binary files /dev/null and b/mcl_comparators/textures/mcl_comparators_off.png differ diff --git a/mcl_comparators/textures/mcl_comparators_on.png b/mcl_comparators/textures/mcl_comparators_on.png new file mode 100644 index 0000000..c2e250d Binary files /dev/null and b/mcl_comparators/textures/mcl_comparators_on.png differ diff --git a/mcl_comparators/textures/mcl_comparators_sides_comp.png b/mcl_comparators/textures/mcl_comparators_sides_comp.png new file mode 100644 index 0000000..536d61b Binary files /dev/null and b/mcl_comparators/textures/mcl_comparators_sides_comp.png differ diff --git a/mcl_comparators/textures/mcl_comparators_sides_off.png b/mcl_comparators/textures/mcl_comparators_sides_off.png new file mode 100644 index 0000000..ba70c3e Binary files /dev/null and b/mcl_comparators/textures/mcl_comparators_sides_off.png differ diff --git a/mcl_comparators/textures/mcl_comparators_sides_on.png b/mcl_comparators/textures/mcl_comparators_sides_on.png new file mode 100644 index 0000000..bb683c9 Binary files /dev/null and b/mcl_comparators/textures/mcl_comparators_sides_on.png differ diff --git a/mcl_comparators/textures/mcl_comparators_sides_sub.png b/mcl_comparators/textures/mcl_comparators_sides_sub.png new file mode 100644 index 0000000..76d9187 Binary files /dev/null and b/mcl_comparators/textures/mcl_comparators_sides_sub.png differ diff --git a/mcl_comparators/textures/mcl_comparators_sub.png b/mcl_comparators/textures/mcl_comparators_sub.png new file mode 100644 index 0000000..a62e6c7 Binary files /dev/null and b/mcl_comparators/textures/mcl_comparators_sub.png differ diff --git a/mcl_dispensers/API.md b/mcl_dispensers/API.md new file mode 100644 index 0000000..419c3ac --- /dev/null +++ b/mcl_dispensers/API.md @@ -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. diff --git a/mcl_dispensers/init.lua b/mcl_dispensers/init.lua new file mode 100644 index 0000000..7c2c073 --- /dev/null +++ b/mcl_dispensers/init.lua @@ -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, +}) diff --git a/mcl_dispensers/locale/mcl_dispensers.de.tr b/mcl_dispensers/locale/mcl_dispensers.de.tr new file mode 100644 index 0000000..129350e --- /dev/null +++ b/mcl_dispensers/locale/mcl_dispensers.de.tr @@ -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 diff --git a/mcl_dispensers/locale/mcl_dispensers.es.tr b/mcl_dispensers/locale/mcl_dispensers.es.tr new file mode 100644 index 0000000..cf69530 --- /dev/null +++ b/mcl_dispensers/locale/mcl_dispensers.es.tr @@ -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 diff --git a/mcl_dispensers/locale/mcl_dispensers.fr.tr b/mcl_dispensers/locale/mcl_dispensers.fr.tr new file mode 100644 index 0000000..622d0a7 --- /dev/null +++ b/mcl_dispensers/locale/mcl_dispensers.fr.tr @@ -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 diff --git a/mcl_dispensers/locale/mcl_dispensers.pl.tr b/mcl_dispensers/locale/mcl_dispensers.pl.tr new file mode 100644 index 0000000..ee2b3cf --- /dev/null +++ b/mcl_dispensers/locale/mcl_dispensers.pl.tr @@ -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 diff --git a/mcl_dispensers/locale/mcl_dispensers.ru.tr b/mcl_dispensers/locale/mcl_dispensers.ru.tr new file mode 100644 index 0000000..af4d856 --- /dev/null +++ b/mcl_dispensers/locale/mcl_dispensers.ru.tr @@ -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=Выбрасывает предметы при подаче энергии редстоуна diff --git a/mcl_dispensers/locale/template.txt b/mcl_dispensers/locale/template.txt new file mode 100644 index 0000000..91129aa --- /dev/null +++ b/mcl_dispensers/locale/template.txt @@ -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= diff --git a/mcl_dispensers/mod.conf b/mcl_dispensers/mod.conf new file mode 100644 index 0000000..13cdb5f --- /dev/null +++ b/mcl_dispensers/mod.conf @@ -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 diff --git a/mcl_dispensers/textures/mcl_dispensers_dispenser_front_horizontal.png b/mcl_dispensers/textures/mcl_dispensers_dispenser_front_horizontal.png new file mode 100644 index 0000000..ca08f4f Binary files /dev/null and b/mcl_dispensers/textures/mcl_dispensers_dispenser_front_horizontal.png differ diff --git a/mcl_dispensers/textures/mcl_dispensers_dispenser_front_vertical.png b/mcl_dispensers/textures/mcl_dispensers_dispenser_front_vertical.png new file mode 100644 index 0000000..2b2328a Binary files /dev/null and b/mcl_dispensers/textures/mcl_dispensers_dispenser_front_vertical.png differ diff --git a/mcl_droppers/init.lua b/mcl_droppers/init.lua new file mode 100644 index 0000000..b5bcc1d --- /dev/null +++ b/mcl_droppers/init.lua @@ -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, +}) diff --git a/mcl_droppers/init_new.lua b/mcl_droppers/init_new.lua new file mode 100644 index 0000000..5409e6a --- /dev/null +++ b/mcl_droppers/init_new.lua @@ -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, +}) + diff --git a/mcl_droppers/locale/mcl_droppers.de.tr b/mcl_droppers/locale/mcl_droppers.de.tr new file mode 100644 index 0000000..a4eb2eb --- /dev/null +++ b/mcl_droppers/locale/mcl_droppers.de.tr @@ -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 diff --git a/mcl_droppers/locale/mcl_droppers.es.tr b/mcl_droppers/locale/mcl_droppers.es.tr new file mode 100644 index 0000000..8fd8104 --- /dev/null +++ b/mcl_droppers/locale/mcl_droppers.es.tr @@ -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 diff --git a/mcl_droppers/locale/mcl_droppers.fr.tr b/mcl_droppers/locale/mcl_droppers.fr.tr new file mode 100644 index 0000000..137400d --- /dev/null +++ b/mcl_droppers/locale/mcl_droppers.fr.tr @@ -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 diff --git a/mcl_droppers/locale/mcl_droppers.pl.tr b/mcl_droppers/locale/mcl_droppers.pl.tr new file mode 100644 index 0000000..7b0fd3c --- /dev/null +++ b/mcl_droppers/locale/mcl_droppers.pl.tr @@ -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 diff --git a/mcl_droppers/locale/mcl_droppers.ru.tr b/mcl_droppers/locale/mcl_droppers.ru.tr new file mode 100644 index 0000000..2235867 --- /dev/null +++ b/mcl_droppers/locale/mcl_droppers.ru.tr @@ -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=Выбрасывает предмет при подаче энергии редстоуна diff --git a/mcl_droppers/locale/template.txt b/mcl_droppers/locale/template.txt new file mode 100644 index 0000000..24b2bc1 --- /dev/null +++ b/mcl_droppers/locale/template.txt @@ -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= diff --git a/mcl_droppers/mod.conf b/mcl_droppers/mod.conf new file mode 100644 index 0000000..bbb1c19 --- /dev/null +++ b/mcl_droppers/mod.conf @@ -0,0 +1,3 @@ +name = mcl_droppers +depends = mcl_init, mcl_formspec, mesecons, mcl_util +optional_depends = doc, screwdriver diff --git a/mcl_droppers/textures/mcl_droppers_dropper_front_horizontal.png b/mcl_droppers/textures/mcl_droppers_dropper_front_horizontal.png new file mode 100644 index 0000000..e247e92 Binary files /dev/null and b/mcl_droppers/textures/mcl_droppers_dropper_front_horizontal.png differ diff --git a/mcl_droppers/textures/mcl_droppers_dropper_front_vertical.png b/mcl_droppers/textures/mcl_droppers_dropper_front_vertical.png new file mode 100644 index 0000000..37bc9fa Binary files /dev/null and b/mcl_droppers/textures/mcl_droppers_dropper_front_vertical.png differ diff --git a/mcl_observers/init.lua b/mcl_observers/init.lua new file mode 100644 index 0000000..6045b56 --- /dev/null +++ b/mcl_observers/init.lua @@ -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, +}) diff --git a/mcl_observers/locale/mcl_observers.de.tr b/mcl_observers/locale/mcl_observers.de.tr new file mode 100644 index 0000000..3ce085a --- /dev/null +++ b/mcl_observers/locale/mcl_observers.de.tr @@ -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 diff --git a/mcl_observers/locale/mcl_observers.es.tr b/mcl_observers/locale/mcl_observers.es.tr new file mode 100644 index 0000000..146b72b --- /dev/null +++ b/mcl_observers/locale/mcl_observers.es.tr @@ -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í. diff --git a/mcl_observers/locale/mcl_observers.fr.tr b/mcl_observers/locale/mcl_observers.fr.tr new file mode 100644 index 0000000..3295335 --- /dev/null +++ b/mcl_observers/locale/mcl_observers.fr.tr @@ -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 diff --git a/mcl_observers/locale/mcl_observers.pl.tr b/mcl_observers/locale/mcl_observers.pl.tr new file mode 100644 index 0000000..9c789be --- /dev/null +++ b/mcl_observers/locale/mcl_observers.pl.tr @@ -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 + diff --git a/mcl_observers/locale/mcl_observers.ru.tr b/mcl_observers/locale/mcl_observers.ru.tr new file mode 100644 index 0000000..ac8c658 --- /dev/null +++ b/mcl_observers/locale/mcl_observers.ru.tr @@ -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=Генерирует импульс редстоуна при смене блока, находящегося перед ним diff --git a/mcl_observers/locale/template.txt b/mcl_observers/locale/template.txt new file mode 100644 index 0000000..7f59915 --- /dev/null +++ b/mcl_observers/locale/template.txt @@ -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= diff --git a/mcl_observers/mod.conf b/mcl_observers/mod.conf new file mode 100644 index 0000000..fce0019 --- /dev/null +++ b/mcl_observers/mod.conf @@ -0,0 +1,2 @@ +name = mcl_observers +depends = mesecons, mcl_util diff --git a/mcl_observers/textures/mcl_observers_observer_back.png b/mcl_observers/textures/mcl_observers_observer_back.png new file mode 100644 index 0000000..5ecef7d Binary files /dev/null and b/mcl_observers/textures/mcl_observers_observer_back.png differ diff --git a/mcl_observers/textures/mcl_observers_observer_back_lit.png b/mcl_observers/textures/mcl_observers_observer_back_lit.png new file mode 100644 index 0000000..da70498 Binary files /dev/null and b/mcl_observers/textures/mcl_observers_observer_back_lit.png differ diff --git a/mcl_observers/textures/mcl_observers_observer_front.png b/mcl_observers/textures/mcl_observers_observer_front.png new file mode 100644 index 0000000..115f5ca Binary files /dev/null and b/mcl_observers/textures/mcl_observers_observer_front.png differ diff --git a/mcl_observers/textures/mcl_observers_observer_side.png b/mcl_observers/textures/mcl_observers_observer_side.png new file mode 100644 index 0000000..84cd406 Binary files /dev/null and b/mcl_observers/textures/mcl_observers_observer_side.png differ diff --git a/mcl_observers/textures/mcl_observers_observer_top.png b/mcl_observers/textures/mcl_observers_observer_top.png new file mode 100644 index 0000000..73dab21 Binary files /dev/null and b/mcl_observers/textures/mcl_observers_observer_top.png differ diff --git a/mesecons/actionqueue.lua b/mesecons/actionqueue.lua new file mode 100644 index 0000000..489a81b --- /dev/null +++ b/mesecons/actionqueue.lua @@ -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) diff --git a/mesecons/init.lua b/mesecons/init.lua new file mode 100644 index 0000000..1896528 --- /dev/null +++ b/mesecons/init.lua @@ -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"); diff --git a/mesecons/internal.lua b/mesecons/internal.lua new file mode 100644 index 0000000..dbe3ebe --- /dev/null +++ b/mesecons/internal.lua @@ -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 + diff --git a/mesecons/mod.conf b/mesecons/mod.conf new file mode 100644 index 0000000..94be765 --- /dev/null +++ b/mesecons/mod.conf @@ -0,0 +1,3 @@ +name = mesecons +depends = mcl_sounds, mcl_core +optional_depends = doc diff --git a/mesecons/presets.lua b/mesecons/presets.lua new file mode 100644 index 0000000..d9d8418 --- /dev/null +++ b/mesecons/presets.lua @@ -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" diff --git a/mesecons/services.lua b/mesecons/services.lua new file mode 100644 index 0000000..7d1fce2 --- /dev/null +++ b/mesecons/services.lua @@ -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) diff --git a/mesecons/settings.lua b/mesecons/settings.lua new file mode 100644 index 0000000..0220707 --- /dev/null +++ b/mesecons/settings.lua @@ -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 diff --git a/mesecons/util.lua b/mesecons/util.lua new file mode 100644 index 0000000..b660252 --- /dev/null +++ b/mesecons/util.lua @@ -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 node’s 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 server’s main map data cache and then accessed from there. +-- +-- Inside a VM transaction, the transaction’s 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 server’s main map data cache and then accessed from there. +-- +-- Inside a VM transaction, the transaction’s VM cache is used. +-- +-- This function can only be used to change the node’s 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 diff --git a/mesecons_alias/init.lua b/mesecons_alias/init.lua new file mode 100644 index 0000000..111a4b1 --- /dev/null +++ b/mesecons_alias/init.lua @@ -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") diff --git a/mesecons_alias/mod.conf b/mesecons_alias/mod.conf new file mode 100644 index 0000000..533d54c --- /dev/null +++ b/mesecons_alias/mod.conf @@ -0,0 +1,2 @@ +name = mesecons_alias +depends = mesecons diff --git a/mesecons_button/README.md b/mesecons_button/README.md new file mode 100644 index 0000000..31a1fa9 --- /dev/null +++ b/mesecons_button/README.md @@ -0,0 +1,16 @@ +Mesecons button mod. +This mod adds the buttons for MineClone 2. + +MEDIA FILE CREDITS: + +`mesecons_button_push.ogg` + * Author: junggle + * License: CC BY 3.0 + * Original name: `btn121.ogg`, created on January 16th, 2007 + * Source: +`mesecons_button_push_wood.ogg` + * Author: junggle + * License: (CC BY 3.0 + * Original name: `btn314.ogg`, created on January 16th, 2007 + * Sound file was modified + * Source: diff --git a/mesecons_button/init.lua b/mesecons_button/init.lua new file mode 100644 index 0000000..2812b27 --- /dev/null +++ b/mesecons_button/init.lua @@ -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 diff --git a/mesecons_button/locale/mesecons_button.de.tr b/mesecons_button/locale/mesecons_button.de.tr new file mode 100644 index 0000000..9b311b9 --- /dev/null +++ b/mesecons_button/locale/mesecons_button.de.tr @@ -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 diff --git a/mesecons_button/locale/mesecons_button.es.tr b/mesecons_button/locale/mesecons_button.es.tr new file mode 100644 index 0000000..d793b7a --- /dev/null +++ b/mesecons_button/locale/mesecons_button.es.tr @@ -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. diff --git a/mesecons_button/locale/mesecons_button.fr.tr b/mesecons_button/locale/mesecons_button.fr.tr new file mode 100644 index 0000000..96f963b --- /dev/null +++ b/mesecons_button/locale/mesecons_button.fr.tr @@ -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 diff --git a/mesecons_button/locale/mesecons_button.pl.tr b/mesecons_button/locale/mesecons_button.pl.tr new file mode 100644 index 0000000..f6d895a --- /dev/null +++ b/mesecons_button/locale/mesecons_button.pl.tr @@ -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łą diff --git a/mesecons_button/locale/mesecons_button.ru.tr b/mesecons_button/locale/mesecons_button.ru.tr new file mode 100644 index 0000000..a89c809 --- /dev/null +++ b/mesecons_button/locale/mesecons_button.ru.tr @@ -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=Нажимается стрелами diff --git a/mesecons_button/locale/template.txt b/mesecons_button/locale/template.txt new file mode 100644 index 0000000..4c352b8 --- /dev/null +++ b/mesecons_button/locale/template.txt @@ -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= diff --git a/mesecons_button/mod.conf b/mesecons_button/mod.conf new file mode 100644 index 0000000..be12736 --- /dev/null +++ b/mesecons_button/mod.conf @@ -0,0 +1,3 @@ +name = mesecons_button +depends = mesecons +optional_depends = doc diff --git a/mesecons_button/sounds/mesecons_button_push.ogg b/mesecons_button/sounds/mesecons_button_push.ogg new file mode 100644 index 0000000..5ddc193 Binary files /dev/null and b/mesecons_button/sounds/mesecons_button_push.ogg differ diff --git a/mesecons_button/sounds/mesecons_button_push_wood.ogg b/mesecons_button/sounds/mesecons_button_push_wood.ogg new file mode 100644 index 0000000..23f53c4 Binary files /dev/null and b/mesecons_button/sounds/mesecons_button_push_wood.ogg differ diff --git a/mesecons_button/textures/mesecons_button_wield_mask.png b/mesecons_button/textures/mesecons_button_wield_mask.png new file mode 100644 index 0000000..211ac43 Binary files /dev/null and b/mesecons_button/textures/mesecons_button_wield_mask.png differ diff --git a/mesecons_commandblock/init.lua b/mesecons_commandblock/init.lua new file mode 100644 index 0000000..3902c3c --- /dev/null +++ b/mesecons_commandblock/init.lua @@ -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 diff --git a/mesecons_commandblock/locale/mesecons_commandblock.de.tr b/mesecons_commandblock/locale/mesecons_commandblock.de.tr new file mode 100644 index 0000000..a149fee --- /dev/null +++ b/mesecons_commandblock/locale/mesecons_commandblock.de.tr @@ -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= diff --git a/mesecons_commandblock/locale/mesecons_commandblock.es.tr b/mesecons_commandblock/locale/mesecons_commandblock.es.tr new file mode 100644 index 0000000..938c710 --- /dev/null +++ b/mesecons_commandblock/locale/mesecons_commandblock.es.tr @@ -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= diff --git a/mesecons_commandblock/locale/mesecons_commandblock.fr.tr b/mesecons_commandblock/locale/mesecons_commandblock.fr.tr new file mode 100644 index 0000000..b397c97 --- /dev/null +++ b/mesecons_commandblock/locale/mesecons_commandblock.fr.tr @@ -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 diff --git a/mesecons_commandblock/locale/mesecons_commandblock.pl.tr b/mesecons_commandblock/locale/mesecons_commandblock.pl.tr new file mode 100644 index 0000000..6ee1afc --- /dev/null +++ b/mesecons_commandblock/locale/mesecons_commandblock.pl.tr @@ -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 + diff --git a/mesecons_commandblock/locale/mesecons_commandblock.ru.tr b/mesecons_commandblock/locale/mesecons_commandblock.ru.tr new file mode 100644 index 0000000..85bed4b --- /dev/null +++ b/mesecons_commandblock/locale/mesecons_commandblock.ru.tr @@ -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= diff --git a/mesecons_commandblock/locale/template.txt b/mesecons_commandblock/locale/template.txt new file mode 100644 index 0000000..49e98ef --- /dev/null +++ b/mesecons_commandblock/locale/template.txt @@ -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= diff --git a/mesecons_commandblock/mod.conf b/mesecons_commandblock/mod.conf new file mode 100644 index 0000000..2605953 --- /dev/null +++ b/mesecons_commandblock/mod.conf @@ -0,0 +1,3 @@ +name = mesecons_commandblock +depends = mesecons, mcl_colors, mcl_util +optional_depends = doc, doc_items diff --git a/mesecons_commandblock/textures/jeija_commandblock_off.png b/mesecons_commandblock/textures/jeija_commandblock_off.png new file mode 100644 index 0000000..3df0479 Binary files /dev/null and b/mesecons_commandblock/textures/jeija_commandblock_off.png differ diff --git a/mesecons_commandblock/textures/jeija_commandblock_on.png b/mesecons_commandblock/textures/jeija_commandblock_on.png new file mode 100644 index 0000000..3df0479 Binary files /dev/null and b/mesecons_commandblock/textures/jeija_commandblock_on.png differ diff --git a/mesecons_delayer/init.lua b/mesecons_delayer/init.lua new file mode 100644 index 0000000..fc12c0a --- /dev/null +++ b/mesecons_delayer/init.lua @@ -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 diff --git a/mesecons_delayer/locale/mesecons_delayer.de.tr b/mesecons_delayer/locale/mesecons_delayer.de.tr new file mode 100644 index 0000000..45c9595 --- /dev/null +++ b/mesecons_delayer/locale/mesecons_delayer.de.tr @@ -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 diff --git a/mesecons_delayer/locale/mesecons_delayer.es.tr b/mesecons_delayer/locale/mesecons_delayer.es.tr new file mode 100644 index 0000000..fd502c7 --- /dev/null +++ b/mesecons_delayer/locale/mesecons_delayer.es.tr @@ -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) diff --git a/mesecons_delayer/locale/mesecons_delayer.fr.tr b/mesecons_delayer/locale/mesecons_delayer.fr.tr new file mode 100644 index 0000000..e283171 --- /dev/null +++ b/mesecons_delayer/locale/mesecons_delayer.fr.tr @@ -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é diff --git a/mesecons_delayer/locale/mesecons_delayer.pl.tr b/mesecons_delayer/locale/mesecons_delayer.pl.tr new file mode 100644 index 0000000..ed533e2 --- /dev/null +++ b/mesecons_delayer/locale/mesecons_delayer.pl.tr @@ -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 diff --git a/mesecons_delayer/locale/mesecons_delayer.ru.tr b/mesecons_delayer/locale/mesecons_delayer.ru.tr new file mode 100644 index 0000000..f95d3ee --- /dev/null +++ b/mesecons_delayer/locale/mesecons_delayer.ru.tr @@ -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=Выход фиксируется при наличии активного сигнала сбоку diff --git a/mesecons_delayer/locale/template.txt b/mesecons_delayer/locale/template.txt new file mode 100644 index 0000000..5801248 --- /dev/null +++ b/mesecons_delayer/locale/template.txt @@ -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= diff --git a/mesecons_delayer/mod.conf b/mesecons_delayer/mod.conf new file mode 100644 index 0000000..3f84462 --- /dev/null +++ b/mesecons_delayer/mod.conf @@ -0,0 +1,3 @@ +name = mesecons_delayer +depends = mesecons +optional_depends = doc, screwdriver diff --git a/mesecons_delayer/textures/mesecons_delayer_end_locked_off.png b/mesecons_delayer/textures/mesecons_delayer_end_locked_off.png new file mode 100644 index 0000000..bee3eeb Binary files /dev/null and b/mesecons_delayer/textures/mesecons_delayer_end_locked_off.png differ diff --git a/mesecons_delayer/textures/mesecons_delayer_end_locked_on.png b/mesecons_delayer/textures/mesecons_delayer_end_locked_on.png new file mode 100644 index 0000000..3347f1b Binary files /dev/null and b/mesecons_delayer/textures/mesecons_delayer_end_locked_on.png differ diff --git a/mesecons_delayer/textures/mesecons_delayer_ends_off.png b/mesecons_delayer/textures/mesecons_delayer_ends_off.png new file mode 100644 index 0000000..ed6f4a0 Binary files /dev/null and b/mesecons_delayer/textures/mesecons_delayer_ends_off.png differ diff --git a/mesecons_delayer/textures/mesecons_delayer_ends_on.png b/mesecons_delayer/textures/mesecons_delayer_ends_on.png new file mode 100644 index 0000000..8569fcd Binary files /dev/null and b/mesecons_delayer/textures/mesecons_delayer_ends_on.png differ diff --git a/mesecons_delayer/textures/mesecons_delayer_front_locked_off.png b/mesecons_delayer/textures/mesecons_delayer_front_locked_off.png new file mode 100644 index 0000000..e8cff32 Binary files /dev/null and b/mesecons_delayer/textures/mesecons_delayer_front_locked_off.png differ diff --git a/mesecons_delayer/textures/mesecons_delayer_front_locked_on.png b/mesecons_delayer/textures/mesecons_delayer_front_locked_on.png new file mode 100644 index 0000000..59ca938 Binary files /dev/null and b/mesecons_delayer/textures/mesecons_delayer_front_locked_on.png differ diff --git a/mesecons_delayer/textures/mesecons_delayer_item.png b/mesecons_delayer/textures/mesecons_delayer_item.png new file mode 100644 index 0000000..1d27971 Binary files /dev/null and b/mesecons_delayer/textures/mesecons_delayer_item.png differ diff --git a/mesecons_delayer/textures/mesecons_delayer_locked_off.png b/mesecons_delayer/textures/mesecons_delayer_locked_off.png new file mode 100644 index 0000000..3a5482a Binary files /dev/null and b/mesecons_delayer/textures/mesecons_delayer_locked_off.png differ diff --git a/mesecons_delayer/textures/mesecons_delayer_locked_on.png b/mesecons_delayer/textures/mesecons_delayer_locked_on.png new file mode 100644 index 0000000..7e905a6 Binary files /dev/null and b/mesecons_delayer/textures/mesecons_delayer_locked_on.png differ diff --git a/mesecons_delayer/textures/mesecons_delayer_off.png b/mesecons_delayer/textures/mesecons_delayer_off.png new file mode 100644 index 0000000..ed33c42 Binary files /dev/null and b/mesecons_delayer/textures/mesecons_delayer_off.png differ diff --git a/mesecons_delayer/textures/mesecons_delayer_on.png b/mesecons_delayer/textures/mesecons_delayer_on.png new file mode 100644 index 0000000..2456cf0 Binary files /dev/null and b/mesecons_delayer/textures/mesecons_delayer_on.png differ diff --git a/mesecons_delayer/textures/mesecons_delayer_sides_locked_off.png b/mesecons_delayer/textures/mesecons_delayer_sides_locked_off.png new file mode 100644 index 0000000..8b857bd Binary files /dev/null and b/mesecons_delayer/textures/mesecons_delayer_sides_locked_off.png differ diff --git a/mesecons_delayer/textures/mesecons_delayer_sides_locked_on.png b/mesecons_delayer/textures/mesecons_delayer_sides_locked_on.png new file mode 100644 index 0000000..c98e9d1 Binary files /dev/null and b/mesecons_delayer/textures/mesecons_delayer_sides_locked_on.png differ diff --git a/mesecons_delayer/textures/mesecons_delayer_sides_off.png b/mesecons_delayer/textures/mesecons_delayer_sides_off.png new file mode 100644 index 0000000..326dbe6 Binary files /dev/null and b/mesecons_delayer/textures/mesecons_delayer_sides_off.png differ diff --git a/mesecons_delayer/textures/mesecons_delayer_sides_on.png b/mesecons_delayer/textures/mesecons_delayer_sides_on.png new file mode 100644 index 0000000..bab909e Binary files /dev/null and b/mesecons_delayer/textures/mesecons_delayer_sides_on.png differ diff --git a/mesecons_lightstone/init.lua b/mesecons_lightstone/init.lua new file mode 100644 index 0000000..0e517e4 --- /dev/null +++ b/mesecons_lightstone/init.lua @@ -0,0 +1,54 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + +local light = minetest.LIGHT_MAX + +minetest.register_node("mesecons_lightstone:lightstone_off", { + tiles = {"jeija_lightstone_gray_off.png"}, + groups = {handy=1, mesecon_effector_off = 1, mesecon = 2}, + is_ground_content = false, + description= S("Redstone Lamp"), + _tt_help = S("Glows when powered by redstone power"), + _doc_items_longdesc = S("Redstone lamps are simple redstone components which glow brightly (light level @1) when they receive redstone power.", light), + sounds = mcl_sounds.node_sound_glass_defaults(), + mesecons = {effector = { + action_on = function(pos, node) + minetest.swap_node(pos, {name="mesecons_lightstone:lightstone_on", param2 = node.param2}) + end, + rules = mesecon.rules.alldirs, + }}, + _mcl_blast_resistance = 0.3, + _mcl_hardness = 0.3, +}) + +minetest.register_node("mesecons_lightstone:lightstone_on", { + tiles = {"jeija_lightstone_gray_on.png"}, + groups = {handy=1, not_in_creative_inventory=1, mesecon = 2, opaque = 1}, + drop = "node mesecons_lightstone:lightstone_off", + is_ground_content = false, + paramtype = "light", + light_source = light, + sounds = mcl_sounds.node_sound_glass_defaults(), + mesecons = {effector = { + action_off = function(pos, node) + minetest.swap_node(pos, {name="mesecons_lightstone:lightstone_off", param2 = node.param2}) + end, + rules = mesecon.rules.alldirs, + }}, + _mcl_blast_resistance = 0.3, + _mcl_hardness = 0.3, +}) + +minetest.register_craft({ + output = "mesecons_lightstone:lightstone_off", + recipe = { + {"","mesecons:redstone",""}, + {"mesecons:redstone","mcl_nether:glowstone","mesecons:redstone"}, + {"","mesecons:redstone",""}, + } +}) + +-- Add entry alias for the Help +if minetest.get_modpath("doc") then + doc.add_entry_alias("nodes", "mesecons_lightstone:lightstone_off", "nodes", "mesecons_lightstone:lightstone_on") +end + diff --git a/mesecons_lightstone/locale/mesecons_lightstone.de.tr b/mesecons_lightstone/locale/mesecons_lightstone.de.tr new file mode 100644 index 0000000..a0cfc22 --- /dev/null +++ b/mesecons_lightstone/locale/mesecons_lightstone.de.tr @@ -0,0 +1,4 @@ +# textdomain: mesecons_lightstone +Redstone Lamp=Redstonelampe +Redstone lamps are simple redstone components which glow brightly (light level @1) when they receive redstone power.=Redstonelampen sind einfache Redstonekomponenten, die hell aufleuchten (Helligkeitspegel von @1), wenn sie Redstoneenergie erhalten. +Glows when powered by redstone power=Leuchtet, wenn mit Redstoneenergie versorgt diff --git a/mesecons_lightstone/locale/mesecons_lightstone.es.tr b/mesecons_lightstone/locale/mesecons_lightstone.es.tr new file mode 100644 index 0000000..713f0be --- /dev/null +++ b/mesecons_lightstone/locale/mesecons_lightstone.es.tr @@ -0,0 +1,3 @@ +# textdomain: mesecons_lightstone +Redstone Lamp=Lámpara de redstone +Redstone lamps are simple redstone components which glow brightly (light level @1) when they receive redstone power.=Las lámparas Redstone son componentes simples de redstone que brillan intensamente (nivel de luz @ 1) cuando reciben energía de redstone. diff --git a/mesecons_lightstone/locale/mesecons_lightstone.fr.tr b/mesecons_lightstone/locale/mesecons_lightstone.fr.tr new file mode 100644 index 0000000..16601ac --- /dev/null +++ b/mesecons_lightstone/locale/mesecons_lightstone.fr.tr @@ -0,0 +1,4 @@ +# textdomain: mesecons_lightstone +Redstone Lamp=Lampe Redstone +Redstone lamps are simple redstone components which glow brightly (light level @1) when they receive redstone power.=Les lampes Redstone sont de simples composants Redstone qui brillent (niveau de lumière @1) lorsqu'elles reçoivent une puissance Redstone. +Glows when powered by redstone power=Brille lorsqu'il est alimenté par la puissance Redstone diff --git a/mesecons_lightstone/locale/mesecons_lightstone.pl.tr b/mesecons_lightstone/locale/mesecons_lightstone.pl.tr new file mode 100644 index 0000000..cd2f755 --- /dev/null +++ b/mesecons_lightstone/locale/mesecons_lightstone.pl.tr @@ -0,0 +1,4 @@ +# textdomain: mesecons_lightstone +Redstone Lamp=Lampa czerwienitowa +Redstone lamps are simple redstone components which glow brightly (light level @1) when they receive redstone power.=Lampy czerwienitowe to mechanizmy czerwienitowe, które jasno świecą (poziom światła @1), gdy są zasilone energią czerwienitową. +Glows when powered by redstone power=Świeci gdy zasilana czerwienitem diff --git a/mesecons_lightstone/locale/mesecons_lightstone.ru.tr b/mesecons_lightstone/locale/mesecons_lightstone.ru.tr new file mode 100644 index 0000000..cd1592a --- /dev/null +++ b/mesecons_lightstone/locale/mesecons_lightstone.ru.tr @@ -0,0 +1,4 @@ +# textdomain: mesecons_lightstone +Redstone Lamp=Лампа редстоуна +Redstone lamps are simple redstone components which glow brightly (light level @1) when they receive redstone power.=Лампа редстоуна это простой компонент редстоуна, который ярко светится (уровень света @1) при подаче на него энергии редстоуна. +Glows when powered by redstone power=Светит при подаче энергии редстоуна diff --git a/mesecons_lightstone/locale/template.txt b/mesecons_lightstone/locale/template.txt new file mode 100644 index 0000000..2d2cc41 --- /dev/null +++ b/mesecons_lightstone/locale/template.txt @@ -0,0 +1,4 @@ +# textdomain: mesecons_lightstone +Redstone Lamp= +Redstone lamps are simple redstone components which glow brightly (light level @1) when they receive redstone power.= +Glows when powered by redstone power= diff --git a/mesecons_lightstone/mod.conf b/mesecons_lightstone/mod.conf new file mode 100644 index 0000000..95811bd --- /dev/null +++ b/mesecons_lightstone/mod.conf @@ -0,0 +1,3 @@ +name = mesecons_lightstone +depends = mesecons +optional_depends = doc diff --git a/mesecons_lightstone/textures/jeija_lightstone_gray_off.png b/mesecons_lightstone/textures/jeija_lightstone_gray_off.png new file mode 100644 index 0000000..7f0c18b Binary files /dev/null and b/mesecons_lightstone/textures/jeija_lightstone_gray_off.png differ diff --git a/mesecons_lightstone/textures/jeija_lightstone_gray_on.png b/mesecons_lightstone/textures/jeija_lightstone_gray_on.png new file mode 100644 index 0000000..b2f44e7 Binary files /dev/null and b/mesecons_lightstone/textures/jeija_lightstone_gray_on.png differ diff --git a/mesecons_mvps/init.lua b/mesecons_mvps/init.lua new file mode 100644 index 0000000..fedb8fa --- /dev/null +++ b/mesecons_mvps/init.lua @@ -0,0 +1,430 @@ +local table = table + +--register stoppers for movestones/pistons + +mesecon.mvps_stoppers = {} +mesecon.mvps_unsticky = {} +mesecon.mvps_droppers = {} +mesecon.on_mvps_move = {} +mesecon.mvps_unmov = {} + +--- Objects (entities) that cannot be moved +function mesecon.register_mvps_unmov(objectname) + mesecon.mvps_unmov[objectname] = true; +end + +function mesecon.is_mvps_unmov(objectname) + return mesecon.mvps_unmov[objectname] +end + +function mesecon.is_mvps_dropper(node, pushdir, stack, stackid) + local get_dropper = mesecon.mvps_droppers[node.name] + if type (get_dropper) == "function" then + get_dropper = get_dropper(node, pushdir, stack, stackid) + end + if not get_dropper then + get_dropper = minetest.get_item_group(node.name, "dig_by_piston") == 1 + end + return get_dropper +end + +function mesecon.register_mvps_dropper(nodename, get_dropper) + if get_dropper == nil then + get_dropper = true + end + mesecon.mvps_droppers[nodename] = get_dropper +end + +-- Nodes that cannot be pushed / pulled by movestones, pistons +function mesecon.is_mvps_stopper(node) + -- unknown nodes are always stoppers + return mesecon.mvps_stoppers[node.name] or not minetest.registered_nodes[node.name] +end + +function mesecon.register_mvps_stopper(nodename) + mesecon.mvps_stoppers[nodename] = true +end + +-- For nodes which ignore sticky sides. +-- They can't be pulled by sticky pistons and don't interact with slime blocks. +-- TODO: This has NOT any actual effect so far. The actual functionality +-- still needs to be implemented. +function mesecon.register_mvps_unsticky(nodename, get_unsticky) + if get_unsticky == nil then + get_unsticky = true + end + mesecon.mvps_unsticky[nodename] = get_unsticky +end + +function mesecon.is_mvps_unsticky(node, pulldir, stack, stackid) + -- unknown nodes are always unsticky + if not minetest.registered_nodes[node.name] then + return true + end + + local get_unsticky = mesecon.mvps_unsticky[node.name] + if type(get_unsticky) == "function" then + get_unsticky = get_unsticky(node, pulldir, stack, stackid) + end + if get_unsticky == nil then + get_unsticky = false + end + + return get_unsticky +end + +-- Functions to be called on mvps movement +-- See also the callback +function mesecon.register_on_mvps_move(callback) + mesecon.on_mvps_move[#mesecon.on_mvps_move+1] = callback +end + +local function on_mvps_move(moved_nodes) + for _, callback in ipairs(mesecon.on_mvps_move) do + callback(moved_nodes) + end +end + +function mesecon.mvps_process_stack(stack) + -- update mesecons for placed nodes ( has to be done after all nodes have been added ) + for _, n in ipairs(stack) do + mesecon.on_placenode(n.pos, minetest.get_node(n.pos)) + end +end + +-- tests if the node can be pushed into, e.g. air, water, grass +local function node_replaceable(name) + if name == "ignore" then return true end + + if minetest.registered_nodes[name] then + return minetest.registered_nodes[name].buildable_to or false + end + + return false +end + +local function is_available(pos) + local n = minetest.get_node(pos) + if not n then + return false, n + end + local name = n.name + if name == "ignore" then + minetest.get_voxel_manip():read_from_map(pos, pos) + n = minetest.get_node(pos) + if not n then + return false, n + end + name = n.name + end + if name == "ignore" then + return false, n + end + if minetest.registered_nodes[name] then + return minetest.registered_nodes[name].buildable_to, n or false, n + end + return false, n +end + + +function mesecon.mvps_get_stack(pos, dir, maximum, piston_pos) + -- determine the number of nodes to be pushed + local nodes = {} + local frontiers = {pos} + + while #frontiers > 0 do + local np = frontiers[1] + local nn = minetest.get_node(np) + if nn.name == "ignore" then + minetest.get_voxel_manip():read_from_map(np, np) + nn = minetest.get_node(np) + end + + if mesecon.is_mvps_stopper(nn) then + return + end + + if not node_replaceable(nn.name) then + if #nodes >= maximum then return nil, false end + table.insert(nodes, {node = nn, pos = {x=np.x, y=np.y, z=np.z}}) + + -- add connected nodes to frontiers, connected is a vector list + -- the vectors must be absolute positions + local connected = {} + local has_loop + if minetest.registered_nodes[nn.name] + and minetest.registered_nodes[nn.name].mvps_sticky then + connected, has_loop = minetest.registered_nodes[nn.name].mvps_sticky(np, nn, piston_pos) + if has_loop then + return {}, true + end + end + + table.insert(connected, vector.add(np, dir)) + + -- Make sure there are no duplicates in frontiers / nodes before + -- adding nodes in "connected" to frontiers + for _, cp in ipairs(connected) do + local duplicate = false + for _, rp in ipairs(nodes) do + if vector.equals(cp, rp.pos) then + duplicate = true + end + end + for _, fp in ipairs(frontiers) do + if vector.equals(cp, fp) then + duplicate = true + end + end + if not duplicate and not mesecon.is_mvps_stopper(minetest.get_node(cp)) then + table.insert(frontiers, cp) + end + end + end + table.remove(frontiers, 1) + end + + return nodes, false +end + +function mesecon.mvps_set_owner(pos, placer) + local meta = minetest.get_meta(pos) + local owner = placer and placer.get_player_name and placer:get_player_name() + if owner and owner ~= "" then + meta:set_string("owner", owner) + else + meta:set_string("owner", "$unknown") -- to distinguish from older pistons + end +end + +local function are_protected(nodes, player_name) + for _, node in pairs(nodes) do + if minetest.is_protected(node.pos, player_name) then + return true + end + end + return false +end + +function mesecon.mvps_push(pos, dir, maximum, player_name, piston_pos) + return mesecon.mvps_push_or_pull(pos, dir, dir, maximum, player_name, piston_pos) +end + +function mesecon.mvps_pull_single(pos, dir, maximum, player_name, piston_pos) + return mesecon.mvps_push_or_pull(pos, vector.multiply(dir, -1), dir, maximum, player_name, piston_pos) +end + +-- pos: pos of mvps; stackdir: direction of building the stack +-- movedir: direction of actual movement +-- maximum: maximum nodes to be pushed +function mesecon.mvps_push_or_pull(pos, stackdir, movedir, maximum, player_name, piston_pos) + local nodes, has_loop = mesecon.mvps_get_stack(pos, movedir, maximum, piston_pos) + + if has_loop then + return false + end + + if not nodes then return end + + local newpos={} + -- check node availability to push/pull into, and fill newpos[i] + for i in ipairs(nodes) do + newpos[i] = vector.add(nodes[i].pos, movedir) + if (newpos[i].x == piston_pos.x) and (newpos[i].y == piston_pos.y) and (newpos[i].z == piston_pos.z) then + return + end + if not is_available(newpos[i]) then + local available = false + for j in ipairs(nodes) do + if i ~= j then + if (newpos[i].x == nodes[j].pos.x) and (newpos[i].y == nodes[j].pos.y) and (newpos[i].z == nodes[j].pos.z) then + available = true + break + end + end + end + if not available then + return + end + end + end + + if are_protected(nodes, player_name) then + return + end + + local first_dropper = nil + -- remove all nodes + for id, n in ipairs(nodes) do + n.meta = minetest.get_meta(n.pos):to_table() + local is_dropper = mesecon.is_mvps_dropper(n.node, movedir, nodes, id) + if is_dropper then + --local drops = minetest.get_node_drops(n.node.name, "") + minetest.dig_node(n.pos) + else + minetest.remove_node(n.pos) + local node_timer = minetest.get_node_timer(n.pos) + if node_timer:is_started() then + n.node_timer = {node_timer:get_timeout(), node_timer:get_elapsed()} + end + end + if is_dropper then + first_dropper = id + break + end + end + + -- update mesecons for removed nodes ( has to be done after all nodes have been removed ) + for id, n in ipairs(nodes) do + if first_dropper and id >= first_dropper then + break + end + mesecon.on_dignode(n.pos, n.node) + end + + -- add nodes + for id, n in ipairs(nodes) do + if first_dropper and id >= first_dropper then + break + end + local np = newpos[id] + minetest.add_node(np, n.node) + minetest.get_meta(np):from_table(n.meta) + if n.node_timer then + minetest.get_node_timer(np):set(unpack(n.node_timer)) + end + if string.find(n.node.name, "mcl_observers:observer") then + -- It also counts as a block update when the observer itself is moved by a piston (Wiki): + mcl_observers.observer_activate(np) + end + end + + local moved_nodes = {} + local oldstack = mesecon.tablecopy(nodes) + for i in ipairs(nodes) do + if first_dropper and i >= first_dropper then + break + end + moved_nodes[i] = {} + moved_nodes[i].oldpos = nodes[i].pos + nodes[i].pos = newpos[i] + moved_nodes[i].pos = nodes[i].pos + moved_nodes[i].node = nodes[i].node + moved_nodes[i].meta = nodes[i].meta + moved_nodes[i].node_timer = nodes[i].node_timer + end + + on_mvps_move(moved_nodes) + + return true, nodes, oldstack +end + +function mesecon.mvps_move_objects(pos, dir, nodestack) + local objects_to_move = {} + + -- Move object at tip of stack, pushpos is position at tip of stack + local pushpos = vector.add(pos, vector.multiply(dir, #nodestack)) + + local objects = minetest.get_objects_inside_radius(pushpos, 1) + for _, obj in ipairs(objects) do + table.insert(objects_to_move, obj) + end + + -- Move objects lying/standing on the stack (before it was pushed - oldstack) + if tonumber(minetest.settings:get("movement_gravity")) > 0 and dir.y == 0 then + -- If gravity positive and dir horizontal, push players standing on the stack + for _, n in ipairs(nodestack) do + local p_above = vector.add(n.pos, {x=0, y=1, z=0}) + local objects = minetest.get_objects_inside_radius(p_above, 1) + for _, obj in ipairs(objects) do + table.insert(objects_to_move, obj) + end + end + end + + for _, obj in ipairs(objects_to_move) do + local entity = obj:get_luaentity() + if not entity or not mesecon.is_mvps_unmov(entity.name) then + local np = vector.add(obj:get_pos(), dir) + + --move only if destination is not solid + local nn = minetest.get_node(np) + if not ((not minetest.registered_nodes[nn.name]) + or minetest.registered_nodes[nn.name].walkable) then + obj:set_pos(np) + end + end + end +end + +-- Unmovable by design +mesecon.register_mvps_stopper("mcl_core:barrier") +mesecon.register_mvps_stopper("mcl_core:realm_barrier") +mesecon.register_mvps_stopper("mcl_core:void") +mesecon.register_mvps_stopper("mcl_core:bedrock") +mesecon.register_mvps_stopper("mcl_core:obsidian") +mesecon.register_mvps_stopper("mcl_chests:ender_chest") +mesecon.register_mvps_stopper("mcl_mobspawners:spawner") +mesecon.register_mvps_stopper("mesecons_commandblock:commandblock_off") +mesecon.register_mvps_stopper("mesecons_commandblock:commandblock_on") +mesecon.register_mvps_stopper("mcl_portals:portal") +mesecon.register_mvps_stopper("mcl_portals:portal_end") +mesecon.register_mvps_stopper("mcl_portals:end_portal_frame") +mesecon.register_mvps_stopper("mcl_portals:end_portal_frame_eye") + +-- Unmovable by technical restrictions. +-- Open formspec would screw up if node is destroyed (minor problem) +mesecon.register_mvps_stopper("mcl_furnaces:furnace") +mesecon.register_mvps_stopper("mcl_furnaces:furnace_active") +mesecon.register_mvps_stopper("mcl_hoppers:hopper") +mesecon.register_mvps_stopper("mcl_hoppers:hopper_side") +mesecon.register_mvps_stopper("mcl_droppers:dropper") +mesecon.register_mvps_stopper("mcl_droppers:dropper_up") +mesecon.register_mvps_stopper("mcl_droppers:dropper_down") +mesecon.register_mvps_stopper("mcl_dispensers:dispenser") +mesecon.register_mvps_stopper("mcl_dispensers:dispenser_up") +mesecon.register_mvps_stopper("mcl_dispensers:dispenser_down") +mesecon.register_mvps_stopper("mcl_anvils:anvil") +mesecon.register_mvps_stopper("mcl_anvils:anvil_damage_1") +mesecon.register_mvps_stopper("mcl_anvils:anvil_damage_2") +-- Would screw up on/off state of trapped chest (big problem) + +-- Glazed terracotta: unpullable +mesecon.register_mvps_unsticky("mcl_colorblocks:glazed_terracotta_red") +mesecon.register_mvps_unsticky("mcl_colorblocks:glazed_terracotta_orange") +mesecon.register_mvps_unsticky("mcl_colorblocks:glazed_terracotta_yellow") +mesecon.register_mvps_unsticky("mcl_colorblocks:glazed_terracotta_green") +mesecon.register_mvps_unsticky("mcl_colorblocks:glazed_terracotta_lime") +mesecon.register_mvps_unsticky("mcl_colorblocks:glazed_terracotta_purple") +mesecon.register_mvps_unsticky("mcl_colorblocks:glazed_terracotta_magenta") +mesecon.register_mvps_unsticky("mcl_colorblocks:glazed_terracotta_blue") +mesecon.register_mvps_unsticky("mcl_colorblocks:glazed_terracotta_cyan") +mesecon.register_mvps_unsticky("mcl_colorblocks:glazed_terracotta_white") +mesecon.register_mvps_unsticky("mcl_colorblocks:glazed_terracotta_grey") +mesecon.register_mvps_unsticky("mcl_colorblocks:glazed_terracotta_silver") +mesecon.register_mvps_unsticky("mcl_colorblocks:glazed_terracotta_black") +mesecon.register_mvps_unsticky("mcl_colorblocks:glazed_terracotta_brown") +mesecon.register_mvps_unsticky("mcl_colorblocks:glazed_terracotta_light_blue") +mesecon.register_mvps_unsticky("mcl_colorblocks:glazed_terracotta_pink") + +-- Includes node heat when moving them +mesecon.register_on_mvps_move(mesecon.move_hot_nodes) + +mesecon.register_on_mvps_move(function(moved_nodes) + for i = 1, #moved_nodes do + local moved_node = moved_nodes[i] + -- Check for falling after moving node + mesecon.on_placenode(moved_node.pos, moved_node.node) + minetest.after(0, function() + minetest.check_for_falling(moved_node.oldpos) + minetest.check_for_falling(moved_node.pos) + end) + + -- Callback for on_mvps_move stored in nodedef + local node_def = minetest.registered_nodes[moved_node.node.name] + if node_def and node_def.mesecon and node_def.mesecon.on_mvps_move then + node_def.mesecon.on_mvps_move(moved_node.pos, moved_node.node, + moved_node.oldpos, moved_node.meta) + end + end +end) diff --git a/mesecons_mvps/mod.conf b/mesecons_mvps/mod.conf new file mode 100644 index 0000000..3e34787 --- /dev/null +++ b/mesecons_mvps/mod.conf @@ -0,0 +1,2 @@ +name = mesecons_mvps +depends = mesecons diff --git a/mesecons_noteblock/README.txt b/mesecons_noteblock/README.txt new file mode 100644 index 0000000..dd6822a --- /dev/null +++ b/mesecons_noteblock/README.txt @@ -0,0 +1,57 @@ +Credits of sound files: + +Note: Most sounds have not been used verbatim, but tweaked a little to be more suitable for the noteblock mod. + +### Sounds licensed CC0: + + * by freesound.org user AmateurJ + * Source: https://freesound.org/people/AmateurJ/sounds/399523/ +* mesecons_noteblock_bass_drum.ogg + * by freesound.org user Mattc90 + * Source: https://freesound.org/people/Mattc90/sounds/264285/ +* mesecons_noteblock_bell.ogg + * by opengameart.org user Brandon75689 + * Source: https://opengameart.org/content/point-bell +* mesecons_noteblock_chime.ogg + * by freesound.org user + * Source: https://freesound.org/people/ikonochris/sounds/213380/ +* mesecons_noteblock_cowbell.ogg + * by freesound.org user timgormly + * Source: https://freesound.org/people/timgormly/sounds/159760/ +* mesecons_noteblock_flute.ogg + * by freesound.org user menegass + * Source: https://freesound.org/people/menegass/sounds/107307/ +* mesecons_noteblock_bass_guitar.ogg + * by freesound.org user Vres + * Source: https://freesound.org/people/Vres/sounds/133024/ +* mesecons_noteblock_hit.ogg + * by freesound.org user rubberduck + * Source: https://opengameart.org/content/100-cc0-sfx +* mesecons_noteblock_piano_digital.ogg + * by freesound.org user monotraum + * Source: https://freesound.org/people/monotraum/sounds/208889/ +* mesecons_noteblock_squarewave.ogg + * by Wuzzy +* mesecons_noteblock_xylophone_metal.ogg + * by freesound.org user JappeHallunken + * Source: https://freesound.org/people/JappeHallunken/sounds/501300/ +* mesecons_noteblock_xylophone_wood.ogg + * by freesound.org user connersaw8 + * Source: https://freesound.org/people/connersaw8/sounds/125271/ + +### Sounds licensed CC BY 3.0: + +* mesecons_noteblock_bass_guitar.ogg + * by freesound.org user Kyster + * Source: https://freesound.org/people/Kyster/sounds/117707/ +* mesecons_noteblock_didgeridoo.ogg + * by freesound.org user InspectorJ + * Source: https://freesound.org/people/InspectorJ/sounds/398272/ + +Everything else: +Created by Mesecons authors, licensed CC BY 3.0. + +-------------------- +License links: +* CC0: http://creativecommons.org/publicdomain/zero/1.0/ +* CC BY 3.0: http://creativecommons.org/licenses/by/3.0/ diff --git a/mesecons_noteblock/init.lua b/mesecons_noteblock/init.lua new file mode 100644 index 0000000..ac56d8b --- /dev/null +++ b/mesecons_noteblock/init.lua @@ -0,0 +1,199 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + +local math = math + +minetest.register_node("mesecons_noteblock:noteblock", { + description = S("Note Block"), + _tt_help = S("Plays a musical note when powered by redstone power"), + _doc_items_longdesc = S("A note block is a musical block which plays one of many musical notes and different intruments when it is punched or supplied with redstone power."), + _doc_items_usagehelp = S("Use the note block to choose the next musical note (there are 25 semitones, or 2 octaves). The intrument played depends on the material of the block below the note block:").."\n\n".. + +S("• Glass: Sticks").."\n".. +S("• Wood: Bass guitar").."\n".. +S("• Stone: Bass drum").."\n".. +S("• Sand or gravel: Snare drum").."\n".. +S("• Block of Gold: Bell").."\n".. +S("• Clay: Flute").."\n".. +S("• Packed Ice: Chime").."\n".. +S("• Wool: Guitar").."\n".. +S("• Bone Block: Xylophne").."\n".. +S("• Block of Iron: Iron xylophne").."\n".. +S("• Soul Sand: Cow bell").."\n".. +S("• Pumpkin: Didgeridoo").."\n".. +S("• Block of Emerald: Square wave").."\n".. +S("• Hay Bale: Banjo").."\n".. +S("• Glowstone: Electric piano").."\n".. +S("• Anything else: Piano").."\n\n".. + +S("The note block will only play a note when it is below air, otherwise, it stays silent."), + tiles = {"mesecons_noteblock.png"}, + groups = {handy=1,axey=1, material_wood=1, flammable=-1}, + is_ground_content = false, + place_param2 = 0, + on_rightclick = function(pos, node, clicker) -- change sound when rightclicked + local protname = clicker:get_player_name() + if minetest.is_protected(pos, protname) then + minetest.record_protection_violation(pos, protname) + return + end + node.param2 = (node.param2+1)%25 + mesecon.noteblock_play(pos, node.param2) + minetest.set_node(pos, node) + end, + on_punch = function(pos, node) -- play current sound when punched + mesecon.noteblock_play(pos, node.param2) + end, + sounds = mcl_sounds.node_sound_wood_defaults(), + mesecons = {effector = { -- play sound when activated + action_on = function(pos, node) + mesecon.noteblock_play(pos, node.param2) + end, + rules = mesecon.rules.alldirs, + }}, + _mcl_blast_resistance = 0.8, + _mcl_hardness = 0.8, +}) + +minetest.register_craft({ + output = "mesecons_noteblock:noteblock", + recipe = { + {"group:wood", "group:wood", "group:wood"}, + {"group:wood", "mesecons:redstone", "group:wood"}, + {"group:wood", "group:wood", "group:wood"}, + } +}) + +minetest.register_craft({ + type = "fuel", + recipe = "mesecons_noteblock:noteblock", + burntime = 15 +}) + +local soundnames_piano = { + [0] = "mesecons_noteblock_c", + "mesecons_noteblock_csharp", + "mesecons_noteblock_d", + "mesecons_noteblock_dsharp", + "mesecons_noteblock_e", + "mesecons_noteblock_f", + "mesecons_noteblock_fsharp", + "mesecons_noteblock_g", + "mesecons_noteblock_gsharp", + "mesecons_noteblock_a", + "mesecons_noteblock_asharp", + "mesecons_noteblock_b", + + "mesecons_noteblock_c2", + "mesecons_noteblock_csharp2", + "mesecons_noteblock_d2", + "mesecons_noteblock_dsharp2", + "mesecons_noteblock_e2", + "mesecons_noteblock_f2", + "mesecons_noteblock_fsharp2", + "mesecons_noteblock_g2", + "mesecons_noteblock_gsharp2", + "mesecons_noteblock_a2", + "mesecons_noteblock_asharp2", + "mesecons_noteblock_b2", + + -- TODO: Add dedicated sound file? + "mesecons_noteblock_b2", +} + +local function param2_to_note_color(param2) + local r, g, b + if param2 < 8 then -- 0..7 + -- More red, less green + r = param2 / 8 * 255 + g = (8-param2) / 8 * 255 + b = 0 + elseif param2 < 16 then -- 0..15 + -- More blue, less red + r = (8-(param2 - 8)) / 8 * 255 + g = 0 + b = (param2 - 8) / 8 * 255 + else -- 16..24 + -- More green, less blue + r = 0 + g = (param2 - 16) / 9 * 255 + b = (9-(param2 - 16)) / 9 * 255 + end + r = math.floor(r) + g = math.floor(g) + b = math.floor(b) + local color = 0x10000 * r + 0x100 * g + b + -- Convert to ColorString + return string.format("#%06X", color) +end + +local function param2_to_pitch(param2) + return 2^((param2-12)/12) +end + +function mesecon.noteblock_play(pos, param2) + local block_above_name = minetest.get_node({x=pos.x, y=pos.y+1, z=pos.z}).name + if block_above_name ~= "air" then + -- Don't play sound if no air is above + return + end + + local block_below_name = minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}).name + local pitched = false + local soundname, pitch + if block_below_name == "mcl_core:goldblock" then + soundname="mesecons_noteblock_bell" + elseif block_below_name == "mcl_core:clay" then + soundname="mesecons_noteblock_flute" + elseif block_below_name == "mcl_core:packed_ice" then + soundname="mesecons_noteblock_chime" + elseif block_below_name == "mcl_core:bone_block" then + soundname="mesecons_noteblock_xylophone_wood" + elseif block_below_name == "mcl_core:ironblock" then + soundname="mesecons_noteblock_xylophone_metal" + elseif block_below_name == "mcl_nether:soul_sand" then + soundname="mesecons_noteblock_cowbell" + elseif block_below_name == "mcl_farming:pumpkin" or block_below_name == "mcl_farming:pumpkin_face" or block_below_name == "mcl_farming:pumpkin_face_light" then + soundname="mesecons_noteblock_didgeridoo" + elseif block_below_name == "mcl_core:emeraldblock" then + soundname="mesecons_noteblock_squarewave" + elseif block_below_name == "mcl_farming:hay_block" then + soundname="mesecons_noteblock_banjo" + elseif block_below_name == "mcl_nether:glowstone" then + soundname="mesecons_noteblock_piano_digital" + elseif minetest.get_item_group(block_below_name, "wool") ~= 0 then + soundname="mesecons_noteblock_guitar" + elseif minetest.get_item_group(block_below_name, "material_glass") ~= 0 then + soundname="mesecons_noteblock_hit" + elseif minetest.get_item_group(block_below_name, "material_wood") ~= 0 then + soundname="mesecons_noteblock_bass_guitar" + elseif minetest.get_item_group(block_below_name, "material_sand") ~= 0 then + soundname="mesecons_noteblock_snare" + elseif minetest.get_item_group(block_below_name, "material_stone") ~= 0 then + soundname="mesecons_noteblock_bass_drum" + else + -- Default: One of 25 piano notes + soundname = soundnames_piano[param2] + -- Workaround: Final sound gets automatic higher pitch instead + if param2 == 24 then + pitch = 2^(1/12) + end + pitched = true + end + if not pitched then + pitch = param2_to_pitch(param2) + end + + local note_color = param2_to_note_color(param2) + + minetest.add_particle({ + texture = "mcl_particles_note.png^[colorize:"..note_color..":92", + pos = { x = pos.x, y = pos.y + 0.35, z = pos.z }, + velocity = { x = 0, y = 2, z = 0 }, + acceleration = { x = 0, y = -2, z = 0 }, + expirationtime = 1.0, + collisiondetection = false, + size = 3, + }) + minetest.sound_play(soundname, + {pos = pos, gain = 1.0, max_hear_distance = 48, pitch = pitch}) +end diff --git a/mesecons_noteblock/locale/mesecons_noteblock.de.tr b/mesecons_noteblock/locale/mesecons_noteblock.de.tr new file mode 100644 index 0000000..b3fe222 --- /dev/null +++ b/mesecons_noteblock/locale/mesecons_noteblock.de.tr @@ -0,0 +1,22 @@ +# textdomain: mesecons_noteblock +Note Block=Notenblock +A note block is a musical block which plays one of many musical notes and different intruments when it is punched or supplied with redstone power.=Ein Notenblock ist ein musikalischer Block, der eine von vielen Noten von verschiedenen Instrumenten spielt, wenn er geschlagen oder mit Redstoneenergie versorgt wird. +Use the note block to choose the next musical note (there are 25 semitones, or 2 octaves). The intrument played depends on the material of the block below the note block:=Benutzen Sie den Notenblock, um die nächste Musiknote zu wählen (es gibt 25 Halbtöne bzw. oder 2 Oktaven). Das gespielte Instrument hängt vom Material des Blocks unter dem Notenblock ab: +• Glass: Sticks=• Glas: Stöcke +• Wood: Bass guitar=• Holz: Bassgitarre +• Stone: Bass drum=• Stein: Basstrommel +• Sand or gravel: Snare drum=• Sand oder Kies: Kleine Trommel +• Block of Gold: Bell=• Goldblock: Glocke +• Clay: Flute=• Ton: Flöte +• Packed Ice: Chime=• Packeis: Glockenspiel +• Wool: Guitar=• Wolle: Gitarre +• Bone Block: Xylophne=• Knochenblock: Xylophon +• Block of Iron: Iron xylophne=• Eisenblock: Eisenxylophon +• Soul Sand: Cow bell=• Seelensand: Kuhglocke +• Pumpkin: Didgeridoo=• Kürbis: Didgeridoo +• Block of Emerald: Square wave=• Smaragdblock: Rechteckschwingung +• Hay Bale: Banjo=• Heuballen: Banjo +• Glowstone: Electric piano=• Leuchtstein: E-Piano +• Anything else: Piano=• Alles andere: Klavier +The note block will only play a note when it is below air, otherwise, it stays silent.=Der Notenblock wird nur eine Note spielen, wenn er sich unter Luft befindet, sonst bleibt er stumm. +Plays a musical note when powered by redstone power=Spielt eine Musiknote, wenn mit Redstoneenergie versorgt diff --git a/mesecons_noteblock/locale/mesecons_noteblock.es.tr b/mesecons_noteblock/locale/mesecons_noteblock.es.tr new file mode 100644 index 0000000..123862d --- /dev/null +++ b/mesecons_noteblock/locale/mesecons_noteblock.es.tr @@ -0,0 +1,10 @@ +# textdomain: mesecons_noteblock +Note Block=Bloque musical +A note block is a musical block which plays one of many musical notes and different intruments when it is punched or supplied with redstone power.=Un bloque de notas es un bloque musical que reproduce una de las muchas notas musicales e instrumentos diferentes cuando se golpea o se le suministra energía de redstone. +Use the note block to choose the next musical note (there are 25 semitones, or 2 octaves). The intrument played depends on the material of the block below the note block:=Use el bloque de notas para elegir la siguiente nota musical (hay 25 semitonos, o 2 octavas). El instrumento jugado depende del material del bloque debajo del bloque de nota: +• Glass: Sticks=• Cristal: Palos +• Wood: Bass guitar=• Madera: Bajo +• Stone: Bass drum=• Piedra: Bombo +• Sand or gravel: Snare drum=• Arena o grava: tambor +• Anything else: Piano=• Cualquier otra cosa: piano +The note block will only play a note when it is below air, otherwise, it stays silent.=El bloque de notas solo reproducirá una nota cuando esté debajo del aire, de lo contrario, permanecerá en silencio. diff --git a/mesecons_noteblock/locale/mesecons_noteblock.fr.tr b/mesecons_noteblock/locale/mesecons_noteblock.fr.tr new file mode 100644 index 0000000..f8d8e3d --- /dev/null +++ b/mesecons_noteblock/locale/mesecons_noteblock.fr.tr @@ -0,0 +1,22 @@ +# textdomain: mesecons_noteblock +Note Block=Bloc de notes +A note block is a musical block which plays one of many musical notes and different intruments when it is punched or supplied with redstone power.=Un bloc de notes est un bloc musical qui joue l'une des nombreuses notes de musique et différents instruments lorsqu'il est frappé ou alimenté en redstone. +Use the note block to choose the next musical note (there are 25 semitones, or 2 octaves). The intrument played depends on the material of the block below the note block:=Utilisez le bloc de notes pour choisir la prochaine note de musique (il y a 25 demi-tons ou 2 octaves). L'instrument joué dépend du matériau du bloc situé sous le bloc de notes: +• Glass: Sticks=• Glass: Sticks +• Wood: Bass guitar=• Bois: Guitare Basse +• Stone: Bass drum=• Pierre: Grosse caisse +• Sand or gravel: Snare drum=• Sable ou gravier: Caisse claire +• Block of Gold: Bell=• Bloc d'OR: Cloche +• Clay: Flute=• Argile: Flûte +• Packed Ice: Chime=• Glace tassée: Carillon +• Wool: Guitar=• Laine: Guitare +• Bone Block: Xylophne=• Bloc osseux: Xylophne +• Block of Iron: Iron xylophne=• Bloc de fer: Xylophone en fer +• Soul Sand: Cow bell=• Soul Sand: Cloche de vache +• Pumpkin: Didgeridoo=• Citrouille: Didgeridoo +• Block of Emerald: Square wave=• Bloc d'émeraude: Onde carrée +• Hay Bale: Banjo=• Hay Bale: Banjo +• Glowstone: Electric piano=• Glowstone: Piano Electrique +• Anything else: Piano=• Autres: Piano +The note block will only play a note when it is below air, otherwise, it stays silent.=Le bloc de notes ne jouera une note que lorsqu'il est sous l'air, sinon il reste silencieux. +Plays a musical note when powered by redstone power=Joue une note de musique lorsqu'il est alimenté par une puissance redstone diff --git a/mesecons_noteblock/locale/mesecons_noteblock.pl.tr b/mesecons_noteblock/locale/mesecons_noteblock.pl.tr new file mode 100644 index 0000000..fbf31bc --- /dev/null +++ b/mesecons_noteblock/locale/mesecons_noteblock.pl.tr @@ -0,0 +1,22 @@ +# textdomain: mesecons_noteblock +Note Block=Blok nuty +A note block is a musical block which plays one of many musical notes and different intruments when it is punched or supplied with redstone power.=Blok nuty jest muzycznym blokiem, który gra jedną z wielu muzycznych nut różnych instrumentów gdy jest uderzony, lub zasilony czerwienitem. +Use the note block to choose the next musical note (there are 25 semitones, or 2 octaves). The intrument played depends on the material of the block below the note block:=Użyj bloku nuty aby wybrać następną muzyczną nutę (możliwe jest 25 półtonów, lub 2 oktawy). Zagrany instrument zależy od materiału znajdującego się pod blokiem nuty: +• Glass: Sticks=• Szkło: patyki +• Wood: Bass guitar=• Drewno: gitara basowa +• Stone: Bass drum=• Kamień: bęben +• Sand or gravel: Snare drum=• Piasek lub żwir: bęben mały +• Anything else: Piano=• Cokolwiek innego: pianino +• Block of Gold: Bell=• Blok złota: dzwon +• Clay: Flute=• Glina: flet +• Packed Ice: Chime=• Zbity lud: cymbałki +• Wool: Guitar=• Wełna: gitara +• Bone Block: Xylophne=• Blok kości: ksylofon +• Block of Iron: Iron xylophne=• Blok żelaza: żelazny ksylofon +• Soul Sand: Cow bell=• Piasek dusz: krowi dzwonek +• Pumpkin: Didgeridoo=• Dynia: Didgeridoo +• Block of Emerald: Square wave=• Blok szmaragdu: fala kwadratowa +• Hay Bale: Banjo=• Bela siana: banjo +• Glowstone: Electric piano=• Jasnogłaz: elektryczne pianino +The note block will only play a note when it is below air, otherwise, it stays silent.=Blok nuty gra tylko gdy jest poniżej powietrza, w przeciwnym przypadku będzie cichy. +Plays a musical note when powered by redstone power=Gra muzyczną nutę gdy zasilana energię czerwienitową diff --git a/mesecons_noteblock/locale/mesecons_noteblock.ru.tr b/mesecons_noteblock/locale/mesecons_noteblock.ru.tr new file mode 100644 index 0000000..fbac436 --- /dev/null +++ b/mesecons_noteblock/locale/mesecons_noteblock.ru.tr @@ -0,0 +1,22 @@ +# textdomain: mesecons_noteblock +Note Block=Нотный блок +A note block is a musical block which plays one of many musical notes and different intruments when it is punched or supplied with redstone power.=Нотный блок это музыкальный блок, который при ударе, а также при подаче энергии редстоуна проигрывает одну из множества музыкальных нот различными инструментами. +Use the note block to choose the next musical note (there are 25 semitones, or 2 octaves). The intrument played depends on the material of the block below the note block:=[Используйте] нотный блок, чтобы выбрать следующую ноту (всего предусмотрено 25 полутонов или 2 октавы). Проигрываемый инструмент зависит от материала, который находится непосредственно под нотным блоком. +• Glass: Sticks=• Стекло: палочки +• Wood: Bass guitar=• Дерево: бас-гитара +• Stone: Bass drum=• Камень: бочка +• Sand or gravel: Snare drum=• Песок или гравий: барабан +• Anything else: Piano=• Что-либо другое: фортепиано +• Block of Gold: Bell=• Золотой блок: колокол +• Clay: Flute=• Глина: флейта +• Packed Ice: Chime=• Упакованный лёд: звон +• Wool: Guitar=• Шерсть: гитара +• Bone Block: Xylophne=• Костный блок: ксилофон +• Block of Iron: Iron xylophne=• Железный блок: металлофон +• Soul Sand: Cow bell=• Песок душ: колокольчик +• Pumpkin: Didgeridoo=• Тыква: диджериду +• Block of Emerald: Square wave=• Изумрудный блок: прямоугольный сигнал +• Hay Bale: Banjo=• Стог сена: банджо +• Glowstone: Electric piano=• Электронное фортепиано +The note block will only play a note when it is below air, otherwise, it stays silent.=Нотный блок проигрывает ноту только когда над ним имеется воздух, в противном случае он остаётся тихим. +Plays a musical note when powered by redstone power=Проигрывает ноту при подключении энергии редстоуна diff --git a/mesecons_noteblock/locale/template.txt b/mesecons_noteblock/locale/template.txt new file mode 100644 index 0000000..2bc0e2b --- /dev/null +++ b/mesecons_noteblock/locale/template.txt @@ -0,0 +1,22 @@ +# textdomain: mesecons_noteblock +Note Block= +A note block is a musical block which plays one of many musical notes and different intruments when it is punched or supplied with redstone power.= +Use the note block to choose the next musical note (there are 25 semitones, or 2 octaves). The intrument played depends on the material of the block below the note block:= +• Glass: Sticks= +• Wood: Bass guitar= +• Stone: Bass drum= +• Sand or gravel: Snare drum= +• Anything else: Piano= +• Block of Gold: Bell= +• Clay: Flute= +• Packed Ice: Chime= +• Wool: Guitar= +• Bone Block: Xylophne= +• Block of Iron: Iron xylophne= +• Soul Sand: Cow bell= +• Pumpkin: Didgeridoo= +• Block of Emerald: Square wave= +• Hay Bale: Banjo= +• Glowstone: Electric piano= +The note block will only play a note when it is below air, otherwise, it stays silent.= +Plays a musical note when powered by redstone power= diff --git a/mesecons_noteblock/mod.conf b/mesecons_noteblock/mod.conf new file mode 100644 index 0000000..c388e7a --- /dev/null +++ b/mesecons_noteblock/mod.conf @@ -0,0 +1,2 @@ +name = mesecons_noteblock +depends = mesecons, mcl_particles diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_a.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_a.ogg new file mode 100644 index 0000000..331fc1c Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_a.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_a2.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_a2.ogg new file mode 100644 index 0000000..695b0f4 Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_a2.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_asharp.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_asharp.ogg new file mode 100644 index 0000000..db96aed Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_asharp.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_asharp2.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_asharp2.ogg new file mode 100644 index 0000000..27bd09d Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_asharp2.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_b.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_b.ogg new file mode 100644 index 0000000..810fe18 Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_b.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_b2.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_b2.ogg new file mode 100644 index 0000000..3de1250 Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_b2.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_banjo.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_banjo.ogg new file mode 100644 index 0000000..62d93d5 Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_banjo.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_bass_drum.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_bass_drum.ogg new file mode 100644 index 0000000..c470537 Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_bass_drum.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_bass_guitar.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_bass_guitar.ogg new file mode 100644 index 0000000..48069d8 Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_bass_guitar.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_bell.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_bell.ogg new file mode 100644 index 0000000..6758e2c Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_bell.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_c.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_c.ogg new file mode 100644 index 0000000..5c60d31 Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_c.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_c2.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_c2.ogg new file mode 100644 index 0000000..724db7d Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_c2.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_chime.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_chime.ogg new file mode 100644 index 0000000..4c13126 Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_chime.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_cowbell.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_cowbell.ogg new file mode 100644 index 0000000..32b4c9f Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_cowbell.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_csharp.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_csharp.ogg new file mode 100644 index 0000000..12c1ef3 Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_csharp.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_csharp2.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_csharp2.ogg new file mode 100644 index 0000000..fc7f6c8 Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_csharp2.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_d.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_d.ogg new file mode 100644 index 0000000..929b7fb Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_d.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_d2.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_d2.ogg new file mode 100644 index 0000000..dfd702b Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_d2.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_didgeridoo.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_didgeridoo.ogg new file mode 100644 index 0000000..221cd84 Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_didgeridoo.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_dsharp.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_dsharp.ogg new file mode 100644 index 0000000..eb6045d Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_dsharp.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_dsharp2.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_dsharp2.ogg new file mode 100644 index 0000000..5ac16dd Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_dsharp2.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_e.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_e.ogg new file mode 100644 index 0000000..94977e0 Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_e.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_e2.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_e2.ogg new file mode 100644 index 0000000..1dcc0c4 Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_e2.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_f.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_f.ogg new file mode 100644 index 0000000..221d926 Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_f.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_f2.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_f2.ogg new file mode 100644 index 0000000..acf10db Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_f2.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_flute.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_flute.ogg new file mode 100644 index 0000000..3a8bbc6 Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_flute.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_fsharp.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_fsharp.ogg new file mode 100644 index 0000000..7af83a8 Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_fsharp.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_fsharp2.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_fsharp2.ogg new file mode 100644 index 0000000..a96f637 Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_fsharp2.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_g.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_g.ogg new file mode 100644 index 0000000..480ca36 Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_g.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_g2.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_g2.ogg new file mode 100644 index 0000000..917b2b9 Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_g2.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_gsharp.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_gsharp.ogg new file mode 100644 index 0000000..2e71fea Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_gsharp.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_gsharp2.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_gsharp2.ogg new file mode 100644 index 0000000..941c685 Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_gsharp2.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_guitar.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_guitar.ogg new file mode 100644 index 0000000..1dcd5b8 Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_guitar.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_hit.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_hit.ogg new file mode 100644 index 0000000..cf8a5bf Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_hit.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_piano_digital.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_piano_digital.ogg new file mode 100644 index 0000000..6461a70 Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_piano_digital.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_snare.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_snare.ogg new file mode 100644 index 0000000..329a43b Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_snare.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_squarewave.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_squarewave.ogg new file mode 100644 index 0000000..b6bc5c4 Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_squarewave.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_xylophone_metal.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_xylophone_metal.ogg new file mode 100644 index 0000000..2d99327 Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_xylophone_metal.ogg differ diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_xylophone_wood.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_xylophone_wood.ogg new file mode 100644 index 0000000..5598f62 Binary files /dev/null and b/mesecons_noteblock/sounds/mesecons_noteblock_xylophone_wood.ogg differ diff --git a/mesecons_noteblock/textures/mesecons_noteblock.png b/mesecons_noteblock/textures/mesecons_noteblock.png new file mode 100644 index 0000000..6a48136 Binary files /dev/null and b/mesecons_noteblock/textures/mesecons_noteblock.png differ diff --git a/mesecons_pistons/init.lua b/mesecons_pistons/init.lua new file mode 100644 index 0000000..93b8df9 --- /dev/null +++ b/mesecons_pistons/init.lua @@ -0,0 +1,904 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + +local PISTON_MAXIMUM_PUSH = 12 + +--Get mesecon rules of pistons + +--everything apart from z- (pusher side) +local piston_rules = { + {x=0, y=0, z=1}, + {x=1, y=0, z=0}, + {x=-1, y=0, z=0}, + {x=0, y=1, z=0}, + {x=0, y=-1, z=0}, +} + +--everything apart from y+ (pusher side) +local piston_up_rules = { + {x=0, y=0, z=-1}, + {x=0, y=0, z=1}, + {x=-1, y=0, z=0}, + {x=1, y=0, z=0}, + {x=0, y=-1, z=0}, +} + +--everything apart from y- (pusher side) +local piston_down_rules = { + {x=0, y=0, z=-1}, + {x=0, y=0, z=1}, + {x=-1, y=0, z=0}, + {x=1, y=0, z=0}, + {x=0, y=1, z=0}, +} + +local function piston_get_rules(node) + local rules = piston_rules + for i = 1, node.param2 do + rules = mesecon.rotate_rules_left(rules) + end + return rules +end + +local function piston_facedir_direction(node) + local rules = {{x = 0, y = 0, z = -1}} + for i = 1, node.param2 do + rules = mesecon.rotate_rules_left(rules) + end + return rules[1] +end + +local function piston_get_direction(dir, node) + if type(dir) == "function" then + return dir(node) + else + return dir + end +end + +-- Remove pusher of piston. +-- To be used when piston was destroyed or dug. +local function piston_remove_pusher(pos, oldnode) + local pistonspec = minetest.registered_nodes[oldnode.name].mesecons_piston + + local dir = piston_get_direction(pistonspec.dir, oldnode) + local pusherpos = vector.add(pos, dir) + local pushername = minetest.get_node(pusherpos).name + + if pushername == pistonspec.pusher then -- make sure there actually is a pusher + minetest.remove_node(pusherpos) + minetest.check_for_falling(pusherpos) + minetest.sound_play("piston_retract", { + pos = pos, + max_hear_distance = 31, + gain = 0.3, + }, true) + end +end + +-- Remove base node of piston. +-- To be used when pusher was destroyed. +local function piston_remove_base(pos, oldnode) + local basenodename = minetest.registered_nodes[oldnode.name].corresponding_piston + local pistonspec = minetest.registered_nodes[basenodename].mesecons_piston + + local dir = piston_get_direction(pistonspec.dir, oldnode) + local basepos = vector.subtract(pos, dir) + local basename = minetest.get_node(basepos).name + + if basename == pistonspec.onname then -- make sure there actually is a base node + minetest.remove_node(basepos) + minetest.check_for_falling(basepos) + minetest.sound_play("piston_retract", { + pos = pos, + max_hear_distance = 31, + gain = 0.3, + }, true) + end +end + +local function piston_on(pos, node) + local pistonspec = minetest.registered_nodes[node.name].mesecons_piston + + local dir = piston_get_direction(pistonspec.dir, node) + local np = vector.add(pos, dir) + local meta = minetest.get_meta(pos) + local success, stack, oldstack = mesecon.mvps_push(np, dir, PISTON_MAXIMUM_PUSH, meta:get_string("owner"), pos) + if success then + minetest.swap_node(pos, {param2 = node.param2, name = pistonspec.onname}) + minetest.set_node(np, {param2 = node.param2, name = pistonspec.pusher}) + local below = minetest.get_node({x=np.x,y=np.y-1,z=np.z}) + if below.name == "mcl_farming:soil" or below.name == "mcl_farming:soil_wet" then + minetest.set_node({x=np.x,y=np.y-1,z=np.z}, {name = "mcl_core:dirt"}) + end + mesecon.mvps_process_stack(stack) + mesecon.mvps_move_objects(np, dir, oldstack) + minetest.sound_play("piston_extend", { + pos = pos, + max_hear_distance = 31, + gain = 0.3, + }, true) + end +end + +local function piston_off(pos, node) + local pistonspec = minetest.registered_nodes[node.name].mesecons_piston + minetest.swap_node(pos, {param2 = node.param2, name = pistonspec.offname}) + piston_remove_pusher (pos, node) + if not pistonspec.sticky then + return + end + + local dir = piston_get_direction(pistonspec.dir, node) + local pullpos = vector.add(pos, vector.multiply(dir, 2)) + local meta = minetest.get_meta(pos) + local success, stack = mesecon.mvps_pull_single(pullpos, vector.multiply(dir, -1), PISTON_MAXIMUM_PUSH, meta:get_string("owner"), pos) + if success then + mesecon.mvps_process_stack(pos, dir, stack) + end +end + +local function piston_orientate(pos, placer) + mesecon.mvps_set_owner(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 = minetest.get_node(pos) + local pistonspec = minetest.registered_nodes[node.name].mesecons_piston + if pitch > 55 then + minetest.add_node(pos, {name=pistonspec.piston_up}) + elseif pitch < -55 then + minetest.add_node(pos, {name=pistonspec.piston_down}) + end +end + + +-- Horizontal pistons + +local pt = 4/16 -- pusher thickness + +local piston_pusher_box = { + type = "fixed", + fixed = { + {-2/16, -2/16, -.5 + pt, 2/16, 2/16, .5 + pt}, + {-.5 , -.5 , -.5 , .5 , .5 , -.5 + pt}, + }, +} + +local piston_on_box = { + type = "fixed", + fixed = { + {-.5, -.5, -.5 + pt, .5, .5, .5} + }, +} + + +-- Normal (non-sticky) ones: + +local pistonspec_normal = { + offname = "mesecons_pistons:piston_normal_off", + onname = "mesecons_pistons:piston_normal_on", + dir = piston_facedir_direction, + pusher = "mesecons_pistons:piston_pusher_normal", + piston_down = "mesecons_pistons:piston_down_normal_off", + piston_up = "mesecons_pistons:piston_up_normal_off", +} + +local usagehelp_piston = S("This block can have one of 6 possible orientations.") + +-- offstate +minetest.register_node("mesecons_pistons:piston_normal_off", { + description = S("Piston"), + _tt_help = S("Pushes block when powered by redstone power"), + _doc_items_longdesc = S("A piston is a redstone component with a pusher which pushes the block or blocks in front of it when it is supplied with redstone power. Not all blocks can be pushed, however."), + _doc_items_usagehelp = usagehelp_piston, + tiles = { + "mesecons_piston_bottom.png^[transformR180", + "mesecons_piston_bottom.png", + "mesecons_piston_bottom.png^[transformR90", + "mesecons_piston_bottom.png^[transformR270", + "mesecons_piston_back.png", + "mesecons_piston_pusher_front.png" + }, + groups = {handy=1, piston=1}, + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + after_place_node = piston_orientate, + mesecons_piston = pistonspec_normal, + sounds = mcl_sounds.node_sound_stone_defaults(), + mesecons = { + effector = { + action_on = piston_on, + rules = piston_get_rules + }, + }, + _mcl_blast_resistance = 0.5, + _mcl_hardness = 0.5, + on_rotate = function(pos, node, user, mode) + if mode == screwdriver.ROTATE_AXIS then + minetest.set_node(pos, {name="mesecons_pistons:piston_up_normal_off"}) + return true + end + end, +}) + +-- onstate +minetest.register_node("mesecons_pistons:piston_normal_on", { + drawtype = "nodebox", + tiles = { + "mesecons_piston_bottom.png^[transformR180", + "mesecons_piston_bottom.png", + "mesecons_piston_bottom.png^[transformR90", + "mesecons_piston_bottom.png^[transformR270", + "mesecons_piston_back.png", + "mesecons_piston_on_front.png" + }, + groups = {handy=1, piston=1, not_in_creative_inventory=1}, + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + drop = "mesecons_pistons:piston_normal_off", + after_destruct = piston_remove_pusher, + node_box = piston_on_box, + selection_box = piston_on_box, + mesecons_piston = pistonspec_normal, + sounds = mcl_sounds.node_sound_stone_defaults(), + mesecons = { + effector = { + action_off = piston_off, + rules = piston_get_rules + }, + }, + _mcl_blast_resistance = 0.5, + _mcl_hardness = 0.5, + on_rotate = false, +}) + +-- pusher +minetest.register_node("mesecons_pistons:piston_pusher_normal", { + drawtype = "nodebox", + tiles = { + "mesecons_piston_pusher_top.png", + "mesecons_piston_pusher_bottom.png", + "mesecons_piston_pusher_left.png", + "mesecons_piston_pusher_right.png", + "mesecons_piston_pusher_back.png", + "mesecons_piston_pusher_front.png" + }, + paramtype = "light", + paramtype2 = "facedir", + groups = {piston_pusher=1}, + is_ground_content = false, + after_destruct = piston_remove_base, + diggable = false, + drop = "", + corresponding_piston = "mesecons_pistons:piston_normal_on", + selection_box = piston_pusher_box, + node_box = piston_pusher_box, + sounds = mcl_sounds.node_sound_wood_defaults(), + _mcl_blast_resistance = 0.5, + on_rotate = false, +}) + +-- Sticky ones + +local pistonspec_sticky = { + offname = "mesecons_pistons:piston_sticky_off", + onname = "mesecons_pistons:piston_sticky_on", + dir = piston_facedir_direction, + pusher = "mesecons_pistons:piston_pusher_sticky", + sticky = true, + piston_down = "mesecons_pistons:piston_down_sticky_off", + piston_up = "mesecons_pistons:piston_up_sticky_off", +} + +-- offstate +minetest.register_node("mesecons_pistons:piston_sticky_off", { + description = S("Sticky Piston"), + _tt_help = S("Pushes or pulls block when powered by redstone power"), + _doc_items_longdesc = S("A sticky piston is a redstone component with a sticky pusher which can be extended and retracted. It extends when it is supplied with redstone power. When the pusher extends, it pushes the block or blocks in front of it. When it retracts, it pulls back the single block in front of it. Note that not all blocks can be pushed or pulled."), + _doc_items_usagehelp = usagehelp_piston, + + tiles = { + "mesecons_piston_bottom.png^[transformR180", + "mesecons_piston_bottom.png", + "mesecons_piston_bottom.png^[transformR90", + "mesecons_piston_bottom.png^[transformR270", + "mesecons_piston_back.png", + "mesecons_piston_pusher_front_sticky.png" + }, + groups = {handy=1, piston=2}, + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + after_place_node = piston_orientate, + mesecons_piston = pistonspec_sticky, + sounds = mcl_sounds.node_sound_stone_defaults(), + mesecons = { + effector = { + action_on = piston_on, + rules = piston_get_rules + }, + }, + _mcl_blast_resistance = 0.5, + _mcl_hardness = 0.5, + on_rotate = function(pos, node, user, mode) + if mode == screwdriver.ROTATE_AXIS then + minetest.set_node(pos, {name="mesecons_pistons:piston_up_sticky_off"}) + return true + end + end, +}) + +-- onstate +minetest.register_node("mesecons_pistons:piston_sticky_on", { + drawtype = "nodebox", + tiles = { + "mesecons_piston_bottom.png^[transformR180", + "mesecons_piston_bottom.png", + "mesecons_piston_bottom.png^[transformR90", + "mesecons_piston_bottom.png^[transformR270", + "mesecons_piston_back.png", + "mesecons_piston_on_front.png" + }, + groups = {handy=1, piston=2, not_in_creative_inventory=1}, + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + drop = "mesecons_pistons:piston_sticky_off", + after_destruct = piston_remove_pusher, + node_box = piston_on_box, + selection_box = piston_on_box, + mesecons_piston = pistonspec_sticky, + sounds = mcl_sounds.node_sound_stone_defaults(), + mesecons = { + effector = { + action_off = piston_off, + rules = piston_get_rules + }, + }, + _mcl_blast_resistance = 0.5, + _mcl_hardness = 0.5, + on_rotate = false, +}) + +-- pusher +minetest.register_node("mesecons_pistons:piston_pusher_sticky", { + drawtype = "nodebox", + tiles = { + "mesecons_piston_pusher_top.png", + "mesecons_piston_pusher_bottom.png", + "mesecons_piston_pusher_left.png", + "mesecons_piston_pusher_right.png", + "mesecons_piston_pusher_back.png", + "mesecons_piston_pusher_front_sticky.png" + }, + paramtype = "light", + paramtype2 = "facedir", + groups = {piston_pusher=2}, + is_ground_content = false, + after_destruct = piston_remove_base, + diggable = false, + drop = "", + corresponding_piston = "mesecons_pistons:piston_sticky_on", + selection_box = piston_pusher_box, + node_box = piston_pusher_box, + sounds = mcl_sounds.node_sound_wood_defaults(), + _mcl_blast_resistance = 0.5, + on_rotate = false, +}) + +-- +-- +-- UP +-- +-- + +local piston_up_pusher_box = { + type = "fixed", + fixed = { + {-2/16, -.5 - pt, -2/16, 2/16, .5 - pt, 2/16}, + {-.5 , .5 - pt, -.5 , .5 , .5 , .5}, + }, +} + +local piston_up_on_box = { + type = "fixed", + fixed = { + {-.5, -.5, -.5 , .5, .5-pt, .5} + }, +} + +-- Normal + +local pistonspec_normal_up = { + offname = "mesecons_pistons:piston_up_normal_off", + onname = "mesecons_pistons:piston_up_normal_on", + dir = {x = 0, y = 1, z = 0}, + pusher = "mesecons_pistons:piston_up_pusher_normal", +} + +-- offstate +minetest.register_node("mesecons_pistons:piston_up_normal_off", { + tiles = { + "mesecons_piston_pusher_front.png", + "mesecons_piston_back.png", + "mesecons_piston_bottom.png", + "mesecons_piston_bottom.png", + "mesecons_piston_bottom.png", + "mesecons_piston_bottom.png", + }, + groups = {handy=1, piston=1, not_in_creative_inventory=1}, + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + drop = "mesecons_pistons:piston_normal_off", + mesecons_piston = pistonspec_normal_up, + mesecons = { + effector = { + action_on = piston_on, + rules = piston_up_rules, + }, + }, + sounds = mcl_sounds.node_sound_stone_defaults({ + footstep = mcl_sounds.node_sound_wood_defaults().footstep + }), + _mcl_blast_resistance = 0.5, + _mcl_hardness = 0.5, + on_rotate = function(pos, node, user, mode) + if mode == screwdriver.ROTATE_AXIS then + minetest.set_node(pos, {name="mesecons_pistons:piston_down_normal_off"}) + return true + end + return false + end, +}) + +-- onstate +minetest.register_node("mesecons_pistons:piston_up_normal_on", { + drawtype = "nodebox", + tiles = { + "mesecons_piston_on_front.png", + "mesecons_piston_back.png", + "mesecons_piston_bottom.png", + "mesecons_piston_bottom.png", + "mesecons_piston_bottom.png", + "mesecons_piston_bottom.png", + }, + groups = {handy=1, piston_=1, not_in_creative_inventory=1}, + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + drop = "mesecons_pistons:piston_normal_off", + after_destruct = piston_remove_pusher, + node_box = piston_up_on_box, + selection_box = piston_up_on_box, + mesecons_piston = pistonspec_normal_up, + sounds = mcl_sounds.node_sound_stone_defaults(), + mesecons = { + effector = { + action_off = piston_off, + rules = piston_up_rules, + }, + }, + _mcl_blast_resistance = 0.5, + _mcl_hardness = 0.5, + on_rotate = false, +}) + +-- pusher +minetest.register_node("mesecons_pistons:piston_up_pusher_normal", { + drawtype = "nodebox", + tiles = { + "mesecons_piston_pusher_front.png", + "mesecons_piston_pusher_back.png", + "mesecons_piston_pusher_left.png^[transformR270", + "mesecons_piston_pusher_right.png^[transformR90", + "mesecons_piston_pusher_bottom.png", + "mesecons_piston_pusher_top.png^[transformR180", + }, + paramtype = "light", + paramtype2 = "facedir", + groups = {piston_pusher=1}, + is_ground_content = false, + after_destruct = piston_remove_base, + diggable = false, + drop = "", + corresponding_piston = "mesecons_pistons:piston_up_normal_on", + selection_box = piston_up_pusher_box, + node_box = piston_up_pusher_box, + sounds = mcl_sounds.node_sound_wood_defaults(), + _mcl_blast_resistance = 0.5, + on_rotate = false, +}) + + + +-- Sticky + + +local pistonspec_sticky_up = { + offname = "mesecons_pistons:piston_up_sticky_off", + onname = "mesecons_pistons:piston_up_sticky_on", + dir = {x = 0, y = 1, z = 0}, + pusher = "mesecons_pistons:piston_up_pusher_sticky", + sticky = true, +} + +-- offstate +minetest.register_node("mesecons_pistons:piston_up_sticky_off", { + tiles = { + "mesecons_piston_pusher_front_sticky.png", + "mesecons_piston_back.png", + "mesecons_piston_bottom.png", + "mesecons_piston_bottom.png", + "mesecons_piston_bottom.png", + "mesecons_piston_bottom.png", + }, + groups = {handy=1, piston=2, not_in_creative_inventory=1}, + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + drop = "mesecons_pistons:piston_sticky_off", + mesecons_piston = pistonspec_sticky_up, + sounds = mcl_sounds.node_sound_stone_defaults({ + footstep = mcl_sounds.node_sound_wood_defaults().footstep + }), + mesecons = { + effector = { + action_on = piston_on, + rules = piston_up_rules, + }, + }, + _mcl_blast_resistance = 0.5, + _mcl_hardness = 0.5, + on_rotate = function(pos, node, user, mode) + if mode == screwdriver.ROTATE_AXIS then + minetest.set_node(pos, {name="mesecons_pistons:piston_down_sticky_off"}) + return true + end + return false + end, +}) + +-- onstate +minetest.register_node("mesecons_pistons:piston_up_sticky_on", { + drawtype = "nodebox", + tiles = { + "mesecons_piston_on_front.png", + "mesecons_piston_back.png", + "mesecons_piston_bottom.png", + "mesecons_piston_bottom.png", + "mesecons_piston_bottom.png", + "mesecons_piston_bottom.png", + }, + groups = {handy=1, piston=2, not_in_creative_inventory=1}, + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + drop = "mesecons_pistons:piston_sticky_off", + after_destruct = piston_remove_pusher, + node_box = piston_up_on_box, + selection_box = piston_up_on_box, + mesecons_piston = pistonspec_sticky_up, + sounds = mcl_sounds.node_sound_stone_defaults(), + mesecons = { + effector = { + action_off = piston_off, + rules = piston_up_rules, + }, + }, + _mcl_blast_resistance = 0.5, + _mcl_hardness = 0.5, + on_rotate = false, +}) + +-- pusher +minetest.register_node("mesecons_pistons:piston_up_pusher_sticky", { + drawtype = "nodebox", + tiles = { + "mesecons_piston_pusher_front_sticky.png", + "mesecons_piston_pusher_back.png", + "mesecons_piston_pusher_left.png^[transformR270", + "mesecons_piston_pusher_right.png^[transformR90", + "mesecons_piston_pusher_bottom.png", + "mesecons_piston_pusher_top.png^[transformR180", + }, + paramtype = "light", + paramtype2 = "facedir", + groups = {piston_pusher=2}, + is_ground_content = false, + after_destruct = piston_remove_base, + diggable = false, + drop = "", + corresponding_piston = "mesecons_pistons:piston_up_sticky_on", + selection_box = piston_up_pusher_box, + node_box = piston_up_pusher_box, + sounds = mcl_sounds.node_sound_wood_defaults(), + _mcl_blast_resistance = 0.5, + on_rotate = false, +}) + +-- +-- +-- DOWN +-- +-- + +local piston_down_pusher_box = { + type = "fixed", + fixed = { + {-2/16, -.5 + pt, -2/16, 2/16, .5 + pt, 2/16}, + {-.5 , -.5 , -.5 , .5 , -.5 + pt, .5}, + }, +} + +local piston_down_on_box = { + type = "fixed", + fixed = { + {-.5, -.5+pt, -.5 , .5, .5, .5} + }, +} + + + +-- Normal + +local pistonspec_normal_down = { + offname = "mesecons_pistons:piston_down_normal_off", + onname = "mesecons_pistons:piston_down_normal_on", + dir = {x = 0, y = -1, z = 0}, + pusher = "mesecons_pistons:piston_down_pusher_normal", +} + +-- offstate +minetest.register_node("mesecons_pistons:piston_down_normal_off", { + tiles = { + "mesecons_piston_back.png", + "mesecons_piston_pusher_front.png", + "mesecons_piston_bottom.png^[transformR180", + "mesecons_piston_bottom.png^[transformR180", + "mesecons_piston_bottom.png^[transformR180", + "mesecons_piston_bottom.png^[transformR180", + }, + groups = {handy=1, piston=1, not_in_creative_inventory=1}, + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + drop = "mesecons_pistons:piston_normal_off", + mesecons_piston = pistonspec_normal_down, + sounds = mcl_sounds.node_sound_stone_defaults(), + mesecons = { + effector = { + action_on = piston_on, + rules = piston_down_rules, + }, + }, + _mcl_blast_resistance = 0.5, + _mcl_hardness = 0.5, + on_rotate = function(pos, node, user, mode) + if mode == screwdriver.ROTATE_AXIS then + minetest.set_node(pos, {name="mesecons_pistons:piston_normal_off"}) + return true + end + return false + end, +}) + +-- onstate +minetest.register_node("mesecons_pistons:piston_down_normal_on", { + drawtype = "nodebox", + tiles = { + "mesecons_piston_back.png", + "mesecons_piston_on_front.png", + "mesecons_piston_bottom.png^[transformR180", + "mesecons_piston_bottom.png^[transformR180", + "mesecons_piston_bottom.png^[transformR180", + "mesecons_piston_bottom.png^[transformR180", + }, + groups = {handy=1, piston=1, not_in_creative_inventory=1}, + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + drop = "mesecons_pistons:piston_normal_off", + after_destruct = piston_remove_pusher, + node_box = piston_down_on_box, + selection_box = piston_down_on_box, + mesecons_piston = pistonspec_normal_down, + sounds = mcl_sounds.node_sound_stone_defaults(), + mesecons = { + effector = { + action_off = piston_off, + rules = piston_down_rules, + }, + }, + _mcl_blast_resistance = 0.5, + _mcl_hardness = 0.5, + on_rotate = false, +}) + +-- pusher +minetest.register_node("mesecons_pistons:piston_down_pusher_normal", { + drawtype = "nodebox", + tiles = { + "mesecons_piston_pusher_back.png", + "mesecons_piston_pusher_front.png", + "mesecons_piston_pusher_left.png^[transformR90", + "mesecons_piston_pusher_right.png^[transformR270", + "mesecons_piston_pusher_bottom.png^[transformR180", + "mesecons_piston_pusher_top.png", + }, + paramtype = "light", + paramtype2 = "facedir", + groups = {piston_pusher=1}, + is_ground_content = false, + after_destruct = piston_remove_base, + diggable = false, + drop = "", + corresponding_piston = "mesecons_pistons:piston_down_normal_on", + selection_box = piston_down_pusher_box, + node_box = piston_down_pusher_box, + sounds = mcl_sounds.node_sound_wood_defaults(), + _mcl_blast_resistance = 0.5, + on_rotate = false, +}) + +-- Sticky + +local pistonspec_sticky_down = { + onname = "mesecons_pistons:piston_down_sticky_on", + offname = "mesecons_pistons:piston_down_sticky_off", + dir = {x = 0, y = -1, z = 0}, + pusher = "mesecons_pistons:piston_down_pusher_sticky", + sticky = true, +} + +-- offstate +minetest.register_node("mesecons_pistons:piston_down_sticky_off", { + tiles = { + "mesecons_piston_back.png", + "mesecons_piston_pusher_front_sticky.png", + "mesecons_piston_bottom.png^[transformR180", + "mesecons_piston_bottom.png^[transformR180", + "mesecons_piston_bottom.png^[transformR180", + "mesecons_piston_bottom.png^[transformR180", + }, + groups = {handy=1, piston=2, not_in_creative_inventory = 1}, + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + drop = "mesecons_pistons:piston_sticky_off", + mesecons_piston = pistonspec_sticky_down, + sounds = mcl_sounds.node_sound_stone_defaults(), + mesecons = { + effector = { + action_on = piston_on, + rules = piston_down_rules, + }, + }, + _mcl_blast_resistance = 0.5, + _mcl_hardness = 0.5, + on_rotate = function(pos, node, user, mode) + if mode == screwdriver.ROTATE_AXIS then + minetest.set_node(pos, {name="mesecons_pistons:piston_sticky_off"}) + return true + end + return false + end, +}) + +-- onstate +minetest.register_node("mesecons_pistons:piston_down_sticky_on", { + drawtype = "nodebox", + tiles = { + "mesecons_piston_back.png", + "mesecons_piston_on_front.png", + "mesecons_piston_bottom.png^[transformR180", + "mesecons_piston_bottom.png^[transformR180", + "mesecons_piston_bottom.png^[transformR180", + "mesecons_piston_bottom.png^[transformR180", + }, + groups = {handy=1, piston=1, not_in_creative_inventory=1}, + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + drop = "mesecons_pistons:piston_sticky_off", + after_destruct = piston_remove_pusher, + node_box = piston_down_on_box, + selection_box = piston_down_on_box, + mesecons_piston = pistonspec_sticky_down, + sounds = mcl_sounds.node_sound_stone_defaults(), + mesecons = { + effector = { + action_off = piston_off, + rules = piston_down_rules, + }, + }, + _mcl_blast_resistance = 0.5, + _mcl_hardness = 0.5, + on_rotate = false, +}) + +-- pusher +minetest.register_node("mesecons_pistons:piston_down_pusher_sticky", { + drawtype = "nodebox", + tiles = { + "mesecons_piston_pusher_back.png", + "mesecons_piston_pusher_front_sticky.png", + "mesecons_piston_pusher_left.png^[transformR90", + "mesecons_piston_pusher_right.png^[transformR270", + "mesecons_piston_pusher_bottom.png^[transformR180", + "mesecons_piston_pusher_top.png", + }, + paramtype = "light", + paramtype2 = "facedir", + groups = {piston_pusher=2}, + is_ground_content = false, + after_destruct = piston_remove_base, + diggable = false, + drop = "", + corresponding_piston = "mesecons_pistons:piston_down_sticky_on", + selection_box = piston_down_pusher_box, + node_box = piston_down_pusher_box, + sounds = mcl_sounds.node_sound_wood_defaults(), + _mcl_blast_resistance = 0.5, + on_rotate = false, +}) + + +mesecon.register_mvps_stopper("mesecons_pistons:piston_pusher_normal") +mesecon.register_mvps_stopper("mesecons_pistons:piston_pusher_sticky") +mesecon.register_mvps_stopper("mesecons_pistons:piston_up_pusher_normal") +mesecon.register_mvps_stopper("mesecons_pistons:piston_up_pusher_sticky") +mesecon.register_mvps_stopper("mesecons_pistons:piston_down_pusher_normal") +mesecon.register_mvps_stopper("mesecons_pistons:piston_down_pusher_sticky") +mesecon.register_mvps_stopper("mesecons_pistons:piston_normal_on") +mesecon.register_mvps_stopper("mesecons_pistons:piston_sticky_on") +mesecon.register_mvps_stopper("mesecons_pistons:piston_up_normal_on") +mesecon.register_mvps_stopper("mesecons_pistons:piston_up_sticky_on") +mesecon.register_mvps_stopper("mesecons_pistons:piston_down_normal_on") +mesecon.register_mvps_stopper("mesecons_pistons:piston_down_sticky_on") + +--craft recipes +minetest.register_craft({ + output = "mesecons_pistons:piston_normal_off", + recipe = { + {"group:wood", "group:wood", "group:wood"}, + {"mcl_core:cobble", "mcl_core:iron_ingot", "mcl_core:cobble"}, + {"mcl_core:cobble", "mesecons:redstone", "mcl_core:cobble"}, + }, +}) + +minetest.register_craft({ + output = "mesecons_pistons:piston_sticky_off", + recipe = { + {"mcl_mobitems:slimeball"}, + {"mesecons_pistons:piston_normal_off"}, + }, +}) + +-- Add entry aliases for the Help +if minetest.get_modpath("doc") then + doc.add_entry_alias("nodes", "mesecons_pistons:piston_normal_off", "nodes", "mesecons_pistons:piston_normal_on") + doc.add_entry_alias("nodes", "mesecons_pistons:piston_normal_off", "nodes", "mesecons_pistons:piston_up_normal_off") + doc.add_entry_alias("nodes", "mesecons_pistons:piston_normal_off", "nodes", "mesecons_pistons:piston_up_normal_on") + doc.add_entry_alias("nodes", "mesecons_pistons:piston_normal_off", "nodes", "mesecons_pistons:piston_down_normal_off") + doc.add_entry_alias("nodes", "mesecons_pistons:piston_normal_off", "nodes", "mesecons_pistons:piston_down_normal_on") + doc.add_entry_alias("nodes", "mesecons_pistons:piston_normal_off", "nodes", "mesecons_pistons:piston_pusher_normal") + doc.add_entry_alias("nodes", "mesecons_pistons:piston_normal_off", "nodes", "mesecons_pistons:piston_up_pusher_normal") + doc.add_entry_alias("nodes", "mesecons_pistons:piston_normal_off", "nodes", "mesecons_pistons:piston_down_pusher_normal") + + doc.add_entry_alias("nodes", "mesecons_pistons:piston_sticky_off", "nodes", "mesecons_pistons:piston_sticky_on") + doc.add_entry_alias("nodes", "mesecons_pistons:piston_sticky_off", "nodes", "mesecons_pistons:piston_up_sticky_off") + doc.add_entry_alias("nodes", "mesecons_pistons:piston_sticky_off", "nodes", "mesecons_pistons:piston_up_sticky_on") + doc.add_entry_alias("nodes", "mesecons_pistons:piston_sticky_off", "nodes", "mesecons_pistons:piston_down_sticky_off") + doc.add_entry_alias("nodes", "mesecons_pistons:piston_sticky_off", "nodes", "mesecons_pistons:piston_down_sticky_on") + doc.add_entry_alias("nodes", "mesecons_pistons:piston_sticky_off", "nodes", "mesecons_pistons:piston_pusher_sticky") + doc.add_entry_alias("nodes", "mesecons_pistons:piston_sticky_off", "nodes", "mesecons_pistons:piston_up_pusher_sticky") + doc.add_entry_alias("nodes", "mesecons_pistons:piston_sticky_off", "nodes", "mesecons_pistons:piston_down_pusher_sticky") +end + diff --git a/mesecons_pistons/locale/mesecons_pistons.de.tr b/mesecons_pistons/locale/mesecons_pistons.de.tr new file mode 100644 index 0000000..9719812 --- /dev/null +++ b/mesecons_pistons/locale/mesecons_pistons.de.tr @@ -0,0 +1,8 @@ +# textdomain: mesecons_pistons +This block can have one of 6 possible orientations.=Dieser Block kann eine von 6 möglichen Richtungen annehmen. +Piston=Kolben +A piston is a redstone component with a pusher which pushes the block or blocks in front of it when it is supplied with redstone power. Not all blocks can be pushed, however.=Ein Kolben ist eine Redstonekomponente mit einem Schieber den Block oder die Blöcke vor ihm schieben wird, wenn er mit Redstoneenergie versorgt wird. Allerdings können nicht alle Blöcke können geschoben werden. +Sticky Piston=Klebriger Kolben +A sticky piston is a redstone component with a sticky pusher which can be extended and retracted. It extends when it is supplied with redstone power. When the pusher extends, it pushes the block or blocks in front of it. When it retracts, it pulls back the single block in front of it. Note that not all blocks can be pushed or pulled.=Ein klebriger Kolben ist eine Redstonekomponente mit einem klebrigen Schieber, der ein- und ausgefahren werden kann. Er fährt aus, wenn er mit Redstoneenergie versorgt wird. Wenn der Schieber ausgefahren wird, schiebt er den Block oder die Blöcke vor ihm. Wird er eingefahren, zieht er den Block vor ihm zu sich. Nicht alle Blöcke können geschoben oder gezogen werden. +Pushes block when powered by redstone power=Schiebt Block, wenn mit Redstoneenergie versorgt +Pushes or pulls block when powered by redstone power=Schiebt oder zieht Block, wenn mit Redstoneenergie versorgt diff --git a/mesecons_pistons/locale/mesecons_pistons.es.tr b/mesecons_pistons/locale/mesecons_pistons.es.tr new file mode 100644 index 0000000..113472a --- /dev/null +++ b/mesecons_pistons/locale/mesecons_pistons.es.tr @@ -0,0 +1,6 @@ +# textdomain: mesecons_pistons +This block can have one of 6 possible orientations.=Este bloque puede tener una de las 6 orientaciones posibles. +Piston=Pistón +A piston is a redstone component with a pusher which pushes the block or blocks in front of it when it is supplied with redstone power. Not all blocks can be pushed, however.=Un pistón es un componente de redstone con un empujador que empuja el bloque o bloques frente a él cuando se le suministra energía de redstone. Sin embargo, no todos los bloques se pueden empujar. +Sticky Piston=Pistón pegajoso +A sticky piston is a redstone component with a sticky pusher which can be extended and retracted. It extends when it is supplied with redstone power. When the pusher extends, it pushes the block or blocks in front of it. When it retracts, it pulls back the single block in front of it. Note that not all blocks can be pushed or pulled.=Un pistón pegajoso es un componente de redstone con un empujador pegajoso que se puede extender y retraer. Se extiende cuando se le suministra energía de redstone. Cuando el empujador se extiende, empuja el bloque o bloques frente a él. Cuando se retrae, tira hacia atrás el bloque único que está frente a él. Tenga en cuenta que no todos los bloques se pueden empujar o tirar. diff --git a/mesecons_pistons/locale/mesecons_pistons.fr.tr b/mesecons_pistons/locale/mesecons_pistons.fr.tr new file mode 100644 index 0000000..9046e2d --- /dev/null +++ b/mesecons_pistons/locale/mesecons_pistons.fr.tr @@ -0,0 +1,8 @@ +# textdomain: mesecons_pistons +This block can have one of 6 possible orientations.=Ce bloc peut avoir l'une des 6 orientations possibles. +Piston=Piston +A piston is a redstone component with a pusher which pushes the block or blocks in front of it when it is supplied with redstone power. Not all blocks can be pushed, however.=Un piston est un composant de redstone avec un poussoir qui pousse le ou les blocs devant lui lorsqu'il est alimenté en redstone. Cependant, tous les blocs ne peuvent pas être poussés. +Sticky Piston=Piston collant +A sticky piston is a redstone component with a sticky pusher which can be extended and retracted. It extends when it is supplied with redstone power. When the pusher extends, it pushes the block or blocks in front of it. When it retracts, it pulls back the single block in front of it. Note that not all blocks can be pushed or pulled.=Un piston collant est un composant de redstone avec un poussoir collant qui peut être étendu et rétracté. Il se prolonge lorsqu'il est alimenté en redstone. Lorsque le poussoir s'étend, il pousse le ou les blocs devant lui. Quand il se rétracte, il recule le bloc unique devant lui. Notez que tous les blocs ne peuvent pas être poussés ou tirés. +Pushes block when powered by redstone power=Pousse le bloc lorsqu'il est alimenté par la puissance Redstone +Pushes or pulls block when powered by redstone power=Pousse ou tire le bloc lorsqu'il est alimenté par une puissance redstone diff --git a/mesecons_pistons/locale/mesecons_pistons.pl.tr b/mesecons_pistons/locale/mesecons_pistons.pl.tr new file mode 100644 index 0000000..8f7f451 --- /dev/null +++ b/mesecons_pistons/locale/mesecons_pistons.pl.tr @@ -0,0 +1,9 @@ +# textdomain: mesecons_pistons +This block can have one of 6 possible orientations.=Ten blok może mieć 6 możliwych orientacji. +Piston=Tłok +A piston is a redstone component with a pusher which pushes the block or blocks in front of it when it is supplied with redstone power. Not all blocks can be pushed, however.=Tłoki są mechanizmami czerwienitowymi które popycha blok lub bloki stojące przed nim gdy dostarczy się mu energię czerwienitową, jednak nie wszystkie bloki mogą zostać popchnięte. +Sticky Piston=Lepki tłok +A sticky piston is a redstone component with a sticky pusher which can be extended and retracted. It extends when it is supplied with redstone power. When the pusher extends, it pushes the block or blocks in front of it. When it retracts, it pulls back the single block in front of it. Note that not all blocks can be pushed or pulled.=Lepki tłok jest mechanizmem czerwienitowym z lepkim wysięgnikiem, który można wysuwać i wsuwać. Wysuwa się gdy dostarczana jest energia czerwienitowa. Gdy się wysuwa popycha on blok lub bloki znajdujące się przed nim. Gdy się wsuwa przyciąga on pojedynczy blok przed nim. Nie wszystkie bloki mogą być przesuwane i przyciągane. +Pushes block when powered by redstone power=Popycha blok gdy jest zasilony czerwienitem +Pushes or pulls block when powered by redstone power=Popycha lub przyciąga blok gdy jest zasilany czerwienitem + diff --git a/mesecons_pistons/locale/mesecons_pistons.ru.tr b/mesecons_pistons/locale/mesecons_pistons.ru.tr new file mode 100644 index 0000000..d69542e --- /dev/null +++ b/mesecons_pistons/locale/mesecons_pistons.ru.tr @@ -0,0 +1,8 @@ +# textdomain: mesecons_pistons +This block can have one of 6 possible orientations.=Этот блок быть ориентирован в одном из 6 возможных направлений. +Piston=Поршень +A piston is a redstone component with a pusher which pushes the block or blocks in front of it when it is supplied with redstone power. Not all blocks can be pushed, however.=Поршень это компонент редстоуна с толкателем, который толкает блок или блоки перед собой при подаче энергии редстоуна. Следует отметить, что не все блоки могут быть сдвинуты. +Sticky Piston=Липкий поршень +A sticky piston is a redstone component with a sticky pusher which can be extended and retracted. It extends when it is supplied with redstone power. When the pusher extends, it pushes the block or blocks in front of it. When it retracts, it pulls back the single block in front of it. Note that not all blocks can be pushed or pulled.=Липкий поршень представляет собой компонент редстоуна с липким толкателем, который можно удлинять и втягивать обратно. Он расширяется, когда на него подается энергия красного камня. Когда толкатель выдвигается, он толкает блок или блоки перед собой. Когда он втягивается, он возвращает обратно один блок перед собой. Следует отметить, что не все блоки могут быть сдвинуты. или втянуты. +Pushes block when powered by redstone power=Толкает блок при подаче энергии редстоуна +Pushes or pulls block when powered by redstone power=Толкает или тянет блок при подаче энергии редстоуна diff --git a/mesecons_pistons/locale/template.txt b/mesecons_pistons/locale/template.txt new file mode 100644 index 0000000..6b54c58 --- /dev/null +++ b/mesecons_pistons/locale/template.txt @@ -0,0 +1,8 @@ +# textdomain: mesecons_pistons +This block can have one of 6 possible orientations.= +Piston= +A piston is a redstone component with a pusher which pushes the block or blocks in front of it when it is supplied with redstone power. Not all blocks can be pushed, however.= +Sticky Piston= +A sticky piston is a redstone component with a sticky pusher which can be extended and retracted. It extends when it is supplied with redstone power. When the pusher extends, it pushes the block or blocks in front of it. When it retracts, it pulls back the single block in front of it. Note that not all blocks can be pushed or pulled.= +Pushes block when powered by redstone power= +Pushes or pulls block when powered by redstone power= diff --git a/mesecons_pistons/mod.conf b/mesecons_pistons/mod.conf new file mode 100644 index 0000000..5a3f6c8 --- /dev/null +++ b/mesecons_pistons/mod.conf @@ -0,0 +1,3 @@ +name = mesecons_pistons +depends = mesecons, mesecons_mvps, mcl_mobitems +optional_depends = doc, screwdriver diff --git a/mesecons_pistons/sounds/piston_extend.ogg b/mesecons_pistons/sounds/piston_extend.ogg new file mode 100644 index 0000000..e234ad9 Binary files /dev/null and b/mesecons_pistons/sounds/piston_extend.ogg differ diff --git a/mesecons_pistons/sounds/piston_retract.ogg b/mesecons_pistons/sounds/piston_retract.ogg new file mode 100644 index 0000000..feb9f04 Binary files /dev/null and b/mesecons_pistons/sounds/piston_retract.ogg differ diff --git a/mesecons_pistons/textures/mesecons_piston_back.png b/mesecons_pistons/textures/mesecons_piston_back.png new file mode 100644 index 0000000..6ea941d Binary files /dev/null and b/mesecons_pistons/textures/mesecons_piston_back.png differ diff --git a/mesecons_pistons/textures/mesecons_piston_bottom.png b/mesecons_pistons/textures/mesecons_piston_bottom.png new file mode 100644 index 0000000..b3b4471 Binary files /dev/null and b/mesecons_pistons/textures/mesecons_piston_bottom.png differ diff --git a/mesecons_pistons/textures/mesecons_piston_on_front.png b/mesecons_pistons/textures/mesecons_piston_on_front.png new file mode 100644 index 0000000..a718134 Binary files /dev/null and b/mesecons_pistons/textures/mesecons_piston_on_front.png differ diff --git a/mesecons_pistons/textures/mesecons_piston_pusher_back.png b/mesecons_pistons/textures/mesecons_piston_pusher_back.png new file mode 100644 index 0000000..79ecafc Binary files /dev/null and b/mesecons_pistons/textures/mesecons_piston_pusher_back.png differ diff --git a/mesecons_pistons/textures/mesecons_piston_pusher_bottom.png b/mesecons_pistons/textures/mesecons_piston_pusher_bottom.png new file mode 100644 index 0000000..79ecafc Binary files /dev/null and b/mesecons_pistons/textures/mesecons_piston_pusher_bottom.png differ diff --git a/mesecons_pistons/textures/mesecons_piston_pusher_front.png b/mesecons_pistons/textures/mesecons_piston_pusher_front.png new file mode 100644 index 0000000..79ecafc Binary files /dev/null and b/mesecons_pistons/textures/mesecons_piston_pusher_front.png differ diff --git a/mesecons_pistons/textures/mesecons_piston_pusher_front_sticky.png b/mesecons_pistons/textures/mesecons_piston_pusher_front_sticky.png new file mode 100644 index 0000000..8f5eaf4 Binary files /dev/null and b/mesecons_pistons/textures/mesecons_piston_pusher_front_sticky.png differ diff --git a/mesecons_pistons/textures/mesecons_piston_pusher_left.png b/mesecons_pistons/textures/mesecons_piston_pusher_left.png new file mode 100644 index 0000000..79ecafc Binary files /dev/null and b/mesecons_pistons/textures/mesecons_piston_pusher_left.png differ diff --git a/mesecons_pistons/textures/mesecons_piston_pusher_right.png b/mesecons_pistons/textures/mesecons_piston_pusher_right.png new file mode 100644 index 0000000..79ecafc Binary files /dev/null and b/mesecons_pistons/textures/mesecons_piston_pusher_right.png differ diff --git a/mesecons_pistons/textures/mesecons_piston_pusher_top.png b/mesecons_pistons/textures/mesecons_piston_pusher_top.png new file mode 100644 index 0000000..79ecafc Binary files /dev/null and b/mesecons_pistons/textures/mesecons_piston_pusher_top.png differ diff --git a/mesecons_pressureplates/init.lua b/mesecons_pressureplates/init.lua new file mode 100644 index 0000000..c089422 --- /dev/null +++ b/mesecons_pressureplates/init.lua @@ -0,0 +1,204 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + +local PRESSURE_PLATE_INTERVAL = 0.04 + +local pp_box_off = { + type = "fixed", + fixed = { -7/16, -8/16, -7/16, 7/16, -7/16, 7/16 }, +} + +local pp_box_on = { + type = "fixed", + fixed = { -7/16, -8/16, -7/16, 7/16, -7.5/16, 7/16 }, +} + +local function pp_on_timer(pos, elapsed) + local node = minetest.get_node(pos) + local basename = minetest.registered_nodes[node.name].pressureplate_basename + local activated_by = minetest.registered_nodes[node.name].pressureplate_activated_by + + -- This is a workaround for a strange bug that occurs when the server is started + -- For some reason the first time on_timer is called, the pos is wrong + if not basename then return end + + if activated_by == nil then + activated_by = { any = true } + end + + local obj_does_activate = function(obj, activated_by) + if activated_by.any then + return true + elseif activated_by.mob and obj:get_luaentity() and obj:get_luaentity()._cmi_is_mob == true then + return true + elseif activated_by.player and obj:is_player() then + return true + else + return false + end + end + + local objs = minetest.get_objects_inside_radius(pos, 1) + + if node.name == basename .. "_on" then + local disable + if #objs == 0 then + disable = true + elseif not activated_by.any then + disable = true + for k, obj in pairs(objs) do + if obj_does_activate(obj, activated_by) then + disable = false + break + end + end + end + if disable then + minetest.set_node(pos, {name = basename .. "_off"}) + mesecon.receptor_off(pos, mesecon.rules.pplate) + end + elseif node.name == basename .. "_off" then + for k, obj in pairs(objs) do + local objpos = obj:get_pos() + if obj_does_activate(obj, activated_by) then + if objpos.y > pos.y-1 and objpos.y < pos.y then + minetest.set_node(pos, {name = basename .. "_on"}) + mesecon.receptor_on(pos, mesecon.rules.pplate) + break + end + end + end + end + return true +end + +-- Register a Pressure Plate +-- basename: base name of the pressure plate +-- description: description displayed in the player's inventory +-- textures_off:textures of the pressure plate when inactive +-- textures_on: textures of the pressure plate when active +-- image_w: wield image of the pressure plate +-- image_i: inventory image of the pressure plate +-- recipe: crafting recipe of the pressure plate +-- sounds: sound table (like in minetest.register_node) +-- plusgroups: group memberships (attached_node=1 and not_in_creative_inventory=1 are already used) +-- activated_by: optinal table with elements denoting by which entities this pressure plate is triggered +-- Possible table fields: +-- * player=true: Player +-- * mob=true: Mob +-- By default, is triggered by all entities +-- longdesc: Customized long description for the in-game help (if omitted, a dummy text is used) + +function mesecon.register_pressure_plate(basename, description, textures_off, textures_on, image_w, image_i, recipe, sounds, plusgroups, activated_by, longdesc) + local groups_off = table.copy(plusgroups) + groups_off.attached_node = 1 + groups_off.dig_by_piston = 1 + groups_off.pressure_plate = 1 + local groups_on = table.copy(groups_off) + groups_on.not_in_creative_inventory = 1 + groups_on.pressure_plate = 2 + if not longdesc then + longdesc = S("A pressure plate is a redstone component which supplies its surrounding blocks with redstone power while someone or something rests on top of it.") + end + local tt = S("Provides redstone power when pushed") + if not activated_by then + tt = tt .. "\n" .. S("Pushable by players, mobs and objects") + elseif activated_by.mob and activated_by.player then + tt = tt .. "\n" .. S("Pushable by players and mobs") + elseif activated_by.mob then + tt = tt .. "\n" .. S("Pushable by mobs") + elseif activated_by.player then + tt = tt .. "\n" .. S("Pushable by players") + end + + mesecon.register_node(basename, { + drawtype = "nodebox", + inventory_image = image_i, + wield_image = image_w, + paramtype = "light", + walkable = false, + description = description, + on_timer = pp_on_timer, + on_construct = function(pos) + minetest.get_node_timer(pos):start(PRESSURE_PLATE_INTERVAL) + end, + sounds = sounds, + is_ground_content = false, + pressureplate_basename = basename, + pressureplate_activated_by = activated_by, + _mcl_blast_resistance = 0.5, + _mcl_hardness = 0.5, + },{ + node_box = pp_box_off, + selection_box = pp_box_off, + groups = groups_off, + tiles = textures_off, + + mesecons = {receptor = { state = mesecon.state.off, rules = mesecon.rules.pplate }}, + _doc_items_longdesc = longdesc, + _tt_help = tt, + },{ + node_box = pp_box_on, + selection_box = pp_box_on, + groups = groups_on, + tiles = textures_on, + description = "", + + mesecons = {receptor = { state = mesecon.state.on, rules = mesecon.rules.pplate }}, + _doc_items_create_entry = false, + }) + + minetest.register_craft({ + output = basename .. "_off", + recipe = recipe, + }) + + if minetest.get_modpath("doc") then + doc.add_entry_alias("nodes", basename .. "_off", "nodes", basename .. "_on") + end +end + +local woods = { + { "wood", "mcl_core:wood", "default_wood.png", S("Oak Pressure Plate") }, + { "acaciawood", "mcl_core:acaciawood", "default_acacia_wood.png", S("Acacia Pressure Plate") }, + { "birchwood", "mcl_core:birchwood", "mcl_core_planks_birch.png", S("Birch Pressure Plate") }, + { "darkwood", "mcl_core:darkwood", "mcl_core_planks_big_oak.png", S("Dark Oak Pressure Plate" )}, + { "sprucewood", "mcl_core:sprucewood", "mcl_core_planks_spruce.png", S("Spruce Pressure Plate") }, + { "junglewood", "mcl_core:junglewood", "default_junglewood.png", S("Jungle Pressure Plate") }, +} + +for w=1, #woods do + mesecon.register_pressure_plate( + "mesecons_pressureplates:pressure_plate_"..woods[w][1], + woods[w][4], + {woods[w][3]}, + {woods[w][3]}, + woods[w][3], + nil, + {{woods[w][2], woods[w][2]}}, + mcl_sounds.node_sound_wood_defaults(), + {axey=1, material_wood=1}, + nil, + S("A wooden pressure plate is a redstone component which supplies its surrounding blocks with redstone power while any movable object (including dropped items, players and mobs) rests on top of it.")) + + minetest.register_craft({ + type = "fuel", + recipe = "mesecons_pressureplates:pressure_plate_"..woods[w][1].."_off", + burntime = 15 + }) + +end + +mesecon.register_pressure_plate( + "mesecons_pressureplates:pressure_plate_stone", + S("Stone Pressure Plate"), + {"default_stone.png"}, + {"default_stone.png"}, + "default_stone.png", + nil, + {{"mcl_core:stone", "mcl_core:stone"}}, + mcl_sounds.node_sound_stone_defaults(), + {pickaxey=1, material_stone=1}, + { player = true, mob = true }, + S("A stone pressure plate is a redstone component which supplies its surrounding blocks with redstone power while a player or mob stands on top of it. It is not triggered by anything else.")) + + diff --git a/mesecons_pressureplates/locale/mesecons_pressureplates.de.tr b/mesecons_pressureplates/locale/mesecons_pressureplates.de.tr new file mode 100644 index 0000000..6e5e761 --- /dev/null +++ b/mesecons_pressureplates/locale/mesecons_pressureplates.de.tr @@ -0,0 +1,16 @@ +# textdomain: mesecons_pressureplates +A pressure plate is a redstone component which supplies its surrounding blocks with redstone power while someone or something rests on top of it.=Eine Druckplatte ist eine Redstonekomponente, die ihre benachbarten Blöcke mit Redstoneenergie versorgt, wenn sich jemand oder etwas auf ihr befindet. +Oak Pressure Plate=Eichendruckplatte +Acacia Pressure Plate=Akaziendruckplatte +Birch Pressure Plate=Birkendruckplatte +Dark Oak Pressure Plate=Schwarzeichendruckplatte +Spruce Pressure Plate=Fichtendruckplatte +Jungle Pressure Plate=Dschungeldruckplatte +A wooden pressure plate is a redstone component which supplies its surrounding blocks with redstone power while any movable object (including dropped items, players and mobs) rests on top of it.=Eine Holzdruckplatte ist eine Redstonekomponente, die ihre benachbarten Blöcke mit Redstoneenergie versorgt, solange sich ein beliebiges bewegliches Objekt (wie Gegenstände, Spieler und Mobs) auf ihm befindet. +Stone Pressure Plate=Steindruckplatte +A stone pressure plate is a redstone component which supplies its surrounding blocks with redstone power while a player or mob stands on top of it. It is not triggered by anything else.=Eine Steindruckplatte ist eine Redstonekomponente, die ihre benachbarten Blöcke mit Redstoneenergie versorgt, solange sich ein Spieler oder Mob auf ihm befindet. Sie wird von nichts anderem ausgelöst. +Provides redstone power when pushed=Gibt Redstoneenergie aus, wenn gedrückt +Pushable by players, mobs and objects=Drückbar von Spielern, Mobs und Objekten +Pushable by players and mobs=Drückbar von Spielern und Mobs +Pushable by players=Drückbar von Spielern +Pushable by mobs=Drückbar von Mobs diff --git a/mesecons_pressureplates/locale/mesecons_pressureplates.es.tr b/mesecons_pressureplates/locale/mesecons_pressureplates.es.tr new file mode 100644 index 0000000..d30dfbf --- /dev/null +++ b/mesecons_pressureplates/locale/mesecons_pressureplates.es.tr @@ -0,0 +1,11 @@ +# textdomain: mesecons_pressureplates +A pressure plate is a redstone component which supplies its surrounding blocks with redstone power while someone or something rests on top of it.=Una placa de presión es un componente de redstone que suministra a sus bloques circundantes energía de redstone mientras alguien o algo descansa sobre ella. +Oak Pressure Plate=Placa de presión de roble +Acacia Pressure Plate=Placa de presión de acacia +Birch Pressure Plate=Placa de presión de abedul +Dark Oak Pressure Plate=Placa de presión de roble oscuro +Spruce Pressure Plate=Placa de presión de abeto +Jungle Pressure Plate=Placa de presión de jungla +A wooden pressure plate is a redstone component which supplies its surrounding blocks with redstone power while any movable object (including dropped items, players and mobs) rests on top of it.=Una placa de presión de madera es un componente de redstone que suministra a sus bloques circundantes energía de redstone mientras que cualquier objeto móvil (incluidos los objetos caídos, jugadores y mobs) descansa sobre él. +Stone Pressure Plate=Placa de presión de piedra +A stone pressure plate is a redstone component which supplies its surrounding blocks with redstone power while a player or mob stands on top of it. It is not triggered by anything else.=Una placa de presión de piedra es un componente de redstone que suministra a sus bloques circundantes poder de redstone mientras un jugador o una criatura se paran encima. No se desencadena por nada más. diff --git a/mesecons_pressureplates/locale/mesecons_pressureplates.fr.tr b/mesecons_pressureplates/locale/mesecons_pressureplates.fr.tr new file mode 100644 index 0000000..ef145de --- /dev/null +++ b/mesecons_pressureplates/locale/mesecons_pressureplates.fr.tr @@ -0,0 +1,16 @@ +# textdomain: mesecons_pressureplates +A pressure plate is a redstone component which supplies its surrounding blocks with redstone power while someone or something rests on top of it.=Une plaque de pression est un composant de redstone qui alimente ses blocs environnants en puissance de redstone pendant que quelqu'un ou quelque chose repose dessus. +Oak Pressure Plate=Plaque de pression en Chêne +Acacia Pressure Plate=Plaque de pression en Acacia +Birch Pressure Plate=Plaque de pression en Bouleau +Dark Oak Pressure Plate=Plaque de pression en Chêne Noir +Spruce Pressure Plate=Plaque de pression en Sapin +Jungle Pressure Plate=Plaque de pression en Acajou +A wooden pressure plate is a redstone component which supplies its surrounding blocks with redstone power while any movable object (including dropped items, players and mobs) rests on top of it.=Une plaque de pression en bois est un composant de redstone qui alimente ses blocs environnants en puissance de redstone tandis que tout objet mobile (y compris les objets lâchés, les joueurs et les mobs) repose dessus. +Stone Pressure Plate=Plaque de pression en pierre +A stone pressure plate is a redstone component which supplies its surrounding blocks with redstone power while a player or mob stands on top of it. It is not triggered by anything else.=Une plaque de pression en pierre est un composant de redstone qui alimente ses blocs environnants en puissance de redstone pendant qu'un joueur ou un mob se tient au-dessus. Il n'est déclenché par rien d'autre. +Provides redstone power when pushed=Fournit une puissance de redstone lorsqu'il est poussé +Pushable by players, mobs and objects=Poussable par les joueurs, les mobs et les objets +Pushable by players and mobs=Poussable par les joueurs et les mobs +Pushable by players=Poussable par les joueurs +Pushable by mobs=Poussable par les mobs diff --git a/mesecons_pressureplates/locale/mesecons_pressureplates.pl.tr b/mesecons_pressureplates/locale/mesecons_pressureplates.pl.tr new file mode 100644 index 0000000..50cef3b --- /dev/null +++ b/mesecons_pressureplates/locale/mesecons_pressureplates.pl.tr @@ -0,0 +1,16 @@ +# textdomain: mesecons_pressureplates +A pressure plate is a redstone component which supplies its surrounding blocks with redstone power while someone or something rests on top of it.=Płyta naciskowa jest mechanizmem czerwienitowym, który zasila otaczające bloki energią czerwienitową gdy ktoś lub coś na niej spoczywa. +Oak Pressure Plate=Dębowa płyta naciskowa +Acacia Pressure Plate=Akacjowa płyta naciskowa +Birch Pressure Plate=Brzozowa płyta naciskowa +Dark Oak Pressure Plate=Ciemno-dębowa płyta naciskowa +Spruce Pressure Plate=Świerkowa płyta naciskowa +Jungle Pressure Plate=Tropikalna płyta naciskowa +A wooden pressure plate is a redstone component which supplies its surrounding blocks with redstone power while any movable object (including dropped items, players and mobs) rests on top of it.=Drewniana płyta naciskowa jest mechanizmem czerwienitowym, który zasila otaczające bloki energią czerwienitowym, gdy ruchomy obiekt (włączając w to upuszczone przedmioty, graczy, moby) spoczywa na niej. +Stone Pressure Plate=Kamienna płyta naciskowa +A stone pressure plate is a redstone component which supplies its surrounding blocks with redstone power while a player or mob stands on top of it. It is not triggered by anything else.=Kamienna płyta naciskowa jest mechanizmem czerwienitowym, która zasila otaczające bloki energią czerwienitową gdy gracz lub mob na niej stoi. Nie jest aktywowana niczym innym. +Provides redstone power when pushed=Dostarcza energię czerwienitową gdy naciśnięta +Pushable by players, mobs and objects=Możliwa do naciśnięcia przez graczy, moby i obiekty +Pushable by players and mobs=Możliwa do naciśnięcia przez graczy i moby +Pushable by players=Możliwa do naciśnięcia przez graczy +Pushable by mobs=Możliwa do naciśnięcia przez moby diff --git a/mesecons_pressureplates/locale/mesecons_pressureplates.ru.tr b/mesecons_pressureplates/locale/mesecons_pressureplates.ru.tr new file mode 100644 index 0000000..fcd81f4 --- /dev/null +++ b/mesecons_pressureplates/locale/mesecons_pressureplates.ru.tr @@ -0,0 +1,16 @@ +# textdomain: mesecons_pressureplates +A pressure plate is a redstone component which supplies its surrounding blocks with redstone power while someone or something rests on top of it.=Нажимаемая панель это компонент редстоуна, который начинает снабжать энергией редстоуна окружающие его блоки, когда кто-то или что-то находится прямо на нём. +Oak Pressure Plate=Дубовая нажимная панель +Acacia Pressure Plate=Акациевая нажимная панель +Birch Pressure Plate=Берёзовая нажимная панель +Dark Oak Pressure Plate=Нажимная панель из тёмного дуба +Spruce Pressure Plate=Еловая нажимная панель +Jungle Pressure Plate=Нажимная панель из дерева джунглей +A wooden pressure plate is a redstone component which supplies its surrounding blocks with redstone power while any movable object (including dropped items, players and mobs) rests on top of it.=Деревянная нажимная панель это компонент редстоуна, который начинает снабжать энергией редстоуна окружающие его блоки, когда любой движущийся объект (включая брошенные предметы, игроков и мобов) находится прямо на нём. +Stone Pressure Plate=Каменная нажимная панель +A stone pressure plate is a redstone component which supplies its surrounding blocks with redstone power while a player or mob stands on top of it. It is not triggered by anything else.=Каменная нажимная панель это компонент редстоуна, который начинает снабжать энергией редстоуна окружающие его блоки, когда игрок или моб находится прямо на нём. От чего-то другого он не сработает. +Provides redstone power when pushed=Производит энергию редстоуна при нажимании +Pushable by players, mobs and objects=Нажимается игроками, мобами и объектами +Pushable by players and mobs=Нажимается игроками и мобами +Pushable by players=Нажимается игроками +Pushable by mobs=Нажимается мобами diff --git a/mesecons_pressureplates/locale/template.txt b/mesecons_pressureplates/locale/template.txt new file mode 100644 index 0000000..96eb3f9 --- /dev/null +++ b/mesecons_pressureplates/locale/template.txt @@ -0,0 +1,16 @@ +# textdomain: mesecons_pressureplates +A pressure plate is a redstone component which supplies its surrounding blocks with redstone power while someone or something rests on top of it.= +Oak Pressure Plate= +Acacia Pressure Plate= +Birch Pressure Plate= +Dark Oak Pressure Plate= +Spruce Pressure Plate= +Jungle Pressure Plate= +A wooden pressure plate is a redstone component which supplies its surrounding blocks with redstone power while any movable object (including dropped items, players and mobs) rests on top of it.= +Stone Pressure Plate= +A stone pressure plate is a redstone component which supplies its surrounding blocks with redstone power while a player or mob stands on top of it. It is not triggered by anything else.= +Provides redstone power when pushed= +Pushable by players, mobs and objects= +Pushable by players and mobs= +Pushable by players= +Pushable by mobs= diff --git a/mesecons_pressureplates/mod.conf b/mesecons_pressureplates/mod.conf new file mode 100644 index 0000000..0edd40e --- /dev/null +++ b/mesecons_pressureplates/mod.conf @@ -0,0 +1,3 @@ +name = mesecons_pressureplates +depends = mesecons +optional_depends = doc diff --git a/mesecons_solarpanel/init.lua b/mesecons_solarpanel/init.lua new file mode 100644 index 0000000..ed0e4c6 --- /dev/null +++ b/mesecons_solarpanel/init.lua @@ -0,0 +1,240 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + +local boxes = { -8/16, -8/16, -8/16, 8/16, -2/16, 8/16 } + +-- Daylight Sensor +minetest.register_node("mesecons_solarpanel:solar_panel_on", { + drawtype = "nodebox", + tiles = { "jeija_solar_panel.png","jeija_solar_panel.png","jeija_solar_panel_side.png", + "jeija_solar_panel_side.png","jeija_solar_panel_side.png","jeija_solar_panel_side.png", }, + wield_image = "jeija_solar_panel.png", + wield_scale = { x=1, y=1, z=3 }, + paramtype = "light", + is_ground_content = false, + selection_box = { + type = "fixed", + fixed = boxes + }, + node_box = { + type = "fixed", + fixed = boxes + }, + drop = "mesecons_solarpanel:solar_panel_off", + _doc_items_create_entry = false, + groups = {handy=1,axey=1, not_in_creative_inventory = 1, material_wood=1, flammable=-1}, + sounds = mcl_sounds.node_sound_glass_defaults(), + mesecons = {receptor = { + state = mesecon.state.on, + rules = mesecon.rules.pplate, + }}, + on_rightclick = function(pos, node, clicker, pointed_thing) + 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 = "mesecons_solarpanel:solar_panel_inverted_off"}) + mesecon.receptor_off(pos, mesecon.rules.pplate) + end, + _mcl_blast_resistance = 0.2, + _mcl_hardness = 0.2, +}) + +minetest.register_node("mesecons_solarpanel:solar_panel_off", { + drawtype = "nodebox", + tiles = { "jeija_solar_panel.png","jeija_solar_panel.png","jeija_solar_panel_side.png", + "jeija_solar_panel_side.png","jeija_solar_panel_side.png","jeija_solar_panel_side.png", }, + wield_image = "jeija_solar_panel.png", + wield_scale = { x=1, y=1, z=3 }, + paramtype = "light", + is_ground_content = false, + selection_box = { + type = "fixed", + fixed = boxes + }, + node_box = { + type = "fixed", + fixed = boxes + }, + groups = {handy=1,axey=1, material_wood=1}, + description=S("Daylight Sensor"), + _tt_help = S("Provides redstone power when in sunlight") .. "\n" ..S("Can be inverted"), + _doc_items_longdesc = S("Daylight sensors are redstone components which provide redstone power when they are in sunlight and no power otherwise. They can also be inverted.").."\n".. + S("In inverted state, they provide redstone power when they are not in sunlight and no power otherwise."), + _doc_items_usagehelp = S("Use the daylight sensor to toggle its state."), + sounds = mcl_sounds.node_sound_glass_defaults(), + mesecons = {receptor = { + state = mesecon.state.off, + rules = mesecon.rules.pplate, + }}, + on_rightclick = function(pos, node, clicker, pointed_thing) + 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 = "mesecons_solarpanel:solar_panel_inverted_on"}) + mesecon.receptor_on(pos, mesecon.rules.pplate) + end, + _mcl_blast_resistance = 0.2, + _mcl_hardness = 0.2, +}) + +minetest.register_craft({ + output = "mesecons_solarpanel:solar_panel_off", + recipe = { + {"mcl_core:glass", "mcl_core:glass", "mcl_core:glass"}, + {"mcl_nether:quartz", "mcl_nether:quartz", "mcl_nether:quartz"}, + {"group:wood_slab", "group:wood_slab", "group:wood_slab"}, + } +}) + +minetest.register_abm({ + label = "Daylight turns on solar panels", + nodenames = {"mesecons_solarpanel:solar_panel_off"}, + interval = 1, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + local light = minetest.get_node_light(pos, nil) + + if light >= 12 and minetest.get_timeofday() > 0.2 and minetest.get_timeofday() < 0.8 then + minetest.set_node(pos, {name="mesecons_solarpanel:solar_panel_on", param2=node.param2}) + mesecon.receptor_on(pos, mesecon.rules.pplate) + end + end, +}) + +minetest.register_abm({ + label = "Darkness turns off solar panels", + nodenames = {"mesecons_solarpanel:solar_panel_on"}, + interval = 1, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + local light = minetest.get_node_light(pos, nil) + + if light < 12 then + minetest.set_node(pos, {name="mesecons_solarpanel:solar_panel_off", param2=node.param2}) + mesecon.receptor_off(pos, mesecon.rules.pplate) + end + end, +}) + +--- Inverted Daylight Sensor + +minetest.register_node("mesecons_solarpanel:solar_panel_inverted_on", { + drawtype = "nodebox", + tiles = { "jeija_solar_panel_inverted.png","jeija_solar_panel_inverted.png","jeija_solar_panel_side.png", + "jeija_solar_panel_side.png","jeija_solar_panel_side.png","jeija_solar_panel_side.png", }, + wield_image = "jeija_solar_panel_inverted.png", + wield_scale = { x=1, y=1, z=3 }, + paramtype = "light", + is_ground_content = false, + selection_box = { + type = "fixed", + fixed = boxes + }, + node_box = { + type = "fixed", + fixed = boxes + }, + drop = "mesecons_solarpanel:solar_panel_off", + groups = {handy=1,axey=1, not_in_creative_inventory = 1, material_wood=1}, + _doc_items_create_entry = false, + sounds = mcl_sounds.node_sound_glass_defaults(), + mesecons = {receptor = { + state = mesecon.state.on, + rules = mesecon.rules.pplate, + }}, + on_rightclick = function(pos, node, clicker, pointed_thing) + 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 = "mesecons_solarpanel:solar_panel_off"}) + mesecon.receptor_off(pos, mesecon.rules.pplate) + end, + _mcl_blast_resistance = 0.2, + _mcl_hardness = 0.2, +}) + +minetest.register_node("mesecons_solarpanel:solar_panel_inverted_off", { + drawtype = "nodebox", + tiles = { "jeija_solar_panel_inverted.png","jeija_solar_panel_inverted.png","jeija_solar_panel_side.png", + "jeija_solar_panel_side.png","jeija_solar_panel_side.png","jeija_solar_panel_side.png", }, + wield_image = "jeija_solar_panel_inverted.png", + wield_scale = { x=1, y=1, z=3 }, + paramtype = "light", + is_ground_content = false, + selection_box = { + type = "fixed", + fixed = boxes + }, + node_box = { + type = "fixed", + fixed = boxes + }, + drop = "mesecons_solarpanel:solar_panel_off", + groups = {handy=1,axey=1, not_in_creative_inventory=1, material_wood=1}, + description=S("Inverted Daylight Sensor"), + _doc_items_create_entry = false, + sounds = mcl_sounds.node_sound_glass_defaults(), + mesecons = {receptor = { + state = mesecon.state.off, + rules = mesecon.rules.pplate, + }}, + on_rightclick = function(pos, node, clicker, pointed_thing) + 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 = "mesecons_solarpanel:solar_panel_on"}) + mesecon.receptor_on(pos, mesecon.rules.pplate) + end, + _mcl_blast_resistance = 0.2, + _mcl_hardness = 0.2, +}) + +minetest.register_abm({ + label = "Darkness turns on inverted solar panels", + nodenames = {"mesecons_solarpanel:solar_panel_inverted_off"}, + interval = 1, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + local light = minetest.get_node_light(pos, nil) + + if light < 12 then + minetest.set_node(pos, {name="mesecons_solarpanel:solar_panel_inverted_on", param2=node.param2}) + mesecon.receptor_on(pos, mesecon.rules.pplate) + end + end, +}) + +minetest.register_abm({ + label = "Daylight turns off inverted solar panels", + nodenames = {"mesecons_solarpanel:solar_panel_inverted_on"}, + interval = 1, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + local light = minetest.get_node_light(pos, nil) + + if light >= 12 and minetest.get_timeofday() > 0.8 and minetest.get_timeofday() < 0.2 then + minetest.set_node(pos, {name="mesecons_solarpanel:solar_panel_inverted_off", param2=node.param2}) + mesecon.receptor_off(pos, mesecon.rules.pplate) + end + end, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "mesecons_solarpanel:solar_panel_off", + burntime = 15 +}) + +if minetest.get_modpath("doc") then + doc.add_entry_alias("nodes", "mesecons_solarpanel:solar_panel_off", "nodes", "mesecons_solarpanel:solar_panel_on") + doc.add_entry_alias("nodes", "mesecons_solarpanel:solar_panel_off", "nodes", "mesecons_solarpanel:solar_panel_inverted_off") + doc.add_entry_alias("nodes", "mesecons_solarpanel:solar_panel_off", "nodes", "mesecons_solarpanel:solar_panel_inverted_off") + doc.add_entry_alias("nodes", "mesecons_solarpanel:solar_panel_off", "nodes", "mesecons_solarpanel:solar_panel_inverted_on") +end diff --git a/mesecons_solarpanel/locale/mesecons_solarpanel.de.tr b/mesecons_solarpanel/locale/mesecons_solarpanel.de.tr new file mode 100644 index 0000000..c33fe94 --- /dev/null +++ b/mesecons_solarpanel/locale/mesecons_solarpanel.de.tr @@ -0,0 +1,8 @@ +# textdomain: mesecons_solarpanel +Daylight Sensor=Tageslichtsensor +Daylight sensors are redstone components which provide redstone power when they are in sunlight and no power otherwise. They can also be inverted.=Tageslichtsensoren sind Redstonekomponenten, die Redstoneenergie liefern, wenn sie im Sonnenlicht stehen, sonst nicht. Sie können auch invertiert werden. +Inverted Daylight Sensor=Invertierter Tageslichtsensor +Use the daylight sensor to toggle its state.=Benutzen Sie den Tageslichtsensor, um seinen Zustand umzuschalten. +In inverted state, they provide redstone power when they are not in sunlight and no power otherwise.=Im invertierten Zustand erzeugen sie Redstoneenergie, wenn sie sich nicht im Tageslicht befinden, ansonsten nicht. +Provides redstone power when in sunlight=Gibt Redstoneenergie aus, wenn im Sonnenlicht +Can be inverted=Kann invertiert werden diff --git a/mesecons_solarpanel/locale/mesecons_solarpanel.es.tr b/mesecons_solarpanel/locale/mesecons_solarpanel.es.tr new file mode 100644 index 0000000..986a16d --- /dev/null +++ b/mesecons_solarpanel/locale/mesecons_solarpanel.es.tr @@ -0,0 +1,6 @@ +# textdomain: mesecons_solarpanel +Daylight Sensor=Sensor de luz solar +Daylight sensors are redstone components which provide redstone power when they are in sunlight and no power otherwise. They can also be inverted.=Los sensores de luz diurna son componentes de redstone que proporcionan energía de redstone cuando están bajo la luz solar y no tienen energía de otra manera. También se pueden invertir. +Inverted Daylight Sensor=Sensor de luz solar invertido +Use the daylight sensor to toggle its state.=Use el sensor de luz diurna para alternar su estado. +In inverted state, they provide redstone power when they are not in sunlight and no power otherwise.=En estado invertido, proporcionan energía de redstone cuando no están bajo la luz solar y no tienen energía de otra manera. diff --git a/mesecons_solarpanel/locale/mesecons_solarpanel.fr.tr b/mesecons_solarpanel/locale/mesecons_solarpanel.fr.tr new file mode 100644 index 0000000..a0b7ad7 --- /dev/null +++ b/mesecons_solarpanel/locale/mesecons_solarpanel.fr.tr @@ -0,0 +1,8 @@ +# textdomain: mesecons_solarpanel +Daylight Sensor=Capteur de luminosité +Daylight sensors are redstone components which provide redstone power when they are in sunlight and no power otherwise. They can also be inverted.=Les capteurs de luminosité sont des composants de redstone qui fournissent une puissance de redstone lorsqu'ils sont en plein soleil et aucune autrement. Ils peuvent également être inversés. +Use the daylight sensor to toggle its state.=Utilisez le capteur de luminosité pour basculer son état. +Inverted Daylight Sensor=Capteur de luminosité inversé +In inverted state, they provide redstone power when they are not in sunlight and no power otherwise.=En état inversé, ils fournissent une puissance de redstone lorsqu'ils ne sont pas en plein soleil et aucune puissance autrement. +Provides redstone power when in sunlight=Fournit une puissance de redstone en plein soleil +Can be inverted=Peut être inversé diff --git a/mesecons_solarpanel/locale/mesecons_solarpanel.pl.tr b/mesecons_solarpanel/locale/mesecons_solarpanel.pl.tr new file mode 100644 index 0000000..d7e3e19 --- /dev/null +++ b/mesecons_solarpanel/locale/mesecons_solarpanel.pl.tr @@ -0,0 +1,8 @@ +# textdomain: mesecons_solarpanel +Daylight Sensor=Czujnik światła dziennego +Daylight sensors are redstone components which provide redstone power when they are in sunlight and no power otherwise. They can also be inverted.=Czujniki światła dziennego są czerwienitowymi elementami, które wysyłają energie czerwienitową gdy są w świetle słonecznym i nie dostarczają energii w przeciwnym przypadku. +Use the daylight sensor to toggle its state.=Użyj czujnik światła dziennego by zmienić jego stan. +Inverted Daylight Sensor=Odwrotny czujnik światła dziennego +In inverted state, they provide redstone power when they are not in sunlight and no power otherwise.=W odwrotnym stanie, dostarczają energię czerwienitową gdy nie są w świetle słonecznym i nie dostarczają energii w przeciwnym przypadku. +Provides redstone power when in sunlight=Dostarcza energię czerwienitową gdy w oświetlony słońcem +Can be inverted=Może być odwrócony diff --git a/mesecons_solarpanel/locale/mesecons_solarpanel.ru.tr b/mesecons_solarpanel/locale/mesecons_solarpanel.ru.tr new file mode 100644 index 0000000..108cb9f --- /dev/null +++ b/mesecons_solarpanel/locale/mesecons_solarpanel.ru.tr @@ -0,0 +1,8 @@ +# textdomain: mesecons_solarpanel +Daylight Sensor=Датчик дневного света +Daylight sensors are redstone components which provide redstone power when they are in sunlight and no power otherwise. They can also be inverted.=Датчик дневного света это компонент редстоуна, который производит энергию редстоуна при нахождении в солнечном свете и не производит в противном случае. Он также может быть инвертирован. +Use the daylight sensor to toggle its state.=[Используйте] датчик дневного света для смены его состояния +Inverted Daylight Sensor=Инвертированный датчик дневного света +In inverted state, they provide redstone power when they are not in sunlight and no power otherwise.=В инвертированном состоянии он производит энергию редстоуна, когда на него не попадает солнечны свет, а когда попадает - перестаёт производить. +Provides redstone power when in sunlight=Генерирует энергию редстоуна в солнечном свете +Can be inverted=Может быть инвертирован diff --git a/mesecons_solarpanel/locale/template.txt b/mesecons_solarpanel/locale/template.txt new file mode 100644 index 0000000..84c3ce4 --- /dev/null +++ b/mesecons_solarpanel/locale/template.txt @@ -0,0 +1,8 @@ +# textdomain: mesecons_solarpanel +Daylight Sensor= +Daylight sensors are redstone components which provide redstone power when they are in sunlight and no power otherwise. They can also be inverted.= +Use the daylight sensor to toggle its state.= +Inverted Daylight Sensor= +In inverted state, they provide redstone power when they are not in sunlight and no power otherwise.= +Provides redstone power when in sunlight= +Can be inverted= diff --git a/mesecons_solarpanel/mod.conf b/mesecons_solarpanel/mod.conf new file mode 100644 index 0000000..9897b74 --- /dev/null +++ b/mesecons_solarpanel/mod.conf @@ -0,0 +1,3 @@ +name = mesecons_solarpanel +depends = mesecons +optional_depends = doc diff --git a/mesecons_solarpanel/textures/jeija_solar_panel.png b/mesecons_solarpanel/textures/jeija_solar_panel.png new file mode 100644 index 0000000..c94d506 Binary files /dev/null and b/mesecons_solarpanel/textures/jeija_solar_panel.png differ diff --git a/mesecons_solarpanel/textures/jeija_solar_panel_inverted.png b/mesecons_solarpanel/textures/jeija_solar_panel_inverted.png new file mode 100644 index 0000000..15784f5 Binary files /dev/null and b/mesecons_solarpanel/textures/jeija_solar_panel_inverted.png differ diff --git a/mesecons_solarpanel/textures/jeija_solar_panel_side.png b/mesecons_solarpanel/textures/jeija_solar_panel_side.png new file mode 100644 index 0000000..ca6c3d6 Binary files /dev/null and b/mesecons_solarpanel/textures/jeija_solar_panel_side.png differ diff --git a/mesecons_torch/init.lua b/mesecons_torch/init.lua new file mode 100644 index 0000000..e49b843 --- /dev/null +++ b/mesecons_torch/init.lua @@ -0,0 +1,241 @@ +-- REDSTONE TORCH AND BLOCK OF REDSTONE + +local S = minetest.get_translator(minetest.get_current_modname()) + +local TORCH_COOLOFF = 120 -- Number of seconds it takes for a burned-out torch to reactivate + +local function rotate_torch_rules(rules, param2) + if param2 == 1 then + return rules + elseif param2 == 5 then + return mesecon.rotate_rules_right(rules) + elseif param2 == 2 then + return mesecon.rotate_rules_right(mesecon.rotate_rules_right(rules)) --180 degrees + elseif param2 == 4 then + return mesecon.rotate_rules_left(rules) + elseif param2 == 0 then + return rules + else + return rules + end +end + +local function torch_get_output_rules(node) + if node.param2 == 1 then + return { + { x = -1, y = 0, z = 0 }, + { x = 1, y = 0, z = 0 }, + { x = 0, y = 1, z = 0, spread = true }, + { x = 0, y = 0, z = -1 }, + { x = 0, y = 0, z = 1 }, + } + else + return rotate_torch_rules({ + { x = 1, y = 0, z = 0 }, + { x = 0, y = -1, z = 0 }, + { x = 0, y = 1, z = 0, spread = true }, + { x = 0, y = 1, z = 0 }, + { x = 0, y = 0, z = -1 }, + { x = 0, y = 0, z = 1 }, + }, node.param2) + end +end + +local function torch_get_input_rules(node) + if node.param2 == 1 then + return {{x = 0, y = -1, z = 0 }} + else + return rotate_torch_rules({{ x = -1, y = 0, z = 0 }}, node.param2) + end +end + +local function torch_overheated(pos) + minetest.sound_play("fire_extinguish_flame", {pos = pos, gain = 0.02, max_hear_distance = 6}, true) + minetest.add_particle({ + pos = {x=pos.x, y=pos.y+0.2, z=pos.z}, + velocity = {x = 0, y = 0.6, z = 0}, + expirationtime = 1.2, + size = 1.5, + texture = "mcl_particles_smoke.png", + }) + local timer = minetest.get_node_timer(pos) + timer:start(TORCH_COOLOFF) +end + +local function torch_action_on(pos, node) + local overheat + if node.name == "mesecons_torch:mesecon_torch_on" then + overheat = mesecon.do_overheat(pos) + if overheat then + minetest.swap_node(pos, {name="mesecons_torch:mesecon_torch_overheated", param2=node.param2}) + else + minetest.swap_node(pos, {name="mesecons_torch:mesecon_torch_off", param2=node.param2}) + end + mesecon.receptor_off(pos, torch_get_output_rules(node)) + elseif node.name == "mesecons_torch:mesecon_torch_on_wall" then + overheat = mesecon.do_overheat(pos) + if overheat then + minetest.swap_node(pos, {name="mesecons_torch:mesecon_torch_overheated_wall", param2=node.param2}) + else + minetest.swap_node(pos, {name="mesecons_torch:mesecon_torch_off_wall", param2=node.param2}) + end + mesecon.receptor_off(pos, torch_get_output_rules(node)) + end + if overheat then + torch_overheated(pos) + end +end + +local function torch_action_off(pos, node) + local overheat + if node.name == "mesecons_torch:mesecon_torch_off" or node.name == "mesecons_torch:mesecon_torch_overheated" then + overheat = mesecon.do_overheat(pos) + if overheat then + minetest.swap_node(pos, {name="mesecons_torch:mesecon_torch_overheated", param2=node.param2}) + else + minetest.swap_node(pos, {name="mesecons_torch:mesecon_torch_on", param2=node.param2}) + mesecon.receptor_on(pos, torch_get_output_rules(node)) + end + elseif node.name == "mesecons_torch:mesecon_torch_off_wall" or node.name == "mesecons_torch:mesecon_torch_overheated_wall" then + overheat = mesecon.do_overheat(pos) + if overheat then + minetest.swap_node(pos, {name="mesecons_torch:mesecon_torch_overheated_wall", param2=node.param2}) + else + minetest.swap_node(pos, {name="mesecons_torch:mesecon_torch_on_wall", param2=node.param2}) + mesecon.receptor_on(pos, torch_get_output_rules(node)) + end + end + if overheat then + torch_overheated(pos) + end +end + +minetest.register_craft({ + output = "mesecons_torch:mesecon_torch_on", + recipe = { + {"mesecons:redstone"}, + {"mcl_core:stick"},} +}) + +local off_def = { + name = "mesecon_torch_off", + description = S("Redstone Torch (off)"), + doc_items_create_entry = false, + icon = "jeija_torches_off.png", + tiles = {"jeija_torches_off.png"}, + light = 0, + groups = {dig_immediate=3, dig_by_water=1, redstone_torch=2, mesecon_ignore_opaque_dig=1, not_in_creative_inventory=1}, + sounds = mcl_sounds.node_sound_wood_defaults(), + drop = "mesecons_torch:mesecon_torch_on", +} + +mcl_torches.register_torch(off_def) + +local off_override = { + mesecons = { + receptor = { + state = mesecon.state.off, + rules = torch_get_output_rules, + }, + effector = { + state = mesecon.state.on, + rules = torch_get_input_rules, + action_off = torch_action_off, + }, + } +} + +minetest.override_item("mesecons_torch:mesecon_torch_off", off_override) +minetest.override_item("mesecons_torch:mesecon_torch_off_wall", off_override) + +local overheated_def = table.copy(off_def) +overheated_def.name = "mesecon_torch_overheated" +overheated_def.description = S("Redstone Torch (overheated)") + +mcl_torches.register_torch(overheated_def) + +local overheated_override = { + on_timer = function(pos, elapsed) + if not mesecon.is_powered(pos) then + local node = minetest.get_node(pos) + torch_action_off(pos, node) + end + end +} + +minetest.override_item("mesecons_torch:mesecon_torch_overheated", overheated_override) +minetest.override_item("mesecons_torch:mesecon_torch_overheated_wall", overheated_override) + +local on_def = { + name = "mesecon_torch_on", + description = S("Redstone Torch"), + doc_items_longdesc = S("A redstone torch is a redstone component which can be used to invert a redstone signal. It supplies its surrounding blocks with redstone power, except for the block it is attached to. A redstone torch is normally lit, but it can also be turned off by powering the block it is attached to. While unlit, a redstone torch does not power anything."), + doc_items_usagehelp = S("Redstone torches can be placed at the side and on the top of full solid opaque blocks."), + icon = "jeija_torches_on.png", + tiles = {"jeija_torches_on.png"}, + light = 7, + groups = {dig_immediate=3, dig_by_water=1, redstone_torch=1, mesecon_ignore_opaque_dig=1}, + sounds = mcl_sounds.node_sound_wood_defaults(), +} + +mcl_torches.register_torch(on_def) + +local on_override = { + on_destruct = function(pos, oldnode) + local node = minetest.get_node(pos) + torch_action_on(pos, node) + end, + mesecons = { + receptor = { + state = mesecon.state.on, + rules = torch_get_output_rules + }, + effector = { + state = mesecon.state.off, + rules = torch_get_input_rules, + action_on = torch_action_on, + }, + }, + _tt_help = S("Provides redstone power when it's not powered itself"), +} + +minetest.override_item("mesecons_torch:mesecon_torch_on", on_override) +minetest.override_item("mesecons_torch:mesecon_torch_on_wall", on_override) + +minetest.register_node("mesecons_torch:redstoneblock", { + description = S("Block of Redstone"), + _tt_help = S("Provides redstone power"), + _doc_items_longdesc = S("A block of redstone permanently supplies redstone power to its surrounding blocks."), + tiles = {"redstone_redstone_block.png"}, + stack_max = 64, + groups = {pickaxey=1}, + sounds = mcl_sounds.node_sound_stone_defaults(), + is_ground_content = false, + mesecons = {receptor = { + state = mesecon.state.on, + rules = mesecon.rules.alldirs, + }}, + _mcl_blast_resistance = 6, + _mcl_hardness = 5, +}) + +minetest.register_craft({ + output = "mesecons_torch:redstoneblock", + recipe = { + {"mesecons:wire_00000000_off","mesecons:wire_00000000_off","mesecons:wire_00000000_off"}, + {"mesecons:wire_00000000_off","mesecons:wire_00000000_off","mesecons:wire_00000000_off"}, + {"mesecons:wire_00000000_off","mesecons:wire_00000000_off","mesecons:wire_00000000_off"}, + } +}) + +minetest.register_craft({ + output = "mesecons:wire_00000000_off 9", + recipe = { + {"mesecons_torch:redstoneblock"}, + } +}) + +if minetest.get_modpath("doc") then + doc.add_entry_alias("nodes", "mesecons_torch:mesecon_torch_on", "nodes", "mesecons_torch:mesecon_torch_off") + doc.add_entry_alias("nodes", "mesecons_torch:mesecon_torch_on", "nodes", "mesecons_torch:mesecon_torch_off_wall") +end diff --git a/mesecons_torch/locale/mesecons_torch.de.tr b/mesecons_torch/locale/mesecons_torch.de.tr new file mode 100644 index 0000000..7f3f94c --- /dev/null +++ b/mesecons_torch/locale/mesecons_torch.de.tr @@ -0,0 +1,10 @@ +# textdomain: mesecons_torch +Redstone Torch=Redstonefackel +Redstone Torch (off)=Redstonefackel (aus) +Redstone Torch (overheated)=Redstonefackel (überhitzt) +A redstone torch is a redstone component which can be used to invert a redstone signal. It supplies its surrounding blocks with redstone power, except for the block it is attached to. A redstone torch is normally lit, but it can also be turned off by powering the block it is attached to. While unlit, a redstone torch does not power anything.=Eine Redstonefackel ist eine Redstonekomponente, die benutzt werden kann, um ein Redstonesignal zu invertieren. Sie versorgt die benachbarten Blöcke mit Redstoneenergie, ausgenommen den Block, an dem sie befestigt wurde. Eine Redstonefackel leuchtet normalerweise, aber sie kann auch ausgeschaltet werden, indem der Block, an dem sie befestigt ist, bestromt wird. Wenn sie aus ist, wird sie nichts mit Redstoneenergie versorgen. +Redstone torches can be placed at the side and on the top of full solid opaque blocks.=Redstonefackeln können an der Seite und auf der Oberseite der meisten undurchsichtigen ganzen Blöcke platziert werden. +Block of Redstone=Redstoneblock +A block of redstone permanently supplies redstone power to its surrounding blocks.=Ein Redstoneblock versorgt seine benachbarten Blöcke beständig mit Redstoneenergie. +Provides redstone power when it's not powered itself=Gibt Redstoneenergie aus, wenn es nicht selbst bestromt ist +Provides redstone power=Gibt Redstoneenergie aus diff --git a/mesecons_torch/locale/mesecons_torch.es.tr b/mesecons_torch/locale/mesecons_torch.es.tr new file mode 100644 index 0000000..b27fa1b --- /dev/null +++ b/mesecons_torch/locale/mesecons_torch.es.tr @@ -0,0 +1,8 @@ +# textdomain: mesecons_torch +Redstone Torch=Antorcha de redstone +Redstone Torch (off)=Antorcha de redstone (Apagada) +Redstone Torch (overheated)=Antorcha de redstone (Sobrecalentada) +A redstone torch is a redstone component which can be used to invert a redstone signal. It supplies its surrounding blocks with redstone power, except for the block it is attached to. A redstone torch is normally lit, but it can also be turned off by powering the block it is attached to. While unlit, a redstone torch does not power anything.=Una antorcha de redstone es un componente de redstone que se puede utilizar para invertir una señal de redstone. Suministra a sus bloques circundantes energía de redstone, excepto el bloque al que está unido. Una antorcha de redstone normalmente está encendida, pero también se puede apagar alimentando el bloque al que está conectado. Mientras está apagada, una antorcha de redstone no alimenta nada. +Redstone torches can be placed at the side and on the top of full solid opaque blocks.=Las antorchas Redstone se pueden colocar a un lado y en la parte superior de bloques opacos sólidos completos. +Block of Redstone=Bloque de redstone +A block of redstone permanently supplies redstone power to its surrounding blocks.=Un bloque de redstone suministra permanentemente energía de redstone a sus bloques circundantes. diff --git a/mesecons_torch/locale/mesecons_torch.fr.tr b/mesecons_torch/locale/mesecons_torch.fr.tr new file mode 100644 index 0000000..8c223d8 --- /dev/null +++ b/mesecons_torch/locale/mesecons_torch.fr.tr @@ -0,0 +1,10 @@ +# textdomain: mesecons_torch +Redstone Torch=Torche de Redstone +Redstone Torch (off)=Torche de Redstone (inactive) +Redstone Torch (overheated)=Torche de Redstone (surchauffé) +A redstone torch is a redstone component which can be used to invert a redstone signal. It supplies its surrounding blocks with redstone power, except for the block it is attached to. A redstone torch is normally lit, but it can also be turned off by powering the block it is attached to. While unlit, a redstone torch does not power anything.=Une torche redstone est un composant redstone qui peut être utilisé pour inverser un signal redstone. Il alimente ses blocs environnants en énergie redstone, à l'exception du bloc auquel il est attaché. Une torche Redstone est normalement allumée, mais elle peut également être éteinte en alimentant le bloc auquel elle est attachée. Tant qu'elle n'est pas allumée, une torche redstone n'alimente rien. +Redstone torches can be placed at the side and on the top of full solid opaque blocks.=Les torches Redstone peuvent être placées sur le côté et sur le dessus de blocs opaques solides. +Block of Redstone=Bloc de Redstone +A block of redstone permanently supplies redstone power to its surrounding blocks.=Un bloc de redstone fournit en permanence de l'énergie redstone à ses blocs environnants. +Provides redstone power when it's not powered itself=Fournit une puissance redstone lorsqu'il n'est pas alimenté lui-même +Provides redstone power=Fournit une puissance redstone diff --git a/mesecons_torch/locale/mesecons_torch.pl.tr b/mesecons_torch/locale/mesecons_torch.pl.tr new file mode 100644 index 0000000..a791da3 --- /dev/null +++ b/mesecons_torch/locale/mesecons_torch.pl.tr @@ -0,0 +1,10 @@ +# textdomain: mesecons_torch +Redstone Torch=Pochodnia czerwienitowa +Redstone Torch (off)=Pochodnia czerwienitowa (wyłączona) +Redstone Torch (overheated)=Pochodnia czerwienitowa (przegrzana) +A redstone torch is a redstone component which can be used to invert a redstone signal. It supplies its surrounding blocks with redstone power, except for the block it is attached to. A redstone torch is normally lit, but it can also be turned off by powering the block it is attached to. While unlit, a redstone torch does not power anything.=Pochodnia czerwienitowa to mechanizm czerwienitowy, który można wykorzystać do odwrócenia czerwienitowego sygnału. Dostarcza otaczającym jej blokom energię czerwienitową, z wyjątkiem bloku do którego jest przyczepiona. Pochodnia czerwienitowa normalnie jest zapalona, jednak może zostać wyłączona przez zasilenie bloku do którego jest przyczepiona. Gdy jest wyłączona nie zasila ona niczego. +Redstone torches can be placed at the side and on the top of full solid opaque blocks.=Pochodnia czerwienitowa może być postawiona na boku i wierzchu pełnych, stałych, nieprzezroczystych bloków. +Block of Redstone=Blok czerwienitu +A block of redstone permanently supplies redstone power to its surrounding blocks.=Blok czerwienitu nieustannie dostarcza energię czerwienitową do otaczających go bloków. +Provides redstone power when it's not powered itself=Dostarcza energię czerwienitową gdy nie jest zasilona +Provides redstone power=Dostarcza energię czerwienitową diff --git a/mesecons_torch/locale/mesecons_torch.ru.tr b/mesecons_torch/locale/mesecons_torch.ru.tr new file mode 100644 index 0000000..45d0d76 --- /dev/null +++ b/mesecons_torch/locale/mesecons_torch.ru.tr @@ -0,0 +1,10 @@ +# textdomain: mesecons_torch +Redstone Torch=Факел редстоуна +Redstone Torch (off)=Факел редстоуна (выкл) +Redstone Torch (overheated)=Факел редстоуна (перегрелся) +A redstone torch is a redstone component which can be used to invert a redstone signal. It supplies its surrounding blocks with redstone power, except for the block it is attached to. A redstone torch is normally lit, but it can also be turned off by powering the block it is attached to. While unlit, a redstone torch does not power anything.=Факел редстоуна это компонент, способный инвертировать сигнал редстоуна. Он обеспечивает энергией редстоуна окружающие блоки, за исключением того блока, к которому он присоединён. Факел редстоуна обычно горит, но он также может быть выключен путём подведения энергии редстоуна к тому блоку, к которому он присоединён. Когда он не горит, то не снабжает энергией окружающие блоки. +Redstone torches can be placed at the side and on the top of full solid opaque blocks.=Факелы редстоуна могут быть установлены по краям и на верхней части любого целого плотного твёрдого блока. +Block of Redstone=Блок редстоуна +A block of redstone permanently supplies redstone power to its surrounding blocks.=Блок редстоуна напрямую снабжает энергией окружающие блоки +Provides redstone power when it's not powered itself=Снабжает энергией редстоуна, если не подключён сам +Provides redstone power=Снабжает энергией редстоуна diff --git a/mesecons_torch/locale/template.txt b/mesecons_torch/locale/template.txt new file mode 100644 index 0000000..8cde3ad --- /dev/null +++ b/mesecons_torch/locale/template.txt @@ -0,0 +1,10 @@ +# textdomain: mesecons_torch +Redstone Torch= +Redstone Torch (off)= +Redstone Torch (overheated)= +A redstone torch is a redstone component which can be used to invert a redstone signal. It supplies its surrounding blocks with redstone power, except for the block it is attached to. A redstone torch is normally lit, but it can also be turned off by powering the block it is attached to. While unlit, a redstone torch does not power anything.= +Redstone torches can be placed at the side and on the top of full solid opaque blocks.= +Block of Redstone= +A block of redstone permanently supplies redstone power to its surrounding blocks.= +Provides redstone power when it's not powered itself= +Provides redstone power= diff --git a/mesecons_torch/mod.conf b/mesecons_torch/mod.conf new file mode 100644 index 0000000..85586ca --- /dev/null +++ b/mesecons_torch/mod.conf @@ -0,0 +1,3 @@ +name = mesecons_torch +depends = mesecons, mcl_torches +optional_depends = doc diff --git a/mesecons_torch/textures/jeija_torches_off.png b/mesecons_torch/textures/jeija_torches_off.png new file mode 100644 index 0000000..cecdaf8 Binary files /dev/null and b/mesecons_torch/textures/jeija_torches_off.png differ diff --git a/mesecons_torch/textures/jeija_torches_on.png b/mesecons_torch/textures/jeija_torches_on.png new file mode 100644 index 0000000..24d0a94 Binary files /dev/null and b/mesecons_torch/textures/jeija_torches_on.png differ diff --git a/mesecons_torch/textures/redstone_redstone_block.png b/mesecons_torch/textures/redstone_redstone_block.png new file mode 100644 index 0000000..465de2b Binary files /dev/null and b/mesecons_torch/textures/redstone_redstone_block.png differ diff --git a/mesecons_walllever/README.txt b/mesecons_walllever/README.txt new file mode 100644 index 0000000..8744b56 --- /dev/null +++ b/mesecons_walllever/README.txt @@ -0,0 +1,11 @@ +This mod adds levers. + +# Credits +## Mesh +Lever meshes created by Gerold55. + +## Code +Jeija and Wuzzy. + +## Textures +(See main README file of MineClone 2). diff --git a/mesecons_walllever/init.lua b/mesecons_walllever/init.lua new file mode 100644 index 0000000..c251587 --- /dev/null +++ b/mesecons_walllever/init.lua @@ -0,0 +1,178 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + +local lever_get_output_rules = mesecon.rules.buttonlike_get + +local function on_rotate(pos, node, user, mode) + if mode == screwdriver.ROTATE_FACE then + if node.param2 == 10 then + node.param2 = 13 + minetest.swap_node(pos, node) + return true + elseif node.param2 == 13 then + node.param2 = 10 + minetest.swap_node(pos, node) + return true + elseif node.param2 == 8 then + node.param2 = 15 + minetest.swap_node(pos, node) + return true + elseif node.param2 == 15 then + node.param2 = 8 + minetest.swap_node(pos, node) + return true + end + end + -- TODO: Rotate axis + return false +end + +-- LEVER +minetest.register_node("mesecons_walllever:wall_lever_off", { + drawtype = "mesh", + tiles = { + "jeija_wall_lever_lever_light_on.png", + }, + use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false, + inventory_image = "jeija_wall_lever.png", + wield_image = "jeija_wall_lever.png", + paramtype = "light", + paramtype2 = "facedir", + mesh = "jeija_wall_lever_off.obj", + sunlight_propagates = true, + walkable = false, + selection_box = { + type = "fixed", + fixed = { -3/16, -4/16, 2/16, 3/16, 4/16, 8/16 }, + }, + groups = {handy=1, dig_by_water=1, destroy_by_lava_flow=1, dig_by_piston=1, attached_node_facedir=1}, + is_ground_content = false, + description=S("Lever"), + _tt_help = S("Provides redstone power while it's turned on"), + _doc_items_longdesc = S("A lever is a redstone component which can be flipped on and off. It supplies redstone power to adjacent blocks while it is in the “on” state."), + _doc_items_usagehelp = S("Use the lever to flip it on or off."), + on_rightclick = function(pos, node) + minetest.swap_node(pos, {name="mesecons_walllever:wall_lever_on", param2=node.param2}) + mesecon.receptor_on(pos, lever_get_output_rules(node)) + minetest.sound_play("mesecons_button_push", {pos=pos, max_hear_distance=16}, true) + end, + node_placement_prediction = "", + on_place = function(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 dir = vector.subtract(under, above) + local tau = math.pi*2 + local wdir = minetest.dir_to_facedir(dir, true) + if dir.y ~= 0 then + local yaw = placer:get_look_horizontal() + if (yaw > tau/8 and yaw < (tau/8)*3) or (yaw < (tau/8)*7 and yaw > (tau/8)*5) then + if dir.y == -1 then + wdir = 13 + else + wdir = 15 + end + else + if dir.y == -1 then + wdir = 10 + else + wdir = 8 + end + end + end + + local idef = itemstack:get_definition() + local itemstack, success = minetest.item_place_node(itemstack, placer, pointed_thing, wdir) + + 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, + + sounds = mcl_sounds.node_sound_stone_defaults(), + mesecons = {receptor = { + rules = lever_get_output_rules, + state = mesecon.state.off + }}, + on_rotate = on_rotate, + _mcl_blast_resistance = 0.5, + _mcl_hardness = 0.5, +}) +minetest.register_node("mesecons_walllever:wall_lever_on", { + drawtype = "mesh", + tiles = { + "jeija_wall_lever_lever_light_on.png", + }, + use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false, + paramtype = "light", + paramtype2 = "facedir", + mesh = "jeija_wall_lever_on.obj", + sunlight_propagates = true, + walkable = false, + selection_box = { + type = "fixed", + fixed = { -3/16, -4/16, 2/16, 3/16, 4/16, 8/16 }, + }, + groups = {handy=1, not_in_creative_inventory = 1, dig_by_water=1, destroy_by_lava_flow=1, dig_by_piston=1, attached_node_facedir=1}, + is_ground_content = false, + drop = "mesecons_walllever:wall_lever_off", + _doc_items_create_entry = false, + on_rightclick = function(pos, node) + minetest.swap_node(pos, {name="mesecons_walllever:wall_lever_off", param2=node.param2}) + mesecon.receptor_off(pos, lever_get_output_rules(node)) + minetest.sound_play("mesecons_button_push", {pos=pos, max_hear_distance=16, pitch=0.9}, true) + end, + sounds = mcl_sounds.node_sound_stone_defaults(), + mesecons = {receptor = { + rules = lever_get_output_rules, + state = mesecon.state.on + }}, + on_rotate = on_rotate, + _mcl_blast_resistance = 0.5, + _mcl_hardness = 0.5, +}) + +minetest.register_craft({ + output = "mesecons_walllever:wall_lever_off", + recipe = { + {"mcl_core:stick"}, + {"mcl_core:cobble"}, + } +}) + +if minetest.get_modpath("doc") then + doc.add_entry_alias("nodes", "mesecons_walllever:wall_lever_off", "nodes", "mesecons_walllever:wall_lever_on") +end diff --git a/mesecons_walllever/locale/mesecons_walllever.de.tr b/mesecons_walllever/locale/mesecons_walllever.de.tr new file mode 100644 index 0000000..27a3bb5 --- /dev/null +++ b/mesecons_walllever/locale/mesecons_walllever.de.tr @@ -0,0 +1,5 @@ +# textdomain: mesecons_wallever +Lever=Hebel +A lever is a redstone component which can be flipped on and off. It supplies redstone power to adjacent blocks while it is in the “on” state.=Ein Hebel ist eine Redstonekomponente, die ein- und ausgeschaltet werden kann. Er versorgt seine benachbarten Blöcke mit Redstoneenergie, solange er sich im eingeschalteten Zustand befindet. +Use the lever to flip it on or off.=Benutzen Sie den Hebel, um ihn ein- oder auszuschalten. +Provides redstone power while it's turned on=Gibt Redstoneenergie aus, während er eingeschaltet ist diff --git a/mesecons_walllever/locale/mesecons_walllever.es.tr b/mesecons_walllever/locale/mesecons_walllever.es.tr new file mode 100644 index 0000000..e0e5529 --- /dev/null +++ b/mesecons_walllever/locale/mesecons_walllever.es.tr @@ -0,0 +1,4 @@ +# textdomain: mesecons_wallever +Lever=Palanca +A lever is a redstone component which can be flipped on and off. It supplies redstone power to adjacent blocks while it is in the “on” state.=EUna palanca es un componente de redstone que se puede activar y desactivar. Suministra energía redstone a bloques adyacentes mientras está en el estado "encendido". +Use the lever to flip it on or off.=Use la palanca para encenderlo o apagarlo. diff --git a/mesecons_walllever/locale/mesecons_walllever.fr.tr b/mesecons_walllever/locale/mesecons_walllever.fr.tr new file mode 100644 index 0000000..3d5d23c --- /dev/null +++ b/mesecons_walllever/locale/mesecons_walllever.fr.tr @@ -0,0 +1,5 @@ +# textdomain: mesecons_wallever +Lever=Levier +A lever is a redstone component which can be flipped on and off. It supplies redstone power to adjacent blocks while it is in the “on” state.=Un levier est un composant de redstone qui peut être activé et désactivé. Il fournit de l'énergie redstone aux blocs adjacents pendant qu'il est à l'état "activé". +Use the lever to flip it on or off.=Utilisez le levier pour l'activer ou le désactiver. +Provides redstone power while it's turned on=Fournit une puissance de redstone lorsqu'il est activé diff --git a/mesecons_walllever/locale/mesecons_walllever.pl.tr b/mesecons_walllever/locale/mesecons_walllever.pl.tr new file mode 100644 index 0000000..924fe3d --- /dev/null +++ b/mesecons_walllever/locale/mesecons_walllever.pl.tr @@ -0,0 +1,5 @@ +# textdomain: mesecons_wallever +Lever=Dźwignia +A lever is a redstone component which can be flipped on and off. It supplies redstone power to adjacent blocks while it is in the “on” state.=Dźwignia jest czerwienitowym elementem, który można przełączać między stanem włączonym i wyłączonym. Wysyła ona czerwienitową energię gdy jest w stanie włączonym. +Use the lever to flip it on or off.=Użyj dźwigni by przełączyć ją między stanami. +Provides redstone power while it's turned on=Dostarcza energii czerwienitowej gdy jest włączona diff --git a/mesecons_walllever/locale/mesecons_walllever.ru.tr b/mesecons_walllever/locale/mesecons_walllever.ru.tr new file mode 100644 index 0000000..6ed05b3 --- /dev/null +++ b/mesecons_walllever/locale/mesecons_walllever.ru.tr @@ -0,0 +1,5 @@ +# textdomain: mesecons_wallever +Lever=Рычаг +A lever is a redstone component which can be flipped on and off. It supplies redstone power to adjacent blocks while it is in the “on” state.=Рычаг это компонент редстоуна, который можно включать и выключать. Он подаёт энергию редстоуна на соседние блоки, пока он находится во «включённом» состоянии. +Use the lever to flip it on or off.=[Используйте] рычаг, чтобы перещёлкнуть его во включённое или выключенное положение . +Provides redstone power while it's turned on=Снабжает энергией редстоуна, когда включён diff --git a/mesecons_walllever/locale/template.txt b/mesecons_walllever/locale/template.txt new file mode 100644 index 0000000..0187e6d --- /dev/null +++ b/mesecons_walllever/locale/template.txt @@ -0,0 +1,5 @@ +# textdomain: mesecons_wallever +Lever= +A lever is a redstone component which can be flipped on and off. It supplies redstone power to adjacent blocks while it is in the “on” state.= +Use the lever to flip it on or off.= +Provides redstone power while it's turned on= diff --git a/mesecons_walllever/mod.conf b/mesecons_walllever/mod.conf new file mode 100644 index 0000000..8512e9d --- /dev/null +++ b/mesecons_walllever/mod.conf @@ -0,0 +1,3 @@ +name = mesecons_walllever +depends = mesecons +optional_depends = doc diff --git a/mesecons_walllever/models/jeija_wall_lever_lever_light_on.png b/mesecons_walllever/models/jeija_wall_lever_lever_light_on.png new file mode 100644 index 0000000..9f8af94 Binary files /dev/null and b/mesecons_walllever/models/jeija_wall_lever_lever_light_on.png differ diff --git a/mesecons_walllever/models/jeija_wall_lever_off.obj b/mesecons_walllever/models/jeija_wall_lever_off.obj new file mode 100644 index 0000000..c5044de --- /dev/null +++ b/mesecons_walllever/models/jeija_wall_lever_off.obj @@ -0,0 +1,88 @@ +# Blender v2.79 (sub 0) OBJ File: '' +# www.blender.org +mtllib jeija_wall_lever_off.mtl +o nodebox1.009 +v -0.070437 0.138562 0.459573 +v -0.070383 0.058650 0.407149 +v -0.070618 0.289563 0.117785 +v -0.070672 0.369475 0.170211 +v 0.054549 0.139792 0.459559 +v 0.054604 0.059883 0.407135 +v 0.054369 0.290797 0.117772 +v 0.054313 0.370707 0.170196 +vt 0.062500 0.562500 +vt 0.062500 0.875000 +vt 0.125000 0.875000 +vt 0.125000 0.562500 +vt 0.187500 0.562500 +vt 0.250000 0.562500 +vt 0.250000 0.875000 +vt 0.187500 0.875000 +vt 0.125000 0.562500 +vt 0.062500 0.562500 +vt 0.062500 0.875000 +vt 0.125000 0.875000 +vt 0.250000 0.562500 +vt 0.250000 0.875000 +vt 0.187500 0.875000 +vt 0.187500 0.562500 +vt 0.625000 0.875000 +vt 0.562500 0.875000 +vt 0.562500 0.937500 +vt 0.625000 0.937500 +vn -1.0000 -0.0008 0.0002 +vn 1.0000 0.0008 -0.0002 +vn -0.0076 0.7816 0.6237 +vn 0.0076 -0.7816 -0.6237 +vn -0.0055 0.5485 -0.8361 +usemtl none.009 +s off +f 1/1/1 4/2/1 3/3/1 2/4/1 +f 5/5/2 6/6/2 7/7/2 8/8/2 +f 1/9/3 5/10/3 8/11/3 4/12/3 +f 2/13/4 3/14/4 7/15/4 6/16/4 +f 4/17/5 8/18/5 7/19/5 3/20/5 +o nodebox1.008 +v -0.170183 0.248882 0.492124 +v -0.161792 -0.249536 0.496140 +v -0.161781 -0.250523 0.373114 +v -0.170172 0.247894 0.369098 +v 0.161753 0.245254 0.492135 +v 0.170145 -0.253163 0.496151 +v 0.170155 -0.254151 0.373125 +v 0.161764 0.244266 0.369109 +vt 0.500000 0.203100 +vt 0.500000 0.000000 +vt 0.000000 0.000000 +vt 0.000000 0.203100 +vt 0.500000 0.203100 +vt 0.000000 0.203100 +vt 0.000000 0.000000 +vt 0.500000 0.000000 +vt 0.000000 0.203100 +vt 0.000100 0.000100 +vt 0.500000 0.000000 +vt 0.500000 0.203100 +vt 0.000000 0.203100 +vt 0.000000 -0.000000 +vt 0.000000 0.500000 +vt 0.000000 0.000000 +vt 0.500000 -0.000000 +vt 0.500000 0.500000 +vt -0.000000 0.500000 +vt 0.500000 0.500000 +vt 0.500000 -0.000000 +vn -0.9999 -0.0168 0.0000 +vn 0.9999 0.0168 -0.0000 +vn 0.0109 0.9999 -0.0080 +vn -0.0109 -0.9999 0.0080 +vn 0.0001 0.0081 1.0000 +vn -0.0001 -0.0081 -1.0000 +usemtl none.008 +s off +f 9/21/6 12/22/6 11/23/6 10/24/6 +f 13/25/7 14/26/7 15/27/7 16/28/7 +f 9/29/8 13/25/8 16/28/8 12/30/8 +f 10/31/9 11/32/9 15/33/9 14/34/9 +f 9/35/10 10/36/10 14/37/10 13/38/10 +f 12/39/11 16/40/11 15/41/11 11/23/11 diff --git a/mesecons_walllever/models/jeija_wall_lever_on.obj b/mesecons_walllever/models/jeija_wall_lever_on.obj new file mode 100644 index 0000000..5de8075 --- /dev/null +++ b/mesecons_walllever/models/jeija_wall_lever_on.obj @@ -0,0 +1,88 @@ +# Blender v2.79 (sub 0) OBJ File: '' +# www.blender.org +mtllib jeija_wall_lever_on.mtl +o nodebox1.011 +v -0.170183 0.248540 0.492297 +v -0.161792 -0.249880 0.495967 +v -0.161781 -0.250782 0.372940 +v -0.170172 0.247638 0.369270 +v 0.161753 0.244912 0.492305 +v 0.170145 -0.253508 0.495975 +v 0.170155 -0.254410 0.372949 +v 0.161764 0.244010 0.369279 +vt 0.500000 0.203100 +vt 0.500000 0.000000 +vt 0.000000 0.000000 +vt 0.000000 0.203100 +vt 0.500000 0.203100 +vt 0.000000 0.203100 +vt 0.000000 0.000000 +vt 0.500000 0.000000 +vt 0.000000 0.203100 +vt 0.000100 0.000100 +vt 0.500000 0.000000 +vt 0.500000 0.203100 +vt 0.000000 0.203100 +vt 0.000000 -0.000000 +vt 0.000000 0.500000 +vt 0.000000 0.000000 +vt 0.500000 -0.000000 +vt 0.500000 0.500000 +vt -0.000000 0.500000 +vt 0.500000 0.500000 +vt 0.500000 -0.000000 +vn -0.9999 -0.0168 0.0000 +vn 0.9999 0.0168 -0.0000 +vn 0.0109 0.9999 -0.0073 +vn -0.0109 -0.9999 0.0073 +vn 0.0001 0.0074 1.0000 +vn -0.0001 -0.0074 -1.0000 +usemtl none.011 +s off +f 1/1/1 4/2/1 3/3/1 2/4/1 +f 5/5/2 6/6/2 7/7/2 8/8/2 +f 1/9/3 5/5/3 8/8/3 4/10/3 +f 2/11/4 3/12/4 7/13/4 6/14/4 +f 1/15/5 2/16/5 6/17/5 5/18/5 +f 4/19/6 8/20/6 7/21/6 3/3/6 +o nodebox1.010 +v 0.070437 -0.138656 0.459545 +v 0.070383 -0.058733 0.407137 +v -0.054604 -0.059966 0.407123 +v -0.054549 -0.139886 0.459530 +v 0.070618 -0.289587 0.117726 +v 0.070672 -0.369510 0.170135 +v -0.054369 -0.290821 0.117712 +v -0.054313 -0.370742 0.170120 +vt 0.062500 0.562500 +vt 0.062500 0.875000 +vt 0.125000 0.875000 +vt 0.125000 0.562500 +vt 0.187500 0.562500 +vt 0.250000 0.562500 +vt 0.250000 0.875000 +vt 0.187500 0.875000 +vt 0.125000 0.562500 +vt 0.062500 0.562500 +vt 0.062500 0.875000 +vt 0.125000 0.875000 +vt 0.250000 0.562500 +vt 0.250000 0.875000 +vt 0.187500 0.875000 +vt 0.187500 0.562500 +vt 0.625000 0.875000 +vt 0.562500 0.875000 +vt 0.562500 0.937500 +vt 0.625000 0.937500 +vn 1.0000 0.0008 0.0002 +vn -1.0000 -0.0008 -0.0002 +vn 0.0076 -0.7817 0.6236 +vn -0.0076 0.7817 -0.6236 +vn 0.0055 -0.5484 -0.8362 +usemtl none.010 +s off +f 9/22/7 14/23/7 13/24/7 10/25/7 +f 12/26/8 11/27/8 15/28/8 16/29/8 +f 9/30/9 12/31/9 16/32/9 14/33/9 +f 10/34/10 13/35/10 15/36/10 11/37/10 +f 14/38/11 16/39/11 15/40/11 13/41/11 diff --git a/mesecons_walllever/textures/jeija_wall_lever.png b/mesecons_walllever/textures/jeija_wall_lever.png new file mode 100644 index 0000000..5774607 Binary files /dev/null and b/mesecons_walllever/textures/jeija_wall_lever.png differ diff --git a/mesecons_wires/init.lua b/mesecons_wires/init.lua new file mode 100644 index 0000000..0f2febc --- /dev/null +++ b/mesecons_wires/init.lua @@ -0,0 +1,299 @@ +-- naming scheme: wire:(xp)(zp)(xm)(zm)(xpyp)(zpyp)(xmyp)(zmyp)_on/off +-- where x= x direction, z= z direction, y= y direction, p = +1, m = -1, e.g. xpym = {x=1, y=-1, z=0} +-- The (xp)/(zpyp)/.. statements shall be replaced by either 0 or 1 +-- Where 0 means the wire has no visual connection to that direction and +-- 1 means that the wire visually connects to that other node. + +local S = minetest.get_translator(minetest.get_current_modname()) + +-- ####################### +-- ## Update wire looks ## +-- ####################### + +local wire_rules = +{{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}, + + {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}} + +-- self_pos = pos of any mesecon node, from_pos = pos of conductor to getconnect for +local function wire_getconnect(from_pos, self_pos) + local node = minetest.get_node(self_pos) + if minetest.registered_nodes[node.name] + and minetest.registered_nodes[node.name].mesecons then + -- rules of node to possibly connect to + local rules + if (minetest.registered_nodes[node.name].mesecon_wire) then + rules = wire_rules + else + rules = mesecon.get_any_rules(node) + end + + for _, r in ipairs(mesecon.flattenrules(rules)) do + if (vector.equals(vector.add(self_pos, r), from_pos)) then + return true + end + end + end + return false +end + +-- Update this node +local function wire_updateconnect(pos) + local connections = {} + + for _, r in ipairs(wire_rules) do + if wire_getconnect(pos, vector.add(pos, r)) then + table.insert(connections, r) + end + end + + local nid = {} + for _, vec in ipairs(connections) do + -- flat component + if vec.x == 1 then nid[0] = "1" end + if vec.z == 1 then nid[1] = "1" end + if vec.x == -1 then nid[2] = "1" end + if vec.z == -1 then nid[3] = "1" end + + -- slopy component + if vec.y == 1 then + if vec.x == 1 then nid[4] = "1" end + if vec.z == 1 then nid[5] = "1" end + if vec.x == -1 then nid[6] = "1" end + if vec.z == -1 then nid[7] = "1" end + end + end + + local nodeid = (nid[0] or "0")..(nid[1] or "0")..(nid[2] or "0")..(nid[3] or "0") + ..(nid[4] or "0")..(nid[5] or "0")..(nid[6] or "0")..(nid[7] or "0") + + local state_suffix = string.find(minetest.get_node(pos).name, "_off") and "_off" or "_on" + minetest.set_node(pos, {name = "mesecons:wire_"..nodeid..state_suffix}) +end + +local function update_on_place_dig(pos, node) + -- Update placed node (get_node again as it may have been dug) + local nn = minetest.get_node(pos) + if (minetest.registered_nodes[nn.name]) + and (minetest.registered_nodes[nn.name].mesecon_wire) then + wire_updateconnect(pos) + end + + -- Update nodes around it + local rules + if minetest.registered_nodes[node.name] + and minetest.registered_nodes[node.name].mesecon_wire then + rules = wire_rules + else + rules = mesecon.get_any_rules(node) + end + if (not rules) then return end + + for _, r in ipairs(mesecon.flattenrules(rules)) do + local np = vector.add(pos, r) + if minetest.registered_nodes[minetest.get_node(np).name] + and minetest.registered_nodes[minetest.get_node(np).name].mesecon_wire then + wire_updateconnect(np) + end + end +end + +mesecon.register_autoconnect_hook("wire", update_on_place_dig) + +-- ############################ +-- ## Wire node registration ## +-- ############################ +-- Nodeboxes: +local box_center = {-1/16, -.5, -1/16, 1/16, -.5+1/64, 1/16} +local box_bump1 = { -2/16, -8/16, -2/16, 2/16, -.5+1/64, 2/16 } + +local nbox_nid = +{ + [0] = {1/16, -.5, -1/16, 8/16, -.5+1/64, 1/16}, -- x positive + [1] = {-1/16, -.5, 1/16, 1/16, -.5+1/64, 8/16}, -- z positive + [2] = {-8/16, -.5, -1/16, -1/16, -.5+1/64, 1/16}, -- x negative + [3] = {-1/16, -.5, -8/16, 1/16, -.5+1/64, -1/16}, -- z negative + + [4] = {.5-1/16, -.5+1/16, -1/16, .5, .4999+1/64, 1/16}, -- x positive up + [5] = {-1/16, -.5+1/16, .5-1/16, 1/16, .4999+1/64, .5}, -- z positive up + [6] = {-.5, -.5+1/16, -1/16, -.5+1/16, .4999+1/64, 1/16}, -- x negative up + [7] = {-1/16, -.5+1/16, -.5, 1/16, .4999+1/64, -.5+1/16} -- z negative up +} + +local selectionbox = +{ + type = "fixed", + fixed = {-.5, -.5, -.5, .5, -.5+1/16, .5} +} + +-- go to the next nodeid (ex.: 01000011 --> 01000100) +local function nid_inc() end +function nid_inc(nid) + local i = 0 + while nid[i-1] ~= 1 do + nid[i] = (nid[i] ~= 1) and 1 or 0 + i = i + 1 + end + + -- BUT: Skip impossible nodeids: + if ((nid[0] == 0 and nid[4] == 1) or (nid[1] == 0 and nid[5] == 1) + or (nid[2] == 0 and nid[6] == 1) or (nid[3] == 0 and nid[7] == 1)) then + return nid_inc(nid) + end + + return i <= 8 +end + +local function register_wires() + local nid = {} + while true do + -- Create group specifiction and nodeid string (see note above for details) + local nodeid = (nid[0] or "0")..(nid[1] or "0")..(nid[2] or "0")..(nid[3] or "0") + ..(nid[4] or "0")..(nid[5] or "0")..(nid[6] or "0")..(nid[7] or "0") + + -- Calculate nodebox + local nodebox = {type = "fixed", fixed={box_center}} + for i=0,7 do + if nid[i] == 1 then + table.insert(nodebox.fixed, nbox_nid[i]) + end + end + + -- Add bump to nodebox if curved + if (nid[0] == 1 and nid[1] == 1) or (nid[1] == 1 and nid[2] == 1) + or (nid[2] == 1 and nid[3] == 1) or (nid[3] == 1 and nid[0] == 1) then + table.insert(nodebox.fixed, box_bump1) + end + + -- If nothing to connect to, still make a nodebox of a straight wire + if nodeid == "00000000" then + nodebox.fixed = {-8/16, -.5, -1/16, 8/16, -.5+1/16, 1/16} + end + + local meseconspec_off = { conductor = { + rules = wire_rules, + state = mesecon.state.off, + onstate = "mesecons:wire_"..nodeid.."_on" + }} + + local meseconspec_on = { conductor = { + rules = wire_rules, + state = mesecon.state.on, + offstate = "mesecons:wire_"..nodeid.."_off" + }} + + local groups_on = {dig_immediate = 3, mesecon_conductor_craftable = 1, + not_in_creative_inventory = 1, attached_node = 1, dig_by_water = 1,destroy_by_lava_flow=1, dig_by_piston = 1} + local groups_off = {dig_immediate = 3, mesecon_conductor_craftable = 1, + attached_node = 1, dig_by_water = 1,destroy_by_lava_flow=1, dig_by_piston = 1, craftitem = 1} + if nodeid ~= "00000000" then + groups_off["not_in_creative_inventory"] = 1 + end + + -- Wire textures + local ratio_off = 128 + local ratio_on = 192 + local crossing_off = "(redstone_redstone_dust_dot.png^redstone_redstone_dust_line0.png^(redstone_redstone_dust_line1.png^[transformR90))^[colorize:#FF0000:"..ratio_off + local crossing_on = "(redstone_redstone_dust_dot.png^redstone_redstone_dust_line0.png^(redstone_redstone_dust_line1.png^[transformR90))^[colorize:#FF0000:"..ratio_on + local straight0_off = "redstone_redstone_dust_line0.png^[colorize:#FF0000:"..ratio_off + local straight0_on = "redstone_redstone_dust_line0.png^[colorize:#FF0000:"..ratio_on + local straight1_off = "redstone_redstone_dust_line0.png^[colorize:#FF0000:"..ratio_off + local straight1_on = "redstone_redstone_dust_line0.png^[colorize:#FF0000:"..ratio_on + local dot_off = "redstone_redstone_dust_dot.png^[colorize:#FF0000:"..ratio_off + local dot_on = "redstone_redstone_dust_dot.png^[colorize:#FF0000:"..ratio_on + + local tiles_off, tiles_on + + local wirehelp, tt, longdesc, usagehelp, img, desc_off, desc_on + if nodeid == "00000000" then + -- Non-connected redstone wire + nodebox.fixed = {-8/16, -.5, -8/16, 8/16, -.5+1/64, 8/16} + -- “Dot” texture + tiles_off = { dot_off, dot_off, "blank.png", "blank.png", "blank.png", "blank.png" } + tiles_on = { dot_on, dot_on, "blank.png", "blank.png", "blank.png", "blank.png" } + + tt = S("Transmits redstone power, powers mechanisms") + longdesc = S("Redstone is a versatile conductive mineral which transmits redstone power. It can be placed on the ground as a trail.").."\n".. +S("A redstone trail can be in two states: Powered or not powered. A powered redstone trail will power (and thus activate) adjacent redstone components.").."\n".. +S("Redstone power can be received from various redstone components, such as a block of redstone or a button. Redstone power is used to activate numerous mechanisms, such as redstone lamps or pistons.") + usagehelp = S("Place redstone on the ground to build a redstone trail. The trails will connect to each other automatically and it can also go over hills.").."\n\n".. + +S("Read the help entries on the other redstone components to learn how redstone components interact.") + img = "redstone_redstone_dust.png" + desc_off = S("Redstone") + desc_on = S("Powered Redstone Spot (@1)", nodeid) + else + -- Connected redstone wire + table.insert(nodebox, box_center) + tiles_off = { crossing_off, crossing_off, straight0_off, straight1_off, straight0_off, straight1_off } + tiles_on = { crossing_on, crossing_on, straight0_on, straight1_on, straight0_on, straight1_on } + wirehelp = false + desc_off = S("Redstone Trail (@1)", nodeid) + desc_on = S("Powered Redstone Trail (@1)", nodeid) + end + + mesecon.register_node(":mesecons:wire_"..nodeid, { + drawtype = "nodebox", + paramtype = "light", + use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "clip" or true, + sunlight_propagates = true, + selection_box = selectionbox, + node_box = nodebox, + walkable = false, + drop = "mesecons:wire_00000000_off", + sounds = mcl_sounds.node_sound_defaults(), + is_ground_content = false, + mesecon_wire = true + },{ + description = desc_off, + inventory_image = img, + wield_image = img, + _tt_help = tt, + _doc_items_create_entry = wirehelp, + _doc_items_longdesc = longdesc, + _doc_items_usagehelp = usagehelp, + tiles = tiles_off, + mesecons = meseconspec_off, + groups = groups_off, + },{ + description = desc_on, + _doc_items_create_entry = false, + tiles = tiles_on, + mesecons = meseconspec_on, + groups = groups_on + }) + + -- Add Help entry aliases for e.g. making it identifiable by the lookup tool [doc_identifier] + if minetest.get_modpath("doc") then + if nodeid ~= "00000000" then + doc.add_entry_alias("nodes", "mesecons:wire_00000000_off", "nodes", "mesecons:wire_"..nodeid.."_off") + end + doc.add_entry_alias("nodes", "mesecons:wire_00000000_off", "nodes", "mesecons:wire_"..nodeid.."_on") + end + + if (nid_inc(nid) == false) then return end + end +end +register_wires() + +minetest.register_alias("mesecons:redstone", "mesecons:wire_00000000_off") + +minetest.register_craft({ + type = "cooking", + output = "mesecons:redstone", + recipe = "mcl_core:stone_with_redstone", + cooktime = 10, +}) + diff --git a/mesecons_wires/locale/mesecons_wires.de.tr b/mesecons_wires/locale/mesecons_wires.de.tr new file mode 100644 index 0000000..d6d82e8 --- /dev/null +++ b/mesecons_wires/locale/mesecons_wires.de.tr @@ -0,0 +1,11 @@ +# textdomain: mesecons_wires +Redstone is a versatile conductive mineral which transmits redstone power. It can be placed on the ground as a trail.=Redstone ist ein vielseitiges leitendes Mineral, der Redstoneenergie überträgt. Es kann auf dem Boden in Form einer Spur platziert werden. +A redstone trail can be in two states: Powered or not powered. A powered redstone trail will power (and thus activate) adjacent redstone components.=Eine Redstonespur kann einen von zwei Zuständen annehmen: Bestromt und unbestromt. Eine bestromte Redstonespur wird benachbarte Redstonekomponenten bestromen (und somit aktivieren). +Redstone power can be received from various redstone components, such as a block of redstone or a button. Redstone power is used to activate numerous mechanisms, such as redstone lamps or pistons.=Redstoneenergie kann von verschiedenen Redstonekomponenten erhalten werden, wie zum Beispiel einem Redstoneblock oder einem Knopf. Redstoneenergie wird benutzt, um verschiedene Mechanismen zu aktivieren, wie Redstonelampen oder Kolben. +Place redstone on the ground to build a redstone trail. The trails will connect to each other automatically and it can also go over hills.=Platzieren Sie Redstone auf dem Boden, um eine Redstonespur auszulegen. Die Spuren werden sich automatisch miteinander verbinden und sie können auch über Hügel gehen. +Read the help entries on the other redstone components to learn how redstone components interact.=Lesen Sie die Hilfeeinträge über andere Redstonekomponenten, um zu erfahren, wie sie interagieren. +Redstone=Redstone +Powered Redstone Spot (@1)=Bestromter Redstoneklecks (@1) +Redstone Trail (@1)=Redstonespur (@1) +Powered Redstone Trail (@1)=Bestromte Redstonespur (@1) +Transmits redstone power, powers mechanisms=Überträgt Redstoneenergie, bestromt Mechanismen diff --git a/mesecons_wires/locale/mesecons_wires.es.tr b/mesecons_wires/locale/mesecons_wires.es.tr new file mode 100644 index 0000000..beac845 --- /dev/null +++ b/mesecons_wires/locale/mesecons_wires.es.tr @@ -0,0 +1,10 @@ +# textdomain: mesecons_wires +Redstone is a versatile conductive mineral which transmits redstone power. It can be placed on the ground as a trail.=Redstone es un mineral conductor versátil que transmite el poder de redstone. Se puede colocar en el suelo como un sendero. +A redstone trail can be in two states: Powered or not powered. A powered redstone trail will power (and thus activate) adjacent redstone components.=Un sendero de redstone puede estar en dos estados: alimentado o no alimentado. Un rastro de redstone alimentado alimentará (y por lo tanto activará) los componentes adyacentes de redstone. +Redstone power can be received from various redstone components, such as a block of redstone or a button. Redstone power is used to activate numerous mechanisms, such as redstone lamps or pistons.=El poder de Redstone se puede recibir de varios componentes de redstone, como un bloque de redstone o un botón. El poder de Redstone se utiliza para activar numerosos mecanismos, como las lámparas de redstone o los pistones. +Place redstone on the ground to build a redstone trail. The trails will connect to each other automatically and it can also go over hills.=Coloque redstone en el suelo para construir un sendero de redstone. Los senderos se conectarán entre sí de forma automática y también pueden pasar por colinas. +Read the help entries on the other redstone components to learn how redstone components interact.=Lea las entradas de ayuda en los otros componentes de redstone para aprender cómo interactúan los componentes de redstone. +Redstone=Redstone +Powered Redstone Spot (@1)=Punto de Redstone accionado (@1) +Redstone Trail (@1)=Sendero de Redstone (@1) +Powered Redstone Trail (@1)=Sendero de Redstone con motorizado (@1) diff --git a/mesecons_wires/locale/mesecons_wires.fr.tr b/mesecons_wires/locale/mesecons_wires.fr.tr new file mode 100644 index 0000000..66a4230 --- /dev/null +++ b/mesecons_wires/locale/mesecons_wires.fr.tr @@ -0,0 +1,11 @@ +# textdomain: mesecons_wires +Redstone is a versatile conductive mineral which transmits redstone power. It can be placed on the ground as a trail.=Redstone est un minéral conducteur polyvalent qui transmet la puissance de redstone. Il peut être placé au sol comme un sentier. +A redstone trail can be in two states: Powered or not powered. A powered redstone trail will power (and thus activate) adjacent redstone components.=Un sentier de redstone peut être dans deux états: alimenté ou non alimenté. Un sentier Redstone alimenté alimentera (et activera donc) les composants Redstone adjacents. +Redstone power can be received from various redstone components, such as a block of redstone or a button. Redstone power is used to activate numerous mechanisms, such as redstone lamps or pistons.=L'alimentation Redstone peut être reçue de divers composants Redstone, tels qu'un bloc de Redstone ou un bouton. La puissance Redstone est utilisée pour activer de nombreux mécanismes, tels que les lampes ou les pistons Redstone. +Place redstone on the ground to build a redstone trail. The trails will connect to each other automatically and it can also go over hills. An easy way to power a redstone trail is by placing a redstone torch.=Placez du redstone sur le sol pour construire un sentier de redstone. Les sentiers se connecteront automatiquement et pourront également traverser des collines. Un moyen facile d'alimenter une piste de redstone est de placer une torche de redstone. +Read the help entries on the other redstone components to learn how redstone components interact.=Lisez les entrées d'aide sur les autres composants Redstone pour savoir comment les composants Redstone interagissent. +Redstone=Redstone +Powered Redstone Spot (@1)=Spot Redstone alimenté (@1) +Redstone Trail (@1)=Sentier Redstone (@1) +Powered Redstone Trail (@1)=Sentier Redstone alimenté (@1) +Transmits redstone power, powers mechanisms=Transmet la puissance redstone, alimente les mécanismes diff --git a/mesecons_wires/locale/mesecons_wires.pl.tr b/mesecons_wires/locale/mesecons_wires.pl.tr new file mode 100644 index 0000000..bdc7176 --- /dev/null +++ b/mesecons_wires/locale/mesecons_wires.pl.tr @@ -0,0 +1,11 @@ +# textdomain: mesecons_wires +Redstone is a versatile conductive mineral which transmits redstone power. It can be placed on the ground as a trail.=Czerwienit jest wszechstronnym przewodzącym minerałem, który przewodzi energię czerwienitową. Może być położony na ziemi tworząc ścieżkę. +A redstone trail can be in two states: Powered or not powered. A powered redstone trail will power (and thus activate) adjacent redstone components.=Ścieżka czerwienitu może być w dwóch stanach: Zasilonym lub Nie zasilonym. Zasilona ścieżka będzie zasilać (a więc również aktywować) sąsiadujące mechanizmy czerwienitowe. +Redstone power can be received from various redstone components, such as a block of redstone or a button. Redstone power is used to activate numerous mechanisms, such as redstone lamps or pistons.=Energia czerwienitowa może być uzyskana z różnych mechanizmów czerwienitowych, takich jak blok czerwienitu czy przycisk. Energia czerwienitowa może być wykorzystywana do aktywowania różnych mechanizmów takich jak czerwienitowe lampy lub tłoki. +Place redstone on the ground to build a redstone trail. The trails will connect to each other automatically and it can also go over hills. An easy way to power a redstone trail is by placing a redstone torch.=Połóż czerwienit na ziemi aby stworzyć ścieżkę czerwienitu. Ścieżki połączą się ze sobą automatycznie, nawet jeśli istnieje różnica wysokości. Łatwym sposobem na zasilenie ścieżki czerwienitu jest postawienie czerwienitowej pochodni. +Read the help entries on the other redstone components to learn how redstone components interact.=Przeczytaj wpisy na temat innych czerwienitowych mechanizmów, by dowiedzieć się jak wchodzą ze sobą w interakcję. +Redstone=Czerwienit +Powered Redstone Spot (@1)=Zasilony punkt czerwienitu (@1) +Redstone Trail (@1)=Ścieżka czerwienitu (@1) +Powered Redstone Trail (@1)=Zasilona ścieżka czerwienitu (@1) +Transmits redstone power, powers mechanisms=Przekazuje energię czerwienitową, zasila mechanizmy diff --git a/mesecons_wires/locale/mesecons_wires.ru.tr b/mesecons_wires/locale/mesecons_wires.ru.tr new file mode 100644 index 0000000..4316613 --- /dev/null +++ b/mesecons_wires/locale/mesecons_wires.ru.tr @@ -0,0 +1,11 @@ +# textdomain: mesecons_wires +Redstone is a versatile conductive mineral which transmits redstone power. It can be placed on the ground as a trail.=Редстоун является универсальным проводящим минералом, который передает энергию красного камня. Он может размещаться на поверхности как дорожка. +A redstone trail can be in two states: Powered or not powered. A powered redstone trail will power (and thus activate) adjacent redstone components.=Дорожка редстоуна может быть в двух состояниях: включена или выключена. Включённая дорожка редстоуна будет снабжать (а значит, активировать) смежные компоненты редстоуна. +Redstone power can be received from various redstone components, such as a block of redstone or a button. Redstone power is used to activate numerous mechanisms, such as redstone lamps or pistons.=Энергию редстоуна можно получать от различных компонентов редстоуна, таких как блок редстоуна или кнопка. Эта энергия используется для активации многочисленных механизмов, таких как лампы редстоуна или поршни. +Place redstone on the ground to build a redstone trail. The trails will connect to each other automatically and it can also go over hills. An easy way to power a redstone trail is by placing a redstone torch.=Поместите редстоун на землю, чтобы создать из него дорожку. Фрагменты дорожек будут соединяться между собой автоматически и могут даже проходить по холмам. Простой способ подать энергию редстоуна к дорожке редстоуна это установка факела редстоуна. +Read the help entries on the other redstone components to learn how redstone components interact.=Смотрите справочные записи к остальным компонентам редстоуна, чтобы узнать больше об их взаимодействии. +Redstone=Редстоун +Powered Redstone Spot (@1)=Подключённое пятно редстоуна (@1) +Redstone Trail (@1)=Дорожка редстоуна (@1) +Powered Redstone Trail (@1)=Подключённая дорожка редстоуна (@1) +Transmits redstone power, powers mechanisms=Передаёт энергию редстоуна, подключает механизмы diff --git a/mesecons_wires/locale/template.txt b/mesecons_wires/locale/template.txt new file mode 100644 index 0000000..91e6bde --- /dev/null +++ b/mesecons_wires/locale/template.txt @@ -0,0 +1,11 @@ +# textdomain: mesecons_wires +Redstone is a versatile conductive mineral which transmits redstone power. It can be placed on the ground as a trail.= +A redstone trail can be in two states: Powered or not powered. A powered redstone trail will power (and thus activate) adjacent redstone components.= +Redstone power can be received from various redstone components, such as a block of redstone or a button. Redstone power is used to activate numerous mechanisms, such as redstone lamps or pistons.= +Place redstone on the ground to build a redstone trail. The trails will connect to each other automatically and it can also go over hills. An easy way to power a redstone trail is by placing a redstone torch.= +Read the help entries on the other redstone components to learn how redstone components interact.= +Redstone= +Powered Redstone Spot (@1)= +Redstone Trail (@1)= +Powered Redstone Trail (@1)= +Transmits redstone power, powers mechanisms= diff --git a/mesecons_wires/mod.conf b/mesecons_wires/mod.conf new file mode 100644 index 0000000..15f2e0d --- /dev/null +++ b/mesecons_wires/mod.conf @@ -0,0 +1,3 @@ +name = mesecons_wires +depends = mesecons +optional_depends = doc diff --git a/mesecons_wires/textures/redstone_redstone_dust.png b/mesecons_wires/textures/redstone_redstone_dust.png new file mode 100644 index 0000000..30c42e4 Binary files /dev/null and b/mesecons_wires/textures/redstone_redstone_dust.png differ diff --git a/mesecons_wires/textures/redstone_redstone_dust_dot.png b/mesecons_wires/textures/redstone_redstone_dust_dot.png new file mode 100644 index 0000000..d2e4338 Binary files /dev/null and b/mesecons_wires/textures/redstone_redstone_dust_dot.png differ diff --git a/mesecons_wires/textures/redstone_redstone_dust_line0.png b/mesecons_wires/textures/redstone_redstone_dust_line0.png new file mode 100644 index 0000000..3219df3 Binary files /dev/null and b/mesecons_wires/textures/redstone_redstone_dust_line0.png differ diff --git a/mesecons_wires/textures/redstone_redstone_dust_line1.png b/mesecons_wires/textures/redstone_redstone_dust_line1.png new file mode 100644 index 0000000..61ebb2c Binary files /dev/null and b/mesecons_wires/textures/redstone_redstone_dust_line1.png differ diff --git a/modpack.conf b/modpack.conf new file mode 100644 index 0000000..245aa90 --- /dev/null +++ b/modpack.conf @@ -0,0 +1,2 @@ +name = REDSTONE +description = Redstone modpack, adds redstone and various interactive mechanims to build complex electronic machinery