diff --git a/.github/workflows/check-release.yml b/.github/workflows/check-release.yml index d43987a..616adb3 100644 --- a/.github/workflows/check-release.yml +++ b/.github/workflows/check-release.yml @@ -13,3 +13,29 @@ jobs: run: luarocks install --local luacheck - name: luacheck run run: $HOME/.luarocks/bin/luacheck ./ + + test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@main + - name: apt + run: sudo apt-get install -y luarocks + - name: busted install + run: luarocks install --local busted + - name: luacov install + run: luarocks install --local luacov + - name: mineunit install + run: luarocks install --server=https://luarocks.org/dev --local mineunit + - name: run mesecons tests + working-directory: ./mesecons/ + run: $HOME/.luarocks/bin/mineunit -q + - name: run mesecons_mvps tests + working-directory: ./mesecons_mvps/ + run: $HOME/.luarocks/bin/mineunit -q + - name: run mesecons_fpga tests + working-directory: ./mesecons_fpga/ + run: $HOME/.luarocks/bin/mineunit -q + - name: run mesecons_luacontroller tests + working-directory: ./mesecons_luacontroller/ + run: $HOME/.luarocks/bin/mineunit -q diff --git a/.luacheckrc b/.luacheckrc index c8cccda..f2445a0 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -34,3 +34,26 @@ globals = {"mesecon"} files["mesecons/actionqueue.lua"] = { globals = {"minetest.registered_globalsteps"}, } + +-- Test-specific stuff follows. + +local test_conf = { + read_globals = { + "assert", + "fixture", + "mineunit", + "Player", + "sourcefile", + "world", + }, +} +files["*/spec/*.lua"] = test_conf +files[".test_fixtures/*.lua"] = test_conf + +files[".test_fixtures/screwdriver.lua"] = { + globals = {"screwdriver"}, +} + +files[".test_fixtures/mesecons_fpga.lua"] = { + globals = {"minetest.register_on_player_receive_fields"}, +} diff --git a/.test_fixtures/mesecons.lua b/.test_fixtures/mesecons.lua new file mode 100644 index 0000000..2acd6f6 --- /dev/null +++ b/.test_fixtures/mesecons.lua @@ -0,0 +1,156 @@ +mineunit("core") +mineunit("server") +mineunit("voxelmanip") + +mineunit:set_current_modname("mesecons") +mineunit:set_modpath("mesecons", "../mesecons") +sourcefile("../mesecons/init") + +-- Utility node: this conductor is used to test the connectivity and state of adjacent wires. +do + local off_spec = {conductor = { + state = mesecon.state.off, + rules = mesecon.rules.alldirs, + onstate = "mesecons:test_conductor_on", + }} + local on_spec = {conductor = { + state = mesecon.state.on, + rules = mesecon.rules.alldirs, + offstate = "mesecons:test_conductor_off", + }} + mesecon.register_node("mesecons:test_conductor", { + description = "Test Conductor", + }, {mesecons = off_spec}, {mesecons = on_spec}) +end + +-- Utility node: this receptor is used to test power sources. +do + local off_spec = {receptor = { + state = mesecon.state.off, + rules = mesecon.rules.alldirs, + }} + local on_spec = {receptor = { + state = mesecon.state.on, + rules = mesecon.rules.alldirs, + }} + mesecon.register_node("mesecons:test_receptor", { + description = "Test Receptor", + }, {mesecons = off_spec}, {mesecons = on_spec}) +end + +-- Utility node: this effector is used to test circuit outputs. +do + -- This is a list of actions in the form {, }, + -- where is "on", "off", or "overheat". + mesecon._test_effector_events = {} + local function action_on(pos, node) + table.insert(mesecon._test_effector_events, {"on", pos}) + node.param2 = node.param2 % 64 + 128 -- Turn on bit 7 + minetest.swap_node(pos, node) + end + local function action_off(pos, node) + table.insert(mesecon._test_effector_events, {"off", pos}) + node.param2 = node.param2 % 64 -- Turn off bit 7 + minetest.swap_node(pos, node) + end + local function action_change(pos, node, rule_name, new_state) + if mesecon.do_overheat(pos) then + table.insert(mesecon._test_effector_events, {"overheat", pos}) + minetest.remove_node(pos) + return + end + -- Set the value of a bit in param2 according to the rule name and new state. + local bit = tonumber(rule_name.name, 2) + local bits_above = node.param2 - node.param2 % (bit * 2) + local bits_below = node.param2 % bit + local bits_flipped = new_state == mesecon.state.on and bit or 0 + node.param2 = bits_above + bits_flipped + bits_below + minetest.swap_node(pos, node) + end + minetest.register_node("mesecons:test_effector", { + description = "Test Effector", + mesecons = {effector = { + action_on = action_on, + action_off = action_off, + action_change = action_change, + rules = { + {x = 1, y = 0, z = 0, name = "000001"}, + {x = -1, y = 0, z = 0, name = "000010"}, + {x = 0, y = 1, z = 0, name = "000100"}, + {x = 0, y = -1, z = 0, name = "001000"}, + {x = 0, y = 0, z = 1, name = "010000"}, + {x = 0, y = 0, z = -1, name = "100000"}, + } + }}, + }) +end + +-- Utility node: this conductor is used to test rotation. +do + local get_rules = mesecon.horiz_rules_getter({{x = 1, y = 0, z = 0}, {x = -1, y = 0, z = 0}}) + local off_spec = {conductor = { + state = mesecon.state.off, + rules = get_rules, + onstate = "mesecons:test_conductor_rot_on", + }} + local on_spec = {conductor = { + state = mesecon.state.on, + rules = get_rules, + offstate = "mesecons:test_conductor_rot_off", + }} + mesecon.register_node("mesecons:test_conductor_rot", { + description = "Rotatable Test Conductor", + on_rotate = mesecon.on_rotate_horiz, + }, {mesecons = off_spec}, {mesecons = on_spec}) +end + +-- Utility node: this is used to test multiple conductors within a single node. +do + local mesecons_spec = {conductor = { + rules = { + {{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}, {x = -1, y = 0, z = 0}}, + }, + states = { + "mesecons:test_multiconductor_off", "mesecons:test_multiconductor_001", + "mesecons:test_multiconductor_010", "mesecons:test_multiconductor_011", + "mesecons:test_multiconductor_100", "mesecons:test_multiconductor_101", + "mesecons:test_multiconductor_110", "mesecons:test_multiconductor_on", + }, + }} + for _, state in ipairs(mesecons_spec.conductor.states) do + minetest.register_node(state, { + description = "Test Multiconductor", + mesecons = mesecons_spec, + }) + end +end + +mesecon._test_autoconnects = {} +mesecon.register_autoconnect_hook("test", function(pos, node) + table.insert(mesecon._test_autoconnects, {pos, node}) +end) + +function mesecon._test_dig(pos) + local node = minetest.get_node(pos) + minetest.remove_node(pos) + mesecon.on_dignode(pos, node) +end + +function mesecon._test_place(pos, node) + world.set_node(pos, node) + mesecon.on_placenode(pos, minetest.get_node(pos)) +end + +function mesecon._test_reset() + -- First let circuits settle by simulating many globalsteps. + for i = 1, 10 do + mineunit:execute_globalstep(60) + end + mesecon.queue.actions = {} + mesecon._test_effector_events = {} + mesecon._test_autoconnects = {} +end + +mineunit:execute_globalstep(mesecon.setting("resumetime", 4) + 1) diff --git a/.test_fixtures/mesecons_fpga.lua b/.test_fixtures/mesecons_fpga.lua new file mode 100644 index 0000000..ba4440a --- /dev/null +++ b/.test_fixtures/mesecons_fpga.lua @@ -0,0 +1,59 @@ +mineunit("player") + +fixture("mesecons") +fixture("mesecons_gamecompat") + +local registered_on_player_receive_fields = {} +local old_register_on_player_receive_fields = minetest.register_on_player_receive_fields +function minetest.register_on_player_receive_fields(func) + old_register_on_player_receive_fields(func) + table.insert(registered_on_player_receive_fields, func) +end + +mineunit:set_current_modname("mesecons_fpga") +mineunit:set_modpath("mesecons_fpga", "../mesecons_fpga") +sourcefile("../mesecons_fpga/init") + +local fpga_user = Player("mesecons_fpga_user") + +function mesecon._test_program_fpga(pos, program) + local node = minetest.get_node(pos) + assert.equal("mesecons_fpga:fpga", node.name:sub(1, 18)) + + local fields = {program = true} + for i, instr in ipairs(program) do + -- Translate the instruction into formspec fields. + local op1, act, op2, dst + if #instr == 3 then + act, op2, dst = unpack(instr) + else + assert.equal(4, #instr) + op1, act, op2, dst = unpack(instr) + end + fields[i .. "op1"] = op1 + fields[i .. "act"] = (" "):rep(4 - #act) .. act + fields[i .. "op2"] = op2 + fields[i .. "dst"] = dst + end + + minetest.registered_nodes[node.name].on_rightclick(pos, node, fpga_user) + + for _, func in ipairs(registered_on_player_receive_fields) do + if func(fpga_user, "mesecons:fpga", fields) then + break + end + end +end + +function mesecon._test_copy_fpga_program(pos) + fpga_user:get_inventory():set_stack("main", 1, "mesecons_fpga:programmer") + local pt = {type = "node", under = vector.new(pos), above = vector.offset(pos, 0, 1, 0)} + fpga_user:do_place(pt) + return fpga_user:get_wielded_item() +end + +function mesecon._test_paste_fpga_program(pos, tool) + fpga_user:get_inventory():set_stack("main", 1, tool) + local pt = {type = "node", under = vector.new(pos), above = vector.offset(pos, 0, 1, 0)} + fpga_user:do_use(pt) +end diff --git a/.test_fixtures/mesecons_gamecompat.lua b/.test_fixtures/mesecons_gamecompat.lua new file mode 100644 index 0000000..07bffd0 --- /dev/null +++ b/.test_fixtures/mesecons_gamecompat.lua @@ -0,0 +1,5 @@ +fixture("mesecons") + +mineunit:set_current_modname("mesecons_gamecompat") +mineunit:set_modpath("mesecons_gamecompat", "../mesecons_gamecompat") +sourcefile("../mesecons_gamecompat/init") diff --git a/.test_fixtures/mesecons_luacontroller.lua b/.test_fixtures/mesecons_luacontroller.lua new file mode 100644 index 0000000..9090b47 --- /dev/null +++ b/.test_fixtures/mesecons_luacontroller.lua @@ -0,0 +1,12 @@ +fixture("mesecons") +fixture("mesecons_gamecompat") + +mineunit:set_current_modname("mesecons_luacontroller") +mineunit:set_modpath("mesecons_luacontroller", "../mesecons_luacontroller") +sourcefile("../mesecons_luacontroller/init") + +function mesecon._test_program_luac(pos, code) + local node = minetest.get_node(pos) + assert.equal("mesecons_luacontroller:luacontroller", node.name:sub(1, 36)) + return minetest.registered_nodes[node.name].mesecons.luacontroller.set_program(pos, code) +end diff --git a/.test_fixtures/mesecons_mvps.lua b/.test_fixtures/mesecons_mvps.lua new file mode 100644 index 0000000..b15774c --- /dev/null +++ b/.test_fixtures/mesecons_mvps.lua @@ -0,0 +1,45 @@ +mineunit("protection") + +fixture("mesecons") + +mineunit:set_current_modname("mesecons_mvps") +mineunit:set_modpath("mesecons_mvps", "../mesecons_mvps") +sourcefile("../mesecons_mvps/init") + +minetest.register_node("mesecons_mvps:test_stopper", { + description = "Test Stopper", +}) +mesecon.register_mvps_stopper("mesecons_mvps:test_stopper") + +minetest.register_node("mesecons_mvps:test_stopper_cond", { + description = "Test Stopper (Conditional)", +}) +mesecon.register_mvps_stopper("mesecons_mvps:test_stopper_cond", function(node) + return node.param2 == 0 +end) + +minetest.register_node("mesecons_mvps:test_sticky", { + description = "Test Sticky", + mvps_sticky = function(pos) + local connected = {} + for i, rule in ipairs(mesecon.rules.alldirs) do + connected[i] = vector.add(pos, rule) + end + return connected + end, +}) + +mesecon._test_moves = {} +minetest.register_node("mesecons_mvps:test_on_move", { + description = "Test Moveable", + mesecon = { + on_mvps_move = function(pos, node, oldpos, meta) + table.insert(mesecon._test_moves, {pos, node, oldpos, meta}) + end + }, +}) +local old_reset = mesecon._test_reset +function mesecon._test_reset() + mesecon._test_moves = {} + old_reset() +end diff --git a/.test_fixtures/screwdriver.lua b/.test_fixtures/screwdriver.lua new file mode 100644 index 0000000..1a98de0 --- /dev/null +++ b/.test_fixtures/screwdriver.lua @@ -0,0 +1,6 @@ +mineunit:set_current_modname("screwdriver") + +screwdriver = {} + +screwdriver.ROTATE_FACE = 1 +screwdriver.ROTATE_AXIS = 2 diff --git a/mesecons/init.lua b/mesecons/init.lua index 83e611b..3446004 100644 --- a/mesecons/init.lua +++ b/mesecons/init.lua @@ -99,7 +99,6 @@ mesecon.queue:add_function("receptor_off", function (pos, rules) 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 @@ -118,8 +117,6 @@ function mesecon.receptor_off(pos, rules) end -print("[OK] Mesecons") - -- Deprecated stuff -- To be removed in future releases dofile(minetest.get_modpath("mesecons").."/legacy.lua"); diff --git a/mesecons/internal.lua b/mesecons/internal.lua index 6f52b44..a28c430 100644 --- a/mesecons/internal.lua +++ b/mesecons/internal.lua @@ -542,9 +542,12 @@ function mesecon.turnoff(pos, link) end for _, sig in ipairs(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) + -- If sig.depth is 1, it has not yet been checked that the power source is actually off. + if sig.depth > 1 or not mesecon.is_powered(sig.pos, sig.link) then + 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 end diff --git a/mesecons/locale/mesecons.eo.tr b/mesecons/locale/mesecons.eo.tr new file mode 100644 index 0000000..76961f0 --- /dev/null +++ b/mesecons/locale/mesecons.eo.tr @@ -0,0 +1,4 @@ +# textdomain: mesecons + +### oldwires.lua ### +Mesecons=Mesekonduktilo diff --git a/mesecons/locale/template.txt b/mesecons/locale/template.txt new file mode 100644 index 0000000..ca5f5d1 --- /dev/null +++ b/mesecons/locale/template.txt @@ -0,0 +1,4 @@ +# textdomain: mesecons + +### oldwires.lua ### +Mesecons= diff --git a/mesecons/oldwires.lua b/mesecons/oldwires.lua index 28dd4ec..dfbe067 100644 --- a/mesecons/oldwires.lua +++ b/mesecons/oldwires.lua @@ -1,3 +1,5 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + minetest.register_node("mesecons:mesecon_off", { drawtype = "raillike", tiles = {"jeija_mesecon_off.png", "jeija_mesecon_curved_off.png", "jeija_mesecon_t_junction_off.png", "jeija_mesecon_crossing_off.png"}, @@ -11,7 +13,7 @@ minetest.register_node("mesecons:mesecon_off", { fixed = {-0.5, -0.5, -0.5, 0.5, -0.45, 0.5}, }, groups = {dig_immediate=3, mesecon=1, mesecon_conductor_craftable=1}, - description="Mesecons", + description= S("Mesecons"), mesecons = {conductor={ state = mesecon.state.off, onstate = "mesecons:mesecon_on" diff --git a/mesecons/presets.lua b/mesecons/presets.lua index e10dd36..bf16d99 100644 --- a/mesecons/presets.lua +++ b/mesecons/presets.lua @@ -64,6 +64,8 @@ local rules_buttonlike = { } local function rules_from_dir(ruleset, dir) + if not dir then return {} end + 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 diff --git a/mesecons/spec/action_spec.lua b/mesecons/spec/action_spec.lua new file mode 100644 index 0000000..55f75d8 --- /dev/null +++ b/mesecons/spec/action_spec.lua @@ -0,0 +1,62 @@ +require("mineunit") + +fixture("mesecons") + +describe("action queue", function() + local layout = { + {{x = 1, y = 0, z = 0}, "mesecons:test_receptor_off"}, + {{x = 0, y = 0, z = 0}, "mesecons:test_conductor_off"}, + {{x = -1, y = 0, z = 0}, "mesecons:test_conductor_off"}, + {{x = 0, y = 1, z = 0}, "mesecons:test_effector"}, + {{x = -1, y = 1, z = 0}, "mesecons:test_effector"}, + } + + before_each(function() + world.layout(layout) + end) + + after_each(function() + mesecon._test_reset() + world.clear() + end) + + it("executes in order", function() + world.set_node(layout[1][1], "mesecons:test_receptor_on") + mesecon.receptor_on(layout[1][1], mesecon.rules.alldirs) + mineunit:execute_globalstep() -- Execute receptor_on action + mineunit:execute_globalstep() -- Execute activate/change actions + assert.equal(2, #mesecon._test_effector_events) + assert.same({"on", layout[4][1]}, mesecon._test_effector_events[1]) + assert.same({"on", layout[5][1]}, mesecon._test_effector_events[2]) + + world.set_node(layout[1][1], "mesecons:test_receptor_off") + mesecon.receptor_off(layout[1][1], mesecon.rules.alldirs) + mineunit:execute_globalstep() -- Execute receptor_off action + mineunit:execute_globalstep() -- Execute deactivate/change actions + assert.equal(4, #mesecon._test_effector_events) + assert.same({"off", layout[4][1]}, mesecon._test_effector_events[3]) + assert.same({"off", layout[5][1]}, mesecon._test_effector_events[4]) + end) + + it("discards outdated/overwritten node events", function() + world.set_node(layout[1][1], "mesecons:test_receptor_on") + mesecon.receptor_on(layout[1][1], mesecon.rules.alldirs) + world.set_node(layout[1][1], "mesecons:test_receptor_off") + mesecon.receptor_off(layout[1][1], mesecon.rules.alldirs) + mineunit:execute_globalstep() -- Execute receptor_off action + mineunit:execute_globalstep() -- Execute deactivate/change actions + assert.equal(0, #mesecon._test_effector_events) + end) + + it("delays actions", function() + world.set_node(layout[1][1], "mesecons:test_receptor_on") + mesecon.queue:add_action(layout[1][1], "receptor_on", {mesecon.rules.alldirs}, 1, nil) + mineunit:execute_globalstep(0.1) + mineunit:execute_globalstep(1) + assert.equal(0, #mesecon._test_effector_events) + mineunit:execute_globalstep() -- Execute receptor_on action + assert.equal(0, #mesecon._test_effector_events) + mineunit:execute_globalstep() -- Execute activate/change actions + assert.equal(2, #mesecon._test_effector_events) + end) +end) diff --git a/mesecons/spec/mineunit.conf b/mesecons/spec/mineunit.conf new file mode 100644 index 0000000..81bd36c --- /dev/null +++ b/mesecons/spec/mineunit.conf @@ -0,0 +1 @@ +fixture_paths = {"../.test_fixtures"} diff --git a/mesecons/spec/service_spec.lua b/mesecons/spec/service_spec.lua new file mode 100644 index 0000000..7b6fa0a --- /dev/null +++ b/mesecons/spec/service_spec.lua @@ -0,0 +1,192 @@ +require("mineunit") + +fixture("mesecons") +fixture("screwdriver") + +describe("placement/digging service", function() + local layout = { + {{x = 1, y = 0, z = 0}, "mesecons:test_receptor_on"}, + {{x = 0, y = 0, z = 0}, "mesecons:test_conductor_on"}, + {{x = -1, y = 0, z = 0}, "mesecons:test_conductor_on"}, + {{x = 0, y = 1, z = 0}, "mesecons:test_effector"}, + {{x = -2, y = 0, z = 0}, "mesecons:test_effector"}, + {{x = 2, y = 0, z = 0}, "mesecons:test_effector"}, + } + + before_each(function() + world.layout(layout) + end) + + after_each(function() + mesecon._test_reset() + world.clear() + end) + + it("updates components when a receptor changes", function() + -- Dig then replace a receptor and check that the connected effectors changed. + + mesecon._test_dig(layout[1][1]) + mineunit:execute_globalstep() -- Execute receptor_off action + assert.equal("mesecons:test_conductor_off", world.get_node(layout[2][1]).name) + mineunit:execute_globalstep() -- Execute deactivate/change actions + assert.equal(3, #mesecon._test_effector_events) + + mesecon._test_place(layout[1][1], "mesecons:test_receptor_on") + mineunit:execute_globalstep() -- Execute receptor_on action + assert.equal("mesecons:test_conductor_on", world.get_node(layout[2][1]).name) + mineunit:execute_globalstep() -- Execute activate/change action + assert.equal(6, #mesecon._test_effector_events) + end) + + it("updates components when a conductor changes", function() + -- Dig then replace a powered conductor and check that the connected effectors changed. + + mesecon._test_dig(layout[2][1]) + mineunit:execute_globalstep() -- Execute receptor_off action + assert.equal("mesecons:test_conductor_off", world.get_node(layout[3][1]).name) + mineunit:execute_globalstep() -- Execute deactivate/change actions + assert.equal(2, #mesecon._test_effector_events) + + mesecon._test_place(layout[2][1], "mesecons:test_conductor_off") + assert.equal("mesecons:test_conductor_on", world.get_node(layout[2][1]).name) + assert.equal("mesecons:test_conductor_on", world.get_node(layout[3][1]).name) + mineunit:execute_globalstep() -- Execute activate/change actions + assert.equal(4, #mesecon._test_effector_events) + end) + + it("updates effectors on placement", function() + local pos = {x = 0, y = 0, z = 1} + mesecon._test_place(pos, "mesecons:test_effector") + mineunit:execute_globalstep() -- Execute activate/change actions + assert.equal(tonumber("10100000", 2), world.get_node(pos).param2) + end) + + it("updates multiconductors on placement", function() + local pos = {x = 0, y = 0, z = 1} + mesecon._test_place(pos, "mesecons:test_multiconductor_off") + assert.equal("mesecons:test_multiconductor_010", world.get_node(pos).name) + end) + + it("turns off conductors on placement", function() + local pos = {x = 3, y = 0, z = 0} + mesecon._test_place(pos, "mesecons:test_conductor_on") + assert.equal("mesecons:test_conductor_off", world.get_node(pos).name) + end) + + it("turns off multiconductors on placement", function() + local pos = {x = 3, y = 0, z = 0} + mesecon._test_place(pos, "mesecons:test_multiconductor_on") + assert.equal("mesecons:test_multiconductor_off", world.get_node(pos).name) + end) + + it("triggers autoconnect hooks", function() + mesecon._test_dig(layout[2][1]) + mineunit:execute_globalstep() -- Execute delayed hook + assert.equal(1, #mesecon._test_autoconnects) + + mesecon._test_place(layout[2][1], layout[2][2]) + assert.equal(2, #mesecon._test_autoconnects) + end) +end) + +describe("overheating service", function() + local layout = { + {{x = 0, y = 0, z = 0}, "mesecons:test_receptor_off"}, + {{x = 1, y = 0, z = 0}, "mesecons:test_effector"}, + {{x = 2, y = 0, z = 0}, "mesecons:test_receptor_on"}, + } + + before_each(function() + world.layout(layout) + end) + + after_each(function() + mesecon._test_reset() + world.clear() + end) + + it("tracks heat", function() + mesecon.do_overheat(layout[2][1]) + assert.equal(1, mesecon.get_heat(layout[2][1])) + mesecon.do_cooldown(layout[2][1]) + assert.equal(0, mesecon.get_heat(layout[2][1])) + end) + + it("cools over time", function() + mesecon.do_overheat(layout[2][1]) + assert.equal(1, mesecon.get_heat(layout[2][1])) + mineunit:execute_globalstep(60) + mineunit:execute_globalstep(60) + mineunit:execute_globalstep(60) + assert.equal(0, mesecon.get_heat(layout[2][1])) + end) + + it("tracks movement", function() + local oldpos = layout[2][1] + local pos = vector.offset(oldpos, 0, 1, 0) + mesecon.do_overheat(oldpos) + mesecon.move_hot_nodes({{pos = pos, oldpos = oldpos}}) + assert.equal(0, mesecon.get_heat(oldpos)) + assert.equal(1, mesecon.get_heat(pos)) + end) + + it("causes overheating", function() + -- Switch the first receptor on and off until it overheats/breaks a receptor. + repeat + if mesecon.flipstate(layout[1][1], minetest.get_node(layout[1][1])) == "on" then + mesecon.receptor_on(layout[1][1], mesecon.rules.alldirs) + else + mesecon.receptor_off(layout[1][1], mesecon.rules.alldirs) + end + mineunit:execute_globalstep(0) -- Execute receptor_on/receptor_off/activate/deactivate/change actions + until minetest.get_node(layout[2][1]).name ~= "mesecons:test_effector" + assert.same({"overheat", layout[2][1]}, mesecon._test_effector_events[#mesecon._test_effector_events]) + assert.equal(0, mesecon.get_heat(layout[2][1])) + end) +end) + +describe("screwdriver service", function() + local layout = { + {{x = 0, y = 0, z = 0}, "mesecons:test_conductor_rot_on"}, + {{x = 1, y = 0, z = 0}, "mesecons:test_receptor_on"}, + {{x = -1, y = 0, z = 0}, "mesecons:test_conductor_on"}, + {{x = 0, y = 0, z = 1}, "mesecons:test_receptor_on"}, + {{x = 0, y = 0, z = -1}, "mesecons:test_conductor_off"}, + } + + local function rotate(new_param2) + local pos = layout[1][1] + local node = world.get_node(pos) + local on_rotate = minetest.registered_nodes[node.name].on_rotate + on_rotate(pos, node, nil, screwdriver.ROTATE_FACE, new_param2) + end + + before_each(function() + world.layout(layout) + end) + + after_each(function() + mesecon._test_reset() + world.clear() + end) + + it("updates conductors", function() + -- Rotate a conductor and see that the circuit state changes. + rotate(1) + mineunit:execute_globalstep() -- Execute receptor_off action + assert.equal("mesecons:test_conductor_off", world.get_node(layout[3][1]).name) + assert.equal("mesecons:test_conductor_on", world.get_node(layout[5][1]).name) + rotate(2) + mineunit:execute_globalstep() -- Execute receptor_off action + assert.equal("mesecons:test_conductor_on", world.get_node(layout[3][1]).name) + assert.equal("mesecons:test_conductor_off", world.get_node(layout[5][1]).name) + rotate(3) + mineunit:execute_globalstep() -- Execute receptor_off action + assert.equal("mesecons:test_conductor_off", world.get_node(layout[3][1]).name) + assert.equal("mesecons:test_conductor_on", world.get_node(layout[5][1]).name) + rotate(0) + mineunit:execute_globalstep() -- Execute receptor_off action + assert.equal("mesecons:test_conductor_on", world.get_node(layout[3][1]).name) + assert.equal("mesecons:test_conductor_off", world.get_node(layout[5][1]).name) + end) +end) diff --git a/mesecons/spec/state_spec.lua b/mesecons/spec/state_spec.lua new file mode 100644 index 0000000..c66871b --- /dev/null +++ b/mesecons/spec/state_spec.lua @@ -0,0 +1,147 @@ +require("mineunit") + +fixture("mesecons") + +describe("state", function() + local layout = { + {{x = 1, y = 0, z = 0}, "mesecons:test_receptor_off"}, + {{x = 0, y = 1, z = 0}, "mesecons:test_receptor_off"}, + {{x = 0, y = 0, z = 0}, "mesecons:test_conductor_off"}, + {{x = -1, y = 0, z = 0}, "mesecons:test_effector"}, + {{x = 2, y = 0, z = 0}, "mesecons:test_effector"}, + {{x = 0, y = -1, z = 0}, "mesecons:test_effector"}, + } + + before_each(function() + world.layout(layout) + end) + + after_each(function() + mesecon._test_reset() + world.clear() + end) + + it("turns on", function() + world.set_node(layout[1][1], "mesecons:test_receptor_on") + mesecon.receptor_on(layout[1][1], mesecon.rules.alldirs) + mineunit:execute_globalstep() -- Execute receptor_on action + mineunit:execute_globalstep() -- Execute activate/change actions + assert.equal("mesecons:test_conductor_on", world.get_node(layout[3][1]).name) + assert.equal(tonumber("10000001", 2), world.get_node(layout[4][1]).param2) + assert.equal(tonumber("10000010", 2), world.get_node(layout[5][1]).param2) + assert.equal(tonumber("10000100", 2), world.get_node(layout[6][1]).param2) + + world.set_node(layout[2][1], "mesecons:test_receptor_on") + mesecon.receptor_on(layout[2][1], mesecon.rules.alldirs) + mineunit:execute_globalstep() -- Execute receptor_on action + mineunit:execute_globalstep() -- Execute activate/change actions + assert.equal("mesecons:test_conductor_on", world.get_node(layout[3][1]).name) + assert.equal(tonumber("10000001", 2), world.get_node(layout[4][1]).param2) + assert.equal(tonumber("10000010", 2), world.get_node(layout[5][1]).param2) + assert.equal(tonumber("10000100", 2), world.get_node(layout[6][1]).param2) + end) + + it("turns off", function() + world.set_node(layout[1][1], "mesecons:test_receptor_on") + world.set_node(layout[2][1], "mesecons:test_receptor_on") + mesecon.receptor_on(layout[1][1], mesecon.rules.alldirs) + mesecon.receptor_on(layout[2][1], mesecon.rules.alldirs) + mineunit:execute_globalstep() -- Execute receptor_on actions + + world.set_node(layout[1][1], "mesecons:test_receptor_off") + mesecon.receptor_off(layout[1][1], mesecon.rules.alldirs) + mineunit:execute_globalstep() -- Execute receptor_off and activate/change actions + mineunit:execute_globalstep() -- Execute deactivate/change actions + assert.equal("mesecons:test_conductor_on", world.get_node(layout[3][1]).name) + assert.equal(tonumber("10000001", 2), world.get_node(layout[4][1]).param2) + assert.equal(tonumber("00000000", 2), world.get_node(layout[5][1]).param2) + assert.equal(tonumber("10000100", 2), world.get_node(layout[6][1]).param2) + + world.set_node(layout[2][1], "mesecons:test_receptor_off") + mesecon.receptor_off(layout[2][1], mesecon.rules.alldirs) + mineunit:execute_globalstep() -- Execute receptor_off action + mineunit:execute_globalstep() -- Execute deactivate/change actions + assert.equal("mesecons:test_conductor_off", world.get_node(layout[3][1]).name) + assert.equal(tonumber("00000000", 2), world.get_node(layout[4][1]).param2) + assert.equal(tonumber("00000000", 2), world.get_node(layout[5][1]).param2) + assert.equal(tonumber("00000000", 2), world.get_node(layout[6][1]).param2) + end) +end) + +describe("rotation", function() + local layout = { + {{x = 0, y = 0, z = 0}, "mesecons:test_receptor_off"}, + {{x = 1, y = 0, z = 0}, {name = "mesecons:test_conductor_rot_off", param2 = 0}}, + {{x = 0, y = 0, z = 1}, {name = "mesecons:test_conductor_rot_off", param2 = 1}}, + {{x = -1, y = 0, z = 0}, {name = "mesecons:test_conductor_rot_off", param2 = 2}}, + {{x = 0, y = 0, z = -1}, {name = "mesecons:test_conductor_rot_off", param2 = 3}}, + } + + before_each(function() + for _, entry in ipairs(layout) do + world.set_node(entry[1], entry[2]) + end + end) + + after_each(function() + mesecon._test_reset() + world.clear() + end) + + it("works", function() + world.set_node(layout[1][1], "mesecons:test_receptor_on") + mesecon.receptor_on(layout[1][1], mesecon.rules.alldirs) + mineunit:execute_globalstep() -- Execute receptor_on action + assert.equal("mesecons:test_conductor_rot_on", world.get_node(layout[2][1]).name) + assert.equal("mesecons:test_conductor_rot_on", world.get_node(layout[3][1]).name) + assert.equal("mesecons:test_conductor_rot_on", world.get_node(layout[4][1]).name) + assert.equal("mesecons:test_conductor_rot_on", world.get_node(layout[5][1]).name) + end) +end) + +describe("multiconductor", function() + local layout = { + {{x = 1, y = 0, z = 0}, "mesecons:test_receptor_off"}, + {{x = 0, y = 1, z = 0}, "mesecons:test_receptor_off"}, + {{x = 0, y = 0, z = 1}, "mesecons:test_receptor_off"}, + {{x = 0, y = 0, z = 0}, "mesecons:test_multiconductor_off"}, + } + + before_each(function() + world.layout(layout) + end) + + after_each(function() + world.clear() + mesecon._test_reset() + end) + + it("separates its subparts", function() + world.set_node(layout[1][1], "mesecons:test_receptor_on") + mesecon.receptor_on(layout[1][1], mesecon.rules.alldirs) + mineunit:execute_globalstep() -- Execute receptor_on action + assert.equal("mesecons:test_multiconductor_001", world.get_node(layout[4][1]).name) + + world.set_node(layout[2][1], "mesecons:test_receptor_on") + mesecon.receptor_on(layout[2][1], mesecon.rules.alldirs) + mineunit:execute_globalstep() -- Execute receptor_on action + assert.equal("mesecons:test_multiconductor_011", world.get_node(layout[4][1]).name) + + world.set_node(layout[3][1], "mesecons:test_receptor_on") + mesecon.receptor_on(layout[3][1], mesecon.rules.alldirs) + mineunit:execute_globalstep() -- Execute receptor_on action + assert.equal("mesecons:test_multiconductor_on", world.get_node(layout[4][1]).name) + end) + + it("loops through itself", function() + -- Make a loop. + world.set_node({x = 0, y = -1, z = 0}, "mesecons:test_conductor_off") + world.set_node({x = -1, y = -1, z = 0}, "mesecons:test_conductor_off") + world.set_node({x = -1, y = 0, z = 0}, "mesecons:test_conductor_off") + + world.set_node(layout[1][1], "mesecons:test_receptor_on") + mesecon.receptor_on(layout[1][1], mesecon.rules.alldirs) + mineunit:execute_globalstep() -- Execute receptor_on action + assert.equal("mesecons:test_multiconductor_101", world.get_node(layout[4][1]).name) + end) +end) diff --git a/mesecons_blinkyplant/init.lua b/mesecons_blinkyplant/init.lua index 28cb054..44dd3ff 100644 --- a/mesecons_blinkyplant/init.lua +++ b/mesecons_blinkyplant/init.lua @@ -1,5 +1,7 @@ -- The BLINKY_PLANT +local S = minetest.get_translator(minetest.get_current_modname()) + local toggle_timer = function (pos) local timer = minetest.get_node_timer(pos) if timer:is_started() then @@ -20,7 +22,7 @@ local on_timer = function (pos) end mesecon.register_node("mesecons_blinkyplant:blinky_plant", { - description="Blinky Plant", + description= S("Blinky Plant"), drawtype = "plantlike", inventory_image = "jeija_blinky_plant_off.png", paramtype = "light", diff --git a/mesecons_blinkyplant/locale/mesecons_blinkyplant.eo.tr b/mesecons_blinkyplant/locale/mesecons_blinkyplant.eo.tr new file mode 100644 index 0000000..db628ba --- /dev/null +++ b/mesecons_blinkyplant/locale/mesecons_blinkyplant.eo.tr @@ -0,0 +1,4 @@ +# textdomain: mesecons_blinkyplant + +### init.lua ### +Blinky Plant=Palpebruma Planto diff --git a/mesecons_blinkyplant/locale/template.txt b/mesecons_blinkyplant/locale/template.txt new file mode 100644 index 0000000..e2f5e44 --- /dev/null +++ b/mesecons_blinkyplant/locale/template.txt @@ -0,0 +1,4 @@ +# textdomain: mesecons_blinkyplant + +### init.lua ### +Blinky Plant= diff --git a/mesecons_button/init.lua b/mesecons_button/init.lua index 7c70923..878a6e1 100644 --- a/mesecons_button/init.lua +++ b/mesecons_button/init.lua @@ -1,6 +1,7 @@ -- WALL BUTTON -- A button that when pressed emits power for 1 second -- and then turns off again +local S = minetest.get_translator(minetest.get_current_modname()) mesecon.button_turnoff = function (pos) local node = minetest.get_node(pos) @@ -45,7 +46,7 @@ minetest.register_node("mesecons_button:button_off", { } }, groups = {dig_immediate=2, mesecon_needs_receiver = 1}, - description = "Button", + description = S("Button"), on_rightclick = function (pos, node) minetest.swap_node(pos, {name = "mesecons_button:button_on", param2=node.param2}) mesecon.receptor_on(pos, mesecon.rules.buttonlike_get(node)) @@ -92,7 +93,7 @@ minetest.register_node("mesecons_button:button_on", { }, groups = {dig_immediate=2, not_in_creative_inventory=1, mesecon_needs_receiver = 1}, drop = 'mesecons_button:button_off', - description = "Button", + description = S("Button"), sounds = mesecon.node_sound.stone, mesecons = {receptor = { state = mesecon.state.on, diff --git a/mesecons_button/locale/mesecons_button.eo.tr b/mesecons_button/locale/mesecons_button.eo.tr new file mode 100644 index 0000000..463f65b --- /dev/null +++ b/mesecons_button/locale/mesecons_button.eo.tr @@ -0,0 +1,4 @@ +# textdomain: mesecons_button + +### init.lua ### +Button=Butono diff --git a/mesecons_button/locale/template.txt b/mesecons_button/locale/template.txt new file mode 100644 index 0000000..2a4d5b9 --- /dev/null +++ b/mesecons_button/locale/template.txt @@ -0,0 +1,4 @@ +# textdomain: mesecons_button + +### init.lua ### +Button= diff --git a/mesecons_commandblock/init.lua b/mesecons_commandblock/init.lua index c96cfe8..63fa702 100644 --- a/mesecons_commandblock/init.lua +++ b/mesecons_commandblock/init.lua @@ -1,6 +1,8 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + minetest.register_chatcommand("say", { params = "", - description = "Say as the server", + description = S("Say as the server"), privs = {server=true}, func = function(name, param) minetest.chat_send_all(name .. ": " .. param) @@ -9,7 +11,7 @@ minetest.register_chatcommand("say", { minetest.register_chatcommand("tell", { params = " ", - description = "Say to privately", + description = S("Say to privately"), privs = {shout=true}, func = function(name, param) local found, _, target, message = param:find("^([^%s]+)%s+(.*)$") @@ -26,7 +28,7 @@ minetest.register_chatcommand("tell", { minetest.register_chatcommand("hp", { params = " ", - description = "Set health of to hitpoints", + description = S("Set health of to hitpoints"), privs = {ban=true}, func = function(name, param) local found, _, target, value = param:find("^([^%s]+)%s+(%d+)$") @@ -180,7 +182,7 @@ local function can_dig(pos, player) end minetest.register_node("mesecons_commandblock:commandblock_off", { - description = "Command Block", + description = S("Command Block"), tiles = {"jeija_commandblock_off.png"}, inventory_image = minetest.inventorycube("jeija_commandblock_off.png"), is_ground_content = false, diff --git a/mesecons_commandblock/locale/mesecons_commandblock.eo.tr b/mesecons_commandblock/locale/mesecons_commandblock.eo.tr new file mode 100644 index 0000000..3a9f077 --- /dev/null +++ b/mesecons_commandblock/locale/mesecons_commandblock.eo.tr @@ -0,0 +1,7 @@ +# textdomain: mesecons_commandblock + +### init.lua ### +Say as the server=Diru kiel la servilo +Say to privately=Diru al private +Set health of to hitpoints=Agordu sanon de al +Command Block=Komando-Bloko diff --git a/mesecons_commandblock/locale/template.txt b/mesecons_commandblock/locale/template.txt new file mode 100644 index 0000000..1fdd37c --- /dev/null +++ b/mesecons_commandblock/locale/template.txt @@ -0,0 +1,7 @@ +# textdomain: mesecons_commandblock + +### init.lua ### +Say as the server= +Say to privately= +Set health of to hitpoints= +Command Block= diff --git a/mesecons_delayer/init.lua b/mesecons_delayer/init.lua index bd2eca8..2c4b0f4 100644 --- a/mesecons_delayer/init.lua +++ b/mesecons_delayer/init.lua @@ -1,3 +1,5 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + -- Function that get the input/output rules of the delayer local delayer_get_output_rules = mesecon.horiz_rules_getter({{x = 1, y = 0, z = 0}}) @@ -69,7 +71,7 @@ if i > 1 then end local off_state = { - description = "Delayer", + description = S("Delayer"), tiles = { "mesecons_delayer_off_"..tostring(i)..".png", "mesecons_delayer_bottom.png", @@ -112,7 +114,7 @@ minetest.register_node("mesecons_delayer:delayer_off_"..tostring(i), off_state) -- Activated delayer definition defaults local on_state = { - description = "You hacker you", + description = S("You hacker you"), tiles = { "mesecons_delayer_on_"..tostring(i)..".png", "mesecons_delayer_bottom.png", diff --git a/mesecons_delayer/locale/mesecons_delayer.eo.tr b/mesecons_delayer/locale/mesecons_delayer.eo.tr new file mode 100644 index 0000000..f6d4350 --- /dev/null +++ b/mesecons_delayer/locale/mesecons_delayer.eo.tr @@ -0,0 +1,5 @@ +# textdomain: mesecons_delayer + +### init.lua ### +Delayer=Prokrasto +You hacker you=Vi hakisto diff --git a/mesecons_delayer/locale/template.txt b/mesecons_delayer/locale/template.txt new file mode 100644 index 0000000..e5e06f2 --- /dev/null +++ b/mesecons_delayer/locale/template.txt @@ -0,0 +1,5 @@ +# textdomain: mesecons_delayer + +### init.lua ### +Delayer= +You hacker you= diff --git a/mesecons_detector/init.lua b/mesecons_detector/init.lua index d460936..d5e3c4f 100644 --- a/mesecons_detector/init.lua +++ b/mesecons_detector/init.lua @@ -1,3 +1,5 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + local side_texture = mesecon.texture.steel_block or "mesecons_detector_side.png" local GET_COMMAND = "GET" @@ -71,7 +73,7 @@ minetest.register_node("mesecons_detector:object_detector_off", { is_ground_content = false, walkable = true, groups = {cracky=3}, - description="Player Detector", + description= S("Player Detector"), mesecons = {receptor = { state = mesecon.state.off, rules = mesecon.rules.pplate @@ -247,7 +249,7 @@ minetest.register_node("mesecons_detector:node_detector_off", { is_ground_content = false, walkable = true, groups = {cracky=3}, - description="Node Detector", + description = S("Node Detector"), mesecons = {receptor = { state = mesecon.state.off }}, diff --git a/mesecons_detector/locale/mesecons_detector.eo.tr b/mesecons_detector/locale/mesecons_detector.eo.tr new file mode 100644 index 0000000..0db21e2 --- /dev/null +++ b/mesecons_detector/locale/mesecons_detector.eo.tr @@ -0,0 +1,5 @@ +# textdomain: mesecons_detector + +### init.lua ### +Player Detector=Ludanta Detektilo +Node Detector=Noda Detektilo diff --git a/mesecons_detector/locale/template.txt b/mesecons_detector/locale/template.txt new file mode 100644 index 0000000..1a8a6a7 --- /dev/null +++ b/mesecons_detector/locale/template.txt @@ -0,0 +1,5 @@ +# textdomain: mesecons_detector + +### init.lua ### +Player Detector= +Node Detector= diff --git a/mesecons_extrawires/corner.lua b/mesecons_extrawires/corner.lua index 45ed6f0..6d85b6b 100644 --- a/mesecons_extrawires/corner.lua +++ b/mesecons_extrawires/corner.lua @@ -1,3 +1,5 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + local corner_selectionbox = { type = "fixed", fixed = { -16/32, -16/32, -16/32, 5/32, -12/32, 5/32 }, @@ -36,7 +38,7 @@ minetest.register_node("mesecons_extrawires:corner_on", { minetest.register_node("mesecons_extrawires:corner_off", { drawtype = "mesh", - description = "Insulated Mesecon Corner", + description = S("Insulated Mesecon Corner"), mesh = "mesecons_extrawires_corner.obj", tiles = { { name = "jeija_insulated_wire_sides_off.png", backface_culling = true }, @@ -67,3 +69,9 @@ minetest.register_craft({ {"", "mesecons_insulated:insulated_off"}, } }) + +minetest.register_craft({ + output = "mesecons_insulated:insulated_off", + type = "shapeless", + recipe = {"mesecons_extrawires:corner_off"} +}) diff --git a/mesecons_extrawires/crossover.lua b/mesecons_extrawires/crossover.lua index bf7f0db..1001467 100644 --- a/mesecons_extrawires/crossover.lua +++ b/mesecons_extrawires/crossover.lua @@ -1,3 +1,5 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + local crossover_rules = { {--first wire {x=-1,y=0,z=0}, @@ -17,7 +19,7 @@ local crossover_states = { } minetest.register_node("mesecons_extrawires:crossover_off", { - description = "Insulated Mesecon Crossover", + description = S("Insulated Mesecon Crossover"), drawtype = "mesh", mesh = "mesecons_extrawires_crossover.b3d", tiles = { @@ -43,7 +45,7 @@ minetest.register_node("mesecons_extrawires:crossover_off", { }) minetest.register_node("mesecons_extrawires:crossover_01", { - description = "You hacker you!", + description = S("You hacker you!"), drop = "mesecons_extrawires:crossover_off", drawtype = "mesh", mesh = "mesecons_extrawires_crossover.b3d", @@ -70,7 +72,7 @@ minetest.register_node("mesecons_extrawires:crossover_01", { }) minetest.register_node("mesecons_extrawires:crossover_10", { - description = "You hacker you!", + description = S("You hacker you!"), drop = "mesecons_extrawires:crossover_off", drawtype = "mesh", mesh = "mesecons_extrawires_crossover.b3d", @@ -97,7 +99,7 @@ minetest.register_node("mesecons_extrawires:crossover_10", { }) minetest.register_node("mesecons_extrawires:crossover_on", { - description = "You hacker you!", + description = S("You hacker you!"), drop = "mesecons_extrawires:crossover_off", drawtype = "mesh", mesh = "mesecons_extrawires_crossover.b3d", diff --git a/mesecons_extrawires/doublecorner.lua b/mesecons_extrawires/doublecorner.lua index 4f8e839..36059e1 100644 --- a/mesecons_extrawires/doublecorner.lua +++ b/mesecons_extrawires/doublecorner.lua @@ -1,3 +1,5 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + local doublecorner_selectionbox = { type = "fixed", fixed = { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 }, @@ -31,7 +33,7 @@ for k, state in ipairs(doublecorner_states) do minetest.register_node(state, { drawtype = "mesh", mesh = "mesecons_extrawires_doublecorner.obj", - description = "Insulated Mesecon Double Corner", + description = S("Insulated Mesecon Double Corner"), tiles = { { name = "jeija_insulated_wire_sides_" .. w1 .. ".png", backface_culling = true }, { name = "jeija_insulated_wire_ends_" .. w1 .. ".png", backface_culling = true }, diff --git a/mesecons_extrawires/locale/mesecons_extrawires.eo.tr b/mesecons_extrawires/locale/mesecons_extrawires.eo.tr new file mode 100644 index 0000000..e8d8415 --- /dev/null +++ b/mesecons_extrawires/locale/mesecons_extrawires.eo.tr @@ -0,0 +1,20 @@ +# textdomain: mesecons_extrawires + +### corner.lua ### +Insulated Mesecon Corner=Izolita Mesekonduktila Angulo + +### crossover.lua ### +Insulated Mesecon Crossover=Izolita Mesekonduktila Interkruciĝo +You hacker you!=Vi hakisto + +### doublecorner.lua ### +Insulated Mesecon Double Corner=Izolita Mesekonduktila Duobla Angulo + +### mesewire.lua ### +Mese Wire=Mesea Drato + +### tjunction.lua ### +Insulated Mesecon T-junction=Izolita Mesekonduktila T-Kruciĝo + +### vertical.lua ### +Vertical Mesecon=Vertikala Mesekonduktilo diff --git a/mesecons_extrawires/locale/template.txt b/mesecons_extrawires/locale/template.txt new file mode 100644 index 0000000..44d3abb --- /dev/null +++ b/mesecons_extrawires/locale/template.txt @@ -0,0 +1,20 @@ +# textdomain: mesecons_extrawires + +### corner.lua ### +Insulated Mesecon Corner= + +### crossover.lua ### +Insulated Mesecon Crossover= +You hacker you!= + +### doublecorner.lua ### +Insulated Mesecon Double Corner= + +### mesewire.lua ### +Mese Wire= + +### tjunction.lua ### +Insulated Mesecon T-junction= + +### vertical.lua ### +Vertical Mesecon= diff --git a/mesecons_extrawires/mesewire.lua b/mesecons_extrawires/mesewire.lua index f74fdcb..cdb87a8 100644 --- a/mesecons_extrawires/mesewire.lua +++ b/mesecons_extrawires/mesewire.lua @@ -1,3 +1,5 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + local mese_nodename = minetest.registered_aliases["mesecons_gamecompat:mese"] if mese_nodename then -- Convert placeholders. @@ -6,7 +8,7 @@ else -- Register placeholder. mese_nodename = "mesecons_extrawires:mese" minetest.register_node("mesecons_extrawires:mese", { - description = "Mese Wire", + description = S("Mese Wire"), tiles = {"mesecons_wire_off.png"}, paramtype = "light", light_source = 3, diff --git a/mesecons_extrawires/tjunction.lua b/mesecons_extrawires/tjunction.lua index a69b14a..d6186f2 100644 --- a/mesecons_extrawires/tjunction.lua +++ b/mesecons_extrawires/tjunction.lua @@ -1,3 +1,5 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + local tjunction_nodebox = { type = "fixed", -- ±0.001 is to prevent z-fighting @@ -48,7 +50,7 @@ minetest.register_node("mesecons_extrawires:tjunction_on", { minetest.register_node("mesecons_extrawires:tjunction_off", { drawtype = "nodebox", - description = "Insulated Mesecon T-junction", + description = S("Insulated Mesecon T-junction"), tiles = { "jeija_insulated_wire_tjunction_tb_off.png", "jeija_insulated_wire_tjunction_tb_off.png^[transformR180", diff --git a/mesecons_extrawires/vertical.lua b/mesecons_extrawires/vertical.lua index 72084fc..9e132ac 100644 --- a/mesecons_extrawires/vertical.lua +++ b/mesecons_extrawires/vertical.lua @@ -1,3 +1,5 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + local vertical_box = { type = "fixed", fixed = {-1/16, -8/16, -1/16, 1/16, 8/16, 1/16} @@ -77,7 +79,7 @@ end -- Vertical wire mesecon.register_node("mesecons_extrawires:vertical", { - description = "Vertical Mesecon", + description = S("Vertical Mesecon"), drawtype = "nodebox", walkable = false, paramtype = "light", @@ -110,7 +112,7 @@ mesecon.register_node("mesecons_extrawires:vertical", { -- Vertical wire top mesecon.register_node("mesecons_extrawires:vertical_top", { - description = "Vertical mesecon", + description = S("Vertical Mesecon"), drawtype = "nodebox", walkable = false, paramtype = "light", @@ -142,7 +144,7 @@ mesecon.register_node("mesecons_extrawires:vertical_top", { -- Vertical wire bottom mesecon.register_node("mesecons_extrawires:vertical_bottom", { - description = "Vertical mesecon", + description = S("Vertical Mesecon"), drawtype = "nodebox", walkable = false, paramtype = "light", diff --git a/mesecons_fpga/init.lua b/mesecons_fpga/init.lua index 1898177..fe86ad4 100644 --- a/mesecons_fpga/init.lua +++ b/mesecons_fpga/init.lua @@ -1,3 +1,5 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + local plg = {} plg.rules = {} -- per-player formspec positions @@ -59,7 +61,7 @@ plg.register_nodes = function(template) end plg.register_nodes({ - description = "FPGA", + description = S("FPGA"), drawtype = "nodebox", tiles = { "", -- replaced later diff --git a/mesecons_fpga/locale/mesecons_fpga.eo.tr b/mesecons_fpga/locale/mesecons_fpga.eo.tr new file mode 100644 index 0000000..5ad42b1 --- /dev/null +++ b/mesecons_fpga/locale/mesecons_fpga.eo.tr @@ -0,0 +1,7 @@ +# textdomain: mesecons_fpga + +### init.lua ### +FPGA=FPGA + +### tool.lua ### +FPGA Programmer=FPGA Programilo diff --git a/mesecons_fpga/locale/template.txt b/mesecons_fpga/locale/template.txt new file mode 100644 index 0000000..5764150 --- /dev/null +++ b/mesecons_fpga/locale/template.txt @@ -0,0 +1,7 @@ +# textdomain: mesecons_fpga + +### init.lua ### +FPGA= + +### tool.lua ### +FPGA Programmer= diff --git a/mesecons_fpga/spec/helper_spec.lua b/mesecons_fpga/spec/helper_spec.lua new file mode 100644 index 0000000..5f71c03 --- /dev/null +++ b/mesecons_fpga/spec/helper_spec.lua @@ -0,0 +1,106 @@ +require("mineunit") + +fixture("mesecons_fpga") +fixture("screwdriver") + +local pos = {x = 0, y = 0, z = 0} +local pos_a = {x = -1, y = 0, z = 0} +local pos_b = {x = 0, y = 0, z = 1} +local pos_c = {x = 1, y = 0, z = 0} +local pos_d = {x = 0, y = 0, z = -1} + +describe("FPGA rotation", function() + before_each(function() + world.set_node(pos, "mesecons_fpga:fpga0000") + end) + + after_each(function() + mesecon._test_reset() + world.clear() + end) + + it("rotates I/O operands clockwise", function() + mesecon._test_program_fpga(pos, {{"A", "OR", "B", "C"}}) + + local node = world.get_node(pos) + minetest.registered_nodes[node.name].on_rotate(pos, node, nil, screwdriver.ROTATE_FACE) + + mesecon._test_place(pos_b, "mesecons:test_receptor_on") + mineunit:execute_globalstep() -- Execute receptor_on action + mineunit:execute_globalstep() -- Execute activate/change actions + assert.equal("mesecons_fpga:fpga1000", world.get_node(pos).name) + + mesecon._test_dig(pos_b) + mesecon._test_place(pos_c, "mesecons:test_receptor_on") + mineunit:execute_globalstep() -- Execute receptor_on/receptor_off actions + mineunit:execute_globalstep() -- Execute activate/deactivate/change actions + assert.equal("mesecons_fpga:fpga1000", world.get_node(pos).name) + end) + + it("rotates I/O operands counterclockwise", function() + mesecon._test_program_fpga(pos, {{"A", "OR", "B", "C"}}) + + local node = world.get_node(pos) + minetest.registered_nodes[node.name].on_rotate(pos, node, nil, screwdriver.ROTATE_AXIS) + + mesecon._test_place(pos_d, "mesecons:test_receptor_on") + mineunit:execute_globalstep() -- Execute receptor_on action + mineunit:execute_globalstep() -- Execute activate/change actions + assert.equal("mesecons_fpga:fpga0010", world.get_node(pos).name) + + mesecon._test_dig(pos_d) + mesecon._test_place(pos_a, "mesecons:test_receptor_on") + mineunit:execute_globalstep() -- Execute receptor_on/receptor_off actions + mineunit:execute_globalstep() -- Execute activate/deactivate/change actions + assert.equal("mesecons_fpga:fpga0010", world.get_node(pos).name) + end) + + it("updates ports", function() + mesecon._test_program_fpga(pos, {{"NOT", "A", "B"}}) + assert.equal("mesecons_fpga:fpga0010", world.get_node(pos).name) + + local node = world.get_node(pos) + minetest.registered_nodes[node.name].on_rotate(pos, node, nil, screwdriver.ROTATE_AXIS) + assert.equal("mesecons_fpga:fpga0001", world.get_node(pos).name) + end) +end) + +describe("FPGA programmer", function() + local pos2 = {x = 10, y = 0, z = 0} + + before_each(function() + world.set_node(pos, "mesecons_fpga:fpga0000") + world.set_node(pos2, "mesecons_fpga:fpga0000") + end) + + after_each(function() + mesecon._test_reset() + world.clear() + end) + + it("transfers instructions", function() + mesecon._test_program_fpga(pos2, {{"NOT", "A", "B"}}) + mesecon._test_paste_fpga_program(pos, mesecon._test_copy_fpga_program(pos2)) + assert.equal("mesecons_fpga:fpga0010", world.get_node(pos).name) + end) + + it("does not copy from new FPGAs", function() + mesecon._test_program_fpga(pos, {{"NOT", "A", "B"}}) + mesecon._test_paste_fpga_program(pos, mesecon._test_copy_fpga_program(pos2)) + assert.equal("mesecons_fpga:fpga0010", world.get_node(pos).name) + end) + + it("does not copy from cleared FPGAs", function() + mesecon._test_program_fpga(pos, {{"NOT", "A", "B"}}) + mesecon._test_program_fpga(pos2, {{"=", "A", "B"}}) + mesecon._test_program_fpga(pos2, {}) + mesecon._test_paste_fpga_program(pos, mesecon._test_copy_fpga_program(pos2)) + assert.equal("mesecons_fpga:fpga0010", world.get_node(pos).name) + end) + + it("does not copy from non-FPGA nodes", function() + mesecon._test_program_fpga(pos, {{"NOT", "A", "B"}}) + mesecon._test_paste_fpga_program(pos, mesecon._test_copy_fpga_program(vector.add(pos2, 1))) + assert.equal("mesecons_fpga:fpga0010", world.get_node(pos).name) + end) +end) diff --git a/mesecons_fpga/spec/logic_spec.lua b/mesecons_fpga/spec/logic_spec.lua new file mode 100644 index 0000000..73882dd --- /dev/null +++ b/mesecons_fpga/spec/logic_spec.lua @@ -0,0 +1,235 @@ +require("mineunit") + +fixture("mesecons_fpga") + +describe("FPGA logic", function() + local pos = {x = 0, y = 0, z = 0} + local pos_a = {x = -1, y = 0, z = 0} + local pos_b = {x = 0, y = 0, z = 1} + local pos_c = {x = 1, y = 0, z = 0} + local pos_d = {x = 0, y = 0, z = -1} + + local fpga_set = false + + local function set_fpga() + if not fpga_set then + world.set_node(pos, "mesecons_fpga:fpga0000") + fpga_set = true + end + end + before_each(set_fpga) + + local function reset_world() + if fpga_set then + mesecon._test_reset() + world.clear() + fpga_set = false + end + end + after_each(reset_world) + + local function test_program(inputs, outputs, program) + set_fpga() + + mesecon._test_program_fpga(pos, program) + + if inputs.a then mesecon._test_place(pos_a, "mesecons:test_receptor_on") end + if inputs.b then mesecon._test_place(pos_b, "mesecons:test_receptor_on") end + if inputs.c then mesecon._test_place(pos_c, "mesecons:test_receptor_on") end + if inputs.d then mesecon._test_place(pos_d, "mesecons:test_receptor_on") end + mineunit:execute_globalstep() -- Execute receptor_on actions + mineunit:execute_globalstep() -- Execute activate/change actions + + local expected_name = "mesecons_fpga:fpga" + .. (outputs.d and 1 or 0) .. (outputs.c and 1 or 0) + .. (outputs.b and 1 or 0) .. (outputs.a and 1 or 0) + assert.equal(expected_name, world.get_node(pos).name) + + reset_world() + end + + it("operator and", function() + local prog = {{"A", "AND", "B", "C"}} + test_program({}, {}, prog) + test_program({a = true}, {}, prog) + test_program({b = true}, {}, prog) + test_program({a = true, b = true}, {c = true}, prog) + end) + + it("operator or", function() + local prog = {{"A", "OR", "B", "C"}} + test_program({}, {}, prog) + test_program({a = true}, {c = true}, prog) + test_program({b = true}, {c = true}, prog) + test_program({a = true, b = true}, {c = true}, prog) + end) + + it("operator not", function() + local prog = {{"NOT", "A", "B"}} + test_program({}, {b = true}, prog) + test_program({a = true}, {}, prog) + end) + + it("operator xor", function() + local prog = {{"A", "XOR", "B", "C"}} + test_program({}, {}, prog) + test_program({a = true}, {c = true}, prog) + test_program({b = true}, {c = true}, prog) + test_program({a = true, b = true}, {}, prog) + end) + + it("operator nand", function() + local prog = {{"A", "NAND", "B", "C"}} + test_program({}, {c = true}, prog) + test_program({a = true}, {c = true}, prog) + test_program({b = true}, {c = true}, prog) + test_program({a = true, b = true}, {}, prog) + end) + + it("operator buf", function() + local prog = {{"=", "A", "B"}} + test_program({}, {}, prog) + test_program({a = true}, {b = true}, prog) + end) + + it("operator xnor", function() + local prog = {{"A", "XNOR", "B", "C"}} + test_program({}, {c = true}, prog) + test_program({a = true}, {}, prog) + test_program({b = true}, {}, prog) + test_program({a = true, b = true}, {c = true}, prog) + end) + + it("operator nor", function() + local prog = {{"A", "NOR", "B", "C"}} + test_program({}, {c = true}, prog) + test_program({a = true}, {}, prog) + test_program({b = true}, {}, prog) + test_program({a = true, b = true}, {}, prog) + end) + + it("rejects duplicate operands", function() + test_program({a = true}, {}, {{"A", "OR", "A", "B"}}) + test_program({a = true}, {}, {{"=", "A", "0"}, {"0", "OR", "0", "B"}}) + end) + + it("rejects unassigned memory operands", function() + test_program({a = true}, {}, {{"A", "OR", "0", "B"}}) + test_program({a = true}, {}, {{"0", "OR", "A", "B"}}) + end) + + it("rejects double memory assignment", function() + test_program({a = true}, {}, {{"=", "A", "0"}, {"=", "A", "0"}, {"=", "0", "B"}}) + end) + + it("rejects assignment to memory operand", function() + test_program({a = true}, {}, {{"=", "A", "0"}, {"A", "OR", "0", "0"}, {"=", "0", "B"}}) + end) + + it("allows double port assignment", function() + test_program({a = true}, {b = true}, {{"NOT", "A", "B"}, {"=", "A", "B"}}) + end) + + it("allows assignment to port operand", function() + test_program({a = true}, {b = true}, {{"A", "OR", "B", "B"}}) + end) + + it("preserves initial pin states", function() + test_program({a = true}, {b = true}, {{"=", "A", "B"}, {"=", "B", "C"}}) + end) + + it("rejects binary operations with single operands", function() + test_program({a = true}, {}, {{"=", "A", "B"}, {" ", "OR", "A", "C"}}) + test_program({a = true}, {}, {{"=", "A", "B"}, {"A", "OR", " ", "C"}}) + end) + + it("rejects unary operations with first operands", function() + test_program({a = true}, {}, {{"=", "A", "B"}, {"A", "=", " ", "C"}}) + end) + + it("rejects operations without destinations", function() + test_program({a = true}, {}, {{"=", "A", "B"}, {"=", "A", " "}}) + end) + + it("allows blank statements", function() + test_program({a = true}, {b = true, c = true}, { + {" ", " ", " ", " "}, + {"=", "A", "B"}, + {" ", " ", " ", " "}, + {" ", " ", " ", " "}, + {"=", "A", "C"}, + }) + end) + + it("transmits output signals to adjacent nodes", function() + mesecon._test_program_fpga(pos, { + {"=", "A", "B"}, + {"=", "A", "C"}, + {"NOT", "A", "D"}, + }) + mesecon._test_place(pos_b, "mesecons:test_effector") + mesecon._test_place(pos_c, "mesecons:test_effector") + mesecon._test_place(pos_d, "mesecons:test_effector") + mineunit:execute_globalstep() -- Execute receptor_on actions + mineunit:execute_globalstep() -- Execute activate/change actions + + -- Makes an object from the last three effector events in the list for use with assert.same. + -- This is necessary to ignore the ordering of events. + local function event_tester(list) + local o = {list[#list - 2], list[#list - 1], list[#list - 0]} + table.sort(o, function(a, b) + local fmt = "%s %d %d %d" + return fmt:format(a[1], a[2].x, a[2].y, a[2].z) < fmt:format(b[1], b[2].x, b[2].y, b[2].z) + end) + return o + end + + mesecon._test_place(pos_a, "mesecons:test_receptor_on") + mineunit:execute_globalstep() -- Execute receptor_on action + mineunit:execute_globalstep() -- Execute activate/change actions + mineunit:execute_globalstep() -- Execute receptor_on/receptor_off actions + mineunit:execute_globalstep() -- Execute activate/deactivate/change actions + assert.equal("mesecons_fpga:fpga0110", world.get_node(pos).name) + assert.same(event_tester({{"on", pos_b}, {"on", pos_c}, {"off", pos_d}}), event_tester(mesecon._test_effector_events)) + + mesecon._test_dig(pos_a) + mineunit:execute_globalstep() -- Execute receptor_off action + mineunit:execute_globalstep() -- Execute deactivate/change actions + mineunit:execute_globalstep() -- Execute receptor_on/receptor_off actions + mineunit:execute_globalstep() -- Execute activate/deactivate/change actions + assert.equal("mesecons_fpga:fpga1000", world.get_node(pos).name) + assert.same(event_tester({{"off", pos_b}, {"off", pos_c}, {"on", pos_d}}), event_tester(mesecon._test_effector_events)) + end) + + it("considers past outputs in determining inputs", function() + -- Memory cell: Turning on A turns on C; turning on B turns off C. + mesecon._test_program_fpga(pos, { + {"A", "OR", "C", "0"}, + {"B", "OR", "D", "1"}, + {"NOT", "A", "2"}, + {"NOT", "B", "3"}, + {"0", "AND", "3", "C"}, + {"1", "AND", "2", "D"}, + }) + + mesecon._test_place(pos_a, "mesecons:test_receptor_on") + mineunit:execute_globalstep() -- Execute receptor_on actions + mineunit:execute_globalstep() -- Execute activate/change actions + assert.equal("mesecons_fpga:fpga0100", world.get_node(pos).name) + + mesecon._test_dig(pos_a) + mineunit:execute_globalstep() -- Execute receptor_off actions + mineunit:execute_globalstep() -- Execute deactivate/change actions + assert.equal("mesecons_fpga:fpga0100", world.get_node(pos).name) + + mesecon._test_place(pos_b, "mesecons:test_receptor_on") + mineunit:execute_globalstep() -- Execute receptor_on actions + mineunit:execute_globalstep() -- Execute activate/change actions + assert.equal("mesecons_fpga:fpga1000", world.get_node(pos).name) + + mesecon._test_dig(pos_b) + mineunit:execute_globalstep() -- Execute receptor_off actions + mineunit:execute_globalstep() -- Execute deactivate/change actions + assert.equal("mesecons_fpga:fpga1000", world.get_node(pos).name) + end) +end) diff --git a/mesecons_fpga/spec/mineunit.conf b/mesecons_fpga/spec/mineunit.conf new file mode 100644 index 0000000..81bd36c --- /dev/null +++ b/mesecons_fpga/spec/mineunit.conf @@ -0,0 +1 @@ +fixture_paths = {"../.test_fixtures"} diff --git a/mesecons_fpga/tool.lua b/mesecons_fpga/tool.lua index 73d6c0f..e0aff3b 100644 --- a/mesecons_fpga/tool.lua +++ b/mesecons_fpga/tool.lua @@ -1,8 +1,10 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + return function(plg) minetest.register_tool("mesecons_fpga:programmer", { - description = "FPGA Programmer", + description = S("FPGA Programmer"), inventory_image = "jeija_fpga_programmer.png", stack_max = 1, on_place = function(itemstack, placer, pointed_thing) @@ -21,7 +23,7 @@ minetest.register_tool("mesecons_fpga:programmer", { minetest.sound_play("mesecons_fpga_fail", { pos = placer:get_pos(), gain = 0.1, max_hear_distance = 4 }, true) return itemstack end - itemstack:set_metadata(meta:get_string("instr")) + itemstack:get_meta():set_string("", meta:get_string("instr")) minetest.chat_send_player(placer:get_player_name(), "FPGA gate configuration was successfully copied!") minetest.sound_play("mesecons_fpga_copy", { pos = placer:get_pos(), gain = 0.1, max_hear_distance = 4 }, true) @@ -42,7 +44,7 @@ minetest.register_tool("mesecons_fpga:programmer", { return itemstack end - local imeta = itemstack:get_metadata() + local imeta = itemstack:get_meta():get_string("") if imeta == "" then minetest.chat_send_player(player_name, "Use shift+right-click to copy a gate configuration first.") minetest.sound_play("mesecons_fpga_fail", { pos = user:get_pos(), gain = 0.1, max_hear_distance = 4 }, true) diff --git a/mesecons_hydroturbine/init.lua b/mesecons_hydroturbine/init.lua index 1993d87..6d0038c 100644 --- a/mesecons_hydroturbine/init.lua +++ b/mesecons_hydroturbine/init.lua @@ -1,3 +1,5 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + -- HYDRO_TURBINE -- Water turbine: -- Active if flowing >water< above it @@ -17,7 +19,7 @@ minetest.register_node("mesecons_hydroturbine:hydro_turbine_off", { is_ground_content = false, wield_scale = {x=0.75, y=0.75, z=0.75}, groups = {dig_immediate=2}, - description="Water Turbine", + description = S("Water Turbine"), paramtype = "light", selection_box = { type = "fixed", @@ -47,7 +49,7 @@ minetest.register_node("mesecons_hydroturbine:hydro_turbine_on", { inventory_image = "jeija_hydro_turbine_inv.png", drop = "mesecons_hydroturbine:hydro_turbine_off 1", groups = {dig_immediate=2,not_in_creative_inventory=1}, - description="Water Turbine", + description = S("Water Turbine"), paramtype = "light", selection_box = { type = "fixed", @@ -97,9 +99,8 @@ nodenames = {"mesecons_hydroturbine:hydro_turbine_on"}, minetest.register_craft({ output = "mesecons_hydroturbine:hydro_turbine_off 2", recipe = { - {"","grup:stick", ""}, + {"","group:stick", ""}, {"group:stick", "mesecons_gamecompat:steel_ingot", "group:stick"}, {"","group:stick", ""}, } }) - diff --git a/mesecons_hydroturbine/locale/mesecons_hydroturbine.eo.tr b/mesecons_hydroturbine/locale/mesecons_hydroturbine.eo.tr new file mode 100644 index 0000000..7ca3172 --- /dev/null +++ b/mesecons_hydroturbine/locale/mesecons_hydroturbine.eo.tr @@ -0,0 +1,4 @@ +# textdomain: mesecons_hydroturbine + +### init.lua ### +Water Turbine=Akva Turbino diff --git a/mesecons_hydroturbine/locale/template.txt b/mesecons_hydroturbine/locale/template.txt new file mode 100644 index 0000000..ebf8921 --- /dev/null +++ b/mesecons_hydroturbine/locale/template.txt @@ -0,0 +1,4 @@ +# textdomain: mesecons_hydroturbine + +### init.lua ### +Water Turbine= diff --git a/mesecons_insulated/init.lua b/mesecons_insulated/init.lua index f98565c..a805230 100644 --- a/mesecons_insulated/init.lua +++ b/mesecons_insulated/init.lua @@ -1,3 +1,5 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + local insulated_wire_get_rules = mesecon.horiz_rules_getter({ {x = 1, y = 0, z = 0}, {x = -1, y = 0, z = 0}, @@ -5,7 +7,7 @@ local insulated_wire_get_rules = mesecon.horiz_rules_getter({ minetest.register_node("mesecons_insulated:insulated_on", { drawtype = "nodebox", - description = "Straight Insulated Mesecon", + description = S("Straight Insulated Mesecon"), tiles = { "jeija_insulated_wire_sides_on.png", "jeija_insulated_wire_sides_on.png", @@ -42,7 +44,7 @@ minetest.register_node("mesecons_insulated:insulated_on", { minetest.register_node("mesecons_insulated:insulated_off", { drawtype = "nodebox", - description = "Straight Insulated Mesecon", + description = S("Straight Insulated Mesecon"), tiles = { "jeija_insulated_wire_sides_off.png", "jeija_insulated_wire_sides_off.png", diff --git a/mesecons_insulated/locale/mesecons_insulated.eo.tr b/mesecons_insulated/locale/mesecons_insulated.eo.tr new file mode 100644 index 0000000..878908b --- /dev/null +++ b/mesecons_insulated/locale/mesecons_insulated.eo.tr @@ -0,0 +1,4 @@ +# textdomain: mesecons_insulated + +### init.lua ### +Straight Insulated Mesecon=Rekta Izolita Mesekonduktilo diff --git a/mesecons_insulated/locale/template.txt b/mesecons_insulated/locale/template.txt new file mode 100644 index 0000000..8fbde4f --- /dev/null +++ b/mesecons_insulated/locale/template.txt @@ -0,0 +1,4 @@ +# textdomain: mesecons_insulated + +### init.lua ### +Straight Insulated Mesecon= diff --git a/mesecons_lamp/init.lua b/mesecons_lamp/init.lua index aff1f26..ff183fd 100644 --- a/mesecons_lamp/init.lua +++ b/mesecons_lamp/init.lua @@ -1,3 +1,5 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + -- MESELAMPS -- A lamp is "is an electrical device used to create artificial light" (wikipedia) -- guess what? @@ -50,7 +52,7 @@ minetest.register_node("mesecons_lamp:lamp_off", { node_box = mesecon_lamp_box, selection_box = mesecon_lamp_box, groups = {dig_immediate=3, mesecon_receptor_off = 1, mesecon_effector_off = 1}, - description = "Mesecon Lamp", + description = S("Mesecon Lamp"), sounds = mesecon.node_sound.glass, mesecons = {effector = { action_on = function (pos, node) diff --git a/mesecons_lamp/locale/mesecons_lamp.eo.tr b/mesecons_lamp/locale/mesecons_lamp.eo.tr new file mode 100644 index 0000000..3434e65 --- /dev/null +++ b/mesecons_lamp/locale/mesecons_lamp.eo.tr @@ -0,0 +1,4 @@ +# textdomain: mesecons_lamp + +### init.lua ### +Mesecon Lamp=Mesekonduktila Lampo diff --git a/mesecons_lamp/locale/template.txt b/mesecons_lamp/locale/template.txt new file mode 100644 index 0000000..208d3c2 --- /dev/null +++ b/mesecons_lamp/locale/template.txt @@ -0,0 +1,4 @@ +# textdomain: mesecons_lamp + +### init.lua ### +Mesecon Lamp= diff --git a/mesecons_lightstone/init.lua b/mesecons_lightstone/init.lua index f2ea147..d601f07 100644 --- a/mesecons_lightstone/init.lua +++ b/mesecons_lightstone/init.lua @@ -1,3 +1,5 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + local lightstone_rules = { {x=0, y=0, z=-1}, {x=1, y=0, z=0}, @@ -59,15 +61,15 @@ function mesecon.lightstone_add(name, base_item, texture_off, texture_on, desc) end -mesecon.lightstone_add("red", "mesecons_gamecompat:dye_red", "jeija_lightstone_red_off.png", "jeija_lightstone_red_on.png", "Red Lightstone") -mesecon.lightstone_add("green", "mesecons_gamecompat:dye_green", "jeija_lightstone_green_off.png", "jeija_lightstone_green_on.png", "Green Lightstone") -mesecon.lightstone_add("blue", "mesecons_gamecompat:dye_blue", "jeija_lightstone_blue_off.png", "jeija_lightstone_blue_on.png", "Blue Lightstone") -mesecon.lightstone_add("gray", "mesecons_gamecompat:dye_grey", "jeija_lightstone_gray_off.png", "jeija_lightstone_gray_on.png", "Grey Lightstone") -mesecon.lightstone_add("darkgray", "mesecons_gamecompat:dye_dark_grey", "jeija_lightstone_darkgray_off.png", "jeija_lightstone_darkgray_on.png", "Dark Grey Lightstone") -mesecon.lightstone_add("yellow", "mesecons_gamecompat:dye_yellow", "jeija_lightstone_yellow_off.png", "jeija_lightstone_yellow_on.png", "Yellow Lightstone") -mesecon.lightstone_add("orange", "mesecons_gamecompat:dye_orange", "jeija_lightstone_orange_off.png", "jeija_lightstone_orange_on.png", "Orange Lightstone") -mesecon.lightstone_add("white", "mesecons_gamecompat:dye_white", "jeija_lightstone_white_off.png", "jeija_lightstone_white_on.png", "White Lightstone") -mesecon.lightstone_add("pink", "mesecons_gamecompat:dye_pink", "jeija_lightstone_pink_off.png", "jeija_lightstone_pink_on.png", "Pink Lightstone") -mesecon.lightstone_add("magenta", "mesecons_gamecompat:dye_magenta", "jeija_lightstone_magenta_off.png", "jeija_lightstone_magenta_on.png", "Magenta Lightstone") -mesecon.lightstone_add("cyan", "mesecons_gamecompat:dye_cyan", "jeija_lightstone_cyan_off.png", "jeija_lightstone_cyan_on.png", "Cyan Lightstone") -mesecon.lightstone_add("violet", "mesecons_gamecompat:dye_violet", "jeija_lightstone_violet_off.png", "jeija_lightstone_violet_on.png", "Violet Lightstone") +mesecon.lightstone_add("red", "mesecons_gamecompat:dye_red", "jeija_lightstone_red_off.png", "jeija_lightstone_red_on.png", S("Red Lightstone")) +mesecon.lightstone_add("green", "mesecons_gamecompat:dye_green", "jeija_lightstone_green_off.png", "jeija_lightstone_green_on.png", S("Green Lightstone")) +mesecon.lightstone_add("blue", "mesecons_gamecompat:dye_blue", "jeija_lightstone_blue_off.png", "jeija_lightstone_blue_on.png", S("Blue Lightstone")) +mesecon.lightstone_add("gray", "mesecons_gamecompat:dye_grey", "jeija_lightstone_gray_off.png", "jeija_lightstone_gray_on.png", S("Grey Lightstone")) +mesecon.lightstone_add("darkgray", "mesecons_gamecompat:dye_dark_grey", "jeija_lightstone_darkgray_off.png", "jeija_lightstone_darkgray_on.png", S("Dark Grey Lightstone")) +mesecon.lightstone_add("yellow", "mesecons_gamecompat:dye_yellow", "jeija_lightstone_yellow_off.png", "jeija_lightstone_yellow_on.png", S("Yellow Lightstone")) +mesecon.lightstone_add("orange", "mesecons_gamecompat:dye_orange", "jeija_lightstone_orange_off.png", "jeija_lightstone_orange_on.png", S("Orange Lightstone")) +mesecon.lightstone_add("white", "mesecons_gamecompat:dye_white", "jeija_lightstone_white_off.png", "jeija_lightstone_white_on.png", S("White Lightstone")) +mesecon.lightstone_add("pink", "mesecons_gamecompat:dye_pink", "jeija_lightstone_pink_off.png", "jeija_lightstone_pink_on.png", S("Pink Lightstone")) +mesecon.lightstone_add("magenta", "mesecons_gamecompat:dye_magenta", "jeija_lightstone_magenta_off.png", "jeija_lightstone_magenta_on.png", S("Magenta Lightstone")) +mesecon.lightstone_add("cyan", "mesecons_gamecompat:dye_cyan", "jeija_lightstone_cyan_off.png", "jeija_lightstone_cyan_on.png", S("Cyan Lightstone")) +mesecon.lightstone_add("violet", "mesecons_gamecompat:dye_violet", "jeija_lightstone_violet_off.png", "jeija_lightstone_violet_on.png", S("Violet Lightstone")) diff --git a/mesecons_lightstone/locale/mesecons_lightstone.eo.tr b/mesecons_lightstone/locale/mesecons_lightstone.eo.tr new file mode 100644 index 0000000..7dab604 --- /dev/null +++ b/mesecons_lightstone/locale/mesecons_lightstone.eo.tr @@ -0,0 +1,15 @@ +# textdomain: mesecons_lightstone + +### init.lua ### +Red Lightstone=Ruĝa Lumŝtono +Green Lightstone=Verda Lumŝtono +Blue Lightstone=Blua Lumŝtono +Grey Lightstone=Griza Lumŝtono +Dark Grey Lightstone=Malhela Griza Lumŝtono +Yellow Lightstone=Flava Lumŝtono +Orange Lightstone=Oranĝa Lumŝtono +White Lightstone=Blanka Lumŝtono +Pink Lightstone=Rozkolora Lumŝtono +Magenta Lightstone=Magenta Lumŝtono +Cyan Lightstone=Cejana Lumŝtono +Violet Lightstone=Viola Lumŝtono diff --git a/mesecons_lightstone/locale/template.txt b/mesecons_lightstone/locale/template.txt new file mode 100644 index 0000000..884c66f --- /dev/null +++ b/mesecons_lightstone/locale/template.txt @@ -0,0 +1,15 @@ +# textdomain: mesecons_lightstone + +### init.lua ### +Red Lightstone= +Green Lightstone= +Blue Lightstone= +Grey Lightstone= +Dark Grey Lightstone= +Yellow Lightstone= +Orange Lightstone= +White Lightstone= +Pink Lightstone= +Magenta Lightstone= +Cyan Lightstone= +Violet Lightstone= diff --git a/mesecons_luacontroller/init.lua b/mesecons_luacontroller/init.lua index 50a6747..72bee24 100644 --- a/mesecons_luacontroller/init.lua +++ b/mesecons_luacontroller/init.lua @@ -28,6 +28,8 @@ -- (see where local env is defined) -- Something nice to play is is appending minetest.env to it. +local S = minetest.get_translator(minetest.get_current_modname()) + local BASENAME = "mesecons_luacontroller:luacontroller" local rules = { @@ -201,11 +203,13 @@ end ------------------------- local function safe_print(param) - local string_meta = getmetatable("") - local sandbox = string_meta.__index - string_meta.__index = string -- Leave string sandbox temporarily - print(dump(param)) - string_meta.__index = sandbox -- Restore string sandbox + if mesecon.setting("luacontroller_print_behavior", "log") == "log" then + local string_meta = getmetatable("") + local sandbox = string_meta.__index + string_meta.__index = string -- Leave string sandbox temporarily + minetest.log("action", string.format("[mesecons_luacontroller] print(%s)", dump(param))) + string_meta.__index = sandbox -- Restore string sandbox + end end local function safe_date() @@ -851,7 +855,7 @@ for d = 0, 1 do } minetest.register_node(node_name, { - description = "Luacontroller", + description = S("Luacontroller"), drawtype = "nodebox", tiles = { top, diff --git a/mesecons_luacontroller/locale/mesecons_luacontroller.eo.tr b/mesecons_luacontroller/locale/mesecons_luacontroller.eo.tr new file mode 100644 index 0000000..f477ebd --- /dev/null +++ b/mesecons_luacontroller/locale/mesecons_luacontroller.eo.tr @@ -0,0 +1,4 @@ +# textdomain: mesecons_luacontroller + +### init.lua ### +Luacontroller=Luaregilo diff --git a/mesecons_luacontroller/locale/template.txt b/mesecons_luacontroller/locale/template.txt new file mode 100644 index 0000000..ece4275 --- /dev/null +++ b/mesecons_luacontroller/locale/template.txt @@ -0,0 +1,4 @@ +# textdomain: mesecons_luacontroller + +### init.lua ### +Luacontroller= diff --git a/mesecons_luacontroller/spec/lightweight_interrupt_spec.lua b/mesecons_luacontroller/spec/lightweight_interrupt_spec.lua new file mode 100644 index 0000000..045c9b4 --- /dev/null +++ b/mesecons_luacontroller/spec/lightweight_interrupt_spec.lua @@ -0,0 +1,38 @@ +require("mineunit") + +-- This test is done in a separate file since it requires different configuration at startup. +mineunit("core") +minetest.settings:set("mesecon.luacontroller_lightweight_interrupts", "true") + +fixture("mesecons_luacontroller") + +describe("LuaController lightweight interrupt", function() + local pos = {x = 0, y = 0, z = 0} + + before_each(function() + mesecon._test_place(pos, "mesecons_luacontroller:luacontroller0000") + mineunit:execute_globalstep() -- Execute receptor_on action + end) + + after_each(function() + mesecon._test_reset() + world.clear() + end) + + it("works", function() + mesecon._test_program_luac(pos, [[ + if event.type == "program" then + interrupt(5) + interrupt(10) + elseif event.type == "interrupt" then + port.a = not pin.a + end + ]]) + mineunit:execute_globalstep(0.1) + mineunit:execute_globalstep(9) + assert.equal("mesecons_luacontroller:luacontroller0000", world.get_node(pos).name) + mineunit:execute_globalstep(1) + mineunit:execute_globalstep(0.1) + assert.equal("mesecons_luacontroller:luacontroller0001", world.get_node(pos).name) + end) +end) diff --git a/mesecons_luacontroller/spec/luac_spec.lua b/mesecons_luacontroller/spec/luac_spec.lua new file mode 100644 index 0000000..351b2e4 --- /dev/null +++ b/mesecons_luacontroller/spec/luac_spec.lua @@ -0,0 +1,176 @@ +require("mineunit") + +fixture("mesecons_luacontroller") + +-- Digiline is not tested, since that would require the digiline mod. + +describe("LuaController", function() + local pos = {x = 0, y = 0, z = 0} + local pos_a = {x = -1, y = 0, z = 0} + + before_each(function() + mesecon._test_place(pos, "mesecons_luacontroller:luacontroller0000") + mineunit:execute_globalstep() -- Execute receptor_on action + end) + + after_each(function() + mesecon._test_reset() + world.clear() + end) + + it("rejects binary code", function() + local ok = mesecon._test_program_luac(pos, string.dump(function() end)) + assert.is_false(ok) + end) + + it("I/O", function() + mesecon._test_place(pos_a, "mesecons:test_receptor_on") + mineunit:execute_globalstep() -- Execute receptor_on action + mineunit:execute_globalstep() -- Execute activate/change actions + mesecon._test_program_luac(pos, [[ + port.a = not pin.a + port.b = not pin.b + port.c = not pin.c + port.d = not pin.d + ]]) + assert.equal("mesecons_luacontroller:luacontroller1110", world.get_node(pos).name) + mesecon._test_dig(pos_a) + mineunit:execute_globalstep() -- Execute receptor_off action + mineunit:execute_globalstep() -- Execute deactivate/change actions + assert.equal("mesecons_luacontroller:luacontroller0001", world.get_node(pos).name) + end) + + it("memory", function() + mesecon._test_program_luac(pos, [[ + if not mem.x then + mem.x = {} + mem.x[mem.x] = {true, "", 1.2} + else + local b, s, n = unpack(mem.x[mem.x]) + if b == true and s == "" and n == 1.2 then + port.d = true + end + end + ]]) + assert.equal("mesecons_luacontroller:luacontroller0000", world.get_node(pos).name) + mesecon._test_place(pos_a, "mesecons:test_receptor_on") + mineunit:execute_globalstep() -- Execute receptor_on action + mineunit:execute_globalstep() -- Execute activate/change actions + assert.equal("mesecons_luacontroller:luacontroller1000", world.get_node(pos).name) + end) + + it("interrupts without IDs", function() + mesecon._test_program_luac(pos, [[ + if event.type == "program" then + interrupt(4) + interrupt(8) + elseif event.type == "interrupt" then + port.a = not pin.a + end + ]]) + mineunit:execute_globalstep(0.1) + mineunit:execute_globalstep(3) + assert.equal("mesecons_luacontroller:luacontroller0000", world.get_node(pos).name) + mineunit:execute_globalstep(1) + mineunit:execute_globalstep(0.1) + assert.equal("mesecons_luacontroller:luacontroller0001", world.get_node(pos).name) + mineunit:execute_globalstep(3) + assert.equal("mesecons_luacontroller:luacontroller0001", world.get_node(pos).name) + mineunit:execute_globalstep(1) + mineunit:execute_globalstep(0.1) + assert.equal("mesecons_luacontroller:luacontroller0000", world.get_node(pos).name) + end) + + it("interrupts with IDs", function() + mesecon._test_program_luac(pos, [[ + if event.type == "program" then + interrupt(2, "a") + interrupt(4, "a") + interrupt(16, "b") + elseif event.type == "interrupt" then + if event.iid == "a" then + interrupt(5, "b") + interrupt(4, "b") + end + port.a = not pin.a + end + ]]) + mineunit:execute_globalstep(0.1) + mineunit:execute_globalstep(3) + assert.equal("mesecons_luacontroller:luacontroller0000", world.get_node(pos).name) + mineunit:execute_globalstep(1) + mineunit:execute_globalstep(0.1) + assert.equal("mesecons_luacontroller:luacontroller0001", world.get_node(pos).name) + mineunit:execute_globalstep(3) + assert.equal("mesecons_luacontroller:luacontroller0001", world.get_node(pos).name) + mineunit:execute_globalstep(1) + mineunit:execute_globalstep(0.1) + assert.equal("mesecons_luacontroller:luacontroller0000", world.get_node(pos).name) + end) + + it("limits interrupt ID size", function() + mesecon._test_program_luac(pos, [[ + if event.type == "program" then + interrupt(0, (" "):rep(257)) + elseif event.type == "interrupt" then + port.a = not pin.a + end + ]]) + mineunit:execute_globalstep(3) + mineunit:execute_globalstep(3) + assert.equal("mesecons_luacontroller:luacontroller0000", world.get_node(pos).name) + end) + + it("string.rep", function() + mesecon._test_program_luac(pos, [[ + (" "):rep(64000) + port.a = true + ]]) + assert.equal("mesecons_luacontroller:luacontroller0001", world.get_node(pos).name) + mesecon._test_program_luac(pos, [[ + (" "):rep(64001) + port.b = true + ]]) + assert.equal("mesecons_luacontroller:luacontroller0000", world.get_node(pos).name) + end) + + it("string.find", function() + mesecon._test_program_luac(pos, [[ + port.a = (" a"):find("a", nil, true) == 2 + ]]) + assert.equal("mesecons_luacontroller:luacontroller0001", world.get_node(pos).name) + mesecon._test_program_luac(pos, [[ + (" a"):find("a", nil) + port.b = true + ]]) + assert.equal("mesecons_luacontroller:luacontroller0000", world.get_node(pos).name) + end) + + it("overheats", function() + mesecon._test_program_luac(pos, [[ + interrupt(0) + interrupt(0) + ]]) + mineunit:execute_globalstep() -- Execute 2 interrupts + mineunit:execute_globalstep() -- Execute 4 interrupts + mineunit:execute_globalstep() -- Execute 8 interrupts + mineunit:execute_globalstep() -- Execute 16 interrupts + assert.equal("mesecons_luacontroller:luacontroller_burnt", world.get_node(pos).name) + end) + + it("limits memory", function() + mesecon._test_program_luac(pos, [[ + port.a = true + mem.x = (" "):rep(50000) .. (" "):rep(50000) + ]]) + assert.equal("mesecons_luacontroller:luacontroller_burnt", world.get_node(pos).name) + end) + + it("limits run time", function() + mesecon._test_program_luac(pos, [[ + port.a = true + for i = 1, 1000000 do end + ]]) + assert.equal("mesecons_luacontroller:luacontroller0000", world.get_node(pos).name) + end) +end) diff --git a/mesecons_luacontroller/spec/mineunit.conf b/mesecons_luacontroller/spec/mineunit.conf new file mode 100644 index 0000000..81bd36c --- /dev/null +++ b/mesecons_luacontroller/spec/mineunit.conf @@ -0,0 +1 @@ +fixture_paths = {"../.test_fixtures"} diff --git a/mesecons_materials/init.lua b/mesecons_materials/init.lua index c3ed73b..ae95eb5 100644 --- a/mesecons_materials/init.lua +++ b/mesecons_materials/init.lua @@ -1,14 +1,16 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + -- Glue and fiber minetest.register_craftitem("mesecons_materials:glue", { image = "mesecons_glue.png", on_place_on_ground = minetest.craftitem_place_item, - description="Glue", + description = S("Glue"), }) minetest.register_craftitem("mesecons_materials:fiber", { image = "mesecons_fiber.png", on_place_on_ground = minetest.craftitem_place_item, - description="Fiber", + description = S("Fiber"), }) minetest.register_craft({ @@ -29,7 +31,7 @@ minetest.register_craft({ minetest.register_craftitem("mesecons_materials:silicon", { image = "mesecons_silicon.png", on_place_on_ground = minetest.craftitem_place_item, - description="Silicon", + description = S("Silicon"), }) minetest.register_craft({ diff --git a/mesecons_materials/locale/mesecons_materials.eo.tr b/mesecons_materials/locale/mesecons_materials.eo.tr new file mode 100644 index 0000000..501c386 --- /dev/null +++ b/mesecons_materials/locale/mesecons_materials.eo.tr @@ -0,0 +1,6 @@ +# textdomain: mesecons_materials + +### init.lua ### +Glue=Gluo +Fiber=Fibro +Silicon=Silicio diff --git a/mesecons_materials/locale/template.txt b/mesecons_materials/locale/template.txt new file mode 100644 index 0000000..4c1eb74 --- /dev/null +++ b/mesecons_materials/locale/template.txt @@ -0,0 +1,6 @@ +# textdomain: mesecons_materials + +### init.lua ### +Glue= +Fiber= +Silicon= diff --git a/mesecons_microcontroller/init.lua b/mesecons_microcontroller/init.lua index 05384da..d28df2b 100644 --- a/mesecons_microcontroller/init.lua +++ b/mesecons_microcontroller/init.lua @@ -1,3 +1,5 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + local EEPROM_SIZE = 255 local microc_rules = {} @@ -57,7 +59,7 @@ if nodename ~= "mesecons_microcontroller:microcontroller0000" then end minetest.register_node(nodename, { - description = "Microcontroller", + description = S("Microcontroller"), drawtype = "nodebox", tiles = { top, diff --git a/mesecons_microcontroller/locale/mesecons_microcontroller.eo.tr b/mesecons_microcontroller/locale/mesecons_microcontroller.eo.tr new file mode 100644 index 0000000..39c2c90 --- /dev/null +++ b/mesecons_microcontroller/locale/mesecons_microcontroller.eo.tr @@ -0,0 +1,4 @@ +# textdomain: mesecons_microcontroller + +### init.lua ### +Microcontroller=Mikroregilo diff --git a/mesecons_microcontroller/locale/template.txt b/mesecons_microcontroller/locale/template.txt new file mode 100644 index 0000000..f4274a0 --- /dev/null +++ b/mesecons_microcontroller/locale/template.txt @@ -0,0 +1,4 @@ +# textdomain: mesecons_microcontroller + +### init.lua ### +Microcontroller= diff --git a/mesecons_movestones/init.lua b/mesecons_movestones/init.lua index e50103c..715e75c 100644 --- a/mesecons_movestones/init.lua +++ b/mesecons_movestones/init.lua @@ -8,6 +8,8 @@ -- Pushes all block in front of it -- Pull all blocks in its back +local S = minetest.get_translator(minetest.get_current_modname()) + -- settings: local timer_interval = 1 / mesecon.setting("movestone_speed", 3) local max_push = mesecon.setting("movestone_max_push", 50) @@ -128,7 +130,7 @@ mesecon.register_movestone("mesecons_movestones:movestone", { "jeija_movestone_arrows.png", }, groups = {cracky = 3}, - description = "Movestone", + description = S("Movestone"), sounds = mesecon.node_sound.stone }, false, false) @@ -142,7 +144,7 @@ mesecon.register_movestone("mesecons_movestones:sticky_movestone", { "jeija_sticky_movestone.png", }, groups = {cracky = 3}, - description = "Sticky Movestone", + description = S("Sticky Movestone"), sounds = mesecon.node_sound.stone, }, true, false) @@ -156,7 +158,7 @@ mesecon.register_movestone("mesecons_movestones:movestone_vertical", { "jeija_movestone_arrows.png^[transformR90", }, groups = {cracky = 3}, - description = "Vertical Movestone", + description = S("Vertical Movestone"), sounds = mesecon.node_sound.stone }, false, true) @@ -170,7 +172,7 @@ mesecon.register_movestone("mesecons_movestones:sticky_movestone_vertical", { "jeija_movestone_arrows.png^[transformR90", }, groups = {cracky = 3}, - description = "Vertical Sticky Movestone", + description = S("Vertical Sticky Movestone"), sounds = mesecon.node_sound.stone, }, true, true) diff --git a/mesecons_movestones/locale/mesecons_movestones.eo.tr b/mesecons_movestones/locale/mesecons_movestones.eo.tr new file mode 100644 index 0000000..b4f8d37 --- /dev/null +++ b/mesecons_movestones/locale/mesecons_movestones.eo.tr @@ -0,0 +1,7 @@ +# textdomain: mesecons_movestones + +### init.lua ### +Movestone=Movŝtono +Sticky Movestone=Glueca Movŝtono +Vertical Movestone=Vertikala Movŝtono +Vertical Sticky Movestone=Vertikala Glueca Movŝtono diff --git a/mesecons_movestones/locale/template.txt b/mesecons_movestones/locale/template.txt new file mode 100644 index 0000000..a35e6bc --- /dev/null +++ b/mesecons_movestones/locale/template.txt @@ -0,0 +1,7 @@ +# textdomain: mesecons_movestones + +### init.lua ### +Movestone= +Sticky Movestone= +Vertical Movestone= +Vertical Sticky Movestone= diff --git a/mesecons_mvps/spec/mineunit.conf b/mesecons_mvps/spec/mineunit.conf new file mode 100644 index 0000000..81bd36c --- /dev/null +++ b/mesecons_mvps/spec/mineunit.conf @@ -0,0 +1 @@ +fixture_paths = {"../.test_fixtures"} diff --git a/mesecons_mvps/spec/node_spec.lua b/mesecons_mvps/spec/node_spec.lua new file mode 100644 index 0000000..2a9d170 --- /dev/null +++ b/mesecons_mvps/spec/node_spec.lua @@ -0,0 +1,297 @@ +require("mineunit") + +fixture("mesecons_mvps") + +world.set_default_node("air") + +describe("node movement", function() + after_each(function() + mesecon._test_reset() + world.clear() + end) + + it("works with no moved nodes", function() + local pos = {x = 0, y = 0, z = 0} + local dir = {x = 1, y = 0, z = 0} + + assert.same({true, {}, {}}, {mesecon.mvps_push(pos, dir, 1, "")}) + assert.same({true, {}, {}}, {mesecon.mvps_pull_all(pos, dir, 1, "")}) + assert.same({true, {}, {}}, {mesecon.mvps_pull_single(pos, dir, 1, "")}) + end) + + it("works with simple stack", function() + local pos = {x = 0, y = 0, z = 0} + local dir = {x = 1, y = 0, z = 0} + world.set_node(pos, "mesecons:test_conductor_off") + world.set_node(vector.add(pos, dir), "mesecons:test_conductor_off") + + assert.is_true((mesecon.mvps_push(pos, dir, 2, ""))) + assert.equal("air", world.get_node(pos).name) + assert.equal("mesecons:test_conductor_off", world.get_node(vector.add(pos, dir)).name) + assert.equal("mesecons:test_conductor_off", world.get_node(vector.add(pos, vector.multiply(dir, 2))).name) + + assert.is_true((mesecon.mvps_pull_all(vector.add(pos, dir), vector.multiply(dir, -1), 2, ""))) + assert.equal("mesecons:test_conductor_off", world.get_node(pos).name) + assert.equal("mesecons:test_conductor_off", world.get_node(vector.add(pos, dir)).name) + assert.equal("air", world.get_node(vector.add(pos, vector.multiply(dir, 2))).name) + + assert.is_true((mesecon.mvps_pull_single(pos, vector.multiply(dir, -1), 1, ""))) + assert.equal("mesecons:test_conductor_off", world.get_node(vector.subtract(pos, dir)).name) + assert.equal("air", world.get_node(pos).name) + assert.equal("mesecons:test_conductor_off", world.get_node(vector.add(pos, dir)).name) + end) + + it("works with sticky nodes", function() + local pos = {x = 0, y = 0, z = 0} + local dir = {x = 0, y = 1, z = 0} + world.set_node(pos, "mesecons:test_conductor_off") + world.set_node(vector.offset(pos, 0, 1, 0), "mesecons_mvps:test_sticky") + world.set_node(vector.offset(pos, 1, 1, 0), "mesecons:test_conductor_off") + world.set_node(vector.offset(pos, 1, 2, 0), "mesecons:test_conductor_off") + + assert.is_true((mesecon.mvps_push(pos, dir, 4, ""))) + assert.equal("air", world.get_node(vector.offset(pos, 1, 1, 0)).name) + assert.equal("mesecons:test_conductor_off", world.get_node(vector.offset(pos, 1, 2, 0)).name) + assert.equal("mesecons:test_conductor_off", world.get_node(vector.offset(pos, 1, 3, 0)).name) + + assert.is_true((mesecon.mvps_pull_all(vector.add(pos, dir), vector.multiply(dir, -1), 4, ""))) + assert.equal("air", world.get_node(vector.offset(pos, 1, 0, 0)).name) + assert.equal("mesecons:test_conductor_off", world.get_node(vector.offset(pos, 1, 1, 0)).name) + assert.equal("mesecons:test_conductor_off", world.get_node(vector.offset(pos, 1, 2, 0)).name) + + assert.is_true((mesecon.mvps_pull_single(pos, vector.multiply(dir, -1), 3, ""))) + assert.equal("air", world.get_node(vector.offset(pos, 1, -1, 0)).name) + assert.equal("mesecons:test_conductor_off", world.get_node(vector.offset(pos, 1, 0, 0)).name) + assert.equal("air", world.get_node(vector.offset(pos, 1, 1, 0)).name) + end) + + it("respects maximum", function() + local pos = {x = 0, y = 0, z = 0} + local dir = {x = 1, y = 0, z = 0} + world.set_node(pos, "mesecons:test_conductor_off") + world.set_node(vector.add(pos, dir), "mesecons:test_conductor_off") + + assert.is_true(not mesecon.mvps_push(pos, dir, 1, "")) + end) + + it("is blocked by basic stopper", function() + local pos = {x = 0, y = 0, z = 0} + local dir = {x = 1, y = 0, z = 0} + world.set_node(pos, "mesecons_mvps:test_stopper") + + assert.is_true(not mesecon.mvps_push(pos, dir, 1, "")) + end) + + it("is blocked by conditional stopper", function() + local pos = {x = 0, y = 0, z = 0} + local dir = {x = 1, y = 0, z = 0} + + world.set_node(pos, {name = "mesecons_mvps:test_stopper_cond", param2 = 0}) + assert.is_true(not mesecon.mvps_push(pos, dir, 1, "")) + + world.set_node(pos, {name = "mesecons_mvps:test_stopper_cond", param2 = 1}) + assert.is_true((mesecon.mvps_push(pos, dir, 1, ""))) + end) + + -- TODO: I think this is supposed to work? + pending("is blocked by ignore", function() + local pos = {x = 0, y = 0, z = 0} + local dir = {x = 1, y = 0, z = 0} + world.set_node(pos, "mesecons:test_conductor_off") + world.set_node(vector.add(pos, dir), "ignore") + + assert.is_true(not mesecon.mvps_push(pos, dir, 1, "")) + end) + + it("moves metadata", function() + local pos = {x = 0, y = 0, z = 0} + local dir = {x = 1, y = 0, z = 0} + world.set_node(pos, "mesecons:test_conductor_off") + minetest.get_meta(pos):set_string("foo", "bar") + minetest.get_node_timer(pos):set(12, 34) + + mesecon.mvps_push(pos, dir, 1, "") + assert.equal("bar", minetest.get_meta(vector.add(pos, dir)):get("foo")) + local moved_timer = minetest.get_node_timer(vector.add(pos, dir)) + assert.equal(12, moved_timer:get_timeout()) + assert.equal(34, moved_timer:get_elapsed()) + moved_timer:stop() + assert.same({}, minetest.get_meta(pos):to_table().fields) + assert.is_false(minetest.get_node_timer(pos):is_started()) + end) + + it("calls move callbacks", function() + local pos = {x = 0, y = 0, z = 0} + local dir = {x = 1, y = 0, z = 0} + world.set_node(pos, {name = "mesecons_mvps:test_on_move", param2 = 123}) + minetest.get_meta(pos):set_string("foo", "bar") + local move_info = {vector.add(pos, dir), world.get_node(pos), pos, minetest.get_meta(pos):to_table()} + + mesecon.mvps_push(pos, dir, 1, "") + assert.equal(1, #mesecon._test_moves) + assert.same(move_info, mesecon._test_moves[1]) + end) + + it("executes autoconnect hooks", function() + local pos = {x = 0, y = 0, z = 0} + local dir = {x = 1, y = 0, z = 0} + world.set_node(pos, "mesecons:test_conductor_off") + + mesecon.mvps_push(pos, dir, 1, "") + mineunit:execute_globalstep() -- Execute delayed autoconnect hook + assert.equal(2, #mesecon._test_autoconnects) + end) + + it("updates moved receptors", function() + local pos1 = {x = 0, y = 0, z = 0} + local pos2 = vector.offset(pos1, 0, 1, 0) + local pos3 = vector.offset(pos1, 2, 0, 0) + local pos4 = vector.offset(pos1, 0, 0, 1) + local dir = {x = 1, y = 0, z = 0} + mesecon._test_place(pos1, "mesecons:test_receptor_on") + mesecon._test_place(pos2, "mesecons:test_conductor_off") + mesecon._test_place(pos3, "mesecons:test_conductor_off") + mesecon._test_place(pos4, "mesecons:test_conductor_off") + mesecon._test_place(vector.add(pos4, dir), "mesecons:test_conductor_off") + mineunit:execute_globalstep() -- Execute receptor_on action + + mesecon.mvps_push(pos1, dir, 1, "") + mineunit:execute_globalstep() -- Execute receptor_on/receptor_off actions + assert.equal("mesecons:test_conductor_off", world.get_node(pos2).name) + assert.equal("mesecons:test_conductor_on", world.get_node(pos3).name) + assert.equal("mesecons:test_conductor_on", world.get_node(pos4).name) + end) + + it("updates moved conductors", function() + local pos1 = {x = 0, y = 0, z = 0} + local pos2 = vector.offset(pos1, 0, 1, 0) + local pos3 = vector.offset(pos1, 0, -1, 0) + local dir = {x = 1, y = 0, z = 0} + mesecon._test_place(pos1, "mesecons:test_conductor_off") + mesecon._test_place(pos2, "mesecons:test_receptor_on") + mesecon._test_place(pos3, "mesecons:test_conductor_off") + mineunit:execute_globalstep() -- Execute receptor_on action + + mesecon.mvps_push(pos1, dir, 1, "") + mineunit:execute_globalstep() -- Execute receptor_off action + assert.equal("mesecons:test_conductor_off", world.get_node(vector.add(pos1, dir)).name) + assert.equal("mesecons:test_conductor_off", world.get_node(pos3).name) + + mesecon.mvps_pull_all(vector.add(pos1, dir), vector.multiply(dir, -1), 1, "") + mineunit:execute_globalstep() -- Execute receptor_on action + assert.equal("mesecons:test_conductor_on", world.get_node(pos1).name) + assert.equal("mesecons:test_conductor_on", world.get_node(pos3).name) + end) + + it("updates moved effectors", function() + local pos = {x = 0, y = 0, z = 0} + local dir = {x = 1, y = 0, z = 0} + mesecon._test_place(pos, "mesecons:test_effector") + mesecon._test_place(vector.offset(pos, 0, 1, 0), "mesecons:test_receptor_on") + mesecon._test_place(vector.add(pos, dir), "mesecons:test_receptor_on") + mineunit:execute_globalstep() -- Execute receptor_on action + mineunit:execute_globalstep() -- Execute activate/change actions + + mesecon.mvps_push(pos, dir, 2, "") + mineunit:execute_globalstep() -- Execute receptor_on/receptor_off actions + mineunit:execute_globalstep() -- Execute activate/deactivate/change actions + assert.equal(tonumber("10000001", 2), world.get_node(vector.add(pos, dir)).param2) + + mineunit:execute_globalstep() -- Let the component cool down + + mesecon.mvps_pull_single(vector.add(pos, dir), vector.multiply(dir, -1), 1, "") + mineunit:execute_globalstep() -- Execute receptor_on/receptor_off actions + mineunit:execute_globalstep() -- Execute activate/deactivate/change actions + assert.equal(tonumber("10000100", 2), world.get_node(pos).param2) + end) + + -- Since turnon is called before turnoff when pushing, effectors may be incorrectly turned off. + it("does not overwrite turnon with receptor_off", function() + local pos = {x = 0, y = 0, z = 0} + local dir = {x = 1, y = 0, z = 0} + mesecon._test_place(pos, "mesecons:test_effector") + mesecon._test_place(vector.add(pos, dir), "mesecons:test_conductor_off") + mesecon._test_place(vector.add(pos, vector.multiply(dir, 2)), "mesecons:test_receptor_on") + mineunit:execute_globalstep() -- Execute receptor_on action + mineunit:execute_globalstep() -- Execute activate/change actions + + mesecon.mvps_push(pos, dir, 3, "") + mineunit:execute_globalstep() -- Execute receptor_on/receptor_off actions + mineunit:execute_globalstep() -- Execute activate/deactivate/change actions + assert.equal(tonumber("10000001", 2), world.get_node(vector.add(pos, dir)).param2) + end) + + -- mineunit doesn't yet implement minetest.check_for_falling. + pending("causes nodes to fall", function() + end) +end) + +describe("protection", function() + teardown(function() + minetest.settings:remove("mesecon.mvps_protection_mode") + end) + + after_each(function() + mesecon._test_reset() + world.clear() + end) + + local protected_pos = {x = 1, y = 0, z = 0} + mineunit:protect(protected_pos, "Joe") + + it("blocks movement", function() + minetest.settings:set("mesecon.mvps_protection_mode", "restrict") + + local pos = {x = 0, y = 0, z = 0} + world.set_node(pos, "mesecons:test_conductor_off") + + assert.same({false, "protected"}, {mesecon.mvps_push(pos, {x = 1, y = 0, z = 0}, 1, "Bob")}) + end) + + it("allows owner's movement", function() + minetest.settings:set("mesecon.mvps_protection_mode", "restrict") + + local pos = {x = 0, y = 0, z = 0} + world.set_node(pos, "mesecons:test_conductor_off") + + assert.is_true((mesecon.mvps_push(pos, {x = 1, y = 0, z = 0}, 1, "Joe"))) + end) + + it("'ignore'", function() + minetest.settings:set("mesecon.mvps_protection_mode", "ignore") + + local pos = {x = 0, y = 0, z = 0} + world.set_node(pos, "mesecons:test_conductor_off") + + assert.is_true((mesecon.mvps_push(pos, {x = 1, y = 0, z = 0}, 1, "Bob"))) + end) + + it("'normal'", function() + minetest.settings:set("mesecon.mvps_protection_mode", "normal") + + local pos = {x = 0, y = 0, z = 0} + world.set_node(pos, "mesecons:test_conductor_off") + + assert.same({false, "protected"}, {mesecon.mvps_push(pos, {x = 1, y = 0, z = 0}, 1, "")}) + + assert.is_true((mesecon.mvps_push(pos, {x = 0, y = 1, z = 0}, 1, ""))) + end) + + it("'compat'", function() + minetest.settings:set("mesecon.mvps_protection_mode", "compat") + + local pos = {x = 0, y = 0, z = 0} + world.set_node(pos, "mesecons:test_conductor_off") + + assert.is_true((mesecon.mvps_push(pos, {x = 1, y = 0, z = 0}, 1, ""))) + end) + + it("'restrict'", function() + minetest.settings:set("mesecon.mvps_protection_mode", "restrict") + + local pos = {x = 0, y = 0, z = 0} + world.set_node(pos, "mesecons:test_conductor_off") + + assert.same({false, "protected"}, {mesecon.mvps_push(pos, {x = 0, y = 1, z = 0}, 1, "")}) + end) +end) diff --git a/mesecons_mvps/spec/object_spec.lua b/mesecons_mvps/spec/object_spec.lua new file mode 100644 index 0000000..cc2ca8d --- /dev/null +++ b/mesecons_mvps/spec/object_spec.lua @@ -0,0 +1,3 @@ +-- mineunit doesn't yet implement minetest.get_objects_inside_radius +pending("object movement", function() +end) diff --git a/mesecons_noteblock/README.txt b/mesecons_noteblock/README.txt new file mode 100644 index 0000000..e0ad34c --- /dev/null +++ b/mesecons_noteblock/README.txt @@ -0,0 +1,15 @@ +Credits of sound files: + +Note: Most sounds have not been used verbatim, but tweaked a little to be more suitable for the noteblock mod. + +* mesecons_noteblock_litecrash.ogg + * License: CC BY 3.0 + * by freesound.org user ani_music + * Source: https://freesound.org/people/ani_music/sounds/219612/ + +Everything else: +Created by Mesecons authors, licensed CC BY 3.0. + +-------------------- +License links: +* CC BY 3.0: http://creativecommons.org/licenses/by/3.0/ diff --git a/mesecons_noteblock/doc/noteblock/description.html b/mesecons_noteblock/doc/noteblock/description.html index e11724d..a98c0f9 100644 --- a/mesecons_noteblock/doc/noteblock/description.html +++ b/mesecons_noteblock/doc/noteblock/description.html @@ -6,8 +6,8 @@ This effector makes a sound if powered and can be used for making music. Normall Chest or Locked ChestSnare Any treeCrash Any wooden planksLite Crash -Coal BlockExplosion sound -Lava SourceFire sound +Coal BlockExplosion sound (fixed pitch) +Lava SourceFire sound (fixed pitch) Steel BlockPiano (high pitch, one octave higher than normal) Any other blockPiano (low pitch) diff --git a/mesecons_noteblock/init.lua b/mesecons_noteblock/init.lua index f0e7044..847c40b 100644 --- a/mesecons_noteblock/init.lua +++ b/mesecons_noteblock/init.lua @@ -1,5 +1,7 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + minetest.register_node("mesecons_noteblock:noteblock", { - description = "Noteblock", + description = S("Noteblock"), tiles = {"mesecons_noteblock.png"}, is_ground_content = false, groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2}, @@ -18,6 +20,7 @@ minetest.register_node("mesecons_noteblock:noteblock", { mesecon.noteblock_play(pos, node.param2) end }}, + place_param2 = 11, -- initialize at C note on_blast = mesecon.on_blastnode, }) @@ -43,7 +46,7 @@ local soundnames = { "mesecons_noteblock_a", "mesecons_noteblock_asharp", "mesecons_noteblock_b", - "mesecons_noteblock_c" + "mesecons_noteblock_c" -- << noteblock is initialized here } local node_sounds = {} @@ -72,6 +75,9 @@ mesecon.noteblock_play = function(pos, param2) pos.y = pos.y-1 local nodeunder = minetest.get_node(pos).name local soundname = node_sounds[nodeunder] + local use_pitch = true + local pitch + -- Special sounds if not soundname then for k,v in pairs(node_sounds_group) do local g = minetest.get_item_group(nodeunder, k) @@ -81,6 +87,7 @@ mesecon.noteblock_play = function(pos, param2) end end end + -- Piano if not soundname then soundname = soundnames[param2] if not soundname then @@ -90,6 +97,17 @@ mesecon.noteblock_play = function(pos, param2) if nodeunder == steelblock_nodename then soundname = soundname.. 2 end + use_pitch = false + end + -- Disable pitch for fire and explode because they'd sound too odd + if soundname == "fire_fire" or soundname == "tnt_explode" then + use_pitch = false + end + if use_pitch then + -- Calculate pitch + -- Adding 1 to param2 because param2=11 is *lowest* pitch sound + local val = (param2+1)%12 + pitch = 2^((val-6)/12) end pos.y = pos.y+1 if soundname == "fire_fire" then @@ -97,6 +115,6 @@ mesecon.noteblock_play = function(pos, param2) local handle = minetest.sound_play(soundname, {pos = pos, loop = true}) minetest.after(3.0, minetest.sound_fade, handle, -1.5, 0.0) else - minetest.sound_play(soundname, {pos = pos}, true) + minetest.sound_play(soundname, {pos = pos, pitch = pitch}, true) end end diff --git a/mesecons_noteblock/locale/mesecons_noteblock.eo.tr b/mesecons_noteblock/locale/mesecons_noteblock.eo.tr new file mode 100644 index 0000000..bea3735 --- /dev/null +++ b/mesecons_noteblock/locale/mesecons_noteblock.eo.tr @@ -0,0 +1,4 @@ +# textdomain: mesecons_noteblock + +### init.lua ### +Noteblock=Sonbloko diff --git a/mesecons_noteblock/locale/template.txt b/mesecons_noteblock/locale/template.txt new file mode 100644 index 0000000..bcd3754 --- /dev/null +++ b/mesecons_noteblock/locale/template.txt @@ -0,0 +1,4 @@ +# textdomain: mesecons_noteblock + +### init.lua ### +Noteblock= diff --git a/mesecons_noteblock/sounds/mesecons_noteblock_litecrash.ogg b/mesecons_noteblock/sounds/mesecons_noteblock_litecrash.ogg index 79ab256..36d83f3 100644 Binary files a/mesecons_noteblock/sounds/mesecons_noteblock_litecrash.ogg and b/mesecons_noteblock/sounds/mesecons_noteblock_litecrash.ogg differ diff --git a/mesecons_pistons/init.lua b/mesecons_pistons/init.lua index bc940d0..3d75b35 100644 --- a/mesecons_pistons/init.lua +++ b/mesecons_pistons/init.lua @@ -1,3 +1,5 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + local specs = { normal = { offname = "mesecons_pistons:piston_normal_off", @@ -265,7 +267,7 @@ local piston_on_box = { -- Normal (non-sticky) Pistons: -- offstate minetest.register_node("mesecons_pistons:piston_normal_off", { - description = "Piston", + description = S("Piston"), tiles = { "mesecons_piston_top.png", "mesecons_piston_bottom.png", @@ -290,7 +292,7 @@ minetest.register_node("mesecons_pistons:piston_normal_off", { -- onstate minetest.register_node("mesecons_pistons:piston_normal_on", { - description = "Activated Piston Base", + description = S("Activated Piston Base"), drawtype = "nodebox", tiles = { "mesecons_piston_top.png", @@ -319,7 +321,7 @@ minetest.register_node("mesecons_pistons:piston_normal_on", { -- pusher minetest.register_node("mesecons_pistons:piston_pusher_normal", { - description = "Piston Pusher", + description = S("Piston Pusher"), drawtype = "nodebox", tiles = { "mesecons_piston_pusher_top.png", @@ -344,7 +346,7 @@ minetest.register_node("mesecons_pistons:piston_pusher_normal", { -- Sticky ones -- offstate minetest.register_node("mesecons_pistons:piston_sticky_off", { - description = "Sticky Piston", + description = S("Sticky Piston"), tiles = { "mesecons_piston_top.png", "mesecons_piston_bottom.png", @@ -369,7 +371,7 @@ minetest.register_node("mesecons_pistons:piston_sticky_off", { -- onstate minetest.register_node("mesecons_pistons:piston_sticky_on", { - description = "Activated Sticky Piston Base", + description = S("Activated Sticky Piston Base"), drawtype = "nodebox", tiles = { "mesecons_piston_top.png", @@ -398,7 +400,7 @@ minetest.register_node("mesecons_pistons:piston_sticky_on", { -- pusher minetest.register_node("mesecons_pistons:piston_pusher_sticky", { - description = "Sticky Piston Pusher", + description = S("Sticky Piston Pusher"), drawtype = "nodebox", tiles = { "mesecons_piston_pusher_top.png", diff --git a/mesecons_pistons/locale/mesecons_pistons.eo.tr b/mesecons_pistons/locale/mesecons_pistons.eo.tr new file mode 100644 index 0000000..0eba1cc --- /dev/null +++ b/mesecons_pistons/locale/mesecons_pistons.eo.tr @@ -0,0 +1,9 @@ +# textdomain: mesecons_pistons + +### init.lua ### +Piston=Piŝto +Activated Piston Base=Aktivigita Piŝta Bazo +Piston Pusher=Piŝta Pushero +Sticky Piston=Glueca Piŝto +Activated Sticky Piston Base=Aktivigita Glueca Piŝta Bazo +Sticky Piston Pusher=Glueca Piŝta Puŝilo diff --git a/mesecons_pistons/locale/template.txt b/mesecons_pistons/locale/template.txt new file mode 100644 index 0000000..05bed8a --- /dev/null +++ b/mesecons_pistons/locale/template.txt @@ -0,0 +1,9 @@ +# textdomain: mesecons_pistons + +### init.lua ### +Piston= +Activated Piston Base= +Piston Pusher= +Sticky Piston= +Activated Sticky Piston Base= +Sticky Piston Pusher= diff --git a/mesecons_powerplant/init.lua b/mesecons_powerplant/init.lua index 90724bd..28f21b5 100644 --- a/mesecons_powerplant/init.lua +++ b/mesecons_powerplant/init.lua @@ -1,6 +1,8 @@ -- The POWER_PLANT -- Just emits power. always. +local S = minetest.get_translator(minetest.get_current_modname()) + minetest.register_node("mesecons_powerplant:power_plant", { drawtype = "plantlike", visual_scale = 1, @@ -11,7 +13,7 @@ minetest.register_node("mesecons_powerplant:power_plant", { walkable = false, groups = {dig_immediate=3, mesecon = 2}, light_source = minetest.LIGHT_MAX-9, - description="Power Plant", + description=S("Power Plant"), selection_box = { type = "fixed", fixed = {-0.3, -0.5, -0.3, 0.3, -0.5+0.7, 0.3}, diff --git a/mesecons_powerplant/locale/mesecons_powerplant.eo.tr b/mesecons_powerplant/locale/mesecons_powerplant.eo.tr new file mode 100644 index 0000000..8e539c2 --- /dev/null +++ b/mesecons_powerplant/locale/mesecons_powerplant.eo.tr @@ -0,0 +1,4 @@ +# textdomain: mesecons_powerplant + +### init.lua ### +Power Plant=Elektra Planto diff --git a/mesecons_powerplant/locale/template.txt b/mesecons_powerplant/locale/template.txt new file mode 100644 index 0000000..71eceaf --- /dev/null +++ b/mesecons_powerplant/locale/template.txt @@ -0,0 +1,4 @@ +# textdomain: mesecons_powerplant + +### init.lua ### +Power Plant= diff --git a/mesecons_pressureplates/init.lua b/mesecons_pressureplates/init.lua index 737d7cd..5c7346a 100644 --- a/mesecons_pressureplates/init.lua +++ b/mesecons_pressureplates/init.lua @@ -1,3 +1,5 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + local pp_box_off = { type = "fixed", fixed = { -7/16, -8/16, -7/16, 7/16, -7/16, 7/16 }, @@ -87,7 +89,7 @@ end mesecon.register_pressure_plate( "mesecons_pressureplates:pressure_plate_wood", - "Wooden Pressure Plate", + S("Wooden Pressure Plate"), {"jeija_pressure_plate_wood_off.png","jeija_pressure_plate_wood_off.png","jeija_pressure_plate_wood_off_edges.png"}, {"jeija_pressure_plate_wood_on.png","jeija_pressure_plate_wood_on.png","jeija_pressure_plate_wood_on_edges.png"}, "jeija_pressure_plate_wood_wield.png", @@ -98,7 +100,7 @@ mesecon.register_pressure_plate( mesecon.register_pressure_plate( "mesecons_pressureplates:pressure_plate_stone", - "Stone Pressure Plate", + S("Stone Pressure Plate"), {"jeija_pressure_plate_stone_off.png","jeija_pressure_plate_stone_off.png","jeija_pressure_plate_stone_off_edges.png"}, {"jeija_pressure_plate_stone_on.png","jeija_pressure_plate_stone_on.png","jeija_pressure_plate_stone_on_edges.png"}, "jeija_pressure_plate_stone_wield.png", diff --git a/mesecons_pressureplates/locale/mesecons_pressureplates.eo.tr b/mesecons_pressureplates/locale/mesecons_pressureplates.eo.tr new file mode 100644 index 0000000..8af30a0 --- /dev/null +++ b/mesecons_pressureplates/locale/mesecons_pressureplates.eo.tr @@ -0,0 +1,5 @@ +# textdomain: mesecons_pressureplates + +### init.lua ### +Wooden Pressure Plate=Ligna Prema Plato +Stone Pressure Plate=Ŝtona Prema Plato diff --git a/mesecons_pressureplates/locale/template.txt b/mesecons_pressureplates/locale/template.txt new file mode 100644 index 0000000..2241344 --- /dev/null +++ b/mesecons_pressureplates/locale/template.txt @@ -0,0 +1,5 @@ +# textdomain: mesecons_pressureplates + +### init.lua ### +Wooden Pressure Plate= +Stone Pressure Plate= diff --git a/mesecons_random/init.lua b/mesecons_random/init.lua index cc57a46..5342fb3 100644 --- a/mesecons_random/init.lua +++ b/mesecons_random/init.lua @@ -1,3 +1,5 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + -- REMOVESTONE minetest.register_node("mesecons_random:removestone", { @@ -5,7 +7,7 @@ minetest.register_node("mesecons_random:removestone", { is_ground_content = false, inventory_image = minetest.inventorycube("jeija_removestone_inv.png"), groups = {cracky=3}, - description="Removestone", + description = S("Removestone"), sounds = mesecon.node_sound.stone, mesecons = {effector = { action_on = function (pos, node) @@ -29,7 +31,7 @@ minetest.register_craft({ -- GHOSTSTONE minetest.register_node("mesecons_random:ghoststone", { - description="Ghoststone", + description = S("Ghoststone"), tiles = {"jeija_ghoststone.png"}, is_ground_content = false, inventory_image = minetest.inventorycube("jeija_ghoststone_inv.png"), diff --git a/mesecons_random/locale/mesecons_random.eo.tr b/mesecons_random/locale/mesecons_random.eo.tr new file mode 100644 index 0000000..ceca540 --- /dev/null +++ b/mesecons_random/locale/mesecons_random.eo.tr @@ -0,0 +1,5 @@ +# textdomain: mesecons_random + +### init.lua ### +Removestone=Forigŝtono +Ghoststone=Fantomŝtono diff --git a/mesecons_random/locale/template.txt b/mesecons_random/locale/template.txt new file mode 100644 index 0000000..55a69e8 --- /dev/null +++ b/mesecons_random/locale/template.txt @@ -0,0 +1,5 @@ +# textdomain: mesecons_random + +### init.lua ### +Removestone= +Ghoststone= diff --git a/mesecons_solarpanel/init.lua b/mesecons_solarpanel/init.lua index 84bbfd3..228f7a2 100644 --- a/mesecons_solarpanel/init.lua +++ b/mesecons_solarpanel/init.lua @@ -1,6 +1,8 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + -- Solar Panel mesecon.register_node("mesecons_solarpanel:solar_panel", { - description = "Solar Panel", + description = S("Solar Panel"), drawtype = "nodebox", tiles = {"mesecons_solarpanel.png"}, inventory_image = "mesecons_solarpanel.png", diff --git a/mesecons_solarpanel/locale/mesecons_solarpanel.eo.tr b/mesecons_solarpanel/locale/mesecons_solarpanel.eo.tr new file mode 100644 index 0000000..cdbf000 --- /dev/null +++ b/mesecons_solarpanel/locale/mesecons_solarpanel.eo.tr @@ -0,0 +1,4 @@ +# textdomain: mesecons_solarpanel + +### init.lua ### +Solar Panel=Suna Panelo diff --git a/mesecons_solarpanel/locale/template.txt b/mesecons_solarpanel/locale/template.txt new file mode 100644 index 0000000..bb8464a --- /dev/null +++ b/mesecons_solarpanel/locale/template.txt @@ -0,0 +1,4 @@ +# textdomain: mesecons_solarpanel + +### init.lua ### +Solar Panel= diff --git a/mesecons_stickyblocks/init.lua b/mesecons_stickyblocks/init.lua index 622455a..cf8695f 100644 --- a/mesecons_stickyblocks/init.lua +++ b/mesecons_stickyblocks/init.lua @@ -1,10 +1,12 @@ -- Sticky blocks can be used together with pistons or movestones to push / pull -- structures that are "glued" together using sticky blocks +local S = minetest.get_translator(minetest.get_current_modname()) + -- All sides sticky block minetest.register_node("mesecons_stickyblocks:sticky_block_all", { -- TODO: Rename to “All-Faces Sticky Block” when other sticky blocks become available - description = "Sticky Block", + description = S("Sticky Block"), tiles = {"mesecons_stickyblocks_sticky.png"}, is_ground_content = false, groups = {choppy=3, oddly_breakable_by_hand=2}, diff --git a/mesecons_stickyblocks/locale/mesecons_stickyblocks.eo.tr b/mesecons_stickyblocks/locale/mesecons_stickyblocks.eo.tr new file mode 100644 index 0000000..8ac7f94 --- /dev/null +++ b/mesecons_stickyblocks/locale/mesecons_stickyblocks.eo.tr @@ -0,0 +1,4 @@ +# textdomain: mesecons_stickyblocks + +### init.lua ### +Sticky Block=Glueca Bloko diff --git a/mesecons_stickyblocks/locale/template.txt b/mesecons_stickyblocks/locale/template.txt new file mode 100644 index 0000000..b96a697 --- /dev/null +++ b/mesecons_stickyblocks/locale/template.txt @@ -0,0 +1,4 @@ +# textdomain: mesecons_stickyblocks + +### init.lua ### +Sticky Block= diff --git a/mesecons_switch/init.lua b/mesecons_switch/init.lua index 4d650b1..a8115de 100644 --- a/mesecons_switch/init.lua +++ b/mesecons_switch/init.lua @@ -1,8 +1,10 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + -- mesecons_switch mesecon.register_node("mesecons_switch:mesecon_switch", { paramtype2="facedir", - description="Switch", + description=S("Switch"), is_ground_content = false, sounds = mesecon.node_sound.stone, on_rightclick = function (pos, node) diff --git a/mesecons_switch/locale/mesecons_switch.eo.tr b/mesecons_switch/locale/mesecons_switch.eo.tr new file mode 100644 index 0000000..abd93f0 --- /dev/null +++ b/mesecons_switch/locale/mesecons_switch.eo.tr @@ -0,0 +1,4 @@ +# textdomain: mesecons_switch + +### init.lua ### +Switch=Ŝaltilo diff --git a/mesecons_switch/locale/template.txt b/mesecons_switch/locale/template.txt new file mode 100644 index 0000000..c493778 --- /dev/null +++ b/mesecons_switch/locale/template.txt @@ -0,0 +1,4 @@ +# textdomain: mesecons_switch + +### init.lua ### +Switch= diff --git a/mesecons_torch/init.lua b/mesecons_torch/init.lua index 34f3c4d..ab2df98 100644 --- a/mesecons_torch/init.lua +++ b/mesecons_torch/init.lua @@ -1,3 +1,5 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + --MESECON TORCHES local rotate_torch_rules = function (rules, param2) @@ -85,7 +87,7 @@ minetest.register_node("mesecons_torch:mesecon_torch_on", { selection_box = torch_selectionbox, groups = {dig_immediate=3}, light_source = minetest.LIGHT_MAX-5, - description="Mesecon Torch", + description = S("Mesecon Torch"), sounds = mesecon.node_sound.default, mesecons = {receptor = { state = mesecon.state.on, diff --git a/mesecons_torch/locale/mesecons_torch.eo.tr b/mesecons_torch/locale/mesecons_torch.eo.tr new file mode 100644 index 0000000..393dc4d --- /dev/null +++ b/mesecons_torch/locale/mesecons_torch.eo.tr @@ -0,0 +1,4 @@ +# textdomain: mesecons_torch + +### init.lua ### +Mesecon Torch=Mesekonduktila Torĉo diff --git a/mesecons_torch/locale/template.txt b/mesecons_torch/locale/template.txt new file mode 100644 index 0000000..981e850 --- /dev/null +++ b/mesecons_torch/locale/template.txt @@ -0,0 +1,4 @@ +# textdomain: mesecons_torch + +### init.lua ### +Mesecon Torch= diff --git a/mesecons_walllever/init.lua b/mesecons_walllever/init.lua index 670dab5..651cd8d 100644 --- a/mesecons_walllever/init.lua +++ b/mesecons_walllever/init.lua @@ -1,8 +1,10 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + -- WALL LEVER -- Basically a switch that can be attached to a wall -- Powers the block 2 nodes behind (using a receiver) mesecon.register_node("mesecons_walllever:wall_lever", { - description="Lever", + description = S("Lever"), drawtype = "mesh", inventory_image = "jeija_wall_lever_inv.png", wield_image = "jeija_wall_lever_inv.png", diff --git a/mesecons_walllever/locale/mesecons_walllever.eo.tr b/mesecons_walllever/locale/mesecons_walllever.eo.tr new file mode 100644 index 0000000..73d0a9a --- /dev/null +++ b/mesecons_walllever/locale/mesecons_walllever.eo.tr @@ -0,0 +1,4 @@ +# textdomain: mesecons_walllever + +### init.lua ### +Lever=Levilo diff --git a/mesecons_walllever/locale/template.txt b/mesecons_walllever/locale/template.txt new file mode 100644 index 0000000..505a962 --- /dev/null +++ b/mesecons_walllever/locale/template.txt @@ -0,0 +1,4 @@ +# textdomain: mesecons_walllever + +### init.lua ### +Lever= diff --git a/mesecons_wires/init.lua b/mesecons_wires/init.lua index c7669b3..d869cde 100644 --- a/mesecons_wires/init.lua +++ b/mesecons_wires/init.lua @@ -8,6 +8,8 @@ -- ## Update wire looks ## -- ####################### +local S = minetest.get_translator(minetest.get_current_modname()) + -- self_pos = pos of any mesecon node, from_pos = pos of conductor to getconnect for local wire_getconnect = function (from_pos, self_pos) local node = minetest.get_node(self_pos) @@ -203,7 +205,7 @@ local function register_wires() end mesecon.register_node(":mesecons:wire_"..nodeid, { - description = "Mesecon", + description = S("Mesecon"), drawtype = "nodebox", inventory_image = "mesecons_wire_inv.png", wield_image = "mesecons_wire_inv.png", diff --git a/mesecons_wires/locale/mesecons_wires.eo.tr b/mesecons_wires/locale/mesecons_wires.eo.tr new file mode 100644 index 0000000..9fee95a --- /dev/null +++ b/mesecons_wires/locale/mesecons_wires.eo.tr @@ -0,0 +1,4 @@ +# textdomain: mesecons_wires + +### init.lua ### +Mesecon=Mesekonduktilo diff --git a/mesecons_wires/locale/template.txt b/mesecons_wires/locale/template.txt new file mode 100644 index 0000000..82de311 --- /dev/null +++ b/mesecons_wires/locale/template.txt @@ -0,0 +1,4 @@ +# textdomain: mesecons_wires + +### init.lua ### +Mesecon= diff --git a/settingtypes.txt b/settingtypes.txt index 5627440..688baf2 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -28,6 +28,10 @@ mesecon.luacontroller_memsize (Controller memory limit) int 100000 10000 1000000 # IID is ignored and at most one interrupt may be queued if this setting is enabled. mesecon.luacontroller_lightweight_interrupts (Lightweight interrupts) bool false +# Behavior of print() inside a luacontroller. By default, this emits a message into actionstream. +# Set it to noop if you wish to disable that behavior. +mesecon.luacontroller_print_behavior (Behavior of print) enum log log,noop + [mesecons_mvps] # In pre-existing world, MVPS may not be labelled with the owner.