Compare commits
35 Commits
4ecc694518
...
fix_crash
Author | SHA1 | Date | |
---|---|---|---|
3c9055c723 | |||
b46c589a38 | |||
ac83dead50 | |||
ff87cf3162 | |||
096df65cc6 | |||
f718816cea | |||
9ff3ab1007 | |||
368b294c70 | |||
fe57adec26 | |||
d52eac5a4a | |||
e2c8a81e7b | |||
e71cdb6f08 | |||
0c7bb316c7 | |||
0a4651c33c | |||
a82bac7b5b | |||
cffbc33e6d | |||
59780437f2 | |||
50a4bd6170 | |||
7418d5cb61 | |||
6b42419828 | |||
8e30ee4113 | |||
b318aadd0a | |||
fef402e88a | |||
f98ea14023 | |||
7f8758f17b | |||
54de66b3e1 | |||
6890624f3d | |||
2589b391e5 | |||
edcdc6817e | |||
60240ba268 | |||
c10ce2dbc5 | |||
2ede29df9c | |||
a780298cfc | |||
bd07fb0c79 | |||
121082859f |
15
.github/workflows/check-release.yml
vendored
@ -1,15 +0,0 @@
|
||||
on: [push, pull_request]
|
||||
name: Check & Release
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@main
|
||||
- name: apt
|
||||
run: sudo apt-get install -y luarocks
|
||||
- name: luacheck install
|
||||
run: luarocks install --local luacheck
|
||||
- name: luacheck run
|
||||
run: $HOME/.luarocks/bin/luacheck ./
|
41
.github/workflows/check.yml
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
on: [push, pull_request]
|
||||
name: "Check"
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
name: "Luacheck"
|
||||
steps:
|
||||
- uses: actions/checkout@main
|
||||
- name: apt
|
||||
run: sudo apt-get install -y luarocks
|
||||
- name: luacheck install
|
||||
run: luarocks install --local luacheck
|
||||
- name: luacheck run
|
||||
run: $HOME/.luarocks/bin/luacheck ./
|
||||
|
||||
mineunit:
|
||||
runs-on: ubuntu-latest
|
||||
name: "Mineunit tests"
|
||||
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
|
26
.github/workflows/test.yml
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
on: [push, pull_request]
|
||||
name: "Test"
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: "Smoke Test ${{ matrix.cfg.image }}"
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
strategy:
|
||||
matrix:
|
||||
cfg:
|
||||
- { image: 'registry.gitlab.com/minetest/minetest/server:5.0.1', mtg: false }
|
||||
- { image: 'ghcr.io/minetest/minetest:5.9.0', mtg: true }
|
||||
steps:
|
||||
- uses: actions/checkout@main
|
||||
|
||||
- uses: actions/checkout@main
|
||||
with:
|
||||
repository: 'minetest/minetest_game'
|
||||
path: ./.test/minetest_game
|
||||
if: ${{ matrix.cfg.mtg }}
|
||||
|
||||
- name: Run tests
|
||||
run: ./.test/run.sh
|
||||
env:
|
||||
DOCKER_IMAGE: "${{ matrix.cfg.image }}"
|
25
.luacheckrc
@ -27,6 +27,8 @@ read_globals = {
|
||||
"table.insert_all",
|
||||
"vector",
|
||||
"VoxelArea",
|
||||
"mcl_dyes",
|
||||
"mcl_sounds",
|
||||
}
|
||||
|
||||
globals = {"mesecon"}
|
||||
@ -34,3 +36,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"},
|
||||
}
|
||||
|
3
.test/minetest.conf
Normal file
@ -0,0 +1,3 @@
|
||||
mg_name = singlenode
|
||||
mesecon.internal_test = true
|
||||
random_mod_load_order = true
|
31
.test/run.sh
Executable file
@ -0,0 +1,31 @@
|
||||
#!/bin/bash
|
||||
tempdir=$(mktemp -d)
|
||||
confpath=$tempdir/minetest.conf
|
||||
worldpath=$tempdir/world
|
||||
trap 'rm -rf "$tempdir" || :' EXIT
|
||||
|
||||
[ -f mesecons/mod.conf ] || { echo "Must be run in modpack root folder." >&2; exit 1; }
|
||||
|
||||
command -v docker >/dev/null || { echo "Docker is not installed." >&2; exit 1; }
|
||||
mtg=.test/minetest_game
|
||||
[ -d $mtg ] || echo "A source checkout of minetest_game was not found. This can fail if your docker image does not ship a game." >&2
|
||||
|
||||
mkdir "$worldpath"
|
||||
cp -v .test/minetest.conf "$confpath"
|
||||
chmod -R 777 "$tempdir"
|
||||
|
||||
args=(
|
||||
-v "$confpath":/etc/minetest/minetest.conf
|
||||
-v "$tempdir":/var/lib/minetest/.minetest
|
||||
-v "$PWD":/var/lib/minetest/.minetest/world/worldmods/mesecons
|
||||
)
|
||||
[ -d $mtg ] && args+=(
|
||||
-v "$(realpath $mtg)":/var/lib/minetest/.minetest/games/minetest_game
|
||||
)
|
||||
args+=("$DOCKER_IMAGE")
|
||||
[ -d $mtg ] && args+=(--gameid minetest)
|
||||
docker run --rm -i "${args[@]}"
|
||||
|
||||
ls -la "$worldpath"
|
||||
test -f "$worldpath/mesecon_actionqueue" || exit 1
|
||||
exit 0
|
156
.test_fixtures/mesecons.lua
Normal file
@ -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 {<kind>, <pos>},
|
||||
-- where <kind> 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)
|
59
.test_fixtures/mesecons_fpga.lua
Normal file
@ -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
|
5
.test_fixtures/mesecons_gamecompat.lua
Normal file
@ -0,0 +1,5 @@
|
||||
fixture("mesecons")
|
||||
|
||||
mineunit:set_current_modname("mesecons_gamecompat")
|
||||
mineunit:set_modpath("mesecons_gamecompat", "../mesecons_gamecompat")
|
||||
sourcefile("../mesecons_gamecompat/init")
|
12
.test_fixtures/mesecons_luacontroller.lua
Normal file
@ -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
|
45
.test_fixtures/mesecons_mvps.lua
Normal file
@ -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
|
6
.test_fixtures/screwdriver.lua
Normal file
@ -0,0 +1,6 @@
|
||||
mineunit:set_current_modname("screwdriver")
|
||||
|
||||
screwdriver = {}
|
||||
|
||||
screwdriver.ROTATE_FACE = 1
|
||||
screwdriver.ROTATE_AXIS = 2
|
25
README.md
@ -12,6 +12,7 @@ MESECONS by Jeija and contributors
|
||||
|
||||
Mezzee-what?
|
||||
------------
|
||||
|
||||
[Mesecons](https://mesecons.net/)! They're yellow, they're conductive, and they'll add a whole new dimension to Minetest's gameplay.
|
||||
|
||||
Mesecons is a mod for [Minetest](https://www.minetest.net/) that implements a ton of items related to digital circuitry, such as wires, buttons, lights, and even programmable controllers. Among other things, there are also pistons, solar panels, pressure plates, and note blocks.
|
||||
@ -20,15 +21,18 @@ Mesecons has a similar goal to Redstone in Minecraft, but works in its own way,
|
||||
|
||||
OK, I want in.
|
||||
--------------
|
||||
|
||||
Go get it!
|
||||
|
||||
[DOWNLOAD IT NOW](https://github.com/minetest-mods/mesecons/archive/master.zip)
|
||||
[](https://content.minetest.net/packages/Jeija/mesecons/)
|
||||
|
||||
Now go ahead and install it like any other Minetest mod. Don't know how? Check out [the wonderful page about it](https://wiki.minetest.net/Mods) over at the official Minetest Wiki. For your convenience, here's a quick summary:
|
||||
Install it directly from your client by searching it in the Online Content tab.
|
||||
|
||||
**Or** if you've downloaded a ZIP file check out [this page](https://wiki.minetest.net/Mods) over at the official Minetest Wiki. For your convenience, here's a quick summary:
|
||||
|
||||
1. If Mesecons is still in a ZIP file, extract the folder inside to somewhere on the computer.
|
||||
2. Make sure that when you open the folder, you can directly find `README.md` in the listing. If you just see another folder, move that folder up one level and delete the old one.
|
||||
3. Open up the Minetest mods folder - usually `/mods/`. If you see the `minetest` or folder inside of that, that is your mod folder instead.
|
||||
3. Open up the Minetest mods folder - called `mods`.
|
||||
4. Copy the Mesecons folder into the mods folder.
|
||||
|
||||
Don't like some parts of Mesecons? Open up the Mesecons folder and delete the subfolder containing the mod you don't want. If you didn't want movestones, for example, all you have to do is delete the `mesecons_movestones` folder and they will no longer be available.
|
||||
@ -37,21 +41,21 @@ There are no dependencies - it will work right after installing!
|
||||
|
||||
How do I use this thing?
|
||||
------------------------
|
||||
|
||||
How about a [quick overview video](https://www.youtube.com/watch?v=6kmeQj6iW5k)?
|
||||
|
||||
Or maybe a [comprehensive reference](http://mesecons.net/items.html) is your style?
|
||||
Or maybe a [comprehensive reference](https://mesecons.net/items.html) is your style?
|
||||
|
||||
An overview for the very newest of new beginners? How does [this one](http://uberi.mesecons.net/projects/MeseconsBasics/index.html) look?
|
||||
An overview for the very newest of new beginners? How does [this one](https://uberi.mesecons.net/projects/MeseconsBasics/index.html) look?
|
||||
|
||||
There is also a [wiki page](https://wiki.minetest.net/Mods/Mesecons) dedicated to this mod.
|
||||
|
||||
Want to get more into building? Why not check out the [Mesecons Laboratory](http://uberi.mesecons.net/), a website dedicated to advanced Mesecons builders?
|
||||
Want to get more into building? Why not check out the [Mesecons Laboratory](https://uberi.mesecons.net/), a website dedicated to advanced Mesecons builders?
|
||||
|
||||
Want to contribute to Mesecons itself? Check out the [source code](https://github.com/minetest-mods/mesecons)!
|
||||
|
||||
Who wrote it anyways?
|
||||
---------------------
|
||||
These awesome people made Mesecons possible!
|
||||
|
||||
These awesome people made Mesecons possible! (as of 2016)
|
||||
|
||||
| Contributor | Contribution |
|
||||
| --------------- | -------------------------------- |
|
||||
@ -72,8 +76,11 @@ These awesome people made Mesecons possible!
|
||||
|
||||
There are also a whole bunch of other people helping with everything from code to testing and feedback. Mesecons would also not be possible without their help!
|
||||
|
||||
Check out the [entire contributor list](https://github.com/minetest-mods/mesecons/graphs/contributors) on GitHub.
|
||||
|
||||
Alright, how can I use it?
|
||||
--------------------------
|
||||
|
||||
All textures in this project are licensed under the CC-BY-SA 3.0 (Creative Commons Attribution-ShareAlike 3.0 Generic).
|
||||
That means you can distribute and remix them as much as you want to, under the condition that you give credit to the authors and the project, and that if you remix and release them, they must be under the same or similar license to this one.
|
||||
|
||||
|
@ -42,6 +42,7 @@
|
||||
},
|
||||
"Logic" : {
|
||||
"Luacontroller" : "mesecons_luacontroller/doc/luacontroller",
|
||||
"Microcontroller" : "mesecons_microcontroller/doc/microcontroler",
|
||||
"FPGA" : "mesecons_fpga/doc/fpga",
|
||||
"FPGA Programmer" : "mesecons_fpga/doc/programmer",
|
||||
"Torch" : "mesecons_torch/doc/torch",
|
||||
|
@ -70,7 +70,17 @@ end
|
||||
-- However, even that does not work in some cases, that's why we delay the time the globalsteps
|
||||
-- start to be execute by 4 seconds
|
||||
|
||||
local m_time = 0
|
||||
local resumetime = mesecon.setting("resumetime", 4)
|
||||
|
||||
local function globalstep_func(dtime)
|
||||
-- don't even try if server has not been running for XY seconds; resumetime = time to wait
|
||||
-- after starting the server before processing the ActionQueue, don't set this too low
|
||||
if m_time < resumetime then
|
||||
m_time = m_time + dtime
|
||||
return
|
||||
end
|
||||
|
||||
local actions = queue.actions
|
||||
-- split into two categories:
|
||||
-- actions_now: actions to execute now
|
||||
@ -112,23 +122,7 @@ local function globalstep_func(dtime)
|
||||
end
|
||||
end
|
||||
|
||||
-- delay the time the globalsteps start to be execute by 4 seconds
|
||||
do
|
||||
local m_time = 0
|
||||
local resumetime = mesecon.setting("resumetime", 4)
|
||||
local globalstep_func_index = #minetest.registered_globalsteps + 1
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
m_time = m_time + dtime
|
||||
-- don't even try if server has not been running for XY seconds; resumetime = time to wait
|
||||
-- after starting the server before processing the ActionQueue, don't set this too low
|
||||
if m_time < resumetime then
|
||||
return
|
||||
end
|
||||
-- replace this globalstep function
|
||||
minetest.registered_globalsteps[globalstep_func_index] = globalstep_func
|
||||
end)
|
||||
end
|
||||
minetest.register_globalstep(globalstep_func)
|
||||
|
||||
function queue:execute(action)
|
||||
-- ignore if action queue function name doesn't exist,
|
||||
|
@ -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,11 +117,17 @@ 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");
|
||||
|
||||
--Services like turnoff receptor on dignode and so on
|
||||
dofile(minetest.get_modpath("mesecons").."/services.lua");
|
||||
|
||||
-- Automated test run
|
||||
if mesecon.setting("internal_test", false) then
|
||||
-- currently does nothing, we only fail if some error happens right on startup
|
||||
minetest.after(5, function()
|
||||
minetest.request_shutdown()
|
||||
end)
|
||||
end
|
||||
|
@ -51,27 +51,18 @@ mesecon.fifo_queue = dofile(minetest.get_modpath("mesecons").."/fifo_queue.lua")
|
||||
|
||||
-- General
|
||||
function mesecon.get_effector(nodename)
|
||||
if minetest.registered_nodes[nodename]
|
||||
and minetest.registered_nodes[nodename].mesecons
|
||||
and minetest.registered_nodes[nodename].mesecons.effector then
|
||||
return minetest.registered_nodes[nodename].mesecons.effector
|
||||
end
|
||||
local def = minetest.registered_nodes[nodename]
|
||||
return def and def.mesecons and def.mesecons.effector
|
||||
end
|
||||
|
||||
function mesecon.get_receptor(nodename)
|
||||
if minetest.registered_nodes[nodename]
|
||||
and minetest.registered_nodes[nodename].mesecons
|
||||
and minetest.registered_nodes[nodename].mesecons.receptor then
|
||||
return minetest.registered_nodes[nodename].mesecons.receptor
|
||||
end
|
||||
local def = minetest.registered_nodes[nodename]
|
||||
return def and def.mesecons and def.mesecons.receptor
|
||||
end
|
||||
|
||||
function mesecon.get_conductor(nodename)
|
||||
if minetest.registered_nodes[nodename]
|
||||
and minetest.registered_nodes[nodename].mesecons
|
||||
and minetest.registered_nodes[nodename].mesecons.conductor then
|
||||
return minetest.registered_nodes[nodename].mesecons.conductor
|
||||
end
|
||||
local def = minetest.registered_nodes[nodename]
|
||||
return def and def.mesecons and def.mesecons.conductor
|
||||
end
|
||||
|
||||
function mesecon.get_any_outputrules(node)
|
||||
@ -542,11 +533,14 @@ function mesecon.turnoff(pos, link)
|
||||
end
|
||||
|
||||
for _, sig in ipairs(signals) do
|
||||
-- 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
|
||||
|
||||
return true
|
||||
end
|
||||
|
3
mesecons/locale/mesecons.de.tr
Normal file
@ -0,0 +1,3 @@
|
||||
# textdomain: mesecons
|
||||
|
||||
Mesecons=Mesecons
|
4
mesecons/locale/mesecons.eo.tr
Normal file
@ -0,0 +1,4 @@
|
||||
# textdomain: mesecons
|
||||
|
||||
### oldwires.lua ###
|
||||
Mesecons=Mesekonduktilo
|
4
mesecons/locale/mesecons.fr.tr
Normal file
@ -0,0 +1,4 @@
|
||||
# textdomain: mesecons
|
||||
|
||||
### oldwires.lua ###
|
||||
Mesecons=Mesecons
|
4
mesecons/locale/template.txt
Normal file
@ -0,0 +1,4 @@
|
||||
# textdomain: mesecons
|
||||
|
||||
### oldwires.lua ###
|
||||
Mesecons=
|
@ -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"
|
||||
|
@ -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
|
||||
|
62
mesecons/spec/action_spec.lua
Normal file
@ -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)
|
1
mesecons/spec/mineunit.conf
Normal file
@ -0,0 +1 @@
|
||||
fixture_paths = {"../.test_fixtures"}
|
192
mesecons/spec/service_spec.lua
Normal file
@ -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)
|
147
mesecons/spec/state_spec.lua
Normal file
@ -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)
|
Before Width: | Height: | Size: 844 B After Width: | Height: | Size: 844 B |
Before Width: | Height: | Size: 838 B After Width: | Height: | Size: 838 B |
Before Width: | Height: | Size: 851 B After Width: | Height: | Size: 851 B |
Before Width: | Height: | Size: 846 B After Width: | Height: | Size: 846 B |
@ -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",
|
||||
|
2
mesecons_blinkyplant/locale/mesecons_blinkyplant.de.tr
Normal file
@ -0,0 +1,2 @@
|
||||
# textdomain: mesecons_blinkyplant
|
||||
Blinky Plant=Blinkpflanze
|
4
mesecons_blinkyplant/locale/mesecons_blinkyplant.eo.tr
Normal file
@ -0,0 +1,4 @@
|
||||
# textdomain: mesecons_blinkyplant
|
||||
|
||||
### init.lua ###
|
||||
Blinky Plant=Palpebruma Planto
|
4
mesecons_blinkyplant/locale/mesecons_blinkyplant.fr.tr
Normal file
@ -0,0 +1,4 @@
|
||||
# textdomain: mesecons_blinkyplant
|
||||
|
||||
### init.lua ###
|
||||
Blinky Plant=Plante clignotante
|
4
mesecons_blinkyplant/locale/template.txt
Normal file
@ -0,0 +1,4 @@
|
||||
# textdomain: mesecons_blinkyplant
|
||||
|
||||
### init.lua ###
|
||||
Blinky Plant=
|
@ -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,
|
||||
|
2
mesecons_button/locale/mesecons_button.de.tr
Normal file
@ -0,0 +1,2 @@
|
||||
# textdomain: mesecons_button
|
||||
Button=Taster
|
4
mesecons_button/locale/mesecons_button.eo.tr
Normal file
@ -0,0 +1,4 @@
|
||||
# textdomain: mesecons_button
|
||||
|
||||
### init.lua ###
|
||||
Button=Butono
|
4
mesecons_button/locale/mesecons_button.fr.tr
Normal file
@ -0,0 +1,4 @@
|
||||
# textdomain: mesecons_button
|
||||
|
||||
### init.lua ###
|
||||
Button=Bouton
|
4
mesecons_button/locale/template.txt
Normal file
@ -0,0 +1,4 @@
|
||||
# textdomain: mesecons_button
|
||||
|
||||
### init.lua ###
|
||||
Button=
|
@ -1,6 +1,8 @@
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
|
||||
minetest.register_chatcommand("say", {
|
||||
params = "<text>",
|
||||
description = "Say <text> as the server",
|
||||
description = S("Say <text> 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 = "<name> <text>",
|
||||
description = "Say <text> to <name> privately",
|
||||
description = S("Say <text> to <name> 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 = "<name> <value>",
|
||||
description = "Set health of <name> to <value> hitpoints",
|
||||
description = S("Set health of <name> to <value> 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,
|
||||
|
5
mesecons_commandblock/locale/mesecons_commandblock.de.tr
Normal file
@ -0,0 +1,5 @@
|
||||
# textdomain: mesecons_commandblock
|
||||
Say <text> as the server=<Text> als Server sagen
|
||||
Say <text> to <name> privately=<Text> an <Name> privat senden
|
||||
Set health of <name> to <value> hitpoints=Gesundheit von <Name> auf <Wert> Trefferpunkte setzen
|
||||
Command Block=Befehlsblock
|
7
mesecons_commandblock/locale/mesecons_commandblock.eo.tr
Normal file
@ -0,0 +1,7 @@
|
||||
# textdomain: mesecons_commandblock
|
||||
|
||||
### init.lua ###
|
||||
Say <text> as the server=Diru <teksto> kiel la servilo
|
||||
Say <text> to <name> privately=Diru <teksto> al <nomo> private
|
||||
Set health of <name> to <value> hitpoints=Agordu sanon de <nomo> al <valoro>
|
||||
Command Block=Komando-Bloko
|
7
mesecons_commandblock/locale/mesecons_commandblock.fr.tr
Normal file
@ -0,0 +1,7 @@
|
||||
# textdomain: mesecons_commandblock
|
||||
|
||||
### init.lua ###
|
||||
Say <text> as the server=Dire <text> au serveur
|
||||
Say <text> to <name> privately=Dire <text> à <name> en privé
|
||||
Set health of <name> to <value> hitpoints=Définir la vie de <name> sur <value> cœurs
|
||||
Command Block=Bloc de commandes
|
7
mesecons_commandblock/locale/template.txt
Normal file
@ -0,0 +1,7 @@
|
||||
# textdomain: mesecons_commandblock
|
||||
|
||||
### init.lua ###
|
||||
Say <text> as the server=
|
||||
Say <text> to <name> privately=
|
||||
Set health of <name> to <value> hitpoints=
|
||||
Command Block=
|
@ -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}})
|
||||
|
||||
@ -25,20 +27,6 @@ local delaytime = { 0.1, 0.3, 0.5, 1.0 }
|
||||
|
||||
for i = 1, 4 do
|
||||
|
||||
local boxes = {
|
||||
{ -6/16, -8/16, -6/16, 6/16, -7/16, 6/16 }, -- the main slab
|
||||
|
||||
{ -2/16, -7/16, -4/16, 2/16, -26/64, -3/16 }, -- the jeweled "on" indicator
|
||||
{ -3/16, -7/16, -3/16, 3/16, -26/64, -2/16 },
|
||||
{ -4/16, -7/16, -2/16, 4/16, -26/64, 2/16 },
|
||||
{ -3/16, -7/16, 2/16, 3/16, -26/64, 3/16 },
|
||||
{ -2/16, -7/16, 3/16, 2/16, -26/64, 4/16 },
|
||||
|
||||
{ -6/16, -7/16, -6/16, -4/16, -27/64, -4/16 }, -- the timer indicator
|
||||
{ -8/16, -8/16, -1/16, -6/16, -7/16, 1/16 }, -- the two wire stubs
|
||||
{ 6/16, -8/16, -1/16, 8/16, -7/16, 1/16 }
|
||||
}
|
||||
|
||||
-- Delayer definition defaults
|
||||
local def = {
|
||||
drawtype = "nodebox",
|
||||
@ -46,11 +34,14 @@ local def = {
|
||||
walkable = true,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 },
|
||||
fixed = { -8/16, -8/16, -8/16, 8/16, -7/16, 8/16 },
|
||||
},
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = boxes
|
||||
fixed = {
|
||||
{ -8/16, -8/16, -8/16, 8/16, -7/16, 8/16 }, -- bottom slab
|
||||
{ -6/16, -7/16, -6/16, 6/16, -6/16, 6/16 }
|
||||
},
|
||||
},
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
@ -60,6 +51,8 @@ local def = {
|
||||
sounds = mesecon.node_sound.stone,
|
||||
on_blast = mesecon.on_blastnode,
|
||||
drop = "mesecons_delayer:delayer_off_1",
|
||||
delayer_onstate = "mesecons_delayer:delayer_on_"..tostring(i),
|
||||
delayer_offstate = "mesecons_delayer:delayer_off_"..tostring(i),
|
||||
}
|
||||
|
||||
-- Deactivated delayer definition defaults
|
||||
@ -69,17 +62,18 @@ if i > 1 then
|
||||
end
|
||||
|
||||
local off_state = {
|
||||
description = "Delayer",
|
||||
description = S("Delayer"),
|
||||
inventory_image = "jeija_gate_off.png^jeija_delayer.png",
|
||||
wield_image = "jeija_gate_off.png^jeija_delayer.png",
|
||||
tiles = {
|
||||
"mesecons_delayer_off_"..tostring(i)..".png",
|
||||
"mesecons_delayer_bottom.png",
|
||||
"mesecons_delayer_ends_off.png",
|
||||
"mesecons_delayer_ends_off.png",
|
||||
"mesecons_delayer_sides_off.png",
|
||||
"mesecons_delayer_sides_off.png"
|
||||
"jeija_microcontroller_bottom.png^jeija_gate_output_off.png^jeija_gate_off.png^"..
|
||||
"jeija_delayer.png^mesecons_delayer_"..tostring(i)..".png",
|
||||
"jeija_microcontroller_bottom.png^jeija_gate_output_off.png",
|
||||
"jeija_gate_side.png^jeija_gate_side_output_off.png",
|
||||
"jeija_gate_side.png",
|
||||
"jeija_gate_side.png",
|
||||
"jeija_gate_side.png",
|
||||
},
|
||||
inventory_image = "mesecons_delayer_off_1.png",
|
||||
wield_image = "mesecons_delayer_off_1.png",
|
||||
groups = off_groups,
|
||||
on_punch = function(pos, node, puncher)
|
||||
if minetest.is_protected(pos, puncher and puncher:get_player_name() or "") then
|
||||
@ -91,7 +85,6 @@ local off_state = {
|
||||
param2 = node.param2
|
||||
})
|
||||
end,
|
||||
delayer_onstate = "mesecons_delayer:delayer_on_"..tostring(i),
|
||||
mesecons = {
|
||||
receptor =
|
||||
{
|
||||
@ -101,6 +94,7 @@ local off_state = {
|
||||
effector =
|
||||
{
|
||||
rules = delayer_get_input_rules,
|
||||
action_off = delayer_deactivate,
|
||||
action_on = delayer_activate
|
||||
}
|
||||
},
|
||||
@ -112,14 +106,17 @@ 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"),
|
||||
inventory_image = "jeija_gate_on.png^jeija_delayer.png",
|
||||
wield_image = "jeija_gate_on.png^jeija_delayer.png",
|
||||
tiles = {
|
||||
"mesecons_delayer_on_"..tostring(i)..".png",
|
||||
"mesecons_delayer_bottom.png",
|
||||
"mesecons_delayer_ends_on.png",
|
||||
"mesecons_delayer_ends_on.png",
|
||||
"mesecons_delayer_sides_on.png",
|
||||
"mesecons_delayer_sides_on.png"
|
||||
"jeija_microcontroller_bottom.png^jeija_gate_output_on.png^jeija_gate_on.png^"..
|
||||
"jeija_delayer.png^mesecons_delayer_"..tostring(i)..".png",
|
||||
"jeija_microcontroller_bottom.png^jeija_gate_output_on.png",
|
||||
"jeija_gate_side.png^jeija_gate_side_output_on.png",
|
||||
"jeija_gate_side.png",
|
||||
"jeija_gate_side.png",
|
||||
"jeija_gate_side.png",
|
||||
},
|
||||
groups = {bendy = 2, snappy = 1, dig_immediate = 2, not_in_creative_inventory = 1},
|
||||
on_punch = function(pos, node, puncher)
|
||||
@ -132,7 +129,6 @@ local on_state = {
|
||||
param2 = node.param2
|
||||
})
|
||||
end,
|
||||
delayer_offstate = "mesecons_delayer:delayer_off_"..tostring(i),
|
||||
mesecons = {
|
||||
receptor =
|
||||
{
|
||||
@ -142,7 +138,8 @@ local on_state = {
|
||||
effector =
|
||||
{
|
||||
rules = delayer_get_input_rules,
|
||||
action_off = delayer_deactivate
|
||||
action_off = delayer_deactivate,
|
||||
action_on = delayer_activate
|
||||
}
|
||||
},
|
||||
}
|
||||
|
3
mesecons_delayer/locale/mesecons_delayer.de.tr
Normal file
@ -0,0 +1,3 @@
|
||||
# textdomain: mesecons_delayer
|
||||
Delayer=Verzögerer
|
||||
You hacker you=Du Hacker, Du
|
5
mesecons_delayer/locale/mesecons_delayer.eo.tr
Normal file
@ -0,0 +1,5 @@
|
||||
# textdomain: mesecons_delayer
|
||||
|
||||
### init.lua ###
|
||||
Delayer=Prokrasto
|
||||
You hacker you=Vi hakisto
|
5
mesecons_delayer/locale/mesecons_delayer.fr.tr
Normal file
@ -0,0 +1,5 @@
|
||||
# textdomain: mesecons_delayer
|
||||
|
||||
### init.lua ###
|
||||
Delayer=Retardateur
|
||||
You hacker you=Vous êtes un pirate informatique
|
5
mesecons_delayer/locale/template.txt
Normal file
@ -0,0 +1,5 @@
|
||||
# textdomain: mesecons_delayer
|
||||
|
||||
### init.lua ###
|
||||
Delayer=
|
||||
You hacker you=
|
BIN
mesecons_delayer/textures/jeija_delayer.png
Normal file
After Width: | Height: | Size: 149 B |
Before Width: | Height: | Size: 84 B After Width: | Height: | Size: 84 B |
Before Width: | Height: | Size: 84 B After Width: | Height: | Size: 84 B |
Before Width: | Height: | Size: 98 B After Width: | Height: | Size: 98 B |
Before Width: | Height: | Size: 99 B After Width: | Height: | Size: 99 B |
Before Width: | Height: | Size: 136 B After Width: | Height: | Size: 136 B |
Before Width: | Height: | Size: 109 B After Width: | Height: | Size: 109 B |
Before Width: | Height: | Size: 110 B After Width: | Height: | Size: 110 B |
BIN
mesecons_delayer/textures/mesecons_delayer_1.png
Normal file
After Width: | Height: | Size: 338 B |
BIN
mesecons_delayer/textures/mesecons_delayer_2.png
Normal file
After Width: | Height: | Size: 337 B |
BIN
mesecons_delayer/textures/mesecons_delayer_3.png
Normal file
After Width: | Height: | Size: 339 B |
BIN
mesecons_delayer/textures/mesecons_delayer_4.png
Normal file
After Width: | Height: | Size: 334 B |
Before Width: | Height: | Size: 221 B |
Before Width: | Height: | Size: 176 B |
Before Width: | Height: | Size: 187 B |
Before Width: | Height: | Size: 448 B |
Before Width: | Height: | Size: 449 B |
Before Width: | Height: | Size: 448 B |
Before Width: | Height: | Size: 446 B |
Before Width: | Height: | Size: 541 B |
Before Width: | Height: | Size: 541 B |
Before Width: | Height: | Size: 541 B |
Before Width: | Height: | Size: 538 B |
Before Width: | Height: | Size: 173 B |
Before Width: | Height: | Size: 181 B |
@ -1,7 +1,19 @@
|
||||
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"
|
||||
|
||||
|
||||
local function comma_list_to_table(comma_list)
|
||||
local tbl = {}
|
||||
for _, str in ipairs(string.split(comma_list:gsub("%s", ""), ",")) do
|
||||
tbl[str] = true
|
||||
end
|
||||
return tbl
|
||||
end
|
||||
|
||||
|
||||
-- Object detector
|
||||
-- Detects players in a certain radius
|
||||
-- The radius can be specified in mesecons/settings.lua
|
||||
@ -33,10 +45,7 @@ local function object_detector_scan(pos)
|
||||
if next(objs) == nil then return false end
|
||||
|
||||
local scanname = minetest.get_meta(pos):get_string("scanname")
|
||||
local scan_for = {}
|
||||
for _, str in pairs(string.split(scanname:gsub(" ", ""), ",")) do
|
||||
scan_for[str] = true
|
||||
end
|
||||
local scan_for = comma_list_to_table(scanname)
|
||||
|
||||
local every_player = scanname == ""
|
||||
for _, obj in pairs(objs) do
|
||||
@ -71,7 +80,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
|
||||
@ -186,8 +195,9 @@ local function node_detector_scan(pos)
|
||||
vector.subtract(pos, vector.multiply(minetest.facedir_to_dir(node.param2), distance + 1))
|
||||
).name
|
||||
local scanname = meta:get_string("scanname")
|
||||
local scan_for = comma_list_to_table(scanname)
|
||||
|
||||
return (frontname == scanname) or
|
||||
return (scan_for[frontname]) or
|
||||
(frontname ~= "air" and frontname ~= "ignore" and scanname == "")
|
||||
end
|
||||
|
||||
@ -213,10 +223,10 @@ local node_detector_digiline = {
|
||||
|
||||
if type(msg) == "table" then
|
||||
if msg.distance or msg.scanname then
|
||||
if msg.distance then
|
||||
if type(msg.distance) == "number" or type(msg.distance) == "string" then
|
||||
meta:set_string("distance", msg.distance)
|
||||
end
|
||||
if msg.scanname then
|
||||
if type(msg.scanname) == "string" then
|
||||
meta:set_string("scanname", msg.scanname)
|
||||
end
|
||||
node_detector_make_formspec(pos)
|
||||
@ -230,7 +240,7 @@ local node_detector_digiline = {
|
||||
else
|
||||
if msg == GET_COMMAND then
|
||||
node_detector_send_node_name(pos, node, channel, meta)
|
||||
else
|
||||
elseif type(msg) == "string" then
|
||||
meta:set_string("scanname", msg)
|
||||
node_detector_make_formspec(pos)
|
||||
end
|
||||
@ -247,7 +257,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
|
||||
}},
|
||||
|
3
mesecons_detector/locale/mesecons_detector.de.tr
Normal file
@ -0,0 +1,3 @@
|
||||
# textdomain: mesecons_detector
|
||||
Player Detector=Spielerdetektor
|
||||
Node Detector=Blockdetektor
|
5
mesecons_detector/locale/mesecons_detector.eo.tr
Normal file
@ -0,0 +1,5 @@
|
||||
# textdomain: mesecons_detector
|
||||
|
||||
### init.lua ###
|
||||
Player Detector=Ludanta Detektilo
|
||||
Node Detector=Noda Detektilo
|
5
mesecons_detector/locale/mesecons_detector.fr.tr
Normal file
@ -0,0 +1,5 @@
|
||||
# textdomain: mesecons_detector
|
||||
|
||||
### init.lua ###
|
||||
Player Detector=Détecteur de joueur
|
||||
Node Detector=Détecteur de bloc
|
5
mesecons_detector/locale/template.txt
Normal file
@ -0,0 +1,5 @@
|
||||
# textdomain: mesecons_detector
|
||||
|
||||
### init.lua ###
|
||||
Player Detector=
|
||||
Node Detector=
|
@ -22,6 +22,11 @@ end
|
||||
local function meseconify_door(name)
|
||||
if minetest.registered_items[name .. "_b_1"] then
|
||||
-- old style double-node doors
|
||||
if minetest.registered_items[name .. "_b_1"].mesecons then
|
||||
minetest.log("info", "[mesecons_doors] Not touching door " .. name)
|
||||
return
|
||||
end
|
||||
|
||||
local function toggle_state1 (pos)
|
||||
on_rightclick(pos, 1, name.."_t_1", name.."_b_2", name.."_t_2", {1,2,3,0})
|
||||
end
|
||||
@ -47,6 +52,10 @@ local function meseconify_door(name)
|
||||
})
|
||||
elseif minetest.registered_items[name .. "_a"] then
|
||||
-- new style mesh node based doors
|
||||
if minetest.registered_items[name .. "_a"].mesecons then
|
||||
minetest.log("info", "[mesecons_doors] Not touching door " .. name)
|
||||
return
|
||||
end
|
||||
local override = {
|
||||
mesecons = {effector = {
|
||||
action_on = function(pos)
|
||||
@ -73,29 +82,25 @@ local function meseconify_door(name)
|
||||
end
|
||||
end
|
||||
|
||||
meseconify_door("doors:door_wood")
|
||||
meseconify_door("doors:door_steel")
|
||||
meseconify_door("doors:door_glass")
|
||||
meseconify_door("doors:door_obsidian_glass")
|
||||
meseconify_door("xpanes:door_steel_bar")
|
||||
|
||||
-- Trapdoor
|
||||
local function trapdoor_switch(pos, node)
|
||||
local function trapdoor_switch(name)
|
||||
return function(pos, node)
|
||||
local state = minetest.get_meta(pos):get_int("state")
|
||||
|
||||
if state == 1 then
|
||||
minetest.sound_play("doors_door_close", { pos = pos, gain = 0.3, max_hear_distance = 10 }, true)
|
||||
minetest.set_node(pos, {name="doors:trapdoor", param2 = node.param2})
|
||||
minetest.set_node(pos, {name=name, param2 = node.param2})
|
||||
else
|
||||
minetest.sound_play("doors_door_open", { pos = pos, gain = 0.3, max_hear_distance = 10 }, true)
|
||||
minetest.set_node(pos, {name="doors:trapdoor_open", param2 = node.param2})
|
||||
minetest.set_node(pos, {name=name.."_open", param2 = node.param2})
|
||||
end
|
||||
|
||||
minetest.get_meta(pos):set_int("state", state == 1 and 0 or 1)
|
||||
end
|
||||
end
|
||||
|
||||
if doors and doors.get then
|
||||
local override = {
|
||||
local function meseconify_trapdoor(name)
|
||||
local override
|
||||
if doors and doors.get then
|
||||
override = {
|
||||
mesecons = {effector = {
|
||||
action_on = function(pos)
|
||||
local door = doors.get(pos)
|
||||
@ -111,30 +116,32 @@ if doors and doors.get then
|
||||
end,
|
||||
}},
|
||||
}
|
||||
minetest.override_item("doors:trapdoor", override)
|
||||
minetest.override_item("doors:trapdoor_open", override)
|
||||
minetest.override_item("doors:trapdoor_steel", override)
|
||||
minetest.override_item("doors:trapdoor_steel_open", override)
|
||||
|
||||
if minetest.registered_items["xpanes:trapdoor_steel_bar"] then
|
||||
minetest.override_item("xpanes:trapdoor_steel_bar", override)
|
||||
minetest.override_item("xpanes:trapdoor_steel_bar_open", override)
|
||||
else
|
||||
override = {
|
||||
mesecons = {effector = {
|
||||
action_on = trapdoor_switch(name),
|
||||
action_off = trapdoor_switch(name)
|
||||
}},
|
||||
}
|
||||
end
|
||||
|
||||
else
|
||||
if minetest.registered_nodes["doors:trapdoor"] then
|
||||
minetest.override_item("doors:trapdoor", {
|
||||
mesecons = {effector = {
|
||||
action_on = trapdoor_switch,
|
||||
action_off = trapdoor_switch
|
||||
}},
|
||||
})
|
||||
|
||||
minetest.override_item("doors:trapdoor_open", {
|
||||
mesecons = {effector = {
|
||||
action_on = trapdoor_switch,
|
||||
action_off = trapdoor_switch
|
||||
}},
|
||||
})
|
||||
if minetest.registered_items[name] then
|
||||
minetest.override_item(name, override)
|
||||
minetest.override_item(name.."_open", override)
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_on_mods_loaded(function()
|
||||
if doors.registered_doors ~= nil then -- registered_doors is not always available
|
||||
for k,_ in pairs(doors.registered_doors) do
|
||||
if k:find("_a$") then
|
||||
meseconify_door(k:sub(1,-3))
|
||||
end
|
||||
end
|
||||
for k,_ in pairs(doors.registered_trapdoors) do
|
||||
if not k:find("_open$") then
|
||||
meseconify_trapdoor(k)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
@ -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"}
|
||||
})
|
||||
|
@ -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",
|
||||
|
@ -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 },
|
||||
|
8
mesecons_extrawires/locale/mesecons_extrawires.de.tr
Normal file
@ -0,0 +1,8 @@
|
||||
# textdomain: mesecons_extrawires
|
||||
Insulated Mesecon Corner=Isolierte Meseconecke
|
||||
Insulated Mesecon Crossover=Isolierter Meseconübergang
|
||||
You hacker you!=Sie Hacker!
|
||||
Insulated Mesecon Double Corner=Isolierte Mesecondoppelecke
|
||||
Mese Wire=Mesedraht
|
||||
Insulated Mesecon T-junction=Isolierte Mesecongabelung
|
||||
Vertical Mesecon=Vertikaler Mesecon
|
20
mesecons_extrawires/locale/mesecons_extrawires.eo.tr
Normal file
@ -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
|
20
mesecons_extrawires/locale/mesecons_extrawires.fr.tr
Normal file
@ -0,0 +1,20 @@
|
||||
# textdomain: mesecons_extrawires
|
||||
|
||||
### corner.lua ###
|
||||
Insulated Mesecon Corner=Coin de Mesecon isolé
|
||||
|
||||
### crossover.lua ###
|
||||
Insulated Mesecon Crossover=Croisement de Mesecon isolé
|
||||
You hacker you!=Vous êtes un pirate informatique !
|
||||
|
||||
### doublecorner.lua ###
|
||||
Insulated Mesecon Double Corner=Double coin de Mesecon isolé
|
||||
|
||||
### mesewire.lua ###
|
||||
Mese Wire=Câble de Mesecon
|
||||
|
||||
### tjunction.lua ###
|
||||
Insulated Mesecon T-junction=Croisement en T de Mesecon isolé
|
||||
|
||||
### vertical.lua ###
|
||||
Vertical Mesecon=Mesecon vertical
|
20
mesecons_extrawires/locale/template.txt
Normal file
@ -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=
|
@ -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,
|
||||
|
@ -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",
|
||||
|
@ -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}
|
||||
@ -38,17 +40,22 @@ local bottom_rules = {
|
||||
{x=0, y=2, z=0} -- receive power from pressure plate / detector / ... 2 nodes above
|
||||
}
|
||||
|
||||
local function is_vertical_conductor(nodename)
|
||||
local def = minetest.registered_nodes[nodename]
|
||||
return def and def.is_vertical_conductor
|
||||
end
|
||||
|
||||
local vertical_updatepos = function (pos)
|
||||
local node = minetest.get_node(pos)
|
||||
if minetest.registered_nodes[node.name]
|
||||
and minetest.registered_nodes[node.name].is_vertical_conductor then
|
||||
if not is_vertical_conductor(node.name) then
|
||||
return
|
||||
end
|
||||
|
||||
local node_above = minetest.get_node(vector.add(pos, vertical_rules[1]))
|
||||
local node_below = minetest.get_node(vector.add(pos, vertical_rules[2]))
|
||||
|
||||
local above = minetest.registered_nodes[node_above.name]
|
||||
and minetest.registered_nodes[node_above.name].is_vertical_conductor
|
||||
local below = minetest.registered_nodes[node_below.name]
|
||||
and minetest.registered_nodes[node_below.name].is_vertical_conductor
|
||||
local above = is_vertical_conductor(node_above.name)
|
||||
local below = is_vertical_conductor(node_below.name)
|
||||
|
||||
mesecon.on_dignode(pos, node)
|
||||
|
||||
@ -66,7 +73,6 @@ local vertical_updatepos = function (pos)
|
||||
|
||||
minetest.set_node(pos, {name = newname})
|
||||
mesecon.on_placenode(pos, {name = newname})
|
||||
end
|
||||
end
|
||||
|
||||
local vertical_update = function (pos)
|
||||
@ -77,7 +83,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 +116,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 +148,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",
|
||||
|
@ -1,3 +1,5 @@
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
|
||||
local plg = {}
|
||||
plg.rules = {}
|
||||
-- per-player formspec positions
|
||||
@ -18,10 +20,10 @@ plg.register_nodes = function(template)
|
||||
|
||||
-- build top texture string
|
||||
local texture = "jeija_fpga_top.png"
|
||||
if a == 1 then texture = texture .. "^jeija_microcontroller_LED_A.png" end
|
||||
if b == 1 then texture = texture .. "^jeija_microcontroller_LED_B.png" end
|
||||
if c == 1 then texture = texture .. "^jeija_microcontroller_LED_C.png" end
|
||||
if d == 1 then texture = texture .. "^jeija_microcontroller_LED_D.png" end
|
||||
if a == 1 then texture = texture .. "^jeija_luacontroller_LED_A.png" end
|
||||
if b == 1 then texture = texture .. "^jeija_luacontroller_LED_B.png" end
|
||||
if c == 1 then texture = texture .. "^jeija_luacontroller_LED_C.png" end
|
||||
if d == 1 then texture = texture .. "^jeija_luacontroller_LED_D.png" end
|
||||
ndef.tiles[1] = texture
|
||||
ndef.inventory_image = texture
|
||||
|
||||
@ -59,7 +61,7 @@ plg.register_nodes = function(template)
|
||||
end
|
||||
|
||||
plg.register_nodes({
|
||||
description = "FPGA",
|
||||
description = S("FPGA"),
|
||||
drawtype = "nodebox",
|
||||
tiles = {
|
||||
"", -- replaced later
|
||||
|
3
mesecons_fpga/locale/mesecons_fpga.de.tr
Normal file
@ -0,0 +1,3 @@
|
||||
# textdomain: mesecons_fpga
|
||||
FPGA=FPGA
|
||||
FPGA Programmer=FPGA-Programmierer
|
7
mesecons_fpga/locale/mesecons_fpga.eo.tr
Normal file
@ -0,0 +1,7 @@
|
||||
# textdomain: mesecons_fpga
|
||||
|
||||
### init.lua ###
|
||||
FPGA=FPGA
|
||||
|
||||
### tool.lua ###
|
||||
FPGA Programmer=FPGA Programilo
|
7
mesecons_fpga/locale/mesecons_fpga.fr.tr
Normal file
@ -0,0 +1,7 @@
|
||||
# textdomain: mesecons_fpga
|
||||
|
||||
### init.lua ###
|
||||
FPGA=Circuit logique programmable (FPGA)
|
||||
|
||||
### tool.lua ###
|
||||
FPGA Programmer=Programmateur de circuit logique
|
7
mesecons_fpga/locale/template.txt
Normal file
@ -0,0 +1,7 @@
|
||||
# textdomain: mesecons_fpga
|
||||
|
||||
### init.lua ###
|
||||
FPGA=
|
||||
|
||||
### tool.lua ###
|
||||
FPGA Programmer=
|
106
mesecons_fpga/spec/helper_spec.lua
Normal file
@ -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)
|
235
mesecons_fpga/spec/logic_spec.lua
Normal file
@ -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)
|
1
mesecons_fpga/spec/mineunit.conf
Normal file
@ -0,0 +1 @@
|
||||
fixture_paths = {"../.test_fixtures"}
|