forked from minetest-mods/mesecons
		
	Compare commits
	
		
			23 Commits
		
	
	
		
			3dd0eb7e4f
			...
			detector_b
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					32e1cc63f2 | ||
| 
						 | 
					cffbc33e6d | ||
| 
						 | 
					59780437f2 | ||
| 
						 | 
					50a4bd6170 | ||
| 
						 | 
					7418d5cb61 | ||
| 
						 | 
					6b42419828 | ||
| 
						 | 
					8e30ee4113 | ||
| 
						 | 
					b318aadd0a | ||
| 
						 | 
					fef402e88a | ||
| 
						 | 
					f98ea14023 | ||
| 
						 | 
					7f8758f17b | ||
| 
						 | 
					54de66b3e1 | ||
| 
						 | 
					6890624f3d | ||
| 
						 | 
					2589b391e5 | ||
| 
						 | 
					edcdc6817e | ||
| 
						 | 
					60240ba268 | ||
| 
						 | 
					c10ce2dbc5 | ||
| 
						 | 
					2ede29df9c | ||
| 
						 | 
					a780298cfc | ||
| 
						 | 
					bd07fb0c79 | ||
| 
						 | 
					121082859f | ||
| 
						 | 
					68171b3d8d | ||
| 
						 | 
					da57a6214a | 
							
								
								
									
										26
									
								
								.github/workflows/check-release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								.github/workflows/check-release.yml
									
									
									
									
										vendored
									
									
								
							@@ -13,3 +13,29 @@ jobs:
 | 
			
		||||
      run: luarocks install --local luacheck
 | 
			
		||||
    - name: luacheck run
 | 
			
		||||
      run: $HOME/.luarocks/bin/luacheck ./
 | 
			
		||||
 | 
			
		||||
  test:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
    - uses: actions/checkout@main
 | 
			
		||||
    - name: apt
 | 
			
		||||
      run: sudo apt-get install -y luarocks
 | 
			
		||||
    - name: busted install
 | 
			
		||||
      run: luarocks install --local busted
 | 
			
		||||
    - name: luacov install
 | 
			
		||||
      run: luarocks install --local luacov
 | 
			
		||||
    - name: mineunit install
 | 
			
		||||
      run: luarocks install --server=https://luarocks.org/dev --local mineunit
 | 
			
		||||
    - name: run mesecons tests
 | 
			
		||||
      working-directory: ./mesecons/
 | 
			
		||||
      run: $HOME/.luarocks/bin/mineunit -q
 | 
			
		||||
    - name: run mesecons_mvps tests
 | 
			
		||||
      working-directory: ./mesecons_mvps/
 | 
			
		||||
      run: $HOME/.luarocks/bin/mineunit -q
 | 
			
		||||
    - name: run mesecons_fpga tests
 | 
			
		||||
      working-directory: ./mesecons_fpga/
 | 
			
		||||
      run: $HOME/.luarocks/bin/mineunit -q
 | 
			
		||||
    - name: run mesecons_luacontroller tests
 | 
			
		||||
      working-directory: ./mesecons_luacontroller/
 | 
			
		||||
      run: $HOME/.luarocks/bin/mineunit -q
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										23
									
								
								.luacheckrc
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								.luacheckrc
									
									
									
									
									
								
							@@ -34,3 +34,26 @@ globals = {"mesecon"}
 | 
			
		||||
