Merge remote-tracking branch 'upstream/master'

This commit is contained in:
bri cassa 2022-03-05 11:22:46 +01:00
commit 69a4b6b332
61 changed files with 273 additions and 223 deletions

15
.github/workflows/check-release.yml vendored Normal file
View File

@ -0,0 +1,15 @@
on: [push, pull_request]
name: Check & Release
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@main
- name: apt
run: sudo apt-get install -y luarocks
- name: luacheck install
run: luarocks install --local luacheck
- name: luacheck run
run: $HOME/.luarocks/bin/luacheck ./

36
.luacheckrc Normal file
View File

@ -0,0 +1,36 @@
std = "lua51c"
ignore = {
"21/_+", -- Unused variable, except "_", "__", etc.
"213", -- Unused loop variable
"421", -- Shadowing a local variable
"422", -- Shadowing an argument
"423", -- Shadowing a loop variable
"431", -- Shadowing an upvalue
"432", -- Shadowing an upvalue argument
"433", -- Shadowing an upvalue loop variable
"542", -- Empty if branch
}
max_line_length = 200
read_globals = {
"default",
"digiline",
"doors",
"dump",
"jit",
"minetest",
"screwdriver",
"string.split",
"table.copy",
"table.insert_all",
"vector",
"VoxelArea",
}
globals = {"mesecon"}
files["mesecons/actionqueue.lua"] = {
globals = {"minetest.registered_globalsteps"},
}

View File

