voltage for redstone

- wires has voltage from 0 to 15 (lower by one for every step)
- wiring-rules
- comparator read content from chest, hopper, jukebox, group "comparator_signal" (cauldrons, cake, ...)
This commit is contained in:
Henry Behrendt 2021-09-16 08:29:00 +02:00
parent 1a5339e907
commit 80a9df4845
13 changed files with 942 additions and 175 deletions

View File

@ -29,9 +29,49 @@ end
local function comparator_turnon(params)
local rules = comparator_get_output_rules(params.node)
mesecon.receptor_on(params.pos, rules)
if params.lower_voltage then
-- nur den eigenen Strom rausnehmen
-- output verfolgen, solange er kleiner wird und auf 0 setzen
-- Call turnoff on all linking positions
for _, rule in ipairs(mesecon.flattenrules(rules)) do
local np = vector.add(params.pos, rule)
local rulenames = mesecon.rules_link_rule_all(params.pos, rule)
for _, rulename in ipairs(rulenames) do
comparator_removevoltage(np, rulename, params.old_voltage)
end
end
end
mesecon.receptor_on(params.pos, rules, params.voltage)
end
function comparator_removevoltage(pos, link, voltage)
local cur_vol = voltage+1
local frontiers = {{pos = pos, link = link, voltage=cur_vol}}
local depth = 1
while frontiers[1] do
local f = table.remove(frontiers, 1)
local node = mesecon.get_node_force(f.pos)
if node and mesecon.is_conductor_on(node, f.link) then
local meta = minetest.get_meta(f.pos)
local tmp_vol = (meta:get_string("mesecon_voltage")~="" and meta:get_int("mesecon_voltage") or 15)
if tmp_vol<f.voltage and tmp_vol>=1 then
--solange spannung niedriger wird
cur_vol = tmp_vol
meta:set_int("mesecon_voltage", 0)
local rules = mesecon.conductor_get_rules(node)
for _, r in pairs(mesecon.rule2meta(f.link, rules)) do
local np = vector.add(f.pos, r)
-- check neighbors
for _, l in pairs(mesecon.rules_link_rule_all(f.pos, r)) do
table.insert(frontiers, {pos = np, link = l, voltage=cur_vol})
end
end
end
end
depth = depth + 1
end
end
local function comparator_turnoff(params)
local rules = comparator_get_output_rules(params.node)
@ -41,10 +81,10 @@ end
-- Functions that set the correct node type an schedule a turnon/off
local function comparator_activate(pos, node)
local function comparator_activate(pos, node, voltage, lower_voltage, old_voltage)
local def = minetest.registered_nodes[node.name]
minetest.swap_node(pos, { name = def.comparator_onstate, param2 = node.param2 })
minetest.after(0.1, comparator_turnon , {pos = pos, node = node})
minetest.after(0.1, comparator_turnon , {pos = pos, node = node, voltage = voltage, lower_voltage=lower_voltage, old_voltage=old_voltage})
end
@ -56,73 +96,180 @@ end
-- weather pos has an inventory that contains at least one item
local function container_inventory_nonempty(pos)
local function container_inventory_nonempty(pos, rule)
-- https://minecraft.fandom.com/wiki/Redstone_Comparator#Measure_block_state
-- signal strength = floor(1 + ((sum of all slots' fullnesses) / (number of slots in container)) × 14)
-- fullness of a slot = number of items in slot / max stack size for this type of item
local invnode = minetest.get_node(pos)
local invnodedef = minetest.registered_nodes[invnode.name]
-- Ignore stale nodes
if not invnodedef then return false end
if not invnodedef then return 0, false end
-- Only accept containers. When a container is dug, it's inventory
-- seems to stay. and we don't want to accept the inventory of an air
-- block
if not invnodedef.groups.container then return false end
local inv = minetest.get_inventory({type="node", pos=pos})
if not inv then return false end
for listname, _ in pairs(inv:get_lists()) do
if not inv:is_empty(listname) then return true end
if not invnodedef.groups.container then
if minetest.get_item_group(invnode.name, "opaque") == 1 and rule then
--found opaque block -> check next block
local backback_pos = vector.add(pos, rule)
local bb_voltage, _ = container_inventory_nonempty(backback_pos, nil)
return bb_voltage, true
else
return 0, false
end
end
return false
local inv = minetest.get_inventory({type="node", pos=pos})
if not inv then return 0, false end
if invnode.name=="mcl_jukebox:jukebox" then
if not inv:is_empty("main") then
-- Jukebox contains a disc: Stop music and remove disc
local record = inv:get_stack("main", 1)
if mcl_jukebox.registered_records[record:get_name()] then
local ident = mcl_jukebox.registered_records[record:get_name()][3]
local t = {
id_13 = 1,
id_cat = 2,
id_blocks = 3,
id_chirp = 4,
id_far = 5,
id_mall = 6,
id_mellohi = 7,
id_stal = 8,
id_strad = 9,
id_ward = 10,
id_11 = 11,
id_wait = 12,
id_Pigstep = 13,
}
local vol = t["id_"..ident]
if vol then return vol, false end
end
end
else
local item_count = 0
local inv_space = 0
for listname, _ in pairs(inv:get_lists()) do
local stack = inv:get_stack(listname, 1)
local st_size = inv:get_size(listname)
inv_space = inv_space + (64 * st_size)
for i = 1,st_size do
local stack = inv:get_stack(listname, i)
item_count = item_count + (stack:get_count() * 64 / stack:get_stack_max())
end
--if not inv:is_empty(listname) then return true, 15 end
end
if item_count>0 then
local voltage = math.floor(1 + (item_count/inv_space*14))
return voltage, false
end
end
return 0, false
end
-- weather pos has an constant signal output for the comparator
local function static_signal_output(pos)
local node = minetest.get_node(pos)
local g = minetest.get_item_group(node.name, "comparator_signal")
return g > 0
return g
end
-- whether the comparator should be on according to its inputs
local function comparator_desired_on(pos, node)
local my_input_rules = comparator_get_input_rules(node);
local back_rule = my_input_rules[1]
local state
local voltage = 0
if back_rule then
local back_pos = vector.add(pos, back_rule)
state = mesecon.is_power_on(back_pos) or container_inventory_nonempty(back_pos) or static_signal_output(back_pos)
local _, _, vo_back = mesecon.is_powered(pos, back_rule)
local vo_coin, spread = container_inventory_nonempty(back_pos, back_rule)
local vo_sso = static_signal_output(back_pos)
if vo_coin>=1 and spread and vo_back<15 then
--container through opaque block and block is powerd less than 15 -> ignore powered block
vo_back=0
end
voltage = math.max(vo_back, vo_coin, vo_sso)
end
-- if back input if off, we don't need to check side inputs
if not state then return false end
-- if back input is off, we don't need to check side inputs
if voltage<1 then return false, 0 end
-- without power levels, side inputs have no influence on output in compare
-- mode
local mode = minetest.registered_nodes[node.name].comparator_mode
if mode == "comp" then return state end
-- subtract mode, subtract max(side_inputs) from back input
local side_state = false
local side_voltage = 0
for ri = 2,3 do
if my_input_rules[ri] then
side_state = mesecon.is_power_on(vector.add(pos, my_input_rules[ri]))
for _, l in pairs(mesecon.rules_link_rule_all_inverted(pos, my_input_rules[ri])) do
local _, s_voltage = mesecon.is_power_on(vector.add(pos, my_input_rules[ri]))
side_voltage = math.max(side_voltage, s_voltage)
end
end
if side_state then break end
end
-- state is known to be true
return not side_state
local mode = minetest.registered_nodes[node.name].comparator_mode
if mode == "comp" then
-- Comparators in comparison mode
if side_voltage > voltage then
return false, 0
else
return true, voltage
end
end
-- comparator in subtraction mode
voltage = math.max(voltage-side_voltage, 0)
if voltage>0 then
return true, voltage
else
return false, 0
end
end
--[[
Compare signal strength
Comparators in comparison mode.
A redstone comparator in comparison mode (front torch down and unpowered) compares its rear input to its two side inputs.
If either side input is greater than the rear input, the comparator output turns off. If neither side input is greater than
the rear input, the comparator outputs the same signal strength as its rear input.
The formula for calculating the output signal strength is as follows:
output = rear × [left rear AND right rear]
Subtract signal strength
A redstone comparator in subtraction mode (front torch up and powered) subtracts the signal strength of the higher side input from the signal strength of the rear input.
output = max(rear max(left, right), 0)
For example: if the signal strength is 6 at the left input, 7 at the right input and 4 at the rear, the output signal has a strength of max(4 max(6, 7), 0) = max(47, 0) = max(3, 0) = 0.
If the signal strength is 9 at the rear, 2 at the right input and 5 at the left input, the output signal has a strength of max(9 max(2, 5), 0) = max(95, 0) = 4.
--]]
-- update comparator state, if needed
local function update_self(pos, node)
node = node or minetest.get_node(pos)
local old_state = mesecon.is_receptor_on(node.name)
local new_state = comparator_desired_on(pos, node)
if new_state ~= old_state then
local meta = minetest.get_meta(pos)
local old_voltage = old_state and (meta:get_string("mesecon_voltage")~="" and meta:get_int("mesecon_voltage") or 15) or 0
local new_state, new_voltage = comparator_desired_on(pos, node)
if (new_state ~= old_state) or (old_voltage~=new_voltage) then
if old_voltage~=new_voltage then meta:set_int("mesecon_voltage", new_voltage) end
if new_state then
comparator_activate(pos, node)
comparator_activate(pos, node, new_voltage, (new_voltage<old_voltage), old_voltage)
else
comparator_deactivate(pos, node)
end
@ -272,6 +419,7 @@ for _, mode in pairs{"comp", "sub"} do
receptor = {
state = state,
rules = comparator_get_output_rules,
opaquespread = true,
},
effector = {
rules = comparator_get_input_rules,
@ -281,6 +429,12 @@ for _, mode in pairs{"comp", "sub"} do
on_rotate = on_rotate,
}
if state == mesecon.state.on then
nodedef.on_destruct = function(pos, oldnode)
local node = minetest.get_node(pos)
mesecon.on_dignode(pos, node)
end
end
if mode == "comp" and state == mesecon.state.off then
-- This is the prototype
nodedef._doc_items_create_entry = true
@ -328,7 +482,7 @@ minetest.register_abm({
"mcl_comparators:comparator_off_comp",
"mcl_comparators:comparator_off_sub",
},
neighbors = {"group:container", "group:comparator_signal"},
neighbors = {"group:container", "group:comparator_signal", "group:opaque", "mcl_jukebox:jukebox"},
interval = 1,
chance = 1,
action = update_self,

View File

@ -1,3 +1,3 @@
name = mcl_comparators
depends = mcl_wip, mesecons, mcl_sounds
depends = mcl_wip, mesecons, mcl_sounds, mcl_jukebox
optional_depends = doc, screwdriver

View File

@ -1,3 +1,10 @@
--function mesecon.queue:add_function(name, func)
--function mesecon.queue:add_action(pos, func, params, time, overwritecheck, priority)
--function mesecon.queue:execute(action)
local table = table
mesecon.queue.actions={} -- contains all ActionQueue actions

View File

@ -5,7 +5,7 @@
-- | | |___ ____| |___ |____ |____| | \| ____|
-- by Jeija, Uberi (Temperest), sfan5, VanessaE, Hawk777 and contributors
--
--
-- extended by socke2398
--
-- This mod adds mesecons[=minecraft redstone] and different receptors/effectors to minetest.
-- See the documentation on the forum for additional information, especially about crafting
@ -69,30 +69,35 @@ dofile(minetest.get_modpath("mesecons").."/internal.lua");
-- API
-- these are the only functions you need to remember
mesecon.queue:add_function("receptor_on", function (pos, rules)
mesecon.queue:add_function("receptor_on", function (pos, rules, voltage, opaquespread)
mesecon.vm_begin()
rules = rules or mesecon.rules.default
local node = mesecon.get_node_force(pos)
local os=opaquespread or mesecon.is_receptor_opaquespread(node.name)
-- Call turnon on all linking positions
for _, rule in pairs(mesecon.flattenrules(rules)) do
local np = vector.add(pos, rule)
local rulenames = mesecon.rules_link_rule_all(pos, rule)
for _, rulename in pairs(rulenames) do
mesecon.turnon(np, rulename)
if os then rulename.opaquespread=os end
mesecon.turnon(np, rulename, voltage)
end
end
mesecon.vm_commit()
end)
function mesecon.receptor_on(pos, rules)
mesecon.queue:add_action(pos, "receptor_on", {rules}, nil, rules)
function mesecon.receptor_on(pos, rules, voltage, opaquespread)
mesecon.queue:add_action(pos, "receptor_on", {rules, voltage, opaquespread}, nil, rules)
end
mesecon.queue:add_function("receptor_off", function (pos, rules)
mesecon.queue:add_function("receptor_off", function (pos, rules, opaquespread)
rules = rules or mesecon.rules.default
local node = mesecon.get_node_force(pos)
local os=opaquespread or mesecon.is_receptor_opaquespread(node.name)
-- Call turnoff on all linking positions
for _, rule in ipairs(mesecon.flattenrules(rules)) do
local np = vector.add(pos, rule)
@ -104,17 +109,51 @@ mesecon.queue:add_function("receptor_off", function (pos, rules)
-- 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
-- returns true, an onstate receptor was found, abort voxelmanip transaction.
if (mesecon.turnoff(np, rulename)) then
if os then rulename.opaquespread=os end
local res, rec_on = mesecon.turnoff(np, rulename)
if (res) then
mesecon.vm_commit()
else
mesecon.vm_abort()
for _, rec in pairs(rec_on) do
--rules??? -> mesecon.receptor_get_rules(node)
local node = mesecon.get_node_force(rec)
local meta = minetest.get_meta(rec)
local voltage = meta:get_string("mesecon_voltage")~="" and meta:get_int("mesecon_voltage") or 15
mesecon.receptor_on(rec, mesecon.receptor_get_rules(node), voltage)
end
end
end
end
end)
function mesecon.receptor_off(pos, rules)
mesecon.queue:add_action(pos, "receptor_off", {rules}, nil, rules)
function mesecon.receptor_off(pos, rules, opaquespread)
mesecon.queue:add_action(pos, "receptor_off", {rules, opaquespread}, nil, rules)
end
mesecon.queue:add_function("conductor_off", function (pos, rules)
rules = rules or mesecon.rules.default
local node = mesecon.get_node_force(pos)
for _, rule in ipairs(mesecon.flattenrules(rules)) do
mesecon.vm_begin()
mesecon.changesignal(pos, node, rule, mesecon.state.off, 2)
local res, rec_on = mesecon.turnoff(pos, rule)
if (res) then
mesecon.vm_commit()
else
mesecon.vm_abort()
for _, rec in pairs(rec_on) do
local node = mesecon.get_node_force(rec)
local meta = minetest.get_meta(rec)
local voltage = meta:get_string("mesecon_voltage")~="" and meta:get_int("mesecon_voltage") or 15
mesecon.receptor_on(rec, mesecon.receptor_get_rules(node), voltage)
end
end
end
end)
function mesecon.conductor_off(pos, rules)
mesecon.queue:add_action(pos, "conductor_off", {rules}, nil, rules)
end
--Services like turnoff receptor on dignode and so on

View File

@ -47,6 +47,12 @@
-- mesecon.rotate_rules_down(rules)
-- These functions return rules that have been rotated in the specific direction
-- mesecon.turnon(pos, link, voltage)
-- mesecon.turnoff(pos, link)
local rs_tick = 0.05
local equals = vector.equals
local get_node_force = mesecon.get_node_force
local invertRule = mesecon.invertRule
@ -149,6 +155,12 @@ local function receptor_get_rules(node)
end
mesecon.receptor_get_rules = receptor_get_rules
function mesecon.is_receptor_opaquespread(nodename)
local receptor = mesecon.get_receptor(nodename)
return receptor and receptor.opaquespread
end
-- Effectors
-- Nodes that can be powered by mesecons
function mesecon.is_effector_on(nodename)
@ -204,14 +216,14 @@ mesecon.queue:add_function("activate", function (pos, rulename)
end
end)
function mesecon.activate(pos, node, rulename, depth)
function mesecon.activate(pos, node, rulename, depth, time)
if rulename == nil then
for _,rule in pairs(mesecon.effector_get_rules(node)) do
mesecon.activate(pos, node, rule, depth + 1)
mesecon.activate(pos, node, rule, depth + 1, time)
end
return
end
mesecon.queue:add_action(pos, "activate", {rulename}, nil, rulename, 1 / depth)
mesecon.queue:add_action(pos, "activate", {rulename}, time, rulename, 1 / depth)
end
@ -227,14 +239,14 @@ mesecon.queue:add_function("deactivate", function (pos, rulename)
end
end)
function mesecon.deactivate(pos, node, rulename, depth)
function mesecon.deactivate(pos, node, rulename, depth, time)
if rulename == nil then
for _,rule in pairs(mesecon.effector_get_rules(node)) do
mesecon.deactivate(pos, node, rule, depth + 1)
mesecon.deactivate(pos, node, rule, depth + 1, time)
end
return
end
mesecon.queue:add_action(pos, "deactivate", {rulename}, nil, rulename, 1 / depth)
mesecon.queue:add_action(pos, "deactivate", {rulename}, time, rulename, 1 / depth)
end
@ -250,10 +262,10 @@ mesecon.queue:add_function("change", function (pos, rulename, changetype)
end
end)
function mesecon.changesignal(pos, node, rulename, newstate, depth)
function mesecon.changesignal(pos, node, rulename, newstate, depth, time)
if rulename == nil then
for _,rule in pairs(mesecon.effector_get_rules(node)) do
mesecon.changesignal(pos, node, rule, newstate, depth + 1)
mesecon.changesignal(pos, node, rule, newstate, depth + 1, time)
end
return
end
@ -261,7 +273,7 @@ function mesecon.changesignal(pos, node, rulename, newstate, depth)
-- Include "change" in overwritecheck so that it cannot be overwritten
-- by "active" / "deactivate" that will be called upon the node at the same time.
local overwritecheck = {"change", rulename}
mesecon.queue:add_action(pos, "change", {rulename, newstate}, nil, overwritecheck, 1 / depth)
mesecon.queue:add_action(pos, "change", {rulename, newstate}, time, overwritecheck, 1 / depth)
end
-- Conductors
@ -283,7 +295,6 @@ function mesecon.is_conductor_on(node, rulename)
return mesecon.get_bit(binstate, bit)
end
end
return false
end
@ -366,9 +377,11 @@ end
function mesecon.is_power_on(pos, rulename)
local node = get_node_force(pos)
if node and (mesecon.is_conductor_on(node, rulename) or is_receptor_on(node.name)) then
return true
local meta = minetest.get_meta(pos)
voltage = meta:get_string("mesecon_voltage")~="" and meta:get_int("mesecon_voltage") or 15
return true, voltage
end
return false
return false, 0
end
function mesecon.is_power_off(pos, rulename)
@ -379,35 +392,83 @@ function mesecon.is_power_off(pos, rulename)
return false
end
-- Turn off an equipotential section starting at `pos`, which outputs in the direction of `link`.
-- Turn on 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
-- looked at, activating / changing all effectors along the way.
function mesecon.turnon(pos, link)
local frontiers = {{pos = pos, link = link}}
function mesecon.turnon(pos, link, voltage)
voltage = voltage or 15
local pn = get_node_force(pos)
local frontiers = {{pos = pos, link = link, voltage = voltage}}
local depth = 1
while frontiers[1] do
local f = table.remove(frontiers, 1)
local node = get_node_force(f.pos)
if node and mesecon.is_conductor_off(node, f.link) then
local rules = mesecon.conductor_get_rules(node)
-- Call turnon on neighbors
for _, r in pairs(mesecon.rule2meta(f.link, rules)) do
local np = vector.add(f.pos, r)
for _, l in pairs(mesecon.rules_link_rule_all(f.pos, r)) do
insert(frontiers, {pos = np, link = l})
if node and mesecon.is_conductor(node.name) and (f.link.spread==nil and true or f.link.spread) then
--neue spannung berechnen
local meta = minetest.get_meta(f.pos)
local old_v = (mesecon.is_conductor_off(node, f.link) and 0 or meta:get_int("mesecon_voltage"))
local v = math.max(f.voltage, old_v)
--wenn spannung geändert
--wenn gleiche spannung, aber muss ausgeschalten werden
if v~=old_v or (v<1 and mesecon.is_conductor_on(node, f.link)) then
if v>=1 or (v<1 and mesecon.is_conductor_on(node, f.link)) then
-- Call turnon on neighbors
local rules = mesecon.conductor_get_rules(node)
for _, r in pairs(mesecon.rule2meta(f.link, rules)) do
local np = vector.add(f.pos, r)
for _, l in pairs(mesecon.rules_link_rule_all(f.pos, r)) do
--aktuelle spannung an nachbarn übergeben
--wenn nachbar wire -> v-1 sonst v
local nnode = get_node_force(np)
if mesecon.is_conductor(nnode.name) then
insert(frontiers, {pos = np, link = l, voltage=v-1 ,source=f.pos})
else
insert(frontiers, {pos = np, link = l, voltage=v ,source=f.pos})
end
end
end
end
--spannung setzen
if v<1 then
-- ich bin aus
if mesecon.is_conductor_on(node, f.link) then
mesecon.swap_node_force(f.pos, mesecon.get_conductor_off(node, f.link))
end
meta:set_int("mesecon_voltage", 0)
else
if mesecon.is_conductor_off(node, f.link) then
mesecon.swap_node_force(f.pos, mesecon.get_conductor_on(node, f.link))
end
meta:set_int("mesecon_voltage", v)
end
f.voltage = (v<1 and 0 or v)
else
if v<1 then
--ausschalten
if mesecon.is_conductor_on(node, f.link) then
mesecon.swap_node_force(f.pos, mesecon.get_conductor_off(node, f.link))
end
else
--mesecon.swap_node_force(f.pos, mesecon.get_conductor_on(node, f.link))
end
end
mesecon.swap_node_force(f.pos, mesecon.get_conductor_on(node, f.link))
f.link.opaquespread=false
elseif mesecon.is_effector(node.name) then
mesecon.changesignal(f.pos, node, f.link, mesecon.state.on, depth)
if mesecon.is_effector_off(node.name) then
if f.voltage<1 then
--ausschalten
--if mesecon.is_effector_on(node.name) then
mesecon.changesignal(f.pos, node, f.link, mesecon.state.off, depth)
mesecon.deactivate(f.pos, node, f.link, depth)
--end
else
--einschalten
mesecon.changesignal(f.pos, node, f.link, mesecon.state.on, depth)
mesecon.activate(f.pos, node, f.link, depth)
end
if minetest.get_item_group(node.name, "opaque") ~= 1 then f.link.opaquespread=false end
end
if node and f.link.spread and minetest.get_item_group(node.name, "opaque") == 1 then
-- Call turnon on neighbors
@ -416,12 +477,11 @@ function mesecon.turnon(pos, link)
local np = vector.add(f.pos, r)
for _, l in pairs(mesecon.rules_link_rule_all(f.pos, r)) do
local nlink = copy(l)
nlink.spread = false
insert(frontiers, {pos = np, link = nlink})
if not (f.link.opaquespread and mesecon.is_conductor(mesecon.get_node_force(np).name)) then nlink.spread = false end
insert(frontiers, {pos = np, link = nlink, voltage=f.voltage})
end
end
end
depth = depth + 1
end
end
@ -443,8 +503,11 @@ end
-- depth = indicates order in which signals wire fired, higher is later
-- }
function mesecon.turnoff(pos, link)
--muss alle receptor_on zurückliefern
-- komplett durchgehen, nicht abbrechen
local frontiers = {{pos = pos, link = link}}
local signals = {}
local rec_on = {}
local depth = 1
while frontiers[1] do
@ -455,13 +518,12 @@ function mesecon.turnoff(pos, link)
local rules = mesecon.conductor_get_rules(node)
for _, r in pairs(mesecon.rule2meta(f.link, rules)) do
local np = vector.add(f.pos, r)
-- Check if an onstate receptor is connected. If that is the case,
-- abort this turnoff process by returning false. `receptor_off` will
-- discard all the changes that we made in the voxelmanip:
for _, l in pairs(mesecon.rules_link_rule_all_inverted(f.pos, r)) do
if is_receptor_on(get_node_force(np).name) then
return false
insert(rec_on, np)
end
end
@ -469,9 +531,17 @@ function mesecon.turnoff(pos, link)
for _, l in pairs(mesecon.rules_link_rule_all(f.pos, r)) do
insert(frontiers, {pos = np, link = l})
end
end
mesecon.swap_node_force(f.pos, mesecon.get_conductor_off(node, f.link))
local meta = minetest.get_meta(f.pos)
--if mesecon.is_conductor_on(node, f.link) then
--spannung neu rechnen
--else
--erstmal spannung überall auf 0 -> wird im anschluss von den receptoren ausgehend wieder gesetzt
meta:set_int("mesecon_voltage", 0)
--end
elseif mesecon.is_effector(node.name) then
insert(signals, {
pos = f.pos,
@ -486,35 +556,55 @@ function mesecon.turnoff(pos, link)
-- Warning: A LOT of nodes need to be looked at for this to work
local fpos = f.pos
for _, r in pairs(mesecon.rule2meta(f.link, mesecon.rules.mcl_alldirs_spread)) do
local np = {x=fpos.x+r.x, y=fpos.y+r.y, z=fpos.z+r.z}
local np = vector.add(f.pos, r)
local n = get_node_force(np)
if n and is_receptor_on(n.name) then
if n and is_receptor_on(n.name) and mesecon.get_receptor(n.name).opaquespread then
local receptorrules = receptor_get_rules(n)
for _, rr in pairs(receptorrules) do
if rr.spread and equals(invertRule(rr), r) then
return false
insert(rec_on, np)
--return false
end
end
end
if n and mesecon.is_effector(n.name) then
insert(signals, {
pos = np,
node = n,
link = r,
depth = depth
})
end
if mesecon.is_conductor_on(n) and f.link.opaquespread then
insert(frontiers, {pos = np, link = r})
end
for _, l in pairs(mesecon.rules_link_rule_all(fpos, r)) do
local nlink = copy(l)
nlink.spread = false
insert(frontiers, {pos = np, link = nlink})
local lp = vector.add(np, l)
local ln = get_node_force(lp)
if mesecon.is_effector(ln.name) then
local nlink = copy(l)
if not f.link.opaquespread then nlink.spread = false end
insert(frontiers, {pos = np, link = nlink})
end
end
end
end
depth = depth + 1
end
for _, sig in pairs(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 not next(rec_on) then
--nur, wenn kein receptor_on gefunden
for _, sig in pairs(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)
end
end
end
return true
return true, rec_on
else
return false, rec_on
end
end
-- Get all linking inputrules of inputnode (effector or conductor) that is connected to
@ -565,12 +655,12 @@ end
function mesecon.is_powered(pos, rule, depth, sourcepos, home_pos)
if depth == nil then depth = 0 end
if depth > 1 then
return false, false
return false, false, 0, false, false
end
local node = get_node_force(pos)
local rules = mesecon.get_any_inputrules(node)
if not rules then
return false, false
return false, false, 0, false, false
end
if not home_pos then
home_pos = pos
@ -581,61 +671,74 @@ function mesecon.is_powered(pos, rule, depth, sourcepos, home_pos)
sourcepos = {}
end
local function power_walk(pos, home_pos, sourcepos, rulenames, rule, depth)
local function power_walk(pos, home_pos, sourcepos, rulenames, rule, depth, voltage, fc, os)
local spread = false
local cond = fc
for _, rname in pairs(rulenames) do
local np = vector.add(pos, rname)
local nn = get_node_force(np)
if (mesecon.is_conductor_on (nn, invertRule(rname))
or is_receptor_on (nn.name)) then
if (mesecon.is_conductor_on (nn, invertRule(rname)) or is_receptor_on (nn.name)) then
if not equals(home_pos, np) then
local rulez = mesecon.get_any_outputrules(nn)
local spread_tmp = false
for r=1, #rulez do
if equals(invertRule(rname), rulez[r]) then
if rulez[r].spread then
spread_tmp = true
--has output connected to me
local spread_tmp = rulez[r].spread
if depth == 0 or spread_tmp then
local meta = minetest.get_meta(np)
local nvol = meta:get_string("mesecon_voltage")~="" and meta:get_int("mesecon_voltage") or 15
if nvol>voltage then
voltage = nvol
cond = mesecon.is_conductor(nn.name)
end
os = os or mesecon.is_receptor_opaquespread(nn.name)
np.opaquespread=mesecon.is_receptor_opaquespread(nn.name)
insert(sourcepos, np)
if spread_tmp then spread = true end
end
end
end
if depth == 0 or spread_tmp then
insert(sourcepos, np)
if spread_tmp then
spread = true
end
end
end
--elseif depth == 0 and minetest.get_item_group(nn.name, "opaque") == 1 and not pos.conductor then
elseif depth == 0 and minetest.get_item_group(nn.name, "opaque") == 1 then
local more_sourcepos = mesecon.is_powered(np, nil, depth + 1, sourcepos, home_pos)
if more_sourcepos and #more_sourcepos > 0 then
local more_sourcepos, more_spread, more_voltage, more_cond, more_os = mesecon.is_powered(np, nil, depth + 1, sourcepos, home_pos, os)
if more_sourcepos and #more_sourcepos > 0 and more_voltage>=1 and (not pos.conductor or more_os) then
mesecon.mergetable(sourcepos, more_sourcepos)
if more_voltage>voltage then
voltage = more_voltage
cond = more_cond
os=more_os
end
end
end
end
return sourcepos, spread
return sourcepos, spread, voltage, cond, os
end
local v = 0
local fromConductor = false
local spread = false
local opaquespread = false
if not rule then
for _, rule in pairs(mesecon.flattenrules(rules)) do
local spread_temp
local rulenames = mesecon.rules_link_rule_all_inverted(pos, rule)
sourcepos, spread_temp = power_walk(pos, home_pos, sourcepos, rulenames, rule, depth)
if next(rulenames) ~= nil then sourcepos, spread_temp, v, fromConductor, opaquespread = power_walk(pos, home_pos, sourcepos, rulenames, rule, depth, v, fromConductor, opaquespread) end
if spread_temp then
spread = true
end
end
else
local rulenames = mesecon.rules_link_rule_all_inverted(pos, rule)
sourcepos, spread = power_walk(pos, home_pos, sourcepos, rulenames, rule, depth)
sourcepos, spread, v, fromConductor, opaquespread = power_walk(pos, home_pos, sourcepos, rulenames, rule, depth, v, opaquespread)
end
-- Return FALSE if not powered, return list of sources if is powered
if (#sourcepos == 0) then
return false, false
return false, false, 0, false, false
else
return sourcepos, spread
return sourcepos, spread, v, fromConductor, opaquespread
end
end

View File

@ -1,3 +1,12 @@
--function mesecon.on_placenode(pos, node)
--function mesecon.on_dignode(pos, node)
--function mesecon.on_blastnode(pos, node)
--function mesecon.do_overheat(pos)
--function mesecon.do_cooldown(pos)
--function mesecon.get_heat(pos)
--function mesecon.move_hot_nodes(moved_nodes)
-- Dig and place services
function mesecon.on_placenode(pos, node)
@ -11,15 +20,21 @@ function mesecon.on_placenode(pos, node)
-- Conductors: Send turnon signal when powered or replace by respective offstate conductor
-- if placed conductor is an onstate one
if mesecon.is_conductor(node.name) then
local sources = mesecon.is_powered(pos)
if sources then
node = mesecon.get_node_force(pos)
pos.conductor=true
local sources, _, voltage, fromConductor = mesecon.is_powered(pos)
if sources and voltage>=1 then
voltage = fromConductor and voltage-1 or voltage
local meta = minetest.get_meta(pos)
meta:set_int("mesecon_voltage", voltage)
-- also call receptor_on if itself is powered already, so that neighboring
-- conductors will be activated (when pushing an on-conductor with a piston)
for _, s in ipairs(sources) do
local rule = vector.subtract(pos, s)
mesecon.turnon(pos, rule)
local nnode = mesecon.get_node_force(s)
mesecon.turnon(pos, rule, voltage)
end
mesecon.receptor_on (pos, mesecon.conductor_get_rules(node))
mesecon.receptor_on (pos, mesecon.conductor_get_rules(node), voltage-1)
elseif mesecon.is_conductor_on(node) then
minetest.swap_node(pos, {name = mesecon.get_conductor_off(node)})
end
@ -52,29 +67,50 @@ function mesecon.on_placenode(pos, node)
end
if minetest.get_item_group(node.name, "opaque") == 1 then
local neighbors = mesecon.mcl_get_neighbors(pos)
local is_powered, direct_source = mesecon.is_powered(pos)
local is_powered, direct_source, voltage, _, opaquespread = mesecon.is_powered(pos)
if is_powered and direct_source then
for n=1, #neighbors do
local npos = neighbors[n].pos
local nnode = minetest.get_node(npos)
if mesecon.is_conductor_off(nnode) then
mesecon.receptor_on(npos, mesecon.conductor_get_rules(nnode))
-- Redstone torch is a special case and must be ignored
elseif mesecon.is_effector_on(nnode.name) and minetest.get_item_group(nnode.name, "redstone_torch") == 0 then
mesecon.changesignal(npos, nnode, neighbors[n].link, mesecon.state.on, 1)
mesecon.activate(npos, nnode, neighbors[n].link, 1)
if opaquespread then
mesecon.receptor_on(pos, nil, voltage)
else
local neighbors = mesecon.mcl_get_neighbors(pos)
for n=1, #neighbors do
local npos = neighbors[n].pos
local nnode = minetest.get_node(npos)
if mesecon.is_conductor_off(nnode) and opaquespread then
-- Redstone torch is a special case and must be ignored
elseif mesecon.is_effector_off(nnode.name) and minetest.get_item_group(nnode.name, "redstone_torch") == 0 then
mesecon.changesignal(npos, nnode, neighbors[n].link, mesecon.state.on, 1)
mesecon.activate(npos, nnode, neighbors[n].link, 1)
elseif mesecon.is_effector(nnode.name) and minetest.get_item_group(nnode.name, "redstone_torch") == 0 then
--eigen funktion für comparator schreiben
if voltage<1 then
--if mesecon.is_effector_on(node.name) then
--mesecon.changesignal(f.pos, node, f.link, mesecon.state.off, depth)
--mesecon.deactivate(f.pos, node, f.link, depth)
mesecon.changesignal(npos, nnode, neighbors[n].link, mesecon.state.on, 1)
mesecon.deactivate(npos, nnode, neighbors[n].link, 1)
--end
else
mesecon.changesignal(npos, nnode, neighbors[n].link, mesecon.state.on, 1)
mesecon.activate(npos, nnode, neighbors[n].link, 1)
end
end
end
end
end
end
end
function mesecon.on_dignode(pos, node)
if mesecon.is_conductor_on(node) then
mesecon.receptor_off(pos, mesecon.conductor_get_rules(node))
elseif mesecon.is_receptor_on(node.name) then
mesecon.receptor_off(pos, mesecon.receptor_get_rules(node))
function mesecon.on_dignode(pos, node, direct_dig)
local regnode = minetest.registered_nodes[node.name]
if (regnode and regnode.mesecons and not regnode.on_destruct) or not direct_dig then
if mesecon.is_conductor_on(node) then
mesecon.conductor_off(pos, mesecon.conductor_get_rules(node))
elseif mesecon.is_receptor_on(node.name) then
mesecon.receptor_off(pos, mesecon.receptor_get_rules(node), mesecon.is_receptor_opaquespread(node.name))
end
end
if minetest.get_item_group(node.name, "opaque") == 1 then
--local sources = mesecon.is_powered(pos)
@ -84,7 +120,7 @@ function mesecon.on_dignode(pos, node)
local nlink = neighbors[n].link
local nnode = minetest.get_node(npos)
if mesecon.is_conductor_on(nnode) then
mesecon.receptor_off(npos, mesecon.conductor_get_rules(nnode))
mesecon.conductor_off(npos, mesecon.conductor_get_rules(nnode))
-- Disable neighbor effectors unless they are in a special ignore group
elseif mesecon.is_effector_on(nnode.name) and mesecon.is_powered(npos) == false and minetest.get_item_group(nnode.name, "mesecon_ignore_opaque_dig") == 0 then
mesecon.changesignal(npos, nnode, nlink, mesecon.state.off, 1)
@ -102,8 +138,13 @@ function mesecon.on_blastnode(pos, node)
return minetest.get_node_drops(node.name, "")
end
function mesecon.reg_on_dignode(pos, node)
mesecon.on_dignode(pos, node, true)
end
minetest.register_on_placenode(mesecon.on_placenode)
minetest.register_on_dignode(mesecon.on_dignode)
minetest.register_on_dignode(mesecon.reg_on_dignode)
-- Overheating service for fast circuits
local OVERHEAT_MAX = mesecon.setting("overheat_max", 8)

View File

@ -1,3 +1,42 @@
--[[
function mesecon.move_node(pos, newpos)
function mesecon.rotate_rules_right(rules)
function mesecon.rotate_rules_left(rules)
function mesecon.rotate_rules_down(rules)
function mesecon.rotate_rules_up(rules)
function mesecon.flattenrules(allrules)
function mesecon.rule2bit(findrule, allrules)
function mesecon.rule2metaindex(findrule, allrules)
function mesecon.rule2meta(findrule, allrules)
function mesecon.mcl_get_neighbors(pos)
function mesecon.dec2bin(n)
function mesecon.getstate(nodename, states)
function mesecon.getbinstate(nodename, states)
function mesecon.get_bit(binary,bit)
function mesecon.set_bit(binary,bit,value)
function mesecon.invertRule(r)
function mesecon.tablecopy(table) -- deep table copy
function mesecon.cmpAny(t1, t2)
function mesecon.mergetable(source, dest)
function mesecon.register_node(name, spec_common, spec_off, spec_on)
function mesecon.flipstate(pos, node)
function mesecon.file2table(filename)
function mesecon.table2file(filename, table)
function mesecon.vm_begin()
function mesecon.vm_commit()
function mesecon.vm_abort()
function mesecon.vm_get_node(pos)
function mesecon.vm_swap_node(pos, name)
function mesecon.get_node_force(pos)
function mesecon.swap_node_force(pos, name)
function mesecon.register_autoconnect_hook(name, fct)
function mesecon.execute_autoconnect_hooks_now(pos, node)
function mesecon.execute_autoconnect_hooks_queue(pos, node)
function mesecon.tab2str(tbl)
function mesecon.pos2str(pos)
--]]
function mesecon.move_node(pos, newpos)
local node = minetest.get_node(pos)
local meta = minetest.get_meta(pos):to_table()
@ -254,6 +293,13 @@ function mesecon.register_node(name, spec_common, spec_off, spec_on)
spec_off.__mesecon_state = "off"
spec_on = mesecon.mergetable(spec_common, spec_on);
if spec_on.mesecons and (spec_on.mesecons.receptor or spec_on.mesecons.conductor) then
spec_on.on_destruct = spec_on.on_destruct or
function(pos, oldnode)
local node = minetest.get_node(pos)
mesecon.on_dignode(pos, node)
end
end
spec_off = mesecon.mergetable(spec_common, spec_off);
minetest.register_node(name .. "_on", spec_on)
@ -459,3 +505,31 @@ function mesecon.execute_autoconnect_hooks_queue(pos, node)
mesecon.queue:add_action(pos, "autoconnect_hook_"..name, {node})
end
end
function mesecon.tab2str(tbl)
if type(tbl) ~= "table" then
return tostring(tbl)
else
local tmp = ""
for k,v in pairs(tbl) do
if tmp ~="" then tmp = tmp .. " / " end
tmp = tmp .. tostring(k).."=" .. (type(v) == "table" and ("{"..mesecon.tabletostring(v).."}") or tostring(v))
end
return tmp
end
end
function mesecon.pos21tr(pos)
return pos.x .. "/" .. pos.y .. "/" .. pos.z
end
function mesecon.rules_sub(source_rules, sub)
local t = {}
for i = 1, #sub do t[mesecon.postostring(sub[i])] = true end
local res = mesecon.tablecopy(source_rules)
for i = #res, 1, -1 do
if t[mesecon.postostring(res[i])] then table.remove(res, i) end
end
return res
end

View File

@ -139,6 +139,7 @@ function mesecon.register_button(basename, description, texture, recipeitem, sou
mesecons = {receptor = {
state = mesecon.state.off,
rules = button_get_output_rules,
opaquespread = true,
}},
_mcl_button_basename = basename,
_mcl_button_timer = button_timer,
@ -165,7 +166,8 @@ function mesecon.register_button(basename, description, texture, recipeitem, sou
sounds = sounds,
mesecons = {receptor = {
state = mesecon.state.on,
rules = button_get_output_rules
rules = button_get_output_rules,
opaquespread = true,
}},
_mcl_button_basename = basename,
_mcl_button_timer = button_timer,
@ -193,7 +195,10 @@ function mesecon.register_button(basename, description, texture, recipeitem, sou
mesecon.receptor_off(pos, button_get_output_rules(node))
end
end,
on_destruct = function(pos, oldnode)
local node = minetest.get_node(pos)
mesecon.on_dignode(pos, node)
end,
_mcl_blast_resistance = 0.5,
_mcl_hardness = 0.5,
})

View File

@ -290,6 +290,7 @@ for i = 1, 4 do
receptor = {
state = mesecon.state.off,
rules = delayer_get_output_rules,
opaquespread = true,
},
effector = {
rules = delayer_get_input_rules,
@ -359,6 +360,7 @@ for i = 1, 4 do
receptor = {
state = mesecon.state.on,
rules = delayer_get_output_rules,
opaquespread = true,
},
effector = {
rules = delayer_get_input_rules,
@ -366,6 +368,10 @@ for i = 1, 4 do
},
},
on_rotate = on_rotate,
on_destruct = function(pos, oldnode)
local node = minetest.get_node(pos)
mesecon.on_dignode(pos, node)
end,
})
end
@ -417,7 +423,8 @@ minetest.register_node("mesecons_delayer:delayer_off_locked", {
receptor =
{
state = mesecon.state.off,
rules = delayer_get_output_rules
rules = delayer_get_output_rules,
opaquespread = true,
},
effector =
{
@ -472,7 +479,8 @@ minetest.register_node("mesecons_delayer:delayer_on_locked", {
receptor =
{
state = mesecon.state.on,
rules = delayer_get_output_rules
rules = delayer_get_output_rules,
opaquespread = true,
},
effector =
{

View File

@ -133,7 +133,13 @@ function mesecon.register_pressure_plate(basename, description, textures_off, te
groups = groups_off,
tiles = textures_off,
mesecons = {receptor = { state = mesecon.state.off, rules = mesecon.rules.pplate }},
mesecons = {
receptor = {
state = mesecon.state.off,
rules = mesecon.rules.pplate,
opaquespread = true,
}
},
_doc_items_longdesc = longdesc,
_tt_help = tt,
},{
@ -143,7 +149,13 @@ function mesecon.register_pressure_plate(basename, description, textures_off, te
tiles = textures_on,
description = "",
mesecons = {receptor = { state = mesecon.state.on, rules = mesecon.rules.pplate }},
mesecons = {
receptor = {
state = mesecon.state.on,
rules = mesecon.rules.pplate,
opaquespread = true,
}
},
_doc_items_create_entry = false,
})

View File

@ -136,6 +136,7 @@ local off_override = {
receptor = {
state = mesecon.state.off,
rules = torch_get_output_rules,
opaquespread = true,
},
effector = {
state = mesecon.state.on,
@ -184,11 +185,13 @@ local on_override = {
on_destruct = function(pos, oldnode)
local node = minetest.get_node(pos)
torch_action_on(pos, node)
mesecon.on_dignode(pos, node)
end,
mesecons = {
receptor = {
state = mesecon.state.on,
rules = torch_get_output_rules
rules = torch_get_output_rules,
opaquespread = true,
},
effector = {
state = mesecon.state.off,

View File

@ -125,7 +125,8 @@ minetest.register_node("mesecons_walllever:wall_lever_off", {
sounds = mcl_sounds.node_sound_stone_defaults(),
mesecons = {receptor = {
rules = lever_get_output_rules,
state = mesecon.state.off
state = mesecon.state.off,
opaquespread = true,
}},
on_rotate = on_rotate,
_mcl_blast_resistance = 0.5,
@ -158,8 +159,13 @@ minetest.register_node("mesecons_walllever:wall_lever_on", {
sounds = mcl_sounds.node_sound_stone_defaults(),
mesecons = {receptor = {
rules = lever_get_output_rules,
state = mesecon.state.on
state = mesecon.state.on,
opaquespread = true,
}},
on_destruct = function(pos, oldnode)
local node = minetest.get_node(pos)
mesecon.on_dignode(pos, node)
end,
on_rotate = on_rotate,
_mcl_blast_resistance = 0.5,
_mcl_hardness = 0.5,

View File

@ -1,4 +1,4 @@
-- naming scheme: wire:(xp)(zp)(xm)(zm)(xpyp)(zpyp)(xmyp)(zmyp)_on/off
-- naming scheme: wire:(xp)(zp)(xm)(zm)(xpyp)(zpyp)(xmyp)(zmyp)(xpym)(zpym)(xmym)(zmym)_on/off
-- where x= x direction, z= z direction, y= y direction, p = +1, m = -1, e.g. xpym = {x=1, y=-1, z=0}
-- The (xp)/(zpyp)/.. statements shall be replaced by either 0 or 1
-- Where 0 means the wire has no visual connection to that direction and
@ -10,28 +10,28 @@ local S = minetest.get_translator(minetest.get_current_modname())
-- ## Update wire looks ##
-- #######################
local wire_rules =
{{x=-1, y= 0, z= 0, spread=true},
{x= 1, y= 0, z= 0, spread=true},
{x= 0, y=-1, z= 0, spread=true},
{x= 0, y= 1, z= 0, spread=true},
{x= 0, y= 0, z=-1, spread=true},
{x= 0, y= 0, z= 1, spread=true},
local wire_rules = {
{x= 1, y= 0, z= 0, spread=true}, --xp
{x= 0, y= 0, z= 1, spread=true}, --zp
{x=-1, y= 0, z= 0, spread=true}, --xm
{x= 0, y= 0, z=-1, spread=true}, --zm
{x= 1, y= 1, z= 0}, --xpyp
{x= 0, y= 1, z= 1}, --zpyp
{x=-1, y= 1, z= 0}, --xmyp
{x= 0, y= 1, z=-1}, --zmyp
{x= 1, y=-1, z= 0}, --xpym
{x= 0, y=-1, z= 1}, --zpym
{x=-1, y=-1, z= 0}, --xmym
{x= 0, y=-1, z=-1}, --zmym
{x= 0, y=-1, z= 0, spread=true}, --ym (always)
}
{x= 1, y= 1, z= 0},
{x= 1, y=-1, z= 0},
{x=-1, y= 1, z= 0},
{x=-1, y=-1, z= 0},
{x= 0, y= 1, z= 1},
{x= 0, y=-1, z= 1},
{x= 0, y= 1, z=-1},
{x= 0, y=-1, z=-1}}
-- self_pos = pos of any mesecon node, from_pos = pos of conductor to getconnect for
local function wire_getconnect(from_pos, self_pos)
local function wire_getconnect(from_pos, self_pos, from_rule)
local node = minetest.get_node(self_pos)
if minetest.registered_nodes[node.name]
and minetest.registered_nodes[node.name].mesecons then
and minetest.registered_nodes[node.name].mesecons or minetest.get_item_group(node.name, "opaque") == 1 then
-- rules of node to possibly connect to
local rules
if (minetest.registered_nodes[node.name].mesecon_wire) then
@ -42,19 +42,90 @@ local function wire_getconnect(from_pos, self_pos)
for _, r in ipairs(mesecon.flattenrules(rules)) do
if (vector.equals(vector.add(self_pos, r), from_pos)) then
return true
-- no upper-connect with opaqu block above me
if from_rule.y==1 then
local ufnode = mesecon.get_node_force(vector.add(from_pos, {x=0, y=1, z=0}))
if minetest.get_item_group(ufnode.name, "opaque") == 1 then return false, 1 end
end
if from_rule.y==-1 then
local nfnode = mesecon.get_node_force(vector.add(from_pos, {x=from_rule.x, y=0, z=from_rule.z}))
if minetest.get_item_group(nfnode.name, "opaque") == 1 then return false, 2 end
end
-- receptor -> always
if mesecon.is_receptor(node.name) then return true, 3 end
-- conductor -> always
if mesecon.is_conductor(node.name) then return true, 4 end
if from_rule.x==1 or from_rule.x==-1 then
local xpmnode = mesecon.get_node_force(vector.add(from_pos, {x=from_rule.x, y=0, z=0}))
--check blocks z=+-1
local zmnode = mesecon.get_node_force(vector.add(from_pos, {x=0, y=0, z=-1}))
if (mesecon.is_receptor(zmnode.name) or mesecon.is_conductor(zmnode.name)) and not (minetest.get_item_group(xpmnode.name, "opaque") == 1) then return false, 5 end
if minetest.get_item_group(zmnode.name, "opaque") == 1 then
--check upper
local zmypnode = mesecon.get_node_force(vector.add(from_pos, {x=0, y= 1, z=-1}))
if mesecon.is_conductor(zmypnode.name) then return false, 6 end
elseif zmnode.name=="air" then
--check lower
local zmymnode = mesecon.get_node_force(vector.add(from_pos, {x=0, y=-1, z=-1}))
if mesecon.is_conductor(zmymnode.name) then return false, 7 end
end
local zpnode = mesecon.get_node_force(vector.add(from_pos, {x=0, y=0, z= 1}))
if (mesecon.is_receptor(zpnode.name) or mesecon.is_conductor(zpnode.name)) and not (minetest.get_item_group(xpmnode.name, "opaque") == 1) then return false, 8 end
if minetest.get_item_group(zpnode.name, "opaque") == 1 then
--check upper
local zpypnode = mesecon.get_node_force(vector.add(from_pos, {x=0, y=1, z= 1}))
if mesecon.is_conductor(zpypnode.name) then return false, 9 end
elseif zpnode.name=="air" then
--check lower
local zpymnode = mesecon.get_node_force(vector.add(from_pos, {x=0, y=-1, z= 1}))
if mesecon.is_conductor(zpymnode.name) then return false, 10 end
end
end
if from_rule.z==1 or from_rule.z==-1 then
local zpmnode = mesecon.get_node_force(vector.add(from_pos, {x=0, y=0, z=from_rule.z}))
--check blocks x=+-1
local xmnode = mesecon.get_node_force(vector.add(from_pos, {x=-1, y=0, z=0}))
if (mesecon.is_receptor(xmnode.name) or mesecon.is_conductor(xmnode.name)) and not (minetest.get_item_group(zpmnode.name, "opaque") == 1) then return false, 12 end
if minetest.get_item_group(xmnode.name, "opaque") == 1 then
--check upper
local xmypnode = mesecon.get_node_force(vector.add(from_pos, {x=-1, y=1, z=0}))
if mesecon.is_conductor(xmypnode.name) then return false, 13 end
elseif xmnode.name=="air" then
--check lower
local xmymnode = mesecon.get_node_force(vector.add(from_pos, {x=-1, y=-1, z= 0}))
if mesecon.is_conductor(xmymnode.name) then return false, 14 end
end
local xpnode = mesecon.get_node_force(vector.add(from_pos, {x= 1, y=0, z=0}))
if (mesecon.is_receptor(xpnode.name) or mesecon.is_conductor(xpnode.name)) and not (minetest.get_item_group(zpmnode.name, "opaque") == 1) then return false, 15 end
if minetest.get_item_group(xpnode.name, "opaque") == 1 then
--check upper
local xpypnode = mesecon.get_node_force(vector.add(from_pos, {x= 1, y=1, z=0}))
if mesecon.is_conductor(xpypnode.name) then return false, 16 end
elseif xpnode.name=="air" then
--check lower
local xpymnode = mesecon.get_node_force(vector.add(from_pos, {x=1, y=-1, z= 0}))
if mesecon.is_conductor(xpymnode.name) then return false, 17 end
end
end
return true, 0
end
end
end
return false
return false, -1
end
-- Update this node
local function wire_updateconnect(pos)
local connections = {}
--check all rules
for _, r in ipairs(wire_rules) do
if wire_getconnect(pos, vector.add(pos, r)) then
local res, val = wire_getconnect(pos, vector.add(pos, r), r)
if res then
table.insert(connections, r)
end
end
@ -73,14 +144,25 @@ local function wire_updateconnect(pos)
if vec.z == 1 then nid[5] = "1" end
if vec.x == -1 then nid[6] = "1" end
if vec.z == -1 then nid[7] = "1" end
elseif vec.y == -1 then
if vec.x == 1 then nid[ 8] = "1" end
if vec.z == 1 then nid[ 9] = "1" end
if vec.x == -1 then nid[10] = "1" end
if vec.z == -1 then nid[11] = "1" end
end
end
local nodeid = (nid[0] or "0")..(nid[1] or "0")..(nid[2] or "0")..(nid[3] or "0")
..(nid[4] or "0")..(nid[5] or "0")..(nid[6] or "0")..(nid[7] or "0")
local nodeid = (nid[0] or "0")..(nid[1] or "0")..(nid[ 2] or "0")..(nid[ 3] or "0")
..(nid[4] or "0")..(nid[5] or "0")..(nid[ 6] or "0")..(nid[ 7] or "0")
..(nid[8] or "0")..(nid[9] or "0")..(nid[10] or "0")..(nid[11] or "0")
local state_suffix = string.find(minetest.get_node(pos).name, "_off") and "_off" or "_on"
minetest.set_node(pos, {name = "mesecons:wire_"..nodeid..state_suffix})
local orules = mesecon.get_any_inputrules(mesecon.get_node_force(pos))
mesecon.swap_node_force(pos, "mesecons:wire_"..nodeid..state_suffix)
local nrules = mesecon.get_any_inputrules(mesecon.get_node_force(pos))
local res = mesecon.rules_sub(orules, nrules)
return res
end
local function update_on_place_dig(pos, node)
@ -103,9 +185,13 @@ local function update_on_place_dig(pos, node)
for _, r in ipairs(mesecon.flattenrules(rules)) do
local np = vector.add(pos, r)
if minetest.registered_nodes[minetest.get_node(np).name]
and minetest.registered_nodes[minetest.get_node(np).name].mesecon_wire then
wire_updateconnect(np)
local nnode = minetest.get_node(np).name
if minetest.registered_nodes[nnode] and minetest.registered_nodes[nnode].mesecon_wire then
local abandoned_rules = wire_updateconnect(np)
if next(abandoned_rules) ~= nil then
mesecon.conductor_off(np, abandoned_rules)
mesecon.conductor_off(np, mesecon.conductor_get_rules(minetest.get_node(np)))
end
end
end
end
@ -161,7 +247,7 @@ local function register_wires()
while true do
-- Create group specifiction and nodeid string (see note above for details)
local nodeid = (nid[0] or "0")..(nid[1] or "0")..(nid[2] or "0")..(nid[3] or "0")
..(nid[4] or "0")..(nid[5] or "0")..(nid[6] or "0")..(nid[7] or "0")
..(nid[4] or "0")..(nid[5] or "0")..(nid[6] or "0")..(nid[7] or "0")
-- Calculate nodebox
local nodebox = {type = "fixed", fixed={box_center}}
@ -206,13 +292,13 @@ local function register_wires()
local ratio_off = 128
local ratio_on = 192
local crossing_off = "(redstone_redstone_dust_dot.png^redstone_redstone_dust_line0.png^(redstone_redstone_dust_line1.png^[transformR90))^[colorize:#FF0000:"..ratio_off
local crossing_on = "(redstone_redstone_dust_dot.png^redstone_redstone_dust_line0.png^(redstone_redstone_dust_line1.png^[transformR90))^[colorize:#FF0000:"..ratio_on
local crossing_on = "(redstone_redstone_dust_dot.png^redstone_redstone_dust_line0.png^(redstone_redstone_dust_line1.png^[transformR90))^[colorize:#FF0000:"..ratio_on
local straight0_off = "redstone_redstone_dust_line0.png^[colorize:#FF0000:"..ratio_off
local straight0_on = "redstone_redstone_dust_line0.png^[colorize:#FF0000:"..ratio_on
local straight0_on = "redstone_redstone_dust_line0.png^[colorize:#FF0000:"..ratio_on
local straight1_off = "redstone_redstone_dust_line0.png^[colorize:#FF0000:"..ratio_off
local straight1_on = "redstone_redstone_dust_line0.png^[colorize:#FF0000:"..ratio_on
local straight1_on = "redstone_redstone_dust_line0.png^[colorize:#FF0000:"..ratio_on
local dot_off = "redstone_redstone_dust_dot.png^[colorize:#FF0000:"..ratio_off
local dot_on = "redstone_redstone_dust_dot.png^[colorize:#FF0000:"..ratio_on
local dot_on = "redstone_redstone_dust_dot.png^[colorize:#FF0000:"..ratio_on
local tiles_off, tiles_on
@ -286,8 +372,237 @@ S("Read the help entries on the other redstone components to learn how redstone
if (nid_inc(nid) == false) then return end
end
end
-- register the old nodes -> alias?
register_wires()
----------------------------------------------------
-- go to the next nodeid (ex.: 01000011 --> 01000100)
local function nid_inc2() end
function nid_inc2(nid)
local i = 0
while nid[i-1] ~= 1 do
nid[i] = (nid[i] ~= 1) and 1 or 0
i = i + 1
end
-- BUT: Skip impossible nodeids:
if (
(nid[0] == 0 and nid[4] == 1) or (nid[0] == 0 and nid[ 8] == 1) or (nid[4] == 1 and nid[ 8] == 1) or
(nid[1] == 0 and nid[5] == 1) or (nid[1] == 0 and nid[ 9] == 1) or (nid[5] == 1 and nid[ 9] == 1) or
(nid[2] == 0 and nid[6] == 1) or (nid[2] == 0 and nid[10] == 1) or (nid[6] == 1 and nid[10] == 1) or
(nid[3] == 0 and nid[7] == 1) or (nid[3] == 0 and nid[11] == 1) or (nid[7] == 1 and nid[11] == 1)
) then
return nid_inc2(nid)
end
return i <= 12
end
local function register_wires2()
local nid = {}
while true do
-- Create group specifiction and nodeid string (see note above for details)
local nodeid = (nid[0] or "0")..(nid[1] or "0")..(nid[ 2] or "0")..(nid[ 3] or "0")
..(nid[4] or "0")..(nid[5] or "0")..(nid[ 6] or "0")..(nid[ 7] or "0")
..(nid[8] or "0")..(nid[9] or "0")..(nid[10] or "0")..(nid[11] or "0")
-- Calculate nodebox, ignore 8 to 11
local nodebox = {type = "fixed", fixed={box_center}}
for i=0,7 do
if nid[i] == 1 then
table.insert(nodebox.fixed, nbox_nid[i])
end
end
-- Add bump to nodebox if curved
if (nid[0] == 1 and nid[1] == 1) or (nid[1] == 1 and nid[2] == 1)
or (nid[2] == 1 and nid[3] == 1) or (nid[3] == 1 and nid[0] == 1) then
table.insert(nodebox.fixed, box_bump1)
end
-- If nothing to connect to, still make a nodebox of a straight wire
--if nodeid == "00000000" then
if nodeid:sub(1,8) == "00000000" then
nodebox.fixed = {-8/16, -.5, -1/16, 8/16, -.5+1/16, 1/16}
end
--rules berechnen, nur nötige verwenden
local nrules = {}
for i=0,11 do
if nid[i]==1 then
table.insert(nrules,wire_rules[i+1])
end
end
table.insert(nrules,wire_rules[12+1]) --ym (always)
--[[
00100000
-- naming scheme: wire:(xp)(zp)(xm)(zm)(xpyp)(zpyp)(xmyp)(zmyp)_on/off
komplett flat
11110000
{x= 1, y= 0, z= 0, spread=true}, --xp 0 x
{x= 0, y= 0, z= 1, spread=true}, --zp 1 -
{x=-1, y= 0, z= 0, spread=true}, --xm 2 x
{x= 0, y= 0, z=-1, spread=true}, --zm 3
{x= 0, y=-1, z= 0, spread=true}, --unten (immer)
{x= 1, y= 1, z= 0}, --xpyp 4
{x= 0, y= 1, z= 1}, --zpyp 5
{x=-1, y= 1, z= 0}, --xmyp 6
{x= 0, y= 1, z=-1}, --zmyp 7
{x= 1, y=-1, z= 0}, --xpym 8
{x= 0, y=-1, z= 1}, --zpym 9
{x=-1, y=-1, z= 0}, --xmym 10
{x= 0, y=-1, z=-1}, --zmym 11
0,4, 8
1,5, 9
2,6,10
3,7,11
--]]
--[[
{x= 1, y= 0, z= 0, spread=true}, --xp
{x= 0, y= 0, z= 1, spread=true}, --zp
{x=-1, y= 0, z= 0, spread=true}, --xm
{x= 0, y= 0, z=-1, spread=true}, --zm
{x= 1, y= 1, z= 0}, --xpyp
{x= 0, y= 1, z= 1}, --zpyp
{x=-1, y= 1, z= 0}, --xmyp
{x= 0, y= 1, z=-1}, --zmyp
{x= 1, y=-1, z= 0}, --xpym
{x= 0, y=-1, z= 1}, --zpym
{x=-1, y=-1, z= 0}, --xmym
{x= 0, y=-1, z=-1}} --zmym
{x= 0, y=-1, z= 0, spread=true}, --ym (always)
--]]
local meseconspec_off = { conductor = {
--rules = wire_rules,
rules = nrules,
state = mesecon.state.off,
onstate = "mesecons:wire_"..nodeid.."_on"
}}
local meseconspec_on = { conductor = {
--rules = wire_rules,
rules = nrules,
state = mesecon.state.on,
offstate = "mesecons:wire_"..nodeid.."_off"
}}
local groups_on = {dig_immediate = 3, mesecon_conductor_craftable = 1,
not_in_creative_inventory = 1, attached_node = 1, dig_by_water = 1,destroy_by_lava_flow=1, dig_by_piston = 1}
local groups_off = {dig_immediate = 3, mesecon_conductor_craftable = 1,
attached_node = 1, dig_by_water = 1,destroy_by_lava_flow=1, dig_by_piston = 1, craftitem = 1}
--if nodeid ~= "00000000" then
if nodeid:sub(1,8) ~= "00000000" then
groups_off["not_in_creative_inventory"] = 1
end
-- Wire textures
local ratio_off = 128
local ratio_on = 192
local crossing_off = "(redstone_redstone_dust_dot.png^redstone_redstone_dust_line0.png^(redstone_redstone_dust_line1.png^[transformR90))^[colorize:#FF0000:"..ratio_off
local crossing_on = "(redstone_redstone_dust_dot.png^redstone_redstone_dust_line0.png^(redstone_redstone_dust_line1.png^[transformR90))^[colorize:#FF0000:"..ratio_on
local straight0_off = "redstone_redstone_dust_line0.png^[colorize:#FF0000:"..ratio_off
local straight0_on = "redstone_redstone_dust_line0.png^[colorize:#FF0000:"..ratio_on
local straight1_off = "redstone_redstone_dust_line0.png^[colorize:#FF0000:"..ratio_off
local straight1_on = "redstone_redstone_dust_line0.png^[colorize:#FF0000:"..ratio_on
local dot_off = "redstone_redstone_dust_dot.png^[colorize:#FF0000:"..ratio_off
local dot_on = "redstone_redstone_dust_dot.png^[colorize:#FF0000:"..ratio_on
local tiles_off, tiles_on
local wirehelp, tt, longdesc, usagehelp, img, desc_off, desc_on
if nodeid:sub(1,8) == "00000000" then
-- Non-connected redstone wire
nodebox.fixed = {-8/16, -.5, -8/16, 8/16, -.5+1/64, 8/16}
-- “Dot” texture
tiles_off = { dot_off, dot_off, "blank.png", "blank.png", "blank.png", "blank.png" }
tiles_on = { dot_on, dot_on, "blank.png", "blank.png", "blank.png", "blank.png" }
tt = S("Transmits redstone power, powers mechanisms")
longdesc = S("Redstone is a versatile conductive mineral which transmits redstone power. It can be placed on the ground as a trail.").."\n"..
S("A redstone trail can be in two states: Powered or not powered. A powered redstone trail will power (and thus activate) adjacent redstone components.").."\n"..
S("Redstone power can be received from various redstone components, such as a block of redstone or a button. Redstone power is used to activate numerous mechanisms, such as redstone lamps or pistons.")
usagehelp = S("Place redstone on the ground to build a redstone trail. The trails will connect to each other automatically and it can also go over hills.").."\n\n"..
S("Read the help entries on the other redstone components to learn how redstone components interact.")
img = "redstone_redstone_dust.png"
desc_off = S("Redstone")
desc_on = S("Powered Redstone Spot (@1)", nodeid)
else
-- Connected redstone wire
table.insert(nodebox, box_center)
tiles_off = { crossing_off, crossing_off, straight0_off, straight1_off, straight0_off, straight1_off }
tiles_on = { crossing_on, crossing_on, straight0_on, straight1_on, straight0_on, straight1_on }
wirehelp = false
desc_off = S("Redstone Trail (@1)", nodeid)
desc_on = S("Powered Redstone Trail (@1)", nodeid)
end
mesecon.register_node(":mesecons:wire_"..nodeid, {
drawtype = "nodebox",
paramtype = "light",
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "clip" or true,
sunlight_propagates = true,
selection_box = selectionbox,
node_box = nodebox,
walkable = false,
drop = "mesecons:wire_00000000_off",
sounds = mcl_sounds.node_sound_defaults(),
is_ground_content = false,
mesecon_wire = true
},{
description = desc_off,
inventory_image = img,
wield_image = img,
_tt_help = tt,
_doc_items_create_entry = wirehelp,
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usagehelp,
tiles = tiles_off,
mesecons = meseconspec_off,
groups = groups_off,
},{
description = desc_on,
_doc_items_create_entry = false,
tiles = tiles_on,
mesecons = meseconspec_on,
groups = groups_on
})
-- Add Help entry aliases for e.g. making it identifiable by the lookup tool [doc_identifier]
if minetest.get_modpath("doc") then
if nodeid:sub(1,8) ~= "00000000" then
doc.add_entry_alias("nodes", "mesecons:wire_000000000000_off", "nodes", "mesecons:wire_"..nodeid.."_off")
end
doc.add_entry_alias("nodes", "mesecons:wire_000000000000_off", "nodes", "mesecons:wire_"..nodeid.."_on")
end
if (nid_inc2(nid) == false) then return end
end
end
register_wires2()
----------------------------------------------------
minetest.register_alias("mesecons:redstone", "mesecons:wire_00000000_off")
minetest.register_craft({