files["mesecons/actionqueue.lua"] = {
 | 
			
		||||
	globals = {"minetest.registered_globalsteps"},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
-- Test-specific stuff follows.
 | 
			
		||||
 | 
			
		||||
local test_conf = {
 | 
			
		||||
	read_globals = {
 | 
			
		||||
		"assert",
 | 
			
		||||
		"fixture",
 | 
			
		||||
		"mineunit",
 | 
			
		||||
		"Player",
 | 
			
		||||
		"sourcefile",
 | 
			
		||||
		"world",
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
files["*/spec/*.lua"] = test_conf
 | 
			
		||||
files[".test_fixtures/*.lua"] = test_conf
 | 
			
		||||
 | 
			
		||||
files[".test_fixtures/screwdriver.lua"] = {
 | 
			
		||||
	globals = {"screwdriver"},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
files[".test_fixtures/mesecons_fpga.lua"] = {
 | 
			
		||||
	globals = {"minetest.register_on_player_receive_fields"},
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										156
									
								
								.test_fixtures/mesecons.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										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
									
								
							
							
						
						
									
										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
									
								
							
							
						
						
									
										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
									
								
							
							
						
						
									
										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
									
								
							
							
						
						
									
										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
									
								
							
							
						
						
									
										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
 | 
			
		||||
@@ -99,7 +99,6 @@ mesecon.queue:add_function("receptor_off", function (pos, rules)
 | 
			
		||||
		local rulenames = mesecon.rules_link_rule_all(pos, rule)
 | 
			
		||||
		for _, rulename in ipairs(rulenames) do
 | 
			
		||||
			mesecon.vm_begin()
 | 
			
		||||
			mesecon.changesignal(np, minetest.get_node(np), rulename, mesecon.state.off, 2)
 | 
			
		||||
 | 
			
		||||
			-- Turnoff returns true if turnoff process was successful, no onstate receptor
 | 
			
		||||
			-- was found along the way. Commit changes that were made in voxelmanip. If turnoff
 | 
			
		||||
@@ -118,8 +117,6 @@ function mesecon.receptor_off(pos, rules)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
print("[OK] Mesecons")
 | 
			
		||||
 | 
			
		||||
-- Deprecated stuff
 | 
			
		||||
-- To be removed in future releases
 | 
			
		||||
dofile(minetest.get_modpath("mesecons").."/legacy.lua");
 | 
			
		||||
 
 | 
			
		||||
@@ -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,9 +533,12 @@ function mesecon.turnoff(pos, link)
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	for _, sig in ipairs(signals) do
 | 
			
		||||
		mesecon.changesignal(sig.pos, sig.node, sig.link, mesecon.state.off, sig.depth)
 | 
			
		||||
		if mesecon.is_effector_on(sig.node.name) and not mesecon.is_powered(sig.pos) then
 | 
			
		||||
			mesecon.deactivate(sig.pos, sig.node, sig.link, sig.depth)
 | 
			
		||||
		-- If sig.depth is 1, it has not yet been checked that the power source is actually off.
 | 
			
		||||
		if sig.depth > 1 or not mesecon.is_powered(sig.pos, sig.link) then
 | 
			
		||||
			mesecon.changesignal(sig.pos, sig.node, sig.link, mesecon.state.off, sig.depth)
 | 
			
		||||
			if mesecon.is_effector_on(sig.node.name) and not mesecon.is_powered(sig.pos) then
 | 
			
		||||
				mesecon.deactivate(sig.pos, sig.node, sig.link, sig.depth)
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								mesecons/locale/mesecons.de.tr
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								mesecons/locale/mesecons.de.tr
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
# textdomain: mesecons
 | 
			
		||||
 | 
			
		||||
Mesecons=Mesecons
 | 
			
		||||
							
								
								
									
										4
									
								
								mesecons/locale/mesecons.eo.tr
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								mesecons/locale/mesecons.eo.tr
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
# textdomain: mesecons
 | 
			
		||||
 | 
			
		||||
### oldwires.lua ###
 | 
			
		||||
Mesecons=Mesekonduktilo
 | 
			
		||||
							
								
								
									
										4
									
								
								mesecons/locale/template.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										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
									
								
							
							
						
						
									
										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
									
								
							
							
						
						
									
										1
									
								
								mesecons/spec/mineunit.conf
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
fixture_paths = {"../.test_fixtures"}
 | 
			
		||||
							
								
								
									
										192
									
								
								mesecons/spec/service_spec.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										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
									
								
							
							
						
						
									
										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)
 | 
			
		||||
@@ -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
									
								
							
							
						
						
									
										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
									
								
							
							
						
						
									
										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/template.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										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
									
								
							
							
						
						
									
										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
									
								
							
							
						
						
									
										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/template.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										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
									
								
							
							
						
						
									
										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
									
								
							
							
						
						
									
										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/template.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										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}})
 | 
			
		||||
 | 
			
		||||
@@ -60,6 +62,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,7 +73,7 @@ if i > 1 then
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local off_state = {
 | 
			
		||||
	description = "Delayer",
 | 
			
		||||
	description = S("Delayer"),
 | 
			
		||||
	tiles = {
 | 
			
		||||
		"mesecons_delayer_off_"..tostring(i)..".png",
 | 
			
		||||
		"mesecons_delayer_bottom.png",
 | 
			
		||||
@@ -91,7 +95,6 @@ local off_state = {
 | 
			
		||||
			param2 = node.param2
 | 
			
		||||
		})
 | 
			
		||||
	end,
 | 
			
		||||
	delayer_onstate = "mesecons_delayer:delayer_on_"..tostring(i),
 | 
			
		||||
	mesecons = {
 | 
			
		||||
		receptor =
 | 
			
		||||
		{
 | 
			
		||||
@@ -101,6 +104,7 @@ local off_state = {
 | 
			
		||||
		effector =
 | 
			
		||||
		{
 | 
			
		||||
			rules = delayer_get_input_rules,
 | 
			
		||||
			action_off = delayer_deactivate,
 | 
			
		||||
			action_on = delayer_activate
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
@@ -112,7 +116,7 @@ minetest.register_node("mesecons_delayer:delayer_off_"..tostring(i), off_state)
 | 
			
		||||
 | 
			
		||||
-- Activated delayer definition defaults
 | 
			
		||||
local on_state = {
 | 
			
		||||
	description = "You hacker you",
 | 
			
		||||
	description = S("You hacker you"),
 | 
			
		||||
	tiles = {
 | 
			
		||||
		"mesecons_delayer_on_"..tostring(i)..".png",
 | 
			
		||||
		"mesecons_delayer_bottom.png",
 | 
			
		||||
@@ -132,7 +136,6 @@ local on_state = {
 | 
			
		||||
			param2 = node.param2
 | 
			
		||||
		})
 | 
			
		||||
	end,
 | 
			
		||||
	delayer_offstate = "mesecons_delayer:delayer_off_"..tostring(i),
 | 
			
		||||
	mesecons = {
 | 
			
		||||
		receptor =
 | 
			
		||||
		{
 | 
			
		||||
@@ -142,7 +145,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
									
								
							
							
						
						
									
										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
									
								
							
							
						
						
									
										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/template.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								mesecons_delayer/locale/template.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
# textdomain: mesecons_delayer
 | 
			
		||||
 | 
			
		||||
### init.lua ###
 | 
			
		||||
Delayer=
 | 
			
		||||
You hacker you=
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -148,6 +157,23 @@ minetest.register_abm({
 | 
			
		||||
-- Node detector
 | 
			
		||||
-- Detects the node in front of it
 | 
			
		||||
 | 
			
		||||
local blacklist = {
 | 
			
		||||
	air = true,
 | 
			
		||||
	ignore = true,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function mesecon.node_detector_blacklist_add(node)
 | 
			
		||||
	blacklist[node] = true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function mesecon.node_detector_blacklist_remove(node)
 | 
			
		||||
	blacklist[node] = nil
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function mesecon.node_detector_on_blacklist(node)
 | 
			
		||||
	return blacklist[node] == true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function node_detector_make_formspec(pos)
 | 
			
		||||
	local meta = minetest.get_meta(pos)
 | 
			
		||||
	if meta:get_string("distance") == ""  then meta:set_string("distance", "0") end
 | 
			
		||||
@@ -186,9 +212,10 @@ 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
 | 
			
		||||
		(frontname ~= "air" and frontname ~= "ignore" and scanname == "")
 | 
			
		||||
	return (scan_for[frontname]) or
 | 
			
		||||
		(blacklist[frontname] ~= true and scanname == "")
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function node_detector_send_node_name(pos, node, channel, meta)
 | 
			
		||||
@@ -247,7 +274,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
									
								
							
							
						
						
									
										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
									
								
							
							
						
						
									
										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/template.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								mesecons_detector/locale/template.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
# textdomain: mesecons_detector
 | 
			
		||||
 | 
			
		||||
### init.lua ###
 | 
			
		||||
Player Detector=
 | 
			
		||||
Node Detector=
 | 
			
		||||
@@ -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
									
								
							
							
						
						
									
										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
									
								
							
							
						
						
									
										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/template.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										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,35 +40,39 @@ 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
 | 
			
		||||
		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
 | 
			
		||||
 | 
			
		||||
		mesecon.on_dignode(pos, node)
 | 
			
		||||
 | 
			
		||||
		-- Always place offstate conductor and let mesecon.on_placenode take care
 | 
			
		||||
		local newname = "mesecons_extrawires:vertical_"
 | 
			
		||||
		if above and below then -- above and below: vertical mesecon
 | 
			
		||||
			newname = newname .. "off"
 | 
			
		||||
		elseif above and not below then -- above only: bottom
 | 
			
		||||
			newname = newname .. "bottom_off"
 | 
			
		||||
		elseif not above and below then -- below only: top
 | 
			
		||||
			newname = newname .. "top_off"
 | 
			
		||||
		else -- no vertical wire above, no vertical wire below: use bottom
 | 
			
		||||
			newname = newname .. "bottom_off"
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		minetest.set_node(pos, {name = newname})
 | 
			
		||||
		mesecon.on_placenode(pos, {name = newname})
 | 
			
		||||
	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 = is_vertical_conductor(node_above.name)
 | 
			
		||||
	local below = is_vertical_conductor(node_below.name)
 | 
			
		||||
 | 
			
		||||
	mesecon.on_dignode(pos, node)
 | 
			
		||||
 | 
			
		||||
	-- Always place offstate conductor and let mesecon.on_placenode take care
 | 
			
		||||
	local newname = "mesecons_extrawires:vertical_"
 | 
			
		||||
	if above and below then -- above and below: vertical mesecon
 | 
			
		||||
		newname = newname .. "off"
 | 
			
		||||
	elseif above and not below then -- above only: bottom
 | 
			
		||||
		newname = newname .. "bottom_off"
 | 
			
		||||
	elseif not above and below then -- below only: top
 | 
			
		||||
		newname = newname .. "top_off"
 | 
			
		||||
	else -- no vertical wire above, no vertical wire below: use bottom
 | 
			
		||||
		newname = newname .. "bottom_off"
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	minetest.set_node(pos, {name = newname})
 | 
			
		||||
	mesecon.on_placenode(pos, {name = newname})
 | 
			
		||||
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
 | 
			
		||||
@@ -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
									
								
							
							
						
						
									
										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
									
								
							
							
						
						
									
										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/template.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										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
									
								
							
							
						
						
									
										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
									
								
							
							
						
						
									
										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
									
								
							
							
						
						
									
										1
									
								
								mesecons_fpga/spec/mineunit.conf
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
fixture_paths = {"../.test_fixtures"}
 | 
			
		||||
@@ -1,8 +1,10 @@
 | 
			
		||||
local S = minetest.get_translator(minetest.get_current_modname())
 | 
			
		||||
 | 
			
		||||
return function(plg)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
minetest.register_tool("mesecons_fpga:programmer", {
 | 
			
		||||
	description = "FPGA Programmer",
 | 
			
		||||
	description = S("FPGA Programmer"),
 | 
			
		||||
	inventory_image = "jeija_fpga_programmer.png",
 | 
			
		||||
	stack_max = 1,
 | 
			
		||||
	on_place = function(itemstack, placer, pointed_thing)
 | 
			
		||||
@@ -21,7 +23,7 @@ minetest.register_tool("mesecons_fpga:programmer", {
 | 
			
		||||
			minetest.sound_play("mesecons_fpga_fail", { pos = placer:get_pos(), gain = 0.1, max_hear_distance = 4 }, true)
 | 
			
		||||
			return itemstack
 | 
			
		||||
		end
 | 
			
		||||
		itemstack:set_metadata(meta:get_string("instr"))
 | 
			
		||||
		itemstack:get_meta():set_string("", meta:get_string("instr"))
 | 
			
		||||
		minetest.chat_send_player(placer:get_player_name(), "FPGA gate configuration was successfully copied!")
 | 
			
		||||
		minetest.sound_play("mesecons_fpga_copy", { pos = placer:get_pos(), gain = 0.1, max_hear_distance = 4 }, true)
 | 
			
		||||
 | 
			
		||||
@@ -42,7 +44,7 @@ minetest.register_tool("mesecons_fpga:programmer", {
 | 
			
		||||
			return itemstack
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		local imeta = itemstack:get_metadata()
 | 
			
		||||
		local imeta = itemstack:get_meta():get_string("")
 | 
			
		||||
		if imeta == "" then
 | 
			
		||||
			minetest.chat_send_player(player_name, "Use shift+right-click to copy a gate configuration first.")
 | 
			
		||||
			minetest.sound_play("mesecons_fpga_fail", { pos = user:get_pos(), gain = 0.1, max_hear_distance = 4 }, true)
 | 
			
		||||
 
 | 
			
		||||
@@ -59,6 +59,10 @@ if minetest.get_modpath("mesecons_mvps") then
 | 
			
		||||
		"doors:hidden",
 | 
			
		||||
		"doors:trapdoor_steel",
 | 
			
		||||
		"doors:trapdoor_steel_open",
 | 
			
		||||
		"beds:bed_bottom",
 | 
			
		||||
		"beds:bed_top",
 | 
			
		||||
		"beds:fancy_bed_bottom",
 | 
			
		||||
		"beds:fancy_bed_top",
 | 
			
		||||
		"xpanes:door_steel_bar_a",
 | 
			
		||||
		"xpanes:door_steel_bar_b",
 | 
			
		||||
		"xpanes:door_steel_bar_c",
 | 
			
		||||
 
 | 
			
		||||
@@ -23,16 +23,18 @@ local gate_get_input_rules_twoinputs = mesecon.horiz_rules_getter({
 | 
			
		||||
local function set_gate(pos, node, state)
 | 
			
		||||
	local gate = minetest.registered_nodes[node.name]
 | 
			
		||||
 | 
			
		||||
	if mesecon.do_overheat(pos) then
 | 
			
		||||
		minetest.remove_node(pos)
 | 
			
		||||
		mesecon.receptor_off(pos, gate_get_output_rules(node))
 | 
			
		||||
		minetest.add_item(pos, gate.drop)
 | 
			
		||||
	elseif state then
 | 
			
		||||
		minetest.swap_node(pos, {name = gate.onstate, param2=node.param2})
 | 
			
		||||
		mesecon.receptor_on(pos, gate_get_output_rules(node))
 | 
			
		||||
	else
 | 
			
		||||
		minetest.swap_node(pos, {name = gate.offstate, param2=node.param2})
 | 
			
		||||
		mesecon.receptor_off(pos, gate_get_output_rules(node))
 | 
			
		||||
	local new_nodename = state and gate.onstate or gate.offstate
 | 
			
		||||
	minetest.swap_node(pos, {name = new_nodename, param2 = node.param2})
 | 
			
		||||
	if new_nodename ~= node.name then
 | 
			
		||||
		if mesecon.do_overheat(pos) then
 | 
			
		||||
			minetest.remove_node(pos)
 | 
			
		||||
			mesecon.receptor_off(pos, gate_get_output_rules(node))
 | 
			
		||||
			minetest.add_item(pos, gate.drop)
 | 
			
		||||
		elseif state then
 | 
			
		||||
			mesecon.receptor_on(pos, gate_get_output_rules(node))
 | 
			
		||||
		else
 | 
			
		||||
			mesecon.receptor_off(pos, gate_get_output_rules(node))
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
@@ -42,11 +44,36 @@ local function update_gate(pos, node, link, newstate)
 | 
			
		||||
	if gate.inputnumber == 1 then
 | 
			
		||||
		set_gate(pos, node, gate.assess(newstate == "on"))
 | 
			
		||||
	elseif gate.inputnumber == 2 then
 | 
			
		||||
		local meta = minetest.get_meta(pos)
 | 
			
		||||
		meta:set_int(link.name, newstate == "on" and 1 or 0)
 | 
			
		||||
 | 
			
		||||
		local val1 = meta:get_int("input1") == 1
 | 
			
		||||
		local val2 = meta:get_int("input2") == 1
 | 
			
		||||
		-- Inputs are stored in param2. Bit 5 is always set.
 | 
			
		||||
		-- input1 is bit 6 and input2 is bit 7.
 | 
			
		||||
		local val1, val2
 | 
			
		||||
		if node.param2 >= 32 then
 | 
			
		||||
			-- Bit 5 is set, so param2 is in the proper format.
 | 
			
		||||
			if link.name == "input1" then
 | 
			
		||||
				val1 = newstate == "on"
 | 
			
		||||
				val2 = node.param2 >= 128
 | 
			
		||||
			else
 | 
			
		||||
				val1 = node.param2 % 128 >= 64
 | 
			
		||||
				val2 = newstate == "on"
 | 
			
		||||
			end
 | 
			
		||||
		else
 | 
			
		||||
			-- Migrate old gates where the inputs are stored as metadata.
 | 
			
		||||
			-- This also triggers for newly placed gates.
 | 
			
		||||
			local meta = minetest.get_meta(pos)
 | 
			
		||||
			if link.name == "input1" then
 | 
			
		||||
				val1 = newstate == "on"
 | 
			
		||||
				val2 = meta:get_int("input2") == 1
 | 
			
		||||
			else
 | 
			
		||||
				val1 = meta:get_int("input1") == 1
 | 
			
		||||
				val2 = newstate == "on"
 | 
			
		||||
			end
 | 
			
		||||
			-- Set bit 5 so this won't happen again.
 | 
			
		||||
			node.param2 = node.param2 + 32
 | 
			
		||||
			-- Clear the metadata.
 | 
			
		||||
			meta:set_string("input1", "")
 | 
			
		||||
			meta:set_string("input2", "")
 | 
			
		||||
		end
 | 
			
		||||
		node.param2 = node.param2 % 64 + (val1 and 64 or 0) + (val2 and 128 or 0)
 | 
			
		||||
		set_gate(pos, node, gate.assess(val1, val2))
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,5 @@
 | 
			
		||||
local S = minetest.get_translator(minetest.get_current_modname())
 | 
			
		||||
 | 
			
		||||
-- HYDRO_TURBINE
 | 
			
		||||
-- Water turbine:
 | 
			
		||||
-- Active if flowing >water< above it
 | 
			
		||||
@@ -17,7 +19,7 @@ minetest.register_node("mesecons_hydroturbine:hydro_turbine_off", {
 | 
			
		||||
	is_ground_content = false,
 | 
			
		||||
	wield_scale = {x=0.75, y=0.75, z=0.75},
 | 
			
		||||
	groups = {dig_immediate=2},
 | 
			
		||||
	description="Water Turbine",
 | 
			
		||||
	description = S("Water Turbine"),
 | 
			
		||||
	paramtype = "light",
 | 
			
		||||
	selection_box = {
 | 
			
		||||
		type = "fixed",
 | 
			
		||||
@@ -47,7 +49,7 @@ minetest.register_node("mesecons_hydroturbine:hydro_turbine_on", {
 | 
			
		||||
	inventory_image = "jeija_hydro_turbine_inv.png",
 | 
			
		||||
	drop = "mesecons_hydroturbine:hydro_turbine_off 1",
 | 
			
		||||
	groups = {dig_immediate=2,not_in_creative_inventory=1},
 | 
			
		||||
	description="Water Turbine",
 | 
			
		||||
	description = S("Water Turbine"),
 | 
			
		||||
	paramtype = "light",
 | 
			
		||||
	selection_box = {
 | 
			
		||||
		type = "fixed",
 | 
			
		||||
@@ -97,9 +99,8 @@ nodenames = {"mesecons_hydroturbine:hydro_turbine_on"},
 | 
			
		||||
minetest.register_craft({
 | 
			
		||||
	output = "mesecons_hydroturbine:hydro_turbine_off 2",
 | 
			
		||||
	recipe = {
 | 
			
		||||
	{"","grup:stick", ""},
 | 
			
		||||
	{"","group:stick", ""},
 | 
			
		||||
	{"group:stick", "mesecons_gamecompat:steel_ingot", "group:stick"},
 | 
			
		||||
	{"","group:stick", ""},
 | 
			
		||||
	}
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								mesecons_hydroturbine/locale/mesecons_hydroturbine.de.tr
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								mesecons_hydroturbine/locale/mesecons_hydroturbine.de.tr
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
# textdomain: mesecons_hydroturbine
 | 
			
		||||
Water Turbine=Wasserturbine
 | 
			
		||||
							
								
								
									
										4
									
								
								mesecons_hydroturbine/locale/mesecons_hydroturbine.eo.tr
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								mesecons_hydroturbine/locale/mesecons_hydroturbine.eo.tr
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
# textdomain: mesecons_hydroturbine
 | 
			
		||||
 | 
			
		||||
### init.lua ###
 | 
			
		||||
Water Turbine=Akva Turbino
 | 
			
		||||
							
								
								
									
										4
									
								
								mesecons_hydroturbine/locale/template.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								mesecons_hydroturbine/locale/template.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
# textdomain: mesecons_hydroturbine
 | 
			
		||||
 | 
			
		||||
### init.lua ###
 | 
			
		||||
Water Turbine=
 | 
			
		||||
@@ -1,3 +1,5 @@
 | 
			
		||||
local S = minetest.get_translator(minetest.get_current_modname())
 | 
			
		||||
 | 
			
		||||
local insulated_wire_get_rules = mesecon.horiz_rules_getter({
 | 
			
		||||
	{x = 1, y = 0, z = 0},
 | 
			
		||||
	{x = -1, y = 0, z = 0},
 | 
			
		||||
@@ -5,7 +7,7 @@ local insulated_wire_get_rules = mesecon.horiz_rules_getter({
 | 
			
		||||
 | 
			
		||||
minetest.register_node("mesecons_insulated:insulated_on", {
 | 
			
		||||
	drawtype = "nodebox",
 | 
			
		||||
	description = "Straight Insulated Mesecon",
 | 
			
		||||
	description = S("Straight Insulated Mesecon"),
 | 
			
		||||
	tiles = {
 | 
			
		||||
		"jeija_insulated_wire_sides_on.png",
 | 
			
		||||
		"jeija_insulated_wire_sides_on.png",
 | 
			
		||||
@@ -42,7 +44,7 @@ minetest.register_node("mesecons_insulated:insulated_on", {
 | 
			
		||||
 | 
			
		||||
minetest.register_node("mesecons_insulated:insulated_off", {
 | 
			
		||||
	drawtype = "nodebox",
 | 
			
		||||
	description = "Straight Insulated Mesecon",
 | 
			
		||||
	description = S("Straight Insulated Mesecon"),
 | 
			
		||||
	tiles = {
 | 
			
		||||
		"jeija_insulated_wire_sides_off.png",
 | 
			
		||||
		"jeija_insulated_wire_sides_off.png",
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								mesecons_insulated/locale/mesecons_insulated.de.tr
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								mesecons_insulated/locale/mesecons_insulated.de.tr
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
# textdomain: mesecons_insulated
 | 
			
		||||
Straight Insulated Mesecon=Isolierte Mesecongerade
 | 
			
		||||
							
								
								
									
										4
									
								
								mesecons_insulated/locale/mesecons_insulated.eo.tr
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								mesecons_insulated/locale/mesecons_insulated.eo.tr
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
# textdomain: mesecons_insulated
 | 
			
		||||
 | 
			
		||||
### init.lua ###
 | 
			
		||||
Straight Insulated Mesecon=Rekta Izolita Mesekonduktilo
 | 
			
		||||
							
								
								
									
										4
									
								
								mesecons_insulated/locale/template.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								mesecons_insulated/locale/template.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
# textdomain: mesecons_insulated
 | 
			
		||||
 | 
			
		||||
### init.lua ###
 | 
			
		||||
Straight Insulated Mesecon=
 | 
			
		||||
@@ -1,3 +1,5 @@
 | 
			
		||||
local S = minetest.get_translator(minetest.get_current_modname())
 | 
			
		||||
 | 
			
		||||
-- MESELAMPS
 | 
			
		||||
-- A lamp is "is an electrical device used to create artificial light" (wikipedia)
 | 
			
		||||
-- guess what?
 | 
			
		||||
@@ -50,7 +52,7 @@ minetest.register_node("mesecons_lamp:lamp_off", {
 | 
			
		||||
	node_box = mesecon_lamp_box,
 | 
			
		||||
	selection_box = mesecon_lamp_box,
 | 
			
		||||
	groups = {dig_immediate=3, mesecon_receptor_off = 1, mesecon_effector_off = 1},
 | 
			
		||||
	description = "Mesecon Lamp",
 | 
			
		||||
	description = S("Mesecon Lamp"),
 | 
			
		||||
	sounds = mesecon.node_sound.glass,
 | 
			
		||||
	mesecons = {effector = {
 | 
			
		||||
		action_on = function (pos, node)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								mesecons_lamp/locale/mesecons_lamp.de.tr
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								mesecons_lamp/locale/mesecons_lamp.de.tr
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
# textdomain: mesecons_lamp
 | 
			
		||||
Mesecon Lamp=Meseconlampe
 | 
			
		||||
							
								
								
									
										4
									
								
								mesecons_lamp/locale/mesecons_lamp.eo.tr
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								mesecons_lamp/locale/mesecons_lamp.eo.tr
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
# textdomain: mesecons_lamp
 | 
			
		||||
 | 
			
		||||
### init.lua ###
 | 
			
		||||
Mesecon Lamp=Mesekonduktila Lampo
 | 
			
		||||
							
								
								
									
										4
									
								
								mesecons_lamp/locale/template.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								mesecons_lamp/locale/template.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
# textdomain: mesecons_lamp
 | 
			
		||||
 | 
			
		||||
### init.lua ###
 | 
			
		||||
Mesecon Lamp=
 | 
			
		||||
@@ -1,3 +1,5 @@
 | 
			
		||||
local S = minetest.get_translator(minetest.get_current_modname())
 | 
			
		||||
 | 
			
		||||
local lightstone_rules = {
 | 
			
		||||
	{x=0,  y=0,  z=-1},
 | 
			
		||||
	{x=1,  y=0,  z=0},
 | 
			
		||||
@@ -59,15 +61,15 @@ function mesecon.lightstone_add(name, base_item, texture_off, texture_on, desc)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
mesecon.lightstone_add("red", "mesecons_gamecompat:dye_red", "jeija_lightstone_red_off.png", "jeija_lightstone_red_on.png", "Red Lightstone")
 | 
			
		||||
mesecon.lightstone_add("green", "mesecons_gamecompat:dye_green", "jeija_lightstone_green_off.png", "jeija_lightstone_green_on.png", "Green Lightstone")
 | 
			
		||||
mesecon.lightstone_add("blue", "mesecons_gamecompat:dye_blue", "jeija_lightstone_blue_off.png", "jeija_lightstone_blue_on.png", "Blue Lightstone")
 | 
			
		||||
mesecon.lightstone_add("gray", "mesecons_gamecompat:dye_grey", "jeija_lightstone_gray_off.png", "jeija_lightstone_gray_on.png", "Grey Lightstone")
 | 
			
		||||
mesecon.lightstone_add("darkgray", "mesecons_gamecompat:dye_dark_grey", "jeija_lightstone_darkgray_off.png", "jeija_lightstone_darkgray_on.png", "Dark Grey Lightstone")
 | 
			
		||||
mesecon.lightstone_add("yellow", "mesecons_gamecompat:dye_yellow", "jeija_lightstone_yellow_off.png", "jeija_lightstone_yellow_on.png", "Yellow Lightstone")
 | 
			
		||||
mesecon.lightstone_add("orange", "mesecons_gamecompat:dye_orange", "jeija_lightstone_orange_off.png", "jeija_lightstone_orange_on.png", "Orange Lightstone")
 | 
			
		||||
mesecon.lightstone_add("white", "mesecons_gamecompat:dye_white", "jeija_lightstone_white_off.png", "jeija_lightstone_white_on.png", "White Lightstone")
 | 
			
		||||
mesecon.lightstone_add("pink", "mesecons_gamecompat:dye_pink", "jeija_lightstone_pink_off.png", "jeija_lightstone_pink_on.png", "Pink Lightstone")
 | 
			
		||||
mesecon.lightstone_add("magenta", "mesecons_gamecompat:dye_magenta", "jeija_lightstone_magenta_off.png", "jeija_lightstone_magenta_on.png", "Magenta Lightstone")
 | 
			
		||||
mesecon.lightstone_add("cyan", "mesecons_gamecompat:dye_cyan", "jeija_lightstone_cyan_off.png", "jeija_lightstone_cyan_on.png", "Cyan Lightstone")
 | 
			
		||||
mesecon.lightstone_add("violet", "mesecons_gamecompat:dye_violet", "jeija_lightstone_violet_off.png", "jeija_lightstone_violet_on.png", "Violet Lightstone")
 | 
			
		||||
mesecon.lightstone_add("red", "mesecons_gamecompat:dye_red", "jeija_lightstone_red_off.png", "jeija_lightstone_red_on.png", S("Red Lightstone"))
 | 
			
		||||
mesecon.lightstone_add("green", "mesecons_gamecompat:dye_green", "jeija_lightstone_green_off.png", "jeija_lightstone_green_on.png", S("Green Lightstone"))
 | 
			
		||||
mesecon.lightstone_add("blue", "mesecons_gamecompat:dye_blue", "jeija_lightstone_blue_off.png", "jeija_lightstone_blue_on.png", S("Blue Lightstone"))
 | 
			
		||||
mesecon.lightstone_add("gray", "mesecons_gamecompat:dye_grey", "jeija_lightstone_gray_off.png", "jeija_lightstone_gray_on.png", S("Grey Lightstone"))
 | 
			
		||||
mesecon.lightstone_add("darkgray", "mesecons_gamecompat:dye_dark_grey", "jeija_lightstone_darkgray_off.png", "jeija_lightstone_darkgray_on.png", S("Dark Grey Lightstone"))
 | 
			
		||||
mesecon.lightstone_add("yellow", "mesecons_gamecompat:dye_yellow", "jeija_lightstone_yellow_off.png", "jeija_lightstone_yellow_on.png", S("Yellow Lightstone"))
 | 
			
		||||
mesecon.lightstone_add("orange", "mesecons_gamecompat:dye_orange", "jeija_lightstone_orange_off.png", "jeija_lightstone_orange_on.png", S("Orange Lightstone"))
 | 
			
		||||
mesecon.lightstone_add("white", "mesecons_gamecompat:dye_white", "jeija_lightstone_white_off.png", "jeija_lightstone_white_on.png", S("White Lightstone"))
 | 
			
		||||
mesecon.lightstone_add("pink", "mesecons_gamecompat:dye_pink", "jeija_lightstone_pink_off.png", "jeija_lightstone_pink_on.png", S("Pink Lightstone"))
 | 
			
		||||
mesecon.lightstone_add("magenta", "mesecons_gamecompat:dye_magenta", "jeija_lightstone_magenta_off.png", "jeija_lightstone_magenta_on.png", S("Magenta Lightstone"))
 | 
			
		||||
mesecon.lightstone_add("cyan", "mesecons_gamecompat:dye_cyan", "jeija_lightstone_cyan_off.png", "jeija_lightstone_cyan_on.png", S("Cyan Lightstone"))
 | 
			
		||||
mesecon.lightstone_add("violet", "mesecons_gamecompat:dye_violet", "jeija_lightstone_violet_off.png", "jeija_lightstone_violet_on.png", S("Violet Lightstone"))
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								mesecons_lightstone/locale/mesecons_lightstone.de.tr
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								mesecons_lightstone/locale/mesecons_lightstone.de.tr
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
# textdomain: mesecons_lightstone
 | 
			
		||||
Red Lightstone=Roter Leuchtstein
 | 
			
		||||
Green Lightstone=Grüner Leuchtstein
 | 
			
		||||
Blue Lightstone=Blauer Leuchtstein
 | 
			
		||||
Grey Lightstone=Grauer Leuchtstein
 | 
			
		||||
Dark Grey Lightstone=Dunkelgrauer Leuchtstein
 | 
			
		||||
Yellow Lightstone=Gelber Leuchtstein
 | 
			
		||||
Orange Lightstone=Orange Leuchtstein
 | 
			
		||||
White Lightstone=Weißer Leuchtstein
 | 
			
		||||
Pink Lightstone=Rosa Leuchtstein
 | 
			
		||||
Magenta Lightstone=Magenta Leuchtstein
 | 
			
		||||
Cyan Lightstone=Türkiser Leuchtstein
 | 
			
		||||
Violet Lightstone=Violetter Leuchtstein
 | 
			
		||||
							
								
								
									
										15
									
								
								mesecons_lightstone/locale/mesecons_lightstone.eo.tr
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								mesecons_lightstone/locale/mesecons_lightstone.eo.tr
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
# textdomain: mesecons_lightstone
 | 
			
		||||
 | 
			
		||||
### init.lua ###
 | 
			
		||||
Red Lightstone=Ruĝa Lumŝtono
 | 
			
		||||
Green Lightstone=Verda Lumŝtono
 | 
			
		||||
Blue Lightstone=Blua Lumŝtono
 | 
			
		||||
Grey Lightstone=Griza Lumŝtono
 | 
			
		||||
Dark Grey Lightstone=Malhela Griza Lumŝtono
 | 
			
		||||
Yellow Lightstone=Flava Lumŝtono
 | 
			
		||||
Orange Lightstone=Oranĝa Lumŝtono
 | 
			
		||||
White Lightstone=Blanka Lumŝtono
 | 
			
		||||
Pink Lightstone=Rozkolora Lumŝtono
 | 
			
		||||
Magenta Lightstone=Magenta Lumŝtono
 | 
			
		||||
Cyan Lightstone=Cejana Lumŝtono
 | 
			
		||||
Violet Lightstone=Viola Lumŝtono
 | 
			
		||||
							
								
								
									
										15
									
								
								mesecons_lightstone/locale/template.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								mesecons_lightstone/locale/template.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
# textdomain: mesecons_lightstone
 | 
			
		||||
 | 
			
		||||
### init.lua ###
 | 
			
		||||
Red Lightstone=
 | 
			
		||||
Green Lightstone=
 | 
			
		||||
Blue Lightstone=
 | 
			
		||||
Grey Lightstone=
 | 
			
		||||
Dark Grey Lightstone=
 | 
			
		||||
Yellow Lightstone=
 | 
			
		||||
Orange Lightstone=
 | 
			
		||||
White Lightstone=
 | 
			
		||||
Pink Lightstone=
 | 
			
		||||
Magenta Lightstone=
 | 
			
		||||
Cyan Lightstone=
 | 
			
		||||
Violet Lightstone=
 | 
			
		||||
@@ -28,6 +28,8 @@
 | 
			
		||||
-- (see where local env is defined)
 | 
			
		||||
-- Something nice to play is is appending minetest.env to it.
 | 
			
		||||
 | 
			
		||||
local S = minetest.get_translator(minetest.get_current_modname())
 | 
			
		||||
 | 
			
		||||
local BASENAME = "mesecons_luacontroller:luacontroller"
 | 
			
		||||
 | 
			
		||||
local rules = {
 | 
			
		||||
@@ -201,11 +203,13 @@ end
 | 
			
		||||
-------------------------
 | 
			
		||||
 | 
			
		||||
local function safe_print(param)
 | 
			
		||||
	local string_meta = getmetatable("")
 | 
			
		||||
	local sandbox = string_meta.__index
 | 
			
		||||
	string_meta.__index = string -- Leave string sandbox temporarily
 | 
			
		||||
	print(dump(param))
 | 
			
		||||
	string_meta.__index = sandbox -- Restore string sandbox
 | 
			
		||||
	if mesecon.setting("luacontroller_print_behavior", "log") == "log" then
 | 
			
		||||
		local string_meta = getmetatable("")
 | 
			
		||||
		local sandbox = string_meta.__index
 | 
			
		||||
		string_meta.__index = string -- Leave string sandbox temporarily
 | 
			
		||||
		minetest.log("action", string.format("[mesecons_luacontroller] print(%s)", dump(param)))
 | 
			
		||||
		string_meta.__index = sandbox -- Restore string sandbox
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function safe_date()
 | 
			
		||||
@@ -234,6 +238,16 @@ local function safe_string_find(...)
 | 
			
		||||
	return string.find(...)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- do not allow pattern matching in string.split (see string.find for details)
 | 
			
		||||
local function safe_string_split(...)
 | 
			
		||||
	if select(5, ...) then
 | 
			
		||||
		debug.sethook() -- Clear hook
 | 
			
		||||
		error("string.split: 'sep_is_pattern' (fifth parameter) may not be used in a Luacontroller")
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	return string.split(...)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function remove_functions(x)
 | 
			
		||||
	local tp = type(x)
 | 
			
		||||
	if tp == "function" then
 | 
			
		||||
@@ -374,7 +388,10 @@ local function clean_and_weigh_digiline_message(msg, back_references)
 | 
			
		||||
		return msg, #msg + 25
 | 
			
		||||
	elseif t == "number" then
 | 
			
		||||
		-- Numbers are passed by value so need not be touched, and cost 8 bytes
 | 
			
		||||
		-- as all numbers in Lua are doubles.
 | 
			
		||||
		-- as all numbers in Lua are doubles. NaN values are removed.
 | 
			
		||||
		if msg ~= msg then
 | 
			
		||||
			return nil, 0
 | 
			
		||||
		end
 | 
			
		||||
		return msg, 8
 | 
			
		||||
	elseif t == "boolean" then
 | 
			
		||||
		-- Booleans are passed by value so need not be touched, and cost 1
 | 
			
		||||
@@ -503,6 +520,7 @@ local function create_environment(pos, mem, event, itbl, send_warning)
 | 
			
		||||
			reverse = string.reverse,
 | 
			
		||||
			sub = string.sub,
 | 
			
		||||
			find = safe_string_find,
 | 
			
		||||
			split = safe_string_split,
 | 
			
		||||
		},
 | 
			
		||||
		math = {
 | 
			
		||||
			abs = math.abs,
 | 
			
		||||
@@ -851,7 +869,7 @@ for d = 0, 1 do
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	minetest.register_node(node_name, {
 | 
			
		||||
		description = "Luacontroller",
 | 
			
		||||
		description = S("Luacontroller"),
 | 
			
		||||
		drawtype = "nodebox",
 | 
			
		||||
		tiles = {
 | 
			
		||||
			top,
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,2 @@
 | 
			
		||||
# textdomain: mesecons_luacontroller
 | 
			
		||||
Luacontroller=Luacontroller
 | 
			
		||||
@@ -0,0 +1,4 @@
 | 
			
		||||
# textdomain: mesecons_luacontroller
 | 
			
		||||
 | 
			
		||||
### init.lua ###
 | 
			
		||||
Luacontroller=Luaregilo
 | 
			
		||||
							
								
								
									
										4
									
								
								mesecons_luacontroller/locale/template.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								mesecons_luacontroller/locale/template.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
# textdomain: mesecons_luacontroller
 | 
			
		||||
 | 
			
		||||
### init.lua ###
 | 
			
		||||
Luacontroller=
 | 
			
		||||
							
								
								
									
										38
									
								
								mesecons_luacontroller/spec/lightweight_interrupt_spec.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								mesecons_luacontroller/spec/lightweight_interrupt_spec.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
require("mineunit")
 | 
			
		||||
 | 
			
		||||
-- This test is done in a separate file since it requires different configuration at startup.
 | 
			
		||||
mineunit("core")
 | 
			
		||||
minetest.settings:set("mesecon.luacontroller_lightweight_interrupts", "true")
 | 
			
		||||
 | 
			
		||||
fixture("mesecons_luacontroller")
 | 
			
		||||
 | 
			
		||||
describe("LuaController lightweight interrupt", function()
 | 
			
		||||
	local pos = {x = 0, y = 0, z = 0}
 | 
			
		||||
 | 
			
		||||
	before_each(function()
 | 
			
		||||
		mesecon._test_place(pos, "mesecons_luacontroller:luacontroller0000")
 | 
			
		||||
		mineunit:execute_globalstep() -- Execute receptor_on action
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	after_each(function()
 | 
			
		||||
		mesecon._test_reset()
 | 
			
		||||
		world.clear()
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("works", function()
 | 
			
		||||
		mesecon._test_program_luac(pos, [[
 | 
			
		||||
			if event.type == "program" then
 | 
			
		||||
				interrupt(5)
 | 
			
		||||
				interrupt(10)
 | 
			
		||||
			elseif event.type == "interrupt" then
 | 
			
		||||
				port.a = not pin.a
 | 
			
		||||
			end
 | 
			
		||||
		]])
 | 
			
		||||
		mineunit:execute_globalstep(0.1)
 | 
			
		||||
		mineunit:execute_globalstep(9)
 | 
			
		||||
		assert.equal("mesecons_luacontroller:luacontroller0000", world.get_node(pos).name)
 | 
			
		||||
		mineunit:execute_globalstep(1)
 | 
			
		||||
		mineunit:execute_globalstep(0.1)
 | 
			
		||||
		assert.equal("mesecons_luacontroller:luacontroller0001", world.get_node(pos).name)
 | 
			
		||||
	end)
 | 
			
		||||
end)
 | 
			
		||||
							
								
								
									
										176
									
								
								mesecons_luacontroller/spec/luac_spec.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										176
									
								
								mesecons_luacontroller/spec/luac_spec.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,176 @@
 | 
			
		||||
require("mineunit")
 | 
			
		||||
 | 
			
		||||
fixture("mesecons_luacontroller")
 | 
			
		||||
 | 
			
		||||
-- Digiline is not tested, since that would require the digiline mod.
 | 
			
		||||
 | 
			
		||||
describe("LuaController", function()
 | 
			
		||||
	local pos = {x = 0, y = 0, z = 0}
 | 
			
		||||
	local pos_a = {x = -1, y = 0, z = 0}
 | 
			
		||||
 | 
			
		||||
	before_each(function()
 | 
			
		||||
		mesecon._test_place(pos, "mesecons_luacontroller:luacontroller0000")
 | 
			
		||||
		mineunit:execute_globalstep() -- Execute receptor_on action
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	after_each(function()
 | 
			
		||||
		mesecon._test_reset()
 | 
			
		||||
		world.clear()
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("rejects binary code", function()
 | 
			
		||||
		local ok = mesecon._test_program_luac(pos, string.dump(function() end))
 | 
			
		||||
		assert.is_false(ok)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("I/O", function()
 | 
			
		||||
		mesecon._test_place(pos_a, "mesecons:test_receptor_on")
 | 
			
		||||
		mineunit:execute_globalstep() -- Execute receptor_on action
 | 
			
		||||
		mineunit:execute_globalstep() -- Execute activate/change actions
 | 
			
		||||
		mesecon._test_program_luac(pos, [[
 | 
			
		||||
			port.a = not pin.a
 | 
			
		||||
			port.b = not pin.b
 | 
			
		||||
			port.c = not pin.c
 | 
			
		||||
			port.d = not pin.d
 | 
			
		||||
		]])
 | 
			
		||||
		assert.equal("mesecons_luacontroller:luacontroller1110", world.get_node(pos).name)
 | 
			
		||||
		mesecon._test_dig(pos_a)
 | 
			
		||||
		mineunit:execute_globalstep() -- Execute receptor_off action
 | 
			
		||||
		mineunit:execute_globalstep() -- Execute deactivate/change actions
 | 
			
		||||
		assert.equal("mesecons_luacontroller:luacontroller0001", world.get_node(pos).name)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("memory", function()
 | 
			
		||||
		mesecon._test_program_luac(pos, [[
 | 
			
		||||
			if not mem.x then
 | 
			
		||||
				mem.x = {}
 | 
			
		||||
				mem.x[mem.x] = {true, "", 1.2}
 | 
			
		||||
			else
 | 
			
		||||
				local b, s, n = unpack(mem.x[mem.x])
 | 
			
		||||
				if b == true and s == "" and n == 1.2 then
 | 
			
		||||
					port.d = true
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
		]])
 | 
			
		||||
		assert.equal("mesecons_luacontroller:luacontroller0000", world.get_node(pos).name)
 | 
			
		||||
		mesecon._test_place(pos_a, "mesecons:test_receptor_on")
 | 
			
		||||
		mineunit:execute_globalstep() -- Execute receptor_on action
 | 
			
		||||
		mineunit:execute_globalstep() -- Execute activate/change actions
 | 
			
		||||
		assert.equal("mesecons_luacontroller:luacontroller1000", world.get_node(pos).name)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("interrupts without IDs", function()
 | 
			
		||||
		mesecon._test_program_luac(pos, [[
 | 
			
		||||
			if event.type == "program" then
 | 
			
		||||
				interrupt(4)
 | 
			
		||||
				interrupt(8)
 | 
			
		||||
			elseif event.type == "interrupt" then
 | 
			
		||||
				port.a = not pin.a
 | 
			
		||||
			end
 | 
			
		||||
		]])
 | 
			
		||||
		mineunit:execute_globalstep(0.1)
 | 
			
		||||
		mineunit:execute_globalstep(3)
 | 
			
		||||
		assert.equal("mesecons_luacontroller:luacontroller0000", world.get_node(pos).name)
 | 
			
		||||
		mineunit:execute_globalstep(1)
 | 
			
		||||
		mineunit:execute_globalstep(0.1)
 | 
			
		||||
		assert.equal("mesecons_luacontroller:luacontroller0001", world.get_node(pos).name)
 | 
			
		||||
		mineunit:execute_globalstep(3)
 | 
			
		||||
		assert.equal("mesecons_luacontroller:luacontroller0001", world.get_node(pos).name)
 | 
			
		||||
		mineunit:execute_globalstep(1)
 | 
			
		||||
		mineunit:execute_globalstep(0.1)
 | 
			
		||||
		assert.equal("mesecons_luacontroller:luacontroller0000", world.get_node(pos).name)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("interrupts with IDs", function()
 | 
			
		||||
		mesecon._test_program_luac(pos, [[
 | 
			
		||||
			if event.type == "program" then
 | 
			
		||||
				interrupt(2, "a")
 | 
			
		||||
				interrupt(4, "a")
 | 
			
		||||
				interrupt(16, "b")
 | 
			
		||||
			elseif event.type == "interrupt" then
 | 
			
		||||
				if event.iid == "a" then
 | 
			
		||||
					interrupt(5, "b")
 | 
			
		||||
					interrupt(4, "b")
 | 
			
		||||
				end
 | 
			
		||||
				port.a = not pin.a
 | 
			
		||||
			end
 | 
			
		||||
		]])
 | 
			
		||||
		mineunit:execute_globalstep(0.1)
 | 
			
		||||
		mineunit:execute_globalstep(3)
 | 
			
		||||
		assert.equal("mesecons_luacontroller:luacontroller0000", world.get_node(pos).name)
 | 
			
		||||
		mineunit:execute_globalstep(1)
 | 
			
		||||
		mineunit:execute_globalstep(0.1)
 | 
			
		||||
		assert.equal("mesecons_luacontroller:luacontroller0001", world.get_node(pos).name)
 | 
			
		||||
		mineunit:execute_globalstep(3)
 | 
			
		||||
		assert.equal("mesecons_luacontroller:luacontroller0001", world.get_node(pos).name)
 | 
			
		||||
		mineunit:execute_globalstep(1)
 | 
			
		||||
		mineunit:execute_globalstep(0.1)
 | 
			
		||||
		assert.equal("mesecons_luacontroller:luacontroller0000", world.get_node(pos).name)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("limits interrupt ID size", function()
 | 
			
		||||
		mesecon._test_program_luac(pos, [[
 | 
			
		||||
			if event.type == "program" then
 | 
			
		||||
				interrupt(0, (" "):rep(257))
 | 
			
		||||
			elseif event.type == "interrupt" then
 | 
			
		||||
				port.a = not pin.a
 | 
			
		||||
			end
 | 
			
		||||
		]])
 | 
			
		||||
		mineunit:execute_globalstep(3)
 | 
			
		||||
		mineunit:execute_globalstep(3)
 | 
			
		||||
		assert.equal("mesecons_luacontroller:luacontroller0000", world.get_node(pos).name)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("string.rep", function()
 | 
			
		||||
		mesecon._test_program_luac(pos, [[
 | 
			
		||||
			(" "):rep(64000)
 | 
			
		||||
			port.a = true
 | 
			
		||||
		]])
 | 
			
		||||
		assert.equal("mesecons_luacontroller:luacontroller0001", world.get_node(pos).name)
 | 
			
		||||
		mesecon._test_program_luac(pos, [[
 | 
			
		||||
			(" "):rep(64001)
 | 
			
		||||
			port.b = true
 | 
			
		||||
		]])
 | 
			
		||||
		assert.equal("mesecons_luacontroller:luacontroller0000", world.get_node(pos).name)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("string.find", function()
 | 
			
		||||
		mesecon._test_program_luac(pos, [[
 | 
			
		||||
			port.a = (" a"):find("a", nil, true) == 2
 | 
			
		||||
		]])
 | 
			
		||||
		assert.equal("mesecons_luacontroller:luacontroller0001", world.get_node(pos).name)
 | 
			
		||||
		mesecon._test_program_luac(pos, [[
 | 
			
		||||
			(" a"):find("a", nil)
 | 
			
		||||
			port.b = true
 | 
			
		||||
		]])
 | 
			
		||||
		assert.equal("mesecons_luacontroller:luacontroller0000", world.get_node(pos).name)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("overheats", function()
 | 
			
		||||
		mesecon._test_program_luac(pos, [[
 | 
			
		||||
			interrupt(0)
 | 
			
		||||
			interrupt(0)
 | 
			
		||||
		]])
 | 
			
		||||
		mineunit:execute_globalstep() -- Execute 2 interrupts
 | 
			
		||||
		mineunit:execute_globalstep() -- Execute 4 interrupts
 | 
			
		||||
		mineunit:execute_globalstep() -- Execute 8 interrupts
 | 
			
		||||
		mineunit:execute_globalstep() -- Execute 16 interrupts
 | 
			
		||||
		assert.equal("mesecons_luacontroller:luacontroller_burnt", world.get_node(pos).name)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("limits memory", function()
 | 
			
		||||
		mesecon._test_program_luac(pos, [[
 | 
			
		||||
			port.a = true
 | 
			
		||||
			mem.x = (" "):rep(50000) .. (" "):rep(50000)
 | 
			
		||||
		]])
 | 
			
		||||
		assert.equal("mesecons_luacontroller:luacontroller_burnt", world.get_node(pos).name)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("limits run time", function()
 | 
			
		||||
		mesecon._test_program_luac(pos, [[
 | 
			
		||||
			port.a = true
 | 
			
		||||
			for i = 1, 1000000 do end
 | 
			
		||||
		]])
 | 
			
		||||
		assert.equal("mesecons_luacontroller:luacontroller0000", world.get_node(pos).name)
 | 
			
		||||
	end)
 | 
			
		||||
end)
 | 
			
		||||
							
								
								
									
										1
									
								
								mesecons_luacontroller/spec/mineunit.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								mesecons_luacontroller/spec/mineunit.conf
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
fixture_paths = {"../.test_fixtures"}
 | 
			
		||||
@@ -1,14 +1,16 @@
 | 
			
		||||
local S = minetest.get_translator(minetest.get_current_modname())
 | 
			
		||||
 | 
			
		||||
-- Glue and fiber
 | 
			
		||||
minetest.register_craftitem("mesecons_materials:glue", {
 | 
			
		||||
	image = "mesecons_glue.png",
 | 
			
		||||
	on_place_on_ground = minetest.craftitem_place_item,
 | 
			
		||||
	description="Glue",
 | 
			
		||||
	description = S("Glue"),
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
minetest.register_craftitem("mesecons_materials:fiber", {
 | 
			
		||||
	image = "mesecons_fiber.png",
 | 
			
		||||
	on_place_on_ground = minetest.craftitem_place_item,
 | 
			
		||||
	description="Fiber",
 | 
			
		||||
	description = S("Fiber"),
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
minetest.register_craft({
 | 
			
		||||
@@ -29,7 +31,7 @@ minetest.register_craft({
 | 
			
		||||
minetest.register_craftitem("mesecons_materials:silicon", {
 | 
			
		||||
	image = "mesecons_silicon.png",
 | 
			
		||||
	on_place_on_ground = minetest.craftitem_place_item,
 | 
			
		||||
	description="Silicon",
 | 
			
		||||
	description = S("Silicon"),
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
minetest.register_craft({
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								mesecons_materials/locale/mesecons_materials.de.tr
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								mesecons_materials/locale/mesecons_materials.de.tr
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
# textdomain: mesecons_materials
 | 
			
		||||
Glue=Klebstoff
 | 
			
		||||
Fiber=Faser
 | 
			
		||||
Silicon=Silizium
 | 
			
		||||
							
								
								
									
										6
									
								
								mesecons_materials/locale/mesecons_materials.eo.tr
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								mesecons_materials/locale/mesecons_materials.eo.tr
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
# textdomain: mesecons_materials
 | 
			
		||||
 | 
			
		||||
### init.lua ###
 | 
			
		||||
Glue=Gluo
 | 
			
		||||
Fiber=Fibro
 | 
			
		||||
Silicon=Silicio
 | 
			
		||||
							
								
								
									
										6
									
								
								mesecons_materials/locale/template.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								mesecons_materials/locale/template.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
# textdomain: mesecons_materials
 | 
			
		||||
 | 
			
		||||
### init.lua ###
 | 
			
		||||
Glue=
 | 
			
		||||
Fiber=
 | 
			
		||||
Silicon=
 | 
			
		||||
@@ -1,3 +1,5 @@
 | 
			
		||||
local S = minetest.get_translator(minetest.get_current_modname())
 | 
			
		||||
 | 
			
		||||
local EEPROM_SIZE = 255
 | 
			
		||||
 | 
			
		||||
local microc_rules = {}
 | 
			
		||||
@@ -57,7 +59,7 @@ if nodename ~= "mesecons_microcontroller:microcontroller0000" then
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
minetest.register_node(nodename, {
 | 
			
		||||
	description = "Microcontroller",
 | 
			
		||||
	description = S("Microcontroller"),
 | 
			
		||||
	drawtype = "nodebox",
 | 
			
		||||
	tiles = {
 | 
			
		||||
		top,
 | 
			
		||||
@@ -332,7 +334,8 @@ yc.parse_get_eeprom_param = function(cond, starti)
 | 
			
		||||
	local addr
 | 
			
		||||
	while s ~= "" do
 | 
			
		||||
		s = string.sub(cond, i, i)
 | 
			
		||||
		if string.find("0123456789", s) == nil or s == "" then
 | 
			
		||||
		local b = s:byte()
 | 
			
		||||
		if s == "" or 48 > b or b > 57 then
 | 
			
		||||
			addr = string.sub(cond, starti, i-1) -- i: last number i+1 after last number
 | 
			
		||||
			return addr, i
 | 
			
		||||
		end
 | 
			
		||||
@@ -419,13 +422,16 @@ yc.command_sbi = function(params, eeprom, L, Lv)
 | 
			
		||||
 | 
			
		||||
	if status == nil then return nil, nil end
 | 
			
		||||
 | 
			
		||||
	if string.find("ABCD", params[1])~=nil and #params[1]==1 then --is a port
 | 
			
		||||
		if status == "1" then
 | 
			
		||||
			Lv = yc.set_portstate (params[1], true,  Lv)
 | 
			
		||||
		else
 | 
			
		||||
			Lv = yc.set_portstate (params[1], false, Lv)
 | 
			
		||||
	if #params[1]==1 then
 | 
			
		||||
		local b = params[1]:byte()
 | 
			
		||||
		if 65 <= b and b <= 68 then -- is a port
 | 
			
		||||
			if status == "1" then
 | 
			
		||||
				Lv = yc.set_portstate (params[1], true,  Lv)
 | 
			
		||||
			else
 | 
			
		||||
				Lv = yc.set_portstate (params[1], false, Lv)
 | 
			
		||||
			end
 | 
			
		||||
			return eeprom, Lv;
 | 
			
		||||
		end
 | 
			
		||||
		return eeprom, Lv;
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	--is an eeprom address
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,2 @@
 | 
			
		||||
# textdomain: mesecons_microcontroller
 | 
			
		||||
Microcontroller=Mikrocontroller
 | 
			
		||||
@@ -0,0 +1,4 @@
 | 
			
		||||
# textdomain: mesecons_microcontroller
 | 
			
		||||
 | 
			
		||||
### init.lua ###
 | 
			
		||||
Microcontroller=Mikroregilo
 | 
			
		||||
							
								
								
									
										4
									
								
								mesecons_microcontroller/locale/template.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								mesecons_microcontroller/locale/template.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
# textdomain: mesecons_microcontroller
 | 
			
		||||
 | 
			
		||||
### init.lua ###
 | 
			
		||||
Microcontroller=
 | 
			
		||||
@@ -8,6 +8,8 @@
 | 
			
		||||
-- Pushes all block in front of it
 | 
			
		||||
-- Pull all blocks in its back
 | 
			
		||||
 | 
			
		||||
local S = minetest.get_translator(minetest.get_current_modname())
 | 
			
		||||
 | 
			
		||||
-- settings:
 | 
			
		||||
local timer_interval = 1 / mesecon.setting("movestone_speed", 3)
 | 
			
		||||
local max_push = mesecon.setting("movestone_max_push", 50)
 | 
			
		||||
@@ -128,7 +130,7 @@ mesecon.register_movestone("mesecons_movestones:movestone", {
 | 
			
		||||
		"jeija_movestone_arrows.png",
 | 
			
		||||
	},
 | 
			
		||||
	groups = {cracky = 3},
 | 
			
		||||
    description = "Movestone",
 | 
			
		||||
    description = S("Movestone"),
 | 
			
		||||
	sounds = mesecon.node_sound.stone
 | 
			
		||||
}, false, false)
 | 
			
		||||
 | 
			
		||||
@@ -142,7 +144,7 @@ mesecon.register_movestone("mesecons_movestones:sticky_movestone", {
 | 
			
		||||
		"jeija_sticky_movestone.png",
 | 
			
		||||
	},
 | 
			
		||||
	groups = {cracky = 3},
 | 
			
		||||
    description = "Sticky Movestone",
 | 
			
		||||
    description = S("Sticky Movestone"),
 | 
			
		||||
	sounds = mesecon.node_sound.stone,
 | 
			
		||||
}, true, false)
 | 
			
		||||
 | 
			
		||||
@@ -156,7 +158,7 @@ mesecon.register_movestone("mesecons_movestones:movestone_vertical", {
 | 
			
		||||
		"jeija_movestone_arrows.png^[transformR90",
 | 
			
		||||
	},
 | 
			
		||||
	groups = {cracky = 3},
 | 
			
		||||
    description = "Vertical Movestone",
 | 
			
		||||
    description = S("Vertical Movestone"),
 | 
			
		||||
	sounds = mesecon.node_sound.stone
 | 
			
		||||
}, false, true)
 | 
			
		||||
 | 
			
		||||
@@ -170,7 +172,7 @@ mesecon.register_movestone("mesecons_movestones:sticky_movestone_vertical", {
 | 
			
		||||
		"jeija_movestone_arrows.png^[transformR90",
 | 
			
		||||
	},
 | 
			
		||||
	groups = {cracky = 3},
 | 
			
		||||
    description = "Vertical Sticky Movestone",
 | 
			
		||||
    description = S("Vertical Sticky Movestone"),
 | 
			
		||||
	sounds = mesecon.node_sound.stone,
 | 
			
		||||
}, true, true)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								mesecons_movestones/locale/mesecons_movestones.de.tr
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								mesecons_movestones/locale/mesecons_movestones.de.tr
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
# textdomain: mesecons_movestones
 | 
			
		||||
Movestone=Laufstein
 | 
			
		||||
Sticky Movestone=Klebriger Laufstein
 | 
			
		||||
Vertical Movestone=Vertikaler Laufstein
 | 
			
		||||
Vertical Sticky Movestone=Vertikaler klebriger Laufstein
 | 
			
		||||
							
								
								
									
										7
									
								
								mesecons_movestones/locale/mesecons_movestones.eo.tr
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								mesecons_movestones/locale/mesecons_movestones.eo.tr
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
# textdomain: mesecons_movestones
 | 
			
		||||
 | 
			
		||||
### init.lua ###
 | 
			
		||||
Movestone=Movŝtono
 | 
			
		||||
Sticky Movestone=Glueca Movŝtono
 | 
			
		||||
Vertical Movestone=Vertikala Movŝtono
 | 
			
		||||
Vertical Sticky Movestone=Vertikala Glueca Movŝtono
 | 
			
		||||
							
								
								
									
										7
									
								
								mesecons_movestones/locale/template.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								mesecons_movestones/locale/template.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
# textdomain: mesecons_movestones
 | 
			
		||||
 | 
			
		||||
### init.lua ###
 | 
			
		||||
Movestone=
 | 
			
		||||
Sticky Movestone=
 | 
			
		||||
Vertical Movestone=
 | 
			
		||||
Vertical Sticky Movestone=
 | 
			
		||||
@@ -53,11 +53,16 @@ end
 | 
			
		||||
 | 
			
		||||
-- tests if the node can be pushed into, e.g. air, water, grass
 | 
			
		||||
local function node_replaceable(name)
 | 
			
		||||
	if minetest.registered_nodes[name] then
 | 
			
		||||
		return minetest.registered_nodes[name].buildable_to or false
 | 
			
		||||
	local nodedef = minetest.registered_nodes[name]
 | 
			
		||||
 | 
			
		||||
	-- everything that can be an mvps stopper (unknown nodes and nodes in the
 | 
			
		||||
	-- mvps_stoppers table) must not be replacable
 | 
			
		||||
	-- Note: ignore (a stopper) is buildable_to, but we do not want to push into it
 | 
			
		||||
	if not nodedef or mesecon.mvps_stoppers[name] then
 | 
			
		||||
		return false
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	return false
 | 
			
		||||
	return nodedef.buildable_to or false
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function mesecon.mvps_get_stack(pos, dir, maximum, all_pull_sticky)
 | 
			
		||||
@@ -76,9 +81,9 @@ function mesecon.mvps_get_stack(pos, dir, maximum, all_pull_sticky)
 | 
			
		||||
			if #nodes > maximum then return nil end
 | 
			
		||||
 | 
			
		||||
			-- add connected nodes to frontiers
 | 
			
		||||
			if minetest.registered_nodes[nn.name]
 | 
			
		||||
			and minetest.registered_nodes[nn.name].mvps_sticky then
 | 
			
		||||
				local connected = minetest.registered_nodes[nn.name].mvps_sticky(np, nn)
 | 
			
		||||
			local nndef = minetest.registered_nodes[nn.name]
 | 
			
		||||
			if nndef and nndef.mvps_sticky then
 | 
			
		||||
				local connected = nndef.mvps_sticky(np, nn)
 | 
			
		||||
				for _, cp in ipairs(connected) do
 | 
			
		||||
					frontiers:add(cp)
 | 
			
		||||
				end
 | 
			
		||||
@@ -91,10 +96,9 @@ function mesecon.mvps_get_stack(pos, dir, maximum, all_pull_sticky)
 | 
			
		||||
			for _, r in ipairs(mesecon.rules.alldirs) do
 | 
			
		||||
				local adjpos = vector.add(np, r)
 | 
			
		||||
				local adjnode = minetest.get_node(adjpos)
 | 
			
		||||
				if minetest.registered_nodes[adjnode.name]
 | 
			
		||||
				and minetest.registered_nodes[adjnode.name].mvps_sticky then
 | 
			
		||||
					local sticksto = minetest.registered_nodes[adjnode.name]
 | 
			
		||||
						.mvps_sticky(adjpos, adjnode)
 | 
			
		||||
				local adjdef = minetest.registered_nodes[adjnode.name]
 | 
			
		||||
				if adjdef and adjdef.mvps_sticky then
 | 
			
		||||
					local sticksto = adjdef.mvps_sticky(adjpos, adjnode)
 | 
			
		||||
 | 
			
		||||
					-- connects to this position?
 | 
			
		||||
					for _, link in ipairs(sticksto) do
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								mesecons_mvps/spec/mineunit.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								mesecons_mvps/spec/mineunit.conf
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
fixture_paths = {"../.test_fixtures"}
 | 
			
		||||
							
								
								
									
										297
									
								
								mesecons_mvps/spec/node_spec.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										297
									
								
								mesecons_mvps/spec/node_spec.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,297 @@
 | 
			
		||||
require("mineunit")
 | 
			
		||||
 | 
			
		||||
fixture("mesecons_mvps")
 | 
			
		||||
 | 
			
		||||
world.set_default_node("air")
 | 
			
		||||
 | 
			
		||||
describe("node movement", function()
 | 
			
		||||
	after_each(function()
 | 
			
		||||
		mesecon._test_reset()
 | 
			
		||||
		world.clear()
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("works with no moved nodes", function()
 | 
			
		||||
		local pos = {x = 0, y = 0, z = 0}
 | 
			
		||||
		local dir = {x = 1, y = 0, z = 0}
 | 
			
		||||
 | 
			
		||||
		assert.same({true, {}, {}}, {mesecon.mvps_push(pos, dir, 1, "")})
 | 
			
		||||
		assert.same({true, {}, {}}, {mesecon.mvps_pull_all(pos, dir, 1, "")})
 | 
			
		||||
		assert.same({true, {}, {}}, {mesecon.mvps_pull_single(pos, dir, 1, "")})
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("works with simple stack", function()
 | 
			
		||||
		local pos = {x = 0, y = 0, z = 0}
 | 
			
		||||
		local dir = {x = 1, y = 0, z = 0}
 | 
			
		||||
		world.set_node(pos, "mesecons:test_conductor_off")
 | 
			
		||||
		world.set_node(vector.add(pos, dir), "mesecons:test_conductor_off")
 | 
			
		||||
 | 
			
		||||
		assert.is_true((mesecon.mvps_push(pos, dir, 2, "")))
 | 
			
		||||
		assert.equal("air", world.get_node(pos).name)
 | 
			
		||||
		assert.equal("mesecons:test_conductor_off", world.get_node(vector.add(pos, dir)).name)
 | 
			
		||||
		assert.equal("mesecons:test_conductor_off", world.get_node(vector.add(pos, vector.multiply(dir, 2))).name)
 | 
			
		||||
 | 
			
		||||
		assert.is_true((mesecon.mvps_pull_all(vector.add(pos, dir), vector.multiply(dir, -1), 2, "")))
 | 
			
		||||
		assert.equal("mesecons:test_conductor_off", world.get_node(pos).name)
 | 
			
		||||
		assert.equal("mesecons:test_conductor_off", world.get_node(vector.add(pos, dir)).name)
 | 
			
		||||
		assert.equal("air", world.get_node(vector.add(pos, vector.multiply(dir, 2))).name)
 | 
			
		||||
 | 
			
		||||
		assert.is_true((mesecon.mvps_pull_single(pos, vector.multiply(dir, -1), 1, "")))
 | 
			
		||||
		assert.equal("mesecons:test_conductor_off", world.get_node(vector.subtract(pos, dir)).name)
 | 
			
		||||
		assert.equal("air", world.get_node(pos).name)
 | 
			
		||||
		assert.equal("mesecons:test_conductor_off", world.get_node(vector.add(pos, dir)).name)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("works with sticky nodes", function()
 | 
			
		||||
		local pos = {x = 0, y = 0, z = 0}
 | 
			
		||||
		local dir = {x = 0, y = 1, z = 0}
 | 
			
		||||
		world.set_node(pos, "mesecons:test_conductor_off")
 | 
			
		||||
		world.set_node(vector.offset(pos, 0, 1, 0), "mesecons_mvps:test_sticky")
 | 
			
		||||
		world.set_node(vector.offset(pos, 1, 1, 0), "mesecons:test_conductor_off")
 | 
			
		||||
		world.set_node(vector.offset(pos, 1, 2, 0), "mesecons:test_conductor_off")
 | 
			
		||||
 | 
			
		||||
		assert.is_true((mesecon.mvps_push(pos, dir, 4, "")))
 | 
			
		||||
		assert.equal("air", world.get_node(vector.offset(pos, 1, 1, 0)).name)
 | 
			
		||||
		assert.equal("mesecons:test_conductor_off", world.get_node(vector.offset(pos, 1, 2, 0)).name)
 | 
			
		||||
		assert.equal("mesecons:test_conductor_off", world.get_node(vector.offset(pos, 1, 3, 0)).name)
 | 
			
		||||
 | 
			
		||||
		assert.is_true((mesecon.mvps_pull_all(vector.add(pos, dir), vector.multiply(dir, -1), 4, "")))
 | 
			
		||||
		assert.equal("air", world.get_node(vector.offset(pos, 1, 0, 0)).name)
 | 
			
		||||
		assert.equal("mesecons:test_conductor_off", world.get_node(vector.offset(pos, 1, 1, 0)).name)
 | 
			
		||||
		assert.equal("mesecons:test_conductor_off", world.get_node(vector.offset(pos, 1, 2, 0)).name)
 | 
			
		||||
 | 
			
		||||
		assert.is_true((mesecon.mvps_pull_single(pos, vector.multiply(dir, -1), 3, "")))
 | 
			
		||||
		assert.equal("air", world.get_node(vector.offset(pos, 1, -1, 0)).name)
 | 
			
		||||
		assert.equal("mesecons:test_conductor_off", world.get_node(vector.offset(pos, 1, 0, 0)).name)
 | 
			
		||||
		assert.equal("air", world.get_node(vector.offset(pos, 1, 1, 0)).name)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("respects maximum", function()
 | 
			
		||||
		local pos = {x = 0, y = 0, z = 0}
 | 
			
		||||
		local dir = {x = 1, y = 0, z = 0}
 | 
			
		||||
		world.set_node(pos, "mesecons:test_conductor_off")
 | 
			
		||||
		world.set_node(vector.add(pos, dir), "mesecons:test_conductor_off")
 | 
			
		||||
 | 
			
		||||
		assert.is_true(not mesecon.mvps_push(pos, dir, 1, ""))
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("is blocked by basic stopper", function()
 | 
			
		||||
		local pos = {x = 0, y = 0, z = 0}
 | 
			
		||||
		local dir = {x = 1, y = 0, z = 0}
 | 
			
		||||
		world.set_node(pos, "mesecons_mvps:test_stopper")
 | 
			
		||||
 | 
			
		||||
		assert.is_true(not mesecon.mvps_push(pos, dir, 1, ""))
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("is blocked by conditional stopper", function()
 | 
			
		||||
		local pos = {x = 0, y = 0, z = 0}
 | 
			
		||||
		local dir = {x = 1, y = 0, z = 0}
 | 
			
		||||
 | 
			
		||||
		world.set_node(pos, {name = "mesecons_mvps:test_stopper_cond", param2 = 0})
 | 
			
		||||
		assert.is_true(not mesecon.mvps_push(pos, dir, 1, ""))
 | 
			
		||||
 | 
			
		||||
		world.set_node(pos, {name = "mesecons_mvps:test_stopper_cond", param2 = 1})
 | 
			
		||||
		assert.is_true((mesecon.mvps_push(pos, dir, 1, "")))
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	-- TODO: I think this is supposed to work?
 | 
			
		||||
	pending("is blocked by ignore", function()
 | 
			
		||||
		local pos = {x = 0, y = 0, z = 0}
 | 
			
		||||
		local dir = {x = 1, y = 0, z = 0}
 | 
			
		||||
		world.set_node(pos, "mesecons:test_conductor_off")
 | 
			
		||||
		world.set_node(vector.add(pos, dir), "ignore")
 | 
			
		||||
 | 
			
		||||
		assert.is_true(not mesecon.mvps_push(pos, dir, 1, ""))
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("moves metadata", function()
 | 
			
		||||
		local pos = {x = 0, y = 0, z = 0}
 | 
			
		||||
		local dir = {x = 1, y = 0, z = 0}
 | 
			
		||||
		world.set_node(pos, "mesecons:test_conductor_off")
 | 
			
		||||
		minetest.get_meta(pos):set_string("foo", "bar")
 | 
			
		||||
		minetest.get_node_timer(pos):set(12, 34)
 | 
			
		||||
 | 
			
		||||
		mesecon.mvps_push(pos, dir, 1, "")
 | 
			
		||||
		assert.equal("bar", minetest.get_meta(vector.add(pos, dir)):get("foo"))
 | 
			
		||||
		local moved_timer = minetest.get_node_timer(vector.add(pos, dir))
 | 
			
		||||
		assert.equal(12, moved_timer:get_timeout())
 | 
			
		||||
		assert.equal(34, moved_timer:get_elapsed())
 | 
			
		||||
		moved_timer:stop()
 | 
			
		||||
		assert.same({}, minetest.get_meta(pos):to_table().fields)
 | 
			
		||||
		assert.is_false(minetest.get_node_timer(pos):is_started())
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("calls move callbacks", function()
 | 
			
		||||
		local pos = {x = 0, y = 0, z = 0}
 | 
			
		||||
		local dir = {x = 1, y = 0, z = 0}
 | 
			
		||||
		world.set_node(pos, {name = "mesecons_mvps:test_on_move", param2 = 123})
 | 
			
		||||
		minetest.get_meta(pos):set_string("foo", "bar")
 | 
			
		||||
		local move_info = {vector.add(pos, dir), world.get_node(pos), pos, minetest.get_meta(pos):to_table()}
 | 
			
		||||
 | 
			
		||||
		mesecon.mvps_push(pos, dir, 1, "")
 | 
			
		||||
		assert.equal(1, #mesecon._test_moves)
 | 
			
		||||
		assert.same(move_info, mesecon._test_moves[1])
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("executes autoconnect hooks", function()
 | 
			
		||||
		local pos = {x = 0, y = 0, z = 0}
 | 
			
		||||
		local dir = {x = 1, y = 0, z = 0}
 | 
			
		||||
		world.set_node(pos, "mesecons:test_conductor_off")
 | 
			
		||||
 | 
			
		||||
		mesecon.mvps_push(pos, dir, 1, "")
 | 
			
		||||
		mineunit:execute_globalstep() -- Execute delayed autoconnect hook
 | 
			
		||||
		assert.equal(2, #mesecon._test_autoconnects)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("updates moved receptors", function()
 | 
			
		||||
		local pos1 = {x = 0, y = 0, z = 0}
 | 
			
		||||
		local pos2 = vector.offset(pos1, 0, 1, 0)
 | 
			
		||||
		local pos3 = vector.offset(pos1, 2, 0, 0)
 | 
			
		||||
		local pos4 = vector.offset(pos1, 0, 0, 1)
 | 
			
		||||
		local dir = {x = 1, y = 0, z = 0}
 | 
			
		||||
		mesecon._test_place(pos1, "mesecons:test_receptor_on")
 | 
			
		||||
		mesecon._test_place(pos2, "mesecons:test_conductor_off")
 | 
			
		||||
		mesecon._test_place(pos3, "mesecons:test_conductor_off")
 | 
			
		||||
		mesecon._test_place(pos4, "mesecons:test_conductor_off")
 | 
			
		||||
		mesecon._test_place(vector.add(pos4, dir), "mesecons:test_conductor_off")
 | 
			
		||||
		mineunit:execute_globalstep() -- Execute receptor_on action
 | 
			
		||||
 | 
			
		||||
		mesecon.mvps_push(pos1, dir, 1, "")
 | 
			
		||||
		mineunit:execute_globalstep() -- Execute receptor_on/receptor_off actions
 | 
			
		||||
		assert.equal("mesecons:test_conductor_off", world.get_node(pos2).name)
 | 
			
		||||
		assert.equal("mesecons:test_conductor_on", world.get_node(pos3).name)
 | 
			
		||||
		assert.equal("mesecons:test_conductor_on", world.get_node(pos4).name)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("updates moved conductors", function()
 | 
			
		||||
		local pos1 = {x = 0, y = 0, z = 0}
 | 
			
		||||
		local pos2 = vector.offset(pos1, 0, 1, 0)
 | 
			
		||||
		local pos3 = vector.offset(pos1, 0, -1, 0)
 | 
			
		||||
		local dir = {x = 1, y = 0, z = 0}
 | 
			
		||||
		mesecon._test_place(pos1, "mesecons:test_conductor_off")
 | 
			
		||||
		mesecon._test_place(pos2, "mesecons:test_receptor_on")
 | 
			
		||||
		mesecon._test_place(pos3, "mesecons:test_conductor_off")
 | 
			
		||||
		mineunit:execute_globalstep() -- Execute receptor_on action
 | 
			
		||||
 | 
			
		||||
		mesecon.mvps_push(pos1, dir, 1, "")
 | 
			
		||||
		mineunit:execute_globalstep() -- Execute receptor_off action
 | 
			
		||||
		assert.equal("mesecons:test_conductor_off", world.get_node(vector.add(pos1, dir)).name)
 | 
			
		||||
		assert.equal("mesecons:test_conductor_off", world.get_node(pos3).name)
 | 
			
		||||
 | 
			
		||||
		mesecon.mvps_pull_all(vector.add(pos1, dir), vector.multiply(dir, -1), 1, "")
 | 
			
		||||
		mineunit:execute_globalstep() -- Execute receptor_on action
 | 
			
		||||
		assert.equal("mesecons:test_conductor_on", world.get_node(pos1).name)
 | 
			
		||||
		assert.equal("mesecons:test_conductor_on", world.get_node(pos3).name)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("updates moved effectors", function()
 | 
			
		||||
		local pos = {x = 0, y = 0, z = 0}
 | 
			
		||||
		local dir = {x = 1, y = 0, z = 0}
 | 
			
		||||
		mesecon._test_place(pos, "mesecons:test_effector")
 | 
			
		||||
		mesecon._test_place(vector.offset(pos, 0, 1, 0), "mesecons:test_receptor_on")
 | 
			
		||||
		mesecon._test_place(vector.add(pos, dir), "mesecons:test_receptor_on")
 | 
			
		||||
		mineunit:execute_globalstep() -- Execute receptor_on action
 | 
			
		||||
		mineunit:execute_globalstep() -- Execute activate/change actions
 | 
			
		||||
 | 
			
		||||
		mesecon.mvps_push(pos, dir, 2, "")
 | 
			
		||||
		mineunit:execute_globalstep() -- Execute receptor_on/receptor_off actions
 | 
			
		||||
		mineunit:execute_globalstep() -- Execute activate/deactivate/change actions
 | 
			
		||||
		assert.equal(tonumber("10000001", 2), world.get_node(vector.add(pos, dir)).param2)
 | 
			
		||||
 | 
			
		||||
		mineunit:execute_globalstep() -- Let the component cool down
 | 
			
		||||
 | 
			
		||||
		mesecon.mvps_pull_single(vector.add(pos, dir), vector.multiply(dir, -1), 1, "")
 | 
			
		||||
		mineunit:execute_globalstep() -- Execute receptor_on/receptor_off actions
 | 
			
		||||
		mineunit:execute_globalstep() -- Execute activate/deactivate/change actions
 | 
			
		||||
		assert.equal(tonumber("10000100", 2), world.get_node(pos).param2)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	-- Since turnon is called before turnoff when pushing, effectors may be incorrectly turned off.
 | 
			
		||||
	it("does not overwrite turnon with receptor_off", function()
 | 
			
		||||
		local pos = {x = 0, y = 0, z = 0}
 | 
			
		||||
		local dir = {x = 1, y = 0, z = 0}
 | 
			
		||||
		mesecon._test_place(pos, "mesecons:test_effector")
 | 
			
		||||
		mesecon._test_place(vector.add(pos, dir), "mesecons:test_conductor_off")
 | 
			
		||||
		mesecon._test_place(vector.add(pos, vector.multiply(dir, 2)), "mesecons:test_receptor_on")
 | 
			
		||||
		mineunit:execute_globalstep() -- Execute receptor_on action
 | 
			
		||||
		mineunit:execute_globalstep() -- Execute activate/change actions
 | 
			
		||||
 | 
			
		||||
		mesecon.mvps_push(pos, dir, 3, "")
 | 
			
		||||
		mineunit:execute_globalstep() -- Execute receptor_on/receptor_off actions
 | 
			
		||||
		mineunit:execute_globalstep() -- Execute activate/deactivate/change actions
 | 
			
		||||
		assert.equal(tonumber("10000001", 2), world.get_node(vector.add(pos, dir)).param2)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	-- mineunit doesn't yet implement minetest.check_for_falling.
 | 
			
		||||
	pending("causes nodes to fall", function()
 | 
			
		||||
	end)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
describe("protection", function()
 | 
			
		||||
	teardown(function()
 | 
			
		||||
		minetest.settings:remove("mesecon.mvps_protection_mode")
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	after_each(function()
 | 
			
		||||
		mesecon._test_reset()
 | 
			
		||||
		world.clear()
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	local protected_pos = {x = 1, y = 0, z = 0}
 | 
			
		||||
	mineunit:protect(protected_pos, "Joe")
 | 
			
		||||
 | 
			
		||||
	it("blocks movement", function()
 | 
			
		||||
		minetest.settings:set("mesecon.mvps_protection_mode", "restrict")
 | 
			
		||||
 | 
			
		||||
		local pos = {x = 0, y = 0, z = 0}
 | 
			
		||||
		world.set_node(pos, "mesecons:test_conductor_off")
 | 
			
		||||
 | 
			
		||||
		assert.same({false, "protected"}, {mesecon.mvps_push(pos, {x = 1, y = 0, z = 0}, 1, "Bob")})
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("allows owner's movement", function()
 | 
			
		||||
		minetest.settings:set("mesecon.mvps_protection_mode", "restrict")
 | 
			
		||||
 | 
			
		||||
		local pos = {x = 0, y = 0, z = 0}
 | 
			
		||||
		world.set_node(pos, "mesecons:test_conductor_off")
 | 
			
		||||
 | 
			
		||||
		assert.is_true((mesecon.mvps_push(pos, {x = 1, y = 0, z = 0}, 1, "Joe")))
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("'ignore'", function()
 | 
			
		||||
		minetest.settings:set("mesecon.mvps_protection_mode", "ignore")
 | 
			
		||||
 | 
			
		||||
		local pos = {x = 0, y = 0, z = 0}
 | 
			
		||||
		world.set_node(pos, "mesecons:test_conductor_off")
 | 
			
		||||
 | 
			
		||||
		assert.is_true((mesecon.mvps_push(pos, {x = 1, y = 0, z = 0}, 1, "Bob")))
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("'normal'", function()
 | 
			
		||||
		minetest.settings:set("mesecon.mvps_protection_mode", "normal")
 | 
			
		||||
 | 
			
		||||
		local pos = {x = 0, y = 0, z = 0}
 | 
			
		||||
		world.set_node(pos, "mesecons:test_conductor_off")
 | 
			
		||||
 | 
			
		||||
		assert.same({false, "protected"}, {mesecon.mvps_push(pos, {x = 1, y = 0, z = 0}, 1, "")})
 | 
			
		||||
 | 
			
		||||
		assert.is_true((mesecon.mvps_push(pos, {x = 0, y = 1, z = 0}, 1, "")))
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("'compat'", function()
 | 
			
		||||
		minetest.settings:set("mesecon.mvps_protection_mode", "compat")
 | 
			
		||||
 | 
			
		||||
		local pos = {x = 0, y = 0, z = 0}
 | 
			
		||||
		world.set_node(pos, "mesecons:test_conductor_off")
 | 
			
		||||
 | 
			
		||||
		assert.is_true((mesecon.mvps_push(pos, {x = 1, y = 0, z = 0}, 1, "")))
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("'restrict'", function()
 | 
			
		||||
		minetest.settings:set("mesecon.mvps_protection_mode", "restrict")
 | 
			
		||||
 | 
			
		||||
		local pos = {x = 0, y = 0, z = 0}
 | 
			
		||||
		world.set_node(pos, "mesecons:test_conductor_off")
 | 
			
		||||
 | 
			
		||||
		assert.same({false, "protected"}, {mesecon.mvps_push(pos, {x = 0, y = 1, z = 0}, 1, "")})
 | 
			
		||||
	end)
 | 
			
		||||
end)
 | 
			
		||||
							
								
								
									
										3
									
								
								mesecons_mvps/spec/object_spec.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								mesecons_mvps/spec/object_spec.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
-- mineunit doesn't yet implement minetest.get_objects_inside_radius
 | 
			
		||||
pending("object movement", function()
 | 
			
		||||
end)
 | 
			
		||||
							
								
								
									
										15
									
								
								mesecons_noteblock/README.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								mesecons_noteblock/README.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
Credits of sound files:
 | 
			
		||||
 | 
			
		||||
Note: Most sounds have not been used verbatim, but tweaked a little to be more suitable for the noteblock mod.
 | 
			
		||||
 | 
			
		||||
* mesecons_noteblock_litecrash.ogg
 | 
			
		||||
	* License: CC BY 3.0
 | 
			
		||||
	* by freesound.org user ani_music
 | 
			
		||||
	* Source: https://freesound.org/people/ani_music/sounds/219612/
 | 
			
		||||
 | 
			
		||||
Everything else:
 | 
			
		||||
Created by Mesecons authors, licensed CC BY 3.0.
 | 
			
		||||
 | 
			
		||||
--------------------
 | 
			
		||||
License links:
 | 
			
		||||
* CC BY 3.0: http://creativecommons.org/licenses/by/3.0/
 | 
			
		||||
@@ -6,8 +6,8 @@ This effector makes a sound if powered and can be used for making music. Normall
 | 
			
		||||
<tr><td>Chest or Locked Chest</td><td>Snare</td></tr>
 | 
			
		||||
<tr><td>Any tree</td><td>Crash</td></tr>
 | 
			
		||||
<tr><td>Any wooden planks</td><td>Lite Crash</td></tr>
 | 
			
		||||
<tr><td>Coal Block</td><td>Explosion sound</td></tr>
 | 
			
		||||
<tr><td>Lava Source</td><td>Fire sound</td></tr>
 | 
			
		||||
<tr><td>Coal Block</td><td>Explosion sound (fixed pitch)</td></tr>
 | 
			
		||||
<tr><td>Lava Source</td><td>Fire sound (fixed pitch)</td></tr>
 | 
			
		||||
<tr><td>Steel Block</td><td>Piano (high pitch, one octave higher than normal)</td></tr>
 | 
			
		||||
<tr><td>Any other block</td><td>Piano (low pitch)</td></tr>
 | 
			
		||||
</table>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,7 @@
 | 
			
		||||
local S = minetest.get_translator(minetest.get_current_modname())
 | 
			
		||||
 | 
			
		||||
minetest.register_node("mesecons_noteblock:noteblock", {
 | 
			
		||||
	description = "Noteblock",
 | 
			
		||||
	description = S("Noteblock"),
 | 
			
		||||
	tiles = {"mesecons_noteblock.png"},
 | 
			
		||||
	is_ground_content = false,
 | 
			
		||||
	groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2},
 | 
			
		||||
@@ -18,6 +20,7 @@ minetest.register_node("mesecons_noteblock:noteblock", {
 | 
			
		||||
			mesecon.noteblock_play(pos, node.param2)
 | 
			
		||||
		end
 | 
			
		||||
	}},
 | 
			
		||||
	place_param2 = 11, -- initialize at C note
 | 
			
		||||
	on_blast = mesecon.on_blastnode,
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
@@ -43,7 +46,7 @@ local soundnames = {
 | 
			
		||||
	"mesecons_noteblock_a",
 | 
			
		||||
	"mesecons_noteblock_asharp",
 | 
			
		||||
	"mesecons_noteblock_b",
 | 
			
		||||
	"mesecons_noteblock_c"
 | 
			
		||||
	"mesecons_noteblock_c" -- << noteblock is initialized here
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
local node_sounds = {}
 | 
			
		||||
@@ -72,6 +75,9 @@ mesecon.noteblock_play = function(pos, param2)
 | 
			
		||||
	pos.y = pos.y-1
 | 
			
		||||
	local nodeunder = minetest.get_node(pos).name
 | 
			
		||||
	local soundname = node_sounds[nodeunder]
 | 
			
		||||
	local use_pitch = true
 | 
			
		||||
	local pitch
 | 
			
		||||
	-- Special sounds
 | 
			
		||||
	if not soundname then
 | 
			
		||||
		for k,v in pairs(node_sounds_group) do
 | 
			
		||||
			local g = minetest.get_item_group(nodeunder, k)
 | 
			
		||||
@@ -81,6 +87,7 @@ mesecon.noteblock_play = function(pos, param2)
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	-- Piano
 | 
			
		||||
	if not soundname then
 | 
			
		||||
		soundname = soundnames[param2]
 | 
			
		||||
		if not soundname then
 | 
			
		||||
@@ -90,6 +97,17 @@ mesecon.noteblock_play = function(pos, param2)
 | 
			
		||||
		if nodeunder == steelblock_nodename then
 | 
			
		||||
			soundname = soundname.. 2
 | 
			
		||||
		end
 | 
			
		||||
		use_pitch = false
 | 
			
		||||
	end
 | 
			
		||||
	-- Disable pitch for fire and explode because they'd sound too odd
 | 
			
		||||
	if soundname == "fire_fire" or soundname == "tnt_explode" then
 | 
			
		||||
		use_pitch = false
 | 
			
		||||
	end
 | 
			
		||||
	if use_pitch then
 | 
			
		||||
		-- Calculate pitch
 | 
			
		||||
		-- Adding 1 to param2 because param2=11 is *lowest* pitch sound
 | 
			
		||||
		local val = (param2+1)%12
 | 
			
		||||
		pitch = 2^((val-6)/12)
 | 
			
		||||
	end
 | 
			
		||||
	pos.y = pos.y+1
 | 
			
		||||
	if soundname == "fire_fire" then
 | 
			
		||||
@@ -97,6 +115,6 @@ mesecon.noteblock_play = function(pos, param2)
 | 
			
		||||
		local handle = minetest.sound_play(soundname, {pos = pos, loop = true})
 | 
			
		||||
		minetest.after(3.0, minetest.sound_fade, handle, -1.5, 0.0)
 | 
			
		||||
	else
 | 
			
		||||
		minetest.sound_play(soundname, {pos = pos}, true)
 | 
			
		||||
		minetest.sound_play(soundname, {pos = pos, pitch = pitch}, true)
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user