Compare commits
	
		
			247 Commits
		
	
	
		
			zefram_doo
			...
			de4eeebd3b
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 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 | ||
|  | b9178dfcaa | 
							
								
								
									
										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 |  | ||||||
| @@ -1,114 +1,149 @@ | |||||||
| mesecon.queue.actions={} -- contains all ActionQueue actions | --[[ | ||||||
|  | Mesecons uses something it calls an ActionQueue. | ||||||
|  |  | ||||||
| function mesecon.queue:add_function(name, func) | The ActionQueue holds functions and actions. | ||||||
| 	mesecon.queue.funcs[name] = func | 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 | end | ||||||
|  |  | ||||||
| -- If add_action with twice the same overwritecheck and same position are called, the first one is overwritten | -- If add_action with twice the same overwritecheck and same position are called, the first one is overwritten | ||||||
| -- use overwritecheck nil to never overwrite, but just add the event to the queue | -- use overwritecheck nil to never overwrite, but just add the event to the queue | ||||||
| -- priority specifies the order actions are executed within one globalstep, highest first | -- priority specifies the order actions are executed within one globalstep, highest first | ||||||
| -- should be between 0 and 1 | -- should be between 0 and 1 | ||||||
| function mesecon.queue:add_action(pos, func, params, time, overwritecheck, priority) | function queue:add_action(pos, func, params, time, overwritecheck, priority) | ||||||
| 	-- Create Action Table: | 	-- Create Action Table: | ||||||
| 	time = time or 0 -- time <= 0 --> execute, time > 0 --> wait time until execution | 	time = time or 0 -- time <= 0 --> execute, time > 0 --> wait time until execution | ||||||
| 	priority = priority or 1 | 	priority = priority or 1 | ||||||
| 	local action = {	pos=mesecon:tablecopy(pos), | 	local action = { | ||||||
| 				func=func, | 		pos = mesecon.tablecopy(pos), | ||||||
| 				params=mesecon:tablecopy(params), | 		func = func, | ||||||
| 				time=time, | 		params = mesecon.tablecopy(params or {}), | ||||||
| 				owcheck=(overwritecheck and mesecon:tablecopy(overwritecheck)) or nil, | 		time = time, | ||||||
| 				priority=priority} | 		owcheck = (overwritecheck and mesecon.tablecopy(overwritecheck)) or nil, | ||||||
|  | 		priority = priority | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	local toremove = nil | 	 -- check if old action has to be overwritten / removed: | ||||||
| 	-- Otherwise, add the action to the queue | 	if overwritecheck then | ||||||
| 	if overwritecheck then -- check if old action has to be overwritten / removed: | 		for i, ac in ipairs(queue.actions) do | ||||||
| 		for i, ac in ipairs(mesecon.queue.actions) do | 			if vector.equals(pos, ac.pos) | ||||||
| 			if(mesecon:cmpPos(pos, ac.pos) | 					and mesecon.cmpAny(overwritecheck, ac.owcheck) then | ||||||
| 			and mesecon:cmpAny(overwritecheck, ac.owcheck)) then | 				-- remove the old action | ||||||
| 				toremove = i | 				table.remove(queue.actions, i) | ||||||
| 				break | 				break | ||||||
| 			end | 			end | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	if (toremove ~= nil) then | 	table.insert(queue.actions, action) | ||||||
| 		table.remove(mesecon.queue.actions, toremove) |  | ||||||
| 	end |  | ||||||
|  |  | ||||||
| 	table.insert(mesecon.queue.actions, action) |  | ||||||
| end | end | ||||||
|  |  | ||||||
| -- execute the stored functions on a globalstep | -- execute the stored functions on a globalstep | ||||||
| -- if however, the pos of a function is not loaded (get_node_or_nil == nil), do NOT execute the function | -- if however, the pos of a function is not loaded (get_node_or_nil == nil), do NOT execute the function | ||||||
| -- this makes sure that resuming mesecons circuits when restarting minetest works fine | -- 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 | -- However, even that does not work in some cases, that's why we delay the time the globalsteps | ||||||
| -- start to be execute by 5 seconds | -- start to be execute by 4 seconds | ||||||
| local get_highest_priority = function (actions) |  | ||||||
| 	local highestp = -1, highesti |  | ||||||
| 	for i, ac in ipairs(actions) do |  | ||||||
| 		if ac.priority > highestp then |  | ||||||
| 			highestp = ac.priority |  | ||||||
| 			highesti = i |  | ||||||
| 		end |  | ||||||
| 	end |  | ||||||
|  |  | ||||||
| 	return highesti | local function globalstep_func(dtime) | ||||||
| end | 	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 = {} | ||||||
|  |  | ||||||
| local m_time = 0 | 	for _, ac in ipairs(actions) do | ||||||
| minetest.register_globalstep(function (dtime) |  | ||||||
| 	m_time = m_time + dtime |  | ||||||
| 	if (m_time < MESECONS_RESUMETIME) then return end -- don't even try if server has not been running for XY seconds |  | ||||||
| 	local actions = mesecon:tablecopy(mesecon.queue.actions) |  | ||||||
| 	local actions_now={} |  | ||||||
|  |  | ||||||
| 	mesecon.queue.actions = {} |  | ||||||
|  |  | ||||||
| 	-- sort actions into two categories: |  | ||||||
| 	-- those toexecute now (actions_now) and those to execute later (mesecon.queue.actions) |  | ||||||
| 	for i, ac in ipairs(actions) do |  | ||||||
| 		if ac.time > 0 then | 		if ac.time > 0 then | ||||||
| 			ac.time = ac.time - dtime -- executed later | 			-- action ac is to be executed later | ||||||
| 			table.insert(mesecon.queue.actions, ac) | 			-- ~> insert into queue.actions | ||||||
|  | 			ac.time = ac.time - dtime | ||||||
|  | 			table.insert(queue.actions, ac) | ||||||
| 		else | 		else | ||||||
|  | 			-- action ac is to be executed now | ||||||
|  | 			-- ~> insert into actions_now | ||||||
| 			table.insert(actions_now, ac) | 			table.insert(actions_now, ac) | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	while(#actions_now > 0) do -- execute highest priorities first, until all are executed | 	-- stable-sort the executed actions after their priority | ||||||
| 		local hp = get_highest_priority(actions_now) | 	-- some constructions might depend on the execution order, hence we first | ||||||
| 		mesecon.queue:execute(actions_now[hp]) | 	-- execute the actions that had a lower index in actions_now | ||||||
| 		table.remove(actions_now, hp) | 	local old_action_order = {} | ||||||
|  | 	for i, ac in ipairs(actions_now) do | ||||||
|  | 		old_action_order[ac] = i | ||||||
| 	end | 	end | ||||||
| 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) | ||||||
|  |  | ||||||
| function mesecon.queue:execute(action) | 	-- execute highest priorities first, until all are executed | ||||||
| 	mesecon.queue.funcs[action.func](action.pos, unpack(action.params)) | 	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 | end | ||||||
|  |  | ||||||
|  |  | ||||||
| -- Store and read the ActionQueue to / from a file | -- Store and read the ActionQueue to / from a file | ||||||
| -- so that upcoming actions are remembered when the game | -- so that upcoming actions are remembered when the game | ||||||
| -- is restarted | -- is restarted | ||||||
|  | queue.actions = mesecon.file2table("mesecon_actionqueue") | ||||||
| local wpath = minetest.get_worldpath() |  | ||||||
| local function file2table(filename) |  | ||||||
| 	local f = io.open(filename, "r") |  | ||||||
| 	if f==nil then return {} end |  | ||||||
| 	local t = f:read("*all") |  | ||||||
| 	f:close() |  | ||||||
| 	if t=="" or t==nil then return {} end |  | ||||||
| 	return minetest.deserialize(t) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function table2file(filename, table) |  | ||||||
| 	local f = io.open(filename, "w") |  | ||||||
| 	f:write(minetest.serialize(table)) |  | ||||||
| 	f:close() |  | ||||||
| end |  | ||||||
|  |  | ||||||
| mesecon.queue.actions = file2table(wpath.."/mesecon_actionqueue") |  | ||||||
|  |  | ||||||
| minetest.register_on_shutdown(function() | minetest.register_on_shutdown(function() | ||||||
| 	mesecon.queue.actions = table2file(wpath.."/mesecon_actionqueue", mesecon.queue.actions) | 	mesecon.table2file("mesecon_actionqueue", queue.actions) | ||||||
| end) | 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 | ||||||
| -- | -- | ||||||
| -- | -- | ||||||
| -- | -- | ||||||
| @@ -47,15 +47,14 @@ mesecon.queue.funcs={} -- contains all ActionQueue functions | |||||||
| -- Settings | -- Settings | ||||||
| dofile(minetest.get_modpath("mesecons").."/settings.lua") | dofile(minetest.get_modpath("mesecons").."/settings.lua") | ||||||
|  |  | ||||||
| -- Presets (eg default rules) |  | ||||||
| dofile(minetest.get_modpath("mesecons").."/presets.lua"); |  | ||||||
|  |  | ||||||
|  |  | ||||||
| -- Utilities like comparing positions, | -- Utilities like comparing positions, | ||||||
| -- adding positions and rules, | -- adding positions and rules, | ||||||
| -- mostly things that make the source look cleaner | -- mostly things that make the source look cleaner | ||||||
| dofile(minetest.get_modpath("mesecons").."/util.lua"); | dofile(minetest.get_modpath("mesecons").."/util.lua"); | ||||||
|  |  | ||||||
|  | -- Presets (eg default rules) | ||||||
|  | dofile(minetest.get_modpath("mesecons").."/presets.lua"); | ||||||
|  |  | ||||||
| -- The ActionQueue | -- The ActionQueue | ||||||
| -- Saves all the actions that have to be execute in the future | -- Saves all the actions that have to be execute in the future | ||||||
| dofile(minetest.get_modpath("mesecons").."/actionqueue.lua"); | dofile(minetest.get_modpath("mesecons").."/actionqueue.lua"); | ||||||
| @@ -67,75 +66,63 @@ dofile(minetest.get_modpath("mesecons").."/actionqueue.lua"); | |||||||
| -- like calling action_on/off/change | -- like calling action_on/off/change | ||||||
| dofile(minetest.get_modpath("mesecons").."/internal.lua"); | dofile(minetest.get_modpath("mesecons").."/internal.lua"); | ||||||
|  |  | ||||||
| -- Deprecated stuff |  | ||||||
| -- To be removed in future releases |  | ||||||
| -- Currently there is nothing here |  | ||||||
| dofile(minetest.get_modpath("mesecons").."/legacy.lua"); |  | ||||||
|  |  | ||||||
| -- API | -- API | ||||||
| -- these are the only functions you need to remember | -- these are the only functions you need to remember | ||||||
|  |  | ||||||
| mesecon.queue:add_function("receptor_on", function (pos, rules) | mesecon.queue:add_function("receptor_on", function (pos, rules) | ||||||
|  | 	mesecon.vm_begin() | ||||||
|  |  | ||||||
| 	rules = rules or mesecon.rules.default | 	rules = rules or mesecon.rules.default | ||||||
|  |  | ||||||
| 	-- if area (any of the rule targets) is not loaded, keep trying and call this again later | 	-- Call turnon on all linking positions | ||||||
| 	for _, rule in ipairs(mesecon:flattenrules(rules)) do | 	for _, rule in ipairs(mesecon.flattenrules(rules)) do | ||||||
| 		local np = mesecon:addPosRule(pos, rule) | 		local np = vector.add(pos, rule) | ||||||
| 		-- if area is not loaded, keep trying | 		local rulenames = mesecon.rules_link_rule_all(pos, rule) | ||||||
| 		if minetest.get_node_or_nil(np) == nil then | 		for _, rulename in ipairs(rulenames) do | ||||||
| 			mesecon.queue:add_action(pos, "receptor_on", {rules}, nil, rules) | 			mesecon.turnon(np, rulename) | ||||||
| 			return |  | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	-- execute action | 	mesecon.vm_commit() | ||||||
| 	for _, rule in ipairs(mesecon:flattenrules(rules)) do |  | ||||||
| 		local np = mesecon:addPosRule(pos, rule) |  | ||||||
| 		local rulenames = mesecon:rules_link_rule_all(pos, rule) |  | ||||||
| 		for _, rulename in ipairs(rulenames) do |  | ||||||
| 			mesecon:turnon(np, rulename) |  | ||||||
| 		end |  | ||||||
| 	end |  | ||||||
| end) | end) | ||||||
|  |  | ||||||
| function mesecon:receptor_on(pos, rules) | function mesecon.receptor_on(pos, rules) | ||||||
| 	mesecon.queue:add_action(pos, "receptor_on", {rules}, nil, rules) | 	mesecon.queue:add_action(pos, "receptor_on", {rules}, nil, rules) | ||||||
| end | end | ||||||
|  |  | ||||||
| mesecon.queue:add_function("receptor_off", function (pos, rules) | mesecon.queue:add_function("receptor_off", function (pos, rules) | ||||||
| 	rules = rules or mesecon.rules.default | 	rules = rules or mesecon.rules.default | ||||||
|  |  | ||||||
| 	-- if area (any of the rule targets) is not loaded, keep trying and call this again later | 	-- Call turnoff on all linking positions | ||||||
| 	for _, rule in ipairs(mesecon:flattenrules(rules)) do | 	for _, rule in ipairs(mesecon.flattenrules(rules)) do | ||||||
| 		local np = mesecon:addPosRule(pos, rule) | 		local np = vector.add(pos, rule) | ||||||
| 		if minetest.get_node_or_nil(np) == nil then | 		local rulenames = mesecon.rules_link_rule_all(pos, rule) | ||||||
| 			mesecon.queue:add_action(pos, "receptor_off", {rules}, nil, rules) |  | ||||||
| 			return |  | ||||||
| 		end |  | ||||||
| 	end |  | ||||||
|  |  | ||||||
| 	for _, rule in ipairs(mesecon:flattenrules(rules)) do |  | ||||||
| 		local np = mesecon:addPosRule(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) | ||||||
|  |  | ||||||
|  | 			-- Turnoff returns true if turnoff process was successful, no onstate receptor | ||||||
|  | 			-- was found along the way. Commit changes that were made in voxelmanip. If turnoff | ||||||
|  | 			-- returns true, an onstate receptor was found, abort voxelmanip transaction. | ||||||
|  | 			if (mesecon.turnoff(np, rulename)) then | ||||||
|  | 				mesecon.vm_commit() | ||||||
| 			else | 			else | ||||||
| 				mesecon:changesignal(np, minetest.get_node(np), rulename, mesecon.state.off, 2) | 				mesecon.vm_abort() | ||||||
| 			end | 			end | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
| end) | end) | ||||||
|  |  | ||||||
| function mesecon:receptor_off(pos, rules) | function mesecon.receptor_off(pos, rules) | ||||||
| 	mesecon.queue:add_action(pos, "receptor_off", {rules}, nil, rules) | 	mesecon.queue:add_action(pos, "receptor_off", {rules}, nil, rules) | ||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| print("[OK] Mesecons") | print("[OK] Mesecons") | ||||||
|  |  | ||||||
| --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, recdepth)		--> Activates   the effector node at the specific pos (calls nodedef.mesecons.effector.action_on), higher recdepths are executed later | -- 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, recdepth)		--> 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; Uses third parameter recdepth internally to determine how far away the current node is from the initial pos as it uses recursion | -- 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; Uses third parameter recdepth internally to determine how far away the current node is from the initial pos as it uses recursion |  | ||||||
| -- 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.mergetable(mesecon.get_any_inputrules(node) or {}, | ||||||
|  | 		mesecon.get_any_outputrules(node) or {}) | ||||||
| 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 | ||||||
| @@ -183,159 +181,162 @@ end | |||||||
|  |  | ||||||
| -- Activation: | -- Activation: | ||||||
| mesecon.queue:add_function("activate", function (pos, rulename) | mesecon.queue:add_function("activate", function (pos, rulename) | ||||||
| 	node = minetest.get_node(pos) | 	local node = mesecon.get_node_force(pos) | ||||||
| 	effector = mesecon:get_effector(node.name) | 	if not node then return end | ||||||
|  |  | ||||||
|  | 	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) | ||||||
|  |  | ||||||
| function mesecon:activate(pos, node, rulename, recdepth) | function mesecon.activate(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:activate(pos, node, rule, recdepth + 1) | 			mesecon.activate(pos, node, rule, depth + 1) | ||||||
| 		end | 		end | ||||||
| 		return | 		return | ||||||
| 	end | 	end | ||||||
| 	mesecon.queue:add_action(pos, "activate", {rulename}, nil, rulename, 1 / recdepth) | 	mesecon.queue:add_action(pos, "activate", {rulename}, nil, rulename, 1 / depth) | ||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| -- Deactivation | -- Deactivation | ||||||
| mesecon.queue:add_function("deactivate", function (pos, rulename) | mesecon.queue:add_function("deactivate", function (pos, rulename) | ||||||
| 	node = minetest.get_node(pos) | 	local node = mesecon.get_node_force(pos) | ||||||
| 	effector = mesecon:get_effector(node.name) | 	if not node then return end | ||||||
|  |  | ||||||
|  | 	local effector = mesecon.get_effector(node.name) | ||||||
|  |  | ||||||
| 	if effector and effector.action_off then | 	if effector and effector.action_off then | ||||||
| 		effector.action_off(pos, node, rulename) | 		effector.action_off(pos, node, rulename) | ||||||
| 	end | 	end | ||||||
| end) | end) | ||||||
|  |  | ||||||
| function mesecon:deactivate(pos, node, rulename, recdepth) | 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:deactivate(pos, node, rule, recdepth + 1) | 			mesecon.deactivate(pos, node, rule, depth + 1) | ||||||
| 		end | 		end | ||||||
| 		return | 		return | ||||||
| 	end | 	end | ||||||
| 	mesecon.queue:add_action(pos, "deactivate", {rulename}, nil, rulename, 1 / recdepth) | 	mesecon.queue:add_action(pos, "deactivate", {rulename}, nil, rulename, 1 / depth) | ||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| -- Change | -- Change | ||||||
| mesecon.queue:add_function("change", function (pos, rulename, changetype) | mesecon.queue:add_function("change", function (pos, rulename, changetype) | ||||||
| 	node = minetest.get_node(pos) | 	local node = mesecon.get_node_force(pos) | ||||||
| 	effector = mesecon:get_effector(node.name) | 	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, changetype) | 		effector.action_change(pos, node, rulename, changetype) | ||||||
| 	end | 	end | ||||||
| end) | end) | ||||||
|  |  | ||||||
| function mesecon:changesignal(pos, node, rulename, newstate, recdepth) | function mesecon.changesignal(pos, node, rulename, newstate, 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, recdepth + 1) | 			mesecon.changesignal(pos, node, rule, newstate, depth + 1) | ||||||
| 		end | 		end | ||||||
| 		return | 		return | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	mesecon.queue:add_action(pos, "change", {rulename, newstate}, nil, rulename, 1 / recdepth) | 	-- Include "change" in overwritecheck so that it cannot be overwritten | ||||||
| end | 	-- by "active" / "deactivate" that will be called upon the node at the same time. | ||||||
|  | 	local overwritecheck = {"change", rulename} | ||||||
| -- ######### | 	mesecon.queue:add_action(pos, "change", {rulename, newstate}, nil, overwritecheck, 1 / depth) | ||||||
| -- # Rules # "Database" for rulenames |  | ||||||
| -- ######### |  | ||||||
|  |  | ||||||
| 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 | ||||||
| @@ -349,356 +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, recdepth) | -- Turn off an equipotential section starting at `pos`, which outputs in the direction of `link`. | ||||||
| 	recdepth = recdepth or 2 | -- Breadth-first search. Map is abstracted away in a voxelmanip. | ||||||
| 	local node = minetest.get_node(pos) | -- 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(node.name == "ignore") then | 	local depth = 1 | ||||||
| 		-- try turning on later again | 	while frontiers[1] do | ||||||
| 		mesecon.queue:add_action( | 		local f = table.remove(frontiers, 1) | ||||||
| 			pos, "turnon", {rulename, recdepth + 1}, nil, true) | 		local node = mesecon.get_node_force(f.pos) | ||||||
| 	end |  | ||||||
|  |  | ||||||
| 	if mesecon:is_conductor_off(node, rulename) then | 		if not node then | ||||||
| 		local rules = mesecon:conductor_get_rules(node) | 			-- Area does not exist; do nothing | ||||||
|  | 		elseif mesecon.is_conductor_off(node, f.link) then | ||||||
|  | 			local rules = mesecon.conductor_get_rules(node) | ||||||
|  |  | ||||||
| 		if not rulename then | 			-- Call turnon on neighbors | ||||||
| 			for _, rule in ipairs(mesecon:flattenrules(rules)) do | 			for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do | ||||||
| 				if mesecon:connected_to_receptor(pos, rule) then | 				local np = vector.add(f.pos, r) | ||||||
| 					mesecon:turnon(pos, rule, recdepth + 1) | 				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 | ||||||
| 			if(minetest.get_node(np).name == "ignore") then | 				mesecon.activate(f.pos, node, f.link, depth) | ||||||
| 				-- try turning on later again |  | ||||||
| 				mesecon.queue:add_action( |  | ||||||
| 					np, "turnon", {rulename, recdepth + 1}, nil, true) |  | ||||||
| 			else |  | ||||||
| 				local rulenames = mesecon:rules_link_rule_all(pos, rule) |  | ||||||
|  |  | ||||||
| 				for _, rulename in ipairs(rulenames) do |  | ||||||
| 					mesecon:turnon(np, rulename, recdepth + 1) |  | ||||||
| 				end |  | ||||||
| 			end | 			end | ||||||
| 		end | 		end | ||||||
| 	elseif mesecon:is_effector(node.name) then | 		depth = depth + 1 | ||||||
| 		mesecon:changesignal(pos, node, rulename, mesecon.state.on, recdepth) |  | ||||||
| 		if mesecon:is_effector_off(node.name) then |  | ||||||
| 			mesecon:activate(pos, node, rulename, recdepth) |  | ||||||
| 		end |  | ||||||
| 	end | 	end | ||||||
| end | end | ||||||
|  |  | ||||||
| mesecon.queue:add_function("turnon", function (pos, rulename, recdepth) | -- Turn on an equipotential section starting at `pos`, which outputs in the direction of `link`. | ||||||
| 	mesecon:turnon(pos, rulename, recdepth) | -- Breadth-first search. Map is abstracted away in a voxelmanip. | ||||||
| end) | -- 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 = {} | ||||||
|  |  | ||||||
| function mesecon:turnoff(pos, rulename, recdepth) | 	local depth = 1 | ||||||
| 	recdepth = recdepth or 2 | 	while frontiers[1] do | ||||||
| 	local node = minetest.get_node(pos) | 		local f = table.remove(frontiers, 1) | ||||||
|  | 		local node = mesecon.get_node_force(f.pos) | ||||||
|  |  | ||||||
| 	if(node.name == "ignore") then | 		if not node then | ||||||
| 		-- try turning on later again | 			-- Area does not exist; do nothing | ||||||
| 		mesecon.queue:add_action( | 		elseif mesecon.is_conductor_on(node, f.link) then | ||||||
| 			pos, "turnoff", {rulename, recdepth + 1}, nil, true) | 			local rules = mesecon.conductor_get_rules(node) | ||||||
| 	end | 			for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do | ||||||
|  | 				local np = vector.add(f.pos, r) | ||||||
|  |  | ||||||
| 	if mesecon:is_conductor_on(node, rulename) then | 				-- Check if an onstate receptor is connected. If that is the case, | ||||||
| 		local rules = mesecon:conductor_get_rules(node) | 				-- abort this turnoff process by returning false. `receptor_off` will | ||||||
| 		minetest.swap_node(pos, {name = mesecon:get_conductor_off(node, rulename), param2 = node.param2}) | 				-- discard all the changes that we made in the voxelmanip: | ||||||
|  | 				for _, l in ipairs(mesecon.rules_link_rule_all_inverted(f.pos, r)) do | ||||||
| 		for _, rule in ipairs(mesecon:rule2meta(rulename, rules)) do | 					if mesecon.is_receptor_on(mesecon.get_node_force(np).name) then | ||||||
| 			local np = mesecon:addPosRule(pos, rule) | 						return false | ||||||
| 			if(minetest.get_node(np).name == "ignore") then |  | ||||||
| 				-- try turning on later again |  | ||||||
| 				mesecon.queue:add_action( |  | ||||||
| 					np, "turnoff", {rulename, recdepth + 1}, nil, true) |  | ||||||
| 			else |  | ||||||
| 				local rulenames = mesecon:rules_link_rule_all(pos, rule) |  | ||||||
|  |  | ||||||
| 				for _, rulename in ipairs(rulenames) do |  | ||||||
| 					mesecon:turnoff(np, rulename, recdepth + 1) |  | ||||||
| 				end |  | ||||||
| 			end |  | ||||||
| 		end |  | ||||||
| 	elseif mesecon:is_effector(node.name) then |  | ||||||
| 		mesecon:changesignal(pos, node, rulename, mesecon.state.off, recdepth) |  | ||||||
| 		if mesecon:is_effector_on(node.name) |  | ||||||
| 		and not mesecon:is_powered(pos) then |  | ||||||
| 			mesecon:deactivate(pos, node, rulename, recdepth + 1) |  | ||||||
| 		end |  | ||||||
| 	end |  | ||||||
| end |  | ||||||
|  |  | ||||||
| mesecon.queue:add_function("turnoff", function (pos, rulename, recdepth) |  | ||||||
| 	mesecon:turnoff(pos, rulename, recdepth) |  | ||||||
| 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 rulenames = mesecon:rules_link_rule_all_inverted(pos, rule) |  | ||||||
| 		for _, rname in ipairs(rulenames) do |  | ||||||
| 			local np = mesecon:addPosRule(pos, rname) |  | ||||||
| 			if mesecon:find_receptor_on(np, {}, mesecon:invertRule(rname)) then |  | ||||||
| 				return true |  | ||||||
| 			end |  | ||||||
| 		end |  | ||||||
| 	end |  | ||||||
|  |  | ||||||
| 	return false |  | ||||||
| end |  | ||||||
|  |  | ||||||
| function mesecon:find_receptor_on(pos, checked, rulename) |  | ||||||
| 	local node = minetest.get_node(pos) |  | ||||||
|  |  | ||||||
| 	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 |  | ||||||
| 	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 rulenames = mesecon:rules_link_rule_all_inverted(pos, rule) |  | ||||||
| 			for _, rname in ipairs(rulenames) do |  | ||||||
| 				local np = mesecon:addPosRule(pos, rname) |  | ||||||
| 				if mesecon:find_receptor_on(np, checked, mesecon:invertRule(rname)) 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 |  | ||||||
|  |  | ||||||
| function mesecon:rules_link(output, input, dug_outputrules) --output/input are positions (outputrules optional, used if node has been dug), second return value: the name of the affected input rule |  | ||||||
| 	local outputnode = minetest.get_node(output) |  | ||||||
| 	local inputnode = minetest.get_node(input) |  | ||||||
| 	local outputrules = dug_outputrules or mesecon:get_any_outputrules (outputnode) |  | ||||||
| 	local inputrules = mesecon:get_any_inputrules (inputnode) |  | ||||||
| 	if not outputrules or not inputrules then |  | ||||||
| 		return |  | ||||||
| 	end |  | ||||||
|  |  | ||||||
| 	for _, outputrule in ipairs(mesecon:flattenrules(outputrules)) do |  | ||||||
| 		-- Check if output sends to input |  | ||||||
| 		if 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 | ||||||
|  |  | ||||||
|  | 				-- Call turnoff on neighbors | ||||||
|  | 				for _, l in ipairs(mesecon.rules_link_rule_all(f.pos, r)) do | ||||||
|  | 					table.insert(frontiers, {pos = np, link = l}) | ||||||
|  | 				end | ||||||
| 			end | 			end | ||||||
|  |  | ||||||
|  | 			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 | ||||||
| 	end | 	end | ||||||
| 	return false |  | ||||||
|  | 	return true | ||||||
| end | 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 | -- Get all linking inputrules of inputnode (effector or conductor) that is connected to | ||||||
| 	local input = mesecon:addPosRule(output, rule) | -- 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 inputrules = mesecon:get_any_inputrules (inputnode) | 	local input = vector.add(output, rule) | ||||||
|  | 	local inputnode = mesecon.get_node_force(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 | 	end | ||||||
|  |  | ||||||
| 	return rules | 	return rules | ||||||
| end | end | ||||||
|  |  | ||||||
| function mesecon:rules_link_rule_all_inverted(input, rule) | -- Get all linking outputnodes of outputnode (receptor or conductor) that is connected to | ||||||
| 	--local irule = mesecon:invertRule(rule) | -- inputnode (effector or conductor) at position `input` and has an input in direction `rule` | ||||||
| 	local output = mesecon:addPosRule(input, rule) | function mesecon.rules_link_rule_all_inverted(input, rule) | ||||||
| 	local outputnode = minetest.get_node(output) | 	local output = vector.add(input, rule) | ||||||
| 	local outputrules = mesecon:get_any_outputrules (outputnode) | 	local outputnode = mesecon.get_node_force(output) | ||||||
|  | 	local outputrules = mesecon.get_any_outputrules(outputnode) | ||||||
| 	if not outputrules then | 	if not outputrules then | ||||||
| 		return {} | 		return {} | ||||||
| 	end | 	end | ||||||
| 	local rules = {} | 	local rules = {} | ||||||
|  |  | ||||||
| 	for _, outputrule in ipairs(mesecon:flattenrules(outputrules)) do | 	for _, outputrule in ipairs(mesecon.flattenrules(outputrules)) do | ||||||
| 		if  mesecon:cmpPos(mesecon:addPosRule(output, outputrule), input) then | 		if  vector.equals(vector.add(output, outputrule), input) then | ||||||
| 			if outputrule.sx == nil or rule.sx == nil or mesecon:cmpSpecial(outputrule, rule) then | 			table.insert(rules, mesecon.invertRule(outputrule)) | ||||||
| 				rules[#rules+1] = mesecon:invertRule(outputrule) |  | ||||||
| 			end |  | ||||||
| 		end | 		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 rulenames = mesecon:rules_link_rule_all_inverted(pos, rule) | 			local rulenames = mesecon.rules_link_rule_all_inverted(pos, rule) | ||||||
| 			for _, rname in ipairs(rulenames) do | 			for _, rname in ipairs(rulenames) do | ||||||
| 				local np = mesecon:addPosRule(pos, rname) | 				local np = vector.add(pos, rname) | ||||||
| 				local nn = minetest.get_node(np) | 				local nn = mesecon.get_node_force(np) | ||||||
| 				if (mesecon:is_conductor_on (nn, mesecon:invertRule(rname)) or mesecon:is_receptor_on (nn.name)) then |  | ||||||
| 					return true | 				if (mesecon.is_conductor_on(nn, mesecon.invertRule(rname)) | ||||||
|  | 				or mesecon.is_receptor_on(nn.name)) then | ||||||
|  | 					table.insert(sourcepos, np) | ||||||
| 				end | 				end | ||||||
| 			end | 			end | ||||||
| 		end | 		end | ||||||
| 	else | 	else | ||||||
| 		local rulenames = mesecon:rules_link_rule_all_inverted(pos, rule) | 		local rulenames = mesecon.rules_link_rule_all_inverted(pos, rule) | ||||||
| 		for _, rname in ipairs(rulenames) do | 		for _, rname in ipairs(rulenames) do | ||||||
| 			local np = mesecon:addPosRule(pos, rname) | 			local np = vector.add(pos, rname) | ||||||
| 			local nn = minetest.get_node(np) | 			local nn = mesecon.get_node_force(np) | ||||||
| 			if (mesecon:is_conductor_on (nn, mesecon:invertRule(rname)) or mesecon:is_receptor_on (nn.name)) 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 | 	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,32 +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 rules = {} | local old_forceloaded_blocks = mesecon.file2table("mesecon_forceloaded") | ||||||
| rules.a = {x = -1, y = 0, z =  0, name="A"} | for hash, _ in pairs(old_forceloaded_blocks) do | ||||||
| rules.b = {x =  0, y = 0, z =  1, name="B"} | 	minetest.forceload_free_block(unhash_blockpos(hash)) | ||||||
| rules.c = {x =  1, y = 0, z =  0, name="C"} |  | ||||||
| rules.d = {x =  0, y = 0, z = -1, name="D"} |  | ||||||
|  |  | ||||||
| function legacy_update_ports(pos) |  | ||||||
| 	local meta = minetest.get_meta(pos) |  | ||||||
| 	L = { |  | ||||||
| 		a = mesecon:is_power_on(mesecon:addPosRule(pos, rules.a), |  | ||||||
| 			mesecon:invertRule(rules.a)) and |  | ||||||
| 			mesecon:rules_link(mesecon:addPosRule(pos, rules.a), pos), |  | ||||||
| 		b = mesecon:is_power_on(mesecon:addPosRule(pos, rules.b), |  | ||||||
| 			mesecon:invertRule(rules.b)) and |  | ||||||
| 			mesecon:rules_link(mesecon:addPosRule(pos, rules.b), pos), |  | ||||||
| 		c = mesecon:is_power_on(mesecon:addPosRule(pos, rules.c), |  | ||||||
| 			mesecon:invertRule(rules.c)) and |  | ||||||
| 			mesecon:rules_link(mesecon:addPosRule(pos, rules.c), pos), |  | ||||||
| 		d = mesecon:is_power_on(mesecon:addPosRule(pos, rules.d), |  | ||||||
| 			mesecon:invertRule(rules.d)) and |  | ||||||
| 			mesecon:rules_link(mesecon:addPosRule(pos, rules.d), pos), |  | ||||||
| 	} |  | ||||||
| 	local n = (L.a and 1 or 0) + (L.b and 2 or 0) + (L.c and 4 or 0) + (L.d and 8 or 0) + 1 |  | ||||||
| 	meta:set_int("real_portstates", n) |  | ||||||
| 	return L |  | ||||||
| end | 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 =  0, y =  0, z =  1}, | ||||||
|  {x=1,  y=1,  z=0}, | 	{x =  1, y =  1, z =  0}, | ||||||
|  {x=1,  y=-1, z=0}, | 	{x =  1, y = -1, z =  0}, | ||||||
|  {x=-1, y=1,  z=0}, | 	{x = -1, y =  1, z =  0}, | ||||||
|  {x=-1, y=-1, z=0}, | 	{x = -1, y = -1, z =  0}, | ||||||
|  {x=0,  y=1,  z=1}, | 	{x =  0, y =  1, z =  1}, | ||||||
|  {x=0,  y=-1, z=1}, | 	{x =  0, y = -1, z =  1}, | ||||||
|  {x=0,  y=1,  z=-1}, | 	{x =  0, y =  1, z = -1}, | ||||||
|  {x=0,  y=-1, z=-1}} | 	{x =  0, y = -1, z = -1}, | ||||||
|  | } | ||||||
|  |  | ||||||
| mesecon.rules.buttonlike = | mesecon.rules.floor = mesecon.mergetable(mesecon.rules.default, {{x = 0, y = -1, z = 0}}) | ||||||
| {{x = 1,  y = 0, z = 0}, |  | ||||||
|  {x = 1,  y = 1, z = 0}, |  | ||||||
|  {x = 1,  y =-1, z = 0}, |  | ||||||
|  {x = 1,  y =-1, z = 1},  |  | ||||||
|  {x = 1,  y =-1, z =-1}, |  | ||||||
|  {x = 2,  y = 0, z = 0}} |  | ||||||
|  |  | ||||||
| mesecon.rules.flat = | mesecon.rules.pplate = mesecon.mergetable(mesecon.rules.floor, {{x = 0, y = -2, z = 0}}) | ||||||
| {{x = 1, y = 0, z = 0}, |  | ||||||
|  {x =-1, y = 0, z = 0}, | mesecon.rules.buttonlike = { | ||||||
|  {x = 0, y = 0, z = 1}, | 	{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 =  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,76 +1,136 @@ | |||||||
| -- Dig and place services | -- Dig and place services | ||||||
|  |  | ||||||
| mesecon.on_placenode = function (pos, node) | mesecon.on_placenode = function(pos, node) | ||||||
|  | 	mesecon.execute_autoconnect_hooks_now(pos, node) | ||||||
|  |  | ||||||
| 	-- Receptors: Send on signal when active | 	-- Receptors: Send on signal when active | ||||||
| 	if mesecon:is_receptor_on(node.name) then | 	if mesecon.is_receptor_on(node.name) then | ||||||
| 		mesecon:receptor_on(pos, mesecon:receptor_get_rules(node)) | 		mesecon.receptor_on(pos, mesecon.receptor_get_rules(node)) | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	-- Conductors: Send turnon signal when powered or replace by respective offstate conductor | 	-- Conductors: Send turnon signal when powered or replace by respective offstate conductor | ||||||
| 	-- if placed conductor is an onstate one | 	-- if placed conductor is an onstate one | ||||||
| 	if mesecon:is_conductor(node.name) then | 	if mesecon.is_conductor(node.name) then | ||||||
| 		if mesecon:is_powered(pos) then | 		local sources = mesecon.is_powered(pos) | ||||||
|  | 		if sources then | ||||||
| 			-- also call receptor_on if itself is powered already, so that neighboring | 			-- also call receptor_on if itself is powered already, so that neighboring | ||||||
| 			-- conductors will be activated (when pushing an on-conductor with a piston) | 			-- conductors will be activated (when pushing an on-conductor with a piston) | ||||||
| 			mesecon:turnon (pos) | 			for _, s in ipairs(sources) do | ||||||
| 			mesecon:receptor_on (pos, mesecon:conductor_get_rules(node)) | 				local rule = vector.subtract(pos, s) | ||||||
| 		elseif mesecon:is_conductor_off(node.name) then | 				mesecon.turnon(pos, rule) | ||||||
| 			minetest.swap_node(pos, {name = mesecon:get_conductor_off(node)}) | 			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 | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	-- Effectors: Send changesignal and activate or deactivate | 	-- Effectors: Send changesignal and activate or deactivate | ||||||
| 	if mesecon:is_effector(node.name) then | 	if mesecon.is_effector(node.name) then | ||||||
| 		if mesecon:is_powered(pos) then | 		local powered_rules = {} | ||||||
| 			mesecon:changesignal(pos, node, mesecon:effector_get_rules(node), "on", 1) | 		local unpowered_rules = {} | ||||||
| 			mesecon:activate(pos, node, nil, 1) |  | ||||||
|  | 		-- for each input rule, check if powered | ||||||
|  | 		for _, r in ipairs(mesecon.effector_get_rules(node)) do | ||||||
|  | 			local powered = mesecon.is_powered(pos, r) | ||||||
|  | 			if powered then table.insert(powered_rules, r) | ||||||
|  | 			else table.insert(unpowered_rules, r) end | ||||||
|  |  | ||||||
|  | 			local state = powered and mesecon.state.on or mesecon.state.off | ||||||
|  | 			mesecon.changesignal(pos, node, r, state, 1) | ||||||
|  | 		end | ||||||
|  |  | ||||||
|  | 		if (#powered_rules > 0) then | ||||||
|  | 			for _, r in ipairs(powered_rules) do | ||||||
|  | 				mesecon.activate(pos, node, r, 1) | ||||||
|  | 			end | ||||||
| 		else | 		else | ||||||
| 			mesecon:changesignal(pos, node, mesecon:effector_get_rules(node), "off", 1) | 			for _, r in ipairs(unpowered_rules) do | ||||||
| 			mesecon:deactivate(pos, node, nil, 1) | 				mesecon.deactivate(pos, node, r, 1) | ||||||
|  | 			end | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
| end | end | ||||||
|  |  | ||||||
| mesecon.on_dignode = function (pos, node) | mesecon.on_dignode = function(pos, node) | ||||||
| 	if mesecon:is_conductor_on(node) then | 	if mesecon.is_conductor_on(node) then | ||||||
| 		mesecon:receptor_off(pos, mesecon:conductor_get_rules(node)) | 		mesecon.receptor_off(pos, mesecon.conductor_get_rules(node)) | ||||||
| 	elseif mesecon:is_receptor_on(node.name) then | 	elseif mesecon.is_receptor_on(node.name) then | ||||||
| 		mesecon:receptor_off(pos, mesecon:receptor_get_rules(node)) | 		mesecon.receptor_off(pos, mesecon.receptor_get_rules(node)) | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
|  | 	mesecon.execute_autoconnect_hooks_queue(pos, node) | ||||||
|  | end | ||||||
|  |  | ||||||
|  | function mesecon.on_blastnode(pos, intensity) | ||||||
|  | 	local node = minetest.get_node(pos) | ||||||
|  | 	minetest.remove_node(pos) | ||||||
|  | 	mesecon.on_dignode(pos, node) | ||||||
|  | 	return minetest.get_node_drops(node.name, "") | ||||||
| end | end | ||||||
|  |  | ||||||
| minetest.register_on_placenode(mesecon.on_placenode) | minetest.register_on_placenode(mesecon.on_placenode) | ||||||
| minetest.register_on_dignode(mesecon.on_dignode) | minetest.register_on_dignode(mesecon.on_dignode) | ||||||
|  |  | ||||||
| -- Overheating service for fast circuits | -- Overheating service for fast circuits | ||||||
|  | local OVERHEAT_MAX = mesecon.setting("overheat_max", 20) | ||||||
|  | local COOLDOWN_TIME = mesecon.setting("cooldown_time", 2.0) | ||||||
|  | local COOLDOWN_STEP = mesecon.setting("cooldown_granularity", 0.5) | ||||||
|  | local COOLDOWN_MULTIPLIER = OVERHEAT_MAX / COOLDOWN_TIME | ||||||
|  | local cooldown_timer = 0.0 | ||||||
|  | local object_heat = {} | ||||||
|  |  | ||||||
| -- returns true if heat is too high | -- returns true if heat is too high | ||||||
| mesecon.do_overheat = function(pos) | function mesecon.do_overheat(pos) | ||||||
| 	local meta = minetest.get_meta(pos) | 	local id = minetest.hash_node_position(pos) | ||||||
| 	local heat = meta:get_int("heat") or 0 | 	local heat = (object_heat[id] or 0) + 1 | ||||||
|  | 	object_heat[id] = heat | ||||||
| 	heat = heat + 1 | 	if heat >= OVERHEAT_MAX then | ||||||
| 	meta:set_int("heat", heat) | 		minetest.log("action", "Node overheats at " .. minetest.pos_to_string(pos)) | ||||||
|  | 		object_heat[id] = nil | ||||||
| 	if heat < OVERHEAT_MAX then |  | ||||||
| 		mesecon.queue:add_action(pos, "cooldown", {}, 1, nil, 0) |  | ||||||
| 	else |  | ||||||
| 		return true | 		return true | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	return false | 	return false | ||||||
| end | end | ||||||
|  |  | ||||||
|  | function mesecon.do_cooldown(pos) | ||||||
|  | 	local id = minetest.hash_node_position(pos) | ||||||
|  | 	object_heat[id] = nil | ||||||
|  | end | ||||||
|  |  | ||||||
| mesecon.queue:add_function("cooldown", function (pos) | function mesecon.get_heat(pos) | ||||||
| 	if minetest.get_item_group(minetest.get_node(pos).name, "overheat") == 0 then | 	local id = minetest.hash_node_position(pos) | ||||||
| 		return -- node has been moved, this one does not use overheating - ignore | 	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 | 	end | ||||||
|  | 	for id, heat in pairs(new_heat) do | ||||||
| 	local meta = minetest.get_meta(pos) | 		object_heat[id] = heat | ||||||
| 	local heat = meta:get_int("heat") |  | ||||||
|  |  | ||||||
| 	if (heat > 0) then |  | ||||||
| 		meta:set_int("heat", heat - 1) |  | ||||||
| 	end | 	end | ||||||
| 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,12 +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_RESUMETIME = 4		-- time to wait when starting the server before | 			return read | ||||||
| 				-- processing the ActionQueue, don't set this too low | 		end | ||||||
| OVERHEAT_MAX = 20		-- maximum heat of any component that directly sends an output | 	elseif type(default) == "string" then | ||||||
| 				-- signal when the input changes (e.g. luacontroller, gates) | 		return minetest.settings:get("mesecon."..setting) or default | ||||||
| 				-- Unit: actions per second, checks are every 1 second | 	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 | 
| Before Width: | Height: | Size: 592 B | 
| Before Width: | Height: | Size: 487 B | 
| Before Width: | Height: | Size: 341 B | 
| Before Width: | Height: | Size: 340 B | 
| Before Width: | Height: | Size: 307 B | 
| Before Width: | Height: | Size: 307 B | 
| Before Width: | Height: | Size: 743 B | 
| Before Width: | Height: | Size: 725 B | 
| Before Width: | Height: | Size: 204 B | 
| Before Width: | Height: | Size: 196 B | 
| Before Width: | Height: | Size: 713 B | 
| Before Width: | Height: | Size: 751 B | 
| Before Width: | Height: | Size: 737 B | 
| Before Width: | Height: | Size: 598 B | 
| Before Width: | Height: | Size: 692 B | 
| Before Width: | Height: | Size: 553 B | 
| Before Width: | Height: | Size: 330 B | 
| Before Width: | Height: | Size: 319 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 | 
| Before Width: | Height: | Size: 867 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 | 
| Before Width: | Height: | Size: 347 B | 
| Before Width: | Height: | Size: 386 B | 
| Before Width: | Height: | Size: 465 B | 
| Before Width: | Height: | Size: 464 B | 
| Before Width: | Height: | Size: 167 B | 
| Before Width: | Height: | Size: 454 B | 
| Before Width: | Height: | Size: 492 B | 
| Before Width: | Height: | Size: 373 B | 
| Before Width: | Height: | Size: 396 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( | 	local x, y = math.floor(n / 2), n % 2 | ||||||
| 		"base2dec is tonumber(num,base1)\n".. | 	if (n > 1) then | ||||||
| 		"commonlib needs dec2base(num,base2)\n".. | 		return mesecon.dec2bin(x)..y | ||||||
| 		"and it needs base2base(num,base1,base2),\n".. | 	else | ||||||
| 		"which is dec2base(tonumber(num,base1),base2)" | 		return ""..y | ||||||
| 	) |  | ||||||
| else |  | ||||||
| 	function dec2bin(n) |  | ||||||
| 		local x, y = math.floor(n / 2), n % 2 |  | ||||||
| 		if (n > 1) then |  | ||||||
| 			return dec2bin(x)..y |  | ||||||
| 		else |  | ||||||
| 			return ""..y |  | ||||||
| 		end |  | ||||||
| 	end | 	end | ||||||
| end | end | ||||||
|  |  | ||||||
| function mesecon:getstate(nodename, states) | function mesecon.getstate(nodename, states) | ||||||
| 	for state, name in ipairs(states) do | 	for state, name in ipairs(states) do | ||||||
| 		if name == nodename then | 		if name == nodename then | ||||||
| 			return state | 			return state | ||||||
| @@ -128,68 +158,276 @@ 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 | ||||||
| end | 		return table.copy(obj) | ||||||
|  |  | ||||||
| function mesecon:cmpPos(p1, p2) |  | ||||||
| 	return (p1.x == p2.x and p1.y == p2.y and p1.z == p2.z) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| function mesecon:cmpSpecial(r1, r2) |  | ||||||
| 	return (r1.sx == r2.sx and r1.sy == r2.sy and r1.sz == r2.sz) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| function mesecon:tablecopy(table) -- deep table copy |  | ||||||
| 	if type(table) ~= "table" then return table end -- no need to copy |  | ||||||
| 	local newtable = {} |  | ||||||
|  |  | ||||||
| 	for idx, item in pairs(table) do |  | ||||||
| 		if type(item) == "table" then |  | ||||||
| 			newtable[idx] = mesecon:tablecopy(item) |  | ||||||
| 		else |  | ||||||
| 			newtable[idx] = item |  | ||||||
| 		end |  | ||||||
| 	end | 	end | ||||||
|  | 	return obj | ||||||
| 	return newtable |  | ||||||
| end | end | ||||||
|  |  | ||||||
| function mesecon:cmpAny(t1, t2) | function mesecon.cmpAny(t1, t2) | ||||||
| 	if type(t1) ~= type(t2) then return false end | 	if type(t1) ~= type(t2) then return false end | ||||||
| 	if type(t1) ~= "table" and type(t2) ~= "table" then return t1 == t2 end | 	if type(t1) ~= "table" and type(t2) ~= "table" then return t1 == t2 end | ||||||
|  |  | ||||||
| 	for i, e in pairs(t1) do | 	for i, e in pairs(t1) do | ||||||
| 		if not mesecon:cmpAny(e, t2[i]) then return false end | 		if not mesecon.cmpAny(e, t2[i]) then return false end | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	return true | 	return true | ||||||
| end | end | ||||||
|  |  | ||||||
|  | -- does not overwrite values; number keys (ipairs) are appended, not overwritten | ||||||
|  | function mesecon.mergetable(source, dest) | ||||||
|  | 	local rval = mesecon.tablecopy(dest) | ||||||
|  |  | ||||||
|  | 	for k, v in pairs(source) do | ||||||
|  | 		rval[k] = dest[k] or mesecon.tablecopy(v) | ||||||
|  | 	end | ||||||
|  | 	for i, v in ipairs(source) do | ||||||
|  | 		table.insert(rval, mesecon.tablecopy(v)) | ||||||
|  | 	end | ||||||
|  |  | ||||||
|  | 	return rval | ||||||
|  | end | ||||||
|  |  | ||||||
|  | function mesecon.register_node(name, spec_common, spec_off, spec_on) | ||||||
|  | 	spec_common.drop = spec_common.drop or name .. "_off" | ||||||
|  | 	spec_common.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.mergetable(spec_common, spec_on); | ||||||
|  | 	spec_off = mesecon.mergetable(spec_common, spec_off); | ||||||
|  |  | ||||||
|  | 	minetest.register_node(name .. "_on", spec_on) | ||||||
|  | 	minetest.register_node(name .. "_off", spec_off) | ||||||
|  | end | ||||||
|  |  | ||||||
|  | -- swap onstate and offstate nodes, returns new state | ||||||
|  | function mesecon.flipstate(pos, node) | ||||||
|  | 	local nodedef = minetest.registered_nodes[node.name] | ||||||
|  | 	local newstate | ||||||
|  | 	if (nodedef.__mesecon_state == "on") then newstate = "off" end | ||||||
|  | 	if (nodedef.__mesecon_state == "off") then newstate = "on" end | ||||||
|  |  | ||||||
|  | 	minetest.swap_node(pos, {name = nodedef.__mesecon_basename .. "_" .. newstate, | ||||||
|  | 		param2 = node.param2}) | ||||||
|  |  | ||||||
|  | 	return newstate | ||||||
|  | end | ||||||
|  |  | ||||||
|  | -- File writing / reading utilities | ||||||
|  | local wpath = minetest.get_worldpath() | ||||||
|  | function mesecon.file2table(filename) | ||||||
|  | 	local f = io.open(wpath..DIR_DELIM..filename, "r") | ||||||
|  | 	if f == nil then return {} end | ||||||
|  | 	local t = f:read("*all") | ||||||
|  | 	f:close() | ||||||
|  | 	if t == "" or t == nil then return {} end | ||||||
|  | 	return minetest.deserialize(t) | ||||||
|  | end | ||||||
|  |  | ||||||
|  | function mesecon.table2file(filename, table) | ||||||
|  | 	local f = io.open(wpath..DIR_DELIM..filename, "w") | ||||||
|  | 	f:write(minetest.serialize(table)) | ||||||
|  | 	f:close() | ||||||
|  | end | ||||||
|  |  | ||||||
|  | -- 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 | ||||||
|  | 		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 | ||||||
|   | |||||||
| @@ -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,52 @@ | |||||||
| -- 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, |  | ||||||
| 	groups = {dig_immediate=3, mesecon=2}, |  | ||||||
|     description="Blinky Plant", |  | ||||||
| 	sounds = default.node_sound_leaves_defaults(), |  | ||||||
| 	selection_box = { |  | ||||||
| 		type = "fixed", |  | ||||||
| 		fixed = {-0.3, -0.5, -0.3, 0.3, -0.5+0.7, 0.3}, |  | ||||||
| 	}, |  | ||||||
| 	mesecons = {receptor = { |  | ||||||
| 		state = mesecon.state.off |  | ||||||
| 	}}, |  | ||||||
| 	on_rightclick = function(pos, node, clicker) |  | ||||||
|         minetest.set_node(pos, {name="mesecons_blinkyplant:blinky_plant"}) |  | ||||||
|     end |  | ||||||
| }) |  | ||||||
|  |  | ||||||
| minetest.register_node("mesecons_blinkyplant:blinky_plant_on", { |  | ||||||
| 	drawtype = "plantlike", |  | ||||||
| 	visual_scale = 1, |  | ||||||
| 	tiles = {"jeija_blinky_plant_on.png"}, |  | ||||||
| 	inventory_image = "jeija_blinky_plant_off.png", |  | ||||||
| 	paramtype = "light", |  | ||||||
| 	walkable = false, |  | ||||||
| 	groups = {dig_immediate=3, not_in_creative_inventory=1, mesecon=2}, |  | ||||||
| 	drop="mesecons_blinkyplant:blinky_plant_off 1", |  | ||||||
| 	light_source = LIGHT_MAX-7, |  | ||||||
| 	description = "Blinky Plant", |  | ||||||
| 	sounds = default.node_sound_leaves_defaults(), |  | ||||||
| 	selection_box = { |  | ||||||
| 		type = "fixed", |  | ||||||
| 		fixed = {-0.3, -0.5, -0.3, 0.3, -0.5+0.7, 0.3}, |  | ||||||
| 	}, |  | ||||||
| 	mesecons = {receptor = { |  | ||||||
| 		state = mesecon.state.on |  | ||||||
| 	}}, |  | ||||||
| 	on_rightclick = function(pos, node, clicker) |  | ||||||
| 		minetest.set_node(pos, {name = "mesecons_blinkyplant:blinky_plant"}) |  | ||||||
| 		mesecon:receptor_off(pos) |  | ||||||
| 	end | 	end | ||||||
|  | end | ||||||
|  |  | ||||||
|  | local on_timer = function (pos) | ||||||
|  | 	local node = minetest.get_node(pos) | ||||||
|  | 	if(mesecon.flipstate(pos, node) == "on") then | ||||||
|  | 		mesecon.receptor_on(pos) | ||||||
|  | 	else | ||||||
|  | 		mesecon.receptor_off(pos) | ||||||
|  | 	end | ||||||
|  | 	toggle_timer(pos) | ||||||
|  | end | ||||||
|  |  | ||||||
|  | mesecon.register_node("mesecons_blinkyplant:blinky_plant", { | ||||||
|  | 	description="Blinky Plant", | ||||||
|  | 	drawtype = "plantlike", | ||||||
|  | 	inventory_image = "jeija_blinky_plant_off.png", | ||||||
|  | 	paramtype = "light", | ||||||
|  | 	is_ground_content = false, | ||||||
|  | 	walkable = false, | ||||||
|  | 	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}, | ||||||
|  | 	}, | ||||||
|  | 	on_timer = on_timer, | ||||||
|  | 	on_rightclick = toggle_timer, | ||||||
|  | 	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 | ||||||
| Before Width: | Height: | Size: 454 B After Width: | Height: | Size: 367 B | 
| Before Width: | Height: | Size: 463 B 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}) | ||||||
|  | 	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}) | ||||||
| 		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 | ||||||
| Before Width: | Height: | Size: 411 B After Width: | Height: | Size: 371 B | 
| Before Width: | Height: | Size: 449 B After Width: | Height: | Size: 409 B | 
| Before Width: | Height: | Size: 434 B 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 | 
| @@ -43,7 +43,7 @@ minetest.register_chatcommand("hp", { | |||||||
| }) | }) | ||||||
|  |  | ||||||
| local function initialize_data(meta) | local function initialize_data(meta) | ||||||
| 	local commands = meta:get_string("commands") | 	local commands = minetest.formspec_escape(meta:get_string("commands")) | ||||||
| 	meta:set_string("formspec", | 	meta:set_string("formspec", | ||||||
| 		"invsize[9,5;]" .. | 		"invsize[9,5;]" .. | ||||||
| 		"textarea[0.5,0.5;8.5,4;commands;Commands;"..commands.."]" .. | 		"textarea[0.5,0.5;8.5,4;commands;Commands;"..commands.."]" .. | ||||||
| @@ -79,7 +79,7 @@ local function after_place(pos, placer) | |||||||
| end | end | ||||||
|  |  | ||||||
| local function receive_fields(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) | ||||||
| @@ -93,9 +93,22 @@ local function receive_fields(pos, formname, fields, sender) | |||||||
| end | end | ||||||
|  |  | ||||||
| local function resolve_commands(commands, pos) | local function resolve_commands(commands, pos) | ||||||
|  | 	local players = minetest.get_connected_players() | ||||||
|  |  | ||||||
|  | 	-- 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 | ||||||
|  |  | ||||||
| 	local nearest, farthest = nil, nil | 	local nearest, farthest = nil, nil | ||||||
| 	local min_distance, max_distance = math.huge, -1 | 	local min_distance, max_distance = math.huge, -1 | ||||||
| 	local players = minetest.get_connected_players() |  | ||||||
| 	for index, player in pairs(players) do | 	for index, player in pairs(players) do | ||||||
| 		local distance = vector.distance(pos, player:getpos()) | 		local distance = vector.distance(pos, player:getpos()) | ||||||
| 		if distance < min_distance then | 		if distance < min_distance then | ||||||
| @@ -168,6 +181,7 @@ 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, | ||||||
| @@ -176,11 +190,13 @@ minetest.register_node("mesecons_commandblock:commandblock_off", { | |||||||
| 	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", | ||||||
| @@ -191,5 +207,6 @@ minetest.register_node("mesecons_commandblock:commandblock_on", { | |||||||
| 	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 | ||||||
| Before Width: | Height: | Size: 323 B | 
| Before Width: | Height: | Size: 282 B After Width: | Height: | Size: 183 B | 
| Before Width: | Height: | Size: 278 B 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,7 +10,7 @@ end | |||||||
| local delayer_get_input_rules = function(node) | local delayer_get_input_rules = function(node) | ||||||
| 	local rules = {{x = 0, y = 0, z = -1}} | 	local rules = {{x = 0, y = 0, z = -1}} | ||||||
| 	for i = 0, node.param2 do | 	for i = 0, node.param2 do | ||||||
| 		rules = mesecon:rotate_rules_left(rules) | 		rules = mesecon.rotate_rules_left(rules) | ||||||
| 	end | 	end | ||||||
| 	return rules | 	return rules | ||||||
| end | end | ||||||
| @@ -33,21 +33,12 @@ 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 }, | ||||||
| @@ -57,21 +48,12 @@ 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", | ||||||
| 	tiles = { |  | ||||||
| 		"mesecons_delayer_off_"..tostring(i)..".png", |  | ||||||
| 		"mesecons_delayer_bottom.png", |  | ||||||
| 		"mesecons_delayer_ends_off.png", |  | ||||||
| 		"mesecons_delayer_ends_off.png", |  | ||||||
| 		"mesecons_delayer_sides_off.png", |  | ||||||
| 		"mesecons_delayer_sides_off.png" |  | ||||||
| 		}, |  | ||||||
| 	inventory_image = "mesecons_delayer_off_1.png", |  | ||||||
| 	wield_image = "mesecons_delayer_off_1.png", |  | ||||||
| 	walkable = true, | 	walkable = true, | ||||||
| 	selection_box = { | 	selection_box = { | ||||||
| 		type = "fixed", | 		type = "fixed", | ||||||
| @@ -81,26 +63,46 @@ minetest.register_node("mesecons_delayer:delayer_off_"..tostring(i), { | |||||||
| 		type = "fixed", | 		type = "fixed", | ||||||
| 		fixed = boxes | 		fixed = boxes | ||||||
| 	}, | 	}, | ||||||
| 	groups = groups, |  | ||||||
| 	paramtype = "light", | 	paramtype = "light", | ||||||
| 	paramtype2 = "facedir", | 	paramtype2 = "facedir", | ||||||
| 	sunlight_propagates = true, | 	sunlight_propagates = true, | ||||||
| 	is_ground_content = true, | 	is_ground_content = false, | ||||||
| 	drop = 'mesecons_delayer:delayer_off_1', | 	delayer_time = delaytime[i], | ||||||
| 	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, |  | ||||||
| 	delayer_time = delaytime, |  | ||||||
| 	delayer_onstate = "mesecons_delayer:delayer_on_"..tostring(i), |  | ||||||
| 	sounds = default.node_sound_stone_defaults(), | 	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 = { | ||||||
|  | 		"mesecons_delayer_off_"..tostring(i)..".png", | ||||||
|  | 		"mesecons_delayer_bottom.png", | ||||||
|  | 		"mesecons_delayer_ends_off.png", | ||||||
|  | 		"mesecons_delayer_ends_off.png", | ||||||
|  | 		"mesecons_delayer_sides_off.png", | ||||||
|  | 		"mesecons_delayer_sides_off.png" | ||||||
|  | 	}, | ||||||
|  | 	inventory_image = "mesecons_delayer_off_1.png", | ||||||
|  | 	wield_image = "mesecons_delayer_off_1.png", | ||||||
|  | 	groups = off_groups, | ||||||
|  | 	on_punch = function(pos, node, puncher) | ||||||
|  | 		if minetest.is_protected(pos, puncher and puncher:get_player_name()) then | ||||||
|  | 			return | ||||||
|  | 		end | ||||||
|  |  | ||||||
|  | 		minetest.swap_node(pos, { | ||||||
|  | 			name = "mesecons_delayer:delayer_off_"..tostring(i % 4 + 1), | ||||||
|  | 			param2 = node.param2 | ||||||
|  | 		}) | ||||||
|  | 	end, | ||||||
|  | 	delayer_onstate = "mesecons_delayer:delayer_on_"..tostring(i), | ||||||
| 	mesecons = { | 	mesecons = { | ||||||
| 		receptor = | 		receptor = | ||||||
| 		{ | 		{ | ||||||
| @@ -112,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", | ||||||
| @@ -126,34 +131,18 @@ minetest.register_node("mesecons_delayer:delayer_on_"..tostring(i), { | |||||||
| 		"mesecons_delayer_ends_on.png", | 		"mesecons_delayer_ends_on.png", | ||||||
| 		"mesecons_delayer_sides_on.png", | 		"mesecons_delayer_sides_on.png", | ||||||
| 		"mesecons_delayer_sides_on.png" | 		"mesecons_delayer_sides_on.png" | ||||||
| 		}, |  | ||||||
| 	walkable = true, |  | ||||||
| 	selection_box = { |  | ||||||
| 		type = "fixed", |  | ||||||
| 		fixed = { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 }, |  | ||||||
| 	}, |  | ||||||
| 	node_box = { |  | ||||||
| 		type = "fixed", |  | ||||||
| 		fixed = boxes |  | ||||||
| 	}, | 	}, | ||||||
| 	groups = {bendy = 2, snappy = 1, dig_immediate = 2, not_in_creative_inventory = 1}, | 	groups = {bendy = 2, snappy = 1, dig_immediate = 2, not_in_creative_inventory = 1}, | ||||||
| 	paramtype = "light", | 	on_punch = function(pos, node, puncher) | ||||||
| 	paramtype2 = "facedir", | 		if minetest.is_protected(pos, puncher and puncher:get_player_name()) 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 = | ||||||
| @@ -166,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 |