Compare commits
1 Commits
mvps-ignor
...
master
Author | SHA1 | Date | |
---|---|---|---|
78b10c505f |
3
.gitignore
vendored
@ -1,3 +0,0 @@
|
|||||||
*~
|
|
||||||
*.patch
|
|
||||||
*.diff
|
|
0
LICENSE.txt
Normal file → Executable file
9
README.md
Normal file → Executable file
@ -22,9 +22,9 @@ OK, I want in.
|
|||||||
--------------
|
--------------
|
||||||
Go get it!
|
Go get it!
|
||||||
|
|
||||||
[DOWNLOAD IT NOW](https://github.com/minetest-mods/mesecons/archive/master.zip)
|
[DOWNLOAD IT NOW](https://github.com/Jeija/minetest-mod-mesecons/archive/master.zip)
|
||||||
|
|
||||||
Now go ahead and install it like any other Minetest mod. Don't know how? Check out [the wonderful page about it](https://wiki.minetest.net/Mods) over at the official 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:
|
||||||
|
|
||||||
1. If Mesecons is still in a ZIP file, extract the folder inside to somewhere on the computer.
|
1. If Mesecons is still in a ZIP file, extract the folder inside to somewhere on the computer.
|
||||||
2. Make sure that when you open the folder, you can directly find `README.md` in the listing. If you just see another folder, move that folder up one level and delete the old one.
|
2. Make sure that when you open the folder, you can directly find `README.md` in the listing. If you just see another folder, move that folder up one level and delete the old one.
|
||||||
@ -43,11 +43,9 @@ Or maybe a [comprehensive reference](http://mesecons.net/items.html) is your sty
|
|||||||
|
|
||||||
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?
|
||||||
|
|
||||||
There is also a [wiki page](https://wiki.minetest.net/Mods/Mesecons) dedicated to this mod.
|
|
||||||
|
|
||||||
Want to get more into building? Why not check out the [Mesecons Laboratory](http://uberi.mesecons.net/), a website dedicated to advanced Mesecons builders?
|
Want to get more into building? Why not check out the [Mesecons Laboratory](http://uberi.mesecons.net/), a website dedicated to advanced Mesecons builders?
|
||||||
|
|
||||||
Want to contribute to Mesecons itself? Check out the [source code](https://github.com/minetest-mods/mesecons)!
|
Want to contribute to Mesecons itself? Check out the [source code](https://github.com/Jeija/minetest-mod-mesecons)!
|
||||||
|
|
||||||
Who wrote it anyways?
|
Who wrote it anyways?
|
||||||
---------------------
|
---------------------
|
||||||
@ -55,7 +53,6 @@ These awesome people made Mesecons possible!
|
|||||||
|
|
||||||
| Contributor | Contribution |
|
| Contributor | Contribution |
|
||||||
| --------------- | -------------------------------- |
|
| --------------- | -------------------------------- |
|
||||||
| Hawk777 | Code for VoxelManip caching |
|
|
||||||
| Jat15 | Various tweaks. |
|
| Jat15 | Various tweaks. |
|
||||||
| Jeija | **Main developer! Everything.** |
|
| Jeija | **Main developer! Everything.** |
|
||||||
| Jordach | Noteblock sounds. |
|
| Jordach | Noteblock sounds. |
|
||||||
|
12
bower.json
@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "mesecons",
|
|
||||||
"description": "Mesecons is a mod for Minetest that implements items related to digital circuitry: wires, buttons, lights, and programmable controllers.",
|
|
||||||
"homepage": "http://mesecons.net",
|
|
||||||
"authors": "Jeija",
|
|
||||||
"license": "LGPL-3.0+",
|
|
||||||
"keywords": [
|
|
||||||
"mesecons",
|
|
||||||
"minetest",
|
|
||||||
"mod"
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"Conductors" : {
|
"Conductors" : {
|
||||||
"Mesecon" : "mesecons_wires/doc/mesecon",
|
"Mesecon" : "mesecons/doc/mesecon",
|
||||||
"Insulated Wire" : "mesecons_insulated/doc/insulated",
|
"Insulated Wire" : "mesecons_insulated/doc/insulated",
|
||||||
"T-Junction" : "mesecons_extrawires/doc/tjunction",
|
"T-Junction" : "mesecons_extrawires/doc/tjunction",
|
||||||
"Crossing" : "mesecons_extrawires/doc/crossing",
|
"Crossing" : "mesecons_extrawires/doc/crossing",
|
||||||
@ -42,8 +42,6 @@
|
|||||||
},
|
},
|
||||||
"Logic" : {
|
"Logic" : {
|
||||||
"Luacontroller" : "mesecons_luacontroller/doc/luacontroller",
|
"Luacontroller" : "mesecons_luacontroller/doc/luacontroller",
|
||||||
"FPGA" : "mesecons_fpga/doc/fpga",
|
|
||||||
"FPGA Programmer" : "mesecons_fpga/doc/programmer",
|
|
||||||
"Torch" : "mesecons_torch/doc/torch",
|
"Torch" : "mesecons_torch/doc/torch",
|
||||||
"Delayer" : "mesecons_delayer/doc/delayer",
|
"Delayer" : "mesecons_delayer/doc/delayer",
|
||||||
"Gates" : {
|
"Gates" : {
|
||||||
|
170
mesecons/actionqueue.lua
Normal file → Executable file
@ -1,149 +1,101 @@
|
|||||||
--[[
|
mesecon.queue.actions={} -- contains all ActionQueue actions
|
||||||
Mesecons uses something it calls an ActionQueue.
|
|
||||||
|
|
||||||
The ActionQueue holds functions and actions.
|
function mesecon.queue:add_function(name, func)
|
||||||
Functions are added on load time with a specified name.
|
mesecon.queue.funcs[name] = func
|
||||||
Actions are preserved over server restarts.
|
|
||||||
|
|
||||||
Each action consists of a position, the name of an added function to be called,
|
|
||||||
the params that should be used in this function call (additionally to the pos),
|
|
||||||
the time after which it should be executed, an optional overwritecheck and a
|
|
||||||
priority.
|
|
||||||
|
|
||||||
If time = 0, the action will be executed in the next globalstep, otherwise the
|
|
||||||
earliest globalstep when it will be executed is the after next globalstep.
|
|
||||||
|
|
||||||
It is guaranteed, that for two actions ac1, ac2 where ac1 ~= ac2,
|
|
||||||
ac1.time == ac2.time, ac1.priority == ac2.priority and ac1 was added earlier
|
|
||||||
than ac2, ac1 will be executed before ac2 (but in the same globalstep).
|
|
||||||
|
|
||||||
Note: Do not pass references in params, as they can not be preserved.
|
|
||||||
|
|
||||||
Also note: Some of the guarantees here might be dropped at some time.
|
|
||||||
]]
|
|
||||||
|
|
||||||
|
|
||||||
-- localize for speed
|
|
||||||
local queue = mesecon.queue
|
|
||||||
|
|
||||||
queue.actions = {} -- contains all ActionQueue actions
|
|
||||||
|
|
||||||
function queue:add_function(name, func)
|
|
||||||
queue.funcs[name] = func
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- If add_action with twice the same overwritecheck and same position are called, the first one is overwritten
|
-- If add_action with twice the same overwritecheck and same position are called, the first one is overwritten
|
||||||
-- use overwritecheck nil to never overwrite, but just add the event to the queue
|
-- use overwritecheck nil to never overwrite, but just add the event to the queue
|
||||||
-- priority specifies the order actions are executed within one globalstep, highest first
|
-- priority specifies the order actions are executed within one globalstep, highest first
|
||||||
-- should be between 0 and 1
|
-- should be between 0 and 1
|
||||||
function queue:add_action(pos, func, params, time, overwritecheck, priority)
|
function mesecon.queue:add_action(pos, func, params, time, overwritecheck, priority)
|
||||||
-- 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 = {
|
local action = { pos=mesecon.tablecopy(pos),
|
||||||
pos = mesecon.tablecopy(pos),
|
func=func,
|
||||||
func = func,
|
params=mesecon.tablecopy(params or {}),
|
||||||
params = mesecon.tablecopy(params or {}),
|
time=time,
|
||||||
time = time,
|
owcheck=(overwritecheck and mesecon.tablecopy(overwritecheck)) or nil,
|
||||||
owcheck = (overwritecheck and mesecon.tablecopy(overwritecheck)) or nil,
|
priority=priority}
|
||||||
priority = priority
|
|
||||||
}
|
|
||||||
|
|
||||||
-- check if old action has to be overwritten / removed:
|
local toremove = nil
|
||||||
if overwritecheck then
|
-- Otherwise, add the action to the queue
|
||||||
for i, ac in ipairs(queue.actions) do
|
if overwritecheck then -- check if old action has to be overwritten / removed:
|
||||||
if vector.equals(pos, ac.pos)
|
for i, ac in ipairs(mesecon.queue.actions) do
|
||||||
and mesecon.cmpAny(overwritecheck, ac.owcheck) then
|
if(vector.equals(pos, ac.pos)
|
||||||
-- remove the old action
|
and mesecon.cmpAny(overwritecheck, ac.owcheck)) then
|
||||||
table.remove(queue.actions, i)
|
toremove = i
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
table.insert(queue.actions, action)
|
if (toremove ~= nil) then
|
||||||
|
table.remove(mesecon.queue.actions, toremove)
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(mesecon.queue.actions, action)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- execute the stored functions on a globalstep
|
-- execute the stored functions on a globalstep
|
||||||
-- if however, the pos of a function is not loaded (get_node_or_nil == nil), do NOT execute the function
|
-- if however, the pos of a function is not loaded (get_node_or_nil == nil), do NOT execute the function
|
||||||
-- this makes sure that resuming mesecons circuits when restarting minetest works fine (hm, where do we do this?)
|
-- this makes sure that resuming mesecons circuits when restarting minetest works fine
|
||||||
-- 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 4 seconds
|
-- start to be execute by 5 seconds
|
||||||
|
local get_highest_priority = function (actions)
|
||||||
|
local highestp = -1
|
||||||
|
local highesti
|
||||||
|
for i, ac in ipairs(actions) do
|
||||||
|
if ac.priority > highestp then
|
||||||
|
highestp = ac.priority
|
||||||
|
highesti = i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local function globalstep_func(dtime)
|
return highesti
|
||||||
local actions = queue.actions
|
end
|
||||||
-- split into two categories:
|
|
||||||
-- actions_now: actions to execute now
|
|
||||||
-- queue.actions: actions to execute later
|
|
||||||
local actions_now = {}
|
|
||||||
queue.actions = {}
|
|
||||||
|
|
||||||
for _, ac in ipairs(actions) do
|
local m_time = 0
|
||||||
|
local resumetime = mesecon.setting("resumetime", 4)
|
||||||
|
minetest.register_globalstep(function (dtime)
|
||||||
|
m_time = m_time + dtime
|
||||||
|
-- don't even try if server has not been running for XY seconds; resumetime = time to wait
|
||||||
|
-- after starting the server before processing the ActionQueue, don't set this too low
|
||||||
|
if (m_time < resumetime) then return end
|
||||||
|
local actions = mesecon.tablecopy(mesecon.queue.actions)
|
||||||
|
local actions_now={}
|
||||||
|
|
||||||
|
mesecon.queue.actions = {}
|
||||||
|
|
||||||
|
-- sort actions into two categories:
|
||||||
|
-- those toexecute now (actions_now) and those to execute later (mesecon.queue.actions)
|
||||||
|
for i, ac in ipairs(actions) do
|
||||||
if ac.time > 0 then
|
if ac.time > 0 then
|
||||||
-- action ac is to be executed later
|
ac.time = ac.time - dtime -- executed later
|
||||||
-- ~> insert into queue.actions
|
table.insert(mesecon.queue.actions, ac)
|
||||||
ac.time = ac.time - dtime
|
|
||||||
table.insert(queue.actions, ac)
|
|
||||||
else
|
else
|
||||||
-- action ac is to be executed now
|
|
||||||
-- ~> insert into actions_now
|
|
||||||
table.insert(actions_now, ac)
|
table.insert(actions_now, ac)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- stable-sort the executed actions after their priority
|
while(#actions_now > 0) do -- execute highest priorities first, until all are executed
|
||||||
-- some constructions might depend on the execution order, hence we first
|
local hp = get_highest_priority(actions_now)
|
||||||
-- execute the actions that had a lower index in actions_now
|
mesecon.queue:execute(actions_now[hp])
|
||||||
local old_action_order = {}
|
table.remove(actions_now, hp)
|
||||||
for i, ac in ipairs(actions_now) do
|
|
||||||
old_action_order[ac] = i
|
|
||||||
end
|
end
|
||||||
table.sort(actions_now, function(ac1, ac2)
|
end)
|
||||||
if ac1.priority ~= ac2.priority then
|
|
||||||
return ac1.priority > ac2.priority
|
|
||||||
else
|
|
||||||
return old_action_order[ac1] < old_action_order[ac2]
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
-- execute highest priorities first, until all are executed
|
function mesecon.queue:execute(action)
|
||||||
for _, ac in ipairs(actions_now) do
|
mesecon.queue.funcs[action.func](action.pos, unpack(action.params))
|
||||||
queue:execute(ac)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- delay the time the globalsteps start to be execute by 4 seconds
|
|
||||||
do
|
|
||||||
local m_time = 0
|
|
||||||
local resumetime = mesecon.setting("resumetime", 4)
|
|
||||||
local globalstep_func_index = #minetest.registered_globalsteps + 1
|
|
||||||
|
|
||||||
minetest.register_globalstep(function(dtime)
|
|
||||||
m_time = m_time + dtime
|
|
||||||
-- don't even try if server has not been running for XY seconds; resumetime = time to wait
|
|
||||||
-- after starting the server before processing the ActionQueue, don't set this too low
|
|
||||||
if m_time < resumetime then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
-- replace this globalstep function
|
|
||||||
minetest.registered_globalsteps[globalstep_func_index] = globalstep_func
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
function queue:execute(action)
|
|
||||||
-- ignore if action queue function name doesn't exist,
|
|
||||||
-- (e.g. in case the action queue savegame was written by an old mesecons version)
|
|
||||||
if queue.funcs[action.func] then
|
|
||||||
queue.funcs[action.func](action.pos, unpack(action.params))
|
|
||||||
end
|
|
||||||
end
|
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
|
||||||
queue.actions = mesecon.file2table("mesecon_actionqueue")
|
mesecon.queue.actions = mesecon.file2table("mesecon_actionqueue")
|
||||||
|
|
||||||
minetest.register_on_shutdown(function()
|
minetest.register_on_shutdown(function()
|
||||||
mesecon.table2file("mesecon_actionqueue", queue.actions)
|
mesecon.table2file("mesecon_actionqueue", mesecon.queue.actions)
|
||||||
end)
|
end)
|
||||||
|
1
mesecons/depends.txt
Executable file
@ -0,0 +1 @@
|
|||||||
|
default
|
1
mesecons/doc/mesecon/description.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
Mesecons are the wires, use them to connect effectors with receptors.
|
BIN
mesecons/doc/mesecon/preview.png
Executable file
After Width: | Height: | Size: 29 KiB |
BIN
mesecons/doc/mesecon/recipe.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
47
mesecons/init.lua
Normal file → Executable file
@ -3,7 +3,7 @@
|
|||||||
-- | \/ | |___ ____ |___ | | | | \ | |____
|
-- | \/ | |___ ____ |___ | | | | \ | |____
|
||||||
-- | | | | | | | | | \ | |
|
-- | | | | | | | | | \ | |
|
||||||
-- | | |___ ____| |___ |____ |____| | \| ____|
|
-- | | |___ ____| |___ |____ |____| | \| ____|
|
||||||
-- by Jeija, Uberi (Temperest), sfan5, VanessaE, Hawk777 and contributors
|
-- by Jeija, Uberi (Temperest), sfan5, VanessaE
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
@ -11,7 +11,7 @@
|
|||||||
-- See the documentation on the forum for additional information, especially about crafting
|
-- See the documentation on the forum for additional information, especially about crafting
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
-- For basic development resources, see http://mesecons.net/developers.html
|
-- For developer documentation see the Developers' section on mesecons.TK
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
@ -70,11 +70,19 @@ dofile(minetest.get_modpath("mesecons").."/internal.lua");
|
|||||||
-- these are the only functions you need to remember
|
-- these are the only functions you need to remember
|
||||||
|
|
||||||
mesecon.queue:add_function("receptor_on", function (pos, rules)
|
mesecon.queue:add_function("receptor_on", function (pos, rules)
|
||||||
mesecon.vm_begin()
|
|
||||||
|
|
||||||
rules = rules or mesecon.rules.default
|
rules = rules or mesecon.rules.default
|
||||||
|
|
||||||
-- Call turnon on all linking positions
|
-- 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
|
||||||
|
local np = vector.add(pos, rule)
|
||||||
|
-- if area is not loaded, keep trying
|
||||||
|
if minetest.get_node_or_nil(np) == nil then
|
||||||
|
mesecon.queue:add_action(pos, "receptor_on", {rules}, nil, rules)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 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 = vector.add(pos, rule)
|
||||||
local rulenames = mesecon.rules_link_rule_all(pos, rule)
|
local rulenames = mesecon.rules_link_rule_all(pos, rule)
|
||||||
@ -82,8 +90,6 @@ mesecon.queue:add_function("receptor_on", function (pos, rules)
|
|||||||
mesecon.turnon(np, rulename)
|
mesecon.turnon(np, rulename)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
mesecon.vm_commit()
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
function mesecon.receptor_on(pos, rules)
|
function mesecon.receptor_on(pos, rules)
|
||||||
@ -93,21 +99,23 @@ end
|
|||||||
mesecon.queue:add_function("receptor_off", function (pos, rules)
|
mesecon.queue:add_function("receptor_off", function (pos, rules)
|
||||||
rules = rules or mesecon.rules.default
|
rules = rules or mesecon.rules.default
|
||||||
|
|
||||||
-- Call turnoff on all linking positions
|
-- 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
|
||||||
|
local np = vector.add(pos, rule)
|
||||||
|
if minetest.get_node_or_nil(np) == nil then
|
||||||
|
mesecon.queue:add_action(pos, "receptor_off", {rules}, nil, rules)
|
||||||
|
return
|
||||||
|
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 = vector.add(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.vm_begin()
|
if not mesecon.connected_to_receptor(np, mesecon.invertRule(rule)) then
|
||||||
mesecon.changesignal(np, minetest.get_node(np), rulename, mesecon.state.off, 2)
|
mesecon.turnoff(np, rulename)
|
||||||
|
|
||||||
-- Turnoff returns true if turnoff process was successful, no onstate receptor
|
|
||||||
-- was found along the way. Commit changes that were made in voxelmanip. If turnoff
|
|
||||||
-- returns true, an onstate receptor was found, abort voxelmanip transaction.
|
|
||||||
if (mesecon.turnoff(np, rulename)) then
|
|
||||||
mesecon.vm_commit()
|
|
||||||
else
|
else
|
||||||
mesecon.vm_abort()
|
mesecon.changesignal(np, minetest.get_node(np), rulename, mesecon.state.off, 2)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -118,11 +126,14 @@ function mesecon.receptor_off(pos, rules)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
print("[OK] Mesecons")
|
minetest.log("action", "[OK] Mesecons")
|
||||||
|
|
||||||
-- Deprecated stuff
|
-- Deprecated stuff
|
||||||
-- To be removed in future releases
|
-- To be removed in future releases
|
||||||
dofile(minetest.get_modpath("mesecons").."/legacy.lua");
|
dofile(minetest.get_modpath("mesecons").."/legacy.lua");
|
||||||
|
|
||||||
|
--The actual wires
|
||||||
|
dofile(minetest.get_modpath("mesecons").."/wires.lua");
|
||||||
|
|
||||||
--Services like turnoff receptor on dignode and so on
|
--Services like turnoff receptor on dignode and so on
|
||||||
dofile(minetest.get_modpath("mesecons").."/services.lua");
|
dofile(minetest.get_modpath("mesecons").."/services.lua");
|
||||||
|
269
mesecons/internal.lua
Normal file → Executable file
@ -37,6 +37,11 @@
|
|||||||
-- HIGH-LEVEL Internals
|
-- HIGH-LEVEL Internals
|
||||||
-- mesecon.is_power_on(pos) --> Returns true if pos emits power in any way
|
-- mesecon.is_power_on(pos) --> Returns true if pos emits power in any way
|
||||||
-- mesecon.is_power_off(pos) --> Returns true if pos does not emit power in any way
|
-- mesecon.is_power_off(pos) --> Returns true if pos does not emit power in any way
|
||||||
|
-- mesecon.turnon(pos, link) --> link is the input rule that caused calling turnon, turns on every connected node, iterative
|
||||||
|
-- mesecon.turnoff(pos, link) --> link is the input rule that caused calling turnoff, turns off every connected node, iterative
|
||||||
|
-- mesecon.connected_to_receptor(pos, link) --> Returns true if pos is connected to a receptor directly or via conductors, iterative
|
||||||
|
-- mesecon.rules_link(output, input, dug_outputrules) --> Returns true if outputposition + outputrules = inputposition and inputposition + inputrules = outputposition (if the two positions connect)
|
||||||
|
-- mesecon.rules_link_anydir(outp., inp., d_outpr.) --> Same as rules mesecon.rules_link but also returns true if output and input are swapped
|
||||||
-- mesecon.is_powered(pos) --> Returns true if pos is powered by a receptor or a conductor
|
-- mesecon.is_powered(pos) --> Returns true if pos is powered by a receptor or a conductor
|
||||||
|
|
||||||
-- RULES ROTATION helpers
|
-- RULES ROTATION helpers
|
||||||
@ -366,32 +371,52 @@ function mesecon.is_power_off(pos, rulename)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Turn off an equipotential section starting at `pos`, which outputs in the direction of `link`.
|
|
||||||
-- Breadth-first search. Map is abstracted away in a voxelmanip.
|
|
||||||
-- Follow all all conductor paths replacing conductors that were already
|
|
||||||
-- looked at, activating / changing all effectors along the way.
|
|
||||||
function mesecon.turnon(pos, link)
|
function mesecon.turnon(pos, link)
|
||||||
local frontiers = {{pos = pos, link = link}}
|
local frontiers = {{pos = pos, link = link}}
|
||||||
|
|
||||||
local depth = 1
|
local depth = 1
|
||||||
while frontiers[1] do
|
while frontiers[depth] do
|
||||||
local f = table.remove(frontiers, 1)
|
local f = frontiers[depth]
|
||||||
local node = mesecon.get_node_force(f.pos)
|
local node = mesecon.get_node_force(f.pos)
|
||||||
|
|
||||||
|
-- area not loaded, postpone action
|
||||||
if not node then
|
if not node then
|
||||||
-- Area does not exist; do nothing
|
mesecon.queue:add_action(f.pos, "turnon", {f.link}, nil, true)
|
||||||
elseif mesecon.is_conductor_off(node, f.link) then
|
elseif mesecon.is_conductor_off(node, f.link) then
|
||||||
local rules = mesecon.conductor_get_rules(node)
|
local rules = mesecon.conductor_get_rules(node)
|
||||||
|
|
||||||
-- Call turnon on neighbors
|
-- Success: If false, at least one neighboring node is unloaded,
|
||||||
|
-- postpone turning on action
|
||||||
|
local success = true
|
||||||
|
local neighborlinks = {}
|
||||||
|
|
||||||
|
-- call turnon on neighbors
|
||||||
for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do
|
for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do
|
||||||
local np = vector.add(f.pos, r)
|
local np = vector.add(f.pos, r)
|
||||||
for _, l in ipairs(mesecon.rules_link_rule_all(f.pos, r)) do
|
|
||||||
table.insert(frontiers, {pos = np, link = l})
|
-- Neighboring node not loaded, postpone turning on current node
|
||||||
|
-- since we can't even know if neighboring node has matching rules
|
||||||
|
if not mesecon.get_node_force(np) then
|
||||||
|
success = false
|
||||||
|
break
|
||||||
|
else
|
||||||
|
neighborlinks[minetest.hash_node_position(np)] = mesecon.rules_link_rule_all(f.pos, r)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
mesecon.swap_node_force(f.pos, mesecon.get_conductor_on(node, f.link))
|
if success then
|
||||||
|
minetest.swap_node(f.pos, {name = mesecon.get_conductor_on(node, f.link),
|
||||||
|
param2 = node.param2})
|
||||||
|
|
||||||
|
for npos, links in pairs(neighborlinks) do
|
||||||
|
-- links = all links to node, l = each single link
|
||||||
|
for _, l in ipairs(links) do
|
||||||
|
table.insert(frontiers, {pos = minetest.get_position_from_hash(npos), link = l})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
mesecon.queue:add_action(f.pos, "turnon", {f.link}, nil, true)
|
||||||
|
end
|
||||||
elseif mesecon.is_effector(node.name) then
|
elseif mesecon.is_effector(node.name) then
|
||||||
mesecon.changesignal(f.pos, node, f.link, mesecon.state.on, depth)
|
mesecon.changesignal(f.pos, node, f.link, mesecon.state.on, depth)
|
||||||
if mesecon.is_effector_off(node.name) then
|
if mesecon.is_effector_off(node.name) then
|
||||||
@ -402,77 +427,151 @@ function mesecon.turnon(pos, link)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Turn on an equipotential section starting at `pos`, which outputs in the direction of `link`.
|
mesecon.queue:add_function("turnon", function(pos, rulename, recdepth)
|
||||||
-- Breadth-first search. Map is abstracted away in a voxelmanip.
|
mesecon.turnon(pos, rulename, recdepth)
|
||||||
-- Follow all all conductor paths replacing conductors that were already
|
end)
|
||||||
-- looked at, deactivating / changing all effectors along the way.
|
|
||||||
-- In case an onstate receptor is discovered, abort the process by returning false, which will
|
|
||||||
-- cause `receptor_off` to discard all changes made in the voxelmanip.
|
|
||||||
-- Contrary to turnon, turnoff has to cache all change and deactivate signals so that they will only
|
|
||||||
-- be called in the very end when we can be sure that no conductor was found along the path.
|
|
||||||
--
|
|
||||||
-- Signal table entry structure:
|
|
||||||
-- {
|
|
||||||
-- pos = position of effector,
|
|
||||||
-- node = node descriptor (name, param1 and param2),
|
|
||||||
-- link = link the effector is connected to,
|
|
||||||
-- depth = indicates order in which signals wire fired, higher is later
|
|
||||||
-- }
|
|
||||||
function mesecon.turnoff(pos, link)
|
function mesecon.turnoff(pos, link)
|
||||||
local frontiers = {{pos = pos, link = link}}
|
local frontiers = {{pos = pos, link = link}}
|
||||||
local signals = {}
|
|
||||||
|
|
||||||
local depth = 1
|
local depth = 1
|
||||||
while frontiers[1] do
|
while frontiers[depth] do
|
||||||
local f = table.remove(frontiers, 1)
|
local f = frontiers[depth]
|
||||||
local node = mesecon.get_node_force(f.pos)
|
local node = mesecon.get_node_force(f.pos)
|
||||||
|
|
||||||
|
-- area not loaded, postpone action
|
||||||
if not node then
|
if not node then
|
||||||
-- Area does not exist; do nothing
|
mesecon.queue:add_action(f.pos, "turnoff", {f.link}, nil, true)
|
||||||
elseif mesecon.is_conductor_on(node, f.link) then
|
elseif mesecon.is_conductor_on(node, f.link) then
|
||||||
local rules = mesecon.conductor_get_rules(node)
|
local rules = mesecon.conductor_get_rules(node)
|
||||||
|
|
||||||
|
-- Success: If false, at least one neighboring node is unloaded,
|
||||||
|
-- postpone turning on action
|
||||||
|
local success = true
|
||||||
|
local neighborlinks = {}
|
||||||
|
|
||||||
|
-- call turnoff on neighbors
|
||||||
for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do
|
for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do
|
||||||
local np = vector.add(f.pos, r)
|
local np = vector.add(f.pos, r)
|
||||||
|
|
||||||
-- Check if an onstate receptor is connected. If that is the case,
|
-- Neighboring node not loaded, postpone turning off current node
|
||||||
-- abort this turnoff process by returning false. `receptor_off` will
|
-- since we can't even know if neighboring node has matching rules
|
||||||
-- discard all the changes that we made in the voxelmanip:
|
if not mesecon.get_node_force(np) then
|
||||||
for _, l in ipairs(mesecon.rules_link_rule_all_inverted(f.pos, r)) do
|
success = false
|
||||||
if mesecon.is_receptor_on(mesecon.get_node_force(np).name) then
|
break
|
||||||
return false
|
else
|
||||||
end
|
neighborlinks[minetest.hash_node_position(np)] = mesecon.rules_link_rule_all(f.pos, r)
|
||||||
end
|
|
||||||
|
|
||||||
-- Call turnoff on neighbors
|
|
||||||
for _, l in ipairs(mesecon.rules_link_rule_all(f.pos, r)) do
|
|
||||||
table.insert(frontiers, {pos = np, link = l})
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
mesecon.swap_node_force(f.pos, mesecon.get_conductor_off(node, f.link))
|
if success then
|
||||||
|
minetest.swap_node(f.pos, {name = mesecon.get_conductor_off(node, f.link),
|
||||||
|
param2 = node.param2})
|
||||||
|
|
||||||
|
for npos, links in pairs(neighborlinks) do
|
||||||
|
-- links = all links to node, l = each single link
|
||||||
|
for _, l in ipairs(links) do
|
||||||
|
table.insert(frontiers, {pos = minetest.get_position_from_hash(npos), link = l})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
mesecon.queue:add_action(f.pos, "turnoff", {f.link}, nil, true)
|
||||||
|
end
|
||||||
elseif mesecon.is_effector(node.name) then
|
elseif mesecon.is_effector(node.name) then
|
||||||
table.insert(signals, {
|
mesecon.changesignal(f.pos, node, f.link, mesecon.state.off, depth)
|
||||||
pos = f.pos,
|
if mesecon.is_effector_on(node.name) and not mesecon.is_powered(f.pos) then
|
||||||
node = node,
|
mesecon.deactivate(f.pos, node, f.link, depth)
|
||||||
link = f.link,
|
end
|
||||||
depth = depth
|
|
||||||
})
|
|
||||||
end
|
end
|
||||||
depth = depth + 1
|
depth = depth + 1
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
for _, sig in ipairs(signals) do
|
mesecon.queue:add_function("turnoff", function(pos, rulename, recdepth)
|
||||||
mesecon.changesignal(sig.pos, sig.node, sig.link, mesecon.state.off, sig.depth)
|
mesecon.turnoff(pos, rulename, recdepth)
|
||||||
if mesecon.is_effector_on(sig.node.name) and not mesecon.is_powered(sig.pos) then
|
end)
|
||||||
mesecon.deactivate(sig.pos, sig.node, sig.link, sig.depth)
|
|
||||||
|
|
||||||
|
function mesecon.connected_to_receptor(pos, link)
|
||||||
|
local node = mesecon.get_node_force(pos)
|
||||||
|
if not node then return false end
|
||||||
|
|
||||||
|
-- Check if conductors around are connected
|
||||||
|
local rules = mesecon.get_any_inputrules(node)
|
||||||
|
if not rules then return false end
|
||||||
|
|
||||||
|
for _, rule in ipairs(mesecon.rule2meta(link, rules)) do
|
||||||
|
local links = mesecon.rules_link_rule_all_inverted(pos, rule)
|
||||||
|
for _, l in ipairs(links) do
|
||||||
|
local np = vector.add(pos, l)
|
||||||
|
if mesecon.find_receptor_on(np, mesecon.invertRule(l)) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return true
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function mesecon.find_receptor_on(pos, link)
|
||||||
|
local frontiers = {{pos = pos, link = link}}
|
||||||
|
local checked = {}
|
||||||
|
|
||||||
|
-- List of positions that have been searched for onstate receptors
|
||||||
|
local depth = 1
|
||||||
|
while frontiers[depth] do
|
||||||
|
local f = frontiers[depth]
|
||||||
|
local node = mesecon.get_node_force(f.pos)
|
||||||
|
|
||||||
|
if not node then return false end
|
||||||
|
if mesecon.is_receptor_on(node.name) then return true end
|
||||||
|
if mesecon.is_conductor_on(node, f.link) then
|
||||||
|
local rules = mesecon.conductor_get_rules(node)
|
||||||
|
|
||||||
|
-- call turnoff on neighbors: normal rules
|
||||||
|
for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do
|
||||||
|
local np = vector.add(f.pos, r)
|
||||||
|
|
||||||
|
local links = mesecon.rules_link_rule_all_inverted(f.pos, r)
|
||||||
|
for _, l in ipairs(links) do
|
||||||
|
local checkedstring = np.x..np.y..np.z..l.x..l.y..l.z
|
||||||
|
if not checked[checkedstring] then
|
||||||
|
table.insert(frontiers, {pos = np, link = l})
|
||||||
|
checked[checkedstring] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
depth = depth + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function mesecon.rules_link(output, input, dug_outputrules) --output/input are positions (outputrules optional, used if node has been dug), second return value: the name of the affected input rule
|
||||||
|
local outputnode = mesecon.get_node_force(output)
|
||||||
|
local inputnode = mesecon.get_node_force(input)
|
||||||
|
|
||||||
|
local outputrules = dug_outputrules or mesecon.get_any_outputrules(outputnode)
|
||||||
|
local inputrules = mesecon.get_any_inputrules(inputnode)
|
||||||
|
if not outputrules or not inputrules then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, outputrule in ipairs(mesecon.flattenrules(outputrules)) do
|
||||||
|
-- Check if output sends to input
|
||||||
|
if vector.equals(vector.add(output, outputrule), input) then
|
||||||
|
for _, inputrule in ipairs(mesecon.flattenrules(inputrules)) do
|
||||||
|
-- Check if input accepts from output
|
||||||
|
if vector.equals(vector.add(input, inputrule), output) then
|
||||||
|
return true, inputrule
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Get all linking inputrules of inputnode (effector or conductor) that is connected to
|
|
||||||
-- outputnode (receptor or conductor) at position `output` and has an output in direction `rule`
|
|
||||||
function mesecon.rules_link_rule_all(output, rule)
|
function mesecon.rules_link_rule_all(output, rule)
|
||||||
local input = vector.add(output, rule)
|
local input = vector.add(output, rule)
|
||||||
local inputnode = mesecon.get_node_force(input)
|
local inputnode = mesecon.get_node_force(input)
|
||||||
@ -492,9 +591,8 @@ function mesecon.rules_link_rule_all(output, rule)
|
|||||||
return rules
|
return rules
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Get all linking outputnodes of outputnode (receptor or conductor) that is connected to
|
|
||||||
-- inputnode (effector or conductor) at position `input` and has an input in direction `rule`
|
|
||||||
function mesecon.rules_link_rule_all_inverted(input, rule)
|
function mesecon.rules_link_rule_all_inverted(input, rule)
|
||||||
|
--local irule = mesecon.invertRule(rule)
|
||||||
local output = vector.add(input, rule)
|
local output = vector.add(input, rule)
|
||||||
local outputnode = mesecon.get_node_force(output)
|
local outputnode = mesecon.get_node_force(output)
|
||||||
local outputrules = mesecon.get_any_outputrules(outputnode)
|
local outputrules = mesecon.get_any_outputrules(outputnode)
|
||||||
@ -511,6 +609,10 @@ function mesecon.rules_link_rule_all_inverted(input, rule)
|
|||||||
return rules
|
return rules
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function mesecon.rules_link_anydir(pos1, pos2)
|
||||||
|
return mesecon.rules_link(pos1, pos2) or mesecon.rules_link(pos2, pos1)
|
||||||
|
end
|
||||||
|
|
||||||
function mesecon.is_powered(pos, rule)
|
function mesecon.is_powered(pos, rule)
|
||||||
local node = mesecon.get_node_force(pos)
|
local node = mesecon.get_node_force(pos)
|
||||||
local rules = mesecon.get_any_inputrules(node)
|
local rules = mesecon.get_any_inputrules(node)
|
||||||
@ -548,3 +650,52 @@ function mesecon.is_powered(pos, rule)
|
|||||||
if (#sourcepos == 0) then return false
|
if (#sourcepos == 0) then return false
|
||||||
else return sourcepos end
|
else return sourcepos end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--Rules rotation Functions:
|
||||||
|
function mesecon.rotate_rules_right(rules)
|
||||||
|
local nr = {}
|
||||||
|
for i, rule in ipairs(rules) do
|
||||||
|
table.insert(nr, {
|
||||||
|
x = -rule.z,
|
||||||
|
y = rule.y,
|
||||||
|
z = rule.x,
|
||||||
|
name = rule.name})
|
||||||
|
end
|
||||||
|
return nr
|
||||||
|
end
|
||||||
|
|
||||||
|
function mesecon.rotate_rules_left(rules)
|
||||||
|
local nr = {}
|
||||||
|
for i, rule in ipairs(rules) do
|
||||||
|
table.insert(nr, {
|
||||||
|
x = rule.z,
|
||||||
|
y = rule.y,
|
||||||
|
z = -rule.x,
|
||||||
|
name = rule.name})
|
||||||
|
end
|
||||||
|
return nr
|
||||||
|
end
|
||||||
|
|
||||||
|
function mesecon.rotate_rules_down(rules)
|
||||||
|
local nr = {}
|
||||||
|
for i, rule in ipairs(rules) do
|
||||||
|
table.insert(nr, {
|
||||||
|
x = -rule.y,
|
||||||
|
y = rule.x,
|
||||||
|
z = rule.z,
|
||||||
|
name = rule.name})
|
||||||
|
end
|
||||||
|
return nr
|
||||||
|
end
|
||||||
|
|
||||||
|
function mesecon.rotate_rules_up(rules)
|
||||||
|
local nr = {}
|
||||||
|
for i, rule in ipairs(rules) do
|
||||||
|
table.insert(nr, {
|
||||||
|
x = rule.y,
|
||||||
|
y = -rule.x,
|
||||||
|
z = rule.z,
|
||||||
|
name = rule.name})
|
||||||
|
end
|
||||||
|
return nr
|
||||||
|
end
|
||||||
|
38
mesecons/legacy.lua
Normal file → Executable file
@ -1,14 +1,30 @@
|
|||||||
-- Un-forceload any forceloaded mapblocks from older versions of Mesecons which
|
-- Ugly hack to prevent breaking compatibility with other mods
|
||||||
-- used forceloading instead of VoxelManipulators.
|
-- Just remove the following two functions to delete the hack, to be done when other mods have updated
|
||||||
local BLOCKSIZE = 16
|
function mesecon.receptor_on(self, pos, rules)
|
||||||
|
if (self.receptor_on) then
|
||||||
-- convert block hash --> node position
|
print("[Mesecons] Warning: A mod with mesecon support called mesecon:receptor_on.")
|
||||||
local function unhash_blockpos(hash)
|
print("[Mesecons] If you are the programmer of this mod, please update it ")
|
||||||
return vector.multiply(minetest.get_position_from_hash(hash), BLOCKSIZE)
|
print("[Mesecons] to use mesecon.receptor_on instead. mesecon:* is deprecated")
|
||||||
|
print("[Mesecons] Otherwise, please make sure you're running the latest version")
|
||||||
|
print("[Mesecons] of that mod and inform the mod creator.")
|
||||||
|
else
|
||||||
|
rules = pos
|
||||||
|
pos = self
|
||||||
|
end
|
||||||
|
mesecon.queue:add_action(pos, "receptor_on", {rules}, nil, rules)
|
||||||
end
|
end
|
||||||
|
|
||||||
local old_forceloaded_blocks = mesecon.file2table("mesecon_forceloaded")
|
function mesecon.receptor_off(self, pos, rules)
|
||||||
for hash, _ in pairs(old_forceloaded_blocks) do
|
if (self.receptor_off) then
|
||||||
minetest.forceload_free_block(unhash_blockpos(hash))
|
print("[Mesecons] Warning: A mod with mesecon support called mesecon:receptor_off.")
|
||||||
|
print("[Mesecons] If you are the programmer of this mod, please update it ")
|
||||||
|
print("[Mesecons] to use mesecon.receptor_off instead. mesecon:* is deprecated")
|
||||||
|
print("[Mesecons] Otherwise, please make sure you're running the latest version")
|
||||||
|
print("[Mesecons] of that mod and inform the mod creator.")
|
||||||
|
else
|
||||||
|
rules = pos
|
||||||
|
pos = self
|
||||||
|
end
|
||||||
|
mesecon.queue:add_action(pos, "receptor_off", {rules}, nil, rules)
|
||||||
end
|
end
|
||||||
os.remove(minetest.get_worldpath()..DIR_DELIM.."mesecon_forceloaded")
|
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
name = mesecons
|
|
||||||
depends = default
|
|
10
mesecons/oldwires.lua
Normal file → Executable file
@ -4,13 +4,13 @@ minetest.register_node("mesecons:mesecon_off", {
|
|||||||
inventory_image = "jeija_mesecon_off.png",
|
inventory_image = "jeija_mesecon_off.png",
|
||||||
wield_image = "jeija_mesecon_off.png",
|
wield_image = "jeija_mesecon_off.png",
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
is_ground_content = false,
|
is_ground_content = true,
|
||||||
walkable = false,
|
walkable = false,
|
||||||
selection_box = {
|
selection_box = {
|
||||||
type = "fixed",
|
type = "fixed",
|
||||||
fixed = {-0.5, -0.5, -0.5, 0.5, -0.45, 0.5},
|
fixed = {-0.5, -0.5, -0.5, 0.5, -0.45, 0.5},
|
||||||
},
|
},
|
||||||
groups = {dig_immediate=3, mesecon=1, mesecon_conductor_craftable=1},
|
groups = {dig_immediate=2, mesecon=1, mesecon_conductor_craftable=1}, --MFF
|
||||||
description="Mesecons",
|
description="Mesecons",
|
||||||
mesecons = {conductor={
|
mesecons = {conductor={
|
||||||
state = mesecon.state.off,
|
state = mesecon.state.off,
|
||||||
@ -22,15 +22,15 @@ minetest.register_node("mesecons:mesecon_on", {
|
|||||||
drawtype = "raillike",
|
drawtype = "raillike",
|
||||||
tiles = {"jeija_mesecon_on.png", "jeija_mesecon_curved_on.png", "jeija_mesecon_t_junction_on.png", "jeija_mesecon_crossing_on.png"},
|
tiles = {"jeija_mesecon_on.png", "jeija_mesecon_curved_on.png", "jeija_mesecon_t_junction_on.png", "jeija_mesecon_crossing_on.png"},
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
is_ground_content = false,
|
is_ground_content = true,
|
||||||
walkable = false,
|
walkable = false,
|
||||||
selection_box = {
|
selection_box = {
|
||||||
type = "fixed",
|
type = "fixed",
|
||||||
fixed = {-0.5, -0.5, -0.5, 0.5, -0.45, 0.5},
|
fixed = {-0.5, -0.5, -0.5, 0.5, -0.45, 0.5},
|
||||||
},
|
},
|
||||||
groups = {dig_immediate=3, not_in_creaive_inventory=1, mesecon=1},
|
groups = {dig_immediate=2, not_in_creaive_inventory=1, mesecon=1}, --MFF
|
||||||
drop = "mesecons:mesecon_off 1",
|
drop = "mesecons:mesecon_off 1",
|
||||||
light_source = minetest.LIGHT_MAX-11,
|
light_source = default.LIGHT_MAX-11,
|
||||||
mesecons = {conductor={
|
mesecons = {conductor={
|
||||||
state = mesecon.state.on,
|
state = mesecon.state.on,
|
||||||
offstate = "mesecons:mesecon_off"
|
offstate = "mesecons:mesecon_off"
|
||||||
|
115
mesecons/presets.lua
Normal file → Executable file
@ -1,85 +1,54 @@
|
|||||||
mesecon.rules = {}
|
mesecon.rules = {}
|
||||||
mesecon.state = {}
|
mesecon.state = {}
|
||||||
|
|
||||||
mesecon.rules.default = {
|
mesecon.rules.default =
|
||||||
{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 = -1, y = 0, z = 0},
|
{x=-1, y=0, z=0},
|
||||||
{x = 0, y = 0, z = 1},
|
{x=0, y=0, z=1},
|
||||||
{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 = 0},
|
{x=-1, y=1, z=0},
|
||||||
{x = -1, y = -1, z = 0},
|
{x=-1, y=-1, z=0},
|
||||||
{x = 0, y = 1, z = 1},
|
{x=0, y=1, z=1},
|
||||||
{x = 0, y = -1, z = 1},
|
{x=0, y=-1, z=1},
|
||||||
{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.floor = mesecon.mergetable(mesecon.rules.default, {{x = 0, y = -1, z = 0}})
|
mesecon.rules.pplate = mesecon.mergetable(mesecon.rules.default, {{x=0, y=-2, z=0}})
|
||||||
|
|
||||||
mesecon.rules.pplate = mesecon.mergetable(mesecon.rules.floor, {{x = 0, y = -2, z = 0}})
|
mesecon.rules.buttonlike =
|
||||||
|
{{x = 1, y = 0, 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 = 2, y = 0, z = 0}}
|
||||||
|
|
||||||
mesecon.rules.buttonlike = {
|
mesecon.rules.flat =
|
||||||
{x = 1, y = 0, z = 0},
|
{{x = 1, y = 0, z = 0},
|
||||||
{x = 1, y = 1, z = 0},
|
{x =-1, y = 0, z = 0},
|
||||||
{x = 1, y = -1, z = 0},
|
{x = 0, y = 0, z = 1},
|
||||||
{x = 1, y = -1, z = 1},
|
{x = 0, y = 0, z =-1}}
|
||||||
{x = 1, y = -1, z = -1},
|
|
||||||
{x = 2, y = 0, z = 0},
|
|
||||||
}
|
|
||||||
|
|
||||||
mesecon.rules.flat = {
|
mesecon.rules.alldirs =
|
||||||
{x = 1, y = 0, z = 0},
|
{{x= 1, y= 0, z= 0},
|
||||||
{x = -1, y = 0, z = 0},
|
{x=-1, y= 0, z= 0},
|
||||||
{x = 0, y = 0, z = 1},
|
{x= 0, y= 1, z= 0},
|
||||||
{x = 0, y = 0, z = -1},
|
{x= 0, y=-1, z= 0},
|
||||||
}
|
{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},
|
|
||||||
}
|
|
||||||
|
|
||||||
local rules_wallmounted = {
|
|
||||||
xp = mesecon.rotate_rules_down(mesecon.rules.floor),
|
|
||||||
xn = mesecon.rotate_rules_up(mesecon.rules.floor),
|
|
||||||
yp = mesecon.rotate_rules_up(mesecon.rotate_rules_up(mesecon.rules.floor)),
|
|
||||||
yn = mesecon.rules.floor,
|
|
||||||
zp = mesecon.rotate_rules_left(mesecon.rotate_rules_up(mesecon.rules.floor)),
|
|
||||||
zn = mesecon.rotate_rules_right(mesecon.rotate_rules_up(mesecon.rules.floor)),
|
|
||||||
}
|
|
||||||
|
|
||||||
local rules_buttonlike = {
|
|
||||||
xp = mesecon.rules.buttonlike,
|
|
||||||
xn = mesecon.rotate_rules_right(mesecon.rotate_rules_right(mesecon.rules.buttonlike)),
|
|
||||||
yp = mesecon.rotate_rules_down(mesecon.rules.buttonlike),
|
|
||||||
yn = mesecon.rotate_rules_up(mesecon.rules.buttonlike),
|
|
||||||
zp = mesecon.rotate_rules_right(mesecon.rules.buttonlike),
|
|
||||||
zn = mesecon.rotate_rules_left(mesecon.rules.buttonlike),
|
|
||||||
}
|
|
||||||
|
|
||||||
local function rules_from_dir(ruleset, dir)
|
|
||||||
if dir.x == 1 then return ruleset.xp end
|
|
||||||
if dir.y == 1 then return ruleset.yp end
|
|
||||||
if dir.z == 1 then return ruleset.zp end
|
|
||||||
if dir.x == -1 then return ruleset.xn end
|
|
||||||
if dir.y == -1 then return ruleset.yn end
|
|
||||||
if dir.z == -1 then return ruleset.zn end
|
|
||||||
end
|
|
||||||
|
|
||||||
mesecon.rules.wallmounted_get = function(node)
|
|
||||||
local dir = minetest.wallmounted_to_dir(node.param2)
|
|
||||||
return rules_from_dir(rules_wallmounted, dir)
|
|
||||||
end
|
|
||||||
|
|
||||||
mesecon.rules.buttonlike_get = function(node)
|
mesecon.rules.buttonlike_get = function(node)
|
||||||
local dir = minetest.facedir_to_dir(node.param2)
|
local rules = mesecon.rules.buttonlike
|
||||||
return rules_from_dir(rules_buttonlike, dir)
|
if node.param2 == 2 then
|
||||||
|
rules=mesecon.rotate_rules_left(rules)
|
||||||
|
elseif node.param2 == 3 then
|
||||||
|
rules=mesecon.rotate_rules_right(mesecon.rotate_rules_right(rules))
|
||||||
|
elseif node.param2 == 0 then
|
||||||
|
rules=mesecon.rotate_rules_right(rules)
|
||||||
|
end
|
||||||
|
return rules
|
||||||
end
|
end
|
||||||
|
|
||||||
mesecon.state.on = "on"
|
mesecon.state.on = "on"
|
||||||
|
86
mesecons/services.lua
Normal file → Executable file
@ -1,7 +1,7 @@
|
|||||||
-- Dig and place services
|
-- Dig and place services
|
||||||
|
|
||||||
mesecon.on_placenode = function(pos, node)
|
mesecon.on_placenode = function (pos, node)
|
||||||
mesecon.execute_autoconnect_hooks_now(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
|
||||||
@ -21,8 +21,7 @@ mesecon.on_placenode = function(pos, node)
|
|||||||
end
|
end
|
||||||
--mesecon.receptor_on (pos, mesecon.conductor_get_rules(node))
|
--mesecon.receptor_on (pos, mesecon.conductor_get_rules(node))
|
||||||
elseif mesecon.is_conductor_on(node) then
|
elseif mesecon.is_conductor_on(node) then
|
||||||
node.name = mesecon.get_conductor_off(node)
|
minetest.swap_node(pos, {name = mesecon.get_conductor_off(node)})
|
||||||
minetest.swap_node(pos, node)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -53,84 +52,45 @@ mesecon.on_placenode = function(pos, node)
|
|||||||
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})
|
||||||
mesecon.execute_autoconnect_hooks_queue(pos, node)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon.on_blastnode(pos, intensity)
|
mesecon.queue:add_function("update_autoconnect", mesecon.update_autoconnect)
|
||||||
local node = minetest.get_node(pos)
|
|
||||||
minetest.remove_node(pos)
|
|
||||||
mesecon.on_dignode(pos, node)
|
|
||||||
return minetest.get_node_drops(node.name, "")
|
|
||||||
end
|
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
-- Overheating service for fast circuits
|
-- Overheating service for fast circuits
|
||||||
local OVERHEAT_MAX = mesecon.setting("overheat_max", 20)
|
|
||||||
local COOLDOWN_TIME = mesecon.setting("cooldown_time", 2.0)
|
|
||||||
local COOLDOWN_STEP = mesecon.setting("cooldown_granularity", 0.5)
|
|
||||||
local COOLDOWN_MULTIPLIER = OVERHEAT_MAX / COOLDOWN_TIME
|
|
||||||
local cooldown_timer = 0.0
|
|
||||||
local object_heat = {}
|
|
||||||
|
|
||||||
-- returns true if heat is too high
|
-- returns true if heat is too high
|
||||||
function mesecon.do_overheat(pos)
|
mesecon.do_overheat = function(pos)
|
||||||
local id = minetest.hash_node_position(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
local heat = (object_heat[id] or 0) + 1
|
local heat = meta:get_int("heat") or 0
|
||||||
object_heat[id] = heat
|
|
||||||
if heat >= OVERHEAT_MAX then
|
heat = heat + 1
|
||||||
minetest.log("action", "Node overheats at " .. minetest.pos_to_string(pos))
|
meta:set_int("heat", heat)
|
||||||
object_heat[id] = nil
|
|
||||||
|
if heat < mesecon.setting("overheat_max", 20) then
|
||||||
|
mesecon.queue:add_action(pos, "cooldown", {}, 1, nil, 0)
|
||||||
|
else
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon.do_cooldown(pos)
|
|
||||||
local id = minetest.hash_node_position(pos)
|
|
||||||
object_heat[id] = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function mesecon.get_heat(pos)
|
mesecon.queue:add_function("cooldown", function (pos)
|
||||||
local id = minetest.hash_node_position(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
return object_heat[id] or 0
|
local heat = meta:get_int("heat")
|
||||||
end
|
|
||||||
|
|
||||||
function mesecon.move_hot_nodes(moved_nodes)
|
if (heat > 0) then
|
||||||
local new_heat = {}
|
meta:set_int("heat", heat - 1)
|
||||||
for _, n in ipairs(moved_nodes) do
|
|
||||||
local old_id = minetest.hash_node_position(n.oldpos)
|
|
||||||
local new_id = minetest.hash_node_position(n.pos)
|
|
||||||
new_heat[new_id] = object_heat[old_id]
|
|
||||||
object_heat[old_id] = nil
|
|
||||||
end
|
end
|
||||||
for id, heat in pairs(new_heat) do
|
end)
|
||||||
object_heat[id] = heat
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function global_cooldown(dtime)
|
|
||||||
cooldown_timer = cooldown_timer + dtime
|
|
||||||
if cooldown_timer < COOLDOWN_STEP then
|
|
||||||
return -- don't overload the CPU
|
|
||||||
end
|
|
||||||
local cooldown = COOLDOWN_MULTIPLIER * cooldown_timer
|
|
||||||
cooldown_timer = 0
|
|
||||||
for id, heat in pairs(object_heat) do
|
|
||||||
heat = heat - cooldown
|
|
||||||
if heat <= 0 then
|
|
||||||
object_heat[id] = nil -- free some RAM
|
|
||||||
else
|
|
||||||
object_heat[id] = heat
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
minetest.register_globalstep(global_cooldown)
|
|
||||||
|
30
mesecons/settings.lua
Normal file → Executable file
@ -1,15 +1,15 @@
|
|||||||
-- SETTINGS
|
-- SETTINGS
|
||||||
function mesecon.setting(setting, default)
|
function mesecon.setting(setting, default)
|
||||||
if type(default) == "boolean" then
|
if type(default) == "boolean" then
|
||||||
local read = minetest.settings:get_bool("mesecon."..setting)
|
local read = minetest.setting_getbool("mesecon."..setting)
|
||||||
if read == nil then
|
if read == nil then
|
||||||
return default
|
return default
|
||||||
else
|
else
|
||||||
return read
|
return read
|
||||||
end
|
end
|
||||||
elseif type(default) == "string" then
|
elseif type(default) == "string" then
|
||||||
return minetest.settings:get("mesecon."..setting) or default
|
return minetest.setting_get("mesecon."..setting) or default
|
||||||
elseif type(default) == "number" then
|
elseif type(default) == "number" then
|
||||||
return tonumber(minetest.settings:get("mesecon."..setting) or default)
|
return tonumber(minetest.setting_get("mesecon."..setting) or default)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Before Width: | Height: | Size: 191 B |
Before Width: | Height: | Size: 844 B |
Before Width: | Height: | Size: 838 B |
Before Width: | Height: | Size: 851 B |
Before Width: | Height: | Size: 846 B |
Before Width: | Height: | Size: 222 B |
Before Width: | Height: | Size: 504 B |
BIN
mesecons/textures/mesecons_wire_inv.png
Normal file → Executable file
Before Width: | Height: | Size: 144 B After Width: | Height: | Size: 186 B |
BIN
mesecons/textures/mesecons_wire_off.png
Normal file → Executable file
Before Width: | Height: | Size: 377 B After Width: | Height: | Size: 378 B |
BIN
mesecons/textures/mesecons_wire_on.png
Normal file → Executable file
Before Width: | Height: | Size: 362 B After Width: | Height: | Size: 366 B |
257
mesecons/util.lua
Normal file → Executable file
@ -6,56 +6,6 @@ function mesecon.move_node(pos, newpos)
|
|||||||
minetest.get_meta(pos):from_table(meta)
|
minetest.get_meta(pos):from_table(meta)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Rules rotation Functions:
|
|
||||||
function mesecon.rotate_rules_right(rules)
|
|
||||||
local nr = {}
|
|
||||||
for i, rule in ipairs(rules) do
|
|
||||||
table.insert(nr, {
|
|
||||||
x = -rule.z,
|
|
||||||
y = rule.y,
|
|
||||||
z = rule.x,
|
|
||||||
name = rule.name})
|
|
||||||
end
|
|
||||||
return nr
|
|
||||||
end
|
|
||||||
|
|
||||||
function mesecon.rotate_rules_left(rules)
|
|
||||||
local nr = {}
|
|
||||||
for i, rule in ipairs(rules) do
|
|
||||||
table.insert(nr, {
|
|
||||||
x = rule.z,
|
|
||||||
y = rule.y,
|
|
||||||
z = -rule.x,
|
|
||||||
name = rule.name})
|
|
||||||
end
|
|
||||||
return nr
|
|
||||||
end
|
|
||||||
|
|
||||||
function mesecon.rotate_rules_down(rules)
|
|
||||||
local nr = {}
|
|
||||||
for i, rule in ipairs(rules) do
|
|
||||||
table.insert(nr, {
|
|
||||||
x = -rule.y,
|
|
||||||
y = rule.x,
|
|
||||||
z = rule.z,
|
|
||||||
name = rule.name})
|
|
||||||
end
|
|
||||||
return nr
|
|
||||||
end
|
|
||||||
|
|
||||||
function mesecon.rotate_rules_up(rules)
|
|
||||||
local nr = {}
|
|
||||||
for i, rule in ipairs(rules) do
|
|
||||||
table.insert(nr, {
|
|
||||||
x = rule.y,
|
|
||||||
y = -rule.x,
|
|
||||||
z = rule.z,
|
|
||||||
name = rule.name})
|
|
||||||
end
|
|
||||||
return nr
|
|
||||||
end
|
|
||||||
--
|
|
||||||
|
|
||||||
function mesecon.flattenrules(allrules)
|
function mesecon.flattenrules(allrules)
|
||||||
--[[
|
--[[
|
||||||
{
|
{
|
||||||
@ -186,30 +136,29 @@ function mesecon.invertRule(r)
|
|||||||
return vector.multiply(r, -1)
|
return vector.multiply(r, -1)
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon.tablecopy(obj) -- deep copy
|
function mesecon.tablecopy(table) -- deep table copy
|
||||||
if type(obj) == "table" then
|
if type(table) ~= "table" then return table end -- no need to copy
|
||||||
return table.copy(obj)
|
local newtable = {}
|
||||||
|
|
||||||
|
for idx, item in pairs(table) do
|
||||||
|
if type(item) == "table" then
|
||||||
|
newtable[idx] = mesecon.tablecopy(item)
|
||||||
|
else
|
||||||
|
newtable[idx] = item
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return obj
|
|
||||||
|
return newtable
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Returns whether two values are equal.
|
|
||||||
-- In tables, keys are compared for identity but values are compared recursively.
|
|
||||||
-- There is no protection from infinite recursion.
|
|
||||||
function mesecon.cmpAny(t1, t2)
|
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" then return t1 == t2 end
|
if type(t1) ~= "table" and type(t2) ~= "table" then return t1 == t2 end
|
||||||
|
|
||||||
-- Check that for each key of `t1` both tables have the same value
|
|
||||||
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
|
||||||
|
|
||||||
-- Check that all keys of `t2` are also keys of `t1` so were checked in the previous loop
|
|
||||||
for i, _ in pairs(t2) do
|
|
||||||
if t1[i] == nil then return false end
|
|
||||||
end
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -229,7 +178,6 @@ end
|
|||||||
|
|
||||||
function mesecon.register_node(name, spec_common, spec_off, spec_on)
|
function mesecon.register_node(name, spec_common, spec_off, spec_on)
|
||||||
spec_common.drop = spec_common.drop or name .. "_off"
|
spec_common.drop = spec_common.drop or name .. "_off"
|
||||||
spec_common.on_blast = spec_common.on_blast or mesecon.on_blastnode
|
|
||||||
spec_common.__mesecon_basename = name
|
spec_common.__mesecon_basename = name
|
||||||
spec_on.__mesecon_state = "on"
|
spec_on.__mesecon_state = "on"
|
||||||
spec_off.__mesecon_state = "off"
|
spec_off.__mesecon_state = "off"
|
||||||
@ -271,7 +219,7 @@ function mesecon.table2file(filename, table)
|
|||||||
f:close()
|
f:close()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Block position "hashing" (convert to integer) functions for voxelmanip cache
|
-- Forceloading: Force server to load area if node is nil
|
||||||
local BLOCKSIZE = 16
|
local BLOCKSIZE = 16
|
||||||
|
|
||||||
-- convert node position --> block hash
|
-- convert node position --> block hash
|
||||||
@ -283,160 +231,45 @@ local function hash_blockpos(pos)
|
|||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Maps from a hashed mapblock position (as returned by hash_blockpos) to a
|
-- convert block hash --> node position
|
||||||
-- table.
|
local function unhash_blockpos(hash)
|
||||||
--
|
return vector.multiply(minetest.get_position_from_hash(hash), BLOCKSIZE)
|
||||||
-- Contents of the table are:
|
|
||||||
-- “vm” → the VoxelManipulator
|
|
||||||
-- “va” → the VoxelArea
|
|
||||||
-- “data” → the data array
|
|
||||||
-- “param1” → the param1 array
|
|
||||||
-- “param2” → the param2 array
|
|
||||||
-- “dirty” → true if data has been modified
|
|
||||||
--
|
|
||||||
-- Nil if no VM-based transaction is in progress.
|
|
||||||
local vm_cache = nil
|
|
||||||
|
|
||||||
-- Starts a VoxelManipulator-based transaction.
|
|
||||||
--
|
|
||||||
-- During a VM transaction, calls to vm_get_node and vm_swap_node operate on a
|
|
||||||
-- cached copy of the world loaded via VoxelManipulators. That cache can later
|
|
||||||
-- be committed to the real map by means of vm_commit or discarded by means of
|
|
||||||
-- vm_abort.
|
|
||||||
function mesecon.vm_begin()
|
|
||||||
vm_cache = {}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Finishes a VoxelManipulator-based transaction, freeing the VMs and map data
|
mesecon.forceloaded_blocks = {}
|
||||||
-- and writing back any modified areas.
|
|
||||||
function mesecon.vm_commit()
|
|
||||||
for hash, tbl in pairs(vm_cache) do
|
|
||||||
if tbl.dirty then
|
|
||||||
local vm = tbl.vm
|
|
||||||
vm:set_data(tbl.data)
|
|
||||||
vm:write_to_map()
|
|
||||||
vm:update_map()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
vm_cache = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Finishes a VoxelManipulator-based transaction, freeing the VMs and throwing
|
-- get node and force-load area
|
||||||
-- away any modified areas.
|
|
||||||
function mesecon.vm_abort()
|
|
||||||
vm_cache = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Gets the cache entry covering a position, populating it if necessary.
|
|
||||||
local function vm_get_or_create_entry(pos)
|
|
||||||
local hash = hash_blockpos(pos)
|
|
||||||
local tbl = vm_cache[hash]
|
|
||||||
if not tbl then
|
|
||||||
local vm = minetest.get_voxel_manip(pos, pos)
|
|
||||||
local min_pos, max_pos = vm:get_emerged_area()
|
|
||||||
local va = VoxelArea:new{MinEdge = min_pos, MaxEdge = max_pos}
|
|
||||||
tbl = {vm = vm, va = va, data = vm:get_data(), param1 = vm:get_light_data(), param2 = vm:get_param2_data(), dirty = false}
|
|
||||||
vm_cache[hash] = tbl
|
|
||||||
end
|
|
||||||
return tbl
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Gets the node at a given position during a VoxelManipulator-based
|
|
||||||
-- transaction.
|
|
||||||
function mesecon.vm_get_node(pos)
|
|
||||||
local tbl = vm_get_or_create_entry(pos)
|
|
||||||
local index = tbl.va:indexp(pos)
|
|
||||||
local node_value = tbl.data[index]
|
|
||||||
if node_value == core.CONTENT_IGNORE then
|
|
||||||
return nil
|
|
||||||
else
|
|
||||||
local node_param1 = tbl.param1[index]
|
|
||||||
local node_param2 = tbl.param2[index]
|
|
||||||
return {name = minetest.get_name_from_content_id(node_value), param1 = node_param1, param2 = node_param2}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Sets a node’s name during a VoxelManipulator-based transaction.
|
|
||||||
--
|
|
||||||
-- Existing param1, param2, and metadata are left alone.
|
|
||||||
function mesecon.vm_swap_node(pos, name)
|
|
||||||
local tbl = vm_get_or_create_entry(pos)
|
|
||||||
local index = tbl.va:indexp(pos)
|
|
||||||
tbl.data[index] = minetest.get_content_id(name)
|
|
||||||
tbl.dirty = true
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Gets the node at a given position, regardless of whether it is loaded or
|
|
||||||
-- not, respecting a transaction if one is in progress.
|
|
||||||
--
|
|
||||||
-- Outside a VM transaction, if the mapblock is not loaded, it is pulled into
|
|
||||||
-- the server’s main map data cache and then accessed from there.
|
|
||||||
--
|
|
||||||
-- Inside a VM transaction, the transaction’s VM cache is used.
|
|
||||||
function mesecon.get_node_force(pos)
|
function mesecon.get_node_force(pos)
|
||||||
if vm_cache then
|
local hash = hash_blockpos(pos)
|
||||||
return mesecon.vm_get_node(pos)
|
|
||||||
else
|
if mesecon.forceloaded_blocks[hash] == nil then
|
||||||
local node = minetest.get_node_or_nil(pos)
|
-- if no more forceload spaces are available, try again next time
|
||||||
if node == nil then
|
if minetest.forceload_block(pos) then
|
||||||
-- Node is not currently loaded; use a VoxelManipulator to prime
|
mesecon.forceloaded_blocks[hash] = 0
|
||||||
-- the mapblock cache and try again.
|
|
||||||
minetest.get_voxel_manip(pos, pos)
|
|
||||||
node = minetest.get_node_or_nil(pos)
|
|
||||||
end
|
end
|
||||||
return node
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Swaps the node at a given position, regardless of whether it is loaded or
|
|
||||||
-- not, respecting a transaction if one is in progress.
|
|
||||||
--
|
|
||||||
-- Outside a VM transaction, if the mapblock is not loaded, it is pulled into
|
|
||||||
-- the server’s main map data cache and then accessed from there.
|
|
||||||
--
|
|
||||||
-- Inside a VM transaction, the transaction’s VM cache is used.
|
|
||||||
--
|
|
||||||
-- This function can only be used to change the node’s name, not its parameters
|
|
||||||
-- or metadata.
|
|
||||||
function mesecon.swap_node_force(pos, name)
|
|
||||||
if vm_cache then
|
|
||||||
return mesecon.vm_swap_node(pos, name)
|
|
||||||
else
|
else
|
||||||
-- This serves to both ensure the mapblock is loaded and also hand us
|
mesecon.forceloaded_blocks[hash] = 0
|
||||||
-- the old node table so we can preserve param2.
|
|
||||||
local node = mesecon.get_node_force(pos)
|
|
||||||
node.name = name
|
|
||||||
minetest.swap_node(pos, node)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return minetest.get_node_or_nil(pos)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Autoconnect Hooks
|
minetest.register_globalstep(function (dtime)
|
||||||
-- Nodes like conductors may change their appearance and their connection rules
|
for hash, time in pairs(mesecon.forceloaded_blocks) do
|
||||||
-- right after being placed or after being dug, e.g. the default wires use this
|
-- unload forceloaded blocks after 10 minutes without usage
|
||||||
-- to automatically connect to linking nodes after placement.
|
if (time > mesecon.setting("forceload_timeout", 600)) then
|
||||||
-- After placement, the update function will be executed immediately so that the
|
minetest.forceload_free_block(unhash_blockpos(hash))
|
||||||
-- possibly changed rules can be taken into account when recalculating the circuit.
|
mesecon.forceloaded_blocks[hash] = nil
|
||||||
-- After digging, the update function will be queued and executed after
|
else
|
||||||
-- recalculating the circuit. The update function must take care of updating the
|
mesecon.forceloaded_blocks[hash] = time + dtime
|
||||||
-- node at the given position itself, but also all of the other nodes the given
|
end
|
||||||
-- position may have (had) a linking connection to.
|
|
||||||
mesecon.autoconnect_hooks = {}
|
|
||||||
|
|
||||||
-- name: A unique name for the hook, e.g. "foowire". Used to name the actionqueue function.
|
|
||||||
-- fct: The update function with parameters function(pos, node)
|
|
||||||
function mesecon.register_autoconnect_hook(name, fct)
|
|
||||||
mesecon.autoconnect_hooks[name] = fct
|
|
||||||
mesecon.queue:add_function("autoconnect_hook_"..name, fct)
|
|
||||||
end
|
|
||||||
|
|
||||||
function mesecon.execute_autoconnect_hooks_now(pos, node)
|
|
||||||
for _, fct in pairs(mesecon.autoconnect_hooks) do
|
|
||||||
fct(pos, node)
|
|
||||||
end
|
end
|
||||||
end
|
end)
|
||||||
|
|
||||||
function mesecon.execute_autoconnect_hooks_queue(pos, node)
|
-- Store and read the forceloaded blocks to / from a file
|
||||||
for name in pairs(mesecon.autoconnect_hooks) do
|
-- so that those blocks are remembered when the game
|
||||||
mesecon.queue:add_action(pos, "autoconnect_hook_"..name, {node})
|
-- is restarted
|
||||||
end
|
mesecon.forceloaded_blocks = mesecon.file2table("mesecon_forceloaded")
|
||||||
end
|
minetest.register_on_shutdown(function()
|
||||||
|
mesecon.table2file("mesecon_forceloaded", mesecon.forceloaded_blocks)
|
||||||
|
end)
|
||||||
|
20
mesecons_wires/init.lua → mesecons/wires.lua
Normal file → Executable file
@ -91,7 +91,10 @@ local update_on_place_dig = function (pos, node)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
mesecon.register_autoconnect_hook("wire", update_on_place_dig)
|
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 ##
|
-- ## Wire node registration ##
|
||||||
@ -140,7 +143,7 @@ nid_inc = function (nid)
|
|||||||
return i <= 8
|
return i <= 8
|
||||||
end
|
end
|
||||||
|
|
||||||
local function register_wires()
|
register_wires = function()
|
||||||
local nid = {}
|
local nid = {}
|
||||||
while true do
|
while true do
|
||||||
-- Create group specifiction and nodeid string (see note above for details)
|
-- Create group specifiction and nodeid string (see note above for details)
|
||||||
@ -194,29 +197,26 @@ local function register_wires()
|
|||||||
offstate = "mesecons:wire_"..nodeid.."_off"
|
offstate = "mesecons:wire_"..nodeid.."_off"
|
||||||
}}
|
}}
|
||||||
|
|
||||||
local groups_on = {dig_immediate = 3, mesecon_conductor_craftable = 1,
|
local groups_on = {dig_immediate = 2, mesecon_conductor_craftable = 1,
|
||||||
not_in_creative_inventory = 1}
|
not_in_creative_inventory = 1} --MFF
|
||||||
local groups_off = {dig_immediate = 3, mesecon_conductor_craftable = 1}
|
local groups_off = {dig_immediate = 2, mesecon_conductor_craftable = 1} --MFF
|
||||||
if nodeid ~= "00000000" then
|
if nodeid ~= "00000000" then
|
||||||
groups_off["not_in_creative_inventory"] = 1
|
groups_off["not_in_creative_inventory"] = 1
|
||||||
end
|
end
|
||||||
|
|
||||||
mesecon.register_node(":mesecons:wire_"..nodeid, {
|
mesecon.register_node("mesecons:wire_"..nodeid, {
|
||||||
description = "Mesecon",
|
description = "Mesecon",
|
||||||
drawtype = "nodebox",
|
drawtype = "nodebox",
|
||||||
inventory_image = "mesecons_wire_inv.png",
|
inventory_image = "mesecons_wire_inv.png",
|
||||||
wield_image = "mesecons_wire_inv.png",
|
wield_image = "mesecons_wire_inv.png",
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
paramtype2 = "facedir",
|
paramtype2 = "facedir",
|
||||||
is_ground_content = false,
|
|
||||||
sunlight_propagates = true,
|
sunlight_propagates = true,
|
||||||
selection_box = selectionbox,
|
selection_box = selectionbox,
|
||||||
node_box = nodebox,
|
node_box = nodebox,
|
||||||
walkable = false,
|
walkable = false,
|
||||||
drop = "mesecons:wire_00000000_off",
|
drop = "mesecons:wire_00000000_off",
|
||||||
mesecon_wire = true,
|
mesecon_wire = true
|
||||||
sounds = default.node_sound_defaults(),
|
|
||||||
on_rotate = false,
|
|
||||||
}, {tiles = tiles_off, mesecons = meseconspec_off, groups = groups_off},
|
}, {tiles = tiles_off, mesecons = meseconspec_off, groups = groups_off},
|
||||||
{tiles = tiles_on, mesecons = meseconspec_on, groups = groups_on})
|
{tiles = tiles_on, mesecons = meseconspec_on, groups = groups_on})
|
||||||
|
|
1
mesecons_alias/depends.txt
Executable file
@ -0,0 +1 @@
|
|||||||
|
mesecons
|
0
mesecons_alias/init.lua
Normal file → Executable file
@ -1,2 +0,0 @@
|
|||||||
name = mesecons_alias
|
|
||||||
depends = mesecons
|
|
1
mesecons_blinkyplant/depends.txt
Executable file
@ -0,0 +1 @@
|
|||||||
|
mesecons
|
@ -1,2 +1 @@
|
|||||||
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.
|
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.
|
||||||
It stops blinking in an inactive block, then starts again when the block becomes active.
|
|
||||||
|
BIN
mesecons_blinkyplant/doc/blinkyplant/preview.png
Normal file → Executable file
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 2.9 KiB |
25
mesecons_blinkyplant/init.lua
Normal file → Executable file
@ -10,11 +10,25 @@ local toggle_timer = function (pos)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local on_timer = function (pos)
|
local on_timer = function (pos)
|
||||||
local node = minetest.get_node(pos)
|
-- DO NOT TOUCH OR.. THREATS! Thanks, MFF
|
||||||
if(mesecon.flipstate(pos, node) == "on") then
|
local activate = false
|
||||||
mesecon.receptor_on(pos)
|
for _, player in pairs(minetest.get_connected_players()) do
|
||||||
else
|
local p = player:getpos()
|
||||||
mesecon.receptor_off(pos)
|
local dist = ((p.x-pos.x)^2 + (p.y-pos.y)^2 + (p.z-pos.z)^2)^0.5
|
||||||
|
if dist < 40 then
|
||||||
|
activate = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if activate then
|
||||||
|
local node = minetest.get_node(pos)
|
||||||
|
if(mesecon.flipstate(pos, node) == "on") then
|
||||||
|
mesecon.receptor_on(pos)
|
||||||
|
else
|
||||||
|
mesecon.receptor_off(pos)
|
||||||
|
end
|
||||||
|
-- Our modification stops there, thank you, @crabman77
|
||||||
end
|
end
|
||||||
toggle_timer(pos)
|
toggle_timer(pos)
|
||||||
end
|
end
|
||||||
@ -24,7 +38,6 @@ mesecon.register_node("mesecons_blinkyplant:blinky_plant", {
|
|||||||
drawtype = "plantlike",
|
drawtype = "plantlike",
|
||||||
inventory_image = "jeija_blinky_plant_off.png",
|
inventory_image = "jeija_blinky_plant_off.png",
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
is_ground_content = false,
|
|
||||||
walkable = false,
|
walkable = false,
|
||||||
sounds = default.node_sound_leaves_defaults(),
|
sounds = default.node_sound_leaves_defaults(),
|
||||||
selection_box = {
|
selection_box = {
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
name = mesecons_blinkyplant
|
|
||||||
depends = mesecons
|
|
BIN
mesecons_blinkyplant/textures/jeija_blinky_plant_off.png
Normal file → Executable file
Before Width: | Height: | Size: 367 B After Width: | Height: | Size: 370 B |
BIN
mesecons_blinkyplant/textures/jeija_blinky_plant_on.png
Normal file → Executable file
Before Width: | Height: | Size: 394 B After Width: | Height: | Size: 395 B |
2
mesecons_button/depends.txt
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
mesecons
|
||||||
|
mesecons_receiver
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 78 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 7.8 KiB |
28
mesecons_button/init.lua
Normal file → Executable file
@ -4,13 +4,12 @@
|
|||||||
|
|
||||||
mesecon.button_turnoff = function (pos)
|
mesecon.button_turnoff = function (pos)
|
||||||
local node = minetest.get_node(pos)
|
local node = minetest.get_node(pos)
|
||||||
if node.name ~= "mesecons_button:button_on" then -- has been dug
|
if node.name=="mesecons_button:button_on" then --has not been dug
|
||||||
return
|
minetest.swap_node(pos, {name = "mesecons_button:button_off", param2=node.param2})
|
||||||
|
minetest.sound_play("mesecons_button_pop", {pos=pos})
|
||||||
|
local rules = mesecon.rules.buttonlike_get(node)
|
||||||
|
mesecon.receptor_off(pos, rules)
|
||||||
end
|
end
|
||||||
minetest.swap_node(pos, {name = "mesecons_button:button_off", param2 = node.param2})
|
|
||||||
minetest.sound_play("mesecons_button_pop", { pos = pos }, true)
|
|
||||||
local rules = mesecon.rules.buttonlike_get(node)
|
|
||||||
mesecon.receptor_off(pos, rules)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_node("mesecons_button:button_off", {
|
minetest.register_node("mesecons_button:button_off", {
|
||||||
@ -25,10 +24,8 @@ minetest.register_node("mesecons_button:button_off", {
|
|||||||
},
|
},
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
paramtype2 = "facedir",
|
paramtype2 = "facedir",
|
||||||
is_ground_content = false,
|
|
||||||
legacy_wallmounted = true,
|
legacy_wallmounted = true,
|
||||||
walkable = false,
|
walkable = false,
|
||||||
on_rotate = mesecon.buttonlike_onrotate,
|
|
||||||
sunlight_propagates = true,
|
sunlight_propagates = true,
|
||||||
selection_box = {
|
selection_box = {
|
||||||
type = "fixed",
|
type = "fixed",
|
||||||
@ -46,15 +43,14 @@ minetest.register_node("mesecons_button:button_off", {
|
|||||||
on_rightclick = function (pos, node)
|
on_rightclick = 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 }, true)
|
minetest.sound_play("mesecons_button_push", {pos=pos})
|
||||||
minetest.get_node_timer(pos):start(1)
|
minetest.after(1, mesecon.button_turnoff, pos)
|
||||||
end,
|
end,
|
||||||
sounds = default.node_sound_stone_defaults(),
|
sounds = default.node_sound_stone_defaults(),
|
||||||
mesecons = {receptor = {
|
mesecons = {receptor = {
|
||||||
state = mesecon.state.off,
|
state = mesecon.state.off,
|
||||||
rules = mesecon.rules.buttonlike_get
|
rules = mesecon.rules.buttonlike_get
|
||||||
}},
|
}}
|
||||||
on_blast = mesecon.on_blastnode,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_node("mesecons_button:button_on", {
|
minetest.register_node("mesecons_button:button_on", {
|
||||||
@ -69,11 +65,9 @@ minetest.register_node("mesecons_button:button_on", {
|
|||||||
},
|
},
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
paramtype2 = "facedir",
|
paramtype2 = "facedir",
|
||||||
is_ground_content = false,
|
|
||||||
legacy_wallmounted = true,
|
legacy_wallmounted = true,
|
||||||
walkable = false,
|
walkable = false,
|
||||||
on_rotate = false,
|
light_source = default.LIGHT_MAX-7,
|
||||||
light_source = minetest.LIGHT_MAX-7,
|
|
||||||
sunlight_propagates = true,
|
sunlight_propagates = true,
|
||||||
selection_box = {
|
selection_box = {
|
||||||
type = "fixed",
|
type = "fixed",
|
||||||
@ -93,9 +87,7 @@ minetest.register_node("mesecons_button:button_on", {
|
|||||||
mesecons = {receptor = {
|
mesecons = {receptor = {
|
||||||
state = mesecon.state.on,
|
state = mesecon.state.on,
|
||||||
rules = mesecon.rules.buttonlike_get
|
rules = mesecon.rules.buttonlike_get
|
||||||
}},
|
}}
|
||||||
on_timer = mesecon.button_turnoff,
|
|
||||||
on_blast = mesecon.on_blastnode,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_craft({
|
minetest.register_craft({
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
name = mesecons_button
|
|
||||||
depends = mesecons, mesecons_receiver
|
|
0
mesecons_button/sounds/mesecons_button_pop.ogg
Normal file → Executable file
0
mesecons_button/sounds/mesecons_button_push.ogg
Normal file → Executable file
BIN
mesecons_button/textures/jeija_wall_button_off.png
Normal file → Executable file
Before Width: | Height: | Size: 371 B After Width: | Height: | Size: 411 B |
BIN
mesecons_button/textures/jeija_wall_button_on.png
Normal file → Executable file
Before Width: | Height: | Size: 409 B After Width: | Height: | Size: 449 B |
BIN
mesecons_button/textures/jeija_wall_button_sides.png
Normal file → Executable file
Before Width: | Height: | Size: 220 B After Width: | Height: | Size: 220 B |
1
mesecons_commandblock/depends.txt
Executable file
@ -0,0 +1 @@
|
|||||||
|
mesecons
|
@ -1,2 +1 @@
|
|||||||
There is no crafting recipe as this should only be available for server admins. Quite similar to the Minecraft counterpart. Executes server commands.
|
There is no crafting recipe as this should only be available for server admins. Quite similar to the Minecraft counterpart. Executes server commands.
|
||||||
It works in inactive blocks.
|
|
||||||
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 36 KiB |
421
mesecons_commandblock/init.lua
Normal file → Executable file
@ -1,213 +1,208 @@
|
|||||||
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 = minetest.formspec_escape(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 not fields.submit 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 players = minetest.get_connected_players()
|
||||||
|
|
||||||
-- No players online: remove all commands containing
|
-- No players online: remove all commands containing
|
||||||
-- @nearest, @farthest and @random
|
-- @nearest, @farthest and @random
|
||||||
if #players == 0 then
|
if #players == 0 then
|
||||||
commands = commands:gsub("[^\r\n]+", function (line)
|
commands = commands:gsub("[^\r\n]+", function (line)
|
||||||
if line:find("@nearest") then return "" end
|
if line:find("@nearest") then return "" end
|
||||||
if line:find("@farthest") then return "" end
|
if line:find("@farthest") then return "" end
|
||||||
if line:find("@random") then return "" end
|
if line:find("@random") then return "" end
|
||||||
return line
|
return line
|
||||||
end)
|
end)
|
||||||
return commands
|
return commands
|
||||||
end
|
end
|
||||||
|
|
||||||
local nearest, farthest = nil, nil
|
local nearest, farthest = nil, nil
|
||||||
local min_distance, max_distance = math.huge, -1
|
local min_distance, max_distance = math.huge, -1
|
||||||
for index, player in pairs(players) do
|
for index, player in pairs(players) do
|
||||||
local distance = vector.distance(pos, player:get_pos())
|
local distance = vector.distance(pos, player:getpos())
|
||||||
if distance < min_distance then
|
if distance < min_distance then
|
||||||
min_distance = distance
|
min_distance = distance
|
||||||
nearest = player:get_player_name()
|
nearest = player:get_player_name()
|
||||||
end
|
end
|
||||||
if distance > max_distance then
|
if distance > max_distance then
|
||||||
max_distance = distance
|
max_distance = distance
|
||||||
farthest = player:get_player_name()
|
farthest = player:get_player_name()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local random = players[math.random(#players)]:get_player_name()
|
local random = players[math.random(#players)]:get_player_name()
|
||||||
commands = commands:gsub("@nearest", nearest)
|
commands = commands:gsub("@nearest", nearest)
|
||||||
commands = commands:gsub("@farthest", farthest)
|
commands = commands:gsub("@farthest", farthest)
|
||||||
commands = commands:gsub("@random", random)
|
commands = commands:gsub("@random", random)
|
||||||
return commands
|
return commands
|
||||||
end
|
end
|
||||||
|
|
||||||
local function commandblock_action_on(pos, node)
|
local function commandblock_action_on(pos, node)
|
||||||
if node.name ~= "mesecons_commandblock:commandblock_off" then
|
if node.name ~= "mesecons_commandblock:commandblock_off" then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.swap_node(pos, {name = "mesecons_commandblock:commandblock_on"})
|
minetest.swap_node(pos, {name = "mesecons_commandblock:commandblock_on"})
|
||||||
|
|
||||||
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 == "" then
|
if owner == "" then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local commands = resolve_commands(meta:get_string("commands"), pos)
|
local commands = resolve_commands(meta:get_string("commands"), pos)
|
||||||
for _, command in pairs(commands:split("\n")) do
|
for _, command in pairs(commands:split("\n")) do
|
||||||
local pos = command:find(" ")
|
local pos = command:find(" ")
|
||||||
local cmd, param = command, ""
|
local cmd, param = command, ""
|
||||||
if pos then
|
if pos then
|
||||||
cmd = command:sub(1, pos - 1)
|
cmd = command:sub(1, pos - 1)
|
||||||
param = command:sub(pos + 1)
|
param = command:sub(pos + 1)
|
||||||
end
|
end
|
||||||
local cmddef = minetest.chatcommands[cmd]
|
local cmddef = minetest.chatcommands[cmd]
|
||||||
if not cmddef then
|
if not cmddef then
|
||||||
minetest.chat_send_player(owner, "The command "..cmd.." does not exist")
|
minetest.chat_send_player(owner, "The command "..cmd.." does not exist")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local has_privs, missing_privs = minetest.check_player_privs(owner, cmddef.privs)
|
local has_privs, missing_privs = minetest.check_player_privs(owner, cmddef.privs)
|
||||||
if not has_privs then
|
if not has_privs then
|
||||||
minetest.chat_send_player(owner, "You don't have permission "
|
minetest.chat_send_player(owner, "You don't have permission "
|
||||||
.."to run "..cmd
|
.."to run "..cmd
|
||||||
.." (missing privileges: "
|
.." (missing privileges: "
|
||||||
..table.concat(missing_privs, ", ")..")")
|
..table.concat(missing_privs, ", ")..")")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
cmddef.func(owner, param)
|
cmddef.func(owner, param)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function commandblock_action_off(pos, node)
|
local function commandblock_action_off(pos, node)
|
||||||
if node.name == "mesecons_commandblock:commandblock_on" then
|
if node.name == "mesecons_commandblock:commandblock_on" then
|
||||||
minetest.swap_node(pos, {name = "mesecons_commandblock:commandblock_off"})
|
minetest.swap_node(pos, {name = "mesecons_commandblock:commandblock_off"})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function can_dig(pos, player)
|
local function can_dig(pos, player)
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
local owner = meta:get_string("owner")
|
local owner = meta:get_string("owner")
|
||||||
return owner == "" or owner == player:get_player_name() or
|
return owner == "" or owner == player:get_player_name()
|
||||||
minetest.check_player_privs(player, "protection_bypass")
|
end
|
||||||
end
|
|
||||||
|
minetest.register_node("mesecons_commandblock:commandblock_off", {
|
||||||
minetest.register_node("mesecons_commandblock:commandblock_off", {
|
description = "Command Block",
|
||||||
description = "Command Block",
|
tiles = {"jeija_commandblock_off.png"},
|
||||||
tiles = {"jeija_commandblock_off.png"},
|
inventory_image = minetest.inventorycube("jeija_commandblock_off.png"),
|
||||||
inventory_image = minetest.inventorycube("jeija_commandblock_off.png"),
|
groups = {cracky=2, mesecon_effector_off=1},
|
||||||
is_ground_content = false,
|
on_construct = construct,
|
||||||
groups = {cracky=2, mesecon_effector_off=1},
|
after_place_node = after_place,
|
||||||
on_construct = construct,
|
on_receive_fields = receive_fields,
|
||||||
after_place_node = after_place,
|
can_dig = can_dig,
|
||||||
on_receive_fields = receive_fields,
|
sounds = default.node_sound_stone_defaults(),
|
||||||
can_dig = can_dig,
|
mesecons = {effector = {
|
||||||
sounds = default.node_sound_stone_defaults(),
|
action_on = commandblock_action_on
|
||||||
mesecons = {effector = {
|
}}
|
||||||
action_on = commandblock_action_on
|
})
|
||||||
}},
|
|
||||||
on_blast = mesecon.on_blastnode,
|
minetest.register_node("mesecons_commandblock:commandblock_on", {
|
||||||
})
|
tiles = {"jeija_commandblock_on.png"},
|
||||||
|
groups = {cracky=2, mesecon_effector_on=1, not_in_creative_inventory=1},
|
||||||
minetest.register_node("mesecons_commandblock:commandblock_on", {
|
light_source = 10,
|
||||||
tiles = {"jeija_commandblock_on.png"},
|
drop = "mesecons_commandblock:commandblock_off",
|
||||||
is_ground_content = false,
|
on_construct = construct,
|
||||||
groups = {cracky=2, mesecon_effector_on=1, not_in_creative_inventory=1},
|
after_place_node = after_place,
|
||||||
light_source = 10,
|
on_receive_fields = receive_fields,
|
||||||
drop = "mesecons_commandblock:commandblock_off",
|
can_dig = can_dig,
|
||||||
on_construct = construct,
|
sounds = default.node_sound_stone_defaults(),
|
||||||
after_place_node = after_place,
|
mesecons = {effector = {
|
||||||
on_receive_fields = receive_fields,
|
action_off = commandblock_action_off
|
||||||
can_dig = can_dig,
|
}}
|
||||||
sounds = default.node_sound_stone_defaults(),
|
})
|
||||||
mesecons = {effector = {
|
|
||||||
action_off = commandblock_action_off
|
|
||||||
}},
|
|
||||||
on_blast = mesecon.on_blastnode,
|
|
||||||
})
|
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
name = mesecons_commandblock
|
|
||||||
depends = mesecons
|
|
BIN
mesecons_commandblock/textures/jeija_close_window.png
Executable file
After Width: | Height: | Size: 191 B |
BIN
mesecons_commandblock/textures/jeija_commandblock_off.png
Normal file → Executable file
Before Width: | Height: | Size: 183 B After Width: | Height: | Size: 183 B |
BIN
mesecons_commandblock/textures/jeija_commandblock_on.png
Normal file → Executable file
Before Width: | Height: | Size: 183 B After Width: | Height: | Size: 183 B |
1
mesecons_delayer/depends.txt
Executable file
@ -0,0 +1 @@
|
|||||||
|
mesecons
|
@ -1 +1 @@
|
|||||||
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. It works in unloaded blocks.
|
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.
|
||||||
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 8.3 KiB |
136
mesecons_delayer/init.lua
Normal file → Executable file
@ -33,12 +33,21 @@ end
|
|||||||
|
|
||||||
-- Register the 2 (states) x 4 (delay times) delayers
|
-- Register the 2 (states) x 4 (delay times) delayers
|
||||||
|
|
||||||
local delaytime = { 0.1, 0.3, 0.5, 1.0 }
|
|
||||||
|
|
||||||
for i = 1, 4 do
|
for i = 1, 4 do
|
||||||
|
local groups = {}
|
||||||
|
if i == 1 then
|
||||||
|
groups = {bendy=2,snappy=1,dig_immediate=2}
|
||||||
|
else
|
||||||
|
groups = {bendy=2,snappy=1,dig_immediate=2, not_in_creative_inventory=1}
|
||||||
|
end
|
||||||
|
|
||||||
local boxes = {
|
local delaytime
|
||||||
{ -6/16, -8/16, -6/16, 6/16, -7/16, 6/16 }, -- the main slab
|
if i == 1 then delaytime = 0.1
|
||||||
|
elseif i == 2 then delaytime = 0.3
|
||||||
|
elseif i == 3 then delaytime = 0.5
|
||||||
|
elseif i == 4 then delaytime = 1.0 end
|
||||||
|
|
||||||
|
boxes = {{ -6/16, -8/16, -6/16, 6/16, -7/16, 6/16 }, -- the main slab
|
||||||
|
|
||||||
{ -2/16, -7/16, -4/16, 2/16, -26/64, -3/16 }, -- the jeweled "on" indicator
|
{ -2/16, -7/16, -4/16, 2/16, -26/64, -3/16 }, -- the jeweled "on" indicator
|
||||||
{ -3/16, -7/16, -3/16, 3/16, -26/64, -2/16 },
|
{ -3/16, -7/16, -3/16, 3/16, -26/64, -2/16 },
|
||||||
@ -48,12 +57,21 @@ local boxes = {
|
|||||||
|
|
||||||
{ -6/16, -7/16, -6/16, -4/16, -27/64, -4/16 }, -- the timer indicator
|
{ -6/16, -7/16, -6/16, -4/16, -27/64, -4/16 }, -- the timer indicator
|
||||||
{ -8/16, -8/16, -1/16, -6/16, -7/16, 1/16 }, -- the two wire stubs
|
{ -8/16, -8/16, -1/16, -6/16, -7/16, 1/16 }, -- the two wire stubs
|
||||||
{ 6/16, -8/16, -1/16, 8/16, -7/16, 1/16 }
|
{ 6/16, -8/16, -1/16, 8/16, -7/16, 1/16 }}
|
||||||
}
|
|
||||||
|
|
||||||
-- Delayer definition defaults
|
minetest.register_node("mesecons_delayer:delayer_off_"..tostring(i), {
|
||||||
local def = {
|
description = "Delayer",
|
||||||
drawtype = "nodebox",
|
drawtype = "nodebox",
|
||||||
|
tiles = {
|
||||||
|
"mesecons_delayer_off_"..tostring(i)..".png",
|
||||||
|
"mesecons_delayer_bottom.png",
|
||||||
|
"mesecons_delayer_ends_off.png",
|
||||||
|
"mesecons_delayer_ends_off.png",
|
||||||
|
"mesecons_delayer_sides_off.png",
|
||||||
|
"mesecons_delayer_sides_off.png"
|
||||||
|
},
|
||||||
|
inventory_image = "mesecons_delayer_off_1.png",
|
||||||
|
wield_image = "mesecons_delayer_off_1.png",
|
||||||
walkable = true,
|
walkable = true,
|
||||||
selection_box = {
|
selection_box = {
|
||||||
type = "fixed",
|
type = "fixed",
|
||||||
@ -63,46 +81,26 @@ local def = {
|
|||||||
type = "fixed",
|
type = "fixed",
|
||||||
fixed = boxes
|
fixed = boxes
|
||||||
},
|
},
|
||||||
|
groups = groups,
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
paramtype2 = "facedir",
|
paramtype2 = "facedir",
|
||||||
sunlight_propagates = true,
|
sunlight_propagates = true,
|
||||||
is_ground_content = false,
|
is_ground_content = true,
|
||||||
delayer_time = delaytime[i],
|
drop = 'mesecons_delayer:delayer_off_1',
|
||||||
sounds = default.node_sound_stone_defaults(),
|
on_punch = function (pos, node)
|
||||||
on_blast = mesecon.on_blastnode,
|
if node.name=="mesecons_delayer:delayer_off_1" then
|
||||||
drop = "mesecons_delayer:delayer_off_1",
|
minetest.swap_node(pos, {name = "mesecons_delayer:delayer_off_2", param2=node.param2})
|
||||||
}
|
elseif node.name=="mesecons_delayer:delayer_off_2" then
|
||||||
|
minetest.swap_node(pos, {name = "mesecons_delayer:delayer_off_3", param2=node.param2})
|
||||||
-- Deactivated delayer definition defaults
|
elseif node.name=="mesecons_delayer:delayer_off_3" then
|
||||||
local off_groups = {bendy=2,snappy=1,dig_immediate=2}
|
minetest.swap_node(pos, {name = "mesecons_delayer:delayer_off_4", param2=node.param2})
|
||||||
if i > 1 then
|
elseif node.name=="mesecons_delayer:delayer_off_4" then
|
||||||
off_groups.not_in_creative_inventory = 1
|
minetest.swap_node(pos, {name = "mesecons_delayer:delayer_off_1", param2=node.param2})
|
||||||
end
|
|
||||||
|
|
||||||
local off_state = {
|
|
||||||
description = "Delayer",
|
|
||||||
tiles = {
|
|
||||||
"mesecons_delayer_off_"..tostring(i)..".png",
|
|
||||||
"mesecons_delayer_bottom.png",
|
|
||||||
"mesecons_delayer_ends_off.png",
|
|
||||||
"mesecons_delayer_ends_off.png",
|
|
||||||
"mesecons_delayer_sides_off.png",
|
|
||||||
"mesecons_delayer_sides_off.png"
|
|
||||||
},
|
|
||||||
inventory_image = "mesecons_delayer_off_1.png",
|
|
||||||
wield_image = "mesecons_delayer_off_1.png",
|
|
||||||
groups = off_groups,
|
|
||||||
on_punch = function(pos, node, puncher)
|
|
||||||
if minetest.is_protected(pos, puncher and puncher:get_player_name()) then
|
|
||||||
return
|
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.swap_node(pos, {
|
|
||||||
name = "mesecons_delayer:delayer_off_"..tostring(i % 4 + 1),
|
|
||||||
param2 = node.param2
|
|
||||||
})
|
|
||||||
end,
|
end,
|
||||||
|
delayer_time = delaytime,
|
||||||
delayer_onstate = "mesecons_delayer:delayer_on_"..tostring(i),
|
delayer_onstate = "mesecons_delayer:delayer_on_"..tostring(i),
|
||||||
|
sounds = default.node_sound_stone_defaults(),
|
||||||
mesecons = {
|
mesecons = {
|
||||||
receptor =
|
receptor =
|
||||||
{
|
{
|
||||||
@ -114,16 +112,13 @@ local off_state = {
|
|||||||
rules = delayer_get_input_rules,
|
rules = delayer_get_input_rules,
|
||||||
action_on = delayer_activate
|
action_on = delayer_activate
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
}
|
})
|
||||||
for k, v in pairs(def) do
|
|
||||||
off_state[k] = off_state[k] or v
|
|
||||||
end
|
|
||||||
minetest.register_node("mesecons_delayer:delayer_off_"..tostring(i), off_state)
|
|
||||||
|
|
||||||
-- Activated delayer definition defaults
|
|
||||||
local on_state = {
|
minetest.register_node("mesecons_delayer:delayer_on_"..tostring(i), {
|
||||||
description = "You hacker you",
|
description = "You hacker you",
|
||||||
|
drawtype = "nodebox",
|
||||||
tiles = {
|
tiles = {
|
||||||
"mesecons_delayer_on_"..tostring(i)..".png",
|
"mesecons_delayer_on_"..tostring(i)..".png",
|
||||||
"mesecons_delayer_bottom.png",
|
"mesecons_delayer_bottom.png",
|
||||||
@ -131,18 +126,34 @@ local on_state = {
|
|||||||
"mesecons_delayer_ends_on.png",
|
"mesecons_delayer_ends_on.png",
|
||||||
"mesecons_delayer_sides_on.png",
|
"mesecons_delayer_sides_on.png",
|
||||||
"mesecons_delayer_sides_on.png"
|
"mesecons_delayer_sides_on.png"
|
||||||
|
},
|
||||||
|
walkable = true,
|
||||||
|
selection_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 },
|
||||||
|
},
|
||||||
|
node_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = boxes
|
||||||
},
|
},
|
||||||
groups = {bendy = 2, snappy = 1, dig_immediate = 2, not_in_creative_inventory = 1},
|
groups = {bendy = 2, snappy = 1, dig_immediate = 2, not_in_creative_inventory = 1},
|
||||||
on_punch = function(pos, node, puncher)
|
paramtype = "light",
|
||||||
if minetest.is_protected(pos, puncher and puncher:get_player_name()) then
|
paramtype2 = "facedir",
|
||||||
return
|
sunlight_propagates = true,
|
||||||
|
is_ground_content = true,
|
||||||
|
drop = 'mesecons_delayer:delayer_off_1',
|
||||||
|
on_punch = function (pos, node)
|
||||||
|
if node.name=="mesecons_delayer:delayer_on_1" then
|
||||||
|
minetest.swap_node(pos, {name = "mesecons_delayer:delayer_on_2", param2=node.param2})
|
||||||
|
elseif node.name=="mesecons_delayer:delayer_on_2" then
|
||||||
|
minetest.swap_node(pos, {name = "mesecons_delayer:delayer_on_3", param2=node.param2})
|
||||||
|
elseif node.name=="mesecons_delayer:delayer_on_3" then
|
||||||
|
minetest.swap_node(pos, {name = "mesecons_delayer:delayer_on_4", param2=node.param2})
|
||||||
|
elseif node.name=="mesecons_delayer:delayer_on_4" then
|
||||||
|
minetest.swap_node(pos, {name = "mesecons_delayer:delayer_on_1", param2=node.param2})
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.swap_node(pos, {
|
|
||||||
name = "mesecons_delayer:delayer_on_"..tostring(i % 4 + 1),
|
|
||||||
param2 = node.param2
|
|
||||||
})
|
|
||||||
end,
|
end,
|
||||||
|
delayer_time = delaytime,
|
||||||
delayer_offstate = "mesecons_delayer:delayer_off_"..tostring(i),
|
delayer_offstate = "mesecons_delayer:delayer_off_"..tostring(i),
|
||||||
mesecons = {
|
mesecons = {
|
||||||
receptor =
|
receptor =
|
||||||
@ -155,13 +166,8 @@ local on_state = {
|
|||||||
rules = delayer_get_input_rules,
|
rules = delayer_get_input_rules,
|
||||||
action_off = delayer_deactivate
|
action_off = delayer_deactivate
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
}
|
})
|
||||||
for k, v in pairs(def) do
|
|
||||||
on_state[k] = on_state[k] or v
|
|
||||||
end
|
|
||||||
minetest.register_node("mesecons_delayer:delayer_on_"..tostring(i), on_state)
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_craft({
|
minetest.register_craft({
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
name = mesecons_delayer
|
|
||||||
depends = mesecons
|
|
BIN
mesecons_delayer/textures/mesecons_delayer_bottom.png
Normal file → Executable file
Before Width: | Height: | Size: 221 B After Width: | Height: | Size: 261 B |
BIN
mesecons_delayer/textures/mesecons_delayer_ends_off.png
Normal file → Executable file
Before Width: | Height: | Size: 176 B After Width: | Height: | Size: 204 B |
BIN
mesecons_delayer/textures/mesecons_delayer_ends_on.png
Normal file → Executable file
Before Width: | Height: | Size: 187 B After Width: | Height: | Size: 204 B |
0
mesecons_delayer/textures/mesecons_delayer_off_1.png
Normal file → Executable file
Before Width: | Height: | Size: 448 B After Width: | Height: | Size: 448 B |
0
mesecons_delayer/textures/mesecons_delayer_off_2.png
Normal file → Executable file
Before Width: | Height: | Size: 449 B After Width: | Height: | Size: 449 B |
0
mesecons_delayer/textures/mesecons_delayer_off_3.png
Normal file → Executable file
Before Width: | Height: | Size: 448 B After Width: | Height: | Size: 448 B |
0
mesecons_delayer/textures/mesecons_delayer_off_4.png
Normal file → Executable file
Before Width: | Height: | Size: 446 B After Width: | Height: | Size: 446 B |
BIN
mesecons_delayer/textures/mesecons_delayer_on_1.png
Normal file → Executable file
Before Width: | Height: | Size: 541 B After Width: | Height: | Size: 544 B |
BIN
mesecons_delayer/textures/mesecons_delayer_on_2.png
Normal file → Executable file
Before Width: | Height: | Size: 541 B After Width: | Height: | Size: 544 B |
BIN
mesecons_delayer/textures/mesecons_delayer_on_3.png
Normal file → Executable file
Before Width: | Height: | Size: 541 B After Width: | Height: | Size: 544 B |
BIN
mesecons_delayer/textures/mesecons_delayer_on_4.png
Normal file → Executable file
Before Width: | Height: | Size: 538 B After Width: | Height: | Size: 539 B |
BIN
mesecons_delayer/textures/mesecons_delayer_sides_off.png
Normal file → Executable file
Before Width: | Height: | Size: 173 B After Width: | Height: | Size: 204 B |
BIN
mesecons_delayer/textures/mesecons_delayer_sides_on.png
Normal file → Executable file
Before Width: | Height: | Size: 181 B After Width: | Height: | Size: 204 B |
2
mesecons_detector/depends.txt
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
mesecons
|
||||||
|
mesecons_materials
|
@ -1,11 +1,6 @@
|
|||||||
The node detector is a receptor. It changes its state when either any node
|
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.
|
or a specific node is detected. Right-click it to set a nodename to scan for.
|
||||||
It can also receive digiline signals. For example, you can send
|
It can also receive digiline signals. You can either send "GET" and it will
|
||||||
<code>{distance=4, scanname="default:dirt"}</code>
|
respond with the detected nodename or you can send any other string and it will
|
||||||
to set distance to 4 and scan for dirt. You can omit either parameter.
|
set this string as the node to scan for.
|
||||||
There is also a command parameter: <code>{command="get"}</code> will respond
|
|
||||||
with the detected nodename and <code>{command="scan"}</code> will respond with
|
|
||||||
a boolean using the distance and nodename of the detector.
|
|
||||||
Nodenames must include the mod they reside in, so for instance default:dirt, not just dirt.
|
Nodenames must include the mod they reside in, so for instance default:dirt, not just dirt.
|
||||||
The distance parameter specifies how many blocks are between the node detector and the node to detect.
|
|
||||||
Automatic scanning with Mesecons output only works when the detector is in an active block, but Digilines queries always work.
|
|
||||||
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 9.8 KiB |
@ -1,5 +1,3 @@
|
|||||||
The object detector is a receptor. It changes its state when a player approaches.
|
The object detector is a receptor. It changes its state when a player approaches.
|
||||||
Right-click it to set a name to scan for.
|
Right-click it to set a name to scan for.
|
||||||
You can also search for comma-separated lists of players where the detector gets activated if any of the names in the list are found.
|
|
||||||
It can also receive digiline signals which are the name to scan for on the specified channel in the right-click menu.
|
It can also receive digiline signals which are the name to scan for on the specified channel in the right-click menu.
|
||||||
Automatic scanning with Mesecons output only works when the detector is in an active block, but Digilines queries always work.
|
|
||||||
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 9.6 KiB |
156
mesecons_detector/init.lua
Normal file → Executable file
@ -4,19 +4,18 @@ local GET_COMMAND = "GET"
|
|||||||
-- 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)
|
-- The following file was modified to detect multiple players
|
||||||
|
local object_detector_make_formspec = function (pos)
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
meta:set_string("formspec", "size[9,2.5]" ..
|
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;12,2;scanname;Name of player(s) to scan for (empty for any, separate with comma):;${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, formname, fields, sender)
|
local function object_detector_on_receive_fields(pos, _, 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
|
||||||
|
|
||||||
if minetest.is_protected(pos, sender:get_player_name()) 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)
|
||||||
meta:set_string("digiline_channel", fields.digiline_channel)
|
meta:set_string("digiline_channel", fields.digiline_channel)
|
||||||
@ -26,37 +25,36 @@ 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 function object_detector_scan(pos)
|
||||||
local objs = minetest.get_objects_inside_radius(pos, mesecon.setting("detector_radius", 6))
|
local objs = minetest.get_objects_inside_radius(pos, mesecon.setting("detector_radius", 6))
|
||||||
|
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"):gsub(' ', "")
|
||||||
|
if (scanname == "" and isname ~= "") then
|
||||||
local scanname = minetest.get_meta(pos):get_string("scanname")
|
minetest.get_meta(pos):set_string("scanedname", "")
|
||||||
local scan_for = {}
|
return true
|
||||||
for _, str in pairs(string.split(scanname:gsub(" ", ""), ",")) do
|
end
|
||||||
scan_for[str] = true
|
local founds = {}
|
||||||
end
|
for _, name in pairs(scanname:split(',')) do
|
||||||
|
if (isname == name and isname ~= "") then
|
||||||
local every_player = scanname == ""
|
table.insert(founds, isname)
|
||||||
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
|
|
||||||
if every_player or scan_for[foundname] then
|
|
||||||
return true
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if #founds > 0 then
|
||||||
|
minetest.get_meta(pos):set_string("scannedname", table.concat(founds, ','))
|
||||||
|
return true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
minetest.get_meta(pos):set_string("scanedname", "")
|
||||||
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 = {
|
local 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")
|
||||||
meta:set_string("scanname", msg)
|
if channel == active_channel then
|
||||||
|
meta:set_string("scanedname", msg)
|
||||||
object_detector_make_formspec(pos)
|
object_detector_make_formspec(pos)
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
@ -66,7 +64,6 @@ local object_detector_digiline = {
|
|||||||
minetest.register_node("mesecons_detector:object_detector_off", {
|
minetest.register_node("mesecons_detector:object_detector_off", {
|
||||||
tiles = {"default_steel_block.png", "default_steel_block.png", "jeija_object_detector_off.png", "jeija_object_detector_off.png", "jeija_object_detector_off.png", "jeija_object_detector_off.png"},
|
tiles = {"default_steel_block.png", "default_steel_block.png", "jeija_object_detector_off.png", "jeija_object_detector_off.png", "jeija_object_detector_off.png", "jeija_object_detector_off.png"},
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
is_ground_content = false,
|
|
||||||
walkable = true,
|
walkable = true,
|
||||||
groups = {cracky=3},
|
groups = {cracky=3},
|
||||||
description="Player Detector",
|
description="Player Detector",
|
||||||
@ -77,14 +74,12 @@ minetest.register_node("mesecons_detector:object_detector_off", {
|
|||||||
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,
|
||||||
sounds = default.node_sound_stone_defaults(),
|
sounds = default.node_sound_stone_defaults(),
|
||||||
digiline = object_detector_digiline,
|
digiline = object_detector_digiline
|
||||||
on_blast = mesecon.on_blastnode,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_node("mesecons_detector:object_detector_on", {
|
minetest.register_node("mesecons_detector:object_detector_on", {
|
||||||
tiles = {"default_steel_block.png", "default_steel_block.png", "jeija_object_detector_on.png", "jeija_object_detector_on.png", "jeija_object_detector_on.png", "jeija_object_detector_on.png"},
|
tiles = {"default_steel_block.png", "default_steel_block.png", "jeija_object_detector_on.png", "jeija_object_detector_on.png", "jeija_object_detector_on.png", "jeija_object_detector_on.png"},
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
is_ground_content = false,
|
|
||||||
walkable = true,
|
walkable = true,
|
||||||
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',
|
||||||
@ -95,8 +90,7 @@ minetest.register_node("mesecons_detector:object_detector_on", {
|
|||||||
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,
|
||||||
sounds = default.node_sound_stone_defaults(),
|
sounds = default.node_sound_stone_defaults(),
|
||||||
digiline = object_detector_digiline,
|
digiline = object_detector_digiline
|
||||||
on_blast = mesecon.on_blastnode,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_craft({
|
minetest.register_craft({
|
||||||
@ -108,15 +102,6 @@ minetest.register_craft({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_craft({
|
|
||||||
output = 'mesecons_detector:object_detector_off',
|
|
||||||
recipe = {
|
|
||||||
{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
|
|
||||||
{"default:steel_ingot", "mesecons_microcontroller:microcontroller0000", "default:steel_ingot"},
|
|
||||||
{"default:steel_ingot", "group:mesecon_conductor_craftable", "default:steel_ingot"},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
minetest.register_abm({
|
minetest.register_abm({
|
||||||
nodenames = {"mesecons_detector:object_detector_off"},
|
nodenames = {"mesecons_detector:object_detector_off"},
|
||||||
interval = 1,
|
interval = 1,
|
||||||
@ -147,23 +132,17 @@ minetest.register_abm({
|
|||||||
-- Detects the node in front of it
|
-- Detects the node in front of it
|
||||||
|
|
||||||
local function node_detector_make_formspec(pos)
|
local function node_detector_make_formspec(pos)
|
||||||
local meta = minetest.get_meta(pos)
|
minetest.get_meta(pos):set_string("formspec", "size[9,2.5]" ..
|
||||||
if meta:get_string("distance") == "" then meta:set_string("distance", "0") end
|
|
||||||
meta: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, 0;9,2;scanname;Name of node to scan for (empty for any):;${scanname}]"..
|
||||||
"field[0.3,1.5;2.5,2;distance;Distance (0-"..mesecon.setting("node_detector_distance_max", 10).."):;${distance}]"..
|
"field[0.3,1.5;4,2;digiline_channel;Digiline Channel (optional):;${digiline_channel}]"..
|
||||||
"field[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 node_detector_on_receive_fields(pos, fieldname, fields, sender)
|
local function node_detector_on_receive_fields(pos, _, 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
|
||||||
|
|
||||||
if minetest.is_protected(pos, sender:get_player_name()) 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)
|
||||||
meta:set_string("distance", fields.distance or "0")
|
|
||||||
meta:set_string("digiline_channel", fields.digiline_channel)
|
meta:set_string("digiline_channel", fields.digiline_channel)
|
||||||
node_detector_make_formspec(pos)
|
node_detector_make_formspec(pos)
|
||||||
end
|
end
|
||||||
@ -173,65 +152,31 @@ local function node_detector_scan(pos)
|
|||||||
local node = minetest.get_node_or_nil(pos)
|
local node = minetest.get_node_or_nil(pos)
|
||||||
if not node then return end
|
if not node then return end
|
||||||
|
|
||||||
local meta = minetest.get_meta(pos)
|
|
||||||
|
|
||||||
local distance = meta:get_int("distance")
|
|
||||||
local distance_max = mesecon.setting("node_detector_distance_max", 10)
|
|
||||||
if distance < 0 then distance = 0 end
|
|
||||||
if distance > distance_max then distance = distance_max end
|
|
||||||
|
|
||||||
local frontname = minetest.get_node(
|
local frontname = minetest.get_node(
|
||||||
vector.subtract(pos, vector.multiply(minetest.facedir_to_dir(node.param2), distance + 1))
|
vector.subtract(pos, minetest.facedir_to_dir(node.param2))
|
||||||
).name
|
).name
|
||||||
local scanname = meta:get_string("scanname")
|
local scanname = minetest.get_meta(pos):get_string("scanname")
|
||||||
|
|
||||||
return (frontname == scanname) or
|
return (frontname == scanname) or
|
||||||
(frontname ~= "air" and frontname ~= "ignore" and scanname == "")
|
(frontname ~= "air" and frontname ~= "ignore" and scanname == "")
|
||||||
end
|
end
|
||||||
|
|
||||||
local function node_detector_send_node_name(pos, node, channel, meta)
|
|
||||||
local distance = meta:get_int("distance")
|
|
||||||
local distance_max = mesecon.setting("node_detector_distance_max", 10)
|
|
||||||
if distance < 0 then distance = 0 end
|
|
||||||
if distance > distance_max then distance = distance_max end
|
|
||||||
local nodename = minetest.get_node(
|
|
||||||
vector.subtract(pos, vector.multiply(minetest.facedir_to_dir(node.param2), distance + 1))
|
|
||||||
).name
|
|
||||||
|
|
||||||
digiline:receptor_send(pos, digiline.rules.default, channel, nodename)
|
|
||||||
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 node_detector_digiline = {
|
local node_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 return end
|
if channel ~= meta:get_string("digiline_channel") then return end
|
||||||
|
|
||||||
if type(msg) == "table" then
|
if msg == GET_COMMAND then
|
||||||
if msg.distance or msg.scanname then
|
local nodename = minetest.get_node(
|
||||||
if msg.distance then
|
vector.subtract(pos, minetest.facedir_to_dir(node.param2))
|
||||||
meta:set_string("distance", msg.distance)
|
).name
|
||||||
end
|
|
||||||
if msg.scanname then
|
digiline:receptor_send(pos, digiline.rules.default, channel, nodename)
|
||||||
meta:set_string("scanname", msg.scanname)
|
|
||||||
end
|
|
||||||
node_detector_make_formspec(pos)
|
|
||||||
end
|
|
||||||
if msg.command == "get" then
|
|
||||||
node_detector_send_node_name(pos, node, channel, meta)
|
|
||||||
elseif msg.command == "scan" then
|
|
||||||
local result = node_detector_scan(pos)
|
|
||||||
digiline:receptor_send(pos, digiline.rules.default, channel, result)
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
if msg == GET_COMMAND then
|
meta:set_string("scanname", msg)
|
||||||
node_detector_send_node_name(pos, node, channel, meta)
|
node_detector_make_formspec(pos)
|
||||||
else
|
|
||||||
meta:set_string("scanname", msg)
|
|
||||||
node_detector_make_formspec(pos)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
@ -239,7 +184,7 @@ local node_detector_digiline = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
local function after_place_node_detector(pos, placer)
|
local function after_place_node_detector(pos, placer)
|
||||||
local placer_pos = placer:get_pos()
|
local placer_pos = placer:getpos()
|
||||||
if not placer_pos then
|
if not placer_pos then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@ -259,7 +204,6 @@ 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"},
|
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",
|
paramtype = "light",
|
||||||
paramtype2 = "facedir",
|
paramtype2 = "facedir",
|
||||||
is_ground_content = false,
|
|
||||||
walkable = true,
|
walkable = true,
|
||||||
groups = {cracky=3},
|
groups = {cracky=3},
|
||||||
description="Node Detector",
|
description="Node Detector",
|
||||||
@ -268,16 +212,15 @@ minetest.register_node("mesecons_detector:node_detector_off", {
|
|||||||
}},
|
}},
|
||||||
on_construct = node_detector_make_formspec,
|
on_construct = node_detector_make_formspec,
|
||||||
on_receive_fields = node_detector_on_receive_fields,
|
on_receive_fields = node_detector_on_receive_fields,
|
||||||
|
after_place_node = after_place_node_detector,
|
||||||
sounds = default.node_sound_stone_defaults(),
|
sounds = default.node_sound_stone_defaults(),
|
||||||
digiline = node_detector_digiline,
|
digiline = node_detector_digiline
|
||||||
on_blast = mesecon.on_blastnode,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_node("mesecons_detector:node_detector_on", {
|
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"},
|
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",
|
paramtype = "light",
|
||||||
paramtype2 = "facedir",
|
paramtype2 = "facedir",
|
||||||
is_ground_content = false,
|
|
||||||
walkable = true,
|
walkable = true,
|
||||||
groups = {cracky=3,not_in_creative_inventory=1},
|
groups = {cracky=3,not_in_creative_inventory=1},
|
||||||
drop = 'mesecons_detector:node_detector_off',
|
drop = 'mesecons_detector:node_detector_off',
|
||||||
@ -286,9 +229,9 @@ minetest.register_node("mesecons_detector:node_detector_on", {
|
|||||||
}},
|
}},
|
||||||
on_construct = node_detector_make_formspec,
|
on_construct = node_detector_make_formspec,
|
||||||
on_receive_fields = node_detector_on_receive_fields,
|
on_receive_fields = node_detector_on_receive_fields,
|
||||||
|
after_place_node = after_place_node_detector,
|
||||||
sounds = default.node_sound_stone_defaults(),
|
sounds = default.node_sound_stone_defaults(),
|
||||||
digiline = node_detector_digiline,
|
digiline = node_detector_digiline
|
||||||
on_blast = mesecon.on_blastnode,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_craft({
|
minetest.register_craft({
|
||||||
@ -300,15 +243,6 @@ minetest.register_craft({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_craft({
|
|
||||||
output = 'mesecons_detector:node_detector_off',
|
|
||||||
recipe = {
|
|
||||||
{"default:steel_ingot", "group:mesecon_conductor_craftable", "default:steel_ingot"},
|
|
||||||
{"default:steel_ingot", "mesecons_microcontroller:microcontroller0000", "default:steel_ingot"},
|
|
||||||
{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
minetest.register_abm({
|
minetest.register_abm({
|
||||||
nodenames = {"mesecons_detector:node_detector_off"},
|
nodenames = {"mesecons_detector:node_detector_off"},
|
||||||
interval = 1,
|
interval = 1,
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
name = mesecons_detector
|
|
||||||
depends = mesecons, mesecons_materials
|
|
BIN
mesecons_detector/textures/jeija_node_detector_off.png
Normal file → Executable file
Before Width: | Height: | Size: 640 B After Width: | Height: | Size: 680 B |
BIN
mesecons_detector/textures/jeija_node_detector_on.png
Normal file → Executable file
Before Width: | Height: | Size: 687 B After Width: | Height: | Size: 727 B |
BIN
mesecons_detector/textures/jeija_object_detector_off.png
Normal file → Executable file
Before Width: | Height: | Size: 655 B After Width: | Height: | Size: 655 B |
BIN
mesecons_detector/textures/jeija_object_detector_on.png
Normal file → Executable file
Before Width: | Height: | Size: 693 B After Width: | Height: | Size: 733 B |
2
mesecons_doors/depends.txt
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
mesecons
|
||||||
|
doors
|
28
mesecons_doors/init.lua
Normal file → Executable file
@ -13,9 +13,9 @@ local function on_rightclick(pos, dir, check_name, replace, replace_dir, params)
|
|||||||
minetest.swap_node(pos, {name = replace, param2 = p2})
|
minetest.swap_node(pos, {name = replace, param2 = p2})
|
||||||
|
|
||||||
if (minetest.get_meta(pos):get_int("right") ~= 0) == (params[1] ~= 3) then
|
if (minetest.get_meta(pos):get_int("right") ~= 0) == (params[1] ~= 3) then
|
||||||
minetest.sound_play("doors_door_close", { pos = pos, gain = 0.3, max_hear_distance = 10 }, true)
|
minetest.sound_play("doors_door_close", {pos = pos, gain = 0.3, max_hear_distance = 10})
|
||||||
else
|
else
|
||||||
minetest.sound_play("doors_door_open", { pos = pos, gain = 0.3, max_hear_distance = 10 }, true)
|
minetest.sound_play("doors_door_open", {pos = pos, gain = 0.3, max_hear_distance = 10})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -73,17 +73,29 @@ meseconify_door("doors:door_wood")
|
|||||||
meseconify_door("doors:door_steel")
|
meseconify_door("doors:door_steel")
|
||||||
meseconify_door("doors:door_glass")
|
meseconify_door("doors:door_glass")
|
||||||
meseconify_door("doors:door_obsidian_glass")
|
meseconify_door("doors:door_obsidian_glass")
|
||||||
meseconify_door("xpanes:door_steel_bar")
|
|
||||||
|
--MFF meseconify all doors, crabman 12/06/2016
|
||||||
|
meseconify_door("doors:door_cherry")
|
||||||
|
meseconify_door("doors:door_tin")
|
||||||
|
meseconify_door("doors:door_prison")
|
||||||
|
meseconify_door("doors:door_gardengate_white")
|
||||||
|
meseconify_door("doors:door3_wood")
|
||||||
|
meseconify_door("doors:door3_steel")
|
||||||
|
meseconify_door("doors:door3_glass")
|
||||||
|
meseconify_door("doors:door3_obsidian_glass")
|
||||||
|
meseconify_door("doors:door3_cherry")
|
||||||
|
meseconify_door("doors:door3_prison")
|
||||||
|
|
||||||
|
|
||||||
-- Trapdoor
|
-- Trapdoor
|
||||||
local function trapdoor_switch(pos, node)
|
local function trapdoor_switch(pos, node)
|
||||||
local state = minetest.get_meta(pos):get_int("state")
|
local state = minetest.get_meta(pos):get_int("state")
|
||||||
|
|
||||||
if state == 1 then
|
if state == 1 then
|
||||||
minetest.sound_play("doors_door_close", { pos = pos, gain = 0.3, max_hear_distance = 10 }, true)
|
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})
|
minetest.set_node(pos, {name="doors:trapdoor", param2 = node.param2})
|
||||||
else
|
else
|
||||||
minetest.sound_play("doors_door_open", { pos = pos, gain = 0.3, max_hear_distance = 10 }, true)
|
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})
|
minetest.set_node(pos, {name="doors:trapdoor_open", param2 = node.param2})
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -111,12 +123,6 @@ if doors and doors.get then
|
|||||||
minetest.override_item("doors:trapdoor_open", override)
|
minetest.override_item("doors:trapdoor_open", override)
|
||||||
minetest.override_item("doors:trapdoor_steel", override)
|
minetest.override_item("doors:trapdoor_steel", override)
|
||||||
minetest.override_item("doors:trapdoor_steel_open", override)
|
minetest.override_item("doors:trapdoor_steel_open", override)
|
||||||
|
|
||||||
if minetest.registered_items["xpanes:trapdoor_steel_bar"] then
|
|
||||||
minetest.override_item("xpanes:trapdoor_steel_bar", override)
|
|
||||||
minetest.override_item("xpanes:trapdoor_steel_bar_open", override)
|
|
||||||
end
|
|
||||||
|
|
||||||
else
|
else
|
||||||
if minetest.registered_nodes["doors:trapdoor"] then
|
if minetest.registered_nodes["doors:trapdoor"] then
|
||||||
minetest.override_item("doors:trapdoor", {
|
minetest.override_item("doors:trapdoor", {
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
name = mesecons_doors
|
|
||||||
depends = mesecons, doors
|
|
||||||
optional_depends = xpanes
|
|
53
mesecons_extrawires/corner.lua
Normal file → Executable file
@ -1,8 +1,12 @@
|
|||||||
local screwdriver_exists = minetest.global_exists("screwdriver")
|
local corner_nodebox = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = {{ -16/32-0.001, -17/32, -3/32, 0, -13/32, 3/32 },
|
||||||
|
{ -3/32, -17/32, -16/32+0.001, 3/32, -13/32, 3/32}}
|
||||||
|
}
|
||||||
|
|
||||||
local corner_selectionbox = {
|
local corner_selectionbox = {
|
||||||
type = "fixed",
|
type = "fixed",
|
||||||
fixed = { -16/32, -16/32, -16/32, 5/32, -12/32, 5/32 },
|
fixed = { -16/32-0.001, -18/32, -16/32, 5/32, -12/32, 5/32 },
|
||||||
}
|
}
|
||||||
|
|
||||||
local corner_get_rules = function (node)
|
local corner_get_rules = function (node)
|
||||||
@ -18,63 +22,62 @@ local corner_get_rules = function (node)
|
|||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_node("mesecons_extrawires:corner_on", {
|
minetest.register_node("mesecons_extrawires:corner_on", {
|
||||||
drawtype = "mesh",
|
drawtype = "nodebox",
|
||||||
mesh = "mesecons_extrawires_corner.obj",
|
|
||||||
tiles = {
|
tiles = {
|
||||||
{ name = "jeija_insulated_wire_sides_on.png", backface_culling = true },
|
"jeija_insulated_wire_curved_tb_on.png",
|
||||||
{ name = "jeija_insulated_wire_ends_on.png", backface_culling = true },
|
"jeija_insulated_wire_curved_tb_on.png^[transformR270",
|
||||||
|
"jeija_insulated_wire_sides_on.png",
|
||||||
|
"jeija_insulated_wire_ends_on.png",
|
||||||
|
"jeija_insulated_wire_sides_on.png",
|
||||||
|
"jeija_insulated_wire_ends_on.png"
|
||||||
},
|
},
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
paramtype2 = "facedir",
|
paramtype2 = "facedir",
|
||||||
is_ground_content = false,
|
|
||||||
walkable = false,
|
walkable = false,
|
||||||
sunlight_propagates = true,
|
sunlight_propagates = true,
|
||||||
selection_box = corner_selectionbox,
|
selection_box = corner_selectionbox,
|
||||||
node_box = corner_nodebox,
|
node_box = corner_nodebox,
|
||||||
groups = {dig_immediate = 3, not_in_creative_inventory = 1},
|
groups = {dig_immediate = 2, not_in_creative_inventory = 1}, -- MFF
|
||||||
drop = "mesecons_extrawires:corner_off",
|
drop = "mesecons_extrawires:corner_off",
|
||||||
sounds = default.node_sound_defaults(),
|
|
||||||
mesecons = {conductor =
|
mesecons = {conductor =
|
||||||
{
|
{
|
||||||
state = mesecon.state.on,
|
state = mesecon.state.on,
|
||||||
rules = corner_get_rules,
|
rules = corner_get_rules,
|
||||||
offstate = "mesecons_extrawires:corner_off"
|
offstate = "mesecons_extrawires:corner_off"
|
||||||
}},
|
}}
|
||||||
on_blast = mesecon.on_blastnode,
|
|
||||||
on_rotate = screwdriver_exists and screwdriver.rotate_simple,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_node("mesecons_extrawires:corner_off", {
|
minetest.register_node("mesecons_extrawires:corner_off", {
|
||||||
drawtype = "mesh",
|
drawtype = "nodebox",
|
||||||
description = "Insulated Mesecon Corner",
|
description = "Mesecon Corner",
|
||||||
mesh = "mesecons_extrawires_corner.obj",
|
|
||||||
tiles = {
|
tiles = {
|
||||||
{ name = "jeija_insulated_wire_sides_off.png", backface_culling = true },
|
"jeija_insulated_wire_curved_tb_off.png",
|
||||||
{ name = "jeija_insulated_wire_ends_off.png", backface_culling = true },
|
"jeija_insulated_wire_curved_tb_off.png^[transformR270",
|
||||||
|
"jeija_insulated_wire_sides_off.png",
|
||||||
|
"jeija_insulated_wire_ends_off.png",
|
||||||
|
"jeija_insulated_wire_sides_off.png",
|
||||||
|
"jeija_insulated_wire_ends_off.png"
|
||||||
},
|
},
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
paramtype2 = "facedir",
|
paramtype2 = "facedir",
|
||||||
is_ground_content = false,
|
|
||||||
walkable = false,
|
walkable = false,
|
||||||
sunlight_propagates = true,
|
sunlight_propagates = true,
|
||||||
selection_box = corner_selectionbox,
|
selection_box = corner_selectionbox,
|
||||||
node_box = corner_nodebox,
|
node_box = corner_nodebox,
|
||||||
groups = {dig_immediate = 3},
|
groups = {dig_immediate = 2}, --MFF
|
||||||
sounds = default.node_sound_defaults(),
|
|
||||||
mesecons = {conductor =
|
mesecons = {conductor =
|
||||||
{
|
{
|
||||||
state = mesecon.state.off,
|
state = mesecon.state.off,
|
||||||
rules = corner_get_rules,
|
rules = corner_get_rules,
|
||||||
onstate = "mesecons_extrawires:corner_on"
|
onstate = "mesecons_extrawires:corner_on"
|
||||||
}},
|
}}
|
||||||
on_blast = mesecon.on_blastnode,
|
|
||||||
on_rotate = screwdriver_exists and screwdriver.rotate_simple,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_craft({
|
minetest.register_craft({
|
||||||
output = "mesecons_extrawires:corner_off 3",
|
output = "mesecons_extrawires:corner_off 3",
|
||||||
recipe = {
|
recipe = {
|
||||||
{"mesecons_insulated:insulated_off", "mesecons_insulated:insulated_off"},
|
{"", "", ""},
|
||||||
{"", "mesecons_insulated:insulated_off"},
|
{"mesecons_insulated:insulated_off", "mesecons_insulated:insulated_off", ""},
|
||||||
|
{"", "mesecons_insulated:insulated_off", ""},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
115
mesecons_extrawires/crossover.lua
Normal file → Executable file
@ -1,4 +1,4 @@
|
|||||||
local function crossover_get_rules(node)
|
function crossover_get_rules(node)
|
||||||
return {
|
return {
|
||||||
{--first wire
|
{--first wire
|
||||||
{x=-1,y=0,z=0},
|
{x=-1,y=0,z=0},
|
||||||
@ -19,110 +19,143 @@ local crossover_states = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
minetest.register_node("mesecons_extrawires:crossover_off", {
|
minetest.register_node("mesecons_extrawires:crossover_off", {
|
||||||
description = "Insulated Mesecon Crossover",
|
description = "Insulated Crossover",
|
||||||
drawtype = "mesh",
|
drawtype = "nodebox",
|
||||||
mesh = "mesecons_extrawires_crossover.b3d",
|
|
||||||
tiles = {
|
tiles = {
|
||||||
"jeija_insulated_wire_ends_off.png",
|
"jeija_insulated_wire_crossing_tb_off.png",
|
||||||
"jeija_insulated_wire_sides_off.png",
|
"jeija_insulated_wire_crossing_tb_off.png",
|
||||||
"jeija_insulated_wire_sides_off.png",
|
|
||||||
"jeija_insulated_wire_ends_off.png"
|
"jeija_insulated_wire_ends_off.png"
|
||||||
},
|
},
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
is_ground_content = false,
|
|
||||||
walkable = false,
|
walkable = false,
|
||||||
stack_max = 99,
|
stack_max = 99,
|
||||||
selection_box = {type="fixed", fixed={-16/32, -16/32, -16/32, 16/32, -5/32, 16/32}},
|
selection_box = {type="fixed", fixed={-16/32-0.0001, -18/32, -16/32-0.001, 16/32+0.001, -5/32, 16/32+0.001}},
|
||||||
groups = {dig_immediate=3, mesecon=3},
|
node_box = {
|
||||||
sounds = default.node_sound_defaults(),
|
type = "fixed",
|
||||||
|
fixed = {
|
||||||
|
{ -16/32-0.001, -17/32, -3/32, 16/32+0.001, -13/32, 3/32 },
|
||||||
|
{ -3/32, -17/32, -16/32-0.001, 3/32, -13/32, -6/32 },
|
||||||
|
{ -3/32, -13/32, -9/32, 3/32, -6/32, -6/32 },
|
||||||
|
{ -3/32, -9/32, -9/32, 3/32, -6/32, 9/32 },
|
||||||
|
{ -3/32, -13/32, 6/32, 3/32, -6/32, 9/32 },
|
||||||
|
{ -3/32, -17/32, 6/32, 3/32, -13/32, 16/32+0.001 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
groups = {dig_immediate=2, mesecon=3}, --MFF
|
||||||
mesecons = {
|
mesecons = {
|
||||||
conductor = {
|
conductor = {
|
||||||
states = crossover_states,
|
states = crossover_states,
|
||||||
rules = crossover_get_rules(),
|
rules = crossover_get_rules(),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
on_blast = mesecon.on_blastnode,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_node("mesecons_extrawires:crossover_01", {
|
minetest.register_node("mesecons_extrawires:crossover_01", {
|
||||||
description = "You hacker you!",
|
description = "You hacker you!",
|
||||||
drop = "mesecons_extrawires:crossover_off",
|
drop = "mesecons_extrawires:crossover_off",
|
||||||
drawtype = "mesh",
|
drawtype = "nodebox",
|
||||||
mesh = "mesecons_extrawires_crossover.b3d",
|
|
||||||
tiles = {
|
tiles = {
|
||||||
"jeija_insulated_wire_ends_on.png",
|
"jeija_insulated_wire_crossing_tb_01.png",
|
||||||
"jeija_insulated_wire_sides_on.png",
|
"jeija_insulated_wire_crossing_tb_01.png",
|
||||||
"jeija_insulated_wire_sides_off.png",
|
"jeija_insulated_wire_ends_01x.png",
|
||||||
"jeija_insulated_wire_ends_off.png"
|
"jeija_insulated_wire_ends_01x.png",
|
||||||
|
"jeija_insulated_wire_ends_01z.png",
|
||||||
|
"jeija_insulated_wire_ends_01z.png"
|
||||||
},
|
},
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
is_ground_content = false,
|
|
||||||
walkable = false,
|
walkable = false,
|
||||||
stack_max = 99,
|
stack_max = 99,
|
||||||
selection_box = {type="fixed", fixed={-16/32, -16/32, -16/32, 16/32, -5/32, 16/32}},
|
selection_box = {type="fixed", fixed={-16/32-0.0001, -18/32, -16/32-0.001, 16/32+0.001, -5/32, 16/32+0.001}},
|
||||||
groups = {dig_immediate=3, mesecon=3, not_in_creative_inventory=1},
|
node_box = {
|
||||||
sounds = default.node_sound_defaults(),
|
type = "fixed",
|
||||||
|
fixed = {
|
||||||
|
{ -16/32-0.001, -17/32, -3/32, 16/32+0.001, -13/32, 3/32 },
|
||||||
|
{ -3/32, -17/32, -16/32-0.001, 3/32, -13/32, -6/32 },
|
||||||
|
{ -3/32, -13/32, -9/32, 3/32, -6/32, -6/32 },
|
||||||
|
{ -3/32, -9/32, -9/32, 3/32, -6/32, 9/32 },
|
||||||
|
{ -3/32, -13/32, 6/32, 3/32, -6/32, 9/32 },
|
||||||
|
{ -3/32, -17/32, 6/32, 3/32, -13/32, 16/32+0.001 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
groups = {dig_immediate=2, mesecon=3, not_in_creative_inventory=1}, --MFF
|
||||||
mesecons = {
|
mesecons = {
|
||||||
conductor = {
|
conductor = {
|
||||||
states = crossover_states,
|
states = crossover_states,
|
||||||
rules = crossover_get_rules(),
|
rules = crossover_get_rules(),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
on_blast = mesecon.on_blastnode,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_node("mesecons_extrawires:crossover_10", {
|
minetest.register_node("mesecons_extrawires:crossover_10", {
|
||||||
description = "You hacker you!",
|
description = "You hacker you!",
|
||||||
drop = "mesecons_extrawires:crossover_off",
|
drop = "mesecons_extrawires:crossover_off",
|
||||||
drawtype = "mesh",
|
drawtype = "nodebox",
|
||||||
mesh = "mesecons_extrawires_crossover.b3d",
|
|
||||||
tiles = {
|
tiles = {
|
||||||
"jeija_insulated_wire_ends_off.png",
|
"jeija_insulated_wire_crossing_tb_10.png",
|
||||||
"jeija_insulated_wire_sides_off.png",
|
"jeija_insulated_wire_crossing_tb_10.png",
|
||||||
"jeija_insulated_wire_sides_on.png",
|
"jeija_insulated_wire_ends_10x.png",
|
||||||
"jeija_insulated_wire_ends_on.png"
|
"jeija_insulated_wire_ends_10x.png",
|
||||||
|
"jeija_insulated_wire_ends_10z.png",
|
||||||
|
"jeija_insulated_wire_ends_10z.png"
|
||||||
},
|
},
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
is_ground_content = false,
|
|
||||||
walkable = false,
|
walkable = false,
|
||||||
stack_max = 99,
|
stack_max = 99,
|
||||||
selection_box = {type="fixed", fixed={-16/32, -16/32, -16/32, 16/32, -5/32, 16/32}},
|
selection_box = {type="fixed", fixed={-16/32-0.0001, -18/32, -16/32-0.001, 16/32+0.001, -5/32, 16/32+0.001}},
|
||||||
|
node_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = {
|
||||||
|
{ -16/32-0.001, -17/32, -3/32, 16/32+0.001, -13/32, 3/32 },
|
||||||
|
{ -3/32, -17/32, -16/32-0.001, 3/32, -13/32, -6/32 },
|
||||||
|
{ -3/32, -13/32, -9/32, 3/32, -6/32, -6/32 },
|
||||||
|
{ -3/32, -9/32, -9/32, 3/32, -6/32, 9/32 },
|
||||||
|
{ -3/32, -13/32, 6/32, 3/32, -6/32, 9/32 },
|
||||||
|
{ -3/32, -17/32, 6/32, 3/32, -13/32, 16/32+0.001 },
|
||||||
|
},
|
||||||
|
},
|
||||||
groups = {dig_immediate=3, mesecon=3, not_in_creative_inventory=1},
|
groups = {dig_immediate=3, mesecon=3, not_in_creative_inventory=1},
|
||||||
sounds = default.node_sound_defaults(),
|
|
||||||
mesecons = {
|
mesecons = {
|
||||||
conductor = {
|
conductor = {
|
||||||
states = crossover_states,
|
states = crossover_states,
|
||||||
rules = crossover_get_rules(),
|
rules = crossover_get_rules(),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
on_blast = mesecon.on_blastnode,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_node("mesecons_extrawires:crossover_on", {
|
minetest.register_node("mesecons_extrawires:crossover_on", {
|
||||||
description = "You hacker you!",
|
description = "You hacker you!",
|
||||||
drop = "mesecons_extrawires:crossover_off",
|
drop = "mesecons_extrawires:crossover_off",
|
||||||
drawtype = "mesh",
|
drawtype = "nodebox",
|
||||||
mesh = "mesecons_extrawires_crossover.b3d",
|
|
||||||
tiles = {
|
tiles = {
|
||||||
|
"jeija_insulated_wire_crossing_tb_on.png",
|
||||||
|
"jeija_insulated_wire_crossing_tb_on.png",
|
||||||
|
"jeija_insulated_wire_ends_on.png",
|
||||||
|
"jeija_insulated_wire_ends_on.png",
|
||||||
"jeija_insulated_wire_ends_on.png",
|
"jeija_insulated_wire_ends_on.png",
|
||||||
"jeija_insulated_wire_sides_on.png",
|
|
||||||
"jeija_insulated_wire_sides_on.png",
|
|
||||||
"jeija_insulated_wire_ends_on.png"
|
"jeija_insulated_wire_ends_on.png"
|
||||||
},
|
},
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
is_ground_content = false,
|
|
||||||
walkable = false,
|
walkable = false,
|
||||||
stack_max = 99,
|
stack_max = 99,
|
||||||
selection_box = {type="fixed", fixed={-16/32, -16/32, -16/32, 16/32, -5/32, 16/32}},
|
selection_box = {type="fixed", fixed={-16/32-0.0001, -18/32, -16/32-0.001, 16/32+0.001, -5/32, 16/32+0.001}},
|
||||||
|
node_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = {
|
||||||
|
{ -16/32-0.001, -17/32, -3/32, 16/32+0.001, -13/32, 3/32 },
|
||||||
|
{ -3/32, -17/32, -16/32-0.001, 3/32, -13/32, -6/32 },
|
||||||
|
{ -3/32, -13/32, -9/32, 3/32, -6/32, -6/32 },
|
||||||
|
{ -3/32, -9/32, -9/32, 3/32, -6/32, 9/32 },
|
||||||
|
{ -3/32, -13/32, 6/32, 3/32, -6/32, 9/32 },
|
||||||
|
{ -3/32, -17/32, 6/32, 3/32, -13/32, 16/32+0.001 },
|
||||||
|
},
|
||||||
|
},
|
||||||
groups = {dig_immediate=3, mesecon=3, not_in_creative_inventory=1},
|
groups = {dig_immediate=3, mesecon=3, not_in_creative_inventory=1},
|
||||||
sounds = default.node_sound_defaults(),
|
|
||||||
mesecons = {
|
mesecons = {
|
||||||
conductor = {
|
conductor = {
|
||||||
states = crossover_states,
|
states = crossover_states,
|
||||||
rules = crossover_get_rules(),
|
rules = crossover_get_rules(),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
on_blast = mesecon.on_blastnode,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_craft({
|
minetest.register_craft({
|
||||||
|
2
mesecons_extrawires/depends.txt
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
default
|
||||||
|
mesecons
|
@ -1 +1 @@
|
|||||||
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. Like uninsulated wires, they work through unloaded blocks.
|
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.
|
||||||
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 41 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 3.8 KiB |