forked from minetest-mods/mesecons
Compare commits
22 Commits
mvps-ignor
...
e38e4fe0c5
Author | SHA1 | Date | |
---|---|---|---|
e38e4fe0c5 | |||
ecea0a2896 | |||
5ad1e6bc4d | |||
9323445182 | |||
b91fe92d13 | |||
e15c55c066 | |||
6a87290ead | |||
db5879706d | |||
1963bfcc0d | |||
65793514fe | |||
6936c8c2e4 | |||
f5c3f798be | |||
69d4a9584d | |||
3f75c06a3b | |||
2fc1682c04 | |||
93aa24dc42 | |||
93f155f604 | |||
9b835053c2 | |||
583d2c1441 | |||
397d449f1e | |||
29ec26a4c8 | |||
0d86f2c45e |
62
mesecons/fifo_queue.lua
Normal file
62
mesecons/fifo_queue.lua
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
|
||||||
|
-- a simple first-in-first-out queue
|
||||||
|
-- very similar to the one in https://github.com/minetest/minetest/pull/7683
|
||||||
|
|
||||||
|
local fifo_queue = {}
|
||||||
|
|
||||||
|
local metatable = {__index = fifo_queue}
|
||||||
|
|
||||||
|
-- creates a new empty queue
|
||||||
|
function fifo_queue.new()
|
||||||
|
local q = {n_in = 0, n_out = 0, i_out = 1, buf_in = {}, buf_out = {}}
|
||||||
|
setmetatable(q, metatable)
|
||||||
|
return q
|
||||||
|
end
|
||||||
|
|
||||||
|
-- adds an element to the queue
|
||||||
|
function fifo_queue.add(self, v)
|
||||||
|
local n = self.n_in + 1
|
||||||
|
self.n_in = n
|
||||||
|
self.buf_in[n] = v
|
||||||
|
end
|
||||||
|
|
||||||
|
-- removes and returns the next element, or nil of empty
|
||||||
|
function fifo_queue.take(self)
|
||||||
|
local i_out = self.i_out
|
||||||
|
if i_out <= self.n_out then
|
||||||
|
local v = self.buf_out[i_out]
|
||||||
|
self.i_out = i_out + 1
|
||||||
|
self.buf_out[i_out] = true
|
||||||
|
return v
|
||||||
|
end
|
||||||
|
|
||||||
|
-- buf_out is empty, try to swap
|
||||||
|
self.i_out = 1
|
||||||
|
self.n_out = 0
|
||||||
|
if self.n_in == 0 then
|
||||||
|
return nil -- empty
|
||||||
|
end
|
||||||
|
|
||||||
|
-- swap
|
||||||
|
self.n_out = self.n_in
|
||||||
|
self.n_in = 0
|
||||||
|
self.buf_out, self.buf_in = self.buf_in, self.buf_out
|
||||||
|
|
||||||
|
local v = self.buf_out[1]
|
||||||
|
self.i_out = 2
|
||||||
|
self.buf_out[1] = true
|
||||||
|
return v
|
||||||
|
end
|
||||||
|
|
||||||
|
-- returns whether the queue is empty
|
||||||
|
function fifo_queue.is_empty(self)
|
||||||
|
return self.n_out == self.i_out + 1 and self.n_in == 0
|
||||||
|
end
|
||||||
|
|
||||||
|
-- returns stuff for iteration in a for loop, like pairs
|
||||||
|
-- adding new elements while iterating is no problem
|
||||||
|
function fifo_queue.iter(self)
|
||||||
|
return fifo_queue.take, self, nil
|
||||||
|
end
|
||||||
|
|
||||||
|
return fifo_queue
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
-- RECEPTORS
|
-- RECEPTORS
|
||||||
-- mesecon.is_receptor(nodename) --> Returns true if nodename is a receptor
|
-- mesecon.is_receptor(nodename) --> Returns true if nodename is a receptor
|
||||||
-- mesecon.is_receptor_on(nodename --> Returns true if nodename is an receptor with state = mesecon.state.on
|
-- mesecon.is_receptor_on(nodename) --> Returns true if nodename is an receptor with state = mesecon.state.on
|
||||||
-- mesecon.is_receptor_off(nodename) --> Returns true if nodename is an receptor with state = mesecon.state.off
|
-- mesecon.is_receptor_off(nodename) --> Returns true if nodename is an receptor with state = mesecon.state.off
|
||||||
-- mesecon.receptor_get_rules(node) --> Returns the rules of the receptor (mesecon.rules.default if none specified)
|
-- mesecon.receptor_get_rules(node) --> Returns the rules of the receptor (mesecon.rules.default if none specified)
|
||||||
|
|
||||||
@ -46,6 +46,8 @@
|
|||||||
-- mesecon.rotate_rules_down(rules)
|
-- mesecon.rotate_rules_down(rules)
|
||||||
-- These functions return rules that have been rotated in the specific direction
|
-- These functions return rules that have been rotated in the specific direction
|
||||||
|
|
||||||
|
local fifo_queue = dofile(minetest.get_modpath("mesecons").."/fifo_queue.lua")
|
||||||
|
|
||||||
-- General
|
-- General
|
||||||
function mesecon.get_effector(nodename)
|
function mesecon.get_effector(nodename)
|
||||||
if minetest.registered_nodes[nodename]
|
if minetest.registered_nodes[nodename]
|
||||||
@ -92,8 +94,8 @@ function mesecon.get_any_inputrules(node)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function mesecon.get_any_rules(node)
|
function mesecon.get_any_rules(node)
|
||||||
return mesecon.mergetable(mesecon.get_any_inputrules(node) or {},
|
return mesecon.merge_rule_sets(mesecon.get_any_inputrules(node),
|
||||||
mesecon.get_any_outputrules(node) or {})
|
mesecon.get_any_outputrules(node))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Receptors
|
-- Receptors
|
||||||
@ -366,37 +368,105 @@ function mesecon.is_power_off(pos, rulename)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- The set of conductor states which require light updates when they change.
|
||||||
|
local light_update_conductors
|
||||||
|
|
||||||
|
-- Calculate the contents of the above set if they have not been calculated.
|
||||||
|
-- This must be called before get_update_light_conductor.
|
||||||
|
local function find_light_update_conductors()
|
||||||
|
-- The expensive calculation is only done the first time.
|
||||||
|
if light_update_conductors then return end
|
||||||
|
|
||||||
|
light_update_conductors = {}
|
||||||
|
|
||||||
|
-- Find conductors whose lighting characteristics change depending on their state.
|
||||||
|
local checked = {}
|
||||||
|
for name, def in pairs(minetest.registered_nodes) do
|
||||||
|
local conductor = mesecon.get_conductor(name)
|
||||||
|
if conductor and not checked[name] then
|
||||||
|
-- Find the other states of the conductor besides the current one.
|
||||||
|
local other_states
|
||||||
|
if conductor.onstate then
|
||||||
|
other_states = {conductor.onstate}
|
||||||
|
elseif conductor.offstate then
|
||||||
|
other_states = {conductor.offstate}
|
||||||
|
else
|
||||||
|
other_states = conductor.states
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check the conductor. Other states are marked as checked.
|
||||||
|
for _, other_state in ipairs(other_states) do
|
||||||
|
local other_def = minetest.registered_nodes[other_state]
|
||||||
|
if (def.paramtype == "light") ~= (other_def.paramtype == "light")
|
||||||
|
or def.sunlight_propagates ~= other_def.sunlight_propagates
|
||||||
|
or def.light_source ~= other_def.light_source then
|
||||||
|
-- The light characteristics change depending on the state.
|
||||||
|
-- The states are added to the set.
|
||||||
|
light_update_conductors[name] = true
|
||||||
|
for _, other_state in ipairs(other_states) do
|
||||||
|
light_update_conductors[other_state] = true
|
||||||
|
checked[other_state] = true
|
||||||
|
end
|
||||||
|
break
|
||||||
|
end
|
||||||
|
checked[other_state] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- This is the callback for swap_node_force in turnon and turnoff. It determines
|
||||||
|
-- whether a conductor node necessitates a lighting update.
|
||||||
|
local function get_update_light_conductor(pos, name)
|
||||||
|
return light_update_conductors[name] ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
-- Turn off an equipotential section starting at `pos`, which outputs in the direction of `link`.
|
-- Turn off an equipotential section starting at `pos`, which outputs in the direction of `link`.
|
||||||
-- Breadth-first search. Map is abstracted away in a voxelmanip.
|
-- Breadth-first search. Map is abstracted away in a voxelmanip.
|
||||||
-- Follow all all conductor paths replacing conductors that were already
|
-- Follow all all conductor paths replacing conductors that were already
|
||||||
-- looked at, activating / changing all effectors along the way.
|
-- looked at, activating / changing all effectors along the way.
|
||||||
function mesecon.turnon(pos, link)
|
function mesecon.turnon(pos, link)
|
||||||
local frontiers = {{pos = pos, link = link}}
|
find_light_update_conductors()
|
||||||
|
|
||||||
|
local frontiers = fifo_queue.new()
|
||||||
|
frontiers:add({pos = pos, link = link})
|
||||||
|
local pos_can_be_skipped = {}
|
||||||
|
|
||||||
local depth = 1
|
local depth = 1
|
||||||
while frontiers[1] do
|
for f in frontiers:iter() do
|
||||||
local f = table.remove(frontiers, 1)
|
|
||||||
local node = mesecon.get_node_force(f.pos)
|
local node = mesecon.get_node_force(f.pos)
|
||||||
|
|
||||||
if not node then
|
if not node then
|
||||||
-- Area does not exist; do nothing
|
-- Area does not exist; do nothing
|
||||||
elseif mesecon.is_conductor_off(node, f.link) then
|
pos_can_be_skipped[minetest.hash_node_position(f.pos)] = true
|
||||||
|
elseif mesecon.is_conductor(node.name) then
|
||||||
local rules = mesecon.conductor_get_rules(node)
|
local rules = mesecon.conductor_get_rules(node)
|
||||||
|
|
||||||
-- Call turnon on neighbors
|
if mesecon.is_conductor_off(node, f.link) then
|
||||||
for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do
|
-- Call turnon on neighbors
|
||||||
local np = vector.add(f.pos, r)
|
for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do
|
||||||
for _, l in ipairs(mesecon.rules_link_rule_all(f.pos, r)) do
|
local np = vector.add(f.pos, r)
|
||||||
table.insert(frontiers, {pos = np, link = l})
|
if not pos_can_be_skipped[minetest.hash_node_position(np)] then
|
||||||
|
for _, l in ipairs(mesecon.rules_link_rule_all(f.pos, r)) do
|
||||||
|
frontiers:add({pos = np, link = l})
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
mesecon.swap_node_force(f.pos, mesecon.get_conductor_on(node, f.link), get_update_light_conductor)
|
||||||
end
|
end
|
||||||
|
|
||||||
mesecon.swap_node_force(f.pos, mesecon.get_conductor_on(node, f.link))
|
-- Only conductors with flat rules can be reliably skipped later
|
||||||
|
if not rules[1] or rules[1].x then
|
||||||
|
pos_can_be_skipped[minetest.hash_node_position(f.pos)] = true
|
||||||
|
end
|
||||||
elseif mesecon.is_effector(node.name) then
|
elseif mesecon.is_effector(node.name) then
|
||||||
mesecon.changesignal(f.pos, node, f.link, mesecon.state.on, depth)
|
mesecon.changesignal(f.pos, node, f.link, mesecon.state.on, depth)
|
||||||
if mesecon.is_effector_off(node.name) then
|
if mesecon.is_effector_off(node.name) then
|
||||||
mesecon.activate(f.pos, node, f.link, depth)
|
mesecon.activate(f.pos, node, f.link, depth)
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
pos_can_be_skipped[minetest.hash_node_position(f.pos)] = true
|
||||||
end
|
end
|
||||||
depth = depth + 1
|
depth = depth + 1
|
||||||
end
|
end
|
||||||
@ -419,37 +489,51 @@ end
|
|||||||
-- depth = indicates order in which signals wire fired, higher is later
|
-- depth = indicates order in which signals wire fired, higher is later
|
||||||
-- }
|
-- }
|
||||||
function mesecon.turnoff(pos, link)
|
function mesecon.turnoff(pos, link)
|
||||||
local frontiers = {{pos = pos, link = link}}
|
find_light_update_conductors()
|
||||||
|
|
||||||
|
local frontiers = fifo_queue.new()
|
||||||
|
frontiers:add({pos = pos, link = link})
|
||||||
local signals = {}
|
local signals = {}
|
||||||
|
local pos_can_be_skipped = {}
|
||||||
|
|
||||||
local depth = 1
|
local depth = 1
|
||||||
while frontiers[1] do
|
for f in frontiers:iter() do
|
||||||
local f = table.remove(frontiers, 1)
|
|
||||||
local node = mesecon.get_node_force(f.pos)
|
local node = mesecon.get_node_force(f.pos)
|
||||||
|
|
||||||
if not node then
|
if not node then
|
||||||
-- Area does not exist; do nothing
|
-- Area does not exist; do nothing
|
||||||
elseif mesecon.is_conductor_on(node, f.link) then
|
pos_can_be_skipped[minetest.hash_node_position(f.pos)] = true
|
||||||
|
elseif mesecon.is_conductor(node.name) then
|
||||||
local rules = mesecon.conductor_get_rules(node)
|
local rules = mesecon.conductor_get_rules(node)
|
||||||
for _, r in ipairs(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,
|
if mesecon.is_conductor_on(node, f.link) then
|
||||||
-- abort this turnoff process by returning false. `receptor_off` will
|
for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do
|
||||||
-- discard all the changes that we made in the voxelmanip:
|
local np = vector.add(f.pos, r)
|
||||||
for _, l in ipairs(mesecon.rules_link_rule_all_inverted(f.pos, r)) do
|
|
||||||
if mesecon.is_receptor_on(mesecon.get_node_force(np).name) then
|
if not pos_can_be_skipped[minetest.hash_node_position(np)] then
|
||||||
return false
|
-- 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:
|
||||||
|
if mesecon.rules_link_rule_all_inverted(f.pos, r)[1] then
|
||||||
|
if mesecon.is_receptor_on(mesecon.get_node_force(np).name) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Call turnoff on neighbors
|
||||||
|
for _, l in ipairs(mesecon.rules_link_rule_all(f.pos, r)) do
|
||||||
|
frontiers:add({pos = np, link = l})
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Call turnoff on neighbors
|
mesecon.swap_node_force(f.pos, mesecon.get_conductor_off(node, f.link), get_update_light_conductor)
|
||||||
for _, l in ipairs(mesecon.rules_link_rule_all(f.pos, r)) do
|
|
||||||
table.insert(frontiers, {pos = np, link = l})
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
mesecon.swap_node_force(f.pos, mesecon.get_conductor_off(node, f.link))
|
-- Only conductors with flat rules can be reliably skipped later
|
||||||
|
if not rules[1] or rules[1].x then
|
||||||
|
pos_can_be_skipped[minetest.hash_node_position(f.pos)] = true
|
||||||
|
end
|
||||||
elseif mesecon.is_effector(node.name) then
|
elseif mesecon.is_effector(node.name) then
|
||||||
table.insert(signals, {
|
table.insert(signals, {
|
||||||
pos = f.pos,
|
pos = f.pos,
|
||||||
@ -457,6 +541,8 @@ function mesecon.turnoff(pos, link)
|
|||||||
link = f.link,
|
link = f.link,
|
||||||
depth = depth
|
depth = depth
|
||||||
})
|
})
|
||||||
|
else
|
||||||
|
pos_can_be_skipped[minetest.hash_node_position(f.pos)] = true
|
||||||
end
|
end
|
||||||
depth = depth + 1
|
depth = depth + 1
|
||||||
end
|
end
|
||||||
|
@ -16,9 +16,9 @@ mesecon.rules.default = {
|
|||||||
{x = 0, y = -1, z = -1},
|
{x = 0, y = -1, z = -1},
|
||||||
}
|
}
|
||||||
|
|
||||||
mesecon.rules.floor = mesecon.mergetable(mesecon.rules.default, {{x = 0, y = -1, z = 0}})
|
mesecon.rules.floor = mesecon.merge_rule_sets(mesecon.rules.default, {{x = 0, y = -1, z = 0}})
|
||||||
|
|
||||||
mesecon.rules.pplate = mesecon.mergetable(mesecon.rules.floor, {{x = 0, y = -2, z = 0}})
|
mesecon.rules.pplate = mesecon.merge_rule_sets(mesecon.rules.floor, {{x = 0, y = -2, z = 0}})
|
||||||
|
|
||||||
mesecon.rules.buttonlike = {
|
mesecon.rules.buttonlike = {
|
||||||
{x = 1, y = 0, z = 0},
|
{x = 1, y = 0, z = 0},
|
||||||
|
@ -16,7 +16,7 @@ mesecon.on_placenode = function(pos, node)
|
|||||||
-- also call receptor_on if itself is powered already, so that neighboring
|
-- also call receptor_on if itself is powered already, so that neighboring
|
||||||
-- conductors will be activated (when pushing an on-conductor with a piston)
|
-- conductors will be activated (when pushing an on-conductor with a piston)
|
||||||
for _, s in ipairs(sources) do
|
for _, s in ipairs(sources) do
|
||||||
local rule = vector.subtract(pos, s)
|
local rule = vector.subtract(s, pos)
|
||||||
mesecon.turnon(pos, rule)
|
mesecon.turnon(pos, rule)
|
||||||
end
|
end
|
||||||
--mesecon.receptor_on (pos, mesecon.conductor_get_rules(node))
|
--mesecon.receptor_on (pos, mesecon.conductor_get_rules(node))
|
||||||
|
@ -164,7 +164,9 @@ end
|
|||||||
|
|
||||||
function mesecon.get_bit(binary,bit)
|
function mesecon.get_bit(binary,bit)
|
||||||
bit = bit or 1
|
bit = bit or 1
|
||||||
local c = binary:len()-(bit-1)
|
local len = binary:len()
|
||||||
|
if bit > len then return false end
|
||||||
|
local c = len-(bit-1)
|
||||||
return binary:sub(c,c) == "1"
|
return binary:sub(c,c) == "1"
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -213,8 +215,9 @@ function mesecon.cmpAny(t1, t2)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- does not overwrite values; number keys (ipairs) are appended, not overwritten
|
-- Deprecated. Use `merge_tables` or `merge_rule_sets` as appropriate.
|
||||||
function mesecon.mergetable(source, dest)
|
function mesecon.mergetable(source, dest)
|
||||||
|
minetest.log("warning", debug.traceback("Deprecated call to mesecon.mergetable"))
|
||||||
local rval = mesecon.tablecopy(dest)
|
local rval = mesecon.tablecopy(dest)
|
||||||
|
|
||||||
for k, v in pairs(source) do
|
for k, v in pairs(source) do
|
||||||
@ -227,6 +230,32 @@ function mesecon.mergetable(source, dest)
|
|||||||
return rval
|
return rval
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Merges several rule sets in one. Order may not be preserved. Nil arguments
|
||||||
|
-- are ignored.
|
||||||
|
-- The rule sets must be of the same kind (either all single-level or all two-level).
|
||||||
|
-- The function may be changed to normalize the resulting set in some way.
|
||||||
|
function mesecon.merge_rule_sets(...)
|
||||||
|
local rval = {}
|
||||||
|
for _, t in pairs({...}) do -- ignores nils automatically
|
||||||
|
table.insert_all(rval, mesecon.tablecopy(t))
|
||||||
|
end
|
||||||
|
return rval
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Merges two tables, with entries from `replacements` taking precedence over
|
||||||
|
-- those from `base`. Returns the new table.
|
||||||
|
-- Values are deep-copied from either table, keys are referenced.
|
||||||
|
-- Numerical indices aren’t handled specially.
|
||||||
|
function mesecon.merge_tables(base, replacements)
|
||||||
|
local ret = mesecon.tablecopy(replacements) -- these are never overriden so have to be copied in any case
|
||||||
|
for k, v in pairs(base) do
|
||||||
|
if ret[k] == nil then -- it could be `false`
|
||||||
|
ret[k] = mesecon.tablecopy(v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
function mesecon.register_node(name, spec_common, spec_off, spec_on)
|
function mesecon.register_node(name, spec_common, spec_off, spec_on)
|
||||||
spec_common.drop = spec_common.drop or name .. "_off"
|
spec_common.drop = spec_common.drop or name .. "_off"
|
||||||
spec_common.on_blast = spec_common.on_blast or mesecon.on_blastnode
|
spec_common.on_blast = spec_common.on_blast or mesecon.on_blastnode
|
||||||
@ -234,8 +263,8 @@ function mesecon.register_node(name, spec_common, spec_off, spec_on)
|
|||||||
spec_on.__mesecon_state = "on"
|
spec_on.__mesecon_state = "on"
|
||||||
spec_off.__mesecon_state = "off"
|
spec_off.__mesecon_state = "off"
|
||||||
|
|
||||||
spec_on = mesecon.mergetable(spec_common, spec_on);
|
spec_on = mesecon.merge_tables(spec_common, spec_on);
|
||||||
spec_off = mesecon.mergetable(spec_common, spec_off);
|
spec_off = mesecon.merge_tables(spec_common, spec_off);
|
||||||
|
|
||||||
minetest.register_node(name .. "_on", spec_on)
|
minetest.register_node(name .. "_on", spec_on)
|
||||||
minetest.register_node(name .. "_off", spec_off)
|
minetest.register_node(name .. "_off", spec_off)
|
||||||
@ -314,7 +343,7 @@ function mesecon.vm_commit()
|
|||||||
if tbl.dirty then
|
if tbl.dirty then
|
||||||
local vm = tbl.vm
|
local vm = tbl.vm
|
||||||
vm:set_data(tbl.data)
|
vm:set_data(tbl.data)
|
||||||
vm:write_to_map()
|
vm:write_to_map(tbl.update_light)
|
||||||
vm:update_map()
|
vm:update_map()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -335,7 +364,7 @@ local function vm_get_or_create_entry(pos)
|
|||||||
local vm = minetest.get_voxel_manip(pos, pos)
|
local vm = minetest.get_voxel_manip(pos, pos)
|
||||||
local min_pos, max_pos = vm:get_emerged_area()
|
local min_pos, max_pos = vm:get_emerged_area()
|
||||||
local va = VoxelArea:new{MinEdge = min_pos, MaxEdge = max_pos}
|
local va = VoxelArea:new{MinEdge = min_pos, MaxEdge = max_pos}
|
||||||
tbl = {vm = vm, va = va, data = vm:get_data(), param1 = vm:get_light_data(), param2 = vm:get_param2_data(), dirty = false}
|
tbl = {vm = vm, va = va, data = vm:get_data(), param1 = vm:get_light_data(), param2 = vm:get_param2_data(), dirty = false, update_light = false}
|
||||||
vm_cache[hash] = tbl
|
vm_cache[hash] = tbl
|
||||||
end
|
end
|
||||||
return tbl
|
return tbl
|
||||||
@ -359,8 +388,11 @@ end
|
|||||||
-- Sets a node’s name during a VoxelManipulator-based transaction.
|
-- Sets a node’s name during a VoxelManipulator-based transaction.
|
||||||
--
|
--
|
||||||
-- Existing param1, param2, and metadata are left alone.
|
-- Existing param1, param2, and metadata are left alone.
|
||||||
function mesecon.vm_swap_node(pos, name)
|
--
|
||||||
|
-- See mesecon.swap_node_force for documentation about get_update_light.
|
||||||
|
function mesecon.vm_swap_node(pos, name, get_update_light)
|
||||||
local tbl = vm_get_or_create_entry(pos)
|
local tbl = vm_get_or_create_entry(pos)
|
||||||
|
tbl.update_light = tbl.update_light or (get_update_light == nil or get_update_light(pos, name))
|
||||||
local index = tbl.va:indexp(pos)
|
local index = tbl.va:indexp(pos)
|
||||||
tbl.data[index] = minetest.get_content_id(name)
|
tbl.data[index] = minetest.get_content_id(name)
|
||||||
tbl.dirty = true
|
tbl.dirty = true
|
||||||
@ -394,13 +426,15 @@ end
|
|||||||
-- Outside a VM transaction, if the mapblock is not loaded, it is pulled into
|
-- Outside a VM transaction, if the mapblock is not loaded, it is pulled into
|
||||||
-- the server’s main map data cache and then accessed from there.
|
-- the server’s main map data cache and then accessed from there.
|
||||||
--
|
--
|
||||||
-- Inside a VM transaction, the transaction’s VM cache is used.
|
-- Inside a VM transaction, the transaction’s VM cache is used. If a third
|
||||||
|
-- argument is supplied, it may be called. If it returns false, the swap does
|
||||||
|
-- not necessitate a lighting update.
|
||||||
--
|
--
|
||||||
-- This function can only be used to change the node’s name, not its parameters
|
-- This function can only be used to change the node’s name, not its parameters
|
||||||
-- or metadata.
|
-- or metadata.
|
||||||
function mesecon.swap_node_force(pos, name)
|
function mesecon.swap_node_force(pos, name, get_update_light)
|
||||||
if vm_cache then
|
if vm_cache then
|
||||||
return mesecon.vm_swap_node(pos, name)
|
return mesecon.vm_swap_node(pos, name, get_update_light)
|
||||||
else
|
else
|
||||||
-- This serves to both ensure the mapblock is loaded and also hand us
|
-- This serves to both ensure the mapblock is loaded and also hand us
|
||||||
-- the old node table so we can preserve param2.
|
-- the old node table so we can preserve param2.
|
||||||
|
@ -32,7 +32,13 @@ mesecon.register_node("mesecons_blinkyplant:blinky_plant", {
|
|||||||
fixed = {-0.3, -0.5, -0.3, 0.3, -0.5+0.7, 0.3},
|
fixed = {-0.3, -0.5, -0.3, 0.3, -0.5+0.7, 0.3},
|
||||||
},
|
},
|
||||||
on_timer = on_timer,
|
on_timer = on_timer,
|
||||||
on_rightclick = toggle_timer,
|
on_rightclick = function(pos, node, clicker)
|
||||||
|
if minetest.is_protected(pos, clicker and clicker:get_player_name() or "") then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
toggle_timer(pos)
|
||||||
|
end,
|
||||||
on_construct = toggle_timer
|
on_construct = toggle_timer
|
||||||
},{
|
},{
|
||||||
tiles = {"jeija_blinky_plant_off.png"},
|
tiles = {"jeija_blinky_plant_off.png"},
|
||||||
|
@ -13,16 +13,19 @@ mesecon.button_turnoff = function (pos)
|
|||||||
mesecon.receptor_off(pos, rules)
|
mesecon.receptor_off(pos, rules)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or nil
|
||||||
|
|
||||||
minetest.register_node("mesecons_button:button_off", {
|
minetest.register_node("mesecons_button:button_off", {
|
||||||
drawtype = "nodebox",
|
drawtype = "nodebox",
|
||||||
tiles = {
|
tiles = {
|
||||||
"jeija_wall_button_sides.png",
|
"jeija_wall_button_sides.png",
|
||||||
"jeija_wall_button_sides.png",
|
"jeija_wall_button_sides.png",
|
||||||
"jeija_wall_button_sides.png",
|
"jeija_wall_button_sides.png",
|
||||||
"jeija_wall_button_sides.png",
|
"jeija_wall_button_sides.png",
|
||||||
"jeija_wall_button_sides.png",
|
"jeija_wall_button_sides.png",
|
||||||
"jeija_wall_button_off.png"
|
"jeija_wall_button_off.png"
|
||||||
},
|
},
|
||||||
|
use_texture_alpha = use_texture_alpha,
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
paramtype2 = "facedir",
|
paramtype2 = "facedir",
|
||||||
is_ground_content = false,
|
is_ground_content = false,
|
||||||
@ -66,7 +69,8 @@ minetest.register_node("mesecons_button:button_on", {
|
|||||||
"jeija_wall_button_sides.png",
|
"jeija_wall_button_sides.png",
|
||||||
"jeija_wall_button_sides.png",
|
"jeija_wall_button_sides.png",
|
||||||
"jeija_wall_button_on.png"
|
"jeija_wall_button_on.png"
|
||||||
},
|
},
|
||||||
|
use_texture_alpha = use_texture_alpha,
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
paramtype2 = "facedir",
|
paramtype2 = "facedir",
|
||||||
is_ground_content = false,
|
is_ground_content = false,
|
||||||
|
@ -10,6 +10,7 @@ minetest.register_chatcommand("say", {
|
|||||||
minetest.register_chatcommand("tell", {
|
minetest.register_chatcommand("tell", {
|
||||||
params = "<name> <text>",
|
params = "<name> <text>",
|
||||||
description = "Say <text> to <name> privately",
|
description = "Say <text> to <name> privately",
|
||||||
|
privs = {shout=true},
|
||||||
func = function(name, param)
|
func = function(name, param)
|
||||||
local found, _, target, message = param:find("^([^%s]+)%s+(.*)$")
|
local found, _, target, message = param:find("^([^%s]+)%s+(.*)$")
|
||||||
if found == nil then
|
if found == nil then
|
||||||
|
@ -54,6 +54,7 @@ local boxes = {
|
|||||||
-- Delayer definition defaults
|
-- Delayer definition defaults
|
||||||
local def = {
|
local def = {
|
||||||
drawtype = "nodebox",
|
drawtype = "nodebox",
|
||||||
|
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or nil,
|
||||||
walkable = true,
|
walkable = true,
|
||||||
selection_box = {
|
selection_box = {
|
||||||
type = "fixed",
|
type = "fixed",
|
||||||
@ -93,7 +94,7 @@ local off_state = {
|
|||||||
wield_image = "mesecons_delayer_off_1.png",
|
wield_image = "mesecons_delayer_off_1.png",
|
||||||
groups = off_groups,
|
groups = off_groups,
|
||||||
on_punch = function(pos, node, puncher)
|
on_punch = function(pos, node, puncher)
|
||||||
if minetest.is_protected(pos, puncher and puncher:get_player_name()) then
|
if minetest.is_protected(pos, puncher and puncher:get_player_name() or "") then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -134,7 +135,7 @@ local on_state = {
|
|||||||
},
|
},
|
||||||
groups = {bendy = 2, snappy = 1, dig_immediate = 2, not_in_creative_inventory = 1},
|
groups = {bendy = 2, snappy = 1, dig_immediate = 2, not_in_creative_inventory = 1},
|
||||||
on_punch = function(pos, node, puncher)
|
on_punch = function(pos, node, puncher)
|
||||||
if minetest.is_protected(pos, puncher and puncher:get_player_name()) then
|
if minetest.is_protected(pos, puncher and puncher:get_player_name() or "") then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -30,7 +30,6 @@ minetest.register_node("mesecons_extrawires:corner_on", {
|
|||||||
walkable = false,
|
walkable = false,
|
||||||
sunlight_propagates = true,
|
sunlight_propagates = true,
|
||||||
selection_box = corner_selectionbox,
|
selection_box = corner_selectionbox,
|
||||||
node_box = corner_nodebox,
|
|
||||||
groups = {dig_immediate = 3, not_in_creative_inventory = 1},
|
groups = {dig_immediate = 3, not_in_creative_inventory = 1},
|
||||||
drop = "mesecons_extrawires:corner_off",
|
drop = "mesecons_extrawires:corner_off",
|
||||||
sounds = default.node_sound_defaults(),
|
sounds = default.node_sound_defaults(),
|
||||||
@ -58,7 +57,6 @@ minetest.register_node("mesecons_extrawires:corner_off", {
|
|||||||
walkable = false,
|
walkable = false,
|
||||||
sunlight_propagates = true,
|
sunlight_propagates = true,
|
||||||
selection_box = corner_selectionbox,
|
selection_box = corner_selectionbox,
|
||||||
node_box = corner_nodebox,
|
|
||||||
groups = {dig_immediate = 3},
|
groups = {dig_immediate = 3},
|
||||||
sounds = default.node_sound_defaults(),
|
sounds = default.node_sound_defaults(),
|
||||||
mesecons = {conductor =
|
mesecons = {conductor =
|
||||||
|
@ -18,7 +18,7 @@ minetest.override_item("default:mese", {
|
|||||||
|
|
||||||
-- Copy node definition of powered mese from normal mese
|
-- Copy node definition of powered mese from normal mese
|
||||||
-- and brighten texture tiles to indicate mese is powered
|
-- and brighten texture tiles to indicate mese is powered
|
||||||
local powered_def = mesecon.mergetable(minetest.registered_nodes["default:mese"], {
|
local powered_def = mesecon.merge_tables(minetest.registered_nodes["default:mese"], {
|
||||||
drop = "default:mese",
|
drop = "default:mese",
|
||||||
light_source = 5,
|
light_source = 5,
|
||||||
mesecons = {conductor = {
|
mesecons = {conductor = {
|
||||||
|
@ -175,9 +175,9 @@ mesecon.register_node("mesecons_extrawires:vertical_bottom", {
|
|||||||
minetest.register_craft({
|
minetest.register_craft({
|
||||||
output = "mesecons_extrawires:vertical_off 3",
|
output = "mesecons_extrawires:vertical_off 3",
|
||||||
recipe = {
|
recipe = {
|
||||||
{"mesecons:wire_00000000_off"},
|
{"group:mesecon_conductor_craftable"},
|
||||||
{"mesecons:wire_00000000_off"},
|
{"group:mesecon_conductor_craftable"},
|
||||||
{"mesecons:wire_00000000_off"}
|
{"group:mesecon_conductor_craftable"},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ minetest.register_node("mesecons_hydroturbine:hydro_turbine_off", {
|
|||||||
"jeija_hydro_turbine_turbine_top_bottom_off.png",
|
"jeija_hydro_turbine_turbine_top_bottom_off.png",
|
||||||
"jeija_hydro_turbine_turbine_misc_off.png"
|
"jeija_hydro_turbine_turbine_misc_off.png"
|
||||||
},
|
},
|
||||||
|
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or nil,
|
||||||
inventory_image = "jeija_hydro_turbine_inv.png",
|
inventory_image = "jeija_hydro_turbine_inv.png",
|
||||||
is_ground_content = false,
|
is_ground_content = false,
|
||||||
wield_scale = {x=0.75, y=0.75, z=0.75},
|
wield_scale = {x=0.75, y=0.75, z=0.75},
|
||||||
@ -42,6 +43,7 @@ minetest.register_node("mesecons_hydroturbine:hydro_turbine_on", {
|
|||||||
{ name = "jeija_hydro_turbine_turbine_misc_on.png",
|
{ name = "jeija_hydro_turbine_turbine_misc_on.png",
|
||||||
animation = {type = "vertical_frames", aspect_w = 256, aspect_h = 32, length = 0.4} }
|
animation = {type = "vertical_frames", aspect_w = 256, aspect_h = 32, length = 0.4} }
|
||||||
},
|
},
|
||||||
|
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "clip" or nil,
|
||||||
inventory_image = "jeija_hydro_turbine_inv.png",
|
inventory_image = "jeija_hydro_turbine_inv.png",
|
||||||
drop = "mesecons_hydroturbine:hydro_turbine_off 1",
|
drop = "mesecons_hydroturbine:hydro_turbine_off 1",
|
||||||
groups = {dig_immediate=2,not_in_creative_inventory=1},
|
groups = {dig_immediate=2,not_in_creative_inventory=1},
|
||||||
|
@ -86,7 +86,7 @@ minetest.register_craft({
|
|||||||
output = "mesecons_insulated:insulated_off 3",
|
output = "mesecons_insulated:insulated_off 3",
|
||||||
recipe = {
|
recipe = {
|
||||||
{"mesecons_materials:fiber", "mesecons_materials:fiber", "mesecons_materials:fiber"},
|
{"mesecons_materials:fiber", "mesecons_materials:fiber", "mesecons_materials:fiber"},
|
||||||
{"mesecons:wire_00000000_off", "mesecons:wire_00000000_off", "mesecons:wire_00000000_off"},
|
{"group:mesecon_conductor_craftable", "group:mesecon_conductor_craftable", "group:mesecon_conductor_craftable"},
|
||||||
{"mesecons_materials:fiber", "mesecons_materials:fiber", "mesecons_materials:fiber"},
|
{"mesecons_materials:fiber", "mesecons_materials:fiber", "mesecons_materials:fiber"},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -9,9 +9,12 @@ local mesecon_lamp_box = {
|
|||||||
wall_side = {-0.375,-0.3125,-0.3125,-0.5,0.3125,0.3125},
|
wall_side = {-0.375,-0.3125,-0.3125,-0.5,0.3125,0.3125},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or nil
|
||||||
|
|
||||||
minetest.register_node("mesecons_lamp:lamp_on", {
|
minetest.register_node("mesecons_lamp:lamp_on", {
|
||||||
drawtype = "nodebox",
|
drawtype = "nodebox",
|
||||||
tiles = {"jeija_meselamp_on.png"},
|
tiles = {"jeija_meselamp_on.png"},
|
||||||
|
use_texture_alpha = use_texture_alpha,
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
paramtype2 = "wallmounted",
|
paramtype2 = "wallmounted",
|
||||||
is_ground_content = false,
|
is_ground_content = false,
|
||||||
@ -36,6 +39,7 @@ minetest.register_node("mesecons_lamp:lamp_on", {
|
|||||||
minetest.register_node("mesecons_lamp:lamp_off", {
|
minetest.register_node("mesecons_lamp:lamp_off", {
|
||||||
drawtype = "nodebox",
|
drawtype = "nodebox",
|
||||||
tiles = {"jeija_meselamp_off.png"},
|
tiles = {"jeija_meselamp_off.png"},
|
||||||
|
use_texture_alpha = use_texture_alpha,
|
||||||
inventory_image = "jeija_meselamp.png",
|
inventory_image = "jeija_meselamp.png",
|
||||||
wield_image = "jeija_meselamp.png",
|
wield_image = "jeija_meselamp.png",
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
|
@ -29,9 +29,6 @@ function mesecon.is_mvps_stopper(node, pushdir, stack, stackid)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function mesecon.register_mvps_stopper(nodename, get_stopper)
|
function mesecon.register_mvps_stopper(nodename, get_stopper)
|
||||||
if minetest.registered_nodes[nodename] and minetest.registered_nodes[nodename].buildable_to then
|
|
||||||
minetest.log("warning", ("Registering a buildable-to node \"%s\" as a mesecon stopper, this is not supported"):format(nodename))
|
|
||||||
end
|
|
||||||
if get_stopper == nil then
|
if get_stopper == nil then
|
||||||
get_stopper = true
|
get_stopper = true
|
||||||
end
|
end
|
||||||
@ -74,10 +71,6 @@ function mesecon.mvps_get_stack(pos, dir, maximum, all_pull_sticky)
|
|||||||
local np = frontiers[1]
|
local np = frontiers[1]
|
||||||
local nn = minetest.get_node(np)
|
local nn = minetest.get_node(np)
|
||||||
|
|
||||||
-- Never push into unloaded blocks. Don’t try to pull from them, either.
|
|
||||||
-- TODO: load blocks instead, as with wires.
|
|
||||||
if nn.name == "ignore" then return nil end
|
|
||||||
|
|
||||||
if not node_replaceable(nn.name) then
|
if not node_replaceable(nn.name) then
|
||||||
table.insert(nodes, {node = nn, pos = np})
|
table.insert(nodes, {node = nn, pos = np})
|
||||||
if #nodes > maximum then return nil end
|
if #nodes > maximum then return nil end
|
||||||
@ -334,6 +327,10 @@ function mesecon.mvps_move_objects(pos, dir, nodestack, movefactor)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Never push into unloaded blocks. Don’t try to pull from them, either.
|
||||||
|
-- TODO: load blocks instead, as with wires.
|
||||||
|
mesecon.register_mvps_stopper("ignore")
|
||||||
|
|
||||||
mesecon.register_mvps_stopper("doors:door_steel_b_1")
|
mesecon.register_mvps_stopper("doors:door_steel_b_1")
|
||||||
mesecon.register_mvps_stopper("doors:door_steel_t_1")
|
mesecon.register_mvps_stopper("doors:door_steel_t_1")
|
||||||
mesecon.register_mvps_stopper("doors:door_steel_b_2")
|
mesecon.register_mvps_stopper("doors:door_steel_b_2")
|
||||||
|
@ -3,7 +3,11 @@ minetest.register_node("mesecons_noteblock:noteblock", {
|
|||||||
tiles = {"mesecons_noteblock.png"},
|
tiles = {"mesecons_noteblock.png"},
|
||||||
is_ground_content = false,
|
is_ground_content = false,
|
||||||
groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2},
|
groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2},
|
||||||
on_punch = function(pos, node) -- change sound when punched
|
on_punch = function(pos, node, puncher) -- change sound when punched
|
||||||
|
if minetest.is_protected(pos, puncher and puncher:get_player_name() or "") then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
node.param2 = (node.param2+1)%12
|
node.param2 = (node.param2+1)%12
|
||||||
mesecon.noteblock_play(pos, node.param2)
|
mesecon.noteblock_play(pos, node.param2)
|
||||||
minetest.set_node(pos, node)
|
minetest.set_node(pos, node)
|
||||||
|
@ -195,10 +195,11 @@ local function register_wires()
|
|||||||
}}
|
}}
|
||||||
|
|
||||||
local groups_on = {dig_immediate = 3, mesecon_conductor_craftable = 1,
|
local groups_on = {dig_immediate = 3, mesecon_conductor_craftable = 1,
|
||||||
not_in_creative_inventory = 1}
|
not_in_creative_inventory = 1, not_in_craft_guide = 1}
|
||||||
local groups_off = {dig_immediate = 3, mesecon_conductor_craftable = 1}
|
local groups_off = {dig_immediate = 3, mesecon_conductor_craftable = 1}
|
||||||
if nodeid ~= "00000000" then
|
if nodeid ~= "00000000" then
|
||||||
groups_off["not_in_creative_inventory"] = 1
|
groups_off["not_in_creative_inventory"] = 1
|
||||||
|
groups_off["not_in_craft_guide"] = 1
|
||||||
end
|
end
|
||||||
|
|
||||||
mesecon.register_node(":mesecons:wire_"..nodeid, {
|
mesecon.register_node(":mesecons:wire_"..nodeid, {
|
||||||
|
Reference in New Issue
Block a user