2014-11-22 15:42:22 +01:00
|
|
|
|
function mesecon.move_node(pos, newpos)
|
2013-12-01 04:13:00 +01:00
|
|
|
|
local node = minetest.get_node(pos)
|
|
|
|
|
local meta = minetest.get_meta(pos):to_table()
|
|
|
|
|
minetest.remove_node(pos)
|
2016-02-14 21:00:37 +01:00
|
|
|
|
minetest.set_node(newpos, node)
|
2013-12-01 04:13:00 +01:00
|
|
|
|
minetest.get_meta(pos):from_table(meta)
|
2012-12-16 11:58:43 +01:00
|
|
|
|
end
|
|
|
|
|
|
2017-10-08 01:39:02 +02:00
|
|
|
|
-- Rules rotation Functions:
|
|
|
|
|
function mesecon.rotate_rules_right(rules)
|
|
|
|
|
local nr = {}
|
|
|
|
|
for i, rule in ipairs(rules) do
|
|
|
|
|
table.insert(nr, {
|
|
|
|
|
x = -rule.z,
|
|
|
|
|
y = rule.y,
|
|
|
|
|
z = rule.x,
|
|
|
|
|
name = rule.name})
|
|
|
|
|
end
|
|
|
|
|
return nr
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function mesecon.rotate_rules_left(rules)
|
|
|
|
|
local nr = {}
|
|
|
|
|
for i, rule in ipairs(rules) do
|
|
|
|
|
table.insert(nr, {
|
|
|
|
|
x = rule.z,
|
|
|
|
|
y = rule.y,
|
|
|
|
|
z = -rule.x,
|
|
|
|
|
name = rule.name})
|
|
|
|
|
end
|
|
|
|
|
return nr
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function mesecon.rotate_rules_down(rules)
|
|
|
|
|
local nr = {}
|
|
|
|
|
for i, rule in ipairs(rules) do
|
|
|
|
|
table.insert(nr, {
|
|
|
|
|
x = -rule.y,
|
|
|
|
|
y = rule.x,
|
|
|
|
|
z = rule.z,
|
|
|
|
|
name = rule.name})
|
|
|
|
|
end
|
|
|
|
|
return nr
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function mesecon.rotate_rules_up(rules)
|
|
|
|
|
local nr = {}
|
|
|
|
|
for i, rule in ipairs(rules) do
|
|
|
|
|
table.insert(nr, {
|
|
|
|
|
x = rule.y,
|
|
|
|
|
y = -rule.x,
|
|
|
|
|
z = rule.z,
|
|
|
|
|
name = rule.name})
|
|
|
|
|
end
|
|
|
|
|
return nr
|
|
|
|
|
end
|
|
|
|
|
--
|
|
|
|
|
|
2014-11-22 15:42:22 +01:00
|
|
|
|
function mesecon.flattenrules(allrules)
|
2013-06-20 04:38:34 +02:00
|
|
|
|
--[[
|
|
|
|
|
{
|
|
|
|
|
{
|
|
|
|
|
{xyz},
|
|
|
|
|
{xyz},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
{xyz},
|
|
|
|
|
{xyz},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
--]]
|
|
|
|
|
if allrules[1] and
|
|
|
|
|
allrules[1].x then
|
|
|
|
|
return allrules
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local shallowrules = {}
|
|
|
|
|
for _, metarule in ipairs( allrules) do
|
|
|
|
|
for _, rule in ipairs(metarule ) do
|
|
|
|
|
table.insert(shallowrules, rule)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
return shallowrules
|
|
|
|
|
--[[
|
|
|
|
|
{
|
|
|
|
|
{xyz},
|
|
|
|
|
{xyz},
|
|
|
|
|
{xyz},
|
|
|
|
|
{xyz},
|
|
|
|
|
}
|
|
|
|
|
--]]
|
|
|
|
|
end
|
|
|
|
|
|
2014-11-22 15:42:22 +01:00
|
|
|
|
function mesecon.rule2bit(findrule, allrules)
|
2013-06-20 04:38:34 +02:00
|
|
|
|
--get the bit of the metarule the rule is in, or bit 1
|
|
|
|
|
if (allrules[1] and
|
|
|
|
|
allrules[1].x) or
|
|
|
|
|
not findrule then
|
|
|
|
|
return 1
|
|
|
|
|
end
|
|
|
|
|
for m,metarule in ipairs( allrules) do
|
|
|
|
|
for _, rule in ipairs(metarule ) do
|
2016-02-14 20:55:50 +01:00
|
|
|
|
if vector.equals(findrule, rule) then
|
2013-06-20 04:38:34 +02:00
|
|
|
|
return m
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2014-11-22 15:42:22 +01:00
|
|
|
|
function mesecon.rule2metaindex(findrule, allrules)
|
2013-06-20 04:38:34 +02:00
|
|
|
|
--get the metarule the rule is in, or allrules
|
|
|
|
|
if allrules[1].x then
|
2014-01-04 15:52:52 +01:00
|
|
|
|
return nil
|
2013-06-20 04:38:34 +02:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if not(findrule) then
|
2014-11-22 15:42:22 +01:00
|
|
|
|
return mesecon.flattenrules(allrules)
|
2013-06-20 04:38:34 +02:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
for m, metarule in ipairs( allrules) do
|
|
|
|
|
for _, rule in ipairs(metarule ) do
|
2016-02-14 20:55:50 +01:00
|
|
|
|
if vector.equals(findrule, rule) then
|
2014-01-04 15:52:52 +01:00
|
|
|
|
return m
|
2013-06-20 04:38:34 +02:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2014-11-22 15:42:22 +01:00
|
|
|
|
function mesecon.rule2meta(findrule, allrules)
|
2015-01-03 09:57:46 +01:00
|
|
|
|
if #allrules == 0 then return {} end
|
|
|
|
|
|
2014-11-22 15:42:22 +01:00
|
|
|
|
local index = mesecon.rule2metaindex(findrule, allrules)
|
2014-01-04 16:51:52 +01:00
|
|
|
|
if index == nil then
|
|
|
|
|
if allrules[1].x then
|
|
|
|
|
return allrules
|
|
|
|
|
else
|
|
|
|
|
return {}
|
|
|
|
|
end
|
|
|
|
|
end
|
2014-01-04 15:52:52 +01:00
|
|
|
|
return allrules[index]
|
|
|
|
|
end
|
|
|
|
|
|
2014-12-20 10:11:12 +01:00
|
|
|
|
function mesecon.dec2bin(n)
|
|
|
|
|
local x, y = math.floor(n / 2), n % 2
|
|
|
|
|
if (n > 1) then
|
|
|
|
|
return mesecon.dec2bin(x)..y
|
|
|
|
|
else
|
|
|
|
|
return ""..y
|
2013-06-20 04:38:34 +02:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2014-11-22 15:42:22 +01:00
|
|
|
|
function mesecon.getstate(nodename, states)
|
2013-06-20 04:38:34 +02:00
|
|
|
|
for state, name in ipairs(states) do
|
|
|
|
|
if name == nodename then
|
|
|
|
|
return state
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
error(nodename.." doesn't mention itself in "..dump(states))
|
|
|
|
|
end
|
|
|
|
|
|
2014-11-22 15:42:22 +01:00
|
|
|
|
function mesecon.getbinstate(nodename, states)
|
2014-12-20 10:11:12 +01:00
|
|
|
|
return mesecon.dec2bin(mesecon.getstate(nodename, states)-1)
|
2013-06-20 04:38:34 +02:00
|
|
|
|
end
|
|
|
|
|
|
2014-11-22 15:42:22 +01:00
|
|
|
|
function mesecon.get_bit(binary,bit)
|
2013-06-20 04:38:34 +02:00
|
|
|
|
bit = bit or 1
|
2021-08-02 21:33:45 +02:00
|
|
|
|
local len = binary:len()
|
|
|
|
|
if bit > len then return false end
|
|
|
|
|
local c = len-(bit-1)
|
2013-06-20 04:38:34 +02:00
|
|
|
|
return binary:sub(c,c) == "1"
|
|
|
|
|
end
|
|
|
|
|
|
2014-11-22 15:42:22 +01:00
|
|
|
|
function mesecon.set_bit(binary,bit,value)
|
2013-06-20 04:38:34 +02:00
|
|
|
|
if value == "1" then
|
2014-11-22 15:42:22 +01:00
|
|
|
|
if not mesecon.get_bit(binary,bit) then
|
2014-12-20 10:11:12 +01:00
|
|
|
|
return mesecon.dec2bin(tonumber(binary,2)+math.pow(2,bit-1))
|
2013-06-20 04:38:34 +02:00
|
|
|
|
end
|
|
|
|
|
elseif value == "0" then
|
2014-11-22 15:42:22 +01:00
|
|
|
|
if mesecon.get_bit(binary,bit) then
|
2014-12-20 10:11:12 +01:00
|
|
|
|
return mesecon.dec2bin(tonumber(binary,2)-math.pow(2,bit-1))
|
2013-06-20 04:38:34 +02:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
return binary
|
2015-10-04 13:30:34 +02:00
|
|
|
|
|
2013-06-20 04:38:34 +02:00
|
|
|
|
end
|
|
|
|
|
|
2014-11-22 15:42:22 +01:00
|
|
|
|
function mesecon.invertRule(r)
|
2016-02-14 20:55:50 +01:00
|
|
|
|
return vector.multiply(r, -1)
|
2012-12-08 21:56:09 +01:00
|
|
|
|
end
|
2013-04-02 11:56:37 +02:00
|
|
|
|
|
2019-09-21 23:09:46 +02:00
|
|
|
|
function mesecon.tablecopy(obj) -- deep copy
|
|
|
|
|
if type(obj) == "table" then
|
|
|
|
|
return table.copy(obj)
|
2013-04-02 11:56:37 +02:00
|
|
|
|
end
|
2019-09-21 23:09:46 +02:00
|
|
|
|
return obj
|
2013-04-02 11:56:37 +02:00
|
|
|
|
end
|
2014-01-10 22:29:18 +01:00
|
|
|
|
|
2020-09-21 21:32:25 +02:00
|
|
|
|
-- Returns whether two values are equal.
|
|
|
|
|
-- In tables, keys are compared for identity but values are compared recursively.
|
|
|
|
|
-- There is no protection from infinite recursion.
|
2014-11-22 15:42:22 +01:00
|
|
|
|
function mesecon.cmpAny(t1, t2)
|
2014-01-10 22:29:18 +01:00
|
|
|
|
if type(t1) ~= type(t2) then return false end
|
2020-09-21 21:32:25 +02:00
|
|
|
|
if type(t1) ~= "table" then return t1 == t2 end
|
2014-01-10 22:29:18 +01:00
|
|
|
|
|
2020-09-21 21:32:25 +02:00
|
|
|
|
-- Check that for each key of `t1` both tables have the same value
|
2014-01-10 22:29:18 +01:00
|
|
|
|
for i, e in pairs(t1) do
|
2014-11-22 15:42:22 +01:00
|
|
|
|
if not mesecon.cmpAny(e, t2[i]) then return false end
|
2014-01-10 22:29:18 +01:00
|
|
|
|
end
|
|
|
|
|
|
2020-09-21 21:32:25 +02:00
|
|
|
|
-- Check that all keys of `t2` are also keys of `t1` so were checked in the previous loop
|
|
|
|
|
for i, _ in pairs(t2) do
|
|
|
|
|
if t1[i] == nil then return false end
|
|
|
|
|
end
|
|
|
|
|
|
2014-01-10 22:29:18 +01:00
|
|
|
|
return true
|
|
|
|
|
end
|
2014-11-22 11:37:47 +01:00
|
|
|
|
|
2020-12-19 21:12:00 +01:00
|
|
|
|
-- Deprecated. Use `merge_tables` or `merge_rule_sets` as appropriate.
|
2014-11-22 20:49:54 +01:00
|
|
|
|
function mesecon.mergetable(source, dest)
|
2020-12-19 21:12:00 +01:00
|
|
|
|
minetest.log("warning", debug.traceback("Deprecated call to mesecon.mergetable"))
|
2014-11-22 17:12:48 +01:00
|
|
|
|
local rval = mesecon.tablecopy(dest)
|
|
|
|
|
|
2014-11-22 11:37:47 +01:00
|
|
|
|
for k, v in pairs(source) do
|
2014-11-22 17:12:48 +01:00
|
|
|
|
rval[k] = dest[k] or mesecon.tablecopy(v)
|
2014-11-22 11:37:47 +01:00
|
|
|
|
end
|
2014-11-22 12:28:45 +01:00
|
|
|
|
for i, v in ipairs(source) do
|
2014-11-22 17:12:48 +01:00
|
|
|
|
table.insert(rval, mesecon.tablecopy(v))
|
2014-11-22 12:28:45 +01:00
|
|
|
|
end
|
2014-11-22 17:12:48 +01:00
|
|
|
|
|
|
|
|
|
return rval
|
2014-11-22 11:37:47 +01:00
|
|
|
|
end
|
|
|
|
|
|
2020-12-19 21:12:00 +01:00
|
|
|
|
-- 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
|
|
|
|
|
|
2014-11-22 20:49:54 +01:00
|
|
|
|
function mesecon.register_node(name, spec_common, spec_off, spec_on)
|
2014-11-22 11:37:47 +01:00
|
|
|
|
spec_common.drop = spec_common.drop or name .. "_off"
|
2017-10-07 00:44:49 +02:00
|
|
|
|
spec_common.on_blast = spec_common.on_blast or mesecon.on_blastnode
|
2014-11-22 20:49:54 +01:00
|
|
|
|
spec_common.__mesecon_basename = name
|
|
|
|
|
spec_on.__mesecon_state = "on"
|
|
|
|
|
spec_off.__mesecon_state = "off"
|
2014-11-22 11:37:47 +01:00
|
|
|
|
|
2020-12-19 21:12:00 +01:00
|
|
|
|
spec_on = mesecon.merge_tables(spec_common, spec_on);
|
|
|
|
|
spec_off = mesecon.merge_tables(spec_common, spec_off);
|
2014-11-22 11:37:47 +01:00
|
|
|
|
|
|
|
|
|
minetest.register_node(name .. "_on", spec_on)
|
|
|
|
|
minetest.register_node(name .. "_off", spec_off)
|
|
|
|
|
end
|
2014-11-22 20:49:54 +01:00
|
|
|
|
|
|
|
|
|
-- swap onstate and offstate nodes, returns new state
|
|
|
|
|
function mesecon.flipstate(pos, node)
|
|
|
|
|
local nodedef = minetest.registered_nodes[node.name]
|
|
|
|
|
local newstate
|
|
|
|
|
if (nodedef.__mesecon_state == "on") then newstate = "off" end
|
|
|
|
|
if (nodedef.__mesecon_state == "off") then newstate = "on" end
|
2015-10-04 13:30:34 +02:00
|
|
|
|
|
2014-11-22 20:49:54 +01:00
|
|
|
|
minetest.swap_node(pos, {name = nodedef.__mesecon_basename .. "_" .. newstate,
|
|
|
|
|
param2 = node.param2})
|
|
|
|
|
|
|
|
|
|
return newstate
|
|
|
|
|
end
|
2016-02-19 12:11:38 +01:00
|
|
|
|
|
|
|
|
|
-- File writing / reading utilities
|
|
|
|
|
local wpath = minetest.get_worldpath()
|
|
|
|
|
function mesecon.file2table(filename)
|
|
|
|
|
local f = io.open(wpath..DIR_DELIM..filename, "r")
|
|
|
|
|
if f == nil then return {} end
|
|
|
|
|
local t = f:read("*all")
|
|
|
|
|
f:close()
|
|
|
|
|
if t == "" or t == nil then return {} end
|
|
|
|
|
return minetest.deserialize(t)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function mesecon.table2file(filename, table)
|
|
|
|
|
local f = io.open(wpath..DIR_DELIM..filename, "w")
|
|
|
|
|
f:write(minetest.serialize(table))
|
|
|
|
|
f:close()
|
|
|
|
|
end
|
|
|
|
|
|
2016-08-30 19:32:11 +02:00
|
|
|
|
-- Block position "hashing" (convert to integer) functions for voxelmanip cache
|
2016-02-19 12:11:38 +01:00
|
|
|
|
local BLOCKSIZE = 16
|
|
|
|
|
|
|
|
|
|
-- convert node position --> block hash
|
|
|
|
|
local function hash_blockpos(pos)
|
|
|
|
|
return minetest.hash_node_position({
|
|
|
|
|
x = math.floor(pos.x/BLOCKSIZE),
|
|
|
|
|
y = math.floor(pos.y/BLOCKSIZE),
|
|
|
|
|
z = math.floor(pos.z/BLOCKSIZE)
|
|
|
|
|
})
|
|
|
|
|
end
|
|
|
|
|
|
2016-08-21 06:53:02 +02:00
|
|
|
|
-- Maps from a hashed mapblock position (as returned by hash_blockpos) to a
|
|
|
|
|
-- table.
|
|
|
|
|
--
|
|
|
|
|
-- Contents of the table are:
|
|
|
|
|
-- “vm” → the VoxelManipulator
|
|
|
|
|
-- “va” → the VoxelArea
|
|
|
|
|
-- “data” → the data array
|
|
|
|
|
-- “param1” → the param1 array
|
|
|
|
|
-- “param2” → the param2 array
|
|
|
|
|
-- “dirty” → true if data has been modified
|
|
|
|
|
--
|
|
|
|
|
-- Nil if no VM-based transaction is in progress.
|
|
|
|
|
local vm_cache = nil
|
|
|
|
|
|
|
|
|
|
-- Starts a VoxelManipulator-based transaction.
|
|
|
|
|
--
|
|
|
|
|
-- During a VM transaction, calls to vm_get_node and vm_swap_node operate on a
|
|
|
|
|
-- cached copy of the world loaded via VoxelManipulators. That cache can later
|
|
|
|
|
-- be committed to the real map by means of vm_commit or discarded by means of
|
|
|
|
|
-- vm_abort.
|
|
|
|
|
function mesecon.vm_begin()
|
|
|
|
|
vm_cache = {}
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Finishes a VoxelManipulator-based transaction, freeing the VMs and map data
|
|
|
|
|
-- and writing back any modified areas.
|
|
|
|
|
function mesecon.vm_commit()
|
|
|
|
|
for hash, tbl in pairs(vm_cache) do
|
|
|
|
|
if tbl.dirty then
|
|
|
|
|
local vm = tbl.vm
|
|
|
|
|
vm:set_data(tbl.data)
|
2021-11-27 16:28:13 +01:00
|
|
|
|
vm:write_to_map(tbl.update_light)
|
2016-08-21 06:53:02 +02:00
|
|
|
|
vm:update_map()
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
vm_cache = nil
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Finishes a VoxelManipulator-based transaction, freeing the VMs and throwing
|
|
|
|
|
-- away any modified areas.
|
|
|
|
|
function mesecon.vm_abort()
|
|
|
|
|
vm_cache = nil
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Gets the cache entry covering a position, populating it if necessary.
|
|
|
|
|
local function vm_get_or_create_entry(pos)
|
|
|
|
|
local hash = hash_blockpos(pos)
|
|
|
|
|
local tbl = vm_cache[hash]
|
|
|
|
|
if not tbl then
|
|
|
|
|
local vm = minetest.get_voxel_manip(pos, pos)
|
|
|
|
|
local min_pos, max_pos = vm:get_emerged_area()
|
|
|
|
|
local va = VoxelArea:new{MinEdge = min_pos, MaxEdge = max_pos}
|
2021-11-27 16:28:13 +01:00
|
|
|
|
tbl = {vm = vm, va = va, data = vm:get_data(), param1 = vm:get_light_data(), param2 = vm:get_param2_data(), dirty = false, update_light = false}
|
2016-08-21 06:53:02 +02:00
|
|
|
|
vm_cache[hash] = tbl
|
|
|
|
|
end
|
|
|
|
|
return tbl
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Gets the node at a given position during a VoxelManipulator-based
|
|
|
|
|
-- transaction.
|
|
|
|
|
function mesecon.vm_get_node(pos)
|
|
|
|
|
local tbl = vm_get_or_create_entry(pos)
|
|
|
|
|
local index = tbl.va:indexp(pos)
|
|
|
|
|
local node_value = tbl.data[index]
|
|
|
|
|
if node_value == core.CONTENT_IGNORE then
|
|
|
|
|
return nil
|
|
|
|
|
else
|
|
|
|
|
local node_param1 = tbl.param1[index]
|
|
|
|
|
local node_param2 = tbl.param2[index]
|
|
|
|
|
return {name = minetest.get_name_from_content_id(node_value), param1 = node_param1, param2 = node_param2}
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Sets a node’s name during a VoxelManipulator-based transaction.
|
|
|
|
|
--
|
|
|
|
|
-- Existing param1, param2, and metadata are left alone.
|
2021-11-27 16:28:13 +01:00
|
|
|
|
--
|
|
|
|
|
-- See mesecon.swap_node_force for documentation about get_update_light.
|
|
|
|
|
function mesecon.vm_swap_node(pos, name, get_update_light)
|
2016-08-21 06:53:02 +02:00
|
|
|
|
local tbl = vm_get_or_create_entry(pos)
|
2021-11-27 16:28:13 +01:00
|
|
|
|
tbl.update_light = tbl.update_light or (get_update_light == nil or get_update_light(pos, name))
|
2016-08-21 06:53:02 +02:00
|
|
|
|
local index = tbl.va:indexp(pos)
|
|
|
|
|
tbl.data[index] = minetest.get_content_id(name)
|
|
|
|
|
tbl.dirty = true
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Gets the node at a given position, regardless of whether it is loaded or
|
|
|
|
|
-- not, respecting a transaction if one is in progress.
|
|
|
|
|
--
|
|
|
|
|
-- 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.
|
|
|
|
|
--
|
|
|
|
|
-- Inside a VM transaction, the transaction’s VM cache is used.
|
2016-02-19 12:11:38 +01:00
|
|
|
|
function mesecon.get_node_force(pos)
|
2016-08-21 06:53:02 +02:00
|
|
|
|
if vm_cache then
|
|
|
|
|
return mesecon.vm_get_node(pos)
|
|
|
|
|
else
|
|
|
|
|
local node = minetest.get_node_or_nil(pos)
|
|
|
|
|
if node == nil then
|
|
|
|
|
-- Node is not currently loaded; use a VoxelManipulator to prime
|
|
|
|
|
-- the mapblock cache and try again.
|
|
|
|
|
minetest.get_voxel_manip(pos, pos)
|
|
|
|
|
node = minetest.get_node_or_nil(pos)
|
|
|
|
|
end
|
|
|
|
|
return node
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Swaps the node at a given position, regardless of whether it is loaded or
|
|
|
|
|
-- not, respecting a transaction if one is in progress.
|
|
|
|
|
--
|
|
|
|
|
-- 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.
|
|
|
|
|
--
|
2021-11-27 16:28:13 +01:00
|
|
|
|
-- 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.
|
2016-08-21 06:53:02 +02:00
|
|
|
|
--
|
|
|
|
|
-- This function can only be used to change the node’s name, not its parameters
|
|
|
|
|
-- or metadata.
|
2021-11-27 16:28:13 +01:00
|
|
|
|
function mesecon.swap_node_force(pos, name, get_update_light)
|
2016-08-21 06:53:02 +02:00
|
|
|
|
if vm_cache then
|
2021-11-27 16:28:13 +01:00
|
|
|
|
return mesecon.vm_swap_node(pos, name, get_update_light)
|
2016-08-21 06:53:02 +02:00
|
|
|
|
else
|
|
|
|
|
-- This serves to both ensure the mapblock is loaded and also hand us
|
|
|
|
|
-- the old node table so we can preserve param2.
|
|
|
|
|
local node = mesecon.get_node_force(pos)
|
|
|
|
|
node.name = name
|
|
|
|
|
minetest.swap_node(pos, node)
|
2016-02-19 12:11:38 +01:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2016-08-23 07:20:46 +02:00
|
|
|
|
-- Autoconnect Hooks
|
|
|
|
|
-- Nodes like conductors may change their appearance and their connection rules
|
|
|
|
|
-- right after being placed or after being dug, e.g. the default wires use this
|
|
|
|
|
-- to automatically connect to linking nodes after placement.
|
|
|
|
|
-- After placement, the update function will be executed immediately so that the
|
|
|
|
|
-- possibly changed rules can be taken into account when recalculating the circuit.
|
|
|
|
|
-- After digging, the update function will be queued and executed after
|
|
|
|
|
-- recalculating the circuit. The update function must take care of updating the
|
|
|
|
|
-- node at the given position itself, but also all of the other nodes the given
|
|
|
|
|
-- position may have (had) a linking connection to.
|
|
|
|
|
mesecon.autoconnect_hooks = {}
|
|
|
|
|
|
|
|
|
|
-- name: A unique name for the hook, e.g. "foowire". Used to name the actionqueue function.
|
|
|
|
|
-- fct: The update function with parameters function(pos, node)
|
|
|
|
|
function mesecon.register_autoconnect_hook(name, fct)
|
|
|
|
|
mesecon.autoconnect_hooks[name] = fct
|
|
|
|
|
mesecon.queue:add_function("autoconnect_hook_"..name, fct)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function mesecon.execute_autoconnect_hooks_now(pos, node)
|
|
|
|
|
for _, fct in pairs(mesecon.autoconnect_hooks) do
|
|
|
|
|
fct(pos, node)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function mesecon.execute_autoconnect_hooks_queue(pos, node)
|
|
|
|
|
for name in pairs(mesecon.autoconnect_hooks) do
|
|
|
|
|
mesecon.queue:add_action(pos, "autoconnect_hook_"..name, {node})
|
|
|
|
|
end
|
|
|
|
|
end
|