1 Commits

Author SHA1 Message Date
77b8f6514a Better mesecon-enabled doors
The mesecons_compatibility doors erred in making steel doors, which
are meant to be locked, openable by anyone using a mesecon signal.
They also didn't handle mirror-paired doors, and nastily duplicated
lots of the standard door code rather than using it and adding to it.
Replace mesecons_compatibility with a new system, in which standard
doors are left alone and new types of door are added that have mesecon
behaviour.  The new door types are each available in both wood and steel,
using the standard door textures.

The mesecon-operated doors open and close according to the mesecon
signal they receive: open when the signal is on and closed when off.
Unlike the old mesecons_compatibility doors, which only accepted the
signal to the bottom half, these accept the signal to either half of
the door.  A convenient kind of control therefore is a wall-mounted
button just above the doorway: the signal flows diagonally down to the
top half of the door.  The door cannot be operated manually.

The mesecon-signalling doors are opened and closed manually, and generate
a mesecon signal indicating whether they're open, on when open and off
when closed.  Thus opening the door can trigger automatic activity.
Pairing a mesecon-signalling door with a mesecon-operated door results
in a door pair where right-clicking on one door operates both.

By making use of the pairing behaviour built into the standard doors mod,
which is inherited by the mesecon doors, and placing doors from sideways
angles, it is possible to effectively get mesecon doors with the opposite
signal sense.  For example, a mesecon-signalling door that sends an on
signal when closed, turning the signal off when opened.
2014-05-04 16:47:47 +02:00
273 changed files with 2667 additions and 3709 deletions

View File

@ -1,30 +0,0 @@
The Mesecons Mod for Minetest is
Copyright (C) 2011-2016 Mesecons Mod Developer Team and contributors
See the version control system log for information about other authors.
License of source code
----------------------
Copyright (C) 2011-2016 Mesecons Mod Developer Team and contributors
This program is free software; you can redistribute the Mesecons Mod and/or
modify it under the terms of the GNU Lesser General Public License version 3
published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Boston, MA 02110-1301, USA.
License of media (textures, sounds and documentation)
-----------------------------------------------------
Copyright (C) 2011-2016 Mesecons Mod Developer Team and contributors
All textures, sounds and documentation files are licensed under the
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
http://creativecommons.org/licenses/by-sa/3.0/

View File

