1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 --pcnaming.lua --a.k.a Passive component naming --Allows to assign names to passive components, so they can be called like: --setstate("iamasignal", "green") atlatc.pcnaming={name_map={}} function atlatc.pcnaming.load(stuff) if type(stuff)=="table" then atlatc.pcnaming.name_map=stuff end end function atlatc.pcnaming.save() return atlatc.pcnaming.name_map end function atlatc.pcnaming.resolve_pos(pos, func_name) if type(pos)=="string" then local e = atlatc.pcnaming.name_map[pos] if e then return e end elseif type(pos)=="table" and pos.x and pos.y and pos.z then return pos end error("Invalid position supplied to " .. (func_name or "???")..": " .. dump(pos)) end minetest.register_craftitem("advtrains_luaautomation:pcnaming",{ description = attrans("Passive Component Naming Tool\n\nRight-click to name a passive component."), groups = {cracky=1}, -- key=name, value=rating; rating=1..3. inventory_image = "atlatc_pcnaming.png", wield_image = "atlatc_pcnaming.png", stack_max = 1, on_place = function(itemstack, placer, pointed_thing) local pname = placer:get_player_name() if not pname then return end if not minetest.check_player_privs(pname, {atlatc=true}) then minetest.chat_send_player(pname, "Missing privilege: atlatc") return end if pointed_thing.type=="node" then local pos=pointed_thing.under if advtrains.is_protected(pos, pname) then minetest.record_protection_violation(pos, pname) return end if advtrains.-- mesecon_controller.lua -- Mesecon-interfaceable Operation Panel alternative -- Looks like a Mesecon Luacontroller -- Luacontroller Adapted Code -- From Mesecons mod https://mesecons.net/ -- (c) Jeija and Contributors local S = atltrans local BASENAME = "advtrains_luaautomation:mesecon_controller" local rules = { a = {x = -1, y = 0, z = 0, name="A"}, b = {x = 0, y = 0, z = 1, name="B"}, c = {x = 1, y = 0, z = 0, name="C"}, d = {x = 0, y = 0, z = -1, name="D"}, } local function generate_name(ports) local d = ports.d and 1 or 0 local c = ports.c and 1 or 0 local b = ports.b and 1 or 0 local a = ports.a and 1 or 0 return BASENAME..d..c..b..a end local function set_port(pos, rule, state) if state then mesecon.receptor_on(pos, {rule}) else mesecon.receptor_off(pos, {rule}) end end local function clean_port_states(ports) ports.a = ports.a and true or false ports.b = ports.b and true or false ports.c = ports.c and true or false ports.d = ports.d and true or false end -- Local table for storing which Mesecons off events should be ignored -- Indexed by hex encoded position local ignored_off_events = {} local function set_port_states(pos, ports) local node = advtrains.ndb.get_node(pos) local name = node.name clean_port_states(ports) local vports = minetest.registered_nodes[name].virtual_portstates local new_name = generate_name(ports) if name ~= new_name and vports then -- Problem: -- We need to place the new node first so that when turning -- off some port, it won't stay on because the rules indicate -- there is an onstate output port there. -- When turning the output off then, it will however cause feedback -- so that the luacontroller will receive an "off" event by turning -- its output off. -- Solution / Workaround: -- Remember which output was turned off and ignore next "off" event. local ph=minetest.pos_to_string(pos) local railtbl = atlatc.active.nodes[ph] if not railtbl then return end local ign = railtbl.ignored_off_events or {} if ports.a and not vports.a and not mesecon.is_powered(pos, rules.a) then ign.A = true end if ports.b and not vports.b and not mesecon.is_powered(pos, rules.b) then ign.B = true end if ports.c and not vports.c and not mesecon.is_powered(pos, rules.c) then ign.C = true end if ports.d and not vports.d and not mesecon.is_powered(pos, rules.d) then ign.D = true end railtbl.ignored_off_events = ign advtrains.ndb.swap_node(pos, {name = new_name, param2 = node.param2}) -- Apply mesecon state only if node loaded -- If node is not loaded, mesecon update will occur on next load via on_updated_from_nodedb if advtrains.is_node_loaded(pos) then if ports.a ~= vports.a then set_port(pos, rules.a, ports.a) end if ports.b ~= vports.b then set_port(pos, rules.b, ports.b) end if ports.c ~= vports.c then set_port(pos, rules.c, ports.c) end if ports.d ~= vports.d then set_port(pos, rules.d, ports.d) end end end end local function on_updated_from_nodedb(pos, newnode, oldnode) -- Switch appropriate Mesecon receptors depending on the node change local vports = minetest.registered_nodes[oldnode.name].virtual_portstates local ports = minetest.registered_nodes[newnode.name].virtual_portstates if ports.a ~= vports.a then set_port(pos, rules.a, ports.a) end if ports.b ~= vports.b then set_port(pos, rules.b, ports.b) end if ports.c ~= vports.c then set_port(pos, rules.c, ports.c) end if ports.d ~= vports.d then set_port(pos, rules.d, ports.d) end end local function ignore_offevent(pos, rule) local ph=minetest.pos_to_string(pos) local railtbl = atlatc.active.nodes[ph] if not railtbl then return nil end local ign = railtbl.ignored_off_events if ign and ign[rule.name] then ign[rule.name] = nil return true end return false end local valid_ports = {a=true, b=true, c=true, d=true} local function fire_event(pos, evtdata) local customfct={ set_mesecon_outputs = function(states) assertt(states, "table") set_port_states(pos, states) end, get_mesecon_input = function(port) local portl = string.lower(port) if not valid_ports[portl] then error("get_mesecon_input: Invalid port (expected a,b,c,d)") end if mesecon.is_powered(pos, rules[portl]) then return true end return false end, } atlatc.active.run_in_env(pos, evtdata, customfct, true) end local output_rules = {} local input_rules = {} local node_box = { type = "fixed", fixed = { {-8/16, -8/16, -8/16, 8/16, -7/16, 8/16}, -- Bottom slab {-5/16, -7/16, -5/16, 5/16, -6/16, 5/16}, -- Circuit board {-3/16, -6/16, -3/16, 3/16, -5/16, 3/16}, -- IC } } local selection_box = { type = "fixed", fixed = { -8/16, -8/16, -8/16, 8/16, -5/16, 8/16 }, } for a = 0, 1 do -- 0 = off 1 = on for b = 0, 1 do for c = 0, 1 do for d = 0, 1 do local cid = tostring(d)..tostring(c)..tostring(b)..tostring(a) local node_name = BASENAME..cid local top = "atlatc_luacontroller_top.png" if a == 1 then top = top.."^atlatc_luacontroller_LED_A.png" end if b == 1 then top = top.."^atlatc_luacontroller_LED_B.png" end if c == 1 then top = top.."^atlatc_luacontroller_LED_C.png" end if d == 1 then top = top.."^atlatc_luacontroller_LED_D.png" end local groups if a + b + c + d ~= 0 then groups = {dig_immediate=2, not_in_creative_inventory=1, save_in_at_nodedb=1} else groups = {dig_immediate=2, save_in_at_nodedb=1} end output_rules[cid] = {} input_rules[cid] = {} if a == 1 then table.insert(output_rules[cid], rules.a) end if b == 1 then table.insert(output_rules[cid], rules.b) end if c == 1 then table.insert(output_rules[cid], rules.c) end if d == 1 then table.insert(output_rules[cid], rules.d) end if a == 0 then table.insert( input_rules[cid], rules.a) end if b == 0 then table.insert( input_rules[cid], rules.b) end if c == 0 then table.insert( input_rules[cid], rules.c) end if d == 0 then table.insert( input_rules[cid], rules.d) end local mesecons = { effector = { rules = input_rules[cid], action_change = function (pos, _, rule_name, new_state) if new_state == "off" then -- check for ignored off event on this node if ignore_offevent(pos, rule_name) then return end end --Note: rule_name is not a *name* but actually the full rule table (position + name field) --Event format consistent with Mesecons Luacontroller event atlatc.interrupt.add(0, pos, {type=new_state, [new_state]=true, pin=rule_name}) end, }, receptor = { state = mesecon.state.on, rules = output_rules[cid] }, } minetest.register_node(node_name, { description = S("LuaATC Mesecon Controller"), drawtype = "nodebox", tiles = { top, "atlatc_luacontroller_bottom.png", "atlatc_luacontroller_sides.png", "atlatc_luacontroller_sides.png", "atlatc_luacontroller_sides.png", "atlatc_luacontroller_sides.png" }, inventory_image = top, paramtype = "light", is_ground_content = false, groups = groups, drop = BASENAME.."0000", sunlight_propagates = true, selection_box = selection_box, node_box = node_box, mesecons = mesecons, -- Virtual portstates are the ports that -- the node shows as powered up (light up). virtual_portstates = { a = a == 1, b = b == 1, c = c == 1, d = d == 1, }, after_dig_node = function (pos, node, player) mesecon.receptor_off(pos, output_rules) atlatc.active.after_dig_node(pos, node, player) end, after_place_node = atlatc.active.after_place_node, on_receive_fields = atlatc.active.on_receive_fields, advtrains = { on_updated_from_nodedb = on_updated_from_nodedb }, luaautomation = { fire_event=fire_event }, digiline = { receptor = {}, effector = { action = atlatc.active.on_digiline_receive }, }, }) end end end end