From d80674055b548820c3adfac3de2a914c92588369 Mon Sep 17 00:00:00 2001 From: root Date: Sat, 6 Nov 2021 16:01:45 +0100 Subject: [PATCH] update --- mods/advtrains/advtrains/couple.lua | 2 + mods/advtrains/advtrains/nodedb.lua | 2 +- mods/advtrains/advtrains/trainlogic.lua | 14 +- .../advtrains_luaautomation/active_common.lua | 18 +- .../advtrains_luaautomation/atc_rail.lua | 4 +- .../advtrains_luaautomation/environment.lua | 2 +- .../advtrains_luaautomation/init.lua | 5 + .../mesecon_controller.lua | 259 ++++++++++++++++++ .../operation_panel.lua | 2 +- .../advtrains_luaautomation/pcnaming.lua | 7 +- .../textures/atlatc_luacontroller_LED_A.png | Bin 0 -> 2196 bytes .../textures/atlatc_luacontroller_LED_B.png | Bin 0 -> 2188 bytes .../textures/atlatc_luacontroller_LED_C.png | Bin 0 -> 2191 bytes .../textures/atlatc_luacontroller_LED_D.png | Bin 0 -> 2200 bytes .../textures/atlatc_luacontroller_bottom.png | Bin 0 -> 222 bytes .../textures/atlatc_luacontroller_sides.png | Bin 0 -> 504 bytes .../textures/atlatc_luacontroller_top.png | Bin 0 -> 8440 bytes mods/advtrains/readme.txt | 1 + mods/cloud_items/CODE_OF_CONDUCT.md | 132 +++++++++ mods/doors/init.lua | 5 +- mods/moreblocks/crafting.lua | 2 +- 21 files changed, 436 insertions(+), 19 deletions(-) create mode 100644 mods/advtrains/advtrains_luaautomation/mesecon_controller.lua create mode 100644 mods/advtrains/advtrains_luaautomation/textures/atlatc_luacontroller_LED_A.png create mode 100644 mods/advtrains/advtrains_luaautomation/textures/atlatc_luacontroller_LED_B.png create mode 100644 mods/advtrains/advtrains_luaautomation/textures/atlatc_luacontroller_LED_C.png create mode 100644 mods/advtrains/advtrains_luaautomation/textures/atlatc_luacontroller_LED_D.png create mode 100644 mods/advtrains/advtrains_luaautomation/textures/atlatc_luacontroller_bottom.png create mode 100644 mods/advtrains/advtrains_luaautomation/textures/atlatc_luacontroller_sides.png create mode 100644 mods/advtrains/advtrains_luaautomation/textures/atlatc_luacontroller_top.png create mode 100644 mods/cloud_items/CODE_OF_CONDUCT.md diff --git a/mods/advtrains/advtrains/couple.lua b/mods/advtrains/advtrains/couple.lua index c421f610..3e6c432e 100644 --- a/mods/advtrains/advtrains/couple.lua +++ b/mods/advtrains/advtrains/couple.lua @@ -252,6 +252,8 @@ function advtrains.couple_trains(init_train, invert_init_train, stat_train, stat init_train.index = advtrains.path_get_index_by_offset(init_train, init_train.index, stat_trainlen) advtrains.update_trainpart_properties(init_train.id) + advtrains.update_train_start_and_end(init_train) + advtrains.couple_invalidate(init_train) return true end diff --git a/mods/advtrains/advtrains/nodedb.lua b/mods/advtrains/advtrains/nodedb.lua index 36b5deae..41ac0899 100644 --- a/mods/advtrains/advtrains/nodedb.lua +++ b/mods/advtrains/advtrains/nodedb.lua @@ -302,7 +302,7 @@ ndb.run_lbm = function(pos, node) minetest.swap_node(pos, newnode) local ndef=minetest.registered_nodes[nodeid] if ndef and ndef.advtrains and ndef.advtrains.on_updated_from_nodedb then - ndef.advtrains.on_updated_from_nodedb(pos, newnode) + ndef.advtrains.on_updated_from_nodedb(pos, newnode, node) end return true end diff --git a/mods/advtrains/advtrains/trainlogic.lua b/mods/advtrains/advtrains/trainlogic.lua index 4650f9ec..e7f2fd45 100644 --- a/mods/advtrains/advtrains/trainlogic.lua +++ b/mods/advtrains/advtrains/trainlogic.lua @@ -251,6 +251,11 @@ local callbacks_update, run_callbacks_update = mkcallback("update") local callbacks_create, run_callbacks_create = mkcallback("create") local callbacks_remove, run_callbacks_remove = mkcallback("remove") +-- required to call from couple.lua +function advtrains.update_train_start_and_end(train) + recalc_end_index(train) + run_callbacks_update(train.id, train) +end -- train_ensure_init: responsible for creating a state that we can work on, after one of the following events has happened: -- - the train's path got cleared @@ -643,7 +648,8 @@ function advtrains.train_step_b(id, train, dtime) if target_is_inside then local our_index = advtrains.path_project(otrn, ref_index, id) --atdebug("Backprojected our_index",our_index) - if our_index and our_index <= new_index_curr_tv then + if our_index and our_index <= new_index_curr_tv + and our_index >= train.index then --FIX: If train was already past the collision point in the previous step, there is no collision! Fixes bug with split_at_index -- ON_TRACK COLLISION IS HAPPENING -- the actual collision is handled in train_step_c, so set appropriate signal variables train.ontrack_collision_info = { @@ -1113,6 +1119,7 @@ end function advtrains.split_train_at_index(train, index) -- this function splits a train at index, creating a new train from the back part of the train. + --atdebug("split_train_at_index invoked on",train.id,"index",index) local train_id=train.id if index > #train.trainparts then @@ -1135,6 +1142,7 @@ function advtrains.split_train_at_index(train, index) local p_index=advtrains.path_get_index_by_offset(train, train.index, - data.pos_in_train + wagon.wagon_span) local pos, connid, frac = advtrains.path_getrestore(train, p_index) + --atdebug("new train position p_index",p_index,"pos",pos,"connid",connid,"frac",frac) local tp = {} for k,v in ipairs(train.trainparts) do if k >= index then @@ -1144,12 +1152,14 @@ function advtrains.split_train_at_index(train, index) end advtrains.update_trainpart_properties(train_id) recalc_end_index(train) + --atdebug("old train index",train.index,"end_index",train.end_index) run_callbacks_update(train_id, train) --create subtrain local newtrain_id=advtrains.create_new_train_at(pos, connid, frac, tp) local newtrain=advtrains.trains[newtrain_id] - + --atdebug("new train created with ID",newtrain_id,"index",newtrain.index,"end_index",newtrain.end_index) + newtrain.velocity=train.velocity -- copy various properties from the old to the new train newtrain.door_open = train.door_open diff --git a/mods/advtrains/advtrains_luaautomation/active_common.lua b/mods/advtrains/advtrains_luaautomation/active_common.lua index 9bf83778..50fb2bc0 100644 --- a/mods/advtrains/advtrains_luaautomation/active_common.lua +++ b/mods/advtrains/advtrains_luaautomation/active_common.lua @@ -14,7 +14,7 @@ end function ac.after_place_node(pos, player) local meta=minetest.get_meta(pos) meta:set_string("formspec", ac.getform(pos, meta)) - meta:set_string("infotext", "LuaAutomation component, unconfigured.") + meta:set_string("infotext", "LuaATC component, unconfigured.") local ph=minetest.pos_to_string(pos) --just get first available key! for en,_ in pairs(atlatc.envs) do @@ -48,7 +48,7 @@ function ac.getform(pos, meta_p) .."button[5,0.2;2,1;save;Save]" .."button[7,0.2;3,1;cle;Clear Local Env.]" .."textarea[0.3,1.5;"..atlatc.CODE_FORM_SIZE..";code;Code;"..minetest.formspec_escape(code).."]" - .."label[0,9.7;"..err.."]" + .."label["..atlatc.CODE_FORM_ERRLABELPOS..";"..err.."]" return form end @@ -91,17 +91,17 @@ function ac.on_receive_fields(pos, formname, fields, player) meta:set_string("formspec", ac.getform(pos, meta)) if nodetbl.env then - meta:set_string("infotext", "LuaAutomation component, assigned to environment '"..nodetbl.env.."'") + meta:set_string("infotext", "LuaATC component, assigned to environment '"..nodetbl.env.."'") else - meta:set_string("infotext", "LuaAutomation component, invalid enviroment set!") + meta:set_string("infotext", "LuaATC component, invalid enviroment set!") end end -function ac.run_in_env(pos, evtdata, customfct_p) +function ac.run_in_env(pos, evtdata, customfct_p, ignore_no_code) local ph=minetest.pos_to_string(pos) local nodetbl = ac.nodes[ph] if not nodetbl then - atwarn("LuaAutomation component at",ph,": Data not in memory! Please visit component and click 'Save'!") + atwarn("LuaATC component at",ph,": Data not in memory! Please visit component and click 'Save'!") return end @@ -111,12 +111,14 @@ function ac.run_in_env(pos, evtdata, customfct_p) end if not nodetbl.env or not atlatc.envs[nodetbl.env] then - atwarn("LuaAutomation component at",ph,": Not an existing environment: "..(nodetbl.env or "")) + atwarn("LuaATC component at",ph,": Not an existing environment: "..(nodetbl.env or "")) return false end local env = atlatc.envs[nodetbl.env] if not nodetbl.code or nodetbl.code=="" then - env:log("warning", "LuaAutomation component at",ph,": No code to run! (insert -- to suppress warning)") + if not ignore_no_code then + env:log("warning", "LuaATC component at",ph,": No code to run! (insert -- to suppress warning)") + end return false end diff --git a/mods/advtrains/advtrains_luaautomation/atc_rail.lua b/mods/advtrains/advtrains_luaautomation/atc_rail.lua index b862129a..bfd73579 100644 --- a/mods/advtrains/advtrains_luaautomation/atc_rail.lua +++ b/mods/advtrains/advtrains_luaautomation/atc_rail.lua @@ -14,7 +14,7 @@ function r.fire_event(pos, evtdata, appr_internal) local railtbl = atlatc.active.nodes[ph] if not railtbl then - atwarn("LuaAutomation ATC interface rail at",ph,": Data not in memory! Please visit position and click 'Save'!") + atwarn("LuaATC interface rail at",ph,": Data not in memory! Please visit position and click 'Save'!") return end @@ -188,7 +188,7 @@ advtrains.register_tracks("default", { models_prefix="advtrains_dtrack", models_suffix=".b3d", shared_texture="advtrains_dtrack_shared_atc.png", - description=atltrans("LuaAutomation ATC Rail"), + description=atltrans("LuaATC Rail"), formats={}, get_additional_definiton = function(def, preset, suffix, rotation) return { diff --git a/mods/advtrains/advtrains_luaautomation/environment.lua b/mods/advtrains/advtrains_luaautomation/environment.lua index 63aa68d8..e93b9c3f 100644 --- a/mods/advtrains/advtrains_luaautomation/environment.lua +++ b/mods/advtrains/advtrains_luaautomation/environment.lua @@ -150,7 +150,7 @@ local static_env = { --interrupts are handled per node, position unknown. (same goes for digilines) --however external interrupts can be set here. interrupt_pos = function(parpos, imesg) - local pos=atlatc.pcnaming.resolve_pos(parpos) + local pos=atlatc.pcnaming.resolve_pos(parpos, "interrupt_pos") atlatc.interrupt.add(0, pos, {type="ext_int", ext_int=true, message=imesg}) end, -- sends an atc command to train regardless of where it is in the world diff --git a/mods/advtrains/advtrains_luaautomation/init.lua b/mods/advtrains/advtrains_luaautomation/init.lua index ab625b10..c51aa71e 100644 --- a/mods/advtrains/advtrains_luaautomation/init.lua +++ b/mods/advtrains/advtrains_luaautomation/init.lua @@ -14,6 +14,8 @@ minetest.register_privilege("atlatc", { description = "Player can place and modi --Size of code input forms in X,Y notation. Must be at least 10x10 atlatc.CODE_FORM_SIZE = "15,12" +--Position of Error Label in Code Form +atlatc.CODE_FORM_ERRLABELPOS = "0,12" --assertt helper. error if a variable is not of a type function assertt(var, typ) @@ -31,6 +33,9 @@ dofile(mp.."/interrupt.lua") dofile(mp.."/active_common.lua") dofile(mp.."/atc_rail.lua") dofile(mp.."/operation_panel.lua") +if mesecon then + dofile(mp.."/mesecon_controller.lua") +end dofile(mp.."/pcnaming.lua") dofile(mp.."/chatcmds.lua") diff --git a/mods/advtrains/advtrains_luaautomation/mesecon_controller.lua b/mods/advtrains/advtrains_luaautomation/mesecon_controller.lua new file mode 100644 index 00000000..bffff84e --- /dev/null +++ b/mods/advtrains/advtrains_luaautomation/mesecon_controller.lua @@ -0,0 +1,259 @@ +-- 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 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 = "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 diff --git a/mods/advtrains/advtrains_luaautomation/operation_panel.lua b/mods/advtrains/advtrains_luaautomation/operation_panel.lua index f8b93b56..bfbbda41 100644 --- a/mods/advtrains/advtrains_luaautomation/operation_panel.lua +++ b/mods/advtrains/advtrains_luaautomation/operation_panel.lua @@ -7,7 +7,7 @@ end minetest.register_node("advtrains_luaautomation:oppanel", { drawtype = "normal", tiles={"atlatc_oppanel.png"}, - description = "LuaAutomation operation panel", + description = "LuaATC operation panel", groups = { cracky = 1, save_in_at_nodedb=1, diff --git a/mods/advtrains/advtrains_luaautomation/pcnaming.lua b/mods/advtrains/advtrains_luaautomation/pcnaming.lua index ebb769fb..71f4d9a4 100644 --- a/mods/advtrains/advtrains_luaautomation/pcnaming.lua +++ b/mods/advtrains/advtrains_luaautomation/pcnaming.lua @@ -44,7 +44,12 @@ minetest.register_craftitem("advtrains_luaautomation:pcnaming",{ return end local node = advtrains.ndb.get_node(pos) - if node.name and (minetest.get_item_group(node.name, "advtrains_signal")>0 or advtrains.is_passive(pos)) then + local ndef = minetest.registered_nodes[node.name] + if node.name and ( + minetest.get_item_group(node.name, "advtrains_signal")>0 --is IL signal + or advtrains.is_passive(pos) -- is passive component + or (ndef and ndef.luaautomation) -- is active component + ) then --look if this one already has a name local pn="" for name, npos in pairs(atlatc.pcnaming.name_map) do diff --git a/mods/advtrains/advtrains_luaautomation/textures/atlatc_luacontroller_LED_A.png b/mods/advtrains/advtrains_luaautomation/textures/atlatc_luacontroller_LED_A.png new file mode 100644 index 0000000000000000000000000000000000000000..c6182cc51b0edbe6554df4841dd285e107748ae7 GIT binary patch literal 2196 zcmb_cdrVVT7(Z=M3IhucD82?A4n#ocG~iYQ6{;|$A{re?px^`?mWMcoNFO4PjG`ei z6BiU8Q*pyt(UylmDPX0M&QY?_9mM zQM@tPPVtVw^h+O18JN2H>~QmmbX$W7w(fLW6XoWM3AXN9>4(Ygl~gMA>pfqsUAvY> zqeVqUMMp;`B_(BLW!2Qwh(w~gy1IsjhP!v~HZ?UhH#dvL;+B>ciA2)c+S=CE*52NJ z@7_JBRNB$e(b?JA-2;>=&^G{7gJ5tNs9%8Lm*9mKywm|L1au<+8U-U`V00Xe8NfIU z3`PJ?1EUE{qrij$^sOof)NgJ7GZ`^s^8RwoNvj)JT*8h-F?M15{~~{ry(_`2lc0;dDe6WB-r)9UW5tboj&3H}s0@WJk5Z+R;9=t5Rnbp*+OUBFFTL ziz1VafpxS-8qGLV!T$}akZPqK(vz3jCQ+h51{uHYwN@48Ar&L6$#p`NAv%+NaRSy& z`iP~=A^?6PAOf5#u;2kZfd6ptTkMhGb)z7U?Xx|9_W#+J?%PQ+Ya)fd->>oK|2pW` z^!Z_K(m=Qjd0@nij!OqKE@tQXI_xX7mv{o)T>tOI0ao1^a0pXpDk_@TZIRwr|N<@@&d#n=~df zMmWBp6fkh+Aewo=c`MMtdKL!_@6KjkmBC}I4f(yMs1!(Los5|Hm;T~*osx5?UZo%9 zn<$~YPksMS^--k=fSk5~SqYfMlBXv!MJal;yrkB&QQ6u^ui&CTcMmJ-V3>s#nKtRr zgW3S$P`X8i^}Hx0c?(A}>+OR`ind1?8?c1#!JZ=_?DBR?iegz#z@g&v%um>sU887> z>4g)=$t4G=W0tiVdv7NVVkv};r?EoH#d%3Ln@tNdh#=EGNTn#`T>H_f!)dDQ{^rD2 zmN``^klaWeJ&KKm6R})Zi2Rhe1ys$?|6wv<1?9y-a&2b=axg_pIAaz^_HkMvmAYc+P;}1xlAfdw`o&Q8S1BKzxecNal-18`g{->jH!1_EAnkCAE+)9aGirz-*h@g z-^aa#w0eDV7B#agkZJd`9x1w z5Z7r@NzdgKXms}z(pjv5&6F^aY2!|bmuo2Maky997eANH2cA51KhV;RJbyIrh0%ll zxJnKqFq+O;VqM@EAJ5sbHXWZOMvEzlj_bRDy6;x>u($QwlH|B;J)51gu WxZQF)|0IC}FbStKLT_$n=Klj^Xa5`k literal 0 HcmV?d00001 diff --git a/mods/advtrains/advtrains_luaautomation/textures/atlatc_luacontroller_LED_B.png b/mods/advtrains/advtrains_luaautomation/textures/atlatc_luacontroller_LED_B.png new file mode 100644 index 0000000000000000000000000000000000000000..04c2da07ce7a35638147c80031008c182d977b13 GIT binary patch literal 2188 zcmb_cdrXs86u&KlflDMD$`@@xwg7=q$NtrMgQTBsFTEuW>Y@7u-7!z%l0Cnxujd(Z249zVxK z?{r$|wh#c|6d4f~3jiJ-@xZ|jZn8hT{{jGqkJ+_1eC^t`>m!KkBRn@mcy9dCb7RzM zA4t1a`+Nm?jW6VA$X>owFW(riO_1Qa+iO#-7YPzv_jr>b?e+Ha^V|IO$Nv8Qfq{Xs zv9WP+aY;!@X=!P-wY8ToUlxf(4Gj&Ajg8IC%`Gi0VzF2vkw~S|*4Eaxwls-~1!HCSb>f>6r(pZzRxIRxd4^w{VonwB#7Pd*oc*(URV4#u1@M5fV9x_6sbj2ZJ0;#mdt2S8mA@ zatvL+IBx@B3BZQ{2Y~Yggshp1;FCMOq_T|dAj9Mf@Nd6QeSWzlq%oLtbJD4UPI1x| z=jn7>Ba?;s9g#R{lKbkh(vIPP!vljWr8NNehVto4BJqM;uGXRX-HkMilAS7L^Lsr?V`2GF6WePr8^Js^nZvs)tfeM^`9QF!tdA z_R~ePGFIqdquAKBffT`qG-8zN#dM0ZF1&gGNBb-J39A9;Jo&wVdDNZ#U zXI>WG52is7u|kf!1J|xu48&(CO)@ixN9+AaOOp zmdrf&e2ITn0`8q)+@`_?oJ>C0vR-X88!rlJzagChJ5f-u^pZwXD&!R*QE~EK`<`y* z!x?;)A^fWx zmuG_l!tIgXgwt}lghXZz2QXGCv&sBt4D5!RzQ#jg{2?n>%S;9m{2PX+FH=>9SeOzH zix<*D8$^s)1&{bp(w4bOiReB=m{`g^whNng1F+wlo8OrxjS0r}bO+y7cb^qj_lj!x z_LcI|3U1)m)B*NVr3y7Qb!hk$;&T_M4P4CY6p68O|AED^YrzBQE-!WtJ0Cb>7=w;X zpgfs5Z5VraX;uot_R4#!59tLkfFU_K;f#S*((9&>Ugu$;gWJhjs`PrhcwP^ctbkE5 z#Q571N!om6SZ4=RDEd#{2<$*+i@8Z_?AIcS+%e)cX8hfFOxzm9uz2^_(_xq!=d}Z- zeZ|`}WTh)?Zj%aqnNm{Yeo`=~!2YZXpqu)H)p|{@?4?YIE>p(mE7tUoWZPj)>fRa= zK)M>(=(NcXVkd3f9nmO3xAlnVym5@5quI|V9Y1jQtd^}t9~2_%o+*a79O(!1dY|PX zK6ip)sjC{Hv+d_r?JM}LA(aOKtsAYNx}w6=%Xbq|?^rnN)ZMTa+`lPAd@?P@=B)60 zl8MahiOkcX!dRX1e&Y{yV$__Yw=bJ9&L4@Pb)_6j~mhq7LlrcqAr#uyQ z7qns26P9y3NrgPV;KY0xC4@AKX*G&`+&qJ)j$?WM_X6<>+URFB08(UlbXfI{#2^0! DLhd9v literal 0 HcmV?d00001 diff --git a/mods/advtrains/advtrains_luaautomation/textures/atlatc_luacontroller_LED_C.png b/mods/advtrains/advtrains_luaautomation/textures/atlatc_luacontroller_LED_C.png new file mode 100644 index 0000000000000000000000000000000000000000..01f6ae48e9b0f279b03dd996ca74d503fe079ee3 GIT binary patch literal 2191 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 VSVZJ&y(Iv)q_~vW=AAhe{{oQ%0tf&A literal 0 HcmV?d00001 diff --git a/mods/advtrains/advtrains_luaautomation/textures/atlatc_luacontroller_bottom.png b/mods/advtrains/advtrains_luaautomation/textures/atlatc_luacontroller_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..7ae955c128f07634750247dc5337d322153ba888 GIT binary patch literal 222 zcmeAS@N?(olHy`uVBq!ia0vp^0wBx*Bp9q_EZ7UAmU_B4hDb=V9_%b+HsoP;_;!DS z?ng$4z;u73mzuke-PQ8n!d`5}%aHWUBi;4M#^{*4!Zo(SpSJLB49Vg++t%sM`Q}?` z)6b1XtIm5b)k{D4&SHDSACJ0s5;khik(U}6y(cuh(s$F(mDuce?-g51hD68h{T*UI zE^{P@TuWN?uC~i)*D8zed#cSexX+i*Z(TlnPlM~R1y<&B{0({D*2=BxTmY1%Q~loCICRUS#1CS literal 0 HcmV?d00001 diff --git a/mods/advtrains/advtrains_luaautomation/textures/atlatc_luacontroller_sides.png b/mods/advtrains/advtrains_luaautomation/textures/atlatc_luacontroller_sides.png new file mode 100644 index 0000000000000000000000000000000000000000..40f4b60c92ff7fb625c425c7f83f37a4acc4c4ee GIT binary patch literal 504 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 Lj5Q0??F0V{`@{QH literal 0 HcmV?d00001 diff --git a/mods/advtrains/readme.txt b/mods/advtrains/readme.txt index 05a5d5e5..f341033c 100644 --- a/mods/advtrains/readme.txt +++ b/mods/advtrains/readme.txt @@ -28,6 +28,7 @@ Steam engine / wagon texture: mbb Detailed Steam engine : mbb / Krokoschlange(animation) Industrial engine/wagons : mbb Inventory images : mbb +Node texture for LuaATC controller: Jeija (from Mesecons) Mod Description : hajo Sounds: advtrains_crossing_bell : Codesound diff --git a/mods/cloud_items/CODE_OF_CONDUCT.md b/mods/cloud_items/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..a073e119 --- /dev/null +++ b/mods/cloud_items/CODE_OF_CONDUCT.md @@ -0,0 +1,132 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of + any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, + without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +halfpacho@gmail.com. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/mods/doors/init.lua b/mods/doors/init.lua index 96e8e7e2..7d5e38bd 100644 --- a/mods/doors/init.lua +++ b/mods/doors/init.lua @@ -345,6 +345,7 @@ function doors.register(name, def) return itemstack end + local doorname = itemstack:get_name() local node = minetest.get_node(pointed_thing.under) local pdef = minetest.registered_nodes[node.name] @@ -402,10 +403,10 @@ function doors.register(name, def) if minetest.get_item_group(minetest.get_node(aside).name, "door") == 1 then state = state + 2 - minetest.set_node(pos, {name = name .. "_b", param2 = dir}) + minetest.set_node(pos, {name = doorname .. "_b", param2 = dir}) minetest.set_node(above, {name = "doors:hidden", param2 = (dir + 3) % 4}) else - minetest.set_node(pos, {name = name .. "_a", param2 = dir}) + minetest.set_node(pos, {name = doorname .. "_a", param2 = dir}) minetest.set_node(above, {name = "doors:hidden", param2 = dir}) end diff --git a/mods/moreblocks/crafting.lua b/mods/moreblocks/crafting.lua index 34d1dc04..0161a2ed 100644 --- a/mods/moreblocks/crafting.lua +++ b/mods/moreblocks/crafting.lua @@ -554,7 +554,7 @@ minetest.register_craft({ }) minetest.register_craft({ - output = "moreblocks:cactuschecker 4", + output = "moreblocks:cactus_checker 4", recipe = { {"default:stone", "default:cactus"}, {"default:cactus", "default:stone"},