Bluestone: update
parent
0130afec1a
commit
291889599f
|
@ -36,7 +36,7 @@ read_globals = {
|
|||
"hopper",
|
||||
"workbench",
|
||||
-- Silence errors about custom table methods.
|
||||
table = { fields = { "copy", "indexof" } },
|
||||
table = { fields = { "copy", "indexof", "insert_all" } },
|
||||
-- Silence warnings about accessing undefined fields of global 'math'
|
||||
math = { fields = { "sign" } }
|
||||
}
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
|
||||
local S = mesecon.S
|
||||
|
||||
local function button_turnoff(pos, material)
|
||||
local function button_turnoff(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
minetest.swap_node(pos, {name = "bluestone_button:button_" .. material .. "_off", param2 = node.param2})
|
||||
minetest.sound_play("mesecons_button_pop", {pos = pos})
|
||||
local rules = mesecon.rules.buttonlike_get(node)
|
||||
minetest.sound_play("mesecons_button_pop", {pos = pos})
|
||||
mesecon.flipstate(pos, node)
|
||||
mesecon.receptor_off(pos, rules)
|
||||
end
|
||||
|
||||
|
@ -19,9 +19,9 @@ local function on_place(itemstack, placer, pointed_thing)
|
|||
local node_def = minetest.registered_nodes[node.name]
|
||||
if node_def and node_def.on_rightclick and
|
||||
not (placer and placer:is_player() and
|
||||
placer:get_player_control().sneak) then
|
||||
placer:get_player_control().sneak) then
|
||||
return node_def.on_rightclick(under, node, placer, itemstack,
|
||||
pointed_thing) or itemstack
|
||||
pointed_thing) or itemstack
|
||||
end
|
||||
|
||||
if not node_def or not node_def.walkable then
|
||||
|
@ -35,10 +35,10 @@ local function on_place(itemstack, placer, pointed_thing)
|
|||
return itemstack
|
||||
end
|
||||
|
||||
local function press(pos, node, material)
|
||||
minetest.swap_node(pos, {name = "bluestone_button:button_" .. material .. "_on", param2 = node.param2})
|
||||
mesecon.receptor_on(pos, mesecon.rules.buttonlike_get(node))
|
||||
local function press(pos, node)
|
||||
minetest.sound_play("mesecons_button_push", {pos = pos})
|
||||
mesecon.flipstate(pos, node)
|
||||
mesecon.receptor_on(pos, mesecon.rules.buttonlike_get(node))
|
||||
minetest.get_node_timer(pos):start(1)
|
||||
end
|
||||
|
||||
|
@ -70,7 +70,7 @@ mesecon.register_node("bluestone_button:button_stone", {
|
|||
sunlight_propagates = true,
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
on_blast = mesecon.on_blastnode
|
||||
},{
|
||||
}, {
|
||||
description = S("Stone Button"),
|
||||
on_rotate = mesecon.buttonlike_onrotate,
|
||||
node_box = {
|
||||
|
@ -79,24 +79,18 @@ mesecon.register_node("bluestone_button:button_stone", {
|
|||
},
|
||||
groups = {dig_immediate = 2, attached_node2 = 1},
|
||||
node_placement_prediction = "",
|
||||
|
||||
on_place = on_place,
|
||||
on_rightclick = function(pos, node)
|
||||
press(pos, node, "stone")
|
||||
end,
|
||||
on_rightclick = press,
|
||||
mesecons = mesecons_off
|
||||
},{
|
||||
}, {
|
||||
on_rotate = false,
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = boxes_on
|
||||
},
|
||||
groups = {dig_immediate = 2, attached_node2 = 1, not_in_creative_inventory = 1},
|
||||
|
||||
mesecons = mesecons_on,
|
||||
on_timer = function(pos)
|
||||
button_turnoff(pos, "stone")
|
||||
end
|
||||
on_timer = button_turnoff
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
|
@ -115,7 +109,7 @@ mesecon.register_node("bluestone_button:button_wood", {
|
|||
sunlight_propagates = true,
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
on_blast = mesecon.on_blastnode
|
||||
},{
|
||||
}, {
|
||||
description = S("Wood Button"),
|
||||
on_rotate = mesecon.buttonlike_onrotate,
|
||||
node_box = {
|
||||
|
@ -126,22 +120,17 @@ mesecon.register_node("bluestone_button:button_wood", {
|
|||
node_placement_prediction = "",
|
||||
|
||||
on_place = on_place,
|
||||
on_rightclick = function(pos, node)
|
||||
press(pos, node, "wood")
|
||||
end,
|
||||
on_rightclick = press,
|
||||
mesecons = mesecons_off
|
||||
},{
|
||||
}, {
|
||||
on_rotate = false,
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = boxes_on
|
||||
},
|
||||
groups = {dig_immediate = 2, attached_node2 = 1, not_in_creative_inventory = 1},
|
||||
|
||||
mesecons = mesecons_on,
|
||||
on_timer = function(pos)
|
||||
button_turnoff(pos, "wood")
|
||||
end
|
||||
on_timer = button_turnoff
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
|
|
|
@ -14,7 +14,7 @@ http://www.gnu.org/licenses/lgpl-3.0.html
|
|||
|
||||
License of textures
|
||||
-------------------
|
||||
Copyright (C) 2016-2020 MultiCraft Development Team
|
||||
Copyright (C) 2016-2021 MultiCraft Development Team
|
||||
|
||||
Graphics in this mod is NOT free and can be used only as part of the official MultiCraft build.
|
||||
Allowed to be used in non-official builds ONLY for personal use.
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
mesecons
|
||||
screwdriver?
|
||||
|
|
|
@ -1,14 +1,38 @@
|
|||
local S = mesecon.S
|
||||
|
||||
local screwdriver_exists = minetest.global_exists("screwdriver")
|
||||
local interval = mesecon.setting("observer_interval", 1)
|
||||
local deg = math.deg
|
||||
local vsubtract = vector.subtract
|
||||
|
||||
local neighbor = {
|
||||
[0] = {x = 0, y = 0, z = 1},
|
||||
[1] = {x = 1, y = 0, z = 0},
|
||||
[2] = {x = 0, y = 0, z = -1},
|
||||
[3] = {x = -1, y = 0, z = 0},
|
||||
[4] = {x = 0, y = -1, z = 0},
|
||||
[8] = {x = 0, y = 1, z = 0}
|
||||
}
|
||||
|
||||
local function get_rules_flat(node)
|
||||
local rules = {{x = 0, y = 0, z = 1}}
|
||||
for _ = 1, node.param2 do
|
||||
rules = mesecon.rotate_rules_left(rules)
|
||||
return {neighbor[node.param2]}
|
||||
end
|
||||
|
||||
local function observer_orientate(pos, placer)
|
||||
-- Not placed by player
|
||||
if not placer then return end
|
||||
|
||||
-- Pitch in degrees
|
||||
local pitch = deg(placer:get_look_vertical())
|
||||
local node = minetest.get_node(pos)
|
||||
|
||||
if pitch > 55 then
|
||||
node.param2 = 4
|
||||
elseif pitch < -55 then
|
||||
node.param2 = 8
|
||||
else
|
||||
return
|
||||
end
|
||||
return rules
|
||||
minetest.swap_node(pos, node)
|
||||
end
|
||||
|
||||
-- Scan the node in front of the observer
|
||||
|
@ -17,10 +41,9 @@ local function observer_scan(pos, initialize)
|
|||
local node = minetest.get_node(pos)
|
||||
local nodeparam2 = node.param2
|
||||
local dir = minetest.facedir_to_dir(nodeparam2)
|
||||
local front = {x = pos.x - dir.x, y = pos.y, z = pos.z - dir.z}
|
||||
local frontnode = minetest.get_node(front)
|
||||
local frontname = frontnode.name
|
||||
local frontparam2 = frontnode.param2
|
||||
local front = minetest.get_node(vsubtract(pos, dir))
|
||||
local frontname = front.name
|
||||
local frontparam2 = front.param2
|
||||
local meta = minetest.get_meta(pos)
|
||||
local oldnode = meta:get_string("node_name")
|
||||
local oldparam2 = meta:get_string("node_param2")
|
||||
|
@ -45,16 +68,13 @@ end
|
|||
local ttop = "default_furnace_top.png"
|
||||
local tside = "default_furnace_side.png"
|
||||
|
||||
mesecon.register_node("bluestone_observer:observer",
|
||||
{
|
||||
mesecon.register_node("bluestone_observer:observer", {
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
paramtype2 = "facedir",
|
||||
},
|
||||
{
|
||||
}, {
|
||||
description = S("Observer"),
|
||||
groups = {cracky = 3},
|
||||
on_rotate = screwdriver_exists and screwdriver.rotate_simple,
|
||||
tiles = {
|
||||
ttop, ttop,
|
||||
tside, tside,
|
||||
|
@ -66,6 +86,8 @@ mesecon.register_node("bluestone_observer:observer",
|
|||
rules = get_rules_flat
|
||||
}},
|
||||
|
||||
after_place_node = observer_orientate,
|
||||
|
||||
on_construct = function(pos)
|
||||
minetest.get_node_timer(pos):start(interval)
|
||||
observer_scan(pos, true)
|
||||
|
@ -75,8 +97,7 @@ mesecon.register_node("bluestone_observer:observer",
|
|||
observer_scan(pos)
|
||||
return true
|
||||
end
|
||||
},
|
||||
{
|
||||
}, {
|
||||
groups = {cracky = 3, not_in_creative_inventory = 1},
|
||||
on_rotate = false,
|
||||
tiles = {
|
||||
|
|
|
@ -53,7 +53,7 @@ function queue:add_action(pos, func, params, time, overwritecheck, priority)
|
|||
|
||||
-- check if old action has to be overwritten / removed:
|
||||
if overwritecheck then
|
||||
for i, ac in pairs(queue.actions) do
|
||||
for i, ac in ipairs(queue.actions) do
|
||||
if vequals(pos, ac.pos)
|
||||
and mesecon.cmpAny(overwritecheck, ac.owcheck) then
|
||||
-- remove the old action
|
||||
|
@ -80,7 +80,7 @@ local function globalstep_func(dtime)
|
|||
local actions_now = {}
|
||||
queue.actions = {}
|
||||
|
||||
for _, ac in pairs(actions) do
|
||||
for _, ac in ipairs(actions) do
|
||||
if ac.time > 0 then
|
||||
-- action ac is to be executed later
|
||||
-- ~> insert into queue.actions
|
||||
|
@ -97,7 +97,7 @@ local function globalstep_func(dtime)
|
|||
-- some constructions might depend on the execution order, hence we first
|
||||
-- execute the actions that had a lower index in actions_now
|
||||
local old_action_order = {}
|
||||
for i, ac in pairs(actions_now) do
|
||||
for i, ac in ipairs(actions_now) do
|
||||
old_action_order[ac] = i
|
||||
end
|
||||
table_sort(actions_now, function(ac1, ac2)
|
||||
|
@ -109,7 +109,7 @@ local function globalstep_func(dtime)
|
|||
end)
|
||||
|
||||
-- execute highest priorities first, until all are executed
|
||||
for _, ac in pairs(actions_now) do
|
||||
for _, ac in ipairs(actions_now) do
|
||||
queue:execute(ac)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
-- 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
|
||||
-- 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.receptor_get_rules(node) --> Returns the rules of the receptor (mesecon.rules.default if none specified)
|
||||
|
||||
|
@ -49,7 +49,7 @@
|
|||
-- mesecon.rotate_rules_down(rules)
|
||||
-- These functions return rules that have been rotated in the specific direction
|
||||
|
||||
local table_remove = table.remove
|
||||
local fifo_queue = dofile(minetest.get_modpath("mesecons") .. "/fifo_queue.lua")
|
||||
local vadd, vequals = vector.add, vector.equals
|
||||
|
||||
-- General
|
||||
|
@ -97,9 +97,9 @@ function mesecon.get_any_inputrules(node)
|
|||
end
|
||||
end
|
||||
|
||||
function mesecon.get_any_rules (node)
|
||||
return mesecon.mergetable(mesecon.get_any_inputrules(node) or {},
|
||||
mesecon.get_any_outputrules(node) or {})
|
||||
function mesecon.get_any_rules(node)
|
||||
return mesecon.merge_rule_sets(mesecon.get_any_inputrules(node),
|
||||
mesecon.get_any_outputrules(node))
|
||||
end
|
||||
|
||||
-- Receptors
|
||||
|
@ -205,7 +205,7 @@ end)
|
|||
|
||||
function mesecon.activate(pos, node, rulename, depth)
|
||||
if rulename == nil then
|
||||
for _,rule in ipairs(mesecon.effector_get_rules(node)) do
|
||||
for _, rule in ipairs(mesecon.effector_get_rules(node)) do
|
||||
mesecon.activate(pos, node, rule, depth + 1)
|
||||
end
|
||||
return
|
||||
|
@ -251,7 +251,7 @@ end)
|
|||
|
||||
function mesecon.changesignal(pos, node, rulename, newstate, depth)
|
||||
if rulename == nil then
|
||||
for _,rule in ipairs(mesecon.effector_get_rules(node)) do
|
||||
for _, rule in ipairs(mesecon.effector_get_rules(node)) do
|
||||
mesecon.changesignal(pos, node, rule, newstate, depth + 1)
|
||||
end
|
||||
return
|
||||
|
@ -383,32 +383,45 @@ end
|
|||
-- 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}}
|
||||
local frontiers = fifo_queue.new()
|
||||
frontiers:add({pos = pos, link = link})
|
||||
local pos_can_be_skipped = {}
|
||||
|
||||
local depth = 1
|
||||
while frontiers[1] do
|
||||
local f = table_remove(frontiers, 1)
|
||||
for f in frontiers:iter() do
|
||||
local node = mesecon.get_node_force(f.pos)
|
||||
|
||||
if not node then
|
||||
-- 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)
|
||||
|
||||
-- Call turnon on neighbors
|
||||
for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do
|
||||
local np = vadd(f.pos, r)
|
||||
for _, l in ipairs(mesecon.rules_link_rule_all(f.pos, r)) do
|
||||
frontiers[#frontiers+1] = {pos = np, link = l}
|
||||
if mesecon.is_conductor_off(node, f.link) then
|
||||
-- Call turnon on neighbors
|
||||
for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do
|
||||
local np = vadd(f.pos, r)
|
||||
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
|
||||
|
||||
mesecon.swap_node_force(f.pos, mesecon.get_conductor_on(node, f.link))
|
||||
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
|
||||
mesecon.changesignal(f.pos, node, f.link, mesecon.state.on, depth)
|
||||
if mesecon.is_effector_off(node.name) then
|
||||
mesecon.activate(f.pos, node, f.link, depth)
|
||||
end
|
||||
else
|
||||
pos_can_be_skipped[minetest.hash_node_position(f.pos)] = true
|
||||
end
|
||||
depth = depth + 1
|
||||
end
|
||||
|
@ -431,37 +444,49 @@ end
|
|||
-- depth = indicates order in which signals wire fired, higher is later
|
||||
-- }
|
||||
function mesecon.turnoff(pos, link)
|
||||
local frontiers = {{pos = pos, link = link}}
|
||||
local frontiers = fifo_queue.new()
|
||||
frontiers:add({pos = pos, link = link})
|
||||
local signals = {}
|
||||
local pos_can_be_skipped = {}
|
||||
|
||||
local depth = 1
|
||||
while frontiers[1] do
|
||||
local f = table_remove(frontiers, 1)
|
||||
for f in frontiers:iter() do
|
||||
local node = mesecon.get_node_force(f.pos)
|
||||
|
||||
if not node then
|
||||
-- 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)
|
||||
for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do
|
||||
local np = vadd(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 _ in ipairs(mesecon.rules_link_rule_all_inverted(f.pos, r)) do
|
||||
if mesecon.is_receptor_on(mesecon.get_node_force(np).name) then
|
||||
return false
|
||||
if mesecon.is_conductor_on(node, f.link) then
|
||||
for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do
|
||||
local np = vadd(f.pos, r)
|
||||
|
||||
if not pos_can_be_skipped[minetest.hash_node_position(np)] then
|
||||
-- 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
|
||||
|
||||
-- Call turnoff on neighbors
|
||||
for _, l in ipairs(mesecon.rules_link_rule_all(f.pos, r)) do
|
||||
frontiers[#frontiers+1] = {pos = np, link = l}
|
||||
end
|
||||
mesecon.swap_node_force(f.pos, mesecon.get_conductor_off(node, f.link))
|
||||
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
|
||||
signals[#signals+1] = {
|
||||
pos = f.pos,
|
||||
|
@ -469,6 +494,8 @@ function mesecon.turnoff(pos, link)
|
|||
link = f.link,
|
||||
depth = depth
|
||||
}
|
||||
else
|
||||
pos_can_be_skipped[minetest.hash_node_position(f.pos)] = true
|
||||
end
|
||||
depth = depth + 1
|
||||
end
|
||||
|
@ -488,7 +515,7 @@ end
|
|||
function mesecon.rules_link_rule_all(output, rule)
|
||||
local input = vadd(output, rule)
|
||||
local inputnode = mesecon.get_node_force(input)
|
||||
local inputrules = mesecon.get_any_inputrules (inputnode)
|
||||
local inputrules = mesecon.get_any_inputrules(inputnode)
|
||||
if not inputrules then
|
||||
return {}
|
||||
end
|
||||
|
|
|
@ -16,14 +16,14 @@ mesecon.rules.default = {
|
|||
{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.all = mesecon.mergetable(mesecon.rules.default, {
|
||||
mesecon.rules.all = mesecon.merge_rule_sets(mesecon.rules.default, {
|
||||
{x = 0, y = 1, z = 0},
|
||||
{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 = {
|
||||
{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
|
||||
-- conductors will be activated (when pushing an on-conductor with a piston)
|
||||
for _, s in ipairs(sources) do
|
||||
local rule = vsubtract(pos, s)
|
||||
local rule = vsubtract(s, pos)
|
||||
mesecon.turnon(pos, rule)
|
||||
end
|
||||
--mesecon.receptor_on (pos, mesecon.conductor_get_rules(node))
|
||||
|
|
|
@ -78,8 +78,8 @@ function mesecon.flattenrules(allrules)
|
|||
end
|
||||
|
||||
local shallowrules = {}
|
||||
for _, metarule in ipairs( allrules) do
|
||||
for _, rule in ipairs(metarule ) do
|
||||
for _, metarule in ipairs(allrules) do
|
||||
for _, rule in ipairs(metarule) do
|
||||
shallowrules[#shallowrules+1] = rule
|
||||
end
|
||||
end
|
||||
|
@ -101,8 +101,8 @@ function mesecon.rule2bit(findrule, allrules)
|
|||
not findrule then
|
||||
return 1
|
||||
end
|
||||
for m,metarule in ipairs( allrules) do
|
||||
for _, rule in ipairs(metarule ) do
|
||||
for m, metarule in ipairs(allrules) do
|
||||
for _, rule in ipairs(metarule) do
|
||||
if vequals(findrule, rule) then
|
||||
return m
|
||||
end
|
||||
|
@ -120,8 +120,8 @@ function mesecon.rule2metaindex(findrule, allrules)
|
|||
return mesecon.flattenrules(allrules)
|
||||
end
|
||||
|
||||
for m, metarule in ipairs( allrules) do
|
||||
for _, rule in ipairs(metarule ) do
|
||||
for m, metarule in ipairs(allrules) do
|
||||
for _, rule in ipairs(metarule) do
|
||||
if vequals(findrule, rule) then
|
||||
return m
|
||||
end
|
||||
|
@ -167,7 +167,9 @@ end
|
|||
|
||||
function mesecon.get_bit(binary,bit)
|
||||
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"
|
||||
end
|
||||
|
||||
|
@ -196,6 +198,9 @@ function mesecon.tablecopy(obj) -- deep copy
|
|||
return obj
|
||||
end
|
||||
|
||||
-- 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.
|
||||
function mesecon.cmpAny(t1, t2)
|
||||
if type(t1) ~= type(t2) then return false end
|
||||
if type(t1) ~= "table" and type(t2) ~= "table" then return t1 == t2 end
|
||||
|
@ -213,20 +218,32 @@ function mesecon.cmpAny(t1, t2)
|
|||
return true
|
||||
end
|
||||
|
||||
-- does not overwrite values; number keys (ipairs) are appended, not overwritten
|
||||
function mesecon.mergetable(source, dest)
|
||||
local rval = mesecon.tablecopy(dest)
|
||||
|
||||
for k, v in pairs(source) do
|
||||
rval[k] = dest[k] or mesecon.tablecopy(v)
|
||||
-- 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
|
||||
for _, v in ipairs(source) do
|
||||
rval[#rval+1] = mesecon.tablecopy(v)
|
||||
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)
|
||||
spec_common.drop = spec_common.drop or name .. "_off"
|
||||
spec_common.on_blast = spec_common.on_blast or mesecon.on_blastnode
|
||||
|
@ -234,8 +251,8 @@ function mesecon.register_node(name, spec_common, spec_off, spec_on)
|
|||
spec_on.__mesecon_state = "on"
|
||||
spec_off.__mesecon_state = "off"
|
||||
|
||||
spec_on = mesecon.mergetable(spec_common, spec_on);
|
||||
spec_off = mesecon.mergetable(spec_common, spec_off);
|
||||
spec_on = mesecon.merge_tables(spec_common, spec_on);
|
||||
spec_off = mesecon.merge_tables(spec_common, spec_off);
|
||||
|
||||
minetest.register_node(name .. "_on", spec_on)
|
||||
minetest.register_node(name .. "_off", spec_off)
|
||||
|
|
|
@ -10,7 +10,7 @@ are so many weird tables below.
|
|||
|
||||
local S = mesecon.S
|
||||
|
||||
local random, pi = math.random, math.pi
|
||||
local deg, random = math.deg, math.random
|
||||
local tcopy, tinsert = table.copy, table.insert
|
||||
local vsubtract = vector.subtract
|
||||
|
||||
|
@ -43,12 +43,12 @@ local function setup_dropper(pos)
|
|||
inv:set_size("split", 1)
|
||||
end
|
||||
|
||||
local function orientate_dropper(pos, placer)
|
||||
local function dropper_orientate(pos, placer)
|
||||
-- Not placed by player
|
||||
if not placer then return end
|
||||
|
||||
-- Pitch in degrees
|
||||
local pitch = placer:get_look_vertical() * (180 / pi)
|
||||
local pitch = deg(placer:get_look_vertical())
|
||||
|
||||
if pitch > 55 then
|
||||
minetest.swap_node(pos, {name = "mesecons_dropper:dropper_up"})
|
||||
|
@ -189,7 +189,7 @@ horizontal_def.after_place_node = function(pos, placer)
|
|||
minetest.get_meta(pos):set_string("owner", name)
|
||||
|
||||
setup_dropper(pos, placer)
|
||||
orientate_dropper(pos, placer)
|
||||
dropper_orientate(pos, placer)
|
||||
end
|
||||
horizontal_def.tiles = {
|
||||
ttop, ttop,
|
||||
|
|
|
@ -51,7 +51,7 @@ local function piston_get_rules(node)
|
|||
break
|
||||
end
|
||||
end
|
||||
local rules = table_copy(mesecon.rules.default)
|
||||
local rules = table_copy(mesecon.rules.all)
|
||||
for i, rule in pairs(rules) do
|
||||
if rule[dir[1]] == dir[2] then
|
||||
table_remove(rules, i)
|
||||
|
@ -275,7 +275,7 @@ end
|
|||
|
||||
-- Boxes:
|
||||
|
||||
local pt = 3/16 -- pusher thickness
|
||||
local pt = 4/16 -- pusher thickness
|
||||
|
||||
local piston_pusher_box = {
|
||||
type = "fixed",
|
||||
|
@ -287,9 +287,7 @@ local piston_pusher_box = {
|
|||
|
||||
local piston_on_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-.5, -.5, -.5 + pt, .5, .5, .5}
|
||||
}
|
||||
fixed = {-.5, -.5, -.5 + pt, .5, .5, .5}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -12,22 +12,18 @@ local pp_box_on = {
|
|||
|
||||
local function pp_on_timer(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
local basename = minetest.registered_nodes[node.name].pressureplate_basename
|
||||
|
||||
-- This is a workaround for a strange bug that occurs when the server is started
|
||||
-- For some reason the first time on_timer is called, the pos is wrong
|
||||
if not basename then return end
|
||||
|
||||
local objs = minetest.get_objects_inside_radius(pos, 0.8)
|
||||
local is_on = mesecon.is_receptor_on(node.name)
|
||||
|
||||
if objs[1] == nil and node.name == basename .. "_on" then
|
||||
minetest.set_node(pos, {name = basename .. "_off"})
|
||||
if objs[1] == nil and is_on then
|
||||
mesecon.flipstate(pos, node)
|
||||
mesecon.receptor_off(pos, mesecon.rules.pplate)
|
||||
elseif node.name == basename .. "_off" then
|
||||
elseif not is_on then
|
||||
for _, obj in pairs(objs) do
|
||||
local objpos = obj:get_pos()
|
||||
if objpos.y > pos.y-1 and objpos.y < pos.y then
|
||||
minetest.set_node(pos, {name = basename .. "_on"})
|
||||
mesecon.flipstate(pos, node)
|
||||
mesecon.receptor_on(pos, mesecon.rules.pplate )
|
||||
end
|
||||
end
|
||||
|
@ -67,14 +63,14 @@ function mesecon.register_pressure_plate(basename, description, tile, recipe, gr
|
|||
on_construct = function(pos)
|
||||
minetest.get_node_timer(pos):start(mesecon.setting("pplate_interval", 0.1))
|
||||
end
|
||||
},{
|
||||
}, {
|
||||
mesecons = {receptor = {
|
||||
state = mesecon.state.off, rules = mesecon.rules.pplate
|
||||
}},
|
||||
node_box = pp_box_off,
|
||||
selection_box = pp_box_off,
|
||||
groups = groups_off
|
||||
},{
|
||||
}, {
|
||||
mesecons = {receptor = {
|
||||
state = mesecon.state.on, rules = mesecon.rules.pplate
|
||||
}},
|
||||
|
|
|
@ -22,14 +22,13 @@ mesecon.register_node("mesecons_solarpanel:solar_panel", {
|
|||
on_timer = function(pos)
|
||||
local light = minetest.get_node_light(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
local is_on = mesecon.is_receptor_on(node.name)
|
||||
|
||||
if light >= 10 and node.name == "mesecons_solarpanel:solar_panel_off" then
|
||||
node.name = "mesecons_solarpanel:solar_panel_on"
|
||||
minetest.swap_node(pos, node)
|
||||
if light >= 10 and not is_on then
|
||||
mesecon.flipstate(pos, node)
|
||||
mesecon.receptor_on(pos, mesecon.rules.wallmounted_get(node))
|
||||
elseif light < 10 and node.name == "mesecons_solarpanel:solar_panel_on" then
|
||||
node.name = "mesecons_solarpanel:solar_panel_off"
|
||||
minetest.swap_node(pos, node)
|
||||
elseif light < 10 and is_on then
|
||||
mesecon.flipstate(pos, node)
|
||||
mesecon.receptor_off(pos, mesecon.rules.wallmounted_get(node))
|
||||
end
|
||||
|
||||
|
@ -39,14 +38,14 @@ mesecon.register_node("mesecons_solarpanel:solar_panel", {
|
|||
on_construct = function(pos)
|
||||
minetest.get_node_timer(pos):start(mesecon.setting("spanel_interval", 1))
|
||||
end
|
||||
},{
|
||||
}, {
|
||||
description = S("Solar Panel"),
|
||||
groups = {dig_immediate = 3, attached_node = 1},
|
||||
mesecons = {receptor = {
|
||||
state = mesecon.state.off,
|
||||
rules = mesecon.rules.wallmounted_get
|
||||
}}
|
||||
},{
|
||||
}, {
|
||||
groups = {dig_immediate = 3, attached_node = 1, not_in_creative_inventory = 1},
|
||||
mesecons = {receptor = {
|
||||
state = mesecon.state.on,
|
||||
|
|
|
@ -21,7 +21,7 @@ mesecon.register_node("mesecons_walllever:wall_lever", {
|
|||
end
|
||||
minetest.sound_play("mesecons_lever", {pos = pos})
|
||||
end
|
||||
},{
|
||||
}, {
|
||||
tiles = {
|
||||
"default_stone.png",
|
||||
"default_stone.png^jeija_wall_lever_top.png^[transformFY",
|
||||
|
@ -40,7 +40,7 @@ mesecon.register_node("mesecons_walllever:wall_lever", {
|
|||
state = mesecon.state.off
|
||||
}},
|
||||
groups = {dig_immediate = 2},
|
||||
},{
|
||||
}, {
|
||||
tiles = {
|
||||
"default_stone.png^jeija_wall_lever_top.png",
|
||||
"default_stone.png",
|
||||
|
|
|
@ -221,8 +221,11 @@ local function register_wires()
|
|||
mesecon_wire = true,
|
||||
sounds = default.node_sound_defaults(),
|
||||
on_rotate = false,
|
||||
}, {tiles = tiles_off, mesecons = meseconspec_off, groups = groups_off},
|
||||
{tiles = tiles_on, mesecons = meseconspec_on, groups = groups_on})
|
||||
}, {
|
||||
tiles = tiles_off, mesecons = meseconspec_off, groups = groups_off
|
||||
}, {
|
||||
tiles = tiles_on, mesecons = meseconspec_on, groups = groups_on
|
||||
})
|
||||
|
||||
if (nid_inc(nid) == false) then return end
|
||||
end
|
||||
|
@ -236,5 +239,5 @@ register_wires()
|
|||
minetest.register_craft({
|
||||
type = "cooking",
|
||||
output = "mesecons:wire_00000000_off 8",
|
||||
recipe = "default:stone_with_bluestone",
|
||||
recipe = "default:stone_with_bluestone"
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue