Compare commits
305 Commits
patch_#135
...
9b835053c2
Author | SHA1 | Date | |
---|---|---|---|
9b835053c2 | |||
583d2c1441 | |||
397d449f1e | |||
29ec26a4c8 | |||
0d86f2c45e | |||
d356f901a3 | |||
6921909100 | |||
3202bf6786 | |||
fedbf49372 | |||
9fda51b650 | |||
4750925eab | |||
16836b16d6 | |||
c1eccba247 | |||
01332a7ba1 | |||
de4eeebd3b | |||
75bd1e8be6 | |||
95e6e2e4a5 | |||
168a923665 | |||
8dec053996 | |||
e1cffdedbf | |||
d3aedd2b98 | |||
68c1729990 | |||
9b58f8db29 | |||
7784b13da5 | |||
0dd530312b | |||
e78bbd6f98 | |||
bfd952b51a | |||
b7873e8e02 | |||
d6b2a39c99 | |||
1b54011b68 | |||
15e743629e | |||
1bf862f932 | |||
1a9704f184 | |||
8baa789eb1 | |||
b0158f5674 | |||
073c92d487 | |||
737f366741 | |||
302a28934d | |||
6e767a6c76 | |||
9d239cbfff | |||
d3cabedbb0 | |||
df4e880d8b | |||
45bbd9f7e3 | |||
028c290cd7 | |||
8808bb8911 | |||
fa040eb085 | |||
a4f5ae5b89 | |||
9e6eac4285 | |||
c73b451f9b | |||
9ff2329253 | |||
444cd0f2f1 | |||
d4e05f33af | |||
334400a541 | |||
5a0492b176 | |||
f61b1affea | |||
a234006592 | |||
12fb09f452 | |||
ff73d0e60f | |||
7013f2e5d4 | |||
f70a308bb0 | |||
d8f82e6771 | |||
7537b9f381 | |||
5ae3354227 | |||
1b513d2111 | |||
6f1ff24474 | |||
065e870349 | |||
fec82ab246 | |||
02f8d29170 | |||
2b096f050d | |||
993fdedd8c | |||
ff0bd76efe | |||
db39eef2f6 | |||
f78937b351 | |||
cc860acf8a | |||
748446b3cc | |||
1b10610f92 | |||
4f400f3fae | |||
7094f0b606 | |||
b08e93fc8b | |||
928f04fa9c | |||
c4a1aa0b98 | |||
37eb7f00e8 | |||
905260c8db | |||
8999597df2 | |||
0b3039e9a9 | |||
1f5601661e | |||
fa58607546 | |||
1963d8b3d5 | |||
954262d016 | |||
3ef8ae01e7 | |||
42cd973921 | |||
36a6419481 | |||
564bdc2d9b | |||
f9ebbdc0fb | |||
4dcc7fb32f | |||
54b9eaffa2 | |||
2554164674 | |||
967bde284a | |||
d80c788fab | |||
03ab151c87 | |||
dd2b36c41c | |||
0cb286b425 | |||
46cbc76988 | |||
fa3bd19270 | |||
2bc3c5d97c | |||
07d074075c | |||
5188853014 | |||
7667e7d8c5 | |||
ececf525b6 | |||
54daee236e | |||
c2e3d7c4e5 | |||
7415036f5b | |||
1bd936ad8c | |||
79edbed8d7 | |||
8743699298 | |||
703e6fdadb | |||
67cd17aa79 | |||
203aaf3c90 | |||
95fedc88bc | |||
433778c2ec | |||
54efc64558 | |||
dfeb070a20 | |||
6dacdaee1f | |||
e561be7fa3 | |||
89153f6909 | |||
8e6536ca2e | |||
bc9d4c2d5a | |||
6d79272ed4 | |||
564cee346a | |||
912f17f335 | |||
4816dee396 | |||
a3042b44fc | |||
53eaf2af11 | |||
778ee427f4 | |||
7c7595fd7d | |||
acd41b5773 | |||
f9f7600017 | |||
40487a65f4 | |||
75308f73e4 | |||
478680292c | |||
85bc62a65d | |||
ed3964da80 | |||
6cae381c27 | |||
4249ed4986 | |||
c4f0c5c169 | |||
2dea21f9ef | |||
b487783c23 | |||
72e513ecbd | |||
1e77b193dd | |||
08b14e3af0 | |||
e5dba66c21 | |||
417a136c5e | |||
2dc8101fa1 | |||
4b9039266e | |||
c7428d8135 | |||
cfd4f7c287 | |||
f099b43e11 | |||
7b84105512 | |||
80f72b2621 | |||
fe9c6871de | |||
7865d42834 | |||
809192f353 | |||
6b54f025c1 | |||
c98805a5b5 | |||
fb4c440265 | |||
cf45e24c57 | |||
3f00c1d1cb | |||
c1d0481f8f | |||
f56c4ce35c | |||
0ec503f32c | |||
35b647ed4a | |||
eab09b9d73 | |||
2682d09291 | |||
a6b28d1f11 | |||
0ec771bf7d | |||
75bd081a67 | |||
b89fe52469 | |||
97f7b5745f | |||
24958e253b | |||
0e7f68ea92 | |||
6ef3b965df | |||
6e326a6a03 | |||
d95ccf86f8 | |||
d0354d0dab | |||
fec43a3243 | |||
5612f84243 | |||
3066346d75 | |||
52ea2c3c66 | |||
b6ae419b00 | |||
a6d0a523ba | |||
aa5538a734 | |||
eb416475cc | |||
1ee3b2107d | |||
1df6e5a03b | |||
b7076e635c | |||
6d9f44455c | |||
8bf5b7d0e4 | |||
14281a1bd4 | |||
1d93a51f6e | |||
639fc8988e | |||
a9ec0a10c0 | |||
775d250112 | |||
3c06da7908 | |||
11cf727bfb | |||
30468b09cf | |||
a895715720 | |||
94604e890c | |||
ac0e062281 | |||
562cee7438 | |||
a33859574c | |||
09bb11d3e5 | |||
cb598cbe18 | |||
aed4d3997b | |||
1509510262 | |||
d6b53a2962 | |||
eb3ad9e537 | |||
3c82e2fc3a | |||
f02ccdfa5d | |||
80648b6c14 | |||
adb803ce17 | |||
dca4706c7f | |||
011543a782 | |||
b3aa8f5d13 | |||
c326dc221a | |||
d2373eb605 | |||
2a51e40af9 | |||
4bd9d2a9ec | |||
f69caba036 | |||
e74241f4aa | |||
f388dc475a | |||
fb695e9c1c | |||
fc4d675b84 | |||
085b4d8bb7 | |||
0e3aa57ed3 | |||
a814abd1e0 | |||
fb5c9edaf4 | |||
f977ac821a | |||
80d136125e | |||
a550323fea | |||
d19e975955 | |||
29dc50057c | |||
5be179bf11 | |||
ffacbfde5a | |||
b5cc933287 | |||
194155fff8 | |||
87bfbb4de9 | |||
1b9f1b8c13 | |||
dcf1f799c5 | |||
bd1766e448 | |||
d325292291 | |||
1ebd50ac75 | |||
1908a225f9 | |||
0c62545a3a | |||
e88e213183 | |||
63998fd7e7 | |||
13432ac87c | |||
b8714f7d93 | |||
99cb021f15 | |||
041429c985 | |||
e5896076fe | |||
b64fea4f70 | |||
a6916191aa | |||
f1eaee2281 | |||
b9178dfcaa | |||
300abcb587 | |||
1f66687580 | |||
1852e967a9 | |||
a9427d267b | |||
2cab6aa5ef | |||
37405e5a06 | |||
3d2cfeace8 | |||
df6829e553 | |||
39a0e56c18 | |||
b50721c701 | |||
38ff900274 | |||
9eda62df7b | |||
8440d05e8c | |||
5d3cba0bd4 | |||
5002315ec9 | |||
a59f53d71a | |||
c240d399fb | |||
ee3797746f | |||
8a71f51b26 | |||
a632a8abc8 | |||
a6bd955449 | |||
6c979a6ebb | |||
fe50e87da1 | |||
c8ef37f522 | |||
1a492feb7a | |||
eea4dbbea8 | |||
cd30aed807 | |||
76b9198717 | |||
d066b91632 | |||
1083539e9b | |||
6afded8284 | |||
ff5e315325 | |||
f1211f7dae | |||
93fb489bdb | |||
f1ae54ed12 | |||
7517cc4af1 | |||
c067e52714 | |||
2d004b19ea | |||
de6dd30745 | |||
3f76b77001 | |||
5e02b3beef |
2
.gitignore
vendored
@ -1 +1,3 @@
|
|||||||
*~
|
*~
|
||||||
|
*.patch
|
||||||
|
*.diff
|
||||||
|
30
COPYING.txt
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
The Mesecons Mod for Minetest is
|
||||||
|
Copyright (C) 2011-2016 Mesecons Mod Developer Team and contributors
|
||||||
|
|
||||||
|
See the version control system log for information about other authors.
|
||||||
|
|
||||||
|
License of source code
|
||||||
|
----------------------
|
||||||
|
Copyright (C) 2011-2016 Mesecons Mod Developer Team and contributors
|
||||||
|
|
||||||
|
This program is free software; you can redistribute the Mesecons Mod and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public License version 3
|
||||||
|
published by the Free Software Foundation.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
License of media (textures, sounds and documentation)
|
||||||
|
-----------------------------------------------------
|
||||||
|
Copyright (C) 2011-2016 Mesecons Mod Developer Team and contributors
|
||||||
|
|
||||||
|
All textures, sounds and documentation files are licensed under the
|
||||||
|
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
|
||||||
|
http://creativecommons.org/licenses/by-sa/3.0/
|
11
README.md
@ -22,9 +22,9 @@ OK, I want in.
|
|||||||
--------------
|
--------------
|
||||||
Go get it!
|
Go get it!
|
||||||
|
|
||||||
[DOWNLOADS PAGE](http://mesecons.net/downloads.php)
|
[DOWNLOAD IT NOW](https://github.com/minetest-mods/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](http://wiki.minetest.com/wiki/Mods) over at the Minetest Wiki. For your convenience, here's a quick summary:
|
Now go ahead and install it like any other Minetest mod. Don't know how? Check out [the wonderful page about it](https://wiki.minetest.net/Mods) over at the official 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.
|
||||||
@ -39,13 +39,15 @@ How do I use this thing?
|
|||||||
------------------------
|
------------------------
|
||||||
How about a [quick overview video](https://www.youtube.com/watch?v=6kmeQj6iW5k)?
|
How about a [quick overview video](https://www.youtube.com/watch?v=6kmeQj6iW5k)?
|
||||||
|
|
||||||
Or maybe a [comprehensive reference](http://mesecons.net/items.php) is your style?
|
Or maybe a [comprehensive reference](http://mesecons.net/items.html) is your style?
|
||||||
|
|
||||||
An overview for the very newest of new beginners? How does [this one](http://uberi.mesecons.net/projects/MeseconsBasics/index.html) look?
|
An overview for the very newest of new beginners? How does [this one](http://uberi.mesecons.net/projects/MeseconsBasics/index.html) look?
|
||||||
|
|
||||||
|
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/Jeija/minetest-mod-mesecons)!
|
Want to contribute to Mesecons itself? Check out the [source code](https://github.com/minetest-mods/mesecons)!
|
||||||
|
|
||||||
Who wrote it anyways?
|
Who wrote it anyways?
|
||||||
---------------------
|
---------------------
|
||||||
@ -53,6 +55,7 @@ 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
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
]
|
||||||
|
}
|
64
documentation.json
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
{
|
||||||
|
"Conductors" : {
|
||||||
|
"Mesecon" : "mesecons_wires/doc/mesecon",
|
||||||
|
"Insulated Wire" : "mesecons_insulated/doc/insulated",
|
||||||
|
"T-Junction" : "mesecons_extrawires/doc/tjunction",
|
||||||
|
"Crossing" : "mesecons_extrawires/doc/crossing",
|
||||||
|
"Corner" : "mesecons_extrawires/doc/corner",
|
||||||
|
"Vertical Wire" : "mesecons_extrawires/doc/vertical",
|
||||||
|
"Mese" : "mesecons_extrawires/doc/mese"
|
||||||
|
},
|
||||||
|
"Receptors" : {
|
||||||
|
"Power Plant" : "mesecons_powerplant/doc/powerplant",
|
||||||
|
"Blinky Plant" : "mesecons_blinkyplant/doc/blinkyplant",
|
||||||
|
"Switch" : "mesecons_switch/doc/switch",
|
||||||
|
"Object Detector" : "mesecons_detector/doc/objectdetector",
|
||||||
|
"Node Detector" : "mesecons_detector/doc/nodedetector",
|
||||||
|
"Wall Lever" : "mesecons_walllever/doc/walllever",
|
||||||
|
"Pressure Plate" : "mesecons_pressureplates/doc/pressureplate_wood",
|
||||||
|
"Pressure Plate" : "mesecons_pressureplates/doc/pressureplate_stone",
|
||||||
|
"Water Turbine" : "mesecons_hydroturbine/doc/waterturbine",
|
||||||
|
"Solar Panel" : "mesecons_solarpanel/doc/solarpanel",
|
||||||
|
"Wall Button" : "mesecons_button/doc/button"
|
||||||
|
},
|
||||||
|
"Effectors" : {
|
||||||
|
"Noteblock" : "mesecons_noteblock/doc/noteblock",
|
||||||
|
"Lamp" : "mesecons_lamp/doc/lamp",
|
||||||
|
"Piston" : "mesecons_pistons/doc/piston",
|
||||||
|
"Sticky Piston" : "mesecons_pistons/doc/piston_sticky",
|
||||||
|
"Movestone" : "mesecons_movestones/doc/movestone",
|
||||||
|
"Sticky Movestone" : "mesecons_movestones/doc/movestone_sticky",
|
||||||
|
"Removestone" : "mesecons_random/doc/removestone",
|
||||||
|
"Ghoststone" : "mesecons_random/doc/ghoststone",
|
||||||
|
"Command Block" : "mesecons_commandblock/doc/commandblock",
|
||||||
|
"Lightstones" : {
|
||||||
|
"Dark Grey" : "mesecons_lightstone/doc/lightstone_darkgrey",
|
||||||
|
"Light Grey" : "mesecons_lightstone/doc/lightstone_lightgrey",
|
||||||
|
"Green" : "mesecons_lightstone/doc/lightstone_green",
|
||||||
|
"Red" : "mesecons_lightstone/doc/lightstone_red",
|
||||||
|
"Blue" : "mesecons_lightstone/doc/lightstone_blue",
|
||||||
|
"Yellow" : "mesecons_lightstone/doc/lightstone_yellow"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Logic" : {
|
||||||
|
"Luacontroller" : "mesecons_luacontroller/doc/luacontroller",
|
||||||
|
"FPGA" : "mesecons_fpga/doc/fpga",
|
||||||
|
"FPGA Programmer" : "mesecons_fpga/doc/programmer",
|
||||||
|
"Torch" : "mesecons_torch/doc/torch",
|
||||||
|
"Delayer" : "mesecons_delayer/doc/delayer",
|
||||||
|
"Gates" : {
|
||||||
|
"Diode" : "mesecons_gates/doc/diode",
|
||||||
|
"NOT Gate" : "mesecons_gates/doc/not",
|
||||||
|
"AND Gate" : "mesecons_gates/doc/and",
|
||||||
|
"NAND Gate" : "mesecons_gates/doc/nand",
|
||||||
|
"OR Gate" : "mesecons_gates/doc/or",
|
||||||
|
"NOR Gate" : "mesecons_gates/doc/nor",
|
||||||
|
"XOR Gate" : "mesecons_gates/doc/xor"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Crafts" : {
|
||||||
|
"Silicon" : "mesecons_materials/doc/silicon",
|
||||||
|
"Glue" : "mesecons_materials/doc/glue",
|
||||||
|
"Fiber" : "mesecons_materials/doc/fiber"
|
||||||
|
}
|
||||||
|
}
|
@ -1 +0,0 @@
|
|||||||
0.41 DEV
|
|
149
mesecons/actionqueue.lua
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
--[[
|
||||||
|
Mesecons uses something it calls an ActionQueue.
|
||||||
|
|
||||||
|
The ActionQueue holds functions and actions.
|
||||||
|
Functions are added on load time with a specified name.
|
||||||
|
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
|
||||||
|
|
||||||
|
-- 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
|
||||||
|
-- priority specifies the order actions are executed within one globalstep, highest first
|
||||||
|
-- should be between 0 and 1
|
||||||
|
function queue:add_action(pos, func, params, time, overwritecheck, priority)
|
||||||
|
-- Create Action Table:
|
||||||
|
time = time or 0 -- time <= 0 --> execute, time > 0 --> wait time until execution
|
||||||
|
priority = priority or 1
|
||||||
|
local action = {
|
||||||
|
pos = mesecon.tablecopy(pos),
|
||||||
|
func = func,
|
||||||
|
params = mesecon.tablecopy(params or {}),
|
||||||
|
time = time,
|
||||||
|
owcheck = (overwritecheck and mesecon.tablecopy(overwritecheck)) or nil,
|
||||||
|
priority = priority
|
||||||
|
}
|
||||||
|
|
||||||
|
-- check if old action has to be overwritten / removed:
|
||||||
|
if overwritecheck then
|
||||||
|
for i, ac in ipairs(queue.actions) do
|
||||||
|
if vector.equals(pos, ac.pos)
|
||||||
|
and mesecon.cmpAny(overwritecheck, ac.owcheck) then
|
||||||
|
-- remove the old action
|
||||||
|
table.remove(queue.actions, i)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(queue.actions, action)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 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
|
||||||
|
-- this makes sure that resuming mesecons circuits when restarting minetest works fine (hm, where do we do this?)
|
||||||
|
-- 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
|
||||||
|
|
||||||
|
local function globalstep_func(dtime)
|
||||||
|
local actions = queue.actions
|
||||||
|
-- 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
|
||||||
|
if ac.time > 0 then
|
||||||
|
-- action ac is to be executed later
|
||||||
|
-- ~> insert into queue.actions
|
||||||
|
ac.time = ac.time - dtime
|
||||||
|
table.insert(queue.actions, ac)
|
||||||
|
else
|
||||||
|
-- action ac is to be executed now
|
||||||
|
-- ~> insert into actions_now
|
||||||
|
table.insert(actions_now, ac)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- stable-sort the executed actions after their priority
|
||||||
|
-- some constructions might depend on the execution order, hence we first
|
||||||
|
-- execute the actions that had a lower index in actions_now
|
||||||
|
local old_action_order = {}
|
||||||
|
for i, ac in ipairs(actions_now) do
|
||||||
|
old_action_order[ac] = i
|
||||||
|
end
|
||||||
|
table.sort(actions_now, function(ac1, ac2)
|
||||||
|
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
|
||||||
|
for _, ac in ipairs(actions_now) do
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
-- Store and read the ActionQueue to / from a file
|
||||||
|
-- so that upcoming actions are remembered when the game
|
||||||
|
-- is restarted
|
||||||
|
queue.actions = mesecon.file2table("mesecon_actionqueue")
|
||||||
|
|
||||||
|
minetest.register_on_shutdown(function()
|
||||||
|
mesecon.table2file("mesecon_actionqueue", queue.actions)
|
||||||
|
end)
|
@ -1 +0,0 @@
|
|||||||
default
|
|
@ -3,7 +3,7 @@
|
|||||||
-- | \/ | |___ ____ |___ | | | | \ | |____
|
-- | \/ | |___ ____ |___ | | | | \ | |____
|
||||||
-- | | | | | | | | | \ | |
|
-- | | | | | | | | | \ | |
|
||||||
-- | | |___ ____| |___ |____ |____| | \| ____|
|
-- | | |___ ____| |___ |____ |____| | \| ____|
|
||||||
-- by Jeija, Uberi (Temperest), sfan5, VanessaE
|
-- by Jeija, Uberi (Temperest), sfan5, VanessaE, Hawk777 and contributors
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
@ -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 developer documentation see the Developers' section on mesecons.TK
|
-- For basic development resources, see http://mesecons.net/developers.html
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
@ -39,53 +39,26 @@
|
|||||||
-- }
|
-- }
|
||||||
--}
|
--}
|
||||||
|
|
||||||
|
|
||||||
-- PUBLIC VARIABLES
|
-- PUBLIC VARIABLES
|
||||||
mesecon={} -- contains all functions and all global variables
|
mesecon={} -- contains all functions and all global variables
|
||||||
mesecon.actions_on={} -- Saves registered function callbacks for mesecon on | DEPRECATED
|
mesecon.queue={} -- contains the ActionQueue
|
||||||
mesecon.actions_off={} -- Saves registered function callbacks for mesecon off | DEPRECATED
|
mesecon.queue.funcs={} -- contains all ActionQueue functions
|
||||||
mesecon.actions_change={} -- Saves registered function callbacks for mesecon change | DEPRECATED
|
|
||||||
mesecon.receptors={} -- saves all information about receptors | DEPRECATED
|
|
||||||
mesecon.effectors={} -- saves all information about effectors | DEPRECATED
|
|
||||||
mesecon.conductors={} -- saves all information about conductors | DEPRECATED
|
|
||||||
|
|
||||||
|
|
||||||
local wpath = minetest.get_worldpath()
|
|
||||||
local function read_file(fn)
|
|
||||||
local f = io.open(fn, "r")
|
|
||||||
if f==nil then return {} end
|
|
||||||
local t = f:read("*all")
|
|
||||||
f:close()
|
|
||||||
if t=="" or t==nil then return {} end
|
|
||||||
return minetest.deserialize(t)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function write_file(fn, tbl)
|
|
||||||
local f = io.open(fn, "w")
|
|
||||||
f:write(minetest.serialize(tbl))
|
|
||||||
f:close()
|
|
||||||
end
|
|
||||||
|
|
||||||
mesecon.to_update = read_file(wpath.."/mesecon_to_update")
|
|
||||||
mesecon.r_to_update = read_file(wpath.."/mesecon_r_to_update")
|
|
||||||
|
|
||||||
minetest.register_on_shutdown(function()
|
|
||||||
write_file(wpath.."/mesecon_to_update",mesecon.to_update)
|
|
||||||
write_file(wpath.."/mesecon_r_to_update",mesecon.r_to_update)
|
|
||||||
end)
|
|
||||||
|
|
||||||
-- Settings
|
-- Settings
|
||||||
dofile(minetest.get_modpath("mesecons").."/settings.lua")
|
dofile(minetest.get_modpath("mesecons").."/settings.lua")
|
||||||
|
|
||||||
-- Presets (eg default rules)
|
|
||||||
dofile(minetest.get_modpath("mesecons").."/presets.lua");
|
|
||||||
|
|
||||||
|
|
||||||
-- Utilities like comparing positions,
|
-- Utilities like comparing positions,
|
||||||
-- adding positions and rules,
|
-- adding positions and rules,
|
||||||
-- mostly things that make the source look cleaner
|
-- mostly things that make the source look cleaner
|
||||||
dofile(minetest.get_modpath("mesecons").."/util.lua");
|
dofile(minetest.get_modpath("mesecons").."/util.lua");
|
||||||
|
|
||||||
|
-- Presets (eg default rules)
|
||||||
|
dofile(minetest.get_modpath("mesecons").."/presets.lua");
|
||||||
|
|
||||||
|
-- The ActionQueue
|
||||||
|
-- Saves all the actions that have to be execute in the future
|
||||||
|
dofile(minetest.get_modpath("mesecons").."/actionqueue.lua");
|
||||||
|
|
||||||
-- Internal stuff
|
-- Internal stuff
|
||||||
-- This is the most important file
|
-- This is the most important file
|
||||||
-- it handles signal transmission and basically everything else
|
-- it handles signal transmission and basically everything else
|
||||||
@ -93,64 +66,63 @@ dofile(minetest.get_modpath("mesecons").."/util.lua");
|
|||||||
-- like calling action_on/off/change
|
-- like calling action_on/off/change
|
||||||
dofile(minetest.get_modpath("mesecons").."/internal.lua");
|
dofile(minetest.get_modpath("mesecons").."/internal.lua");
|
||||||
|
|
||||||
-- Deprecated stuff
|
|
||||||
-- To be removed in future releases
|
|
||||||
-- Currently there is nothing here
|
|
||||||
dofile(minetest.get_modpath("mesecons").."/legacy.lua");
|
|
||||||
|
|
||||||
-- API
|
-- API
|
||||||
-- these are the only functions you need to remember
|
-- these are the only functions you need to remember
|
||||||
|
|
||||||
function mesecon:receptor_on_i(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
|
||||||
|
|
||||||
for _, rule in ipairs(mesecon:flattenrules(rules)) do
|
-- Call turnon on all linking positions
|
||||||
local np = mesecon:addPosRule(pos, rule)
|
for _, rule in ipairs(mesecon.flattenrules(rules)) do
|
||||||
local rulenames = mesecon:rules_link_rule_all(pos, rule)
|
local np = vector.add(pos, rule)
|
||||||
|
local rulenames = mesecon.rules_link_rule_all(pos, rule)
|
||||||
for _, rulename in ipairs(rulenames) do
|
for _, rulename in ipairs(rulenames) do
|
||||||
mesecon:turnon(np, rulename)
|
mesecon.turnon(np, rulename)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
mesecon.vm_commit()
|
||||||
|
end)
|
||||||
|
|
||||||
|
function mesecon.receptor_on(pos, rules)
|
||||||
|
mesecon.queue:add_action(pos, "receptor_on", {rules}, nil, rules)
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:receptor_on(pos, rules)
|
mesecon.queue:add_function("receptor_off", function (pos, rules)
|
||||||
if MESECONS_GLOBALSTEP then
|
|
||||||
rules = rules or mesecon.rules.default
|
rules = rules or mesecon.rules.default
|
||||||
mesecon.r_to_update[#mesecon.r_to_update+1]={pos=pos, rules=rules, action="on"}
|
|
||||||
else
|
|
||||||
mesecon:receptor_on_i(pos, rules)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function mesecon:receptor_off_i(pos, rules)
|
-- Call turnoff on all linking positions
|
||||||
rules = rules or mesecon.rules.default
|
for _, rule in ipairs(mesecon.flattenrules(rules)) do
|
||||||
for _, rule in ipairs(mesecon:flattenrules(rules)) do
|
local np = vector.add(pos, rule)
|
||||||
local np = mesecon:addPosRule(pos, rule)
|
local rulenames = mesecon.rules_link_rule_all(pos, rule)
|
||||||
local rulenames = mesecon:rules_link_rule_all(pos, rule)
|
|
||||||
for _, rulename in ipairs(rulenames) do
|
for _, rulename in ipairs(rulenames) do
|
||||||
if not mesecon:connected_to_receptor(np, mesecon:invertRule(rule)) then
|
mesecon.vm_begin()
|
||||||
mesecon:turnoff(np, rulename)
|
mesecon.changesignal(np, minetest.get_node(np), rulename, mesecon.state.off, 2)
|
||||||
else
|
|
||||||
mesecon:changesignal(np, minetest.get_node(np), rulename, mesecon.state.off)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function mesecon:receptor_off(pos, rules)
|
-- Turnoff returns true if turnoff process was successful, no onstate receptor
|
||||||
if MESECONS_GLOBALSTEP then
|
-- was found along the way. Commit changes that were made in voxelmanip. If turnoff
|
||||||
rules = rules or mesecon.rules.default
|
-- returns true, an onstate receptor was found, abort voxelmanip transaction.
|
||||||
mesecon.r_to_update[#mesecon.r_to_update+1]={pos=pos, rules=rules, action="off"}
|
if (mesecon.turnoff(np, rulename)) then
|
||||||
|
mesecon.vm_commit()
|
||||||
else
|
else
|
||||||
mesecon:receptor_off_i(pos, rules)
|
mesecon.vm_abort()
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
function mesecon.receptor_off(pos, rules)
|
||||||
|
mesecon.queue:add_action(pos, "receptor_off", {rules}, nil, rules)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
print("[OK] Mesecons")
|
print("[OK] Mesecons")
|
||||||
|
|
||||||
--The actual wires
|
-- Deprecated stuff
|
||||||
dofile(minetest.get_modpath("mesecons").."/wires.lua");
|
-- To be removed in future releases
|
||||||
|
dofile(minetest.get_modpath("mesecons").."/legacy.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");
|
||||||
|
@ -1,62 +1,53 @@
|
|||||||
-- Internal.lua - The core of mesecons
|
-- Internal.lua - The core of mesecons
|
||||||
--
|
--
|
||||||
-- For more practical developer resources see mesecons.tk
|
-- For more practical developer resources see http://mesecons.net/developers.php
|
||||||
--
|
--
|
||||||
-- Function overview
|
-- Function overview
|
||||||
-- mesecon:get_effector(nodename) --> Returns the mesecons.effector -specifictation in the nodedef by the nodename
|
-- mesecon.get_effector(nodename) --> Returns the mesecons.effector -specifictation in the nodedef by the nodename
|
||||||
-- mesecon:get_receptor(nodename) --> Returns the mesecons.receptor -specifictation in the nodedef by the nodename
|
-- mesecon.get_receptor(nodename) --> Returns the mesecons.receptor -specifictation in the nodedef by the nodename
|
||||||
-- mesecon:get_conductor(nodename) --> Returns the mesecons.conductor-specifictation in the nodedef by the nodename
|
-- mesecon.get_conductor(nodename) --> Returns the mesecons.conductor-specifictation in the nodedef by the nodename
|
||||||
-- mesecon:get_any_inputrules (node) --> Returns the rules of a node if it is a conductor or an effector
|
-- mesecon.get_any_inputrules (node) --> Returns the rules of a node if it is a conductor or an effector
|
||||||
-- mesecon:get_any_outputrules (node) --> Returns the rules of a node if it is a conductor or a receptor
|
-- mesecon.get_any_outputrules (node) --> Returns the rules of a node if it is a conductor or a receptor
|
||||||
|
|
||||||
-- RECEPTORS
|
-- RECEPTORS
|
||||||
-- mesecon:is_receptor(nodename) --> Returns true if nodename is a receptor
|
-- mesecon.is_receptor(nodename) --> Returns true if nodename is a receptor
|
||||||
-- mesecon:is_receptor_on(nodename) --> Returns true if nodename is an receptor with state = mesecon.state.on
|
-- mesecon.is_receptor_on(nodename --> Returns true if nodename is an receptor with state = mesecon.state.on
|
||||||
-- mesecon:is_receptor_off(nodename) --> Returns true if nodename is an receptor with state = mesecon.state.off
|
-- mesecon.is_receptor_off(nodename) --> Returns true if nodename is an receptor with state = mesecon.state.off
|
||||||
-- mesecon:receptor_get_rules(node) --> Returns the rules of the receptor (mesecon.rules.default if none specified)
|
-- mesecon.receptor_get_rules(node) --> Returns the rules of the receptor (mesecon.rules.default if none specified)
|
||||||
|
|
||||||
-- EFFECTORS
|
-- EFFECTORS
|
||||||
-- mesecon:is_effector(nodename) --> Returns true if nodename is an effector
|
-- mesecon.is_effector(nodename) --> Returns true if nodename is an effector
|
||||||
-- mesecon:is_effector_on(nodename) --> Returns true if nodename is an effector with nodedef.mesecons.effector.action_off
|
-- mesecon.is_effector_on(nodename) --> Returns true if nodename is an effector with nodedef.mesecons.effector.action_off
|
||||||
-- mesecon:is_effector_off(nodename) --> Returns true if nodename is an effector with nodedef.mesecons.effector.action_on
|
-- mesecon.is_effector_off(nodename) --> Returns true if nodename is an effector with nodedef.mesecons.effector.action_on
|
||||||
-- mesecon:effector_get_rules(node) --> Returns the input rules of the effector (mesecon.rules.default if none specified)
|
-- mesecon.effector_get_rules(node) --> Returns the input rules of the effector (mesecon.rules.default if none specified)
|
||||||
|
|
||||||
-- SIGNALS
|
-- SIGNALS
|
||||||
-- mesecon:activate(pos, node) --> Activates the effector node at the specific pos (calls nodedef.mesecons.effector.action_on)
|
-- mesecon.activate(pos, node, depth) --> Activates the effector node at the specific pos (calls nodedef.mesecons.effector.action_on), higher depths are executed later
|
||||||
-- mesecon:deactivate(pos, node) --> Deactivates the effector node at the specific pos (calls nodedef.mesecons.effector.action_off)
|
-- mesecon.deactivate(pos, node, depth) --> Deactivates the effector node at the specific pos (calls nodedef.mesecons.effector.action_off), higher depths are executed later
|
||||||
-- mesecon:changesignal(pos, node, rulename, newstate) --> Changes the effector node at the specific pos (calls nodedef.mesecons.effector.action_change)
|
-- mesecon.changesignal(pos, node, rulename, newstate, depth) --> Changes the effector node at the specific pos (calls nodedef.mesecons.effector.action_change), higher depths are executed later
|
||||||
|
|
||||||
-- RULES
|
|
||||||
-- mesecon:add_rules(name, rules) | deprecated? --> Saves rules table by name
|
|
||||||
-- mesecon:get_rules(name, rules) | deprecated? --> Loads rules table with name
|
|
||||||
|
|
||||||
-- CONDUCTORS
|
-- CONDUCTORS
|
||||||
-- mesecon:is_conductor(nodename) --> Returns true if nodename is a conductor
|
-- mesecon.is_conductor(nodename) --> Returns true if nodename is a conductor
|
||||||
-- mesecon:is_conductor_on(node) --> Returns true if node is a conductor with state = mesecon.state.on
|
-- mesecon.is_conductor_on(node --> Returns true if node is a conductor with state = mesecon.state.on
|
||||||
-- mesecon:is_conductor_off(node) --> Returns true if node is a conductor with state = mesecon.state.off
|
-- mesecon.is_conductor_off(node) --> Returns true if node is a conductor with state = mesecon.state.off
|
||||||
-- mesecon:get_conductor_on(node_off) --> Returns the onstate nodename of the conductor
|
-- mesecon.get_conductor_on(node_off) --> Returns the onstate nodename of the conductor
|
||||||
-- mesecon:get_conductor_off(node_on) --> Returns the offstate nodename of the conductor
|
-- mesecon.get_conductor_off(node_on) --> Returns the offstate nodename of the conductor
|
||||||
-- mesecon:conductor_get_rules(node) --> Returns the input+output rules of a conductor (mesecon.rules.default if none specified)
|
-- mesecon.conductor_get_rules(node) --> Returns the input+output rules of a conductor (mesecon.rules.default if none specified)
|
||||||
|
|
||||||
-- 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, rulename) --> Returns true whatever there is at pos. Calls itself for connected nodes (if pos is a conductor) --> recursive, the rulename is the name of the input rule that caused calling turnon
|
-- mesecon.is_powered(pos) --> Returns true if pos is powered by a receptor or a conductor
|
||||||
-- mesecon:turnoff(pos, rulename) --> Turns off whatever there is at pos. Calls itself for connected nodes (if pos is a conductor) --> recursive, the rulename is the name of the input rule that caused calling turnoff
|
|
||||||
-- mesecon:connected_to_receptor(pos) --> Returns true if pos is connected to a receptor directly or via conductors; calls itself if pos is a conductor --> recursive
|
|
||||||
-- 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
|
|
||||||
|
|
||||||
-- RULES ROTATION helpsers
|
-- RULES ROTATION helpers
|
||||||
-- mesecon:rotate_rules_right(rules)
|
-- mesecon.rotate_rules_right(rules)
|
||||||
-- mesecon:rotate_rules_left(rules)
|
-- mesecon.rotate_rules_left(rules)
|
||||||
-- mesecon:rotate_rules_up(rules)
|
-- mesecon.rotate_rules_up(rules)
|
||||||
-- mesecon:rotate_rules_down(rules)
|
-- mesecon.rotate_rules_down(rules)
|
||||||
-- These functions return rules that have been rotated in the specific direction
|
-- These functions return rules that have been rotated in the specific direction
|
||||||
|
|
||||||
-- General
|
-- General
|
||||||
function mesecon:get_effector(nodename)
|
function mesecon.get_effector(nodename)
|
||||||
if minetest.registered_nodes[nodename]
|
if minetest.registered_nodes[nodename]
|
||||||
and minetest.registered_nodes[nodename].mesecons
|
and minetest.registered_nodes[nodename].mesecons
|
||||||
and minetest.registered_nodes[nodename].mesecons.effector then
|
and minetest.registered_nodes[nodename].mesecons.effector then
|
||||||
@ -64,7 +55,7 @@ function mesecon:get_effector(nodename)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:get_receptor(nodename)
|
function mesecon.get_receptor(nodename)
|
||||||
if minetest.registered_nodes[nodename]
|
if minetest.registered_nodes[nodename]
|
||||||
and minetest.registered_nodes[nodename].mesecons
|
and minetest.registered_nodes[nodename].mesecons
|
||||||
and minetest.registered_nodes[nodename].mesecons.receptor then
|
and minetest.registered_nodes[nodename].mesecons.receptor then
|
||||||
@ -72,7 +63,7 @@ function mesecon:get_receptor(nodename)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:get_conductor(nodename)
|
function mesecon.get_conductor(nodename)
|
||||||
if minetest.registered_nodes[nodename]
|
if minetest.registered_nodes[nodename]
|
||||||
and minetest.registered_nodes[nodename].mesecons
|
and minetest.registered_nodes[nodename].mesecons
|
||||||
and minetest.registered_nodes[nodename].mesecons.conductor then
|
and minetest.registered_nodes[nodename].mesecons.conductor then
|
||||||
@ -80,52 +71,59 @@ function mesecon:get_conductor(nodename)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:get_any_outputrules (node)
|
function mesecon.get_any_outputrules(node)
|
||||||
if mesecon:is_conductor(node.name) then
|
if not node then return nil end
|
||||||
return mesecon:conductor_get_rules(node)
|
|
||||||
elseif mesecon:is_receptor(node.name) then
|
if mesecon.is_conductor(node.name) then
|
||||||
return mesecon:receptor_get_rules(node)
|
return mesecon.conductor_get_rules(node)
|
||||||
|
elseif mesecon.is_receptor(node.name) then
|
||||||
|
return mesecon.receptor_get_rules(node)
|
||||||
end
|
end
|
||||||
return false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:get_any_inputrules (node)
|
function mesecon.get_any_inputrules(node)
|
||||||
if mesecon:is_conductor(node.name) then
|
if not node then return nil end
|
||||||
return mesecon:conductor_get_rules(node)
|
|
||||||
elseif mesecon:is_effector(node.name) then
|
if mesecon.is_conductor(node.name) then
|
||||||
return mesecon:effector_get_rules(node)
|
return mesecon.conductor_get_rules(node)
|
||||||
|
elseif mesecon.is_effector(node.name) then
|
||||||
|
return mesecon.effector_get_rules(node)
|
||||||
end
|
end
|
||||||
return false
|
end
|
||||||
|
|
||||||
|
function mesecon.get_any_rules(node)
|
||||||
|
return mesecon.merge_rule_sets(mesecon.get_any_inputrules(node),
|
||||||
|
mesecon.get_any_outputrules(node))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Receptors
|
-- Receptors
|
||||||
-- Nodes that can power mesecons
|
-- Nodes that can power mesecons
|
||||||
function mesecon:is_receptor_on(nodename)
|
function mesecon.is_receptor_on(nodename)
|
||||||
local receptor = mesecon:get_receptor(nodename)
|
local receptor = mesecon.get_receptor(nodename)
|
||||||
if receptor and receptor.state == mesecon.state.on then
|
if receptor and receptor.state == mesecon.state.on then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:is_receptor_off(nodename)
|
function mesecon.is_receptor_off(nodename)
|
||||||
local receptor = mesecon:get_receptor(nodename)
|
local receptor = mesecon.get_receptor(nodename)
|
||||||
if receptor and receptor.state == mesecon.state.off then
|
if receptor and receptor.state == mesecon.state.off then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:is_receptor(nodename)
|
function mesecon.is_receptor(nodename)
|
||||||
local receptor = mesecon:get_receptor(nodename)
|
local receptor = mesecon.get_receptor(nodename)
|
||||||
if receptor then
|
if receptor then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:receptor_get_rules(node)
|
function mesecon.receptor_get_rules(node)
|
||||||
local receptor = mesecon:get_receptor(node.name)
|
local receptor = mesecon.get_receptor(node.name)
|
||||||
if receptor then
|
if receptor then
|
||||||
local rules = receptor.rules
|
local rules = receptor.rules
|
||||||
if type(rules) == 'function' then
|
if type(rules) == 'function' then
|
||||||
@ -140,32 +138,32 @@ end
|
|||||||
|
|
||||||
-- Effectors
|
-- Effectors
|
||||||
-- Nodes that can be powered by mesecons
|
-- Nodes that can be powered by mesecons
|
||||||
function mesecon:is_effector_on(nodename)
|
function mesecon.is_effector_on(nodename)
|
||||||
local effector = mesecon:get_effector(nodename)
|
local effector = mesecon.get_effector(nodename)
|
||||||
if effector and effector.action_off then
|
if effector and effector.action_off then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:is_effector_off(nodename)
|
function mesecon.is_effector_off(nodename)
|
||||||
local effector = mesecon:get_effector(nodename)
|
local effector = mesecon.get_effector(nodename)
|
||||||
if effector and effector.action_on then
|
if effector and effector.action_on then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:is_effector(nodename)
|
function mesecon.is_effector(nodename)
|
||||||
local effector = mesecon:get_effector(nodename)
|
local effector = mesecon.get_effector(nodename)
|
||||||
if effector then
|
if effector then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:effector_get_rules(node)
|
function mesecon.effector_get_rules(node)
|
||||||
local effector = mesecon:get_effector(node.name)
|
local effector = mesecon.get_effector(node.name)
|
||||||
if effector then
|
if effector then
|
||||||
local rules = effector.rules
|
local rules = effector.rules
|
||||||
if type(rules) == 'function' then
|
if type(rules) == 'function' then
|
||||||
@ -177,210 +175,168 @@ function mesecon:effector_get_rules(node)
|
|||||||
return mesecon.rules.default
|
return mesecon.rules.default
|
||||||
end
|
end
|
||||||
|
|
||||||
--Signals
|
-- #######################
|
||||||
|
-- # Signals (effectors) #
|
||||||
|
-- #######################
|
||||||
|
|
||||||
|
-- Activation:
|
||||||
|
mesecon.queue:add_function("activate", function (pos, rulename)
|
||||||
|
local node = mesecon.get_node_force(pos)
|
||||||
|
if not node then return end
|
||||||
|
|
||||||
|
local effector = mesecon.get_effector(node.name)
|
||||||
|
|
||||||
function mesecon:activate(pos, node, rulename)
|
|
||||||
if MESECONS_GLOBALSTEP then
|
|
||||||
if rulename == nil then
|
|
||||||
for _,rule in ipairs(mesecon:effector_get_rules(node)) do
|
|
||||||
mesecon:activate(pos, node, rule)
|
|
||||||
end
|
|
||||||
return
|
|
||||||
end
|
|
||||||
add_action(pos, "on", rulename)
|
|
||||||
else
|
|
||||||
local effector = mesecon:get_effector(node.name)
|
|
||||||
if effector and effector.action_on then
|
if effector and effector.action_on then
|
||||||
effector.action_on (pos, node, rulename)
|
effector.action_on(pos, node, rulename)
|
||||||
end
|
end
|
||||||
end
|
end)
|
||||||
end
|
|
||||||
|
|
||||||
function mesecon:deactivate(pos, node, rulename)
|
function mesecon.activate(pos, node, rulename, depth)
|
||||||
if MESECONS_GLOBALSTEP then
|
|
||||||
if rulename == nil then
|
if rulename == nil then
|
||||||
for _,rule in ipairs(mesecon:effector_get_rules(node)) do
|
for _,rule in ipairs(mesecon.effector_get_rules(node)) do
|
||||||
mesecon:deactivate(pos, node, rule)
|
mesecon.activate(pos, node, rule, depth + 1)
|
||||||
end
|
end
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
add_action(pos, "off", rulename)
|
mesecon.queue:add_action(pos, "activate", {rulename}, nil, rulename, 1 / depth)
|
||||||
else
|
|
||||||
local effector = mesecon:get_effector(node.name)
|
|
||||||
if effector and effector.action_off then
|
|
||||||
effector.action_off (pos, node, rulename)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:changesignal(pos, node, rulename, newstate)
|
|
||||||
|
|
||||||
newstate = newstate or "on"
|
-- Deactivation
|
||||||
--rulename = rulename or mesecon.rules.default
|
mesecon.queue:add_function("deactivate", function (pos, rulename)
|
||||||
if MESECONS_GLOBALSTEP then
|
local node = mesecon.get_node_force(pos)
|
||||||
|
if not node then return end
|
||||||
|
|
||||||
|
local effector = mesecon.get_effector(node.name)
|
||||||
|
|
||||||
|
if effector and effector.action_off then
|
||||||
|
effector.action_off(pos, node, rulename)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
function mesecon.deactivate(pos, node, rulename, depth)
|
||||||
if rulename == nil then
|
if rulename == nil then
|
||||||
for _,rule in ipairs(mesecon:effector_get_rules(node)) do
|
for _,rule in ipairs(mesecon.effector_get_rules(node)) do
|
||||||
mesecon:changesignal(pos, node, rule, newstate)
|
mesecon.deactivate(pos, node, rule, depth + 1)
|
||||||
end
|
end
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
add_action(pos, "c"..newstate, rulename)
|
mesecon.queue:add_action(pos, "deactivate", {rulename}, nil, rulename, 1 / depth)
|
||||||
else
|
end
|
||||||
local effector = mesecon:get_effector(node.name)
|
|
||||||
|
|
||||||
|
-- Change
|
||||||
|
mesecon.queue:add_function("change", function (pos, rulename, changetype)
|
||||||
|
local node = mesecon.get_node_force(pos)
|
||||||
|
if not node then return end
|
||||||
|
|
||||||
|
local effector = mesecon.get_effector(node.name)
|
||||||
|
|
||||||
if effector and effector.action_change then
|
if effector and effector.action_change then
|
||||||
effector.action_change (pos, node, rulename, newstate)
|
effector.action_change(pos, node, rulename, changetype)
|
||||||
end
|
end
|
||||||
end
|
end)
|
||||||
end
|
|
||||||
|
|
||||||
function execute_actions(dtime)
|
function mesecon.changesignal(pos, node, rulename, newstate, depth)
|
||||||
local nactions = mesecon.to_update
|
if rulename == nil then
|
||||||
mesecon.to_update = {}
|
for _,rule in ipairs(mesecon.effector_get_rules(node)) do
|
||||||
for _,i in ipairs(nactions) do
|
mesecon.changesignal(pos, node, rule, newstate, depth + 1)
|
||||||
node = minetest.get_node(i.pos)
|
|
||||||
if node.name=="ignore" then
|
|
||||||
add_action(i.pos, i.action, i.rname)
|
|
||||||
else
|
|
||||||
effector = mesecon:get_effector(node.name)
|
|
||||||
if i.action == "on" then
|
|
||||||
if effector and effector.action_on then
|
|
||||||
effector.action_on(i.pos, node, i.rname)
|
|
||||||
end
|
end
|
||||||
elseif i.action == "off" then
|
return
|
||||||
if effector and effector.action_off then
|
|
||||||
effector.action_off(i.pos, node, i.rname)
|
|
||||||
end
|
end
|
||||||
elseif i.action == "con" then
|
|
||||||
if effector and effector.action_change then
|
|
||||||
effector.action_change(i.pos, node, i.rname, "on")
|
|
||||||
end
|
|
||||||
elseif i.action == "coff" then
|
|
||||||
if effector and effector.action_change then
|
|
||||||
effector.action_change(i.pos, node, i.rname, "off")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local nactions = mesecon.r_to_update
|
|
||||||
mesecon.r_to_update = {}
|
|
||||||
for _,i in ipairs(nactions) do
|
|
||||||
if i.action == "on" then
|
|
||||||
mesecon:receptor_on_i(i.pos, i.rules)
|
|
||||||
else
|
|
||||||
mesecon:receptor_off_i(i.pos,i.rules)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
minetest.register_globalstep(execute_actions)
|
-- Include "change" in overwritecheck so that it cannot be overwritten
|
||||||
|
-- by "active" / "deactivate" that will be called upon the node at the same time.
|
||||||
function add_action(pos, action, rname)
|
local overwritecheck = {"change", rulename}
|
||||||
for _,i in ipairs(mesecon.to_update) do
|
mesecon.queue:add_action(pos, "change", {rulename, newstate}, nil, overwritecheck, 1 / depth)
|
||||||
if i.pos.x == pos.x and i.pos.y == pos.y and i.pos.z == pos.z and i.rname.x == rname.x and i.rname.y == rname.y and i.rname.z == rname.z then
|
|
||||||
if (i.action == "on" and action == "on") or (i.action == "off" and action == "off") then
|
|
||||||
--nothing
|
|
||||||
elseif i.action == "coff" and action == "on" then i.action = "on"
|
|
||||||
elseif i.action == "con" and action == "off" then i.action = "off"
|
|
||||||
else
|
|
||||||
if action == "on" or action == "con" then i.action = "con" end
|
|
||||||
if action == "off" or action == "coff" then i.action = "coff" end
|
|
||||||
end
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
mesecon.to_update[#mesecon.to_update+1] = {pos = pos, action = action, rname = rname}
|
|
||||||
end
|
|
||||||
|
|
||||||
--Rules
|
|
||||||
|
|
||||||
function mesecon:add_rules(name, rules)
|
|
||||||
mesecon.rules[name] = rules
|
|
||||||
end
|
|
||||||
|
|
||||||
function mesecon:get_rules(name)
|
|
||||||
return mesecon.rules[name]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Conductors
|
-- Conductors
|
||||||
|
|
||||||
function mesecon:is_conductor_on(node, rulename)
|
function mesecon.is_conductor_on(node, rulename)
|
||||||
local conductor = mesecon:get_conductor(node.name)
|
if not node then return false end
|
||||||
|
|
||||||
|
local conductor = mesecon.get_conductor(node.name)
|
||||||
if conductor then
|
if conductor then
|
||||||
if conductor.state then
|
if conductor.state then
|
||||||
return conductor.state == mesecon.state.on
|
return conductor.state == mesecon.state.on
|
||||||
end
|
end
|
||||||
if conductor.states then
|
if conductor.states then
|
||||||
if not rulename then
|
if not rulename then
|
||||||
return mesecon:getstate(node.name, conductor.states) ~= 1
|
return mesecon.getstate(node.name, conductor.states) ~= 1
|
||||||
end
|
end
|
||||||
local bit = mesecon:rule2bit(rulename, mesecon:conductor_get_rules(node))
|
local bit = mesecon.rule2bit(rulename, mesecon.conductor_get_rules(node))
|
||||||
local binstate = mesecon:getbinstate(node.name, conductor.states)
|
local binstate = mesecon.getbinstate(node.name, conductor.states)
|
||||||
return mesecon:get_bit(binstate, bit)
|
return mesecon.get_bit(binstate, bit)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:is_conductor_off(node, rulename)
|
function mesecon.is_conductor_off(node, rulename)
|
||||||
local conductor = mesecon:get_conductor(node.name)
|
if not node then return false end
|
||||||
|
|
||||||
|
local conductor = mesecon.get_conductor(node.name)
|
||||||
if conductor then
|
if conductor then
|
||||||
if conductor.state then
|
if conductor.state then
|
||||||
return conductor.state == mesecon.state.off
|
return conductor.state == mesecon.state.off
|
||||||
end
|
end
|
||||||
if conductor.states then
|
if conductor.states then
|
||||||
if not rulename then
|
if not rulename then
|
||||||
return mesecon:getstate(node.name, conductor.states) == 1
|
return mesecon.getstate(node.name, conductor.states) == 1
|
||||||
end
|
end
|
||||||
local bit = mesecon:rule2bit(rulename, mesecon:conductor_get_rules(node))
|
local bit = mesecon.rule2bit(rulename, mesecon.conductor_get_rules(node))
|
||||||
local binstate = mesecon:getbinstate(node.name, conductor.states)
|
local binstate = mesecon.getbinstate(node.name, conductor.states)
|
||||||
return not mesecon:get_bit(binstate, bit)
|
return not mesecon.get_bit(binstate, bit)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:is_conductor(nodename)
|
function mesecon.is_conductor(nodename)
|
||||||
local conductor = mesecon:get_conductor(nodename)
|
local conductor = mesecon.get_conductor(nodename)
|
||||||
if conductor then
|
if conductor then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:get_conductor_on(node_off, rulename)
|
function mesecon.get_conductor_on(node_off, rulename)
|
||||||
local conductor = mesecon:get_conductor(node_off.name)
|
local conductor = mesecon.get_conductor(node_off.name)
|
||||||
if conductor then
|
if conductor then
|
||||||
if conductor.onstate then
|
if conductor.onstate then
|
||||||
return conductor.onstate
|
return conductor.onstate
|
||||||
end
|
end
|
||||||
if conductor.states then
|
if conductor.states then
|
||||||
local bit = mesecon:rule2bit(rulename, mesecon:conductor_get_rules(node_off))
|
local bit = mesecon.rule2bit(rulename, mesecon.conductor_get_rules(node_off))
|
||||||
local binstate = mesecon:getbinstate(node_off.name, conductor.states)
|
local binstate = mesecon.getbinstate(node_off.name, conductor.states)
|
||||||
binstate = mesecon:set_bit(binstate, bit, "1")
|
binstate = mesecon.set_bit(binstate, bit, "1")
|
||||||
return conductor.states[tonumber(binstate,2)+1]
|
return conductor.states[tonumber(binstate,2)+1]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return offstate
|
return offstate
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:get_conductor_off(node_on, rulename)
|
function mesecon.get_conductor_off(node_on, rulename)
|
||||||
local conductor = mesecon:get_conductor(node_on.name)
|
local conductor = mesecon.get_conductor(node_on.name)
|
||||||
if conductor then
|
if conductor then
|
||||||
if conductor.offstate then
|
if conductor.offstate then
|
||||||
return conductor.offstate
|
return conductor.offstate
|
||||||
end
|
end
|
||||||
if conductor.states then
|
if conductor.states then
|
||||||
local bit = mesecon:rule2bit(rulename, mesecon:conductor_get_rules(node_on))
|
local bit = mesecon.rule2bit(rulename, mesecon.conductor_get_rules(node_on))
|
||||||
local binstate = mesecon:getbinstate(node_on.name, conductor.states)
|
local binstate = mesecon.getbinstate(node_on.name, conductor.states)
|
||||||
binstate = mesecon:set_bit(binstate, bit, "0")
|
binstate = mesecon.set_bit(binstate, bit, "0")
|
||||||
return conductor.states[tonumber(binstate,2)+1]
|
return conductor.states[tonumber(binstate,2)+1]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return onstate
|
return onstate
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:conductor_get_rules(node)
|
function mesecon.conductor_get_rules(node)
|
||||||
local conductor = mesecon:get_conductor(node.name)
|
local conductor = mesecon.get_conductor(node.name)
|
||||||
if conductor then
|
if conductor then
|
||||||
local rules = conductor.rules
|
local rules = conductor.rules
|
||||||
if type(rules) == 'function' then
|
if type(rules) == 'function' then
|
||||||
@ -394,308 +350,201 @@ end
|
|||||||
|
|
||||||
-- some more general high-level stuff
|
-- some more general high-level stuff
|
||||||
|
|
||||||
function mesecon:is_power_on(pos, rulename)
|
function mesecon.is_power_on(pos, rulename)
|
||||||
local node = minetest.get_node(pos)
|
local node = mesecon.get_node_force(pos)
|
||||||
if mesecon:is_conductor_on(node, rulename) or mesecon:is_receptor_on(node.name) then
|
if node and (mesecon.is_conductor_on(node, rulename) or mesecon.is_receptor_on(node.name)) then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:is_power_off(pos, rulename)
|
function mesecon.is_power_off(pos, rulename)
|
||||||
local node = minetest.get_node(pos)
|
local node = mesecon.get_node_force(pos)
|
||||||
if mesecon:is_conductor_off(node, rulename) or mesecon:is_receptor_off(node.name) then
|
if node and (mesecon.is_conductor_off(node, rulename) or mesecon.is_receptor_off(node.name)) then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:turnon(pos, rulename)
|
-- Turn off an equipotential section starting at `pos`, which outputs in the direction of `link`.
|
||||||
local node = minetest.get_node(pos)
|
-- 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)
|
||||||
|
local frontiers = {{pos = pos, link = link}}
|
||||||
|
|
||||||
if mesecon:is_conductor_off(node, rulename) then
|
local depth = 1
|
||||||
local rules = mesecon:conductor_get_rules(node)
|
while frontiers[1] do
|
||||||
|
local f = table.remove(frontiers, 1)
|
||||||
|
local node = mesecon.get_node_force(f.pos)
|
||||||
|
|
||||||
if not rulename then
|
if not node then
|
||||||
for _, rule in ipairs(mesecon:flattenrules(rules)) do
|
-- Area does not exist; do nothing
|
||||||
if mesecon:connected_to_receptor(pos, rule) then
|
elseif mesecon.is_conductor_off(node, f.link) then
|
||||||
mesecon:turnon(pos, rule)
|
local rules = mesecon.conductor_get_rules(node)
|
||||||
|
|
||||||
|
-- Call turnon on neighbors
|
||||||
|
for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do
|
||||||
|
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})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
minetest.swap_node(pos, {name = mesecon:get_conductor_on(node, rulename), param2 = node.param2})
|
mesecon.swap_node_force(f.pos, mesecon.get_conductor_on(node, f.link))
|
||||||
|
elseif mesecon.is_effector(node.name) then
|
||||||
for _, rule in ipairs(mesecon:rule2meta(rulename, rules)) do
|
mesecon.changesignal(f.pos, node, f.link, mesecon.state.on, depth)
|
||||||
local np = mesecon:addPosRule(pos, rule)
|
if mesecon.is_effector_off(node.name) then
|
||||||
local rulenames = mesecon:rules_link_rule_all(pos, rule)
|
mesecon.activate(f.pos, node, f.link, depth)
|
||||||
|
|
||||||
for _, rulename in ipairs(rulenames) do
|
|
||||||
mesecon:turnon(np, rulename)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif mesecon:is_effector(node.name) then
|
depth = depth + 1
|
||||||
mesecon:changesignal(pos, node, rulename, mesecon.state.on)
|
|
||||||
if mesecon:is_effector_off(node.name) then
|
|
||||||
mesecon:activate(pos, node, rulename)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:turnoff(pos, rulename)
|
-- Turn on an equipotential section starting at `pos`, which outputs in the direction of `link`.
|
||||||
local node = minetest.get_node(pos)
|
-- Breadth-first search. Map is abstracted away in a voxelmanip.
|
||||||
|
-- Follow all all conductor paths replacing conductors that were already
|
||||||
|
-- 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)
|
||||||
|
local frontiers = {{pos = pos, link = link}}
|
||||||
|
local signals = {}
|
||||||
|
|
||||||
if mesecon:is_conductor_on(node, rulename) then
|
local depth = 1
|
||||||
local rules = mesecon:conductor_get_rules(node)
|
while frontiers[1] do
|
||||||
--[[
|
local f = table.remove(frontiers, 1)
|
||||||
if not rulename then
|
local node = mesecon.get_node_force(f.pos)
|
||||||
for _, rule in ipairs(mesecon:flattenrules(rules)) do
|
|
||||||
if mesecon:is_powered(pos, rule) then
|
|
||||||
mesecon:turnoff(pos, rule)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return
|
|
||||||
end
|
|
||||||
--]]
|
|
||||||
minetest.swap_node(pos, {name = mesecon:get_conductor_off(node, rulename), param2 = node.param2})
|
|
||||||
|
|
||||||
for _, rule in ipairs(mesecon:rule2meta(rulename, rules)) do
|
if not node then
|
||||||
local np = mesecon:addPosRule(pos, rule)
|
-- Area does not exist; do nothing
|
||||||
local rulenames = mesecon:rules_link_rule_all(pos, rule)
|
elseif mesecon.is_conductor_on(node, f.link) then
|
||||||
|
local rules = mesecon.conductor_get_rules(node)
|
||||||
for _, rulename in ipairs(rulenames) do
|
for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do
|
||||||
mesecon:turnoff(np, rulename)
|
local np = vector.add(f.pos, r)
|
||||||
end
|
|
||||||
end
|
|
||||||
elseif mesecon:is_effector(node.name) then
|
|
||||||
mesecon:changesignal(pos, node, rulename, mesecon.state.off)
|
|
||||||
if mesecon:is_effector_on(node.name)
|
|
||||||
and not mesecon:is_powered(pos) then
|
|
||||||
mesecon:deactivate(pos, node, rulename)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function mesecon:connected_to_receptor(pos, rulename)
|
|
||||||
local node = minetest.get_node(pos)
|
|
||||||
|
|
||||||
-- 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(rulename, rules)) do
|
|
||||||
local np = mesecon:addPosRule(pos, rule)
|
|
||||||
if mesecon:rules_link(np, pos) then
|
|
||||||
if mesecon:find_receptor_on(np, {}, mesecon:invertRule(rule)) then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
-- Check if an onstate receptor is connected. If that is the case,
|
||||||
|
-- abort this turnoff process by returning false. `receptor_off` will
|
||||||
|
-- discard all the changes that we made in the voxelmanip:
|
||||||
|
for _, l in ipairs(mesecon.rules_link_rule_all_inverted(f.pos, r)) do
|
||||||
|
if mesecon.is_receptor_on(mesecon.get_node_force(np).name) then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function mesecon:find_receptor_on(pos, checked, rulename)
|
-- Call turnoff on neighbors
|
||||||
local node = minetest.get_node(pos)
|
for _, l in ipairs(mesecon.rules_link_rule_all(f.pos, r)) do
|
||||||
|
table.insert(frontiers, {pos = np, link = l})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
mesecon.swap_node_force(f.pos, mesecon.get_conductor_off(node, f.link))
|
||||||
|
elseif mesecon.is_effector(node.name) then
|
||||||
|
table.insert(signals, {
|
||||||
|
pos = f.pos,
|
||||||
|
node = node,
|
||||||
|
link = f.link,
|
||||||
|
depth = depth
|
||||||
|
})
|
||||||
|
end
|
||||||
|
depth = depth + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, sig in ipairs(signals) do
|
||||||
|
mesecon.changesignal(sig.pos, sig.node, sig.link, mesecon.state.off, sig.depth)
|
||||||
|
if mesecon.is_effector_on(sig.node.name) and not mesecon.is_powered(sig.pos) then
|
||||||
|
mesecon.deactivate(sig.pos, sig.node, sig.link, sig.depth)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if mesecon:is_receptor_on(node.name) then
|
|
||||||
-- add current position to checked
|
|
||||||
table.insert(checked, {x=pos.x, y=pos.y, z=pos.z})
|
|
||||||
return true
|
return true
|
||||||
end
|
|
||||||
|
|
||||||
if mesecon:is_conductor(node.name) then
|
|
||||||
local rules = mesecon:conductor_get_rules(node)
|
|
||||||
local metaindex = mesecon:rule2metaindex(rulename, rules)
|
|
||||||
-- find out if node has already been checked (to prevent from endless loop)
|
|
||||||
for _, cp in ipairs(checked) do
|
|
||||||
if mesecon:cmpPos(cp, pos) and cp.metaindex == metaindex then
|
|
||||||
return false, checked
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- add current position to checked
|
|
||||||
table.insert(checked, {x=pos.x, y=pos.y, z=pos.z, metaindex = metaindex})
|
|
||||||
for _, rule in ipairs(mesecon:rule2meta(rulename, rules)) do
|
|
||||||
local np = mesecon:addPosRule(pos, rule)
|
|
||||||
if mesecon:rules_link(np, pos) then
|
|
||||||
if mesecon:find_receptor_on(np, checked, mesecon:invertRule(rule)) then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
-- find out if node has already been checked (to prevent from endless loop)
|
|
||||||
for _, cp in ipairs(checked) do
|
|
||||||
if mesecon:cmpPos(cp, pos) then
|
|
||||||
return false, checked
|
|
||||||
end
|
|
||||||
end
|
|
||||||
table.insert(checked, {x=pos.x, y=pos.y, z=pos.z})
|
|
||||||
end
|
|
||||||
|
|
||||||
return false
|
|
||||||
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
|
-- Get all linking inputrules of inputnode (effector or conductor) that is connected to
|
||||||
local outputnode = minetest.get_node(output)
|
-- outputnode (receptor or conductor) at position `output` and has an output in direction `rule`
|
||||||
local inputnode = minetest.get_node(input)
|
function mesecon.rules_link_rule_all(output, rule)
|
||||||
local outputrules = dug_outputrules or mesecon:get_any_outputrules (outputnode)
|
local input = vector.add(output, rule)
|
||||||
local inputrules = mesecon:get_any_inputrules (inputnode)
|
local inputnode = mesecon.get_node_force(input)
|
||||||
if not outputrules or not inputrules then
|
local inputrules = mesecon.get_any_inputrules(inputnode)
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
for _, outputrule in ipairs(mesecon:flattenrules(outputrules)) do
|
|
||||||
-- Check if output sends to input
|
|
||||||
if mesecon:cmpPos(mesecon:addPosRule(output, outputrule), input) then
|
|
||||||
for _, inputrule in ipairs(mesecon:flattenrules(inputrules)) do
|
|
||||||
-- Check if input accepts from output
|
|
||||||
if mesecon:cmpPos(mesecon:addPosRule(input, inputrule), output) then
|
|
||||||
if inputrule.sx == nil or outputrule.sx == nil or mesecon:cmpSpecial(inputrule, outputrule) then
|
|
||||||
return true, inputrule
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
function mesecon:rules_link_rule_all(output, rule) --output/input are positions (outputrules optional, used if node has been dug), second return value: affected input rules
|
|
||||||
local input = mesecon:addPosRule(output, rule)
|
|
||||||
local inputnode = minetest.get_node(input)
|
|
||||||
local inputrules = mesecon:get_any_inputrules (inputnode)
|
|
||||||
if not inputrules then
|
if not inputrules then
|
||||||
return {}
|
return {}
|
||||||
end
|
end
|
||||||
local rules = {}
|
local rules = {}
|
||||||
|
|
||||||
for _, inputrule in ipairs(mesecon:flattenrules(inputrules)) do
|
for _, inputrule in ipairs(mesecon.flattenrules(inputrules)) do
|
||||||
-- Check if input accepts from output
|
-- Check if input accepts from output
|
||||||
if mesecon:cmpPos(mesecon:addPosRule(input, inputrule), output) then
|
if vector.equals(vector.add(input, inputrule), output) then
|
||||||
if inputrule.sx == nil or rule.sx == nil or mesecon:cmpSpecial(inputrule, rule) then
|
table.insert(rules, inputrule)
|
||||||
rules[#rules+1] = inputrule
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return rules
|
||||||
|
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)
|
||||||
|
local output = vector.add(input, rule)
|
||||||
|
local outputnode = mesecon.get_node_force(output)
|
||||||
|
local outputrules = mesecon.get_any_outputrules(outputnode)
|
||||||
|
if not outputrules then
|
||||||
|
return {}
|
||||||
|
end
|
||||||
|
local rules = {}
|
||||||
|
|
||||||
|
for _, outputrule in ipairs(mesecon.flattenrules(outputrules)) do
|
||||||
|
if vector.equals(vector.add(output, outputrule), input) then
|
||||||
|
table.insert(rules, mesecon.invertRule(outputrule))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return rules
|
return rules
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:rules_link_anydir(pos1, pos2)
|
function mesecon.is_powered(pos, rule)
|
||||||
return mesecon:rules_link(pos1, pos2) or mesecon:rules_link(pos2, pos1)
|
local node = mesecon.get_node_force(pos)
|
||||||
end
|
local rules = mesecon.get_any_inputrules(node)
|
||||||
|
|
||||||
function mesecon:is_powered(pos, rule)
|
|
||||||
local node = minetest.get_node(pos)
|
|
||||||
local rules = mesecon:get_any_inputrules(node)
|
|
||||||
if not rules then return false end
|
if not rules then return false end
|
||||||
|
|
||||||
|
-- List of nodes that send out power to pos
|
||||||
|
local sourcepos = {}
|
||||||
|
|
||||||
if not rule then
|
if not rule then
|
||||||
for _, rule in ipairs(mesecon:flattenrules(rules)) do
|
for _, rule in ipairs(mesecon.flattenrules(rules)) do
|
||||||
local np = mesecon:addPosRule(pos, rule)
|
local rulenames = mesecon.rules_link_rule_all_inverted(pos, rule)
|
||||||
local nn = minetest.get_node(np)
|
for _, rname in ipairs(rulenames) do
|
||||||
|
local np = vector.add(pos, rname)
|
||||||
|
local nn = mesecon.get_node_force(np)
|
||||||
|
|
||||||
if (mesecon:is_conductor_on (nn, mesecon:invertRule(rule)) or mesecon:is_receptor_on (nn.name))
|
if (mesecon.is_conductor_on(nn, mesecon.invertRule(rname))
|
||||||
and mesecon:rules_link(np, pos) then
|
or mesecon.is_receptor_on(nn.name)) then
|
||||||
return true
|
table.insert(sourcepos, np)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local np = mesecon:addPosRule(pos, rule)
|
local rulenames = mesecon.rules_link_rule_all_inverted(pos, rule)
|
||||||
local nn = minetest.get_node(np)
|
for _, rname in ipairs(rulenames) do
|
||||||
|
local np = vector.add(pos, rname)
|
||||||
if (mesecon:is_conductor_on (nn, mesecon:invertRule(rule)) or mesecon:is_receptor_on (nn.name))
|
local nn = mesecon.get_node_force(np)
|
||||||
and mesecon:rules_link(np, pos) then
|
if (mesecon.is_conductor_on (nn, mesecon.invertRule(rname))
|
||||||
return true
|
or mesecon.is_receptor_on (nn.name)) then
|
||||||
|
table.insert(sourcepos, np)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return false
|
-- Return FALSE if not powered, return list of sources if is powered
|
||||||
end
|
if (#sourcepos == 0) then return false
|
||||||
|
else return sourcepos end
|
||||||
--Rules rotation Functions:
|
|
||||||
function mesecon:rotate_rules_right(rules)
|
|
||||||
local nr = {}
|
|
||||||
for i, rule in ipairs(rules) do
|
|
||||||
if rule.sx then
|
|
||||||
table.insert(nr, {
|
|
||||||
x = -rule.z,
|
|
||||||
y = rule.y,
|
|
||||||
z = rule.x,
|
|
||||||
sx = -rule.sz,
|
|
||||||
sy = rule.sy,
|
|
||||||
sz = rule.sx})
|
|
||||||
else
|
|
||||||
table.insert(nr, {
|
|
||||||
x = -rule.z,
|
|
||||||
y = rule.y,
|
|
||||||
z = rule.x})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return nr
|
|
||||||
end
|
|
||||||
|
|
||||||
function mesecon:rotate_rules_left(rules)
|
|
||||||
local nr = {}
|
|
||||||
for i, rule in ipairs(rules) do
|
|
||||||
if rule.sx then
|
|
||||||
table.insert(nr, {
|
|
||||||
x = rule.z,
|
|
||||||
y = rule.y,
|
|
||||||
z = -rule.x,
|
|
||||||
sx = rule.sz,
|
|
||||||
sy = rule.sy,
|
|
||||||
sz = -rule.sx})
|
|
||||||
else
|
|
||||||
table.insert(nr, {
|
|
||||||
x = rule.z,
|
|
||||||
y = rule.y,
|
|
||||||
z = -rule.x})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return nr
|
|
||||||
end
|
|
||||||
|
|
||||||
function mesecon:rotate_rules_down(rules)
|
|
||||||
local nr = {}
|
|
||||||
for i, rule in ipairs(rules) do
|
|
||||||
if rule.sx then
|
|
||||||
table.insert(nr, {
|
|
||||||
x = -rule.y,
|
|
||||||
y = rule.x,
|
|
||||||
z = rule.z,
|
|
||||||
sx = -rule.sy,
|
|
||||||
sy = rule.sx,
|
|
||||||
sz = rule.sz})
|
|
||||||
else
|
|
||||||
table.insert(nr, {
|
|
||||||
x = -rule.y,
|
|
||||||
y = rule.x,
|
|
||||||
z = rule.z})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return nr
|
|
||||||
end
|
|
||||||
|
|
||||||
function mesecon:rotate_rules_up(rules)
|
|
||||||
local nr = {}
|
|
||||||
for i, rule in ipairs(rules) do
|
|
||||||
if rule.sx then
|
|
||||||
table.insert(nr, {
|
|
||||||
x = rule.y,
|
|
||||||
y = -rule.x,
|
|
||||||
z = rule.z,
|
|
||||||
sx = rule.sy,
|
|
||||||
sy = -rule.sx,
|
|
||||||
sz = rule.sz})
|
|
||||||
else
|
|
||||||
table.insert(nr, {
|
|
||||||
x = rule.y,
|
|
||||||
y = -rule.x,
|
|
||||||
z = rule.z})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return nr
|
|
||||||
end
|
end
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
minetest.swap_node = minetest.swap_node or function(pos, node)
|
-- Un-forceload any forceloaded mapblocks from older versions of Mesecons which
|
||||||
local data = minetest.get_meta(pos):to_table()
|
-- used forceloading instead of VoxelManipulators.
|
||||||
minetest.add_node(pos, node)
|
local BLOCKSIZE = 16
|
||||||
minetest.get_meta(pos):from_table(data)
|
|
||||||
|
-- convert block hash --> node position
|
||||||
|
local function unhash_blockpos(hash)
|
||||||
|
return vector.multiply(minetest.get_position_from_hash(hash), BLOCKSIZE)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local old_forceloaded_blocks = mesecon.file2table("mesecon_forceloaded")
|
||||||
|
for hash, _ in pairs(old_forceloaded_blocks) do
|
||||||
|
minetest.forceload_free_block(unhash_blockpos(hash))
|
||||||
|
end
|
||||||
|
os.remove(minetest.get_worldpath()..DIR_DELIM.."mesecon_forceloaded")
|
||||||
|
2
mesecons/mod.conf
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
name = mesecons
|
||||||
|
depends = default
|
@ -4,7 +4,7 @@ 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 = true,
|
is_ground_content = false,
|
||||||
walkable = false,
|
walkable = false,
|
||||||
selection_box = {
|
selection_box = {
|
||||||
type = "fixed",
|
type = "fixed",
|
||||||
@ -22,7 +22,7 @@ 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 = true,
|
is_ground_content = false,
|
||||||
walkable = false,
|
walkable = false,
|
||||||
selection_box = {
|
selection_box = {
|
||||||
type = "fixed",
|
type = "fixed",
|
||||||
@ -30,7 +30,7 @@ minetest.register_node("mesecons:mesecon_on", {
|
|||||||
},
|
},
|
||||||
groups = {dig_immediate=3, not_in_creaive_inventory=1, mesecon=1},
|
groups = {dig_immediate=3, not_in_creaive_inventory=1, mesecon=1},
|
||||||
drop = "mesecons:mesecon_off 1",
|
drop = "mesecons:mesecon_off 1",
|
||||||
light_source = LIGHT_MAX-11,
|
light_source = minetest.LIGHT_MAX-11,
|
||||||
mesecons = {conductor={
|
mesecons = {conductor={
|
||||||
state = mesecon.state.on,
|
state = mesecon.state.on,
|
||||||
offstate = "mesecons:mesecon_off"
|
offstate = "mesecons:mesecon_off"
|
||||||
|
@ -1,44 +1,85 @@
|
|||||||
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=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}}
|
|
||||||
|
|
||||||
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.flat =
|
|
||||||
{{x = 1, y = 0, z = 0},
|
|
||||||
{x =-1, y = 0, z = 0},
|
|
||||||
{x = 0, y = 0, z = 1},
|
{x = 0, y = 0, z = 1},
|
||||||
{x = 0, y = 0, z =-1}}
|
{x = 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},
|
||||||
|
}
|
||||||
|
|
||||||
|
mesecon.rules.floor = mesecon.merge_rule_sets(mesecon.rules.default, {{x = 0, y = -1, z = 0}})
|
||||||
|
|
||||||
|
mesecon.rules.pplate = mesecon.merge_rule_sets(mesecon.rules.floor, {{x = 0, y = -2, z = 0}})
|
||||||
|
|
||||||
|
mesecon.rules.buttonlike = {
|
||||||
|
{x = 1, y = 0, z = 0},
|
||||||
|
{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.flat = {
|
||||||
|
{x = 1, y = 0, z = 0},
|
||||||
|
{x = -1, y = 0, z = 0},
|
||||||
|
{x = 0, y = 0, z = 1},
|
||||||
|
{x = 0, y = 0, z = -1},
|
||||||
|
}
|
||||||
|
|
||||||
|
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 rules = mesecon.rules.buttonlike
|
local dir = minetest.facedir_to_dir(node.param2)
|
||||||
if node.param2 == 2 then
|
return rules_from_dir(rules_buttonlike, dir)
|
||||||
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"
|
||||||
|
@ -1,38 +1,136 @@
|
|||||||
mesecon.on_placenode = function (pos, node)
|
-- Dig and place services
|
||||||
if mesecon:is_receptor_on(node.name) then
|
|
||||||
mesecon:receptor_on(pos, mesecon:receptor_get_rules(node))
|
mesecon.on_placenode = function(pos, node)
|
||||||
elseif mesecon:is_powered(pos) then
|
mesecon.execute_autoconnect_hooks_now(pos, node)
|
||||||
if mesecon:is_conductor(node.name) then
|
|
||||||
mesecon:turnon (pos)
|
-- Receptors: Send on signal when active
|
||||||
--mesecon:receptor_on (pos, mesecon:conductor_get_rules(node))
|
if mesecon.is_receptor_on(node.name) then
|
||||||
|
mesecon.receptor_on(pos, mesecon.receptor_get_rules(node))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Conductors: Send turnon signal when powered or replace by respective offstate conductor
|
||||||
|
-- if placed conductor is an onstate one
|
||||||
|
if mesecon.is_conductor(node.name) then
|
||||||
|
local sources = mesecon.is_powered(pos)
|
||||||
|
if sources then
|
||||||
|
-- also call receptor_on if itself is powered already, so that neighboring
|
||||||
|
-- conductors will be activated (when pushing an on-conductor with a piston)
|
||||||
|
for _, s in ipairs(sources) do
|
||||||
|
local rule = vector.subtract(pos, s)
|
||||||
|
mesecon.turnon(pos, rule)
|
||||||
|
end
|
||||||
|
--mesecon.receptor_on (pos, mesecon.conductor_get_rules(node))
|
||||||
|
elseif mesecon.is_conductor_on(node) then
|
||||||
|
node.name = mesecon.get_conductor_off(node)
|
||||||
|
minetest.swap_node(pos, node)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Effectors: Send changesignal and activate or deactivate
|
||||||
|
if mesecon.is_effector(node.name) then
|
||||||
|
local powered_rules = {}
|
||||||
|
local unpowered_rules = {}
|
||||||
|
|
||||||
|
-- for each input rule, check if powered
|
||||||
|
for _, r in ipairs(mesecon.effector_get_rules(node)) do
|
||||||
|
local powered = mesecon.is_powered(pos, r)
|
||||||
|
if powered then table.insert(powered_rules, r)
|
||||||
|
else table.insert(unpowered_rules, r) end
|
||||||
|
|
||||||
|
local state = powered and mesecon.state.on or mesecon.state.off
|
||||||
|
mesecon.changesignal(pos, node, r, state, 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
if (#powered_rules > 0) then
|
||||||
|
for _, r in ipairs(powered_rules) do
|
||||||
|
mesecon.activate(pos, node, r, 1)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
mesecon:changesignal(pos, node, mesecon:effector_get_rules(node), "on")
|
for _, r in ipairs(unpowered_rules) do
|
||||||
mesecon:activate(pos, node)
|
mesecon.deactivate(pos, node, r, 1)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
elseif mesecon:is_conductor_on(node) then
|
|
||||||
minetest.swap_node(pos, {name = mesecon:get_conductor_off(node)})
|
|
||||||
elseif mesecon:is_effector_on (node.name) then
|
|
||||||
mesecon:deactivate(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_i(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.execute_autoconnect_hooks_queue(pos, node)
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_abm({
|
function mesecon.on_blastnode(pos, intensity)
|
||||||
nodenames = {"group:overheat"},
|
local node = minetest.get_node(pos)
|
||||||
interval = 1.0,
|
minetest.remove_node(pos)
|
||||||
chance = 1,
|
mesecon.on_dignode(pos, node)
|
||||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
return minetest.get_node_drops(node.name, "")
|
||||||
local meta = minetest.get_meta(pos)
|
end
|
||||||
meta:set_int("heat",0)
|
|
||||||
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
|
||||||
|
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
|
||||||
|
function mesecon.do_overheat(pos)
|
||||||
|
local id = minetest.hash_node_position(pos)
|
||||||
|
local heat = (object_heat[id] or 0) + 1
|
||||||
|
object_heat[id] = heat
|
||||||
|
if heat >= OVERHEAT_MAX then
|
||||||
|
minetest.log("action", "Node overheats at " .. minetest.pos_to_string(pos))
|
||||||
|
object_heat[id] = nil
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function mesecon.do_cooldown(pos)
|
||||||
|
local id = minetest.hash_node_position(pos)
|
||||||
|
object_heat[id] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function mesecon.get_heat(pos)
|
||||||
|
local id = minetest.hash_node_position(pos)
|
||||||
|
return object_heat[id] or 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function mesecon.move_hot_nodes(moved_nodes)
|
||||||
|
local new_heat = {}
|
||||||
|
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
|
||||||
|
for id, heat in pairs(new_heat) do
|
||||||
|
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)
|
||||||
|
@ -1,9 +1,15 @@
|
|||||||
-- SETTINGS
|
-- SETTINGS
|
||||||
BLINKY_PLANT_INTERVAL = 3
|
function mesecon.setting(setting, default)
|
||||||
NEW_STYLE_WIRES = true -- true = new nodebox wires, false = old raillike wires
|
if type(default) == "boolean" then
|
||||||
PRESSURE_PLATE_INTERVAL = 0.1
|
local read = minetest.settings:get_bool("mesecon."..setting)
|
||||||
OBJECT_DETECTOR_RADIUS = 6
|
if read == nil then
|
||||||
PISTON_MAXIMUM_PUSH = 15
|
return default
|
||||||
MOVESTONE_MAXIMUM_PUSH = 100
|
else
|
||||||
MESECONS_GLOBALSTEP = true -- true = receptors/effectors won't be updated
|
return read
|
||||||
-- until next globalstep, decreases server load
|
end
|
||||||
|
elseif type(default) == "string" then
|
||||||
|
return minetest.settings:get("mesecon."..setting) or default
|
||||||
|
elseif type(default) == "number" then
|
||||||
|
return tonumber(minetest.settings:get("mesecon."..setting) or default)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
BIN
mesecons/textures/jeija_close_window.png
Normal file
After Width: | Height: | Size: 191 B |
BIN
mesecons/textures/jeija_microcontroller_LED_A.png
Normal file
After Width: | Height: | Size: 844 B |
BIN
mesecons/textures/jeija_microcontroller_LED_B.png
Normal file
After Width: | Height: | Size: 838 B |
BIN
mesecons/textures/jeija_microcontroller_LED_C.png
Normal file
After Width: | Height: | Size: 851 B |
BIN
mesecons/textures/jeija_microcontroller_LED_D.png
Normal file
After Width: | Height: | Size: 846 B |
BIN
mesecons/textures/jeija_microcontroller_bottom.png
Normal file
After Width: | Height: | Size: 222 B |
BIN
mesecons/textures/jeija_microcontroller_sides.png
Normal file
After Width: | Height: | Size: 504 B |
BIN
mesecons/textures/mesecons_wire_inv.png
Normal file
After Width: | Height: | Size: 144 B |
BIN
mesecons/textures/mesecons_wire_off.png
Normal file
After Width: | Height: | Size: 377 B |
BIN
mesecons/textures/mesecons_wire_on.png
Normal file
After Width: | Height: | Size: 362 B |
@ -1,24 +1,62 @@
|
|||||||
function mesecon:move_node(pos, newpos)
|
function mesecon.move_node(pos, newpos)
|
||||||
local node = minetest.get_node(pos)
|
local node = minetest.get_node(pos)
|
||||||
local meta = minetest.get_meta(pos):to_table()
|
local meta = minetest.get_meta(pos):to_table()
|
||||||
minetest.remove_node(pos)
|
minetest.remove_node(pos)
|
||||||
minetest.add_node(newpos, node)
|
minetest.set_node(newpos, node)
|
||||||
minetest.get_meta(pos):from_table(meta)
|
minetest.get_meta(pos):from_table(meta)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[ new functions:
|
-- Rules rotation Functions:
|
||||||
mesecon:flattenrules(allrules)
|
function mesecon.rotate_rules_right(rules)
|
||||||
mesecon:rule2bit(findrule, allrules)
|
local nr = {}
|
||||||
mesecon:rule2meta(findrule, allrules)
|
for i, rule in ipairs(rules) do
|
||||||
dec2bin(n)
|
table.insert(nr, {
|
||||||
mesecon:getstate(nodename, states)
|
x = -rule.z,
|
||||||
mesecon:getbinstate(nodename, states)
|
y = rule.y,
|
||||||
mesecon:get_bit(binary, bit)
|
z = rule.x,
|
||||||
mesecon:set_bit(binary, bit, value)
|
name = rule.name})
|
||||||
mesecon:invertRule(r)
|
end
|
||||||
--]]
|
return nr
|
||||||
|
end
|
||||||
|
|
||||||
function mesecon:flattenrules(allrules)
|
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)
|
||||||
--[[
|
--[[
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@ -53,7 +91,7 @@ function mesecon:flattenrules(allrules)
|
|||||||
--]]
|
--]]
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:rule2bit(findrule, allrules)
|
function mesecon.rule2bit(findrule, allrules)
|
||||||
--get the bit of the metarule the rule is in, or bit 1
|
--get the bit of the metarule the rule is in, or bit 1
|
||||||
if (allrules[1] and
|
if (allrules[1] and
|
||||||
allrules[1].x) or
|
allrules[1].x) or
|
||||||
@ -62,35 +100,36 @@ function mesecon:rule2bit(findrule, allrules)
|
|||||||
end
|
end
|
||||||
for m,metarule in ipairs( allrules) do
|
for m,metarule in ipairs( allrules) do
|
||||||
for _, rule in ipairs(metarule ) do
|
for _, rule in ipairs(metarule ) do
|
||||||
if mesecon:cmpPos(findrule, rule) and mesecon:cmpSpecial(findrule, rule) then
|
if vector.equals(findrule, rule) then
|
||||||
return m
|
return m
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:rule2metaindex(findrule, allrules)
|
function mesecon.rule2metaindex(findrule, allrules)
|
||||||
--get the metarule the rule is in, or allrules
|
--get the metarule the rule is in, or allrules
|
||||||
|
|
||||||
if allrules[1].x then
|
if allrules[1].x then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
if not(findrule) then
|
if not(findrule) then
|
||||||
return mesecon:flattenrules(allrules)
|
return mesecon.flattenrules(allrules)
|
||||||
end
|
end
|
||||||
|
|
||||||
for m, metarule in ipairs( allrules) do
|
for m, metarule in ipairs( allrules) do
|
||||||
for _, rule in ipairs(metarule ) do
|
for _, rule in ipairs(metarule ) do
|
||||||
if mesecon:cmpPos(findrule, rule) and mesecon:cmpSpecial(findrule, rule) then
|
if vector.equals(findrule, rule) then
|
||||||
return m
|
return m
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:rule2meta(findrule, allrules)
|
function mesecon.rule2meta(findrule, allrules)
|
||||||
local index = mesecon:rule2metaindex(findrule, allrules)
|
if #allrules == 0 then return {} end
|
||||||
|
|
||||||
|
local index = mesecon.rule2metaindex(findrule, allrules)
|
||||||
if index == nil then
|
if index == nil then
|
||||||
if allrules[1].x then
|
if allrules[1].x then
|
||||||
return allrules
|
return allrules
|
||||||
@ -101,25 +140,16 @@ function mesecon:rule2meta(findrule, allrules)
|
|||||||
return allrules[index]
|
return allrules[index]
|
||||||
end
|
end
|
||||||
|
|
||||||
if convert_base then
|
function mesecon.dec2bin(n)
|
||||||
print(
|
|
||||||
"base2dec is tonumber(num,base1)\n"..
|
|
||||||
"commonlib needs dec2base(num,base2)\n"..
|
|
||||||
"and it needs base2base(num,base1,base2),\n"..
|
|
||||||
"which is dec2base(tonumber(num,base1),base2)"
|
|
||||||
)
|
|
||||||
else
|
|
||||||
function dec2bin(n)
|
|
||||||
local x, y = math.floor(n / 2), n % 2
|
local x, y = math.floor(n / 2), n % 2
|
||||||
if (n > 1) then
|
if (n > 1) then
|
||||||
return dec2bin(x)..y
|
return mesecon.dec2bin(x)..y
|
||||||
else
|
else
|
||||||
return ""..y
|
return ""..y
|
||||||
end
|
end
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:getstate(nodename, states)
|
function mesecon.getstate(nodename, states)
|
||||||
for state, name in ipairs(states) do
|
for state, name in ipairs(states) do
|
||||||
if name == nodename then
|
if name == nodename then
|
||||||
return state
|
return state
|
||||||
@ -128,56 +158,312 @@ function mesecon:getstate(nodename, states)
|
|||||||
error(nodename.." doesn't mention itself in "..dump(states))
|
error(nodename.." doesn't mention itself in "..dump(states))
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:getbinstate(nodename, states)
|
function mesecon.getbinstate(nodename, states)
|
||||||
return dec2bin(mesecon:getstate(nodename, states)-1)
|
return mesecon.dec2bin(mesecon.getstate(nodename, states)-1)
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:get_bit(binary,bit)
|
function mesecon.get_bit(binary,bit)
|
||||||
bit = bit or 1
|
bit = bit or 1
|
||||||
local c = binary:len()-(bit-1)
|
local c = binary:len()-(bit-1)
|
||||||
return binary:sub(c,c) == "1"
|
return binary:sub(c,c) == "1"
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:set_bit(binary,bit,value)
|
function mesecon.set_bit(binary,bit,value)
|
||||||
if value == "1" then
|
if value == "1" then
|
||||||
if not mesecon:get_bit(binary,bit) then
|
if not mesecon.get_bit(binary,bit) then
|
||||||
return dec2bin(tonumber(binary,2)+math.pow(2,bit-1))
|
return mesecon.dec2bin(tonumber(binary,2)+math.pow(2,bit-1))
|
||||||
end
|
end
|
||||||
elseif value == "0" then
|
elseif value == "0" then
|
||||||
if mesecon:get_bit(binary,bit) then
|
if mesecon.get_bit(binary,bit) then
|
||||||
return dec2bin(tonumber(binary,2)-math.pow(2,bit-1))
|
return mesecon.dec2bin(tonumber(binary,2)-math.pow(2,bit-1))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return binary
|
return binary
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:invertRule(r)
|
function mesecon.invertRule(r)
|
||||||
return {x = -r.x, y = -r.y, z = -r.z, sx = r.sx, sy = r.sy, sz = r.sz}
|
return vector.multiply(r, -1)
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:addPosRule(p, r)
|
function mesecon.tablecopy(obj) -- deep copy
|
||||||
return {x = p.x + r.x, y = p.y + r.y, z = p.z + r.z}
|
if type(obj) == "table" then
|
||||||
|
return table.copy(obj)
|
||||||
|
end
|
||||||
|
return obj
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:cmpPos(p1, p2)
|
-- Returns whether two values are equal.
|
||||||
return (p1.x == p2.x and p1.y == p2.y and p1.z == p2.z)
|
-- In tables, keys are compared for identity but values are compared recursively.
|
||||||
|
-- There is no protection from infinite recursion.
|
||||||
|
function mesecon.cmpAny(t1, t2)
|
||||||
|
if type(t1) ~= type(t2) then return false end
|
||||||
|
if type(t1) ~= "table" 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
|
||||||
|
if not mesecon.cmpAny(e, t2[i]) then return false 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
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:cmpSpecial(r1, r2)
|
-- Deprecated. Use `merge_tables` or `merge_rule_sets` as appropriate.
|
||||||
return (r1.sx == r2.sx and r1.sy == r2.sy and r1.sz == r2.sz)
|
function mesecon.mergetable(source, dest)
|
||||||
|
minetest.log("warning", debug.traceback("Deprecated call to mesecon.mergetable"))
|
||||||
|
local rval = mesecon.tablecopy(dest)
|
||||||
|
|
||||||
|
for k, v in pairs(source) do
|
||||||
|
rval[k] = dest[k] or mesecon.tablecopy(v)
|
||||||
|
end
|
||||||
|
for i, v in ipairs(source) do
|
||||||
|
table.insert(rval, mesecon.tablecopy(v))
|
||||||
|
end
|
||||||
|
|
||||||
|
return rval
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:tablecopy(table) -- deep table copy
|
-- Merges several rule sets in one. Order may not be preserved. Nil arguments
|
||||||
local newtable = {}
|
-- are ignored.
|
||||||
|
-- The rule sets must be of the same kind (either all single-level or all two-level).
|
||||||
|
-- The function may be changed to normalize the resulting set in some way.
|
||||||
|
function mesecon.merge_rule_sets(...)
|
||||||
|
local rval = {}
|
||||||
|
for _, t in pairs({...}) do -- ignores nils automatically
|
||||||
|
table.insert_all(rval, mesecon.tablecopy(t))
|
||||||
|
end
|
||||||
|
return rval
|
||||||
|
end
|
||||||
|
|
||||||
for idx, item in pairs(table) do
|
-- Merges two tables, with entries from `replacements` taking precedence over
|
||||||
if type(item) == "table" then
|
-- those from `base`. Returns the new table.
|
||||||
newtable[idx] = mesecon:tablecopy(item)
|
-- Values are deep-copied from either table, keys are referenced.
|
||||||
|
-- Numerical indices aren’t handled specially.
|
||||||
|
function mesecon.merge_tables(base, replacements)
|
||||||
|
local ret = mesecon.tablecopy(replacements) -- these are never overriden so have to be copied in any case
|
||||||
|
for k, v in pairs(base) do
|
||||||
|
if ret[k] == nil then -- it could be `false`
|
||||||
|
ret[k] = mesecon.tablecopy(v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
function mesecon.register_node(name, spec_common, spec_off, spec_on)
|
||||||
|
spec_common.drop = spec_common.drop or name .. "_off"
|
||||||
|
spec_common.on_blast = spec_common.on_blast or mesecon.on_blastnode
|
||||||
|
spec_common.__mesecon_basename = name
|
||||||
|
spec_on.__mesecon_state = "on"
|
||||||
|
spec_off.__mesecon_state = "off"
|
||||||
|
|
||||||
|
spec_on = mesecon.merge_tables(spec_common, spec_on);
|
||||||
|
spec_off = mesecon.merge_tables(spec_common, spec_off);
|
||||||
|
|
||||||
|
minetest.register_node(name .. "_on", spec_on)
|
||||||
|
minetest.register_node(name .. "_off", spec_off)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- swap onstate and offstate nodes, returns new state
|
||||||
|
function mesecon.flipstate(pos, node)
|
||||||
|
local nodedef = minetest.registered_nodes[node.name]
|
||||||
|
local newstate
|
||||||
|
if (nodedef.__mesecon_state == "on") then newstate = "off" end
|
||||||
|
if (nodedef.__mesecon_state == "off") then newstate = "on" end
|
||||||
|
|
||||||
|
minetest.swap_node(pos, {name = nodedef.__mesecon_basename .. "_" .. newstate,
|
||||||
|
param2 = node.param2})
|
||||||
|
|
||||||
|
return newstate
|
||||||
|
end
|
||||||
|
|
||||||
|
-- File writing / reading utilities
|
||||||
|
local wpath = minetest.get_worldpath()
|
||||||
|
function mesecon.file2table(filename)
|
||||||
|
local f = io.open(wpath..DIR_DELIM..filename, "r")
|
||||||
|
if f == nil then return {} end
|
||||||
|
local t = f:read("*all")
|
||||||
|
f:close()
|
||||||
|
if t == "" or t == nil then return {} end
|
||||||
|
return minetest.deserialize(t)
|
||||||
|
end
|
||||||
|
|
||||||
|
function mesecon.table2file(filename, table)
|
||||||
|
local f = io.open(wpath..DIR_DELIM..filename, "w")
|
||||||
|
f:write(minetest.serialize(table))
|
||||||
|
f:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Block position "hashing" (convert to integer) functions for voxelmanip cache
|
||||||
|
local BLOCKSIZE = 16
|
||||||
|
|
||||||
|
-- convert node position --> block hash
|
||||||
|
local function hash_blockpos(pos)
|
||||||
|
return minetest.hash_node_position({
|
||||||
|
x = math.floor(pos.x/BLOCKSIZE),
|
||||||
|
y = math.floor(pos.y/BLOCKSIZE),
|
||||||
|
z = math.floor(pos.z/BLOCKSIZE)
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Maps from a hashed mapblock position (as returned by hash_blockpos) to a
|
||||||
|
-- table.
|
||||||
|
--
|
||||||
|
-- Contents of the table are:
|
||||||
|
-- “vm” → the VoxelManipulator
|
||||||
|
-- “va” → the VoxelArea
|
||||||
|
-- “data” → the data array
|
||||||
|
-- “param1” → the param1 array
|
||||||
|
-- “param2” → the param2 array
|
||||||
|
-- “dirty” → true if data has been modified
|
||||||
|
--
|
||||||
|
-- Nil if no VM-based transaction is in progress.
|
||||||
|
local vm_cache = nil
|
||||||
|
|
||||||
|
-- Starts a VoxelManipulator-based transaction.
|
||||||
|
--
|
||||||
|
-- During a VM transaction, calls to vm_get_node and vm_swap_node operate on a
|
||||||
|
-- cached copy of the world loaded via VoxelManipulators. That cache can later
|
||||||
|
-- be committed to the real map by means of vm_commit or discarded by means of
|
||||||
|
-- vm_abort.
|
||||||
|
function mesecon.vm_begin()
|
||||||
|
vm_cache = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Finishes a VoxelManipulator-based transaction, freeing the VMs and map data
|
||||||
|
-- and writing back any modified areas.
|
||||||
|
function mesecon.vm_commit()
|
||||||
|
for hash, tbl in pairs(vm_cache) do
|
||||||
|
if tbl.dirty then
|
||||||
|
local vm = tbl.vm
|
||||||
|
vm:set_data(tbl.data)
|
||||||
|
vm:write_to_map()
|
||||||
|
vm:update_map()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
vm_cache = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Finishes a VoxelManipulator-based transaction, freeing the VMs and throwing
|
||||||
|
-- away any modified areas.
|
||||||
|
function mesecon.vm_abort()
|
||||||
|
vm_cache = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Gets the cache entry covering a position, populating it if necessary.
|
||||||
|
local function vm_get_or_create_entry(pos)
|
||||||
|
local hash = hash_blockpos(pos)
|
||||||
|
local tbl = vm_cache[hash]
|
||||||
|
if not tbl then
|
||||||
|
local vm = minetest.get_voxel_manip(pos, pos)
|
||||||
|
local min_pos, max_pos = vm:get_emerged_area()
|
||||||
|
local va = VoxelArea:new{MinEdge = min_pos, MaxEdge = max_pos}
|
||||||
|
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
|
else
|
||||||
newtable[idx] = item
|
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)
|
||||||
|
if vm_cache then
|
||||||
|
return mesecon.vm_get_node(pos)
|
||||||
|
else
|
||||||
|
local node = minetest.get_node_or_nil(pos)
|
||||||
|
if node == nil then
|
||||||
|
-- Node is not currently loaded; use a VoxelManipulator to prime
|
||||||
|
-- the mapblock cache and try again.
|
||||||
|
minetest.get_voxel_manip(pos, pos)
|
||||||
|
node = minetest.get_node_or_nil(pos)
|
||||||
|
end
|
||||||
|
return node
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Swaps the node at a given position, regardless of whether it is loaded or
|
||||||
|
-- not, respecting a transaction if one is in progress.
|
||||||
|
--
|
||||||
|
-- Outside a VM transaction, if the mapblock is not loaded, it is pulled into
|
||||||
|
-- the server’s main map data cache and then accessed from there.
|
||||||
|
--
|
||||||
|
-- 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
|
||||||
|
-- This serves to both ensure the mapblock is loaded and also hand us
|
||||||
|
-- the old node table so we can preserve param2.
|
||||||
|
local node = mesecon.get_node_force(pos)
|
||||||
|
node.name = name
|
||||||
|
minetest.swap_node(pos, node)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Autoconnect Hooks
|
||||||
|
-- Nodes like conductors may change their appearance and their connection rules
|
||||||
|
-- right after being placed or after being dug, e.g. the default wires use this
|
||||||
|
-- to automatically connect to linking nodes after placement.
|
||||||
|
-- After placement, the update function will be executed immediately so that the
|
||||||
|
-- possibly changed rules can be taken into account when recalculating the circuit.
|
||||||
|
-- After digging, the update function will be queued and executed after
|
||||||
|
-- recalculating the circuit. The update function must take care of updating the
|
||||||
|
-- node at the given position itself, but also all of the other nodes the given
|
||||||
|
-- position may have (had) a linking connection to.
|
||||||
|
mesecon.autoconnect_hooks = {}
|
||||||
|
|
||||||
|
-- name: A unique name for the hook, e.g. "foowire". Used to name the actionqueue function.
|
||||||
|
-- fct: The update function with parameters function(pos, node)
|
||||||
|
function mesecon.register_autoconnect_hook(name, fct)
|
||||||
|
mesecon.autoconnect_hooks[name] = fct
|
||||||
|
mesecon.queue:add_function("autoconnect_hook_"..name, fct)
|
||||||
|
end
|
||||||
|
|
||||||
|
function mesecon.execute_autoconnect_hooks_now(pos, node)
|
||||||
|
for _, fct in pairs(mesecon.autoconnect_hooks) do
|
||||||
|
fct(pos, node)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function mesecon.execute_autoconnect_hooks_queue(pos, node)
|
||||||
|
for name in pairs(mesecon.autoconnect_hooks) do
|
||||||
|
mesecon.queue:add_action(pos, "autoconnect_hook_"..name, {node})
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
return newtable
|
|
||||||
end
|
end
|
||||||
|
@ -1,280 +0,0 @@
|
|||||||
-- naming scheme: wire:(xp)(zp)(xm)(zm)_on/off
|
|
||||||
-- The conditions in brackets define whether there is a mesecon at that place or not
|
|
||||||
-- 1 = there is one; 0 = there is none
|
|
||||||
-- y always means y+
|
|
||||||
|
|
||||||
box_center = {-1/16, -.5, -1/16, 1/16, -.5+1/16, 1/16}
|
|
||||||
box_bump1 = { -2/16, -8/16, -2/16, 2/16, -13/32, 2/16 }
|
|
||||||
|
|
||||||
box_xp = {1/16, -.5, -1/16, 8/16, -.5+1/16, 1/16}
|
|
||||||
box_zp = {-1/16, -.5, 1/16, 1/16, -.5+1/16, 8/16}
|
|
||||||
box_xm = {-8/16, -.5, -1/16, -1/16, -.5+1/16, 1/16}
|
|
||||||
box_zm = {-1/16, -.5, -8/16, 1/16, -.5+1/16, -1/16}
|
|
||||||
|
|
||||||
box_xpy = {.5-1/16, -.5+1/16, -1/16, .5, .4999+1/16, 1/16}
|
|
||||||
box_zpy = {-1/16, -.5+1/16, .5-1/16, 1/16, .4999+1/16, .5}
|
|
||||||
box_xmy = {-.5, -.5+1/16, -1/16, -.5+1/16, .4999+1/16, 1/16}
|
|
||||||
box_zmy = {-1/16, -.5+1/16, -.5, 1/16, .4999+1/16, -.5+1/16}
|
|
||||||
|
|
||||||
-- Registering the wires
|
|
||||||
|
|
||||||
for xp=0, 1 do
|
|
||||||
for zp=0, 1 do
|
|
||||||
for xm=0, 1 do
|
|
||||||
for zm=0, 1 do
|
|
||||||
for xpy=0, 1 do
|
|
||||||
for zpy=0, 1 do
|
|
||||||
for xmy=0, 1 do
|
|
||||||
for zmy=0, 1 do
|
|
||||||
if (xpy == 1 and xp == 0) or (zpy == 1 and zp == 0)
|
|
||||||
or (xmy == 1 and xm == 0) or (zmy == 1 and zm == 0) then break end
|
|
||||||
|
|
||||||
local groups
|
|
||||||
local nodeid = tostring(xp )..tostring(zp )..tostring(xm )..tostring(zm )..
|
|
||||||
tostring(xpy)..tostring(zpy)..tostring(xmy)..tostring(zmy)
|
|
||||||
|
|
||||||
if nodeid == "00000000" then
|
|
||||||
groups = {dig_immediate = 3, mesecon_conductor_craftable=1}
|
|
||||||
wiredesc = "Mesecon"
|
|
||||||
else
|
|
||||||
groups = {dig_immediate = 3, not_in_creative_inventory = 1}
|
|
||||||
wiredesc = "Mesecons Wire (ID: "..nodeid..")"
|
|
||||||
end
|
|
||||||
|
|
||||||
local nodebox = {}
|
|
||||||
local adjx = false
|
|
||||||
local adjz = false
|
|
||||||
if xp == 1 then table.insert(nodebox, box_xp) adjx = true end
|
|
||||||
if zp == 1 then table.insert(nodebox, box_zp) adjz = true end
|
|
||||||
if xm == 1 then table.insert(nodebox, box_xm) adjx = true end
|
|
||||||
if zm == 1 then table.insert(nodebox, box_zm) adjz = true end
|
|
||||||
if xpy == 1 then table.insert(nodebox, box_xpy) end
|
|
||||||
if zpy == 1 then table.insert(nodebox, box_zpy) end
|
|
||||||
if xmy == 1 then table.insert(nodebox, box_xmy) end
|
|
||||||
if zmy == 1 then table.insert(nodebox, box_zmy) end
|
|
||||||
|
|
||||||
if adjx and adjz and (xp + zp + xm + zm > 2) then
|
|
||||||
table.insert(nodebox, box_bump1)
|
|
||||||
tiles_off = {
|
|
||||||
"wires_bump_off.png",
|
|
||||||
"wires_bump_off.png",
|
|
||||||
"wires_vertical_off.png",
|
|
||||||
"wires_vertical_off.png",
|
|
||||||
"wires_vertical_off.png",
|
|
||||||
"wires_vertical_off.png"
|
|
||||||
}
|
|
||||||
tiles_on = {
|
|
||||||
"wires_bump_on.png",
|
|
||||||
"wires_bump_on.png",
|
|
||||||
"wires_vertical_on.png",
|
|
||||||
"wires_vertical_on.png",
|
|
||||||
"wires_vertical_on.png",
|
|
||||||
"wires_vertical_on.png"
|
|
||||||
}
|
|
||||||
else
|
|
||||||
table.insert(nodebox, box_center)
|
|
||||||
tiles_off = {
|
|
||||||
"wires_off.png",
|
|
||||||
"wires_off.png",
|
|
||||||
"wires_vertical_off.png",
|
|
||||||
"wires_vertical_off.png",
|
|
||||||
"wires_vertical_off.png",
|
|
||||||
"wires_vertical_off.png"
|
|
||||||
}
|
|
||||||
tiles_on = {
|
|
||||||
"wires_on.png",
|
|
||||||
"wires_on.png",
|
|
||||||
"wires_vertical_on.png",
|
|
||||||
"wires_vertical_on.png",
|
|
||||||
"wires_vertical_on.png",
|
|
||||||
"wires_vertical_on.png"
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
if nodeid == "00000000" then
|
|
||||||
nodebox = {-8/16, -.5, -1/16, 8/16, -.5+1/16, 1/16}
|
|
||||||
end
|
|
||||||
|
|
||||||
minetest.register_node("mesecons:wire_"..nodeid.."_off", {
|
|
||||||
description = wiredesc,
|
|
||||||
drawtype = "nodebox",
|
|
||||||
tiles = tiles_off,
|
|
||||||
-- inventory_image = "wires_inv.png",
|
|
||||||
-- wield_image = "wires_inv.png",
|
|
||||||
inventory_image = "jeija_mesecon_off.png",
|
|
||||||
wield_image = "jeija_mesecon_off.png",
|
|
||||||
paramtype = "light",
|
|
||||||
paramtype2 = "facedir",
|
|
||||||
sunlight_propagates = true,
|
|
||||||
selection_box = {
|
|
||||||
type = "fixed",
|
|
||||||
fixed = {-.5, -.5, -.5, .5, -.5+4/16, .5}
|
|
||||||
},
|
|
||||||
node_box = {
|
|
||||||
type = "fixed",
|
|
||||||
fixed = nodebox
|
|
||||||
},
|
|
||||||
groups = groups,
|
|
||||||
walkable = false,
|
|
||||||
stack_max = 99,
|
|
||||||
drop = "mesecons:wire_00000000_off",
|
|
||||||
mesecons = {conductor={
|
|
||||||
state = mesecon.state.off,
|
|
||||||
onstate = "mesecons:wire_"..nodeid.."_on"
|
|
||||||
}}
|
|
||||||
})
|
|
||||||
|
|
||||||
minetest.register_node("mesecons:wire_"..nodeid.."_on", {
|
|
||||||
description = "Wire ID:"..nodeid,
|
|
||||||
drawtype = "nodebox",
|
|
||||||
tiles = tiles_on,
|
|
||||||
-- inventory_image = "wires_inv.png",
|
|
||||||
-- wield_image = "wires_inv.png",
|
|
||||||
inventory_image = "jeija_mesecon_off.png",
|
|
||||||
wield_image = "jeija_mesecon_off.png",
|
|
||||||
paramtype = "light",
|
|
||||||
paramtype2 = "facedir",
|
|
||||||
sunlight_propagates = true,
|
|
||||||
selection_box = {
|
|
||||||
type = "fixed",
|
|
||||||
fixed = {-.5, -.5, -.5, .5, -.5+4/16, .5}
|
|
||||||
},
|
|
||||||
node_box = {
|
|
||||||
type = "fixed",
|
|
||||||
fixed = nodebox
|
|
||||||
},
|
|
||||||
groups = {dig_immediate = 3, mesecon = 2, not_in_creative_inventory = 1},
|
|
||||||
walkable = false,
|
|
||||||
stack_max = 99,
|
|
||||||
drop = "mesecons:wire_00000000_off",
|
|
||||||
mesecons = {conductor={
|
|
||||||
state = mesecon.state.on,
|
|
||||||
offstate = "mesecons:wire_"..nodeid.."_off"
|
|
||||||
}}
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Updating the wires:
|
|
||||||
-- Place the right connection wire
|
|
||||||
|
|
||||||
local update_on_place_dig = function (pos, node)
|
|
||||||
if minetest.registered_nodes[node.name]
|
|
||||||
and minetest.registered_nodes[node.name].mesecons then
|
|
||||||
mesecon:update_autoconnect(pos)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
minetest.register_on_placenode(update_on_place_dig)
|
|
||||||
minetest.register_on_dignode(update_on_place_dig)
|
|
||||||
|
|
||||||
function mesecon:update_autoconnect(pos, secondcall, replace_old)
|
|
||||||
local xppos = {x=pos.x+1, y=pos.y, z=pos.z}
|
|
||||||
local zppos = {x=pos.x, y=pos.y, z=pos.z+1}
|
|
||||||
local xmpos = {x=pos.x-1, y=pos.y, z=pos.z}
|
|
||||||
local zmpos = {x=pos.x, y=pos.y, z=pos.z-1}
|
|
||||||
|
|
||||||
local xpympos = {x=pos.x+1, y=pos.y-1, z=pos.z}
|
|
||||||
local zpympos = {x=pos.x, y=pos.y-1, z=pos.z+1}
|
|
||||||
local xmympos = {x=pos.x-1, y=pos.y-1, z=pos.z}
|
|
||||||
local zmympos = {x=pos.x, y=pos.y-1, z=pos.z-1}
|
|
||||||
|
|
||||||
local xpypos = {x=pos.x+1, y=pos.y+1, z=pos.z}
|
|
||||||
local zpypos = {x=pos.x, y=pos.y+1, z=pos.z+1}
|
|
||||||
local xmypos = {x=pos.x-1, y=pos.y+1, z=pos.z}
|
|
||||||
local zmypos = {x=pos.x, y=pos.y+1, z=pos.z-1}
|
|
||||||
|
|
||||||
if secondcall == nil then
|
|
||||||
mesecon:update_autoconnect(xppos, true)
|
|
||||||
mesecon:update_autoconnect(zppos, true)
|
|
||||||
mesecon:update_autoconnect(xmpos, true)
|
|
||||||
mesecon:update_autoconnect(zmpos, true)
|
|
||||||
|
|
||||||
mesecon:update_autoconnect(xpypos, true)
|
|
||||||
mesecon:update_autoconnect(zpypos, true)
|
|
||||||
mesecon:update_autoconnect(xmypos, true)
|
|
||||||
mesecon:update_autoconnect(zmypos, true)
|
|
||||||
|
|
||||||
mesecon:update_autoconnect(xpympos, true)
|
|
||||||
mesecon:update_autoconnect(zpympos, true)
|
|
||||||
mesecon:update_autoconnect(xmympos, true)
|
|
||||||
mesecon:update_autoconnect(zmympos, true)
|
|
||||||
end
|
|
||||||
|
|
||||||
nodename = minetest.get_node(pos).name
|
|
||||||
if string.find(nodename, "mesecons:wire_") == nil and not replace_old then return nil end
|
|
||||||
|
|
||||||
if mesecon:rules_link_anydir(pos, xppos) then xp = 1 else xp = 0 end
|
|
||||||
if mesecon:rules_link_anydir(pos, xmpos) then xm = 1 else xm = 0 end
|
|
||||||
if mesecon:rules_link_anydir(pos, zppos) then zp = 1 else zp = 0 end
|
|
||||||
if mesecon:rules_link_anydir(pos, zmpos) then zm = 1 else zm = 0 end
|
|
||||||
|
|
||||||
if mesecon:rules_link_anydir(pos, xpympos) then xp = 1 end
|
|
||||||
if mesecon:rules_link_anydir(pos, xmympos) then xm = 1 end
|
|
||||||
if mesecon:rules_link_anydir(pos, zpympos) then zp = 1 end
|
|
||||||
if mesecon:rules_link_anydir(pos, zmympos) then zm = 1 end
|
|
||||||
|
|
||||||
if mesecon:rules_link_anydir(pos, xpypos) then xpy = 1 else xpy = 0 end
|
|
||||||
if mesecon:rules_link_anydir(pos, zpypos) then zpy = 1 else zpy = 0 end
|
|
||||||
if mesecon:rules_link_anydir(pos, xmypos) then xmy = 1 else xmy = 0 end
|
|
||||||
if mesecon:rules_link_anydir(pos, zmypos) then zmy = 1 else zmy = 0 end
|
|
||||||
|
|
||||||
if xpy == 1 then xp = 1 end
|
|
||||||
if zpy == 1 then zp = 1 end
|
|
||||||
if xmy == 1 then xm = 1 end
|
|
||||||
if zmy == 1 then zm = 1 end
|
|
||||||
|
|
||||||
local nodeid = tostring(xp )..tostring(zp )..tostring(xm )..tostring(zm )..
|
|
||||||
tostring(xpy)..tostring(zpy)..tostring(xmy)..tostring(zmy)
|
|
||||||
|
|
||||||
|
|
||||||
if string.find(nodename, "_off") ~= nil then
|
|
||||||
minetest.set_node(pos, {name = "mesecons:wire_"..nodeid.."_off"})
|
|
||||||
else
|
|
||||||
minetest.set_node(pos, {name = "mesecons:wire_"..nodeid.."_on" })
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if not minetest.registered_nodes["default:stone_with_mese"] then --before MESE update, use old recipes
|
|
||||||
minetest.register_craft({
|
|
||||||
output = "mesecons:wire_00000000_off 18",
|
|
||||||
recipe = {
|
|
||||||
{"default:mese"},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
else
|
|
||||||
|
|
||||||
minetest.register_craft({
|
|
||||||
type = "cooking",
|
|
||||||
output = "mesecons:wire_00000000_off 2",
|
|
||||||
recipe = "default:mese_crystal_fragment",
|
|
||||||
cooktime = 3,
|
|
||||||
})
|
|
||||||
|
|
||||||
minetest.register_craft({
|
|
||||||
type = "cooking",
|
|
||||||
output = "mesecons:wire_00000000_off 18",
|
|
||||||
recipe = "default:mese_crystal",
|
|
||||||
cooktime = 15,
|
|
||||||
})
|
|
||||||
|
|
||||||
minetest.register_craft({
|
|
||||||
type = "cooking",
|
|
||||||
output = "mesecons:wire_00000000_off 162",
|
|
||||||
recipe = "default:mese",
|
|
||||||
cooktime = 30,
|
|
||||||
})
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
minetest.register_craft({
|
|
||||||
type = "cooking",
|
|
||||||
output = "mesecons:wire_00000000_off 16",
|
|
||||||
recipe = "default:mese_crystal",
|
|
||||||
})
|
|
@ -1 +0,0 @@
|
|||||||
mesecons
|
|
2
mesecons_alias/mod.conf
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
name = mesecons_alias
|
||||||
|
depends = mesecons
|
@ -1 +0,0 @@
|
|||||||
mesecons
|
|
2
mesecons_blinkyplant/doc/blinkyplant/description.html
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
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
After Width: | Height: | Size: 54 KiB |
BIN
mesecons_blinkyplant/doc/blinkyplant/recipe.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
@ -1,102 +1,58 @@
|
|||||||
-- The BLINKY_PLANT
|
-- The BLINKY_PLANT
|
||||||
minetest.register_node("mesecons_blinkyplant:blinky_plant", {
|
|
||||||
drawtype = "plantlike",
|
|
||||||
visual_scale = 1,
|
|
||||||
tiles = {"jeija_blinky_plant_off.png"},
|
|
||||||
inventory_image = "jeija_blinky_plant_off.png",
|
|
||||||
walkable = false,
|
|
||||||
groups = {dig_immediate=3, not_in_creative_inventory=1},
|
|
||||||
drop="mesecons_blinkyplant:blinky_plant_off 1",
|
|
||||||
description="Deactivated Blinky Plant",
|
|
||||||
sounds = default.node_sound_leaves_defaults(),
|
|
||||||
selection_box = {
|
|
||||||
type = "fixed",
|
|
||||||
fixed = {-0.3, -0.5, -0.3, 0.3, -0.5+0.7, 0.3},
|
|
||||||
},
|
|
||||||
mesecons = {receptor = {
|
|
||||||
state = mesecon.state.off
|
|
||||||
}},
|
|
||||||
on_rightclick = function(pos, node, clicker)
|
|
||||||
minetest.set_node(pos, {name="mesecons_blinkyplant:blinky_plant_off"})
|
|
||||||
end
|
|
||||||
})
|
|
||||||
|
|
||||||
minetest.register_node("mesecons_blinkyplant:blinky_plant_off", {
|
local toggle_timer = function (pos)
|
||||||
drawtype = "plantlike",
|
local timer = minetest.get_node_timer(pos)
|
||||||
visual_scale = 1,
|
if timer:is_started() then
|
||||||
tiles = {"jeija_blinky_plant_off.png"},
|
timer:stop()
|
||||||
inventory_image = "jeija_blinky_plant_off.png",
|
else
|
||||||
paramtype = "light",
|
timer:start(mesecon.setting("blinky_plant_interval", 3))
|
||||||
walkable = false,
|
end
|
||||||
groups = {dig_immediate=3, mesecon=2},
|
end
|
||||||
|
|
||||||
|
local on_timer = function (pos)
|
||||||
|
local node = minetest.get_node(pos)
|
||||||
|
if(mesecon.flipstate(pos, node) == "on") then
|
||||||
|
mesecon.receptor_on(pos)
|
||||||
|
else
|
||||||
|
mesecon.receptor_off(pos)
|
||||||
|
end
|
||||||
|
toggle_timer(pos)
|
||||||
|
end
|
||||||
|
|
||||||
|
mesecon.register_node("mesecons_blinkyplant:blinky_plant", {
|
||||||
description="Blinky Plant",
|
description="Blinky Plant",
|
||||||
sounds = default.node_sound_leaves_defaults(),
|
|
||||||
selection_box = {
|
|
||||||
type = "fixed",
|
|
||||||
fixed = {-0.3, -0.5, -0.3, 0.3, -0.5+0.7, 0.3},
|
|
||||||
},
|
|
||||||
mesecons = {receptor = {
|
|
||||||
state = mesecon.state.off
|
|
||||||
}},
|
|
||||||
on_rightclick = function(pos, node, clicker)
|
|
||||||
minetest.set_node(pos, {name="mesecons_blinkyplant:blinky_plant"})
|
|
||||||
end
|
|
||||||
})
|
|
||||||
|
|
||||||
minetest.register_node("mesecons_blinkyplant:blinky_plant_on", {
|
|
||||||
drawtype = "plantlike",
|
drawtype = "plantlike",
|
||||||
visual_scale = 1,
|
|
||||||
tiles = {"jeija_blinky_plant_on.png"},
|
|
||||||
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,
|
||||||
groups = {dig_immediate=3, not_in_creative_inventory=1, mesecon=2},
|
|
||||||
drop="mesecons_blinkyplant:blinky_plant_off 1",
|
|
||||||
light_source = LIGHT_MAX-7,
|
|
||||||
description = "Blinky Plant",
|
|
||||||
sounds = default.node_sound_leaves_defaults(),
|
sounds = default.node_sound_leaves_defaults(),
|
||||||
selection_box = {
|
selection_box = {
|
||||||
type = "fixed",
|
type = "fixed",
|
||||||
fixed = {-0.3, -0.5, -0.3, 0.3, -0.5+0.7, 0.3},
|
fixed = {-0.3, -0.5, -0.3, 0.3, -0.5+0.7, 0.3},
|
||||||
},
|
},
|
||||||
mesecons = {receptor = {
|
on_timer = on_timer,
|
||||||
state = mesecon.state.on
|
|
||||||
}},
|
|
||||||
on_rightclick = function(pos, node, clicker)
|
on_rightclick = function(pos, node, clicker)
|
||||||
minetest.set_node(pos, {name = "mesecons_blinkyplant:blinky_plant"})
|
if minetest.is_protected(pos, clicker and clicker:get_player_name() or "") then
|
||||||
mesecon:receptor_off(pos)
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
toggle_timer(pos)
|
||||||
|
end,
|
||||||
|
on_construct = toggle_timer
|
||||||
|
},{
|
||||||
|
tiles = {"jeija_blinky_plant_off.png"},
|
||||||
|
groups = {dig_immediate=3},
|
||||||
|
mesecons = {receptor = { state = mesecon.state.off }}
|
||||||
|
},{
|
||||||
|
tiles = {"jeija_blinky_plant_on.png"},
|
||||||
|
groups = {dig_immediate=3, not_in_creative_inventory=1},
|
||||||
|
mesecons = {receptor = { state = mesecon.state.on }}
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_craft({
|
minetest.register_craft({
|
||||||
output = "mesecons_blinkyplant:blinky_plant_off 1",
|
output = "mesecons_blinkyplant:blinky_plant_off 1",
|
||||||
recipe = {
|
recipe = { {"","group:mesecon_conductor_craftable",""},
|
||||||
{"","group:mesecon_conductor_craftable",""},
|
{"","group:mesecon_conductor_craftable",""},
|
||||||
{"","group:mesecon_conductor_craftable",""},
|
{"group:sapling","group:sapling","group:sapling"}}
|
||||||
{"default:sapling","default:sapling","default:sapling"},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
minetest.register_abm(
|
|
||||||
{nodenames = {"mesecons_blinkyplant:blinky_plant_off"},
|
|
||||||
interval = BLINKY_PLANT_INTERVAL,
|
|
||||||
chance = 1,
|
|
||||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
|
||||||
--minetest.remove_node(pos)
|
|
||||||
minetest.add_node(pos, {name="mesecons_blinkyplant:blinky_plant_on"})
|
|
||||||
nodeupdate(pos)
|
|
||||||
mesecon:receptor_on(pos)
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
|
|
||||||
minetest.register_abm({
|
|
||||||
nodenames = {"mesecons_blinkyplant:blinky_plant_on"},
|
|
||||||
interval = BLINKY_PLANT_INTERVAL,
|
|
||||||
chance = 1,
|
|
||||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
|
||||||
--minetest.remove_node(pos)
|
|
||||||
minetest.add_node(pos, {name="mesecons_blinkyplant:blinky_plant_off"})
|
|
||||||
nodeupdate(pos)
|
|
||||||
mesecon:receptor_off(pos)
|
|
||||||
end,
|
|
||||||
})
|
})
|
||||||
|
2
mesecons_blinkyplant/mod.conf
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
name = mesecons_blinkyplant
|
||||||
|
depends = mesecons
|
BIN
mesecons_blinkyplant/textures/jeija_blinky_plant_off.png
Normal file
After Width: | Height: | Size: 367 B |
BIN
mesecons_blinkyplant/textures/jeija_blinky_plant_on.png
Normal file
After Width: | Height: | Size: 394 B |
@ -1,2 +0,0 @@
|
|||||||
mesecons
|
|
||||||
mesecons_receiver
|
|
1
mesecons_button/doc/button/description.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
This receptor can be attached to walls. It turns on for 1 second if it's punched.
|
BIN
mesecons_button/doc/button/preview.png
Normal file
After Width: | Height: | Size: 68 KiB |
BIN
mesecons_button/doc/button/recipe.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
@ -4,12 +4,13 @@
|
|||||||
|
|
||||||
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 not been dug
|
if node.name ~= "mesecons_button:button_on" then -- has been dug
|
||||||
minetest.swap_node(pos, {name = "mesecons_button:button_off", param2=node.param2})
|
return
|
||||||
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", {
|
||||||
@ -24,8 +25,10 @@ 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",
|
||||||
@ -40,17 +43,18 @@ minetest.register_node("mesecons_button:button_off", {
|
|||||||
},
|
},
|
||||||
groups = {dig_immediate=2, mesecon_needs_receiver = 1},
|
groups = {dig_immediate=2, mesecon_needs_receiver = 1},
|
||||||
description = "Button",
|
description = "Button",
|
||||||
on_punch = 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})
|
minetest.sound_play("mesecons_button_push", { pos = pos }, true)
|
||||||
minetest.after(1, mesecon.button_turnoff, pos)
|
minetest.get_node_timer(pos):start(1)
|
||||||
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", {
|
||||||
@ -65,9 +69,11 @@ 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,
|
||||||
light_source = LIGHT_MAX-7,
|
on_rotate = false,
|
||||||
|
light_source = minetest.LIGHT_MAX-7,
|
||||||
sunlight_propagates = true,
|
sunlight_propagates = true,
|
||||||
selection_box = {
|
selection_box = {
|
||||||
type = "fixed",
|
type = "fixed",
|
||||||
@ -87,7 +93,9 @@ 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({
|
||||||
|
2
mesecons_button/mod.conf
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
name = mesecons_button
|
||||||
|
depends = mesecons, mesecons_receiver
|
BIN
mesecons_button/textures/jeija_wall_button_off.png
Normal file
After Width: | Height: | Size: 371 B |
BIN
mesecons_button/textures/jeija_wall_button_on.png
Normal file
After Width: | Height: | Size: 409 B |
BIN
mesecons_button/textures/jeija_wall_button_sides.png
Normal file
After Width: | Height: | Size: 220 B |
@ -1 +0,0 @@
|
|||||||
mesecons
|
|
2
mesecons_commandblock/doc/commandblock/description.html
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
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.
|
BIN
mesecons_commandblock/doc/commandblock/preview.png
Normal file
After Width: | Height: | Size: 33 KiB |
@ -23,14 +23,6 @@ minetest.register_chatcommand("tell", {
|
|||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_chatcommand("tellme", {
|
|
||||||
params = "<text>",
|
|
||||||
description = "Say <text> to yourself",
|
|
||||||
func = function(name, param)
|
|
||||||
minetest.chat_send_player(name, param, false)
|
|
||||||
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",
|
||||||
@ -50,16 +42,13 @@ minetest.register_chatcommand("hp", {
|
|||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
local initialize_data = function(meta, player, command, param)
|
local function initialize_data(meta)
|
||||||
|
local commands = minetest.formspec_escape(meta:get_string("commands"))
|
||||||
meta:set_string("formspec",
|
meta:set_string("formspec",
|
||||||
"invsize[9,6;]" ..
|
"invsize[9,5;]" ..
|
||||||
"field[1,1;7.5,1;player;Player;" .. player .. "]" ..
|
"textarea[0.5,0.5;8.5,4;commands;Commands;"..commands.."]" ..
|
||||||
"button[1.3,2;2,1;nearest;Nearest]" ..
|
"label[1,3.8;@nearest, @farthest, and @random are replaced by the respective player names]" ..
|
||||||
"button[3.3,2;2,1;farthest;Farthest]" ..
|
"button_exit[3.3,4.5;2,1;submit;Submit]")
|
||||||
"button[5.3,2;2,1;random;Random]" ..
|
|
||||||
"field[1,4;2,1;command;Command;" .. command .. "]" ..
|
|
||||||
"field[3,4;5.5,1;param;Parameter;" .. param .. "]" ..
|
|
||||||
"button_exit[3.3,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"
|
||||||
@ -68,81 +57,77 @@ local initialize_data = function(meta, player, command, param)
|
|||||||
end
|
end
|
||||||
meta:set_string("infotext", "Command Block\n" ..
|
meta:set_string("infotext", "Command Block\n" ..
|
||||||
"(" .. owner .. ")\n" ..
|
"(" .. owner .. ")\n" ..
|
||||||
"Command: /" .. command .. " " .. param)
|
"Commands: "..commands)
|
||||||
end
|
end
|
||||||
|
|
||||||
local construct = function(pos)
|
local function construct(pos)
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
|
|
||||||
meta:set_string("player", "@nearest")
|
meta:set_string("commands", "tell @nearest Commandblock unconfigured")
|
||||||
meta:set_string("command", "time")
|
|
||||||
meta:set_string("param", "7000")
|
|
||||||
|
|
||||||
meta:set_string("owner", "")
|
meta:set_string("owner", "")
|
||||||
|
|
||||||
initialize_data(meta, "@nearest", "time", "7000")
|
initialize_data(meta)
|
||||||
end
|
end
|
||||||
|
|
||||||
local after_place = function(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, "@nearest", "time", "7000")
|
initialize_data(meta)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local receive_fields = function(pos, formname, fields, sender)
|
local function receive_fields(pos, formname, fields, sender)
|
||||||
if fields.quit then
|
if not fields.submit then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
if fields.nearest then
|
local owner = meta:get_string("owner")
|
||||||
initialize_data(meta, "@nearest", fields.command, fields.param)
|
if owner ~= "" and sender:get_player_name() ~= owner then
|
||||||
elseif fields.farthest then
|
return
|
||||||
initialize_data(meta, "@farthest", fields.command, fields.param)
|
|
||||||
elseif fields.random then
|
|
||||||
initialize_data(meta, "@random", fields.command, fields.param)
|
|
||||||
else --fields.submit or pressed enter
|
|
||||||
meta:set_string("player", fields.player)
|
|
||||||
meta:set_string("command", fields.command)
|
|
||||||
meta:set_string("param", fields.param)
|
|
||||||
|
|
||||||
initialize_data(meta, fields.player, fields.command, fields.param)
|
|
||||||
end
|
end
|
||||||
|
meta:set_string("commands", fields.commands)
|
||||||
|
|
||||||
|
initialize_data(meta)
|
||||||
end
|
end
|
||||||
|
|
||||||
local resolve_player = function(name, pos)
|
local function resolve_commands(commands, pos)
|
||||||
local get_distance = function(pos1, pos2)
|
local players = minetest.get_connected_players()
|
||||||
return math.sqrt((pos1.x - pos2.x) ^ 2 + (pos1.y - pos2.y) ^ 2 + (pos1.z - pos2.z) ^ 2)
|
|
||||||
|
-- No players online: remove all commands containing
|
||||||
|
-- @nearest, @farthest and @random
|
||||||
|
if #players == 0 then
|
||||||
|
commands = commands:gsub("[^\r\n]+", function (line)
|
||||||
|
if line:find("@nearest") then return "" end
|
||||||
|
if line:find("@farthest") then return "" end
|
||||||
|
if line:find("@random") then return "" end
|
||||||
|
return line
|
||||||
|
end)
|
||||||
|
return commands
|
||||||
end
|
end
|
||||||
|
|
||||||
if name == "@nearest" then
|
local nearest, farthest = nil, nil
|
||||||
local min_distance = math.huge
|
local min_distance, max_distance = math.huge, -1
|
||||||
for index, player in ipairs(minetest.get_connected_players()) do
|
for index, player in pairs(players) do
|
||||||
local distance = get_distance(pos, player:getpos())
|
local distance = vector.distance(pos, player:get_pos())
|
||||||
if distance < min_distance then
|
if distance < min_distance then
|
||||||
min_distance = distance
|
min_distance = distance
|
||||||
name = player:get_player_name()
|
nearest = player:get_player_name()
|
||||||
end
|
end
|
||||||
end
|
|
||||||
elseif name == "@farthest" then
|
|
||||||
local max_distance = -1
|
|
||||||
for index, player in ipairs(minetest.get_connected_players()) do
|
|
||||||
local distance = get_distance(pos, player:getpos())
|
|
||||||
if distance > max_distance then
|
if distance > max_distance then
|
||||||
max_distance = distance
|
max_distance = distance
|
||||||
name = player:get_player_name()
|
farthest = player:get_player_name()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif name == "@random" then
|
local random = players[math.random(#players)]:get_player_name()
|
||||||
local players = minetest.get_connected_players()
|
commands = commands:gsub("@nearest", nearest)
|
||||||
local player = players[math.random(#players)]
|
commands = commands:gsub("@farthest", farthest)
|
||||||
name = player:get_player_name()
|
commands = commands:gsub("@random", random)
|
||||||
end
|
return commands
|
||||||
return name
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local commandblock_action_on = function(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
|
||||||
@ -150,61 +135,79 @@ local commandblock_action_on = function(pos, node)
|
|||||||
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 command = minetest.chatcommands[meta:get_string("command")]
|
|
||||||
if command == nil then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local owner = meta:get_string("owner")
|
local owner = meta:get_string("owner")
|
||||||
if owner == "" then
|
if owner == "" then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local has_privs, missing_privs = minetest.check_player_privs(owner, command.privs)
|
|
||||||
if not has_privs then
|
local commands = resolve_commands(meta:get_string("commands"), pos)
|
||||||
minetest.chat_send_player(owner, "You don't have permission to run this command (missing privileges: "..table.concat(missing_privs, ", ")..")")
|
for _, command in pairs(commands:split("\n")) do
|
||||||
|
local pos = command:find(" ")
|
||||||
|
local cmd, param = command, ""
|
||||||
|
if pos then
|
||||||
|
cmd = command:sub(1, pos - 1)
|
||||||
|
param = command:sub(pos + 1)
|
||||||
|
end
|
||||||
|
local cmddef = minetest.chatcommands[cmd]
|
||||||
|
if not cmddef then
|
||||||
|
minetest.chat_send_player(owner, "The command "..cmd.." does not exist")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local player = resolve_player(meta:get_string("player"), pos)
|
local has_privs, missing_privs = minetest.check_player_privs(owner, cmddef.privs)
|
||||||
command.func(player, meta:get_string("param"))
|
if not has_privs then
|
||||||
|
minetest.chat_send_player(owner, "You don't have permission "
|
||||||
|
.."to run "..cmd
|
||||||
|
.." (missing privileges: "
|
||||||
|
..table.concat(missing_privs, ", ")..")")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
cmddef.func(owner, param)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local commandblock_action_off = function(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 meta = minetest.get_meta(pos)
|
||||||
|
local owner = meta:get_string("owner")
|
||||||
|
return owner == "" or owner == player:get_player_name() or
|
||||||
|
minetest.check_player_privs(player, "protection_bypass")
|
||||||
|
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"),
|
||||||
|
is_ground_content = false,
|
||||||
groups = {cracky=2, mesecon_effector_off=1},
|
groups = {cracky=2, mesecon_effector_off=1},
|
||||||
on_construct = construct,
|
on_construct = construct,
|
||||||
after_place_node = after_place,
|
after_place_node = after_place,
|
||||||
on_receive_fields = receive_fields,
|
on_receive_fields = receive_fields,
|
||||||
can_dig = function(pos,player)
|
can_dig = can_dig,
|
||||||
local owner = minetest.get_meta(pos):get_string("owner")
|
|
||||||
return owner == "" or owner == player:get_player_name()
|
|
||||||
end,
|
|
||||||
sounds = default.node_sound_stone_defaults(),
|
sounds = default.node_sound_stone_defaults(),
|
||||||
mesecons = {effector = {
|
mesecons = {effector = {
|
||||||
action_on = commandblock_action_on
|
action_on = commandblock_action_on
|
||||||
}}
|
}},
|
||||||
|
on_blast = mesecon.on_blastnode,
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_node("mesecons_commandblock:commandblock_on", {
|
minetest.register_node("mesecons_commandblock:commandblock_on", {
|
||||||
tiles = {"jeija_commandblock_on.png"},
|
tiles = {"jeija_commandblock_on.png"},
|
||||||
|
is_ground_content = false,
|
||||||
groups = {cracky=2, mesecon_effector_on=1, not_in_creative_inventory=1},
|
groups = {cracky=2, mesecon_effector_on=1, not_in_creative_inventory=1},
|
||||||
light_source = 10,
|
light_source = 10,
|
||||||
drop = "mesecons_commandblock:commandblock_off",
|
drop = "mesecons_commandblock:commandblock_off",
|
||||||
on_construct = construct,
|
on_construct = construct,
|
||||||
after_place_node = after_place,
|
after_place_node = after_place,
|
||||||
on_receive_fields = receive_fields,
|
on_receive_fields = receive_fields,
|
||||||
can_dig = function(pos,player)
|
can_dig = can_dig,
|
||||||
local owner = minetest.get_meta(pos):get_string("owner")
|
|
||||||
return owner == "" or owner == player:get_player_name()
|
|
||||||
end,
|
|
||||||
sounds = default.node_sound_stone_defaults(),
|
sounds = default.node_sound_stone_defaults(),
|
||||||
mesecons = {effector = {
|
mesecons = {effector = {
|
||||||
action_off = commandblock_action_off
|
action_off = commandblock_action_off
|
||||||
}}
|
}},
|
||||||
|
on_blast = mesecon.on_blastnode,
|
||||||
})
|
})
|
||||||
|
2
mesecons_commandblock/mod.conf
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
name = mesecons_commandblock
|
||||||
|
depends = mesecons
|
BIN
mesecons_commandblock/textures/jeija_commandblock_off.png
Normal file
After Width: | Height: | Size: 183 B |
BIN
mesecons_commandblock/textures/jeija_commandblock_on.png
Normal file
After Width: | Height: | Size: 183 B |
@ -1,2 +0,0 @@
|
|||||||
mesecons
|
|
||||||
doors
|
|
@ -1,167 +0,0 @@
|
|||||||
doors = {}
|
|
||||||
|
|
||||||
-- Registers a door - REDEFINITION ONLY | DOORS MOD MUST HAVE BEEN LOADED BEFORE
|
|
||||||
-- name: The name of the door
|
|
||||||
-- def: a table with the folowing fields:
|
|
||||||
-- description
|
|
||||||
-- inventory_image
|
|
||||||
-- groups
|
|
||||||
-- tiles_bottom: the tiles of the bottom part of the door {front, side}
|
|
||||||
-- tiles_top: the tiles of the bottom part of the door {front, side}
|
|
||||||
-- If the following fields are not defined the default values are used
|
|
||||||
-- node_box_bottom
|
|
||||||
-- node_box_top
|
|
||||||
-- selection_box_bottom
|
|
||||||
-- selection_box_top
|
|
||||||
-- only_placer_can_open: if true only the player who placed the door can
|
|
||||||
-- open it
|
|
||||||
|
|
||||||
function doors:register_door(name, def)
|
|
||||||
def.groups.not_in_creative_inventory = 1
|
|
||||||
|
|
||||||
local box = {{-0.5, -0.5, -0.5, 0.5, 0.5, -0.5+1.5/16}}
|
|
||||||
|
|
||||||
if not def.node_box_bottom then
|
|
||||||
def.node_box_bottom = box
|
|
||||||
end
|
|
||||||
if not def.node_box_top then
|
|
||||||
def.node_box_top = box
|
|
||||||
end
|
|
||||||
if not def.selection_box_bottom then
|
|
||||||
def.selection_box_bottom= box
|
|
||||||
end
|
|
||||||
if not def.selection_box_top then
|
|
||||||
def.selection_box_top = box
|
|
||||||
end
|
|
||||||
|
|
||||||
local tt = def.tiles_top
|
|
||||||
local tb = def.tiles_bottom
|
|
||||||
|
|
||||||
local function after_dig_node(pos, name)
|
|
||||||
if minetest.get_node(pos).name == name then
|
|
||||||
minetest.remove_node(pos)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function on_rightclick(pos, dir, check_name, replace, replace_dir, params)
|
|
||||||
pos.y = pos.y+dir
|
|
||||||
if not minetest.get_node(pos).name == check_name then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local p2 = minetest.get_node(pos).param2
|
|
||||||
p2 = params[p2+1]
|
|
||||||
|
|
||||||
local meta = minetest.get_meta(pos):to_table()
|
|
||||||
minetest.set_node(pos, {name=replace_dir, param2=p2})
|
|
||||||
minetest.get_meta(pos):from_table(meta)
|
|
||||||
|
|
||||||
pos.y = pos.y-dir
|
|
||||||
meta = minetest.get_meta(pos):to_table()
|
|
||||||
minetest.set_node(pos, {name=replace, param2=p2})
|
|
||||||
minetest.get_meta(pos):from_table(meta)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function on_mesecons_signal_open (pos, node)
|
|
||||||
on_rightclick(pos, 1, name.."_t_1", name.."_b_2", name.."_t_2", {1,2,3,0})
|
|
||||||
end
|
|
||||||
|
|
||||||
local function on_mesecons_signal_close (pos, node)
|
|
||||||
on_rightclick(pos, 1, name.."_t_2", name.."_b_1", name.."_t_1", {3,0,1,2})
|
|
||||||
end
|
|
||||||
|
|
||||||
local function check_player_priv(pos, player)
|
|
||||||
if not def.only_placer_can_open then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
local meta = minetest.get_meta(pos)
|
|
||||||
local pn = player:get_player_name()
|
|
||||||
return meta:get_string("doors_owner") == pn
|
|
||||||
end
|
|
||||||
|
|
||||||
minetest.register_node(":"..name.."_b_1", {
|
|
||||||
tiles = {tb[2], tb[2], tb[2], tb[2], tb[1], tb[1].."^[transformfx"},
|
|
||||||
paramtype = "light",
|
|
||||||
paramtype2 = "facedir",
|
|
||||||
drop = name,
|
|
||||||
drawtype = "nodebox",
|
|
||||||
node_box = {
|
|
||||||
type = "fixed",
|
|
||||||
fixed = def.node_box_bottom
|
|
||||||
},
|
|
||||||
selection_box = {
|
|
||||||
type = "fixed",
|
|
||||||
fixed = def.selection_box_bottom
|
|
||||||
},
|
|
||||||
groups = def.groups,
|
|
||||||
|
|
||||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
|
||||||
pos.y = pos.y+1
|
|
||||||
after_dig_node(pos, name.."_t_1")
|
|
||||||
end,
|
|
||||||
|
|
||||||
on_rightclick = function(pos, node, puncher)
|
|
||||||
if check_player_priv(pos, puncher) then
|
|
||||||
on_rightclick(pos, 1, name.."_t_1", name.."_b_2", name.."_t_2", {1,2,3,0})
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
|
|
||||||
mesecons = {effector = {
|
|
||||||
action_on = on_mesecons_signal_open
|
|
||||||
}},
|
|
||||||
|
|
||||||
can_dig = check_player_priv,
|
|
||||||
})
|
|
||||||
|
|
||||||
minetest.register_node(":"..name.."_b_2", {
|
|
||||||
tiles = {tb[2], tb[2], tb[2], tb[2], tb[1].."^[transformfx", tb[1]},
|
|
||||||
paramtype = "light",
|
|
||||||
paramtype2 = "facedir",
|
|
||||||
drop = name,
|
|
||||||
drawtype = "nodebox",
|
|
||||||
node_box = {
|
|
||||||
type = "fixed",
|
|
||||||
fixed = def.node_box_bottom
|
|
||||||
},
|
|
||||||
selection_box = {
|
|
||||||
type = "fixed",
|
|
||||||
fixed = def.selection_box_bottom
|
|
||||||
},
|
|
||||||
groups = def.groups,
|
|
||||||
|
|
||||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
|
||||||
pos.y = pos.y+1
|
|
||||||
after_dig_node(pos, name.."_t_2")
|
|
||||||
end,
|
|
||||||
|
|
||||||
on_rightclick = function(pos, node, puncher)
|
|
||||||
if check_player_priv(pos, puncher) then
|
|
||||||
on_rightclick(pos, 1, name.."_t_2", name.."_b_1", name.."_t_1", {3,0,1,2})
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
|
|
||||||
mesecons = {effector = {
|
|
||||||
action_off = on_mesecons_signal_close
|
|
||||||
}},
|
|
||||||
|
|
||||||
can_dig = check_player_priv,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
doors:register_door("doors:door_wood", {
|
|
||||||
description = "Wooden Door",
|
|
||||||
inventory_image = "door_wood.png",
|
|
||||||
groups = {snappy=1,choppy=2,oddly_breakable_by_hand=2,flammable=2,door=1},
|
|
||||||
tiles_bottom = {"door_wood_b.png", "door_brown.png"},
|
|
||||||
tiles_top = {"door_wood_a.png", "door_brown.png"},
|
|
||||||
sounds = default.node_sound_wood_defaults(),
|
|
||||||
})
|
|
||||||
|
|
||||||
doors:register_door("doors:door_steel", {
|
|
||||||
description = "Steel Door",
|
|
||||||
inventory_image = "door_steel.png",
|
|
||||||
groups = {snappy=1,bendy=2,cracky=1,melty=2,level=2,door=1},
|
|
||||||
tiles_bottom = {"door_steel_b.png", "door_grey.png"},
|
|
||||||
tiles_top = {"door_steel_a.png", "door_grey.png"},
|
|
||||||
only_placer_can_open = true,
|
|
||||||
sounds = default.node_sound_stone_defaults(),
|
|
||||||
})
|
|
@ -1 +0,0 @@
|
|||||||
mesecons
|
|
1
mesecons_delayer/doc/delayer/description.html
Normal file
@ -0,0 +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.
|
BIN
mesecons_delayer/doc/delayer/preview.png
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
mesecons_delayer/doc/delayer/recipe.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
@ -2,7 +2,7 @@
|
|||||||
local delayer_get_output_rules = function(node)
|
local delayer_get_output_rules = function(node)
|
||||||
local rules = {{x = 0, y = 0, z = 1}}
|
local rules = {{x = 0, y = 0, z = 1}}
|
||||||
for i = 0, node.param2 do
|
for i = 0, node.param2 do
|
||||||
rules = mesecon:rotate_rules_left(rules)
|
rules = mesecon.rotate_rules_left(rules)
|
||||||
end
|
end
|
||||||
return rules
|
return rules
|
||||||
end
|
end
|
||||||
@ -10,54 +10,35 @@ end
|
|||||||
local delayer_get_input_rules = function(node)
|
local delayer_get_input_rules = function(node)
|
||||||
local rules = {{x = 0, y = 0, z = -1}}
|
local rules = {{x = 0, y = 0, z = -1}}
|
||||||
for i = 0, node.param2 do
|
for i = 0, node.param2 do
|
||||||
rules = mesecon:rotate_rules_left(rules)
|
rules = mesecon.rotate_rules_left(rules)
|
||||||
end
|
end
|
||||||
return rules
|
return rules
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Functions that are called after the delay time
|
-- Functions that are called after the delay time
|
||||||
|
|
||||||
local delayer_turnon = function(params)
|
|
||||||
local rules = delayer_get_output_rules(params.node)
|
|
||||||
mesecon:receptor_on(params.pos, rules)
|
|
||||||
end
|
|
||||||
|
|
||||||
local delayer_turnoff = function(params)
|
|
||||||
local rules = delayer_get_output_rules(params.node)
|
|
||||||
mesecon:receptor_off(params.pos, rules)
|
|
||||||
end
|
|
||||||
|
|
||||||
local delayer_activate = function(pos, node)
|
local delayer_activate = function(pos, node)
|
||||||
local def = minetest.registered_nodes[node.name]
|
local def = minetest.registered_nodes[node.name]
|
||||||
local time = def.delayer_time
|
local time = def.delayer_time
|
||||||
minetest.swap_node(pos, {name = def.delayer_onstate, param2=node.param2})
|
minetest.swap_node(pos, {name = def.delayer_onstate, param2=node.param2})
|
||||||
minetest.after(time, delayer_turnon , {pos = pos, node = node})
|
mesecon.queue:add_action(pos, "receptor_on", {delayer_get_output_rules(node)}, time, nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
local delayer_deactivate = function(pos, node)
|
local delayer_deactivate = function(pos, node)
|
||||||
local def = minetest.registered_nodes[node.name]
|
local def = minetest.registered_nodes[node.name]
|
||||||
local time = def.delayer_time
|
local time = def.delayer_time
|
||||||
minetest.swap_node(pos, {name = def.delayer_offstate, param2=node.param2})
|
minetest.swap_node(pos, {name = def.delayer_offstate, param2=node.param2})
|
||||||
minetest.after(time, delayer_turnoff, {pos = pos, node = node})
|
mesecon.queue:add_action(pos, "receptor_off", {delayer_get_output_rules(node)}, time, nil)
|
||||||
end
|
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 delaytime
|
local boxes = {
|
||||||
if i == 1 then delaytime = 0.1
|
{ -6/16, -8/16, -6/16, 6/16, -7/16, 6/16 }, -- the main slab
|
||||||
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 },
|
||||||
@ -67,11 +48,39 @@ boxes = {{ -6/16, -8/16, -6/16, 6/16, -7/16, 6/16 }, -- the main slab
|
|||||||
|
|
||||||
{ -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 }
|
||||||
|
}
|
||||||
|
|
||||||
minetest.register_node("mesecons_delayer:delayer_off_"..tostring(i), {
|
-- Delayer definition defaults
|
||||||
description = "Delayer",
|
local def = {
|
||||||
drawtype = "nodebox",
|
drawtype = "nodebox",
|
||||||
|
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
|
||||||
|
},
|
||||||
|
paramtype = "light",
|
||||||
|
paramtype2 = "facedir",
|
||||||
|
sunlight_propagates = true,
|
||||||
|
is_ground_content = false,
|
||||||
|
delayer_time = delaytime[i],
|
||||||
|
sounds = default.node_sound_stone_defaults(),
|
||||||
|
on_blast = mesecon.on_blastnode,
|
||||||
|
drop = "mesecons_delayer:delayer_off_1",
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Deactivated delayer definition defaults
|
||||||
|
local off_groups = {bendy=2,snappy=1,dig_immediate=2}
|
||||||
|
if i > 1 then
|
||||||
|
off_groups.not_in_creative_inventory = 1
|
||||||
|
end
|
||||||
|
|
||||||
|
local off_state = {
|
||||||
|
description = "Delayer",
|
||||||
tiles = {
|
tiles = {
|
||||||
"mesecons_delayer_off_"..tostring(i)..".png",
|
"mesecons_delayer_off_"..tostring(i)..".png",
|
||||||
"mesecons_delayer_bottom.png",
|
"mesecons_delayer_bottom.png",
|
||||||
@ -82,35 +91,18 @@ minetest.register_node("mesecons_delayer:delayer_off_"..tostring(i), {
|
|||||||
},
|
},
|
||||||
inventory_image = "mesecons_delayer_off_1.png",
|
inventory_image = "mesecons_delayer_off_1.png",
|
||||||
wield_image = "mesecons_delayer_off_1.png",
|
wield_image = "mesecons_delayer_off_1.png",
|
||||||
walkable = true,
|
groups = off_groups,
|
||||||
selection_box = {
|
on_punch = function(pos, node, puncher)
|
||||||
type = "fixed",
|
if minetest.is_protected(pos, puncher and puncher:get_player_name() or "") then
|
||||||
fixed = { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 },
|
return
|
||||||
},
|
|
||||||
node_box = {
|
|
||||||
type = "fixed",
|
|
||||||
fixed = boxes
|
|
||||||
},
|
|
||||||
groups = groups,
|
|
||||||
paramtype = "light",
|
|
||||||
paramtype2 = "facedir",
|
|
||||||
sunlight_propagates = true,
|
|
||||||
is_ground_content = true,
|
|
||||||
drop = 'mesecons_delayer:delayer_off_1',
|
|
||||||
on_punch = function (pos, node)
|
|
||||||
if node.name=="mesecons_delayer:delayer_off_1" then
|
|
||||||
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})
|
|
||||||
elseif node.name=="mesecons_delayer:delayer_off_3" then
|
|
||||||
minetest.swap_node(pos, {name = "mesecons_delayer:delayer_off_4", param2=node.param2})
|
|
||||||
elseif node.name=="mesecons_delayer:delayer_off_4" then
|
|
||||||
minetest.swap_node(pos, {name = "mesecons_delayer:delayer_off_1", param2=node.param2})
|
|
||||||
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 =
|
||||||
{
|
{
|
||||||
@ -122,13 +114,16 @@ minetest.register_node("mesecons_delayer:delayer_off_"..tostring(i), {
|
|||||||
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
|
||||||
minetest.register_node("mesecons_delayer:delayer_on_"..tostring(i), {
|
local on_state = {
|
||||||
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",
|
||||||
@ -137,33 +132,17 @@ minetest.register_node("mesecons_delayer:delayer_on_"..tostring(i), {
|
|||||||
"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},
|
||||||
paramtype = "light",
|
on_punch = function(pos, node, puncher)
|
||||||
paramtype2 = "facedir",
|
if minetest.is_protected(pos, puncher and puncher:get_player_name() or "") then
|
||||||
sunlight_propagates = true,
|
return
|
||||||
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 =
|
||||||
@ -176,8 +155,13 @@ minetest.register_node("mesecons_delayer:delayer_on_"..tostring(i), {
|
|||||||
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({
|
||||||
|
2
mesecons_delayer/mod.conf
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
name = mesecons_delayer
|
||||||
|
depends = mesecons
|
Before Width: | Height: | Size: 438 B After Width: | Height: | Size: 221 B |
Before Width: | Height: | Size: 226 B After Width: | Height: | Size: 176 B |
Before Width: | Height: | Size: 228 B After Width: | Height: | Size: 187 B |
Before Width: | Height: | Size: 562 B After Width: | Height: | Size: 448 B |
Before Width: | Height: | Size: 558 B After Width: | Height: | Size: 449 B |
Before Width: | Height: | Size: 561 B After Width: | Height: | Size: 448 B |
Before Width: | Height: | Size: 556 B After Width: | Height: | Size: 446 B |
Before Width: | Height: | Size: 635 B After Width: | Height: | Size: 541 B |
Before Width: | Height: | Size: 632 B After Width: | Height: | Size: 541 B |
Before Width: | Height: | Size: 635 B After Width: | Height: | Size: 541 B |
Before Width: | Height: | Size: 630 B After Width: | Height: | Size: 538 B |
Before Width: | Height: | Size: 229 B After Width: | Height: | Size: 173 B |
Before Width: | Height: | Size: 234 B After Width: | Height: | Size: 181 B |
@ -1,2 +0,0 @@
|
|||||||
mesecons
|
|
||||||
mesecons_materials
|
|
11
mesecons_detector/doc/nodedetector/description.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
The node detector is a receptor. It changes its state when either any node
|
||||||
|
or a specific node is detected. Right-click it to set a nodename to scan for.
|
||||||
|
It can also receive digiline signals. For example, you can send
|
||||||
|
<code>{distance=4, scanname="default:dirt"}</code>
|
||||||
|
to set distance to 4 and scan for dirt. You can omit either parameter.
|
||||||
|
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.
|
||||||
|
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.
|
BIN
mesecons_detector/doc/nodedetector/preview.png
Normal file
After Width: | Height: | Size: 43 KiB |
BIN
mesecons_detector/doc/nodedetector/recipe.png
Normal file
After Width: | Height: | Size: 7.3 KiB |
5
mesecons_detector/doc/objectdetector/description.html
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
The object detector is a receptor. It changes its state when a player approaches.
|
||||||
|
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.
|
||||||
|
Automatic scanning with Mesecons output only works when the detector is in an active block, but Digilines queries always work.
|
BIN
mesecons_detector/doc/objectdetector/preview.png
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
mesecons_detector/doc/objectdetector/recipe.png
Normal file
After Width: | Height: | Size: 7.1 KiB |
@ -1,18 +1,22 @@
|
|||||||
|
local GET_COMMAND = "GET"
|
||||||
|
|
||||||
-- Object detector
|
-- Object detector
|
||||||
-- Detects players in a certain radius
|
-- Detects players in a certain radius
|
||||||
-- The radius can be specified in mesecons/settings.lua
|
-- The radius can be specified in mesecons/settings.lua
|
||||||
|
|
||||||
local object_detector_make_formspec = function (pos)
|
local function object_detector_make_formspec(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;9,2;scanname;Name of player to scan for (empty for any):;${scanname}]"..
|
||||||
"field[0.3,1.5;4,2;digiline_channel;Digiline Channel (optional):;${digiline_channel}]")
|
"field[0.3,1.5;4,2;digiline_channel;Digiline Channel (optional):;${digiline_channel}]"..
|
||||||
|
"button_exit[7,0.75;2,3;;Save]")
|
||||||
end
|
end
|
||||||
|
|
||||||
local object_detector_on_receive_fields = function(pos, formname, fields)
|
local function object_detector_on_receive_fields(pos, formname, fields, sender)
|
||||||
if fields.quit then
|
if not fields.scanname or not fields.digiline_channel then return end
|
||||||
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)
|
||||||
@ -20,25 +24,38 @@ local object_detector_on_receive_fields = function(pos, formname, fields)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- returns true if player was found, false if not
|
-- returns true if player was found, false if not
|
||||||
local object_detector_scan = function (pos)
|
local function object_detector_scan(pos)
|
||||||
local objs = minetest.get_objects_inside_radius(pos, OBJECT_DETECTOR_RADIUS)
|
local objs = minetest.get_objects_inside_radius(pos, mesecon.setting("detector_radius", 6))
|
||||||
for k, obj in pairs(objs) do
|
|
||||||
local isname = obj:get_player_name() -- "" is returned if it is not a player; "" ~= nil!
|
-- abort if no scan results were found
|
||||||
|
if next(objs) == nil then return false end
|
||||||
|
|
||||||
local scanname = minetest.get_meta(pos):get_string("scanname")
|
local scanname = minetest.get_meta(pos):get_string("scanname")
|
||||||
if (isname == scanname and isname ~= "") or (isname ~= "" and scanname == "") then -- player with scanname found or not scanname specified
|
local scan_for = {}
|
||||||
|
for _, str in pairs(string.split(scanname:gsub(" ", ""), ",")) do
|
||||||
|
scan_for[str] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
local every_player = scanname == ""
|
||||||
|
for _, obj in pairs(objs) do
|
||||||
|
-- "" is returned if it is not a player; "" ~= nil; so only handle objects with foundname ~= ""
|
||||||
|
local foundname = obj:get_player_name()
|
||||||
|
if foundname ~= "" then
|
||||||
|
if every_player or scan_for[foundname] then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set player name when receiving a digiline signal on a specific channel
|
-- set player name when receiving a digiline signal on a specific channel
|
||||||
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)
|
||||||
local active_channel = meta:get_string("digiline_channel")
|
if channel == meta:get_string("digiline_channel") then
|
||||||
if channel == active_channel then
|
|
||||||
meta:set_string("scanname", msg)
|
meta:set_string("scanname", msg)
|
||||||
object_detector_make_formspec(pos)
|
object_detector_make_formspec(pos)
|
||||||
end
|
end
|
||||||
@ -49,31 +66,37 @@ 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",
|
||||||
mesecons = {receptor = {
|
mesecons = {receptor = {
|
||||||
state = mesecon.state.off
|
state = mesecon.state.off,
|
||||||
|
rules = mesecon.rules.pplate
|
||||||
}},
|
}},
|
||||||
on_construct = object_detector_make_formspec,
|
on_construct = object_detector_make_formspec,
|
||||||
on_receive_fields = object_detector_on_receive_fields,
|
on_receive_fields = object_detector_on_receive_fields,
|
||||||
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',
|
||||||
mesecons = {receptor = {
|
mesecons = {receptor = {
|
||||||
state = mesecon.state.on
|
state = mesecon.state.on,
|
||||||
|
rules = mesecon.rules.pplate
|
||||||
}},
|
}},
|
||||||
on_construct = object_detector_make_formspec,
|
on_construct = object_detector_make_formspec,
|
||||||
on_receive_fields = object_detector_on_receive_fields,
|
on_receive_fields = object_detector_on_receive_fields,
|
||||||
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({
|
||||||
@ -85,26 +108,229 @@ minetest.register_craft({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_abm(
|
minetest.register_craft({
|
||||||
{nodenames = {"mesecons_detector:object_detector_off"},
|
output = 'mesecons_detector:object_detector_off',
|
||||||
interval = 1.0,
|
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({
|
||||||
|
nodenames = {"mesecons_detector:object_detector_off"},
|
||||||
|
interval = 1,
|
||||||
chance = 1,
|
chance = 1,
|
||||||
action = function(pos)
|
action = function(pos, node)
|
||||||
if object_detector_scan(pos) then
|
if not object_detector_scan(pos) then return end
|
||||||
minetest.swap_node(pos, {name = "mesecons_detector:object_detector_on"})
|
|
||||||
mesecon:receptor_on(pos)
|
node.name = "mesecons_detector:object_detector_on"
|
||||||
end
|
minetest.swap_node(pos, node)
|
||||||
|
mesecon.receptor_on(pos, mesecon.rules.pplate)
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_abm(
|
minetest.register_abm({
|
||||||
{nodenames = {"mesecons_detector:object_detector_on"},
|
nodenames = {"mesecons_detector:object_detector_on"},
|
||||||
interval = 1.0,
|
interval = 1,
|
||||||
chance = 1,
|
chance = 1,
|
||||||
action = function(pos)
|
action = function(pos, node)
|
||||||
if not object_detector_scan(pos) then
|
if object_detector_scan(pos) then return end
|
||||||
minetest.swap_node(pos, {name = "mesecons_detector:object_detector_off"})
|
|
||||||
mesecon:receptor_off(pos)
|
node.name = "mesecons_detector:object_detector_off"
|
||||||
end
|
minetest.swap_node(pos, node)
|
||||||
|
mesecon.receptor_off(pos, mesecon.rules.pplate)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Node detector
|
||||||
|
-- Detects the node in front of it
|
||||||
|
|
||||||
|
local function node_detector_make_formspec(pos)
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
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,1.5;2.5,2;distance;Distance (0-"..mesecon.setting("node_detector_distance_max", 10).."):;${distance}]"..
|
||||||
|
"field[3,1.5;4,2;digiline_channel;Digiline Channel (optional):;${digiline_channel}]"..
|
||||||
|
"button_exit[7,0.75;2,3;;Save]")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function node_detector_on_receive_fields(pos, fieldname, fields, sender)
|
||||||
|
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)
|
||||||
|
meta:set_string("scanname", fields.scanname)
|
||||||
|
meta:set_string("distance", fields.distance or "0")
|
||||||
|
meta:set_string("digiline_channel", fields.digiline_channel)
|
||||||
|
node_detector_make_formspec(pos)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- returns true if node was found, false if not
|
||||||
|
local function node_detector_scan(pos)
|
||||||
|
local node = minetest.get_node_or_nil(pos)
|
||||||
|
if not node then return end
|
||||||
|
|
||||||
|
local 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(
|
||||||
|
vector.subtract(pos, vector.multiply(minetest.facedir_to_dir(node.param2), distance + 1))
|
||||||
|
).name
|
||||||
|
local scanname = meta:get_string("scanname")
|
||||||
|
|
||||||
|
return (frontname == scanname) or
|
||||||
|
(frontname ~= "air" and frontname ~= "ignore" and scanname == "")
|
||||||
|
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
|
||||||
|
local node_detector_digiline = {
|
||||||
|
effector = {
|
||||||
|
action = function(pos, node, channel, msg)
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
|
||||||
|
if channel ~= meta:get_string("digiline_channel") then return end
|
||||||
|
|
||||||
|
if type(msg) == "table" then
|
||||||
|
if msg.distance or msg.scanname then
|
||||||
|
if msg.distance then
|
||||||
|
meta:set_string("distance", msg.distance)
|
||||||
|
end
|
||||||
|
if msg.scanname then
|
||||||
|
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
|
||||||
|
if msg == GET_COMMAND then
|
||||||
|
node_detector_send_node_name(pos, node, channel, meta)
|
||||||
|
else
|
||||||
|
meta:set_string("scanname", msg)
|
||||||
|
node_detector_make_formspec(pos)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
receptor = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
local function after_place_node_detector(pos, placer)
|
||||||
|
local placer_pos = placer:get_pos()
|
||||||
|
if not placer_pos then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
--correct for the player's height
|
||||||
|
if placer:is_player() then
|
||||||
|
placer_pos.y = placer_pos.y + 1.625
|
||||||
|
end
|
||||||
|
|
||||||
|
--correct for 6d facedir
|
||||||
|
local node = minetest.get_node(pos)
|
||||||
|
node.param2 = minetest.dir_to_facedir(vector.subtract(pos, placer_pos), true)
|
||||||
|
minetest.set_node(pos, node)
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_node("mesecons_detector:node_detector_off", {
|
||||||
|
tiles = {"default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "jeija_node_detector_off.png"},
|
||||||
|
paramtype = "light",
|
||||||
|
paramtype2 = "facedir",
|
||||||
|
is_ground_content = false,
|
||||||
|
walkable = true,
|
||||||
|
groups = {cracky=3},
|
||||||
|
description="Node Detector",
|
||||||
|
mesecons = {receptor = {
|
||||||
|
state = mesecon.state.off
|
||||||
|
}},
|
||||||
|
on_construct = node_detector_make_formspec,
|
||||||
|
on_receive_fields = node_detector_on_receive_fields,
|
||||||
|
sounds = default.node_sound_stone_defaults(),
|
||||||
|
digiline = node_detector_digiline,
|
||||||
|
on_blast = mesecon.on_blastnode,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("mesecons_detector:node_detector_on", {
|
||||||
|
tiles = {"default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "jeija_node_detector_on.png"},
|
||||||
|
paramtype = "light",
|
||||||
|
paramtype2 = "facedir",
|
||||||
|
is_ground_content = false,
|
||||||
|
walkable = true,
|
||||||
|
groups = {cracky=3,not_in_creative_inventory=1},
|
||||||
|
drop = 'mesecons_detector:node_detector_off',
|
||||||
|
mesecons = {receptor = {
|
||||||
|
state = mesecon.state.on
|
||||||
|
}},
|
||||||
|
on_construct = node_detector_make_formspec,
|
||||||
|
on_receive_fields = node_detector_on_receive_fields,
|
||||||
|
sounds = default.node_sound_stone_defaults(),
|
||||||
|
digiline = node_detector_digiline,
|
||||||
|
on_blast = mesecon.on_blastnode,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
output = 'mesecons_detector:node_detector_off',
|
||||||
|
recipe = {
|
||||||
|
{"default:steel_ingot", "group:mesecon_conductor_craftable", "default:steel_ingot"},
|
||||||
|
{"default:steel_ingot", "mesecons_luacontroller:luacontroller0000", "default:steel_ingot"},
|
||||||
|
{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_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({
|
||||||
|
nodenames = {"mesecons_detector:node_detector_off"},
|
||||||
|
interval = 1,
|
||||||
|
chance = 1,
|
||||||
|
action = function(pos, node)
|
||||||
|
if not node_detector_scan(pos) then return end
|
||||||
|
|
||||||
|
node.name = "mesecons_detector:node_detector_on"
|
||||||
|
minetest.swap_node(pos, node)
|
||||||
|
mesecon.receptor_on(pos)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_abm({
|
||||||
|
nodenames = {"mesecons_detector:node_detector_on"},
|
||||||
|
interval = 1,
|
||||||
|
chance = 1,
|
||||||
|
action = function(pos, node)
|
||||||
|
if node_detector_scan(pos) then return end
|
||||||
|
|
||||||
|
node.name = "mesecons_detector:node_detector_off"
|
||||||
|
minetest.swap_node(pos, node)
|
||||||
|
mesecon.receptor_off(pos)
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
2
mesecons_detector/mod.conf
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
name = mesecons_detector
|
||||||
|
depends = mesecons, mesecons_materials
|
BIN
mesecons_detector/textures/jeija_node_detector_off.png
Normal file
After Width: | Height: | Size: 640 B |
BIN
mesecons_detector/textures/jeija_node_detector_on.png
Normal file
After Width: | Height: | Size: 687 B |
BIN
mesecons_detector/textures/jeija_object_detector_off.png
Normal file
After Width: | Height: | Size: 655 B |
BIN
mesecons_detector/textures/jeija_object_detector_on.png
Normal file
After Width: | Height: | Size: 693 B |
136
mesecons_doors/init.lua
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
-- Modified, from minetest_game/mods/doors/init.lua
|
||||||
|
local function on_rightclick(pos, dir, check_name, replace, replace_dir, params)
|
||||||
|
pos.y = pos.y + dir
|
||||||
|
if not minetest.get_node(pos).name == check_name then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local p2 = minetest.get_node(pos).param2
|
||||||
|
p2 = params[p2 + 1]
|
||||||
|
|
||||||
|
minetest.swap_node(pos, {name = replace_dir, param2 = p2})
|
||||||
|
|
||||||
|
pos.y = pos.y - dir
|
||||||
|
minetest.swap_node(pos, {name = replace, param2 = p2})
|
||||||
|
|
||||||
|
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)
|
||||||
|
else
|
||||||
|
minetest.sound_play("doors_door_open", { pos = pos, gain = 0.3, max_hear_distance = 10 }, true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function meseconify_door(name)
|
||||||
|
if minetest.registered_items[name .. "_b_1"] then
|
||||||
|
-- old style double-node doors
|
||||||
|
local function toggle_state1 (pos, node)
|
||||||
|
on_rightclick(pos, 1, name.."_t_1", name.."_b_2", name.."_t_2", {1,2,3,0})
|
||||||
|
end
|
||||||
|
|
||||||
|
local function toggle_state2 (pos, node)
|
||||||
|
on_rightclick(pos, 1, name.."_t_2", name.."_b_1", name.."_t_1", {3,0,1,2})
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.override_item(name.."_b_1", {
|
||||||
|
mesecons = {effector = {
|
||||||
|
action_on = toggle_state1,
|
||||||
|
action_off = toggle_state1,
|
||||||
|
rules = mesecon.rules.pplate
|
||||||
|
}}
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.override_item(name.."_b_2", {
|
||||||
|
mesecons = {effector = {
|
||||||
|
action_on = toggle_state2,
|
||||||
|
action_off = toggle_state2,
|
||||||
|
rules = mesecon.rules.pplate
|
||||||
|
}}
|
||||||
|
})
|
||||||
|
elseif minetest.registered_items[name .. "_a"] then
|
||||||
|
-- new style mesh node based doors
|
||||||
|
local override = {
|
||||||
|
mesecons = {effector = {
|
||||||
|
action_on = function(pos, node)
|
||||||
|
local door = doors.get(pos)
|
||||||
|
if door then
|
||||||
|
door:open()
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
action_off = function(pos, node)
|
||||||
|
local door = doors.get(pos)
|
||||||
|
if door then
|
||||||
|
door:close()
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
rules = mesecon.rules.pplate
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
minetest.override_item(name .. "_a", override)
|
||||||
|
minetest.override_item(name .. "_b", override)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
meseconify_door("doors:door_wood")
|
||||||
|
meseconify_door("doors:door_steel")
|
||||||
|
meseconify_door("doors:door_glass")
|
||||||
|
meseconify_door("doors:door_obsidian_glass")
|
||||||
|
meseconify_door("xpanes:door_steel_bar")
|
||||||
|
|
||||||
|
-- Trapdoor
|
||||||
|
local function trapdoor_switch(pos, node)
|
||||||
|
local state = minetest.get_meta(pos):get_int("state")
|
||||||
|
|
||||||
|
if state == 1 then
|
||||||
|
minetest.sound_play("doors_door_close", { pos = pos, gain = 0.3, max_hear_distance = 10 }, true)
|
||||||
|
minetest.set_node(pos, {name="doors:trapdoor", param2 = node.param2})
|
||||||
|
else
|
||||||
|
minetest.sound_play("doors_door_open", { pos = pos, gain = 0.3, max_hear_distance = 10 }, true)
|
||||||
|
minetest.set_node(pos, {name="doors:trapdoor_open", param2 = node.param2})
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.get_meta(pos):set_int("state", state == 1 and 0 or 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
if doors and doors.get then
|
||||||
|
local override = {
|
||||||
|
mesecons = {effector = {
|
||||||
|
action_on = function(pos, node)
|
||||||
|
local door = doors.get(pos)
|
||||||
|
if door then
|
||||||
|
door:open()
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
action_off = function(pos, node)
|
||||||
|
local door = doors.get(pos)
|
||||||
|
if door then
|
||||||
|
door:close()
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
minetest.override_item("doors:trapdoor", override)
|
||||||
|
minetest.override_item("doors:trapdoor_open", override)
|
||||||
|
minetest.override_item("doors:trapdoor_steel", 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
|
||||||
|
if minetest.registered_nodes["doors:trapdoor"] then
|
||||||
|
minetest.override_item("doors:trapdoor", {
|
||||||
|
mesecons = {effector = {
|
||||||
|
action_on = trapdoor_switch,
|
||||||
|
action_off = trapdoor_switch
|
||||||
|
}},
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.override_item("doors:trapdoor_open", {
|
||||||
|
mesecons = {effector = {
|
||||||
|
action_on = trapdoor_switch,
|
||||||
|
action_off = trapdoor_switch
|
||||||
|
}},
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
3
mesecons_doors/mod.conf
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
name = mesecons_doors
|
||||||
|
depends = mesecons, doors
|
||||||
|
optional_depends = xpanes
|
@ -1,12 +1,8 @@
|
|||||||
local corner_nodebox = {
|
local screwdriver_exists = minetest.global_exists("screwdriver")
|
||||||
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-0.001, -18/32, -16/32, 5/32, -12/32, 5/32 },
|
fixed = { -16/32, -16/32, -16/32, 5/32, -12/32, 5/32 },
|
||||||
}
|
}
|
||||||
|
|
||||||
local corner_get_rules = function (node)
|
local corner_get_rules = function (node)
|
||||||
@ -15,69 +11,68 @@ local corner_get_rules = function (node)
|
|||||||
{x = 0, y = 0, z = -1}}
|
{x = 0, y = 0, z = -1}}
|
||||||
|
|
||||||
for i = 0, node.param2 do
|
for i = 0, node.param2 do
|
||||||
rules = mesecon:rotate_rules_left(rules)
|
rules = mesecon.rotate_rules_left(rules)
|
||||||
end
|
end
|
||||||
|
|
||||||
return rules
|
return rules
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_node("mesecons_extrawires:corner_on", {
|
minetest.register_node("mesecons_extrawires:corner_on", {
|
||||||
drawtype = "nodebox",
|
drawtype = "mesh",
|
||||||
|
mesh = "mesecons_extrawires_corner.obj",
|
||||||
tiles = {
|
tiles = {
|
||||||
"jeija_insulated_wire_curved_tb_on.png",
|
{ name = "jeija_insulated_wire_sides_on.png", backface_culling = true },
|
||||||
"jeija_insulated_wire_curved_tb_on.png^[transformR270",
|
{ name = "jeija_insulated_wire_ends_on.png", backface_culling = true },
|
||||||
"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,
|
|
||||||
groups = {dig_immediate = 3, not_in_creative_inventory = 1},
|
groups = {dig_immediate = 3, not_in_creative_inventory = 1},
|
||||||
drop = "mesecons_extrawires:corner_off",
|
drop = "mesecons_extrawires:corner_off",
|
||||||
|
sounds = default.node_sound_defaults(),
|
||||||
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 = "nodebox",
|
drawtype = "mesh",
|
||||||
description = "Mesecon Corner",
|
description = "Insulated Mesecon Corner",
|
||||||
|
mesh = "mesecons_extrawires_corner.obj",
|
||||||
tiles = {
|
tiles = {
|
||||||
"jeija_insulated_wire_curved_tb_off.png",
|
{ name = "jeija_insulated_wire_sides_off.png", backface_culling = true },
|
||||||
"jeija_insulated_wire_curved_tb_off.png^[transformR270",
|
{ name = "jeija_insulated_wire_ends_off.png", backface_culling = true },
|
||||||
"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,
|
|
||||||
groups = {dig_immediate = 3},
|
groups = {dig_immediate = 3},
|
||||||
|
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", ""},
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
function crossover_get_rules(node)
|
local function crossover_get_rules(node)
|
||||||
return {
|
return {
|
||||||
{--first wire
|
{--first wire
|
||||||
{x=-1,y=0,z=0},
|
{x=-1,y=0,z=0},
|
||||||
@ -19,143 +19,110 @@ local crossover_states = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
minetest.register_node("mesecons_extrawires:crossover_off", {
|
minetest.register_node("mesecons_extrawires:crossover_off", {
|
||||||
description = "Insulated Crossover",
|
description = "Insulated Mesecon Crossover",
|
||||||
drawtype = "nodebox",
|
drawtype = "mesh",
|
||||||
|
mesh = "mesecons_extrawires_crossover.b3d",
|
||||||
tiles = {
|
tiles = {
|
||||||
"jeija_insulated_wire_crossing_tb_off.png",
|
"jeija_insulated_wire_ends_off.png",
|
||||||
"jeija_insulated_wire_crossing_tb_off.png",
|
"jeija_insulated_wire_sides_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-0.0001, -18/32, -16/32-0.001, 16/32+0.001, -5/32, 16/32+0.001}},
|
selection_box = {type="fixed", fixed={-16/32, -16/32, -16/32, 16/32, -5/32, 16/32}},
|
||||||
node_box = {
|
groups = {dig_immediate=3, mesecon=3},
|
||||||
type = "fixed",
|
sounds = default.node_sound_defaults(),
|
||||||
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, mesecon_conductor_craftable=1},
|
|
||||||
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 = "nodebox",
|
drawtype = "mesh",
|
||||||
|
mesh = "mesecons_extrawires_crossover.b3d",
|
||||||
tiles = {
|
tiles = {
|
||||||
"jeija_insulated_wire_crossing_tb_01.png",
|
"jeija_insulated_wire_ends_on.png",
|
||||||
"jeija_insulated_wire_crossing_tb_01.png",
|
"jeija_insulated_wire_sides_on.png",
|
||||||
"jeija_insulated_wire_ends_01x.png",
|
"jeija_insulated_wire_sides_off.png",
|
||||||
"jeija_insulated_wire_ends_01x.png",
|
"jeija_insulated_wire_ends_off.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-0.0001, -18/32, -16/32-0.001, 16/32+0.001, -5/32, 16/32+0.001}},
|
selection_box = {type="fixed", fixed={-16/32, -16/32, -16/32, 16/32, -5/32, 16/32}},
|
||||||
node_box = {
|
groups = {dig_immediate=3, mesecon=3, not_in_creative_inventory=1},
|
||||||
type = "fixed",
|
sounds = default.node_sound_defaults(),
|
||||||
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, mesecon_conductor_craftable=1, not_in_creative_inventory=1},
|
|
||||||
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 = "nodebox",
|
drawtype = "mesh",
|
||||||
|
mesh = "mesecons_extrawires_crossover.b3d",
|
||||||
tiles = {
|
tiles = {
|
||||||
"jeija_insulated_wire_crossing_tb_10.png",
|
"jeija_insulated_wire_ends_off.png",
|
||||||
"jeija_insulated_wire_crossing_tb_10.png",
|
"jeija_insulated_wire_sides_off.png",
|
||||||
"jeija_insulated_wire_ends_10x.png",
|
"jeija_insulated_wire_sides_on.png",
|
||||||
"jeija_insulated_wire_ends_10x.png",
|
"jeija_insulated_wire_ends_on.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-0.0001, -18/32, -16/32-0.001, 16/32+0.001, -5/32, 16/32+0.001}},
|
selection_box = {type="fixed", fixed={-16/32, -16/32, -16/32, 16/32, -5/32, 16/32}},
|
||||||
node_box = {
|
groups = {dig_immediate=3, mesecon=3, not_in_creative_inventory=1},
|
||||||
type = "fixed",
|
sounds = default.node_sound_defaults(),
|
||||||
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, mesecon_conductor_craftable=1, not_in_creative_inventory=1},
|
|
||||||
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 = "nodebox",
|
drawtype = "mesh",
|
||||||
|
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-0.0001, -18/32, -16/32-0.001, 16/32+0.001, -5/32, 16/32+0.001}},
|
selection_box = {type="fixed", fixed={-16/32, -16/32, -16/32, 16/32, -5/32, 16/32}},
|
||||||
node_box = {
|
groups = {dig_immediate=3, mesecon=3, not_in_creative_inventory=1},
|
||||||
type = "fixed",
|
sounds = default.node_sound_defaults(),
|
||||||
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, mesecon_conductor_craftable=1, not_in_creative_inventory=1},
|
|
||||||
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({
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
default
|
|
||||||
mesecons
|
|
1
mesecons_extrawires/doc/corner/description.html
Normal file
@ -0,0 +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.
|
BIN
mesecons_extrawires/doc/corner/preview.png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
mesecons_extrawires/doc/corner/recipe.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
1
mesecons_extrawires/doc/crossing/description.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
Insulated crossing are conductors that conduct two signals between the opposing sides, the signals are insulated to each other. Like uninsulated wires, they work through unloaded blocks.
|
BIN
mesecons_extrawires/doc/crossing/preview.png
Normal file
After Width: | Height: | Size: 58 KiB |
BIN
mesecons_extrawires/doc/crossing/recipe.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
1
mesecons_extrawires/doc/mese/description.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
The basic prerequesite for mesecons, can be crafted into wires and other stuff. Have a look at the <a href="http://wiki.minetest.net/Mese">Minetest Wiki</a> for more information. Mese is a conductor. It conducts in all six directions: Up/Down/Left/Right/Forward/Backward. Like horizontal wires, Mese conduction works through unloaded blocks.
|