@ -12,9 +12,9 @@ MESECONS by Jeija and contributors
Mezzee-what?
------------
[Mesecons](http://mesecons.net/)! They're yellow, they're conductive, and they'll add a whole new dimension to Minetest's gameplay.
[Mesecons](https://mesecons.net/)! They're yellow, they're conductive, and they'll add a whole new dimension to Minetest's gameplay.
Mesecons is a mod for [Minetest](http://minetest.net/) that implements a ton of items related to digital circuitry, such as wires, buttons, lights, and even programmable controllers. Among other things, there are also pistons, solar panels, pressure plates, and note blocks.
Mesecons is a mod for [Minetest](https://www.minetest.net/) that implements a ton of items related to digital circuitry, such as wires, buttons, lights, and even programmable controllers. Among other things, there are also pistons, solar panels, pressure plates, and note blocks.
Mesecons has a similar goal to Redstone in Minecraft, but works in its own way, with different rules and mechanics.
@ -74,8 +74,10 @@ There are also a whole bunch of other people helping with everything from code t
Alright, how can I use it?
--------------------------
All textures in this project are licensed under the CC-BY-SA 3.0 (Creative Commons Attribution-ShareAlike 3.0 Generic). That means you can distribute and remix them as much as you want to, under the condition that you give credit to the authors and the project, and that if you remix and release them, they must be under the same or similar license to this one.
All textures in this project are licensed under the CC-BY-SA 3.0 (Creative Commons Attribution-ShareAlike 3.0 Generic).
That means you can distribute and remix them as much as you want to, under the condition that you give credit to the authors and the project, and that if you remix and release them, they must be under the same or similar license to this one.
All code in this project is licensed under the LGPL version 3 or later. That means you have unlimited freedom to distribute and modify the work however you see fit, provided that if you decide to distribute it or any modified versions of it, you must also use the same license. The LGPL also grants the additional freedom to write extensions for the software and distribute them without the extensions being subject to the terms of the LGPL, although the software itself retains its license.
All code in this project is licensed under the LGPL version 3.
That means you have unlimited freedom to distribute and modify the work however you see fit, provided that if you decide to distribute it or any modified versions of it, you must also use the same license. The LGPL also grants the additional freedom to write extensions for the software and distribute them without the extensions being subject to the terms of the LGPL, although the software itself retains its license.
No warranty is provided, express or implied, for any part of the project.

View File

@ -1,9 +1,9 @@
{
"name": "mesecons",
"description": "Mesecons is a mod for Minetest that implements items related to digital circuitry: wires, buttons, lights, and programmable controllers.",
"homepage": "http://mesecons.net",
"authors": "Jeija",
"license": "LGPL-3.0+",
"homepage": "https://mesecons.net",
"authors": ["Jeija"],
"license": "LGPL-3.0",
"keywords": [
"mesecons",
"minetest",

View File

@ -29,7 +29,7 @@ local queue = mesecon.queue
queue.actions = {} -- contains all ActionQueue actions
function queue:add_function(name, func)
queue.funcs[name] = func
self.funcs[name] = func
end
-- If add_action with twice the same overwritecheck and same position are called, the first one is overwritten
@ -51,17 +51,17 @@ function queue:add_action(pos, func, params, time, overwritecheck, priority)
-- check if old action has to be overwritten / removed:
if overwritecheck then
for i, ac in ipairs(queue.actions) do
for i, ac in ipairs(self.actions) do
if vector.equals(pos, ac.pos)
and mesecon.cmpAny(overwritecheck, ac.owcheck) then
-- remove the old action
table.remove(queue.actions, i)
table.remove(self.actions, i)
break
end
end
end
table.insert(queue.actions, action)
table.insert(self.actions, action)
end
-- execute the stored functions on a globalstep
@ -133,8 +133,8 @@ end
function queue:execute(action)
-- ignore if action queue function name doesn't exist,
-- (e.g. in case the action queue savegame was written by an old mesecons version)
if queue.funcs[action.func] then
queue.funcs[action.func](action.pos, unpack(action.params))
if self.funcs[action.func] then
self.funcs[action.func](action.pos, unpack(action.params))
end
end

View File

@ -318,7 +318,7 @@ function mesecon.get_conductor_on(node_off, rulename)
return conductor.states[tonumber(binstate,2)+1]
end
end
return offstate
return nil
end
function mesecon.get_conductor_off(node_on, rulename)
@ -334,7 +334,7 @@ function mesecon.get_conductor_off(node_on, rulename)
return conductor.states[tonumber(binstate,2)+1]
end
end
return onstate
return nil
end
function mesecon.conductor_get_rules(node)
@ -372,7 +372,6 @@ end
local light_update_conductors
-- Calculate the contents of the above set if they have not been calculated.
-- This must be called before get_update_light_conductor.
local function find_light_update_conductors()
-- The expensive calculation is only done the first time.
if light_update_conductors then return end
@ -415,12 +414,6 @@ local function find_light_update_conductors()
end
end
-- This is the callback for swap_node_force in turnon and turnoff. It determines
-- whether a conductor node necessitates a lighting update.
local function get_update_light_conductor(pos, name)
return light_update_conductors[name] ~= nil
end
-- Turn off an equipotential section starting at `pos`, which outputs in the direction of `link`.
-- Breadth-first search. Map is abstracted away in a voxelmanip.
-- Follow all all conductor paths replacing conductors that were already
@ -453,7 +446,7 @@ function mesecon.turnon(pos, link)
end
end
mesecon.swap_node_force(f.pos, mesecon.get_conductor_on(node, f.link), get_update_light_conductor)
mesecon.swap_node_force(f.pos, mesecon.get_conductor_on(node, f.link), light_update_conductors[node.name] ~= nil)
end
-- Only conductors with flat rules can be reliably skipped later
@ -527,7 +520,7 @@ function mesecon.turnoff(pos, link)
end
end
mesecon.swap_node_force(f.pos, mesecon.get_conductor_off(node, f.link), get_update_light_conductor)
mesecon.swap_node_force(f.pos, mesecon.get_conductor_off(node, f.link), light_update_conductors[node.name] ~= nil)
end
-- Only conductors with flat rules can be reliably skipped later

View File

@ -11,4 +11,4 @@ local old_forceloaded_blocks = mesecon.file2table("mesecon_forceloaded")
for hash, _ in pairs(old_forceloaded_blocks) do
minetest.forceload_free_block(unhash_blockpos(hash))
end
os.remove(minetest.get_worldpath()..DIR_DELIM.."mesecon_forceloaded")
os.remove(minetest.get_worldpath().."/mesecon_forceloaded")

View File

@ -1,2 +1,4 @@
name = mesecons
depends = default
# default is an optional dependency as some mods may expect it as a transitory
# dependency when they depend on mesecons.
optional_depends = default

View File

@ -11,7 +11,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="Mesecons",
mesecons = {conductor={
state = mesecon.state.off,
onstate = "mesecons:mesecon_on"

View File

@ -63,7 +63,7 @@ mesecon.on_dignode = function(pos, node)
mesecon.execute_autoconnect_hooks_queue(pos, node)
end
function mesecon.on_blastnode(pos, intensity)
function mesecon.on_blastnode(pos)
local node = minetest.get_node(pos)
minetest.remove_node(pos)
mesecon.on_dignode(pos, node)

View File

@ -286,7 +286,7 @@ end
-- File writing / reading utilities
local wpath = minetest.get_worldpath()
function mesecon.file2table(filename)
local f = io.open(wpath..DIR_DELIM..filename, "r")
local f = io.open(wpath.."/"..filename, "r")
if f == nil then return {} end
local t = f:read("*all")
f:close()
@ -295,7 +295,7 @@ function mesecon.file2table(filename)
end
function mesecon.table2file(filename, table)
local f = io.open(wpath..DIR_DELIM..filename, "w")
local f = io.open(wpath.."/"..filename, "w")
f:write(minetest.serialize(table))
f:close()
end
@ -326,6 +326,9 @@ end
-- Nil if no VM-based transaction is in progress.
local vm_cache = nil
-- Whether the current transaction will need a light update afterward.
local vm_update_light = false
-- Starts a VoxelManipulator-based transaction.
--
-- During a VM transaction, calls to vm_get_node and vm_swap_node operate on a
@ -334,6 +337,7 @@ local vm_cache = nil
-- vm_abort.
function mesecon.vm_begin()
vm_cache = {}
vm_update_light = false
end
-- Finishes a VoxelManipulator-based transaction, freeing the VMs and map data
@ -343,7 +347,7 @@ function mesecon.vm_commit()
if tbl.dirty then
local vm = tbl.vm
vm:set_data(tbl.data)
vm:write_to_map(tbl.update_light)
vm:write_to_map(vm_update_light)
vm:update_map()
end
end
@ -364,7 +368,7 @@ local function vm_get_or_create_entry(pos)
local vm = minetest.get_voxel_manip(pos, pos)
local min_pos, max_pos = vm:get_emerged_area()
local va = VoxelArea:new{MinEdge = min_pos, MaxEdge = max_pos}
tbl = {vm = vm, va = va, data = vm:get_data(), param1 = vm:get_light_data(), param2 = vm:get_param2_data(), dirty = false, update_light = false}
tbl = {vm = vm, va = va, data = vm:get_data(), param1 = vm:get_light_data(), param2 = vm:get_param2_data(), dirty = false}
vm_cache[hash] = tbl
end
return tbl
@ -376,7 +380,7 @@ function mesecon.vm_get_node(pos)
local tbl = vm_get_or_create_entry(pos)
local index = tbl.va:indexp(pos)
local node_value = tbl.data[index]
if node_value == core.CONTENT_IGNORE then
if node_value == minetest.CONTENT_IGNORE then
return nil
else
local node_param1 = tbl.param1[index]
@ -389,10 +393,13 @@ end
--
-- Existing param1, param2, and metadata are left alone.
--
-- See mesecon.swap_node_force for documentation about get_update_light.
function mesecon.vm_swap_node(pos, name, get_update_light)
-- The swap will necessitate a light update unless update_light equals false.
function mesecon.vm_swap_node(pos, name, update_light)
-- If one node needs a light update, all VMs should use light updates to
-- prevent newly calculated light from being overwritten by other VMs.
vm_update_light = vm_update_light or update_light ~= false
local tbl = vm_get_or_create_entry(pos)
tbl.update_light = tbl.update_light or (get_update_light == nil or get_update_light(pos, name))
local index = tbl.va:indexp(pos)
tbl.data[index] = minetest.get_content_id(name)
tbl.dirty = true
@ -426,15 +433,15 @@ end
-- Outside a VM transaction, if the mapblock is not loaded, it is pulled into
-- the servers main map data cache and then accessed from there.
--
-- Inside a VM transaction, the transactions VM cache is used. If a third
-- argument is supplied, it may be called. If it returns false, the swap does
-- not necessitate a lighting update.
-- Inside a VM transaction, the transactions VM cache is used.
--
-- This function can only be used to change the nodes name, not its parameters
-- or metadata.
function mesecon.swap_node_force(pos, name, get_update_light)
--
-- The swap will necessitate a light update unless update_light equals false.
function mesecon.swap_node_force(pos, name, update_light)
if vm_cache then
return mesecon.vm_swap_node(pos, name, get_update_light)
return mesecon.vm_swap_node(pos, name, update_light)
else
-- This serves to both ensure the mapblock is loaded and also hand us
-- the old node table so we can preserve param2.

View File

@ -32,7 +32,7 @@ mesecon.register_node("mesecons_blinkyplant:blinky_plant", {
fixed = {-0.3, -0.5, -0.3, 0.3, -0.5+0.7, 0.3},
},
on_timer = on_timer,
on_rightclick = function(pos, node, clicker)
on_rightclick = function(pos, _, clicker)
if minetest.is_protected(pos, clicker and clicker:get_player_name() or "") then
return
end

View File

@ -1,2 +1,2 @@
name = mesecons_blinkyplant
depends = mesecons
depends = default, mesecons

View File

@ -1,2 +1,2 @@
name = mesecons_button
depends = mesecons, mesecons_receiver
depends = default, mesecons, mesecons_receiver

View File

@ -79,7 +79,7 @@ local function after_place(pos, placer)
end
end
local function receive_fields(pos, formname, fields, sender)
local function receive_fields(pos, _, fields, sender)
if not fields.submit then
return
end

View File

@ -1,2 +1,2 @@
name = mesecons_commandblock
depends = mesecons
depends = default, mesecons

View File

@ -1,2 +1,2 @@
name = mesecons_delayer
depends = mesecons
depends = default, mesecons

View File

@ -12,7 +12,7 @@ local function object_detector_make_formspec(pos)
"button_exit[7,0.75;2,3;;Save]")
end
local function object_detector_on_receive_fields(pos, formname, fields, sender)
local function object_detector_on_receive_fields(pos, _, fields, sender)
if not fields.scanname or not fields.digiline_channel then return end
if minetest.is_protected(pos, sender:get_player_name()) then return end
@ -53,7 +53,7 @@ end
-- set player name when receiving a digiline signal on a specific channel
local object_detector_digiline = {
effector = {
action = function(pos, node, channel, msg)
action = function(pos, _, channel, msg)
local meta = minetest.get_meta(pos)
if channel == meta:get_string("digiline_channel") then
meta:set_string("scanname", msg)
@ -156,7 +156,7 @@ local function node_detector_make_formspec(pos)
"button_exit[7,0.75;2,3;;Save]")
end
local function node_detector_on_receive_fields(pos, fieldname, fields, sender)
local function node_detector_on_receive_fields(pos, _, fields, sender)
if not fields.scanname or not fields.digiline_channel then return end
if minetest.is_protected(pos, sender:get_player_name()) then return end
@ -238,23 +238,6 @@ local node_detector_digiline = {
receptor = {}
}
local function after_place_node_detector(pos, placer)
local placer_pos = placer:get_pos()
if not placer_pos then
return
end
--correct for the player's height
if placer:is_player() then
placer_pos.y = placer_pos.y + 1.625
end
--correct for 6d facedir
local node = minetest.get_node(pos)
node.param2 = minetest.dir_to_facedir(vector.subtract(pos, placer_pos), true)
minetest.set_node(pos, node)
end
minetest.register_node("mesecons_detector:node_detector_off", {
tiles = {"default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "jeija_node_detector_off.png"},
paramtype = "light",

View File

@ -1,2 +1,2 @@
name = mesecons_detector
depends = mesecons, mesecons_materials
depends = default, mesecons, mesecons_materials

View File

@ -22,11 +22,11 @@ end
local function meseconify_door(name)
if minetest.registered_items[name .. "_b_1"] then
-- old style double-node doors
local function toggle_state1 (pos, node)
local function toggle_state1 (pos)
on_rightclick(pos, 1, name.."_t_1", name.."_b_2", name.."_t_2", {1,2,3,0})
end
local function toggle_state2 (pos, node)
local function toggle_state2 (pos)
on_rightclick(pos, 1, name.."_t_2", name.."_b_1", name.."_t_1", {3,0,1,2})
end
@ -49,13 +49,13 @@ local function meseconify_door(name)
-- new style mesh node based doors
local override = {
mesecons = {effector = {
action_on = function(pos, node)
action_on = function(pos)
local door = doors.get(pos)
if door then
door:open()
end
end,
action_off = function(pos, node)
action_off = function(pos)
local door = doors.get(pos)
if door then
door:close()
@ -93,13 +93,13 @@ end
if doors and doors.get then
local override = {
mesecons = {effector = {
action_on = function(pos, node)
action_on = function(pos)
local door = doors.get(pos)
if door then
door:open()
end
end,
action_off = function(pos, node)
action_off = function(pos)
local door = doors.get(pos)
if door then
door:close()

View File

@ -1,15 +1,13 @@
local function crossover_get_rules(node)
return {
{--first wire
{x=-1,y=0,z=0},
{x=1,y=0,z=0},
},
{--second wire
{x=0,y=0,z=-1},
{x=0,y=0,z=1},
},
}
end
local crossover_rules = {
{--first wire
{x=-1,y=0,z=0},
{x=1,y=0,z=0},
},
{--second wire
{x=0,y=0,z=-1},
{x=0,y=0,z=1},
},
}
local crossover_states = {
"mesecons_extrawires:crossover_off",
@ -38,7 +36,7 @@ minetest.register_node("mesecons_extrawires:crossover_off", {
mesecons = {
conductor = {
states = crossover_states,
rules = crossover_get_rules(),
rules = crossover_rules,
}
},
on_blast = mesecon.on_blastnode,
@ -65,7 +63,7 @@ minetest.register_node("mesecons_extrawires:crossover_01", {
mesecons = {
conductor = {
states = crossover_states,
rules = crossover_get_rules(),
rules = crossover_rules,
}
},
on_blast = mesecon.on_blastnode,
@ -92,7 +90,7 @@ minetest.register_node("mesecons_extrawires:crossover_10", {
mesecons = {
conductor = {
states = crossover_states,
rules = crossover_get_rules(),
rules = crossover_rules,
}
},
on_blast = mesecon.on_blastnode,
@ -119,7 +117,7 @@ minetest.register_node("mesecons_extrawires:crossover_on", {
mesecons = {
conductor = {
states = crossover_states,
rules = crossover_get_rules(),
rules = crossover_rules,
}
},
on_blast = mesecon.on_blastnode,

View File

@ -69,7 +69,7 @@ local vertical_updatepos = function (pos)
end
end
local vertical_update = function (pos, node)
local vertical_update = function (pos)
vertical_updatepos(pos) -- this one
vertical_updatepos(vector.add(pos, vertical_rules[1])) -- above
vertical_updatepos(vector.add(pos, vertical_rules[2])) -- below

View File

@ -96,7 +96,7 @@ plg.register_nodes({
meta:set_int("valid", 0)
meta:set_string("infotext", "FPGA")
end,
on_rightclick = function(pos, node, clicker)
on_rightclick = function(pos, _, clicker)
if not minetest.is_player(clicker) then
return
end
@ -113,9 +113,10 @@ plg.register_nodes({
mesecons = {
effector = {
rules = {}, -- replaced later
action_change = function(pos, node, rule, newstate)
plg.ports_changed(pos, rule, newstate)
plg.update(pos)
action_change = function(pos, _, rule, newstate)
if plg.ports_changed(pos, rule, newstate) then
plg.update(pos)
end
end
}
},
@ -129,7 +130,7 @@ plg.register_nodes({
end
end,
on_blast = mesecon.on_blastnode,
on_rotate = function(pos, node, user, mode)
on_rotate = function(pos, _, user, mode)
local abcd1 = {"A", "B", "C", "D"}
local abcd2 = {A = 1, B = 2, C = 3, D = 4}
local ops = {"op1", "op2", "dst"}
@ -326,8 +327,10 @@ plg.update = function(pos)
plg.setports(pos, A, B, C, D)
end
-- Updates the port states according to the signal change.
-- Returns whether the port states actually changed.
plg.ports_changed = function(pos, rule, newstate)
if rule == nil then return end
if rule == nil then return false end
local meta = minetest.get_meta(pos)
local states
@ -347,10 +350,14 @@ plg.ports_changed = function(pos, rule, newstate)
local portno = ({4, 1, nil, 3, 2})[3 + rule.x + 2*rule.z]
states[portno] = (newstate == "on")
meta:set_string("portstates",
local new_portstates =
(states[1] and "1" or "0") .. (states[2] and "1" or "0") ..
(states[3] and "1" or "0") .. (states[4] and "1" or "0")
)
if new_portstates ~= s then
meta:set_string("portstates", new_portstates)
return true
end
return false
end
plg.getports = function(pos) -- gets merged states of INPUT & OUTPUT

View File

@ -10,10 +10,10 @@ local operations = {
-- unary: Whether this gate only has one input
{ gate = "and", short = "&", fs_name = " AND", func = function(a, b) return a and b end },
{ gate = "or", short = "|", fs_name = " OR", func = function(a, b) return a or b end },
{ gate = "not", short = "~", fs_name = " NOT", func = function(a, b) return not b end, unary = true },
{ gate = "not", short = "~", fs_name = " NOT", func = function(_, b) return not b end, unary = true },
{ gate = "xor", short = "^", fs_name = " XOR", func = function(a, b) return a ~= b end },
{ gate = "nand", short = "?", fs_name = "NAND", func = function(a, b) return not (a and b) end },
{ gate = "buf", short = "_", fs_name = " =", func = function(a, b) return b end, unary = true },
{ gate = "buf", short = "_", fs_name = " =", func = function(_, b) return b end, unary = true },
{ gate = "xnor", short = "=", fs_name = "XNOR", func = function(a, b) return a == b end },
{ gate = "nor", short = "!", fs_name = " NOR", func = function(a, b) return not (a or b) end },
}

View File

@ -1,3 +1,3 @@
name = mesecons_fpga
depends = mesecons
depends = default, mesecons
optional_depends = screwdriver

View File

@ -65,7 +65,6 @@ end
local function register_gate(name, inputnumber, assess, recipe, description)
local get_inputrules = inputnumber == 2 and gate_get_input_rules_twoinputs or
gate_get_input_rules_oneinput
description = "Logic Gate: "..name
local basename = "mesecons_gates:"..name
mesecon.register_node(basename, {

View File

@ -1,2 +1,2 @@
name = mesecons_gates
depends = mesecons, mesecons_microcontroller, mesecons_delayer, mesecons_torch, mesecons_materials
depends = default, mesecons, mesecons_microcontroller, mesecons_delayer, mesecons_torch, mesecons_materials

View File

@ -72,7 +72,7 @@ minetest.register_abm({
nodenames = {"mesecons_hydroturbine:hydro_turbine_off"},
interval = 1,
chance = 1,
action = function(pos, node, active_object_count, active_object_count_wider)
action = function(pos)
local waterpos={x=pos.x, y=pos.y+1, z=pos.z}
if is_flowing_water(waterpos) then
minetest.set_node(pos, {name="mesecons_hydroturbine:hydro_turbine_on"})
@ -85,7 +85,7 @@ minetest.register_abm({
nodenames = {"mesecons_hydroturbine:hydro_turbine_on"},
interval = 1,
chance = 1,
action = function(pos, node, active_object_count, active_object_count_wider)
action = function(pos)
local waterpos={x=pos.x, y=pos.y+1, z=pos.z}
if not is_flowing_water(waterpos) then
minetest.set_node(pos, {name="mesecons_hydroturbine:hydro_turbine_off"})

View File

@ -1,2 +1,2 @@
name = mesecons_hydroturbine
depends = mesecons
depends = default, mesecons

View File

@ -1,3 +1,3 @@
name = mesecons_insulated
depends = mesecons
depends = default, mesecons
optional_depends = screwdriver

View File

@ -1,2 +1,2 @@
name = mesecons_lamp
depends = mesecons
depends = default, mesecons

View File

@ -1,2 +1,2 @@
name = mesecons_lightstone
depends = mesecons, dye
depends = default, mesecons, dye

View File

@ -43,13 +43,16 @@ local rules = {
------------------
-- These helpers are required to set the port states of the luacontroller
-- Updates the real port states according to the signal change.
-- Returns whether the real port states actually changed.
local function update_real_port_states(pos, rule_name, new_state)
local meta = minetest.get_meta(pos)
if rule_name == nil then
meta:set_int("real_portstates", 1)
return
return true
end
local n = meta:get_int("real_portstates") - 1
local real_portstates = meta:get_int("real_portstates")
local n = real_portstates - 1
local L = {}
for i = 1, 4 do
L[i] = n % 2
@ -60,18 +63,18 @@ local function update_real_port_states(pos, rule_name, new_state)
if rule_name.x == nil then
for _, rname in ipairs(rule_name) do
local port = pos_to_side[rname.x + (2 * rname.z) + 3]
L[port] = (newstate == "on") and 1 or 0
L[port] = (new_state == "on") and 1 or 0
end
else
local port = pos_to_side[rule_name.x + (2 * rule_name.z) + 3]
L[port] = (new_state == "on") and 1 or 0
end
meta:set_int("real_portstates",
1 +
1 * L[1] +
2 * L[2] +
4 * L[3] +
8 * L[4])
local new_portstates = 1 + 1 * L[1] + 2 * L[2] + 4 * L[3] + 8 * L[4]
if new_portstates ~= real_portstates then
meta:set_int("real_portstates", new_portstates)
return true
end
return false
end
@ -172,7 +175,7 @@ local function burn_controller(pos)
minetest.after(0.2, mesecon.receptor_off, pos, mesecon.rules.flat)
end
local function overheat(pos, meta)
local function overheat(pos)
if mesecon.do_overheat(pos) then -- If too hot
burn_controller(pos)
return true
@ -612,9 +615,8 @@ local function run_inner(pos, code, event)
if overheat(pos) then return true, "" end
if ignore_event(event, meta) then return true, "" end
-- Load code & mem from meta
-- Load mem from meta
local mem = load_memory(meta)
local code = meta:get_string("code")
-- 'Last warning' label.
local warning = ""
@ -626,15 +628,17 @@ local function run_inner(pos, code, event)
local itbl = {}
local env = create_environment(pos, mem, event, itbl, send_warning)
local success, msg
-- Create the sandbox and execute code
local f, msg = create_sandbox(code, env)
local f
f, msg = create_sandbox(code, env)
if not f then return false, msg end
-- Start string true sandboxing
local onetruestring = getmetatable("")
-- If a string sandbox is already up yet inconsistent, something is very wrong
assert(onetruestring.__index == string)
onetruestring.__index = env.string
local success, msg = pcall(f)
success, msg = pcall(f)
onetruestring.__index = string
-- End string true sandboxing
if not success then return false, msg end
@ -748,7 +752,7 @@ local selection_box = {
local digiline = {
receptor = {},
effector = {
action = function(pos, node, channel, msg)
action = function(pos, _, channel, msg)
msg = clean_and_weigh_digiline_message(msg)
run(pos, {type = "digiline", channel = channel, msg = msg})
end
@ -766,7 +770,7 @@ local function set_program(pos, code)
return run(pos, {type="program"})
end
local function on_receive_fields(pos, form_name, fields, sender)
local function on_receive_fields(pos, _, fields, sender)
if not fields.program then
return
end
@ -825,8 +829,9 @@ for d = 0, 1 do
effector = {
rules = input_rules[cid],
action_change = function (pos, _, rule_name, new_state)
update_real_port_states(pos, rule_name, new_state)
run(pos, {type=new_state, pin=rule_name})
if update_real_port_states(pos, rule_name, new_state) then
run(pos, {type=new_state, pin=rule_name})
end
end,
},
receptor = {
@ -871,7 +876,7 @@ for d = 0, 1 do
c = c == 1,
d = d == 1,
},
after_dig_node = function (pos, node)
after_dig_node = function (pos)
mesecon.do_cooldown(pos)
mesecon.receptor_off(pos, output_rules)
end,

View File

@ -1,2 +1,2 @@
name = mesecons_luacontroller
depends = mesecons
depends = default, mesecons

View File

@ -2,13 +2,13 @@
minetest.register_craftitem("mesecons_materials:glue", {
image = "mesecons_glue.png",
on_place_on_ground = minetest.craftitem_place_item,
description="Glue",
description="Glue",
})
minetest.register_craftitem("mesecons_materials:fiber", {
image = "mesecons_fiber.png",
on_place_on_ground = minetest.craftitem_place_item,
description="Fiber",
description="Fiber",
})
minetest.register_craft({
@ -29,7 +29,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="Silicon",
})
minetest.register_craft({

View File

@ -1,2 +1,2 @@
name = mesecons_materials
depends = mesecons
depends = default, mesecons

View File

@ -44,8 +44,9 @@ local mesecons = {effector =
{
rules = input_rules,
action_change = function (pos, node, rulename, newstate)
yc.update_real_portstates(pos, node, rulename, newstate)
yc.update(pos)
if yc.update_real_portstates(pos, node, rulename, newstate) then
yc.update(pos)
end
end
}}
if nodename ~= "mesecons_microcontroller:microcontroller0000" then
@ -102,7 +103,7 @@ minetest.register_node(nodename, {
for i=1, EEPROM_SIZE+1 do r=r.."0" end --Generate a string with EEPROM_SIZE*"0"
meta:set_string("eeprom", r)
end,
on_receive_fields = function(pos, formanme, fields, sender)
on_receive_fields = function(pos, _, fields, sender)
local player_name = sender:get_player_name()
if minetest.is_protected(pos, player_name) and
not minetest.check_player_privs(player_name, {protection_bypass=true}) then
@ -225,7 +226,6 @@ yc.parsecode = function(code, pos)
local Lreal = yc.get_real_portstates(pos)
local Lvirtual = yc.get_virtual_portstates(pos)
if Lvirtual == nil then return nil end
local c
local eeprom = meta:get_string("eeprom")
while true do
local command, params
@ -251,9 +251,9 @@ yc.parsecode = function(code, pos)
if not params then return nil end
end
if command == "on" then
L = yc.command_on (params, Lvirtual)
Lvirtual = yc.command_on (params, Lvirtual)
elseif command == "off" then
L = yc.command_off(params, Lvirtual)
Lvirtual = yc.command_off(params, Lvirtual)
elseif command == "print" then
local su = yc.command_print(params, eeprom, yc.merge_portstates(Lreal, Lvirtual))
if su ~= true then return nil end
@ -384,7 +384,6 @@ end
--Commands
yc.command_on = function(params, L)
local rules = {}
for i, port in ipairs(params) do
L = yc.set_portstate (port, true, L)
end
@ -392,7 +391,6 @@ yc.command_on = function(params, L)
end
yc.command_off = function(params, L)
local rules = {}
for i, port in ipairs(params) do
L = yc.set_portstate (port, false, L)
end
@ -405,7 +403,7 @@ yc.command_print = function(params, eeprom, L)
if param:sub(1,1) == '"' and param:sub(#param, #param) == '"' then
s = s..param:sub(2, #param-1)
else
r = yc.command_parsecondition(param, L, eeprom)
local r = yc.command_parsecondition(param, L, eeprom)
if r == "1" or r == "0" then
s = s..r
else return nil end
@ -469,8 +467,8 @@ yc.command_after_execute = function(params)
if yc.parsecode(params.code, params.pos) == nil then
meta:set_string("infotext", "Code in after() not valid!")
else
if code ~= nil then
meta:set_string("infotext", "Working Microcontroller\n"..code)
if params.code ~= nil then
meta:set_string("infotext", "Working Microcontroller\n"..params.code)
else
meta:set_string("infotext", "Working Microcontroller")
end
@ -543,8 +541,8 @@ yc.command_parsecondition = function(cond, L, eeprom)
cond = string.gsub(cond, "!0", "1")
cond = string.gsub(cond, "!1", "0")
local i = 2
local l = string.len(cond)
i = 2
l = string.len(cond)
while i<=l do
local s = cond:sub(i,i)
local b = tonumber(cond:sub(i-1, i-1))
@ -553,8 +551,7 @@ yc.command_parsecondition = function(cond, L, eeprom)
if s == "=" then
if a==nil then return nil end
if b==nil then return nil end
if a == b then buf = "1" end
if a ~= b then buf = "0" end
local buf = a == b and "1" or "0"
cond = string.gsub(cond, b..s..a, buf)
i = 1
l = string.len(cond)
@ -562,8 +559,8 @@ yc.command_parsecondition = function(cond, L, eeprom)
i = i + 1
end
local i = 2
local l = string.len(cond)
i = 2
l = string.len(cond)
while i<=l do
local s = cond:sub(i,i)
local b = tonumber(cond:sub(i-1, i-1))
@ -659,13 +656,16 @@ yc.set_portstate = function(port, state, L)
return L
end
yc.update_real_portstates = function(pos, node, rulename, newstate)
-- Updates the real port states according to the signal change.
-- Returns whether the real port states actually changed.
yc.update_real_portstates = function(pos, _, rulename, newstate)
local meta = minetest.get_meta(pos)
if rulename == nil then
meta:set_int("real_portstates", 1)
return
return true
end
local n = meta:get_int("real_portstates") - 1
local real_portstates = meta:get_int("real_portstates")
local n = real_portstates - 1
local L = {}
for i = 1, 4 do
L[i] = n%2
@ -680,7 +680,12 @@ yc.update_real_portstates = function(pos, node, rulename, newstate)
local port = ({4, 1, nil, 3, 2})[rulename.x+2*rulename.z+3]
L[port] = (newstate == "on") and 1 or 0
end
meta:set_int("real_portstates", 1 + L[1] + 2*L[2] + 4*L[3] + 8*L[4])
local new_portstates = 1 + L[1] + 2*L[2] + 4*L[3] + 8*L[4]
if new_portstates ~= real_portstates then
meta:set_int("real_portstates", new_portstates)
return true
end
return false
end
yc.get_real_portstates = function(pos) -- determine if ports are powered (by itself or from outside)
@ -696,7 +701,7 @@ end
yc.get_virtual_portstates = function(pos) -- portstates according to the name
local name = minetest.get_node(pos).name
local b, a = string.find(name, ":microcontroller")
local _, a = string.find(name, ":microcontroller")
if a == nil then return nil end
a = a + 1

View File

@ -1,2 +1,2 @@
name = mesecons_microcontroller
depends = mesecons
depends = default, mesecons

View File

@ -71,7 +71,7 @@ function mesecon.register_movestone(name, def, is_sticky, is_vertical)
-- ### Step 3: If sticky, pull stack behind ###
if is_sticky then
local backpos = vector.subtract(pos, direction)
success, stack, oldstack = mesecon.mvps_pull_all(backpos, direction, max_pull, owner)
local success, _, oldstack = mesecon.mvps_pull_all(backpos, direction, max_pull, owner)
if success then
mesecon.mvps_move_objects(backpos, vector.multiply(direction, -1), oldstack, -1)
end
@ -94,7 +94,7 @@ function mesecon.register_movestone(name, def, is_sticky, is_vertical)
def.after_place_node = mesecon.mvps_set_owner
def.on_punch = function(pos, node, player)
def.on_punch = function(pos, _, player)
local player_name = player and player.get_player_name and player:get_player_name()
if mesecon.mvps_claim(pos, player_name) then
minetest.get_node_timer(pos):start(timer_interval)
@ -102,7 +102,7 @@ function mesecon.register_movestone(name, def, is_sticky, is_vertical)
end
end
def.on_timer = function(pos, elapsed)
def.on_timer = function(pos)
local sourcepos = mesecon.is_powered(pos)
if not sourcepos then
return

View File

@ -1,2 +1,2 @@
name = mesecons_movestones
depends = mesecons, mesecons_materials, mesecons_mvps
depends = default, mesecons, mesecons_materials, mesecons_mvps

View File

@ -46,11 +46,9 @@ local function on_mvps_move(moved_nodes)
end
end
function mesecon.mvps_process_stack(stack)
-- update mesecons for placed nodes ( has to be done after all nodes have been added )
for _, n in ipairs(stack) do
mesecon.on_placenode(n.pos, minetest.get_node(n.pos))
end
function mesecon.mvps_process_stack()
-- This function is kept for compatibility.
-- It used to call on_placenode on moved nodes, but that is now done automatically.
end
-- tests if the node can be pushed into, e.g. air, water, grass
@ -273,7 +271,6 @@ function mesecon.mvps_push_or_pull(pos, stackdir, movedir, maximum, all_pull_sti
end
function mesecon.mvps_move_objects(pos, dir, nodestack, movefactor)
local objects_to_move = {}
local dir_k
local dir_l
for k, v in pairs(dir) do
@ -331,11 +328,31 @@ end
-- TODO: load blocks instead, as with wires.
mesecon.register_mvps_stopper("ignore")
mesecon.register_mvps_stopper("doors:door_steel_b_1")
mesecon.register_mvps_stopper("doors:door_steel_t_1")
mesecon.register_mvps_stopper("doors:door_steel_b_2")
mesecon.register_mvps_stopper("doors:door_steel_t_2")
mesecon.register_mvps_stopper("default:chest_locked")
-- All of the locked and internal nodes in Minetest Game
for _, name in ipairs({
"default:chest_locked",
"default:chest_locked_open",
"doors:door_steel_b_1", -- old style doors
"doors:door_steel_b_2", --
"doors:door_steel_t_1", --
"doors:door_steel_t_2", --
"doors:door_steel_a", -- new style doors
"doors:door_steel_b", --
"doors:door_steel_c", --
"doors:door_steel_d", --
"doors:hidden",
"doors:trapdoor_steel",
"doors:trapdoor_steel_open",
"xpanes:door_steel_bar_a",
"xpanes:door_steel_bar_b",
"xpanes:door_steel_bar_c",
"xpanes:door_steel_bar_d",
"xpanes:trapdoor_steel_bar",
"xpanes:trapdoor_steel_bar_open",
}) do
mesecon.register_mvps_stopper(name)
end
mesecon.register_on_mvps_move(mesecon.move_hot_nodes)
mesecon.register_on_mvps_move(function(moved_nodes)
for i = 1, #moved_nodes do

View File

@ -1,2 +1,2 @@
name = mesecons_noteblock
depends = mesecons
depends = default, mesecons

View File

@ -93,7 +93,6 @@ local piston_on = function(pos, node)
minetest.swap_node(pos, {param2 = node.param2, name = pistonspec.onname})
minetest.set_node(pusher_pos, {param2 = node.param2, name = pistonspec.pusher})
minetest.sound_play("piston_extend", { pos = pos, max_hear_distance = 20, gain = 0.3 }, true)
mesecon.mvps_process_stack(stack)
mesecon.mvps_move_objects(pusher_pos, dir, oldstack)
end
@ -108,7 +107,7 @@ local function piston_off(pos, node)
local dir = minetest.facedir_to_dir(node.param2)
local pullpos = vector.add(pos, vector.multiply(dir, -2))
local meta = minetest.get_meta(pos)
local success, stack, oldstack = mesecon.mvps_pull_single(pullpos, dir, max_pull, meta:get_string("owner"))
local success, _, oldstack = mesecon.mvps_pull_single(pullpos, dir, max_pull, meta:get_string("owner"))
if success then
mesecon.mvps_move_objects(pullpos, vector.multiply(dir, -1), oldstack, -1)
end
@ -235,7 +234,7 @@ local function piston_rotate_pusher(pos, node, player, mode)
return piston_rotate_on(piston_pos, piston_node, player, mode)
end
local function piston_punch(pos, node, player)
local function piston_punch(pos, _, player)
local player_name = player and player.get_player_name and player:get_player_name()
if mesecon.mvps_claim(pos, player_name) then
minetest.chat_send_player(player_name, "Reclaimed piston")
@ -423,7 +422,7 @@ minetest.register_node("mesecons_pistons:piston_pusher_sticky", {
-- Register pushers as stoppers if they would be seperated from the piston
local function piston_pusher_get_stopper(node, dir, stack, stackid)
local function piston_pusher_get_stopper(node, _, stack, stackid)
if (stack[stackid + 1]
and stack[stackid + 1].node.name == get_pistonspec(node.name, "pusher").onname
and stack[stackid + 1].node.param2 == node.param2)
@ -435,32 +434,12 @@ local function piston_pusher_get_stopper(node, dir, stack, stackid)
return true
end
local function piston_pusher_up_down_get_stopper(node, dir, stack, stackid)
if (stack[stackid + 1]
and stack[stackid + 1].node.name == get_pistonspec(node.name, "pusher").onname)
or (stack[stackid - 1]
and stack[stackid - 1].node.name == get_pistonspec(node.name, "pusher").onname) then
return false
end
return true
end
mesecon.register_mvps_stopper("mesecons_pistons:piston_pusher_normal", piston_pusher_get_stopper)
mesecon.register_mvps_stopper("mesecons_pistons:piston_pusher_sticky", piston_pusher_get_stopper)
-- Register pistons as stoppers if they would be seperated from the stopper
local piston_up_down_get_stopper = function (node, dir, stack, stackid)
if (stack[stackid + 1]
and stack[stackid + 1].node.name == get_pistonspec(node.name, "onname").pusher)
or (stack[stackid - 1]
and stack[stackid - 1].node.name == get_pistonspec(node.name, "onname").pusher) then
return false
end
return true
end
local function piston_get_stopper(node, dir, stack, stackid)
local function piston_get_stopper(node, _, stack, stackid)
local pistonspec = get_pistonspec(node.name, "onname")
local dir = vector.multiply(minetest.facedir_to_dir(node.param2), -1)
local pusherpos = vector.add(stack[stackid].pos, dir)
@ -500,4 +479,4 @@ minetest.register_craft({
-- load legacy code
dofile(minetest.get_modpath("mesecons_pistons")..DIR_DELIM.."legacy.lua")
dofile(minetest.get_modpath("mesecons_pistons").."/legacy.lua")

View File

@ -1,2 +1,2 @@
name = mesecons_pistons
depends = mesecons, mesecons_mvps
depends = default, mesecons, mesecons_mvps

View File

@ -11,7 +11,7 @@ minetest.register_node("mesecons_powerplant:power_plant", {
walkable = false,
groups = {dig_immediate=3, mesecon = 2},
light_source = minetest.LIGHT_MAX-9,
description="Power Plant",
description="Power Plant",
selection_box = {
type = "fixed",
fixed = {-0.3, -0.5, -0.3, 0.3, -0.5+0.7, 0.3},

View File

@ -1,2 +1,2 @@
name = mesecons_powerplant
depends = mesecons
depends = default, mesecons

View File

@ -8,7 +8,7 @@ local pp_box_on = {
fixed = { -7/16, -8/16, -7/16, 7/16, -7.5/16, 7/16 },
}
local function pp_on_timer(pos, elapsed)
local function pp_on_timer(pos)
local node = minetest.get_node(pos)
local basename = minetest.registered_nodes[node.name].pressureplate_basename
@ -17,7 +17,6 @@ local function pp_on_timer(pos, elapsed)
if not basename then return end
local objs = minetest.get_objects_inside_radius(pos, 1)
local two_below = vector.add(pos, vector.new(0, -2, 0))
if objs[1] == nil and node.name == basename .. "_on" then
minetest.set_node(pos, {name = basename .. "_off"})
@ -46,7 +45,6 @@ end
-- sounds: sound table
function mesecon.register_pressure_plate(basename, description, textures_off, textures_on, image_w, image_i, recipe, groups, sounds)
local groups_off, groups_on
if not groups then
groups = {}
end

View File

@ -1,2 +1,2 @@
name = mesecons_pressureplates
depends = mesecons
depends = default, mesecons

View File

@ -59,7 +59,7 @@ minetest.register_node("mesecons_random:ghoststone_active", {
}},
on_construct = function(pos)
-- remove shadow
shadowpos = vector.add(pos, vector.new(0, 1, 0))
local shadowpos = vector.add(pos, vector.new(0, 1, 0))
if (minetest.get_node(shadowpos).name == "air") then
minetest.dig_node(shadowpos)
end

View File

@ -1,2 +1,2 @@
name = mesecons_random
depends = mesecons
depends = default, mesecons

View File

@ -47,7 +47,7 @@ mesecon.register_node("mesecons_receiver:receiver", {
walkable = false,
on_rotate = false,
selection_box = {
type = "fixed",
type = "fixed",
fixed = { -3/16, -8/16, -8/16, 3/16, 3/16, 8/16 }
},
node_box = {
@ -96,7 +96,7 @@ mesecon.register_node("mesecons_receiver:receiver_up", {
walkable = false,
on_rotate = false,
selection_box = {
type = "fixed",
type = "fixed",
fixed = up_rcvboxes
},
node_box = {
@ -141,7 +141,7 @@ mesecon.register_node("mesecons_receiver:receiver_down", {
walkable = false,
on_rotate = false,
selection_box = {
type = "fixed",
type = "fixed",
fixed = down_rcvboxes
},
node_box = {

View File

@ -1,2 +1,2 @@
name = mesecons_receiver
depends = mesecons
depends = default, mesecons

View File

@ -1,2 +1,2 @@
name = mesecons_solarpanel
depends = mesecons, mesecons_materials
depends = default, mesecons, mesecons_materials

View File

@ -8,7 +8,7 @@ minetest.register_node("mesecons_stickyblocks:sticky_block_all", {
tiles = {"mesecons_stickyblocks_sticky.png"},
is_ground_content = false,
groups = {choppy=3, oddly_breakable_by_hand=2},
mvps_sticky = function (pos, node)
mvps_sticky = function (pos)
local connected = {}
for _, r in ipairs(mesecon.rules.alldirs) do
table.insert(connected, vector.add(pos, r))

View File

@ -1,2 +1,2 @@
name = mesecons_stickyblocks
depends = mesecons, mesecons_mvps
depends = default, mesecons, mesecons_mvps

View File

@ -1,2 +1,2 @@
name = mesecons_switch
depends = mesecons
depends = default, mesecons

View File

@ -27,9 +27,13 @@ local torch_get_output_rules = function(node)
return rotate_torch_rules(rules, node.param2)
end
local torch_input_rules_unrotated_horizontal = {vector.new(-2, 0, 0), vector.new(-1, 1, 0)}
local torch_input_rules_unrotated_vertical = {vector.new(-2, 0, 0)}
local torch_get_input_rules = function(node)
local rules = {{x = -2, y = 0, z = 0},
{x = -1, y = 1, z = 0}}
local rules = (node.param2 == 0 or node.param2 == 1)
and torch_input_rules_unrotated_vertical
or torch_input_rules_unrotated_horizontal
return rotate_torch_rules(rules, node.param2)
end

View File

@ -1,2 +1,2 @@
name = mesecons_torch
depends = mesecons
depends = default, mesecons

View File

@ -1,2 +1,2 @@
name = mesecons_walllever
depends = mesecons, mesecons_receiver
depends = default, mesecons, mesecons_receiver

View File

@ -14,7 +14,7 @@ local wire_getconnect = function (from_pos, self_pos)
if minetest.registered_nodes[node.name]
and minetest.registered_nodes[node.name].mesecons then
-- rules of node to possibly connect to
local rules = {}
local rules
if (minetest.registered_nodes[node.name].mesecon_wire) then
rules = mesecon.rules.default
else
@ -73,7 +73,7 @@ local update_on_place_dig = function (pos, node)
end
-- Update nodes around it
local rules = {}
local rules
if minetest.registered_nodes[node.name]
and minetest.registered_nodes[node.name].mesecon_wire then
rules = mesecon.rules.default

View File

@ -1,2 +1,2 @@
name = mesecons_wires
depends = mesecons
depends = default, mesecons