@ -22,7 +22,7 @@ OK, I want in.
-------------- --------------
Go get it! Go get it!
[DOWNLOAD IT NOW](https://github.com/Jeija/minetest-mod-mesecons/archive/master.zip) [DOWNLOADS PAGE](http://mesecons.net/downloads.php)
Now go ahead and install it like any other Minetest mod. Don't know how? Check out [the wonderful page about it](http://wiki.minetest.com/wiki/Mods) over at the Minetest Wiki. For your convenience, here's a quick summary: Now go ahead and install it like any other Minetest mod. Don't know how? Check out [the wonderful page about it](http://wiki.minetest.com/wiki/Mods) over at the Minetest Wiki. For your convenience, here's a quick summary:
@ -39,7 +39,7 @@ How do I use this thing?
------------------------ ------------------------
How about a [quick overview video](https://www.youtube.com/watch?v=6kmeQj6iW5k)? How about a [quick overview video](https://www.youtube.com/watch?v=6kmeQj6iW5k)?
Or maybe a [comprehensive reference](http://mesecons.net/items.html) is your style? Or maybe a [comprehensive reference](http://mesecons.net/items.php) is your style?
An overview for the very newest of new beginners? How does [this one](http://uberi.mesecons.net/projects/MeseconsBasics/index.html) look? An overview for the very newest of new beginners? How does [this one](http://uberi.mesecons.net/projects/MeseconsBasics/index.html) look?

View File

@ -1,62 +0,0 @@
{
"Conductors" : {
"Mesecon" : "mesecons/doc/mesecon",
"Insulated Wire" : "mesecons_insulated/doc/insulated",
"T-Junction" : "mesecons_extrawires/doc/tjunction",
"Crossing" : "mesecons_extrawires/doc/crossing",
"Corner" : "mesecons_extrawires/doc/corner",
"Vertical Wire" : "mesecons_extrawires/doc/vertical",
"Mese" : "mesecons_extrawires/doc/mese"
},
"Receptors" : {
"Power Plant" : "mesecons_powerplant/doc/powerplant",
"Blinky Plant" : "mesecons_blinkyplant/doc/blinkyplant",
"Switch" : "mesecons_switch/doc/switch",
"Object Detector" : "mesecons_detector/doc/objectdetector",
"Node Detector" : "mesecons_detector/doc/nodedetector",
"Wall Lever" : "mesecons_walllever/doc/walllever",
"Pressure Plate" : "mesecons_pressureplates/doc/pressureplate_wood",
"Pressure Plate" : "mesecons_pressureplates/doc/pressureplate_stone",
"Water Turbine" : "mesecons_hydroturbine/doc/waterturbine",
"Solar Panel" : "mesecons_solarpanel/doc/solarpanel",
"Wall Button" : "mesecons_button/doc/button"
},
"Effectors" : {
"Noteblock" : "mesecons_noteblock/doc/noteblock",
"Lamp" : "mesecons_lamp/doc/lamp",
"Piston" : "mesecons_pistons/doc/piston",
"Sticky Piston" : "mesecons_pistons/doc/piston_sticky",
"Movestone" : "mesecons_movestones/doc/movestone",
"Sticky Movestone" : "mesecons_movestones/doc/movestone_sticky",
"Removestone" : "mesecons_random/doc/removestone",
"Ghoststone" : "mesecons_random/doc/ghoststone",
"Command Block" : "mesecons_commandblock/doc/commandblock",
"Lightstones" : {
"Dark Grey" : "mesecons_lightstone/doc/lightstone_darkgrey",
"Light Grey" : "mesecons_lightstone/doc/lightstone_lightgrey",
"Green" : "mesecons_lightstone/doc/lightstone_green",
"Red" : "mesecons_lightstone/doc/lightstone_red",
"Blue" : "mesecons_lightstone/doc/lightstone_blue",
"Yellow" : "mesecons_lightstone/doc/lightstone_yellow"
}
},
"Logic" : {
"Luacontroller" : "mesecons_luacontroller/doc/luacontroller",
"Torch" : "mesecons_torch/doc/torch",
"Delayer" : "mesecons_delayer/doc/delayer",
"Gates" : {
"Diode" : "mesecons_gates/doc/diode",
"NOT Gate" : "mesecons_gates/doc/not",
"AND Gate" : "mesecons_gates/doc/and",
"NAND Gate" : "mesecons_gates/doc/nand",
"OR Gate" : "mesecons_gates/doc/or",
"NOR Gate" : "mesecons_gates/doc/nor",
"XOR Gate" : "mesecons_gates/doc/xor"
}
},
"Crafts" : {
"Silicon" : "mesecons_materials/doc/silicon",
"Glue" : "mesecons_materials/doc/glue",
"Fiber" : "mesecons_materials/doc/fiber"
}
}

1
mesecons/VERSION Normal file
View File

@ -0,0 +1 @@
0.41 DEV

View File

@ -12,19 +12,19 @@ function mesecon.queue:add_action(pos, func, params, time, overwritecheck, prior
-- Create Action Table: -- Create Action Table:
time = time or 0 -- time <= 0 --> execute, time > 0 --> wait time until execution time = time or 0 -- time <= 0 --> execute, time > 0 --> wait time until execution
priority = priority or 1 priority = priority or 1
local action = { pos=mesecon.tablecopy(pos), local action = { pos=mesecon:tablecopy(pos),
func=func, func=func,
params=mesecon.tablecopy(params or {}), params=mesecon:tablecopy(params),
time=time, time=time,
owcheck=(overwritecheck and mesecon.tablecopy(overwritecheck)) or nil, owcheck=(overwritecheck and mesecon:tablecopy(overwritecheck)) or nil,
priority=priority} priority=priority}
local toremove = nil local toremove = nil
-- Otherwise, add the action to the queue -- Otherwise, add the action to the queue
if overwritecheck then -- check if old action has to be overwritten / removed: if overwritecheck then -- check if old action has to be overwritten / removed:
for i, ac in ipairs(mesecon.queue.actions) do for i, ac in ipairs(mesecon.queue.actions) do
if(vector.equals(pos, ac.pos) if(mesecon:cmpPos(pos, ac.pos)
and mesecon.cmpAny(overwritecheck, ac.owcheck)) then and mesecon:cmpAny(overwritecheck, ac.owcheck)) then
toremove = i toremove = i
break break
end end
@ -44,8 +44,7 @@ end
-- However, even that does not work in some cases, that's why we delay the time the globalsteps -- However, even that does not work in some cases, that's why we delay the time the globalsteps
-- start to be execute by 5 seconds -- start to be execute by 5 seconds
local get_highest_priority = function (actions) local get_highest_priority = function (actions)
local highestp = -1 local highestp = -1, highesti
local highesti
for i, ac in ipairs(actions) do for i, ac in ipairs(actions) do
if ac.priority > highestp then if ac.priority > highestp then
highestp = ac.priority highestp = ac.priority
@ -57,13 +56,10 @@ local get_highest_priority = function (actions)
end end
local m_time = 0 local m_time = 0
local resumetime = mesecon.setting("resumetime", 4)
minetest.register_globalstep(function (dtime) minetest.register_globalstep(function (dtime)
m_time = m_time + dtime m_time = m_time + dtime
-- don't even try if server has not been running for XY seconds; resumetime = time to wait if (m_time < MESECONS_RESUMETIME) then return end -- don't even try if server has not been running for XY seconds
-- after starting the server before processing the ActionQueue, don't set this too low local actions = mesecon:tablecopy(mesecon.queue.actions)
if (m_time < resumetime) then return end
local actions = mesecon.tablecopy(mesecon.queue.actions)
local actions_now={} local actions_now={}
mesecon.queue.actions = {} mesecon.queue.actions = {}
@ -94,8 +90,25 @@ end
-- Store and read the ActionQueue to / from a file -- Store and read the ActionQueue to / from a file
-- so that upcoming actions are remembered when the game -- so that upcoming actions are remembered when the game
-- is restarted -- is restarted
mesecon.queue.actions = mesecon.file2table("mesecon_actionqueue")
local wpath = minetest.get_worldpath()
local function file2table(filename)
local f = io.open(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
local function table2file(filename, table)
local f = io.open(filename, "w")
f:write(minetest.serialize(table))
f:close()
end
mesecon.queue.actions = file2table(wpath.."/mesecon_actionqueue")
minetest.register_on_shutdown(function() minetest.register_on_shutdown(function()
mesecon.table2file("mesecon_actionqueue", mesecon.queue.actions) mesecon.queue.actions = table2file(wpath.."/mesecon_actionqueue", mesecon.queue.actions)
end) end)

View File

@ -1 +0,0 @@
Mesecons are the wires, use them to connect effectors with receptors.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -30,7 +30,7 @@
-- action_change = function -- action_change = function
-- rules = rules/get_rules -- rules = rules/get_rules
-- }, -- },
-- conductor = -- conductor =
-- { -- {
-- state = mesecon.state.on/off -- state = mesecon.state.on/off
-- offstate = opposite state (for state = on only) -- offstate = opposite state (for state = on only)
@ -47,14 +47,15 @@ mesecon.queue.funcs={} -- contains all ActionQueue functions
-- Settings -- Settings
dofile(minetest.get_modpath("mesecons").."/settings.lua") dofile(minetest.get_modpath("mesecons").."/settings.lua")
-- Presets (eg default rules)
dofile(minetest.get_modpath("mesecons").."/presets.lua");
-- Utilities like comparing positions, -- Utilities like comparing positions,
-- adding positions and rules, -- adding positions and rules,
-- mostly things that make the source look cleaner -- mostly things that make the source look cleaner
dofile(minetest.get_modpath("mesecons").."/util.lua"); dofile(minetest.get_modpath("mesecons").."/util.lua");
-- Presets (eg default rules)
dofile(minetest.get_modpath("mesecons").."/presets.lua");
-- The ActionQueue -- The ActionQueue
-- Saves all the actions that have to be execute in the future -- Saves all the actions that have to be execute in the future
dofile(minetest.get_modpath("mesecons").."/actionqueue.lua"); dofile(minetest.get_modpath("mesecons").."/actionqueue.lua");
@ -66,6 +67,11 @@ dofile(minetest.get_modpath("mesecons").."/actionqueue.lua");
-- like calling action_on/off/change -- like calling action_on/off/change
dofile(minetest.get_modpath("mesecons").."/internal.lua"); dofile(minetest.get_modpath("mesecons").."/internal.lua");
-- Deprecated stuff
-- To be removed in future releases
-- Currently there is nothing here
dofile(minetest.get_modpath("mesecons").."/legacy.lua");
-- API -- API
-- these are the only functions you need to remember -- these are the only functions you need to remember
@ -73,8 +79,8 @@ mesecon.queue:add_function("receptor_on", function (pos, rules)
rules = rules or mesecon.rules.default rules = rules or mesecon.rules.default
-- if area (any of the rule targets) is not loaded, keep trying and call this again later -- if area (any of the rule targets) is not loaded, keep trying and call this again later
for _, rule in ipairs(mesecon.flattenrules(rules)) do for _, rule in ipairs(mesecon:flattenrules(rules)) do
local np = vector.add(pos, rule) local np = mesecon:addPosRule(pos, rule)
-- if area is not loaded, keep trying -- if area is not loaded, keep trying
if minetest.get_node_or_nil(np) == nil then if minetest.get_node_or_nil(np) == nil then
mesecon.queue:add_action(pos, "receptor_on", {rules}, nil, rules) mesecon.queue:add_action(pos, "receptor_on", {rules}, nil, rules)
@ -83,16 +89,16 @@ mesecon.queue:add_function("receptor_on", function (pos, rules)
end end
-- execute action -- execute action
for _, rule in ipairs(mesecon.flattenrules(rules)) do for _, rule in ipairs(mesecon:flattenrules(rules)) do
local np = vector.add(pos, rule) local np = mesecon:addPosRule(pos, rule)
local rulenames = mesecon.rules_link_rule_all(pos, rule) local rulenames = mesecon:rules_link_rule_all(pos, rule)
for _, rulename in ipairs(rulenames) do for _, rulename in ipairs(rulenames) do
mesecon.turnon(np, rulename) mesecon:turnon(np, rulename)
end end
end end
end) end)
function mesecon.receptor_on(pos, rules) function mesecon:receptor_on(pos, rules)
mesecon.queue:add_action(pos, "receptor_on", {rules}, nil, rules) mesecon.queue:add_action(pos, "receptor_on", {rules}, nil, rules)
end end
@ -100,38 +106,34 @@ mesecon.queue:add_function("receptor_off", function (pos, rules)
rules = rules or mesecon.rules.default rules = rules or mesecon.rules.default
-- if area (any of the rule targets) is not loaded, keep trying and call this again later -- if area (any of the rule targets) is not loaded, keep trying and call this again later
for _, rule in ipairs(mesecon.flattenrules(rules)) do for _, rule in ipairs(mesecon:flattenrules(rules)) do
local np = vector.add(pos, rule) local np = mesecon:addPosRule(pos, rule)
if minetest.get_node_or_nil(np) == nil then if minetest.get_node_or_nil(np) == nil then
mesecon.queue:add_action(pos, "receptor_off", {rules}, nil, rules) mesecon.queue:add_action(pos, "receptor_off", {rules}, nil, rules)
return return
end end
end end
for _, rule in ipairs(mesecon.flattenrules(rules)) do for _, rule in ipairs(mesecon:flattenrules(rules)) do
local np = vector.add(pos, rule) local np = mesecon:addPosRule(pos, rule)
local rulenames = mesecon.rules_link_rule_all(pos, rule) local rulenames = mesecon:rules_link_rule_all(pos, rule)
for _, rulename in ipairs(rulenames) do for _, rulename in ipairs(rulenames) do
if not mesecon.connected_to_receptor(np, mesecon.invertRule(rule)) then if not mesecon:connected_to_receptor(np, mesecon:invertRule(rule)) then
mesecon.turnoff(np, rulename) mesecon:turnoff(np, rulename)
else else
mesecon.changesignal(np, minetest.get_node(np), rulename, mesecon.state.off, 2) mesecon:changesignal(np, minetest.get_node(np), rulename, mesecon.state.off, 2)
end end
end end
end end
end) end)
function mesecon.receptor_off(pos, rules) function mesecon:receptor_off(pos, rules)
mesecon.queue:add_action(pos, "receptor_off", {rules}, nil, rules) mesecon.queue:add_action(pos, "receptor_off", {rules}, nil, rules)
end end
print("[OK] Mesecons") print("[OK] Mesecons")
-- Deprecated stuff
-- To be removed in future releases
dofile(minetest.get_modpath("mesecons").."/legacy.lua");
--The actual wires --The actual wires
dofile(minetest.get_modpath("mesecons").."/wires.lua"); dofile(minetest.get_modpath("mesecons").."/wires.lua");

File diff suppressed because it is too large Load Diff

View File

@ -1,30 +1,32 @@
-- Ugly hack to prevent breaking compatibility with other mods minetest.swap_node = minetest.swap_node or function(pos, node)
-- Just remove the following two functions to delete the hack, to be done when other mods have updated local data = minetest.get_meta(pos):to_table()
function mesecon.receptor_on(self, pos, rules) minetest.add_node(pos, node)
if (self.receptor_on) then minetest.get_meta(pos):from_table(data)
print("[Mesecons] Warning: A mod with mesecon support called mesecon:receptor_on.") end
print("[Mesecons] If you are the programmer of this mod, please update it ")
print("[Mesecons] to use mesecon.receptor_on instead. mesecon:* is deprecated") local rules = {}
print("[Mesecons] Otherwise, please make sure you're running the latest version") rules.a = {x = -1, y = 0, z = 0, name="A"}
print("[Mesecons] of that mod and inform the mod creator.") rules.b = {x = 0, y = 0, z = 1, name="B"}
else rules.c = {x = 1, y = 0, z = 0, name="C"}
rules = pos rules.d = {x = 0, y = 0, z = -1, name="D"}
pos = self
end function legacy_update_ports(pos)
mesecon.queue:add_action(pos, "receptor_on", {rules}, nil, rules) local meta = minetest.get_meta(pos)
end L = {
a = mesecon:is_power_on(mesecon:addPosRule(pos, rules.a),
function mesecon.receptor_off(self, pos, rules) mesecon:invertRule(rules.a)) and
if (self.receptor_off) then mesecon:rules_link(mesecon:addPosRule(pos, rules.a), pos),
print("[Mesecons] Warning: A mod with mesecon support called mesecon:receptor_off.") b = mesecon:is_power_on(mesecon:addPosRule(pos, rules.b),
print("[Mesecons] If you are the programmer of this mod, please update it ") mesecon:invertRule(rules.b)) and
print("[Mesecons] to use mesecon.receptor_off instead. mesecon:* is deprecated") mesecon:rules_link(mesecon:addPosRule(pos, rules.b), pos),
print("[Mesecons] Otherwise, please make sure you're running the latest version") c = mesecon:is_power_on(mesecon:addPosRule(pos, rules.c),
print("[Mesecons] of that mod and inform the mod creator.") mesecon:invertRule(rules.c)) and
else mesecon:rules_link(mesecon:addPosRule(pos, rules.c), pos),
rules = pos d = mesecon:is_power_on(mesecon:addPosRule(pos, rules.d),
pos = self mesecon:invertRule(rules.d)) and
end mesecon:rules_link(mesecon:addPosRule(pos, rules.d), pos),
mesecon.queue:add_action(pos, "receptor_off", {rules}, nil, rules) }
end local n = (L.a and 1 or 0) + (L.b and 2 or 0) + (L.c and 4 or 0) + (L.d and 8 or 0) + 1
meta:set_int("real_portstates", n)
return L
end

View File

@ -30,7 +30,7 @@ minetest.register_node("mesecons:mesecon_on", {
}, },
groups = {dig_immediate=3, not_in_creaive_inventory=1, mesecon=1}, groups = {dig_immediate=3, not_in_creaive_inventory=1, mesecon=1},
drop = "mesecons:mesecon_off 1", drop = "mesecons:mesecon_off 1",
light_source = default.LIGHT_MAX-11, light_source = LIGHT_MAX-11,
mesecons = {conductor={ mesecons = {conductor={
state = mesecon.state.on, state = mesecon.state.on,
offstate = "mesecons:mesecon_off" offstate = "mesecons:mesecon_off"

View File

@ -15,13 +15,11 @@ mesecon.rules.default =
{x=0, y=1, z=-1}, {x=0, y=1, z=-1},
{x=0, y=-1, z=-1}} {x=0, y=-1, z=-1}}
mesecon.rules.pplate = mesecon.mergetable(mesecon.rules.default, {{x=0, y=-2, z=0}})
mesecon.rules.buttonlike = mesecon.rules.buttonlike =
{{x = 1, y = 0, z = 0}, {{x = 1, y = 0, z = 0},
{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 = 1, y =-1, z = 1}, {x = 1, y =-1, z = 1},
{x = 1, y =-1, z =-1}, {x = 1, y =-1, z =-1},
{x = 2, y = 0, z = 0}} {x = 2, y = 0, z = 0}}
@ -30,23 +28,15 @@ mesecon.rules.flat =
{x =-1, y = 0, z = 0}, {x =-1, y = 0, z = 0},
{x = 0, y = 0, z = 1}, {x = 0, y = 0, z = 1},
{x = 0, y = 0, z =-1}} {x = 0, y = 0, z =-1}}
mesecon.rules.alldirs =
{{x= 1, y= 0, z= 0},
{x=-1, y= 0, z= 0},
{x= 0, y= 1, z= 0},
{x= 0, y=-1, z= 0},
{x= 0, y= 0, z= 1},
{x= 0, y= 0, z=-1}}
mesecon.rules.buttonlike_get = function(node) mesecon.rules.buttonlike_get = function(node)
local rules = mesecon.rules.buttonlike local rules = mesecon.rules.buttonlike
if node.param2 == 2 then if node.param2 == 2 then
rules=mesecon.rotate_rules_left(rules) rules=mesecon:rotate_rules_left(rules)
elseif node.param2 == 3 then elseif node.param2 == 3 then
rules=mesecon.rotate_rules_right(mesecon.rotate_rules_right(rules)) rules=mesecon:rotate_rules_right(mesecon:rotate_rules_right(rules))
elseif node.param2 == 0 then elseif node.param2 == 0 then
rules=mesecon.rotate_rules_right(rules) rules=mesecon:rotate_rules_right(rules)
end end
return rules return rules
end end

View File

@ -1,68 +1,44 @@
-- Dig and place services -- Dig and place services
mesecon.on_placenode = function (pos, node) mesecon.on_placenode = function (pos, node)
mesecon.update_autoconnect(pos, node)
-- Receptors: Send on signal when active -- Receptors: Send on signal when active
if mesecon.is_receptor_on(node.name) then if mesecon:is_receptor_on(node.name) then
mesecon.receptor_on(pos, mesecon.receptor_get_rules(node)) mesecon:receptor_on(pos, mesecon:receptor_get_rules(node))
end end
-- Conductors: Send turnon signal when powered or replace by respective offstate conductor -- Conductors: Send turnon signal when powered or replace by respective offstate conductor
-- if placed conductor is an onstate one -- if placed conductor is an onstate one
if mesecon.is_conductor(node.name) then if mesecon:is_conductor(node.name) then
local sources = mesecon.is_powered(pos) if mesecon:is_powered(pos) then
if sources then
-- 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 mesecon:turnon (pos)
local rule = vector.subtract(pos, s) mesecon:receptor_on (pos, mesecon:conductor_get_rules(node))
mesecon.turnon(pos, rule) elseif mesecon:is_conductor_off(node.name) then
end minetest.swap_node(pos, {name = mesecon:get_conductor_off(node)})
--mesecon.receptor_on (pos, mesecon.conductor_get_rules(node))
elseif mesecon.is_conductor_on(node) then
minetest.swap_node(pos, {name = mesecon.get_conductor_off(node)})
end end
end end
-- Effectors: Send changesignal and activate or deactivate -- Effectors: Send changesignal and activate or deactivate
if mesecon.is_effector(node.name) then if mesecon:is_effector(node.name) then
local powered_rules = {} if mesecon:is_powered(pos) then
local unpowered_rules = {} mesecon:changesignal(pos, node, mesecon:effector_get_rules(node), "on", 1)
mesecon:activate(pos, node, nil, 1)
-- for each input rule, check if powered
for _, r in ipairs(mesecon.effector_get_rules(node)) do
local powered = mesecon.is_powered(pos, r)
if powered then table.insert(powered_rules, r)
else table.insert(unpowered_rules, r) end
local state = powered and mesecon.state.on or mesecon.state.off
mesecon.changesignal(pos, node, r, state, 1)
end
if (#powered_rules > 0) then
for _, r in ipairs(powered_rules) do
mesecon.activate(pos, node, r, 1)
end
else else
for _, r in ipairs(unpowered_rules) do mesecon:changesignal(pos, node, mesecon:effector_get_rules(node), "off", 1)
mesecon.deactivate(pos, node, r, 1) mesecon:deactivate(pos, node, nil, 1)
end
end end
end end
end end
mesecon.on_dignode = function (pos, node) mesecon.on_dignode = function (pos, node)
if mesecon.is_conductor_on(node) then if mesecon:is_conductor_on(node) then
mesecon.receptor_off(pos, mesecon.conductor_get_rules(node)) mesecon:receptor_off(pos, mesecon:conductor_get_rules(node))
elseif mesecon.is_receptor_on(node.name) then elseif mesecon:is_receptor_on(node.name) then
mesecon.receptor_off(pos, mesecon.receptor_get_rules(node)) mesecon:receptor_off(pos, mesecon:receptor_get_rules(node))
end end
mesecon.queue:add_action(pos, "update_autoconnect", {node})
end end
mesecon.queue:add_function("update_autoconnect", mesecon.update_autoconnect)
minetest.register_on_placenode(mesecon.on_placenode) minetest.register_on_placenode(mesecon.on_placenode)
minetest.register_on_dignode(mesecon.on_dignode) minetest.register_on_dignode(mesecon.on_dignode)
@ -76,7 +52,7 @@ mesecon.do_overheat = function(pos)
heat = heat + 1 heat = heat + 1
meta:set_int("heat", heat) meta:set_int("heat", heat)
if heat < mesecon.setting("overheat_max", 20) then if heat < OVERHEAT_MAX then
mesecon.queue:add_action(pos, "cooldown", {}, 1, nil, 0) mesecon.queue:add_action(pos, "cooldown", {}, 1, nil, 0)
else else
return true return true
@ -87,6 +63,10 @@ end
mesecon.queue:add_function("cooldown", function (pos) mesecon.queue:add_function("cooldown", function (pos)
if minetest.get_item_group(minetest.get_node(pos).name, "overheat") == 0 then
return -- node has been moved, this one does not use overheating - ignore
end
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
local heat = meta:get_int("heat") local heat = meta:get_int("heat")

View File

@ -1,15 +1,12 @@
-- SETTINGS -- SETTINGS
function mesecon.setting(setting, default) BLINKY_PLANT_INTERVAL = 3
if type(default) == "boolean" then NEW_STYLE_WIRES = true -- true = new nodebox wires, false = old raillike wires
local read = minetest.setting_getbool("mesecon."..setting) PRESSURE_PLATE_INTERVAL = 0.1
if read == nil then OBJECT_DETECTOR_RADIUS = 6
return default PISTON_MAXIMUM_PUSH = 15
else MOVESTONE_MAXIMUM_PUSH = 100
return read MESECONS_RESUMETIME = 4 -- time to wait when starting the server before
end -- processing the ActionQueue, don't set this too low
elseif type(default) == "string" then OVERHEAT_MAX = 20 -- maximum heat of any component that directly sends an output
return minetest.setting_get("mesecon."..setting) or default -- signal when the input changes (e.g. luacontroller, gates)
elseif type(default) == "number" then -- Unit: actions per second, checks are every 1 second
return tonumber(minetest.setting_get("mesecon."..setting) or default)
end
end

View File

Before

Width:  |  Height:  |  Size: 592 B

After

Width:  |  Height:  |  Size: 592 B

View File

Before

Width:  |  Height:  |  Size: 487 B

After

Width:  |  Height:  |  Size: 487 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 743 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 725 B

View File

Before

Width:  |  Height:  |  Size: 204 B

After

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 713 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 751 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 737 B

View File

Before

Width:  |  Height:  |  Size: 598 B

After

Width:  |  Height:  |  Size: 598 B

View File

Before

Width:  |  Height:  |  Size: 692 B

After

Width:  |  Height:  |  Size: 692 B

View File

Before

Width:  |  Height:  |  Size: 553 B

After

Width:  |  Height:  |  Size: 553 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 330 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 319 B

View File

Before

Width:  |  Height:  |  Size: 867 B

After

Width:  |  Height:  |  Size: 867 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 347 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 B

View File

Before

Width:  |  Height:  |  Size: 465 B

After

Width:  |  Height:  |  Size: 465 B

View File

Before

Width:  |  Height:  |  Size: 464 B

After

Width:  |  Height:  |  Size: 464 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 454 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 492 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 373 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 B

View File

@ -1,12 +1,24 @@
function mesecon.move_node(pos, newpos) function mesecon:move_node(pos, newpos)
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
local meta = minetest.get_meta(pos):to_table() local meta = minetest.get_meta(pos):to_table()
minetest.remove_node(pos) minetest.remove_node(pos)
minetest.set_node(newpos, node) minetest.add_node(newpos, node)
minetest.get_meta(pos):from_table(meta) minetest.get_meta(pos):from_table(meta)
end end
function mesecon.flattenrules(allrules) --[[ new functions:
mesecon:flattenrules(allrules)
mesecon:rule2bit(findrule, allrules)
mesecon:rule2meta(findrule, allrules)
dec2bin(n)
mesecon:getstate(nodename, states)
mesecon:getbinstate(nodename, states)
mesecon:get_bit(binary, bit)
mesecon:set_bit(binary, bit, value)
mesecon:invertRule(r)
--]]
function mesecon:flattenrules(allrules)
--[[ --[[
{ {
{ {
@ -41,7 +53,7 @@ function mesecon.flattenrules(allrules)
--]] --]]
end end
function mesecon.rule2bit(findrule, allrules) function mesecon:rule2bit(findrule, allrules)
--get the bit of the metarule the rule is in, or bit 1 --get the bit of the metarule the rule is in, or bit 1
if (allrules[1] and if (allrules[1] and
allrules[1].x) or allrules[1].x) or
@ -50,36 +62,35 @@ function mesecon.rule2bit(findrule, allrules)
end end
for m,metarule in ipairs( allrules) do for m,metarule in ipairs( allrules) do
for _, rule in ipairs(metarule ) do for _, rule in ipairs(metarule ) do
if vector.equals(findrule, rule) then if mesecon:cmpPos(findrule, rule) and mesecon:cmpSpecial(findrule, rule) then
return m return m
end end
end end
end end
end end
function mesecon.rule2metaindex(findrule, allrules) function mesecon:rule2metaindex(findrule, allrules)
--get the metarule the rule is in, or allrules --get the metarule the rule is in, or allrules
if allrules[1].x then if allrules[1].x then
return nil return nil
end end
if not(findrule) then if not(findrule) then
return mesecon.flattenrules(allrules) return mesecon:flattenrules(allrules)
end end
for m, metarule in ipairs( allrules) do for m, metarule in ipairs( allrules) do
for _, rule in ipairs(metarule ) do for _, rule in ipairs(metarule ) do
if vector.equals(findrule, rule) then if mesecon:cmpPos(findrule, rule) and mesecon:cmpSpecial(findrule, rule) then
return m return m
end end
end end
end end
end end
function mesecon.rule2meta(findrule, allrules) function mesecon:rule2meta(findrule, allrules)
if #allrules == 0 then return {} end local index = mesecon:rule2metaindex(findrule, allrules)
local index = mesecon.rule2metaindex(findrule, allrules)
if index == nil then if index == nil then
if allrules[1].x then if allrules[1].x then
return allrules return allrules
@ -90,16 +101,25 @@ function mesecon.rule2meta(findrule, allrules)
return allrules[index] return allrules[index]
end end
function mesecon.dec2bin(n) if convert_base then
local x, y = math.floor(n / 2), n % 2 print(
if (n > 1) then "base2dec is tonumber(num,base1)\n"..
return mesecon.dec2bin(x)..y "commonlib needs dec2base(num,base2)\n"..
else "and it needs base2base(num,base1,base2),\n"..
return ""..y "which is dec2base(tonumber(num,base1),base2)"
)
else
function dec2bin(n)
local x, y = math.floor(n / 2), n % 2
if (n > 1) then
return dec2bin(x)..y
else
return ""..y
end
end end
end end
function mesecon.getstate(nodename, states) function mesecon:getstate(nodename, states)
for state, name in ipairs(states) do for state, name in ipairs(states) do
if name == nodename then if name == nodename then
return state return state
@ -108,41 +128,53 @@ function mesecon.getstate(nodename, states)
error(nodename.." doesn't mention itself in "..dump(states)) error(nodename.." doesn't mention itself in "..dump(states))
end end
function mesecon.getbinstate(nodename, states) function mesecon:getbinstate(nodename, states)
return mesecon.dec2bin(mesecon.getstate(nodename, states)-1) return dec2bin(mesecon:getstate(nodename, states)-1)
end 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 c = binary:len()-(bit-1)
return binary:sub(c,c) == "1" return binary:sub(c,c) == "1"
end end
function mesecon.set_bit(binary,bit,value) function mesecon:set_bit(binary,bit,value)
if value == "1" then if value == "1" then
if not mesecon.get_bit(binary,bit) then if not mesecon:get_bit(binary,bit) then
return mesecon.dec2bin(tonumber(binary,2)+math.pow(2,bit-1)) return dec2bin(tonumber(binary,2)+math.pow(2,bit-1))
end end
elseif value == "0" then elseif value == "0" then
if mesecon.get_bit(binary,bit) then if mesecon:get_bit(binary,bit) then
return mesecon.dec2bin(tonumber(binary,2)-math.pow(2,bit-1)) return dec2bin(tonumber(binary,2)-math.pow(2,bit-1))
end end
end end
return binary return binary
end end
function mesecon.invertRule(r) function mesecon:invertRule(r)
return vector.multiply(r, -1) return {x = -r.x, y = -r.y, z = -r.z, sx = r.sx, sy = r.sy, sz = r.sz}
end end
function mesecon.tablecopy(table) -- deep table copy function mesecon:addPosRule(p, r)
return {x = p.x + r.x, y = p.y + r.y, z = p.z + r.z}
end
function mesecon:cmpPos(p1, p2)
return (p1.x == p2.x and p1.y == p2.y and p1.z == p2.z)
end
function mesecon:cmpSpecial(r1, r2)
return (r1.sx == r2.sx and r1.sy == r2.sy and r1.sz == r2.sz)
end
function mesecon:tablecopy(table) -- deep table copy
if type(table) ~= "table" then return table end -- no need to copy if type(table) ~= "table" then return table end -- no need to copy
local newtable = {} local newtable = {}
for idx, item in pairs(table) do for idx, item in pairs(table) do
if type(item) == "table" then if type(item) == "table" then
newtable[idx] = mesecon.tablecopy(item) newtable[idx] = mesecon:tablecopy(item)
else else
newtable[idx] = item newtable[idx] = item
end end
@ -151,125 +183,13 @@ function mesecon.tablecopy(table) -- deep table copy
return newtable return newtable
end end
function mesecon.cmpAny(t1, t2) function mesecon:cmpAny(t1, t2)
if type(t1) ~= type(t2) then return false end if type(t1) ~= type(t2) then return false end
if type(t1) ~= "table" and type(t2) ~= "table" then return t1 == t2 end if type(t1) ~= "table" and type(t2) ~= "table" then return t1 == t2 end
for i, e in pairs(t1) do for i, e in pairs(t1) do
if not mesecon.cmpAny(e, t2[i]) then return false end if not mesecon:cmpAny(e, t2[i]) then return false end
end end
return true return true
end 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)
end
for i, v in ipairs(source) do
table.insert(rval, mesecon.tablecopy(v))
end
return rval
end
function mesecon.register_node(name, spec_common, spec_off, spec_on)
spec_common.drop = spec_common.drop or name .. "_off"
spec_common.__mesecon_basename = name
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);
minetest.register_node(name .. "_on", spec_on)
minetest.register_node(name .. "_off", spec_off)
end
-- 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
minetest.swap_node(pos, {name = nodedef.__mesecon_basename .. "_" .. newstate,
param2 = node.param2})
return newstate
end
-- 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
-- Forceloading: Force server to load area if node is nil
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
-- convert block hash --> node position
local function unhash_blockpos(hash)
return vector.multiply(minetest.get_position_from_hash(hash), BLOCKSIZE)
end
mesecon.forceloaded_blocks = {}
-- get node and force-load area
function mesecon.get_node_force(pos)
local hash = hash_blockpos(pos)
if mesecon.forceloaded_blocks[hash] == nil then
-- if no more forceload spaces are available, try again next time
if minetest.forceload_block(pos) then
mesecon.forceloaded_blocks[hash] = 0
end
else
mesecon.forceloaded_blocks[hash] = 0
end
return minetest.get_node_or_nil(pos)
end
minetest.register_globalstep(function (dtime)
for hash, time in pairs(mesecon.forceloaded_blocks) do
-- unload forceloaded blocks after 10 minutes without usage
if (time > mesecon.setting("forceload_timeout", 600)) then
minetest.forceload_free_block(unhash_blockpos(hash))
mesecon.forceloaded_blocks[hash] = nil
else
mesecon.forceloaded_blocks[hash] = time + dtime
end
end
end)
-- Store and read the forceloaded blocks to / from a file
-- so that those blocks are remembered when the game
-- is restarted
mesecon.forceloaded_blocks = mesecon.file2table("mesecon_forceloaded")
minetest.register_on_shutdown(function()
mesecon.table2file("mesecon_forceloaded", mesecon.forceloaded_blocks)
end)

View File

@ -1,250 +1,280 @@
-- naming scheme: wire:(xp)(zp)(xm)(zm)(xpyp)(zpyp)(xmyp)(zmyp)_on/off -- naming scheme: wire:(xp)(zp)(xm)(zm)_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 conditions in brackets define whether there is a mesecon at that place or not
-- The (xp)/(zpyp)/.. statements shall be replaced by either 0 or 1 -- 1 = there is one; 0 = there is none
-- Where 0 means the wire has no visual connection to that direction and -- y always means y+
-- 1 means that the wire visually connects to that other node.
-- ####################### box_center = {-1/16, -.5, -1/16, 1/16, -.5+1/16, 1/16}
-- ## Update wire looks ## box_bump1 = { -2/16, -8/16, -2/16, 2/16, -13/32, 2/16 }
-- #######################
-- self_pos = pos of any mesecon node, from_pos = pos of conductor to getconnect for box_xp = {1/16, -.5, -1/16, 8/16, -.5+1/16, 1/16}
local wire_getconnect = function (from_pos, self_pos) box_zp = {-1/16, -.5, 1/16, 1/16, -.5+1/16, 8/16}
local node = minetest.get_node(self_pos) box_xm = {-8/16, -.5, -1/16, -1/16, -.5+1/16, 1/16}
if minetest.registered_nodes[node.name] box_zm = {-1/16, -.5, -8/16, 1/16, -.5+1/16, -1/16}
and minetest.registered_nodes[node.name].mesecons then
-- rules of node to possibly connect to
local rules = {}
if (minetest.registered_nodes[node.name].mesecon_wire) then
rules = mesecon.rules.default
else
rules = mesecon.get_any_rules(node)
end
for _, r in ipairs(mesecon.flattenrules(rules)) do box_xpy = {.5-1/16, -.5+1/16, -1/16, .5, .4999+1/16, 1/16}
if (vector.equals(vector.add(self_pos, r), from_pos)) then box_zpy = {-1/16, -.5+1/16, .5-1/16, 1/16, .4999+1/16, .5}
return true box_xmy = {-.5, -.5+1/16, -1/16, -.5+1/16, .4999+1/16, 1/16}
end box_zmy = {-1/16, -.5+1/16, -.5, 1/16, .4999+1/16, -.5+1/16}
end
end
return false
end
-- Update this node -- Registering the wires
local wire_updateconnect = function (pos)
local connections = {}
for _, r in ipairs(mesecon.rules.default) do for xp=0, 1 do
if wire_getconnect(pos, vector.add(pos, r)) then for zp=0, 1 do
table.insert(connections, r) for xm=0, 1 do
end for zm=0, 1 do
end for xpy=0, 1 do
for zpy=0, 1 do
for xmy=0, 1 do
for zmy=0, 1 do
if (xpy == 1 and xp == 0) or (zpy == 1 and zp == 0)
or (xmy == 1 and xm == 0) or (zmy == 1 and zm == 0) then break end
local nid = {} local groups
for _, vec in ipairs(connections) do local nodeid = tostring(xp )..tostring(zp )..tostring(xm )..tostring(zm )..
-- flat component tostring(xpy)..tostring(zpy)..tostring(xmy)..tostring(zmy)
if vec.x == 1 then nid[0] = "1" end
if vec.z == 1 then nid[1] = "1" end
if vec.x == -1 then nid[2] = "1" end
if vec.z == -1 then nid[3] = "1" end
-- slopy component if nodeid == "00000000" then
if vec.y == 1 then groups = {dig_immediate = 3, mesecon_conductor_craftable=1}
if vec.x == 1 then nid[4] = "1" end wiredesc = "Mesecon"
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
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 state_suffix = string.find(minetest.get_node(pos).name, "_off") and "_off" or "_on"
minetest.set_node(pos, {name = "mesecons:wire_"..nodeid..state_suffix})
end
local update_on_place_dig = function (pos, node)
-- Update placed node (get_node again as it may have been dug)
local nn = minetest.get_node(pos)
if (minetest.registered_nodes[nn.name])
and (minetest.registered_nodes[nn.name].mesecon_wire) then
wire_updateconnect(pos)
end
-- Update nodes around it
local rules = {}
if minetest.registered_nodes[node.name]
and minetest.registered_nodes[node.name].mesecon_wire then
rules = mesecon.rules.default
else else
rules = mesecon.get_any_rules(node) groups = {dig_immediate = 3, not_in_creative_inventory = 1}
end wiredesc = "Mesecons Wire (ID: "..nodeid..")"
if (not rules) then return end
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)
end
end
end
function mesecon.update_autoconnect(pos, node)
if (not node) then node = minetest.get_node(pos) end
update_on_place_dig(pos, node)
end
-- ############################
-- ## Wire node registration ##
-- ############################
-- Nodeboxes:
local box_center = {-1/16, -.5, -1/16, 1/16, -.5+1/16, 1/16}
local box_bump1 = { -2/16, -8/16, -2/16, 2/16, -13/32, 2/16 }
local nbox_nid =
{
[0] = {1/16, -.5, -1/16, 8/16, -.5+1/16, 1/16}, -- x positive
[1] = {-1/16, -.5, 1/16, 1/16, -.5+1/16, 8/16}, -- z positive
[2] = {-8/16, -.5, -1/16, -1/16, -.5+1/16, 1/16}, -- x negative
[3] = {-1/16, -.5, -8/16, 1/16, -.5+1/16, -1/16}, -- z negative
[4] = {.5-1/16, -.5+1/16, -1/16, .5, .4999+1/16, 1/16}, -- x positive up
[5] = {-1/16, -.5+1/16, .5-1/16, 1/16, .4999+1/16, .5}, -- z positive up
[6] = {-.5, -.5+1/16, -1/16, -.5+1/16, .4999+1/16, 1/16}, -- x negative up
[7] = {-1/16, -.5+1/16, -.5, 1/16, .4999+1/16, -.5+1/16} -- z negative up
}
local tiles_off = { "mesecons_wire_off.png" }
local tiles_on = { "mesecons_wire_on.png" }
local selectionbox =
{
type = "fixed",
fixed = {-.5, -.5, -.5, .5, -.5+4/16, .5}
}
-- go to the next nodeid (ex.: 01000011 --> 01000100)
local nid_inc = function() end
nid_inc = function (nid)
local i = 0
while nid[i-1] ~= 1 do
nid[i] = (nid[i] ~= 1) and 1 or 0
i = i + 1
end end
-- BUT: Skip impossible nodeids: local nodebox = {}
if ((nid[0] == 0 and nid[4] == 1) or (nid[1] == 0 and nid[5] == 1) local adjx = false
or (nid[2] == 0 and nid[6] == 1) or (nid[3] == 0 and nid[7] == 1)) then local adjz = false
return nid_inc(nid) if xp == 1 then table.insert(nodebox, box_xp) adjx = true end
if zp == 1 then table.insert(nodebox, box_zp) adjz = true end
if xm == 1 then table.insert(nodebox, box_xm) adjx = true end
if zm == 1 then table.insert(nodebox, box_zm) adjz = true end
if xpy == 1 then table.insert(nodebox, box_xpy) end
if zpy == 1 then table.insert(nodebox, box_zpy) end
if xmy == 1 then table.insert(nodebox, box_xmy) end
if zmy == 1 then table.insert(nodebox, box_zmy) end
if adjx and adjz and (xp + zp + xm + zm > 2) then
table.insert(nodebox, box_bump1)
tiles_off = {
"wires_bump_off.png",
"wires_bump_off.png",
"wires_vertical_off.png",
"wires_vertical_off.png",
"wires_vertical_off.png",
"wires_vertical_off.png"
}
tiles_on = {
"wires_bump_on.png",
"wires_bump_on.png",
"wires_vertical_on.png",
"wires_vertical_on.png",
"wires_vertical_on.png",
"wires_vertical_on.png"
}
else
table.insert(nodebox, box_center)
tiles_off = {
"wires_off.png",
"wires_off.png",
"wires_vertical_off.png",
"wires_vertical_off.png",
"wires_vertical_off.png",
"wires_vertical_off.png"
}
tiles_on = {
"wires_on.png",
"wires_on.png",
"wires_vertical_on.png",
"wires_vertical_on.png",
"wires_vertical_on.png",
"wires_vertical_on.png"
}
end end
return i <= 8 if nodeid == "00000000" then
end nodebox = {-8/16, -.5, -1/16, 8/16, -.5+1/16, 1/16}
end
register_wires = function() minetest.register_node("mesecons:wire_"..nodeid.."_off", {
local nid = {} description = wiredesc,
while true do drawtype = "nodebox",
-- Create group specifiction and nodeid string (see note above for details) tiles = tiles_off,
local nodeid = (nid[0] or "0")..(nid[1] or "0")..(nid[2] or "0")..(nid[3] or "0") -- inventory_image = "wires_inv.png",
..(nid[4] or "0")..(nid[5] or "0")..(nid[6] or "0")..(nid[7] or "0") -- wield_image = "wires_inv.png",
inventory_image = "jeija_mesecon_off.png",
-- Calculate nodebox wield_image = "jeija_mesecon_off.png",
local nodebox = {type = "fixed", fixed={box_center}} paramtype = "light",
for i=0,7 do paramtype2 = "facedir",
if nid[i] == 1 then sunlight_propagates = true,
table.insert(nodebox.fixed, nbox_nid[i]) selection_box = {
end type = "fixed",
end fixed = {-.5, -.5, -.5, .5, -.5+4/16, .5}
},
-- Add bump to nodebox if curved node_box = {
if (nid[0] == 1 and nid[1] == 1) or (nid[1] == 1 and nid[2] == 1) type = "fixed",
or (nid[2] == 1 and nid[3] == 1) or (nid[3] == 1 and nid[0] == 1) then fixed = nodebox
table.insert(nodebox.fixed, box_bump1) },
end groups = groups,
walkable = false,
-- If nothing to connect to, still make a nodebox of a straight wire stack_max = 99,
if nodeid == "00000000" then drop = "mesecons:wire_00000000_off",
nodebox.fixed = {-8/16, -.5, -1/16, 8/16, -.5+1/16, 1/16} mesecons = {conductor={
end
local rules = {}
if (nid[0] == 1) then table.insert(rules, vector.new( 1, 0, 0)) end
if (nid[1] == 1) then table.insert(rules, vector.new( 0, 0, 1)) end
if (nid[2] == 1) then table.insert(rules, vector.new(-1, 0, 0)) end
if (nid[3] == 1) then table.insert(rules, vector.new( 0, 0, -1)) end
if (nid[0] == 1) then table.insert(rules, vector.new( 1, -1, 0)) end
if (nid[1] == 1) then table.insert(rules, vector.new( 0, -1, 1)) end
if (nid[2] == 1) then table.insert(rules, vector.new(-1, -1, 0)) end
if (nid[3] == 1) then table.insert(rules, vector.new( 0, -1, -1)) end
if (nid[4] == 1) then table.insert(rules, vector.new( 1, 1, 0)) end
if (nid[5] == 1) then table.insert(rules, vector.new( 0, 1, 1)) end
if (nid[6] == 1) then table.insert(rules, vector.new(-1, 1, 0)) end
if (nid[7] == 1) then table.insert(rules, vector.new( 0, 1, -1)) end
local meseconspec_off = { conductor = {
rules = rules,
state = mesecon.state.off, state = mesecon.state.off,
onstate = "mesecons:wire_"..nodeid.."_on" onstate = "mesecons:wire_"..nodeid.."_on"
}} }}
})
local meseconspec_on = { conductor = { minetest.register_node("mesecons:wire_"..nodeid.."_on", {
rules = rules, description = "Wire ID:"..nodeid,
drawtype = "nodebox",
tiles = tiles_on,
-- inventory_image = "wires_inv.png",
-- wield_image = "wires_inv.png",
inventory_image = "jeija_mesecon_off.png",
wield_image = "jeija_mesecon_off.png",
paramtype = "light",
paramtype2 = "facedir",
sunlight_propagates = true,
selection_box = {
type = "fixed",
fixed = {-.5, -.5, -.5, .5, -.5+4/16, .5}
},
node_box = {
type = "fixed",
fixed = nodebox
},
groups = {dig_immediate = 3, mesecon = 2, not_in_creative_inventory = 1},
walkable = false,
stack_max = 99,
drop = "mesecons:wire_00000000_off",
mesecons = {conductor={
state = mesecon.state.on, state = mesecon.state.on,
offstate = "mesecons:wire_"..nodeid.."_off" offstate = "mesecons:wire_"..nodeid.."_off"
}} }}
})
end
end
end
end
end
end
end
end
local groups_on = {dig_immediate = 3, mesecon_conductor_craftable = 1, -- Updating the wires:
not_in_creative_inventory = 1} -- Place the right connection wire
local groups_off = {dig_immediate = 3, mesecon_conductor_craftable = 1}
if nodeid ~= "00000000" then
groups_off["not_in_creative_inventory"] = 1
end
mesecon.register_node("mesecons:wire_"..nodeid, { local update_on_place_dig = function (pos, node)
description = "Mesecon", if minetest.registered_nodes[node.name]
drawtype = "nodebox", and minetest.registered_nodes[node.name].mesecons then
inventory_image = "mesecons_wire_inv.png", mesecon:update_autoconnect(pos)
wield_image = "mesecons_wire_inv.png",
paramtype = "light",
paramtype2 = "facedir",
sunlight_propagates = true,
selection_box = selectionbox,
node_box = nodebox,
walkable = false,
drop = "mesecons:wire_00000000_off",
mesecon_wire = true
}, {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 end
end end
register_wires()
-- ############## minetest.register_on_placenode(update_on_place_dig)
-- ## Crafting ## minetest.register_on_dignode(update_on_place_dig)
-- ##############
minetest.register_craft({ function mesecon:update_autoconnect(pos, secondcall, replace_old)
type = "cooking", local xppos = {x=pos.x+1, y=pos.y, z=pos.z}
output = "mesecons:wire_00000000_off 2", local zppos = {x=pos.x, y=pos.y, z=pos.z+1}
recipe = "default:mese_crystal_fragment", local xmpos = {x=pos.x-1, y=pos.y, z=pos.z}
cooktime = 3, local zmpos = {x=pos.x, y=pos.y, z=pos.z-1}
})
local xpympos = {x=pos.x+1, y=pos.y-1, z=pos.z}
local zpympos = {x=pos.x, y=pos.y-1, z=pos.z+1}
local xmympos = {x=pos.x-1, y=pos.y-1, z=pos.z}
local zmympos = {x=pos.x, y=pos.y-1, z=pos.z-1}
local xpypos = {x=pos.x+1, y=pos.y+1, z=pos.z}
local zpypos = {x=pos.x, y=pos.y+1, z=pos.z+1}
local xmypos = {x=pos.x-1, y=pos.y+1, z=pos.z}
local zmypos = {x=pos.x, y=pos.y+1, z=pos.z-1}
if secondcall == nil then
mesecon:update_autoconnect(xppos, true)
mesecon:update_autoconnect(zppos, true)
mesecon:update_autoconnect(xmpos, true)
mesecon:update_autoconnect(zmpos, true)
mesecon:update_autoconnect(xpypos, true)
mesecon:update_autoconnect(zpypos, true)
mesecon:update_autoconnect(xmypos, true)
mesecon:update_autoconnect(zmypos, true)
mesecon:update_autoconnect(xpympos, true)
mesecon:update_autoconnect(zpympos, true)
mesecon:update_autoconnect(xmympos, true)
mesecon:update_autoconnect(zmympos, true)
end
nodename = minetest.get_node(pos).name
if string.find(nodename, "mesecons:wire_") == nil and not replace_old then return nil end
if mesecon:rules_link_anydir(pos, xppos) then xp = 1 else xp = 0 end
if mesecon:rules_link_anydir(pos, xmpos) then xm = 1 else xm = 0 end
if mesecon:rules_link_anydir(pos, zppos) then zp = 1 else zp = 0 end
if mesecon:rules_link_anydir(pos, zmpos) then zm = 1 else zm = 0 end
if mesecon:rules_link_anydir(pos, xpympos) then xp = 1 end
if mesecon:rules_link_anydir(pos, xmympos) then xm = 1 end
if mesecon:rules_link_anydir(pos, zpympos) then zp = 1 end
if mesecon:rules_link_anydir(pos, zmympos) then zm = 1 end
if mesecon:rules_link_anydir(pos, xpypos) then xpy = 1 else xpy = 0 end
if mesecon:rules_link_anydir(pos, zpypos) then zpy = 1 else zpy = 0 end
if mesecon:rules_link_anydir(pos, xmypos) then xmy = 1 else xmy = 0 end
if mesecon:rules_link_anydir(pos, zmypos) then zmy = 1 else zmy = 0 end
if xpy == 1 then xp = 1 end
if zpy == 1 then zp = 1 end
if xmy == 1 then xm = 1 end
if zmy == 1 then zm = 1 end
local nodeid = tostring(xp )..tostring(zp )..tostring(xm )..tostring(zm )..
tostring(xpy)..tostring(zpy)..tostring(xmy)..tostring(zmy)
if string.find(nodename, "_off") ~= nil then
minetest.set_node(pos, {name = "mesecons:wire_"..nodeid.."_off"})
else
minetest.set_node(pos, {name = "mesecons:wire_"..nodeid.."_on" })
end
end
if not minetest.registered_nodes["default:stone_with_mese"] then --before MESE update, use old recipes
minetest.register_craft({
output = "mesecons:wire_00000000_off 18",
recipe = {
{"default:mese"},
}
})
else
minetest.register_craft({
type = "cooking",
output = "mesecons:wire_00000000_off 2",
recipe = "default:mese_crystal_fragment",
cooktime = 3,
})
minetest.register_craft({
type = "cooking",
output = "mesecons:wire_00000000_off 18",
recipe = "default:mese_crystal",
cooktime = 15,
})
minetest.register_craft({
type = "cooking",
output = "mesecons:wire_00000000_off 162",
recipe = "default:mese",
cooktime = 30,
})
end
minetest.register_craft({ minetest.register_craft({
type = "cooking", type = "cooking",
output = "mesecons:wire_00000000_off 18", output = "mesecons:wire_00000000_off 16",
recipe = "default:mese_crystal", recipe = "default:mese_crystal",
cooktime = 15,
})
minetest.register_craft({
type = "cooking",
output = "mesecons:wire_00000000_off 162",
recipe = "default:mese",
cooktime = 30,
}) })

View File

@ -1 +0,0 @@
The blinky plants toggles between on and off state every three seconds. Can be used to make clocks. Also works after having restarted the game.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -1,51 +1,102 @@
-- The BLINKY_PLANT -- The BLINKY_PLANT
minetest.register_node("mesecons_blinkyplant:blinky_plant", {
local toggle_timer = function (pos)
local timer = minetest.get_node_timer(pos)
if timer:is_started() then
timer:stop()
else
timer:start(mesecon.setting("blinky_plant_interval", 3))
end
end
local on_timer = function (pos)
local node = minetest.get_node(pos)
if(mesecon.flipstate(pos, node) == "on") then
mesecon.receptor_on(pos)
else
mesecon.receptor_off(pos)
end
toggle_timer(pos)
end
mesecon.register_node("mesecons_blinkyplant:blinky_plant", {
description="Blinky Plant",
drawtype = "plantlike", drawtype = "plantlike",
visual_scale = 1,
tiles = {"jeija_blinky_plant_off.png"},
inventory_image = "jeija_blinky_plant_off.png", inventory_image = "jeija_blinky_plant_off.png",
paramtype = "light",
walkable = false, walkable = false,
groups = {dig_immediate=3, not_in_creative_inventory=1},
drop="mesecons_blinkyplant:blinky_plant_off 1",
description="Deactivated Blinky Plant",
sounds = default.node_sound_leaves_defaults(), sounds = default.node_sound_leaves_defaults(),
selection_box = { selection_box = {
type = "fixed", type = "fixed",
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, mesecons = {receptor = {
on_rightclick = toggle_timer, state = mesecon.state.off
on_construct = toggle_timer }},
},{ on_rightclick = function(pos, node, clicker)
minetest.set_node(pos, {name="mesecons_blinkyplant:blinky_plant_off"})
end
})
minetest.register_node("mesecons_blinkyplant:blinky_plant_off", {
drawtype = "plantlike",
visual_scale = 1,
tiles = {"jeija_blinky_plant_off.png"}, tiles = {"jeija_blinky_plant_off.png"},
groups = {dig_immediate=3}, inventory_image = "jeija_blinky_plant_off.png",
mesecons = {receptor = { state = mesecon.state.off }} paramtype = "light",
},{ walkable = false,
groups = {dig_immediate=3, mesecon=2},
description="Blinky Plant",
sounds = default.node_sound_leaves_defaults(),
selection_box = {
type = "fixed",
fixed = {-0.3, -0.5, -0.3, 0.3, -0.5+0.7, 0.3},
},
mesecons = {receptor = {
state = mesecon.state.off
}},
on_rightclick = function(pos, node, clicker)
minetest.set_node(pos, {name="mesecons_blinkyplant:blinky_plant"})
end
})
minetest.register_node("mesecons_blinkyplant:blinky_plant_on", {
drawtype = "plantlike",
visual_scale = 1,
tiles = {"jeija_blinky_plant_on.png"}, tiles = {"jeija_blinky_plant_on.png"},
groups = {dig_immediate=3, not_in_creative_inventory=1}, inventory_image = "jeija_blinky_plant_off.png",
mesecons = {receptor = { state = mesecon.state.on }} paramtype = "light",
walkable = false,
groups = {dig_immediate=3, not_in_creative_inventory=1, mesecon=2},
drop="mesecons_blinkyplant:blinky_plant_off 1",
light_source = LIGHT_MAX-7,
description = "Blinky Plant",
sounds = default.node_sound_leaves_defaults(),
selection_box = {
type = "fixed",
fixed = {-0.3, -0.5, -0.3, 0.3, -0.5+0.7, 0.3},
},
mesecons = {receptor = {
state = mesecon.state.on
}},
on_rightclick = function(pos, node, clicker)
minetest.set_node(pos, {name = "mesecons_blinkyplant:blinky_plant"})
mesecon:receptor_off(pos)
end
}) })
minetest.register_craft({ minetest.register_craft({
output = "mesecons_blinkyplant:blinky_plant_off 1", output = "mesecons_blinkyplant:blinky_plant_off 1",
recipe = { {"","group:mesecon_conductor_craftable",""}, recipe = {
{"","group:mesecon_conductor_craftable",""}, {"","group:mesecon_conductor_craftable",""},
{"group:sapling","group:sapling","group:sapling"}} {"","group:mesecon_conductor_craftable",""},
{"default:sapling","default:sapling","default:sapling"},
}
})
minetest.register_abm(
{nodenames = {"mesecons_blinkyplant:blinky_plant_off"},
interval = BLINKY_PLANT_INTERVAL,
chance = 1,
action = function(pos, node, active_object_count, active_object_count_wider)
--minetest.remove_node(pos)
minetest.add_node(pos, {name="mesecons_blinkyplant:blinky_plant_on"})
nodeupdate(pos)
mesecon:receptor_on(pos)
end,
})
minetest.register_abm({
nodenames = {"mesecons_blinkyplant:blinky_plant_on"},
interval = BLINKY_PLANT_INTERVAL,
chance = 1,
action = function(pos, node, active_object_count, active_object_count_wider)
--minetest.remove_node(pos)
minetest.add_node(pos, {name="mesecons_blinkyplant:blinky_plant_off"})
nodeupdate(pos)
mesecon:receptor_off(pos)
end,
}) })

View File

@ -1 +0,0 @@
This receptor can be attached to walls. It turns on for 1 second if it's punched.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

View File

@ -8,14 +8,14 @@ mesecon.button_turnoff = function (pos)
minetest.swap_node(pos, {name = "mesecons_button:button_off", param2=node.param2}) minetest.swap_node(pos, {name = "mesecons_button:button_off", param2=node.param2})
minetest.sound_play("mesecons_button_pop", {pos=pos}) minetest.sound_play("mesecons_button_pop", {pos=pos})
local rules = mesecon.rules.buttonlike_get(node) local rules = mesecon.rules.buttonlike_get(node)
mesecon.receptor_off(pos, rules) mesecon:receptor_off(pos, rules)
end end
end end
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",
@ -32,7 +32,7 @@ minetest.register_node("mesecons_button:button_off", {
fixed = { -6/16, -6/16, 5/16, 6/16, 6/16, 8/16 } fixed = { -6/16, -6/16, 5/16, 6/16, 6/16, 8/16 }
}, },
node_box = { node_box = {
type = "fixed", type = "fixed",
fixed = { fixed = {
{ -6/16, -6/16, 6/16, 6/16, 6/16, 8/16 }, -- the thin plate behind the button { -6/16, -6/16, 6/16, 6/16, 6/16, 8/16 }, -- the thin plate behind the button
{ -4/16, -2/16, 4/16, 4/16, 2/16, 6/16 } -- the button itself { -4/16, -2/16, 4/16, 4/16, 2/16, 6/16 } -- the button itself
@ -40,9 +40,9 @@ minetest.register_node("mesecons_button:button_off", {
}, },
groups = {dig_immediate=2, mesecon_needs_receiver = 1}, groups = {dig_immediate=2, mesecon_needs_receiver = 1},
description = "Button", description = "Button",
on_rightclick = function (pos, node) on_punch = function (pos, node)
minetest.swap_node(pos, {name = "mesecons_button:button_on", param2=node.param2}) minetest.swap_node(pos, {name = "mesecons_button:button_on", param2=node.param2})
mesecon.receptor_on(pos, mesecon.rules.buttonlike_get(node)) mesecon:receptor_on(pos, mesecon.rules.buttonlike_get(node))
minetest.sound_play("mesecons_button_push", {pos=pos}) minetest.sound_play("mesecons_button_push", {pos=pos})
minetest.after(1, mesecon.button_turnoff, pos) minetest.after(1, mesecon.button_turnoff, pos)
end, end,
@ -67,7 +67,7 @@ minetest.register_node("mesecons_button:button_on", {
paramtype2 = "facedir", paramtype2 = "facedir",
legacy_wallmounted = true, legacy_wallmounted = true,
walkable = false, walkable = false,
light_source = default.LIGHT_MAX-7, light_source = LIGHT_MAX-7,
sunlight_propagates = true, sunlight_propagates = true,
selection_box = { selection_box = {
type = "fixed", type = "fixed",

View File

@ -1 +0,0 @@
There is no crafting recipe as this should only be available for server admins. Quite similar to the Minecraft counterpart. Executes server commands.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

View File

@ -1,208 +1,195 @@
minetest.register_chatcommand("say", { minetest.register_chatcommand("say", {
params = "<text>", params = "<text>",
description = "Say <text> as the server", description = "Say <text> as the server",
privs = {server=true}, privs = {server=true},
func = function(name, param) func = function(name, param)
minetest.chat_send_all(name .. ": " .. param) minetest.chat_send_all(name .. ": " .. param)
end end
}) })
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",
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
minetest.chat_send_player(name, "Invalid usage: " .. param) minetest.chat_send_player(name, "Invalid usage: " .. param)
return return
end end
if not minetest.get_player_by_name(target) then if not minetest.get_player_by_name(target) then
minetest.chat_send_player(name, "Invalid target: " .. target) minetest.chat_send_player(name, "Invalid target: " .. target)
end end
minetest.chat_send_player(target, name .. " whispers: " .. message, false) minetest.chat_send_player(target, name .. " whispers: " .. message, false)
end end
}) })
minetest.register_chatcommand("hp", { minetest.register_chatcommand("hp", {
params = "<name> <value>", params = "<name> <value>",
description = "Set health of <name> to <value> hitpoints", description = "Set health of <name> to <value> hitpoints",
privs = {ban=true}, privs = {ban=true},
func = function(name, param) func = function(name, param)
local found, _, target, value = param:find("^([^%s]+)%s+(%d+)$") local found, _, target, value = param:find("^([^%s]+)%s+(%d+)$")
if found == nil then if found == nil then
minetest.chat_send_player(name, "Invalid usage: " .. param) minetest.chat_send_player(name, "Invalid usage: " .. param)
return return
end end
local player = minetest.get_player_by_name(target) local player = minetest.get_player_by_name(target)
if player then if player then
player:set_hp(value) player:set_hp(value)
else else
minetest.chat_send_player(name, "Invalid target: " .. target) minetest.chat_send_player(name, "Invalid target: " .. target)
end end
end end
}) })
local function initialize_data(meta) local function initialize_data(meta)
local commands = minetest.formspec_escape(meta:get_string("commands")) local commands = meta:get_string("commands")
meta:set_string("formspec", meta:set_string("formspec",
"invsize[9,5;]" .. "invsize[9,5;]" ..
"textarea[0.5,0.5;8.5,4;commands;Commands;"..commands.."]" .. "textarea[0.5,0.5;8.5,4;commands;Commands;"..commands.."]" ..
"label[1,3.8;@nearest, @farthest, and @random are replaced by the respective player names]" .. "label[1,3.8;@nearest, @farthest, and @random are replaced by the respective player names]" ..
"button_exit[3.3,4.5;2,1;submit;Submit]") "button_exit[3.3,4.5;2,1;submit;Submit]")
local owner = meta:get_string("owner") local owner = meta:get_string("owner")
if owner == "" then if owner == "" then
owner = "not owned" owner = "not owned"
else else
owner = "owned by " .. owner owner = "owned by " .. owner
end end
meta:set_string("infotext", "Command Block\n" .. meta:set_string("infotext", "Command Block\n" ..
"(" .. owner .. ")\n" .. "(" .. owner .. ")\n" ..
"Commands: "..commands) "Commands: "..commands)
end end
local function construct(pos) local function construct(pos)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
meta:set_string("commands", "tell @nearest Commandblock unconfigured") meta:set_string("commands", "tell @nearest Commandblock unconfigured")
meta:set_string("owner", "") meta:set_string("owner", "")
initialize_data(meta) initialize_data(meta)
end end
local function after_place(pos, placer) local function after_place(pos, placer)
if placer then if placer then
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
meta:set_string("owner", placer:get_player_name()) meta:set_string("owner", placer:get_player_name())
initialize_data(meta) initialize_data(meta)
end end
end end
local function receive_fields(pos, formname, fields, sender) local function receive_fields(pos, formname, fields, sender)
if not fields.submit then if fields.quit then
return return
end end
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
local owner = meta:get_string("owner") local owner = meta:get_string("owner")
if owner ~= "" and sender:get_player_name() ~= owner then if owner ~= "" and sender:get_player_name() ~= owner then
return return
end end
meta:set_string("commands", fields.commands) meta:set_string("commands", fields.commands)
initialize_data(meta) initialize_data(meta)
end end
local function resolve_commands(commands, pos) local function resolve_commands(commands, pos)
local players = minetest.get_connected_players() local nearest, farthest = nil, nil
local min_distance, max_distance = math.huge, -1
-- No players online: remove all commands containing local players = minetest.get_connected_players()
-- @nearest, @farthest and @random for index, player in pairs(players) do
if #players == 0 then local distance = vector.distance(pos, player:getpos())
commands = commands:gsub("[^\r\n]+", function (line) if distance < min_distance then
if line:find("@nearest") then return "" end min_distance = distance
if line:find("@farthest") then return "" end nearest = player:get_player_name()
if line:find("@random") then return "" end end
return line if distance > max_distance then
end) max_distance = distance
return commands farthest = player:get_player_name()
end end
end
local nearest, farthest = nil, nil local random = players[math.random(#players)]:get_player_name()
local min_distance, max_distance = math.huge, -1 commands = commands:gsub("@nearest", nearest)
for index, player in pairs(players) do commands = commands:gsub("@farthest", farthest)
local distance = vector.distance(pos, player:getpos()) commands = commands:gsub("@random", random)
if distance < min_distance then return commands
min_distance = distance end
nearest = player:get_player_name()
end local function commandblock_action_on(pos, node)
if distance > max_distance then if node.name ~= "mesecons_commandblock:commandblock_off" then
max_distance = distance return
farthest = player:get_player_name() end
end
end minetest.swap_node(pos, {name = "mesecons_commandblock:commandblock_on"})
local random = players[math.random(#players)]:get_player_name()
commands = commands:gsub("@nearest", nearest) local meta = minetest.get_meta(pos)
commands = commands:gsub("@farthest", farthest) local owner = meta:get_string("owner")
commands = commands:gsub("@random", random) if owner == "" then
return commands return
end end
local function commandblock_action_on(pos, node) local commands = resolve_commands(meta:get_string("commands"), pos)
if node.name ~= "mesecons_commandblock:commandblock_off" then for _, command in pairs(commands:split("\n")) do
return local pos = command:find(" ")
end local cmd, param = command, ""
if pos then
minetest.swap_node(pos, {name = "mesecons_commandblock:commandblock_on"}) cmd = command:sub(1, pos - 1)
param = command:sub(pos + 1)
local meta = minetest.get_meta(pos) end
local owner = meta:get_string("owner") local cmddef = minetest.chatcommands[cmd]
if owner == "" then if not cmddef then
return minetest.chat_send_player(owner, "The command "..cmd.." does not exist")
end return
end
local commands = resolve_commands(meta:get_string("commands"), pos) local has_privs, missing_privs = minetest.check_player_privs(owner, cmddef.privs)
for _, command in pairs(commands:split("\n")) do if not has_privs then
local pos = command:find(" ") minetest.chat_send_player(owner, "You don't have permission "
local cmd, param = command, "" .."to run "..cmd
if pos then .." (missing privileges: "
cmd = command:sub(1, pos - 1) ..table.concat(missing_privs, ", ")..")")
param = command:sub(pos + 1) return
end end
local cmddef = minetest.chatcommands[cmd] cmddef.func(owner, param)
if not cmddef then end
minetest.chat_send_player(owner, "The command "..cmd.." does not exist") end
return
end local function commandblock_action_off(pos, node)
local has_privs, missing_privs = minetest.check_player_privs(owner, cmddef.privs) if node.name == "mesecons_commandblock:commandblock_on" then
if not has_privs then minetest.swap_node(pos, {name = "mesecons_commandblock:commandblock_off"})
minetest.chat_send_player(owner, "You don't have permission " end
.."to run "..cmd end
.." (missing privileges: "
..table.concat(missing_privs, ", ")..")") local function can_dig(pos, player)
return local meta = minetest.get_meta(pos)
end local owner = meta:get_string("owner")
cmddef.func(owner, param) return owner == "" or owner == player:get_player_name()
end end
end
minetest.register_node("mesecons_commandblock:commandblock_off", {
local function commandblock_action_off(pos, node) description = "Command Block",
if node.name == "mesecons_commandblock:commandblock_on" then tiles = {"jeija_commandblock_off.png"},
minetest.swap_node(pos, {name = "mesecons_commandblock:commandblock_off"}) inventory_image = minetest.inventorycube("jeija_commandblock_off.png"),
end groups = {cracky=2, mesecon_effector_off=1},
end on_construct = construct,
after_place_node = after_place,
local function can_dig(pos, player) on_receive_fields = receive_fields,
local meta = minetest.get_meta(pos) can_dig = can_dig,
local owner = meta:get_string("owner") sounds = default.node_sound_stone_defaults(),
return owner == "" or owner == player:get_player_name() mesecons = {effector = {
end action_on = commandblock_action_on
}}
minetest.register_node("mesecons_commandblock:commandblock_off", { })
description = "Command Block",
tiles = {"jeija_commandblock_off.png"}, minetest.register_node("mesecons_commandblock:commandblock_on", {
inventory_image = minetest.inventorycube("jeija_commandblock_off.png"), tiles = {"jeija_commandblock_on.png"},
groups = {cracky=2, mesecon_effector_off=1}, groups = {cracky=2, mesecon_effector_on=1, not_in_creative_inventory=1},
on_construct = construct, light_source = 10,
after_place_node = after_place, drop = "mesecons_commandblock:commandblock_off",
on_receive_fields = receive_fields, on_construct = construct,
can_dig = can_dig, after_place_node = after_place,
sounds = default.node_sound_stone_defaults(), on_receive_fields = receive_fields,
mesecons = {effector = { can_dig = can_dig,
action_on = commandblock_action_on sounds = default.node_sound_stone_defaults(),
}} mesecons = {effector = {
}) action_off = commandblock_action_off
}}
minetest.register_node("mesecons_commandblock:commandblock_on", { })
tiles = {"jeija_commandblock_on.png"},
groups = {cracky=2, mesecon_effector_on=1, not_in_creative_inventory=1},
light_source = 10,
drop = "mesecons_commandblock:commandblock_off",
on_construct = construct,
after_place_node = after_place,
on_receive_fields = receive_fields,
can_dig = can_dig,
sounds = default.node_sound_stone_defaults(),
mesecons = {effector = {
action_off = commandblock_action_off
}}
})

View File

@ -1 +0,0 @@
The delayer delays the signal from the input for a determined time. The time can be set by punching the delayer. Possible delays are: 0.1 seconds, 0.3 seconds, 0.5 seconds and 1 second. You may try to use it for creating songs with the noteblock.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

View File

@ -2,7 +2,7 @@
local delayer_get_output_rules = function(node) local delayer_get_output_rules = function(node)
local rules = {{x = 0, y = 0, z = 1}} local rules = {{x = 0, y = 0, z = 1}}
for i = 0, node.param2 do for i = 0, node.param2 do
rules = mesecon.rotate_rules_left(rules) rules = mesecon:rotate_rules_left(rules)
end end
return rules return rules
end end
@ -10,7 +10,7 @@ end
local delayer_get_input_rules = function(node) local delayer_get_input_rules = function(node)
local rules = {{x = 0, y = 0, z = -1}} local rules = {{x = 0, y = 0, z = -1}}
for i = 0, node.param2 do for i = 0, node.param2 do
rules = mesecon.rotate_rules_left(rules) rules = mesecon:rotate_rules_left(rules)
end end
return rules return rules
end end
@ -35,7 +35,7 @@ end
for i = 1, 4 do for i = 1, 4 do
local groups = {} local groups = {}
if i == 1 then if i == 1 then
groups = {bendy=2,snappy=1,dig_immediate=2} groups = {bendy=2,snappy=1,dig_immediate=2}
else else
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}

View File

@ -1,6 +0,0 @@
The node detector is a receptor. It changes its state when either any node
or a specific node is detected. Right-click it to set a nodename to scan for.
It can also receive digiline signals. You can either send "GET" and it will
respond with the detected nodename or you can send any other string and it will
set this string as the node to scan for.
Nodenames must include the mod they reside in, so for instance default:dirt, not just dirt.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

View File

@ -1,3 +0,0 @@
The object detector is a receptor. It changes its state when a player approaches.
Right-click it to set a name to scan for.
It can also receive digiline signals which are the name to scan for on the specified channel in the right-click menu.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

View File

@ -1,18 +1,17 @@
local GET_COMMAND = "GET"
-- Object detector -- Object detector
-- Detects players in a certain radius -- Detects players in a certain radius
-- The radius can be specified in mesecons/settings.lua -- The radius can be specified in mesecons/settings.lua
local function object_detector_make_formspec(pos) local object_detector_make_formspec = function (pos)
minetest.get_meta(pos):set_string("formspec", "size[9,2.5]" .. local meta = minetest.get_meta(pos)
meta:set_string("formspec", "size[9,2.5]" ..
"field[0.3, 0;9,2;scanname;Name of player to scan for (empty for any):;${scanname}]".. "field[0.3, 0;9,2;scanname;Name of player to scan for (empty for any):;${scanname}]"..
"field[0.3,1.5;4,2;digiline_channel;Digiline Channel (optional):;${digiline_channel}]".. "field[0.3,1.5;4,2;digiline_channel;Digiline Channel (optional):;${digiline_channel}]"..
"button_exit[7,0.75;2,3;;Save]") "button_exit[7,0.75;2,3;;Save]")
end end
local function object_detector_on_receive_fields(pos, _, fields) local object_detector_on_receive_fields = function(pos, formname, fields)
if not fields.scanname or not fields.digiline_channel then return end if not fields.scanname or not fields.digiline_channel then return end;
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
meta:set_string("scanname", fields.scanname) meta:set_string("scanname", fields.scanname)
@ -21,35 +20,25 @@ local function object_detector_on_receive_fields(pos, _, fields)
end end
-- returns true if player was found, false if not -- returns true if player was found, false if not
local function object_detector_scan(pos) local object_detector_scan = function (pos)
local objs = minetest.get_objects_inside_radius(pos, mesecon.setting("detector_radius", 6)) local objs = minetest.get_objects_inside_radius(pos, OBJECT_DETECTOR_RADIUS)
for k, obj in pairs(objs) do
-- abort if no scan results were found local isname = obj:get_player_name() -- "" is returned if it is not a player; "" ~= nil!
if next(objs) == nil then return false end local scanname = minetest.get_meta(pos):get_string("scanname")
if (isname == scanname and isname ~= "") or (isname ~= "" and scanname == "") then -- player with scanname found or not scanname specified
local scanname = minetest.get_meta(pos):get_string("scanname") return true
local every_player = scanname == ""
for _, obj in pairs(objs) do
-- "" is returned if it is not a player; "" ~= nil; so only handle objects with foundname ~= ""
local foundname = obj:get_player_name()
if foundname ~= "" then
-- return true if scanning for any player or if specific playername was detected
if scanname == "" or foundname == scanname then
return true
end
end end
end end
return false return false
end end
-- set player name when receiving a digiline signal on a specific channel -- set player name when receiving a digiline signal on a specific channel
local object_detector_digiline = { object_detector_digiline = {
effector = { effector = {
action = function(pos, node, channel, msg) action = function (pos, node, channel, msg)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
if channel == meta:get_string("digiline_channel") then local active_channel = meta:get_string("digiline_channel")
if channel == active_channel then
meta:set_string("scanname", msg) meta:set_string("scanname", msg)
object_detector_make_formspec(pos) object_detector_make_formspec(pos)
end end
@ -64,8 +53,7 @@ minetest.register_node("mesecons_detector:object_detector_off", {
groups = {cracky=3}, groups = {cracky=3},
description="Player Detector", description="Player Detector",
mesecons = {receptor = { mesecons = {receptor = {
state = mesecon.state.off, state = mesecon.state.off
rules = mesecon.rules.pplate
}}, }},
on_construct = object_detector_make_formspec, on_construct = object_detector_make_formspec,
on_receive_fields = object_detector_on_receive_fields, on_receive_fields = object_detector_on_receive_fields,
@ -80,8 +68,7 @@ minetest.register_node("mesecons_detector:object_detector_on", {
groups = {cracky=3,not_in_creative_inventory=1}, groups = {cracky=3,not_in_creative_inventory=1},
drop = 'mesecons_detector:object_detector_off', drop = 'mesecons_detector:object_detector_off',
mesecons = {receptor = { mesecons = {receptor = {
state = mesecon.state.on, state = mesecon.state.on
rules = mesecon.rules.pplate
}}, }},
on_construct = object_detector_make_formspec, on_construct = object_detector_make_formspec,
on_receive_fields = object_detector_on_receive_fields, on_receive_fields = object_detector_on_receive_fields,
@ -98,169 +85,26 @@ minetest.register_craft({
} }
}) })
minetest.register_abm({ minetest.register_abm(
nodenames = {"mesecons_detector:object_detector_off"}, {nodenames = {"mesecons_detector:object_detector_off"},
interval = 1, interval = 1.0,
chance = 1, chance = 1,
action = function(pos, node) action = function(pos)
if not object_detector_scan(pos) then return end if object_detector_scan(pos) then
minetest.swap_node(pos, {name = "mesecons_detector:object_detector_on"})
node.name = "mesecons_detector:object_detector_on" mesecon:receptor_on(pos)
minetest.swap_node(pos, node) end
mesecon.receptor_on(pos, mesecon.rules.pplate)
end, end,
}) })
minetest.register_abm({ minetest.register_abm(
nodenames = {"mesecons_detector:object_detector_on"}, {nodenames = {"mesecons_detector:object_detector_on"},
interval = 1, interval = 1.0,
chance = 1, chance = 1,
action = function(pos, node) action = function(pos)
if object_detector_scan(pos) then return end if not object_detector_scan(pos) then
minetest.swap_node(pos, {name = "mesecons_detector:object_detector_off"})
node.name = "mesecons_detector:object_detector_off" mesecon:receptor_off(pos)
minetest.swap_node(pos, node) end
mesecon.receptor_off(pos, mesecon.rules.pplate)
end,
})
-- Node detector
-- Detects the node in front of it
local function node_detector_make_formspec(pos)
minetest.get_meta(pos):set_string("formspec", "size[9,2.5]" ..
"field[0.3, 0;9,2;scanname;Name of node to scan for (empty for any):;${scanname}]"..
"field[0.3,1.5;4,2;digiline_channel;Digiline Channel (optional):;${digiline_channel}]"..
"button_exit[7,0.75;2,3;;Save]")
end
local function node_detector_on_receive_fields(pos, _, fields)
if not fields.scanname or not fields.digiline_channel then return end
local meta = minetest.get_meta(pos)
meta:set_string("scanname", fields.scanname)
meta:set_string("digiline_channel", fields.digiline_channel)
node_detector_make_formspec(pos)
end
-- returns true if node was found, false if not
local function node_detector_scan(pos)
local node = minetest.get_node_or_nil(pos)
if not node then return end
local frontname = minetest.get_node(
vector.subtract(pos, minetest.facedir_to_dir(node.param2))
).name
local scanname = minetest.get_meta(pos):get_string("scanname")
return (frontname == scanname) or
(frontname ~= "air" and frontname ~= "ignore" and scanname == "")
end
-- set player name when receiving a digiline signal on a specific channel
local node_detector_digiline = {
effector = {
action = function(pos, node, channel, msg)
local meta = minetest.get_meta(pos)
if channel ~= meta:get_string("digiline_channel") then return end
if msg == GET_COMMAND then
local nodename = minetest.get_node(
vector.subtract(pos, minetest.facedir_to_dir(node.param2))
).name
digiline:receptor_send(pos, digiline.rules.default, channel, nodename)
else
meta:set_string("scanname", msg)
node_detector_make_formspec(pos)
end
end,
},
receptor = {}
}
local function after_place_node_detector(pos, placer)
local placer_pos = placer:getpos()
if not placer_pos then
return
end
--correct for the player's height
if placer:is_player() then
placer_pos.y = placer_pos.y + 1.625
end
--correct for 6d facedir
local node = minetest.get_node(pos)
node.param2 = minetest.dir_to_facedir(vector.subtract(pos, placer_pos), true)
minetest.set_node(pos, node)
end
minetest.register_node("mesecons_detector:node_detector_off", {
tiles = {"default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "jeija_node_detector_off.png"},
paramtype = "light",
paramtype2 = "facedir",
walkable = true,
groups = {cracky=3},
description="Node Detector",
mesecons = {receptor = {
state = mesecon.state.off
}},
on_construct = node_detector_make_formspec,
on_receive_fields = node_detector_on_receive_fields,
after_place_node = after_place_node_detector,
sounds = default.node_sound_stone_defaults(),
digiline = node_detector_digiline
})
minetest.register_node("mesecons_detector:node_detector_on", {
tiles = {"default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "jeija_node_detector_on.png"},
paramtype = "light",
paramtype2 = "facedir",
walkable = true,
groups = {cracky=3,not_in_creative_inventory=1},
drop = 'mesecons_detector:node_detector_off',
mesecons = {receptor = {
state = mesecon.state.on
}},
on_construct = node_detector_make_formspec,
on_receive_fields = node_detector_on_receive_fields,
after_place_node = after_place_node_detector,
sounds = default.node_sound_stone_defaults(),
digiline = node_detector_digiline
})
minetest.register_craft({
output = 'mesecons_detector:node_detector_off',
recipe = {
{"default:steel_ingot", "group:mesecon_conductor_craftable", "default:steel_ingot"},
{"default:steel_ingot", "mesecons_luacontroller:luacontroller0000", "default:steel_ingot"},
{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
}
})
minetest.register_abm({
nodenames = {"mesecons_detector:node_detector_off"},
interval = 1,
chance = 1,
action = function(pos, node)
if not node_detector_scan(pos) then return end
node.name = "mesecons_detector:node_detector_on"
minetest.swap_node(pos, node)
mesecon.receptor_on(pos)
end,
})
minetest.register_abm({
nodenames = {"mesecons_detector:node_detector_on"},
interval = 1,
chance = 1,
action = function(pos, node)
if node_detector_scan(pos) then return end
node.name = "mesecons_detector:node_detector_off"
minetest.swap_node(pos, node)
mesecon.receptor_off(pos)
end, end,
}) })

Binary file not shown.

Before

Width:  |  Height:  |  Size: 717 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 727 B

View File

@ -1,2 +1,2 @@
mesecons
doors doors
mesecons

View File

@ -1,129 +1,130 @@
-- Modified, from minetest_game/mods/doors/init.lua local other_state_node = {}
local function on_rightclick(pos, dir, check_name, replace, replace_dir, params) for _, material in ipairs({
pos.y = pos.y + dir { id = "wood", desc = "Wooden", color = "brown" },
if not minetest.get_node(pos).name == check_name then { id = "steel", desc = "Steel", color = "grey" },
return }) do
doors:register_door("mesecons_doors:op_door_"..material.id, {
description = "Mesecon-operated "..material.desc.." Door",
inventory_image = minetest.registered_items["doors:door_"..material.id].inventory_image,
groups = minetest.registered_nodes["doors:door_"..material.id.."_b_1"].groups,
tiles_bottom = {"door_"..material.id.."_b.png", "door_"..material.color..".png"},
tiles_top = {"door_"..material.id.."_a.png", "door_"..material.color..".png"},
})
local groups_plus_mesecon = { mesecon = 2 }
for k, v in pairs(minetest.registered_nodes["doors:door_"..material.id.."_b_1"].groups) do
groups_plus_mesecon[k] = v
end end
local p2 = minetest.get_node(pos).param2 doors:register_door("mesecons_doors:sig_door_"..material.id, {
p2 = params[p2 + 1] description = "Mesecon-signalling "..material.desc.." Door",
inventory_image = minetest.registered_items["doors:door_"..material.id].inventory_image,
minetest.swap_node(pos, {name = replace_dir, param2 = p2}) groups = groups_plus_mesecon,
tiles_bottom = {"door_"..material.id.."_b.png", "door_"..material.color..".png"},
pos.y = pos.y - dir tiles_top = {"door_"..material.id.."_a.png", "door_"..material.color..".png"},
minetest.swap_node(pos, {name = replace, param2 = p2}) })
for _, thishalf in ipairs({ "t", "b" }) do
if (minetest.get_meta(pos):get_int("right") ~= 0) == (params[1] ~= 3) then local otherhalf = thishalf == "t" and "b" or "t"
minetest.sound_play("doors_door_close", {pos = pos, gain = 0.3, max_hear_distance = 10}) local otherdir = thishalf == "t" and -1 or 1
else for orientation = 1, 2 do
minetest.sound_play("doors_door_open", {pos = pos, gain = 0.3, max_hear_distance = 10}) local thissuffix = material.id.."_"..thishalf.."_"..orientation
end local othersuffix = material.id.."_"..otherhalf.."_"..orientation
end local thisopname = "mesecons_doors:op_door_"..thissuffix
local otheropname = "mesecons_doors:op_door_"..othersuffix
local function meseconify_door(name) local oponr = minetest.registered_nodes[thisopname].on_rightclick
if minetest.registered_items[name .. "_b_1"] then local function handle_mesecon_signal (thispos, thisnode, signal)
-- old style double-node doors local thismeta = minetest.get_meta(thispos)
local function toggle_state1 (pos, node) if signal == thismeta:get_int("sigstate") then return end
on_rightclick(pos, 1, name.."_t_1", name.."_b_2", name.."_t_2", {1,2,3,0}) thismeta:set_int("sigstate", signal)
end local otherpos = { x = thispos.x, y = thispos.y + otherdir, z = thispos.z }
if minetest.get_node(otherpos).name ~= otheropname then return end
local function toggle_state2 (pos, node) local othermeta = minetest.get_meta(otherpos)
on_rightclick(pos, 1, name.."_t_2", name.."_b_1", name.."_t_1", {3,0,1,2}) local newdoorstate = math.max(thismeta:get_int("sigstate"), othermeta:get_int("sigstate"))
end if newdoorstate == thismeta:get_int("doorstate") then return end
oponr(thispos, thisnode, nil)
minetest.override_item(name.."_b_1", { thismeta:set_int("doorstate", newdoorstate)
mesecons = {effector = { othermeta:set_int("doorstate", newdoorstate)
action_on = toggle_state1, end
action_off = toggle_state1, minetest.override_item(thisopname, {
rules = mesecon.rules.pplate on_construct = function (pos)
}} if mesecon:is_powered(pos) then
}) local node = minetest.get_node(pos)
mesecon:changesignal(pos, node, mesecon:effector_get_rules(node), "on", 1)
minetest.override_item(name.."_b_2", { mesecon:activate(pos, node, nil, 1)
mesecons = {effector = {
action_on = toggle_state2,
action_off = toggle_state2,
rules = mesecon.rules.pplate
}}
})
elseif minetest.registered_items[name .. "_a"] then
-- new style mesh node based doors
local override = {
mesecons = {effector = {
action_on = function(pos, node)
local door = doors.get(pos)
if door then
door:open()
end end
end, end,
action_off = function(pos, node) on_rightclick = function (pos, node, clicker) end,
local door = doors.get(pos) mesecons = {
if door then effector = {
door:close() action_on = function (pos, node)
handle_mesecon_signal(pos, node, 1)
end,
action_off = function (pos, node)
handle_mesecon_signal(pos, node, 0)
end,
},
},
})
local thissigname = "mesecons_doors:sig_door_"..thissuffix
local othersigname = "mesecons_doors:sig_door_"..othersuffix
local sigonr = minetest.registered_nodes[thissigname].on_rightclick
minetest.override_item(thissigname, {
on_rightclick = function (thispos, thisnode, clicker)
local otherpos = { x = thispos.x, y = thispos.y + otherdir, z = thispos.z }
print("open: otherpos.name="..minetest.get_node(otherpos).name..", othersigname="..othersigname)
if minetest.get_node(otherpos).name ~= othersigname then return end
sigonr(thispos, thisnode, clicker)
for _, pos in ipairs({ thispos, otherpos }) do
local node = minetest.get_node(pos)
node.name = other_state_node[node.name]
minetest.swap_node(pos, node)
mesecon:receptor_on(pos)
end end
end, end,
rules = mesecon.rules.pplate mesecons = { receptor = { state = mesecon.state.off } },
}} })
} other_state_node[thissigname] = thissigname.."_on"
minetest.override_item(name .. "_a", override) local ondef = {}
minetest.override_item(name .. "_b", override) for k, v in pairs(minetest.registered_nodes[thissigname]) do
end ondef[k] = v
end end
ondef.on_rightclick = function (thispos, thisnode, clicker)
meseconify_door("doors:door_wood") local otherpos = { x = thispos.x, y = thispos.y + otherdir, z = thispos.z }
meseconify_door("doors:door_steel") print("close: otherpos.name="..minetest.get_node(otherpos).name..", othersigname="..othersigname)
meseconify_door("doors:door_glass") if minetest.get_node(otherpos).name ~= othersigname.."_on" then return end
meseconify_door("doors:door_obsidian_glass") for _, pos in ipairs({ thispos, otherpos }) do
local node = minetest.get_node(pos)
-- Trapdoor node.name = other_state_node[node.name]
local function trapdoor_switch(pos, node) minetest.swap_node(pos, node)
local state = minetest.get_meta(pos):get_int("state") mesecon:receptor_off(pos)
if state == 1 then
minetest.sound_play("doors_door_close", {pos = pos, gain = 0.3, max_hear_distance = 10})
minetest.set_node(pos, {name="doors:trapdoor", param2 = node.param2})
else
minetest.sound_play("doors_door_open", {pos = pos, gain = 0.3, max_hear_distance = 10})
minetest.set_node(pos, {name="doors:trapdoor_open", param2 = node.param2})
end
minetest.get_meta(pos):set_int("state", state == 1 and 0 or 1)
end
if doors and doors.get then
local override = {
mesecons = {effector = {
action_on = function(pos, node)
local door = doors.get(pos)
if door then
door:open()
end end
end, sigonr(thispos, thisnode, clicker)
action_off = function(pos, node) end
local door = doors.get(pos) ondef.mesecons = { receptor = { state = mesecon.state.on } }
if door then ondef.after_destruct = function (thispos, thisnode)
door:close() local otherpos = { x = thispos.x, y = thispos.y + otherdir, z = thispos.z }
if minetest.get_node(otherpos).name == othersigname.."_on" then
minetest.remove_node(otherpos)
mesecon:receptor_off(otherpos)
end end
end, end
}}, other_state_node[thissigname.."_on"] = thissigname
} ondef.mesecon_other_state_node = thissigname
minetest.override_item("doors:trapdoor", override) minetest.register_node(thissigname.."_on", ondef)
minetest.override_item("doors:trapdoor_open", override) end
minetest.override_item("doors:trapdoor_steel", override)
minetest.override_item("doors:trapdoor_steel_open", override)
else
if minetest.registered_nodes["doors:trapdoor"] then
minetest.override_item("doors:trapdoor", {
mesecons = {effector = {
action_on = trapdoor_switch,
action_off = trapdoor_switch
}},
})
minetest.override_item("doors:trapdoor_open", {
mesecons = {effector = {
action_on = trapdoor_switch,
action_off = trapdoor_switch
}},
})
end end
minetest.register_craft({
output = "mesecons_doors:op_door_"..material.id,
recipe = {
{ "group:mesecon_conductor_craftable", "", "" },
{ "", "doors:door_"..material.id, "group:mesecon_conductor_craftable" },
{ "group:mesecon_conductor_craftable", "", "" },
},
})
minetest.register_craft({
output = "mesecons_doors:sig_door_"..material.id,
recipe = {
{ "", "", "group:mesecon_conductor_craftable" },
{ "group:mesecon_conductor_craftable", "doors:door_"..material.id, "" },
{ "", "", "group:mesecon_conductor_craftable" },
},
})
end end

View File

@ -10,12 +10,12 @@ local corner_selectionbox = {
} }
local corner_get_rules = function (node) local corner_get_rules = function (node)
local rules = local rules =
{{x = 1, y = 0, z = 0}, {{x = 1, y = 0, z = 0},
{x = 0, y = 0, z = -1}} {x = 0, y = 0, z = -1}}
for i = 0, node.param2 do for i = 0, node.param2 do
rules = mesecon.rotate_rules_left(rules) rules = mesecon:rotate_rules_left(rules)
end end
return rules return rules
@ -39,7 +39,7 @@ minetest.register_node("mesecons_extrawires:corner_on", {
node_box = corner_nodebox, 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",
mesecons = {conductor = mesecons = {conductor =
{ {
state = mesecon.state.on, state = mesecon.state.on,
rules = corner_get_rules, rules = corner_get_rules,
@ -65,7 +65,7 @@ minetest.register_node("mesecons_extrawires:corner_off", {
selection_box = corner_selectionbox, selection_box = corner_selectionbox,
node_box = corner_nodebox, node_box = corner_nodebox,
groups = {dig_immediate = 3}, groups = {dig_immediate = 3},
mesecons = {conductor = mesecons = {conductor =
{ {
state = mesecon.state.off, state = mesecon.state.off,
rules = corner_get_rules, rules = corner_get_rules,

View File

@ -41,7 +41,7 @@ minetest.register_node("mesecons_extrawires:crossover_off", {
{ -3/32, -17/32, 6/32, 3/32, -13/32, 16/32+0.001 }, { -3/32, -17/32, 6/32, 3/32, -13/32, 16/32+0.001 },
}, },
}, },
groups = {dig_immediate=3, mesecon=3}, groups = {dig_immediate=3, mesecon=3, mesecon_conductor_craftable=1},
mesecons = { mesecons = {
conductor = { conductor = {
states = crossover_states, states = crossover_states,

View File

@ -1 +0,0 @@
Insulated corners are conductors that only conduct between the inputs (also not up or down). When placing they always point to the left in direction of your vision.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -1 +0,0 @@
Insulated crossing are conductors that conduct two signals between the opposing sides, the signals are insulated to each other.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -1 +0,0 @@
The basic prerequesite for mesecons, can be crafted into wires and other stuff. Have a look at the <a href="http://wiki.minetest.net/Mese">Minetest Wiki</a> for more information. Mese is a conductor. It conducts in all six directions: Up/Down/Left/Right/Forward/Backward

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

View File

@ -1 +0,0 @@
Insulated T-Junctions are conductors that only conduct between the inputs (also not up or down).

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -1 +0,0 @@
Vertical Mesecons only conduct up and down. Plates appear at the ends, at that place they also conduct to the side.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -8,7 +8,12 @@ local mesewire_rules =
{x = 0, y = 0, z =-1}, {x = 0, y = 0, z =-1},
} }
minetest.override_item("default:mese", { minetest.register_node(":default:mese", {
description = "Mese Block",
tiles = {minetest.registered_nodes["default:mese"].tiles[1]},
is_ground_content = true,
groups = {cracky=1},
sounds = default.node_sound_stone_defaults(),
mesecons = {conductor = { mesecons = {conductor = {
state = mesecon.state.off, state = mesecon.state.off,
onstate = "mesecons_extrawires:mese_powered", onstate = "mesecons_extrawires:mese_powered",
@ -16,21 +21,15 @@ minetest.override_item("default:mese", {
}} }}
}) })
-- Copy node definition of powered mese from normal mese minetest.register_node("mesecons_extrawires:mese_powered", {
-- and brighten texture tiles to indicate mese is powered tiles = {minetest.registered_nodes["default:mese"].tiles[1].."^[brighten"},
local powered_def = mesecon.mergetable(minetest.registered_nodes["default:mese"], { is_ground_content = true,
drop = "default:mese", groups = {cracky=1, not_in_creative_inventory = 1},
light_source = 5, sounds = default.node_sound_stone_defaults(),
mesecons = {conductor = { mesecons = {conductor = {
state = mesecon.state.on, state = mesecon.state.on,
offstate = "default:mese", offstate = "default:mese",
rules = mesewire_rules rules = mesewire_rules
}}, }},
groups = {cracky = 1, not_in_creative_inventory = 1} drop = "default:mese"
}) })
for i, v in pairs(powered_def.tiles) do
powered_def.tiles[i] = v .. "^[brighten"
end
minetest.register_node("mesecons_extrawires:mese_powered", powered_def)

View File

@ -10,13 +10,13 @@ local tjunction_selectionbox = {
} }
local tjunction_get_rules = function (node) local tjunction_get_rules = function (node)
local rules = local rules =
{{x = 0, y = 0, z = 1}, {{x = 0, y = 0, z = 1},
{x = 1, y = 0, z = 0}, {x = 1, y = 0, z = 0},
{x = 0, y = 0, z = -1}} {x = 0, y = 0, z = -1}}
for i = 0, node.param2 do for i = 0, node.param2 do
rules = mesecon.rotate_rules_left(rules) rules = mesecon:rotate_rules_left(rules)
end end
return rules return rules
@ -40,7 +40,7 @@ minetest.register_node("mesecons_extrawires:tjunction_on", {
node_box = tjunction_nodebox, node_box = tjunction_nodebox,
groups = {dig_immediate = 3, not_in_creative_inventory = 1}, groups = {dig_immediate = 3, not_in_creative_inventory = 1},
drop = "mesecons_extrawires:tjunction_off", drop = "mesecons_extrawires:tjunction_off",
mesecons = {conductor = mesecons = {conductor =
{ {
state = mesecon.state.on, state = mesecon.state.on,
rules = tjunction_get_rules, rules = tjunction_get_rules,
@ -65,8 +65,8 @@ minetest.register_node("mesecons_extrawires:tjunction_off", {
sunlight_propagates = true, sunlight_propagates = true,
selection_box = tjunction_selectionbox, selection_box = tjunction_selectionbox,
node_box = tjunction_nodebox, node_box = tjunction_nodebox,
groups = {dig_immediate = 3}, groups = {dig_immediate = 3, mesecon_conductor_craftable=1},
mesecons = {conductor = mesecons = {conductor =
{ {
state = mesecon.state.off, state = mesecon.state.off,
rules = tjunction_get_rules, rules = tjunction_get_rules,

View File

@ -18,7 +18,7 @@ local bottom_box = {
local vertical_rules = { local vertical_rules = {
{x=0, y=1, z=0}, {x=0, y=1, z=0},
{x=0, y=-1, z=0} {x=0, y=-1, z=0},
} }
local top_rules = { local top_rules = {
@ -26,7 +26,7 @@ local top_rules = {
{x=-1,y=0, z=0}, {x=-1,y=0, z=0},
{x=0,y=0, z=1}, {x=0,y=0, z=1},
{x=0,y=0, z=-1}, {x=0,y=0, z=-1},
{x=0,y=-1, z=0} {x=0,y=-1, z=0},
} }
local bottom_rules = { local bottom_rules = {
@ -35,81 +35,85 @@ local bottom_rules = {
{x=0, y=0, z=1}, {x=0, y=0, z=1},
{x=0, y=0, z=-1}, {x=0, y=0, z=-1},
{x=0, y=1, z=0}, {x=0, y=1, z=0},
{x=0, y=2, z=0} -- receive power from pressure plate / detector / ... 2 nodes above
} }
local vertical_updatepos = function (pos) local vertical_updatepos = function (pos)
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
if minetest.registered_nodes[node.name] if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].is_vertical_conductor then
and minetest.registered_nodes[node.name].is_vertical_conductor then local node_above = minetest.get_node(mesecon:addPosRule(pos, vertical_rules[1]))
local node_above = minetest.get_node(vector.add(pos, vertical_rules[1])) local node_below = minetest.get_node(mesecon:addPosRule(pos, vertical_rules[2]))
local node_below = minetest.get_node(vector.add(pos, vertical_rules[2])) local namestate = minetest.registered_nodes[node.name].vertical_conductor_state
local above = minetest.registered_nodes[node_above.name] local above = minetest.registered_nodes[node_above.name] and minetest.registered_nodes[node_above.name].is_vertical_conductor
and minetest.registered_nodes[node_above.name].is_vertical_conductor local below = minetest.registered_nodes[node_below.name] and minetest.registered_nodes[node_below.name].is_vertical_conductor
local below = minetest.registered_nodes[node_below.name]
and minetest.registered_nodes[node_below.name].is_vertical_conductor
mesecon.on_dignode(pos, node)
-- Always place offstate conductor and let mesecon.on_placenode take care
local newname = "mesecons_extrawires:vertical_"
if above and below then -- above and below: vertical mesecon if above and below then -- above and below: vertical mesecon
newname = newname .. "off" minetest.add_node(pos, {name = "mesecons_extrawires:vertical_" .. namestate})
elseif above and not below then -- above only: bottom elseif above and not below then -- above only: bottom
newname = newname .. "bottom_off" minetest.add_node(pos, {name = "mesecons_extrawires:vertical_bottom_" .. namestate})
elseif not above and below then -- below only: top elseif not above and below then -- below only: top
newname = newname .. "top_off" minetest.add_node(pos, {name = "mesecons_extrawires:vertical_top_" .. namestate})
else -- no vertical wire above, no vertical wire below: use bottom else -- no vertical wire above, no vertical wire below: use default wire
newname = newname .. "bottom_off" minetest.add_node(pos, {name = "mesecons_extrawires:vertical_" .. namestate})
end end
minetest.set_node(pos, {name = newname})
mesecon.on_placenode(pos, {name = newname})
end end
end end
local vertical_update = function (pos, node) local vertical_update = function (pos, node)
vertical_updatepos(pos) -- this one vertical_updatepos(pos) -- this one
vertical_updatepos(vector.add(pos, vertical_rules[1])) -- above vertical_updatepos(mesecon:addPosRule(pos, vertical_rules[1])) -- above
vertical_updatepos(vector.add(pos, vertical_rules[2])) -- below vertical_updatepos(mesecon:addPosRule(pos, vertical_rules[2])) -- below
end end
-- Vertical wire -- Vertical wire
mesecon.register_node("mesecons_extrawires:vertical", { minetest.register_node("mesecons_extrawires:vertical_on", {
description = "Vertical mesecon", description = "Vertical mesecon",
drawtype = "nodebox", drawtype = "nodebox",
tiles = {"wires_vertical_on.png"},
walkable = false, walkable = false,
paramtype = "light", paramtype = "light",
sunlight_propagates = true, sunlight_propagates = true,
groups = {dig_immediate=3, not_in_creative_inventory=1},
selection_box = vertical_box, selection_box = vertical_box,
node_box = vertical_box, node_box = vertical_box,
is_vertical_conductor = true, is_vertical_conductor = true,
drop = "mesecons_extrawires:vertical_off", vertical_conductor_state = "on",
after_place_node = vertical_update,
after_dig_node = vertical_update
},{
tiles = {"mesecons_wire_off.png"},
groups = {dig_immediate=3},
mesecons = {conductor = {
state = mesecon.state.off,
onstate = "mesecons_extrawires:vertical_on",
rules = vertical_rules,
}}
},{
tiles = {"mesecons_wire_on.png"},
groups = {dig_immediate=3, not_in_creative_inventory=1},
mesecons = {conductor = { mesecons = {conductor = {
state = mesecon.state.on, state = mesecon.state.on,
offstate = "mesecons_extrawires:vertical_off", offstate = "mesecons_extrawires:vertical_off",
rules = vertical_rules, rules = vertical_rules,
}} }},
drop = "mesecons_extrawires:vertical_off",
after_place_node = vertical_update,
after_dig_node = vertical_update,
})
minetest.register_node("mesecons_extrawires:vertical_off", {
description = "Vertical mesecon",
drawtype = "nodebox",
tiles = {"wires_vertical_off.png"},
walkable = false,
paramtype = "light",
sunlight_propagates = true,
groups = {dig_immediate=3},
selection_box = vertical_box,
node_box = vertical_box,
is_vertical_conductor = true,
vertical_conductor_state = "off",
mesecons = {conductor = {
state = mesecon.state.off,
onstate = "mesecons_extrawires:vertical_on",
rules = vertical_rules,
}},
after_place_node = vertical_update,
after_dig_node = vertical_update,
}) })
-- Vertical wire top -- Vertical wire top
mesecon.register_node("mesecons_extrawires:vertical_top", { minetest.register_node("mesecons_extrawires:vertical_top_on", {
description = "Vertical mesecon", description = "Vertical mesecon",
drawtype = "nodebox", drawtype = "nodebox",
tiles = {"wires_full_on.png","wires_full_on.png","wires_vertical_on.png"},
walkable = false, walkable = false,
paramtype = "light", paramtype = "light",
sunlight_propagates = true, sunlight_propagates = true,
@ -117,29 +121,65 @@ mesecon.register_node("mesecons_extrawires:vertical_top", {
selection_box = top_box, selection_box = top_box,
node_box = top_box, node_box = top_box,
is_vertical_conductor = true, is_vertical_conductor = true,
drop = "mesecons_extrawires:vertical_off", vertical_conductor_state = "on",
after_place_node = vertical_update,
after_dig_node = vertical_update
},{
tiles = {"mesecons_wire_off.png"},
mesecons = {conductor = {
state = mesecon.state.off,
onstate = "mesecons_extrawires:vertical_top_on",
rules = top_rules,
}}
},{
tiles = {"mesecons_wire_on.png"},
mesecons = {conductor = { mesecons = {conductor = {
state = mesecon.state.on, state = mesecon.state.on,
offstate = "mesecons_extrawires:vertical_top_off", offstate = "mesecons_extrawires:vertical_top_off",
rules = top_rules, rules = top_rules,
}} }},
drop = "mesecons_extrawires:vertical_off",
after_place_node = vertical_update,
after_dig_node = vertical_update,
})
minetest.register_node("mesecons_extrawires:vertical_top_off", {
description = "Vertical mesecon",
drawtype = "nodebox",
tiles = {"wires_full_off.png","wires_full_off.png","wires_vertical_off.png"},
walkable = false,
paramtype = "light",
sunlight_propagates = true,
groups = {dig_immediate=3, not_in_creative_inventory=1},
selection_box = top_box,
node_box = top_box,
is_vertical_conductor = true,
vertical_conductor_state = "off",
mesecons = {conductor = {
state = mesecon.state.off,
onstate = "mesecons_extrawires:vertical_top_on",
rules = top_rules,
}},
drop = "mesecons_extrawires:vertical_off",
after_place_node = vertical_update,
after_dig_node = vertical_update,
}) })
-- Vertical wire bottom -- Vertical wire bottom
mesecon.register_node("mesecons_extrawires:vertical_bottom", { minetest.register_node("mesecons_extrawires:vertical_bottom_on", {
description = "Vertical mesecon", description = "Vertical mesecon",
drawtype = "nodebox", drawtype = "nodebox",
tiles = {"wires_full_on.png","wires_full_on.png","wires_vertical_on.png"},
walkable = false,
paramtype = "light",
sunlight_propagates = true,
vertical_conductor_state = "on",
groups = {dig_immediate = 3, not_in_creative_inventory = 1},
selection_box = bottom_box,
node_box = bottom_box,
mesecons = {conductor = {
state = mesecon.state.on,
offstate = "mesecons_extrawires:vertical_bottom_off",
rules = bottom_rules,
}},
drop = "mesecons_extrawires:vertical_off",
after_place_node = vertical_update,
after_dig_node = vertical_update,
})
minetest.register_node("mesecons_extrawires:vertical_bottom_off", {
description = "Vertical mesecon",
drawtype = "nodebox",
tiles = {"wires_full_off.png","wires_full_off.png","wires_vertical_off.png"},
walkable = false, walkable = false,
paramtype = "light", paramtype = "light",
sunlight_propagates = true, sunlight_propagates = true,
@ -147,23 +187,15 @@ mesecon.register_node("mesecons_extrawires:vertical_bottom", {
selection_box = bottom_box, selection_box = bottom_box,
node_box = bottom_box, node_box = bottom_box,
is_vertical_conductor = true, is_vertical_conductor = true,
drop = "mesecons_extrawires:vertical_off", vertical_conductor_state = "off",
after_place_node = vertical_update,
after_dig_node = vertical_update
},{
tiles = {"mesecons_wire_off.png"},
mesecons = {conductor = { mesecons = {conductor = {
state = mesecon.state.off, state = mesecon.state.off,
onstate = "mesecons_extrawires:vertical_bottom_on", onstate = "mesecons_extrawires:vertical_bottom_on",
rules = bottom_rules, rules = bottom_rules,
}} }},
},{ drop = "mesecons_extrawires:vertical_off",
tiles = {"mesecons_wire_on.png"}, after_place_node = vertical_update,
mesecons = {conductor = { after_dig_node = vertical_update,
state = mesecon.state.on,
offstate = "mesecons_extrawires:vertical_bottom_off",
rules = bottom_rules,
}}
}) })
minetest.register_craft({ minetest.register_craft({

View File

@ -1 +0,0 @@
And gates power their output if both inputs (from left and right) are powered.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -1 +0,0 @@
Mesecon diodes, just like real ones, only transfer power (signals) in one direction only.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -1 +0,0 @@
Nand gates do not power their output if both inputs (from left and right) are powered, but power it in every other case.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Some files were not shown because too many files have changed in this diff Show More