Compare commits
	
		
			4 Commits
		
	
	
		
			1963bfcc0d
			...
			meshes
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 966f9a56a6 | ||
|  | 30c28d882f | ||
|  | 78782c9b2b | ||
|  | 51cf528732 | 
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,3 +1 @@ | |||||||
| *~ | *~ | ||||||
| *.patch |  | ||||||
| *.diff |  | ||||||
|   | |||||||
							
								
								
									
										30
									
								
								COPYING.txt
									
									
									
									
									
								
							
							
						
						| @@ -1,30 +0,0 @@ | |||||||
| The Mesecons Mod for Minetest is |  | ||||||
| 	Copyright (C) 2011-2016 Mesecons Mod Developer Team and contributors |  | ||||||
|  |  | ||||||
| See the version control system log for information about other authors. |  | ||||||
|  |  | ||||||
| License of source code |  | ||||||
| ---------------------- |  | ||||||
| Copyright (C) 2011-2016 Mesecons Mod Developer Team and contributors |  | ||||||
|  |  | ||||||
| This program is free software; you can redistribute the Mesecons Mod and/or |  | ||||||
| modify it under the terms of the GNU Lesser General Public License version 3 |  | ||||||
| published by the Free Software Foundation. |  | ||||||
|  |  | ||||||
| This library is distributed in the hope that it will be useful, |  | ||||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU |  | ||||||
| Library General Public License for more details. |  | ||||||
|  |  | ||||||
| You should have received a copy of the GNU Library General Public |  | ||||||
| License along with this library; if not, write to the |  | ||||||
| Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, |  | ||||||
| Boston, MA  02110-1301, USA. |  | ||||||
|  |  | ||||||
| License of media (textures, sounds and documentation) |  | ||||||
| ----------------------------------------------------- |  | ||||||
| Copyright (C) 2011-2016 Mesecons Mod Developer Team and contributors |  | ||||||
|  |  | ||||||
| All textures, sounds and documentation files are licensed under the |  | ||||||
| Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) |  | ||||||
| http://creativecommons.org/licenses/by-sa/3.0/ |  | ||||||
							
								
								
									
										11
									
								
								README.md
									
									
									
									
									
								
							
							
						
						| @@ -22,9 +22,9 @@ OK, I want in. | |||||||
| -------------- | -------------- | ||||||
| Go get it! | Go get it! | ||||||
|  |  | ||||||
| [DOWNLOAD IT NOW](https://github.com/minetest-mods/mesecons/archive/master.zip) | [DOWNLOADS PAGE](http://mesecons.net/downloads.php) | ||||||
|  |  | ||||||
| Now go ahead and install it like any other Minetest mod. Don't know how? Check out [the wonderful page about it](https://wiki.minetest.net/Mods) over at the official Minetest Wiki. For your convenience, here's a quick summary: | Now go ahead and install it like any other Minetest mod. Don't know how? Check out [the wonderful page about it](http://wiki.minetest.com/wiki/Mods) over at the Minetest Wiki. For your convenience, here's a quick summary: | ||||||
|  |  | ||||||
| 1. If Mesecons is still in a ZIP file, extract the folder inside to somewhere on the computer. | 1. If Mesecons is still in a ZIP file, extract the folder inside to somewhere on the computer. | ||||||
| 2. Make sure that when you open the folder, you can directly find `README.md` in the listing. If you just see another folder, move that folder up one level and delete the old one. | 2. Make sure that when you open the folder, you can directly find `README.md` in the listing. If you just see another folder, move that folder up one level and delete the old one. | ||||||
| @@ -39,15 +39,13 @@ How do I use this thing? | |||||||
| ------------------------ | ------------------------ | ||||||
| How about a [quick overview video](https://www.youtube.com/watch?v=6kmeQj6iW5k)? | How about a [quick overview video](https://www.youtube.com/watch?v=6kmeQj6iW5k)? | ||||||
|  |  | ||||||
| Or maybe a [comprehensive reference](http://mesecons.net/items.html) is your style? | Or maybe a [comprehensive reference](http://mesecons.net/items.php) is your style? | ||||||
|  |  | ||||||
| An overview for the very newest of new beginners? How does [this one](http://uberi.mesecons.net/projects/MeseconsBasics/index.html) look? | An overview for the very newest of new beginners? How does [this one](http://uberi.mesecons.net/projects/MeseconsBasics/index.html) look? | ||||||
|  |  | ||||||
| There is also a [wiki page](https://wiki.minetest.net/Mods/Mesecons) dedicated to this mod. |  | ||||||
|  |  | ||||||
| Want to get more into building? Why not check out the [Mesecons Laboratory](http://uberi.mesecons.net/), a website dedicated to advanced Mesecons builders? | Want to get more into building? Why not check out the [Mesecons Laboratory](http://uberi.mesecons.net/), a website dedicated to advanced Mesecons builders? | ||||||
|  |  | ||||||
| Want to contribute to Mesecons itself? Check out the [source code](https://github.com/minetest-mods/mesecons)! | Want to contribute to Mesecons itself? Check out the [source code](https://github.com/Jeija/minetest-mod-mesecons)! | ||||||
|  |  | ||||||
| Who wrote it anyways? | Who wrote it anyways? | ||||||
| --------------------- | --------------------- | ||||||
| @@ -55,7 +53,6 @@ These awesome people made Mesecons possible! | |||||||
|  |  | ||||||
| | Contributor     | Contribution                     | | | Contributor     | Contribution                     | | ||||||
| | --------------- | -------------------------------- | | | --------------- | -------------------------------- | | ||||||
| | Hawk777         | Code for VoxelManip caching      | |  | ||||||
| | Jat15           | Various tweaks.                  | | | Jat15           | Various tweaks.                  | | ||||||
| | Jeija           | **Main developer! Everything.**  | | | Jeija           | **Main developer! Everything.**  | | ||||||
| | Jordach         | Noteblock sounds.                | | | Jordach         | Noteblock sounds.                | | ||||||
|   | |||||||
							
								
								
									
										12
									
								
								bower.json
									
									
									
									
									
								
							
							
						
						| @@ -1,12 +0,0 @@ | |||||||
| { |  | ||||||
|     "name": "mesecons", |  | ||||||
|     "description": "Mesecons is a mod for Minetest that implements items related to digital circuitry: wires, buttons, lights, and programmable controllers.", |  | ||||||
|     "homepage": "http://mesecons.net", |  | ||||||
|     "authors": "Jeija", |  | ||||||
|     "license": "LGPL-3.0+", |  | ||||||
|     "keywords": [ |  | ||||||
|         "mesecons", |  | ||||||
|         "minetest", |  | ||||||
|         "mod" |  | ||||||
|     ] |  | ||||||
| } |  | ||||||
| @@ -1,64 +0,0 @@ | |||||||
| { |  | ||||||
| 	"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
									
								
								mesecons/VERSION
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | |||||||
|  | 0.41 DEV | ||||||
| @@ -1,149 +1,118 @@ | |||||||
| --[[ | mesecon.queue.actions={} -- contains all ActionQueue actions | ||||||
| Mesecons uses something it calls an ActionQueue. |  | ||||||
|  |  | ||||||
| The ActionQueue holds functions and actions. | function mesecon.queue:add_function(name, func) | ||||||
| Functions are added on load time with a specified name. | 	mesecon.queue.funcs[name] = func | ||||||
| Actions are preserved over server restarts. |  | ||||||
|  |  | ||||||
| Each action consists of a position, the name of an added function to be called, |  | ||||||
| the params that should be used in this function call (additionally to the pos), |  | ||||||
| the time after which it should be executed, an optional overwritecheck and a |  | ||||||
| priority. |  | ||||||
|  |  | ||||||
| If time = 0, the action will be executed in the next globalstep, otherwise the |  | ||||||
| earliest globalstep when it will be executed is the after next globalstep. |  | ||||||
|  |  | ||||||
| It is guaranteed, that for two actions ac1, ac2 where ac1 ~= ac2, |  | ||||||
| ac1.time == ac2.time, ac1.priority == ac2.priority and ac1 was added earlier |  | ||||||
| than ac2, ac1 will be executed before ac2 (but in the same globalstep). |  | ||||||
|  |  | ||||||
| Note: Do not pass references in params, as they can not be preserved. |  | ||||||
|  |  | ||||||
| Also note: Some of the guarantees here might be dropped at some time. |  | ||||||
| ]] |  | ||||||
|  |  | ||||||
|  |  | ||||||
| -- localize for speed |  | ||||||
| local queue = mesecon.queue |  | ||||||
|  |  | ||||||
| queue.actions = {} -- contains all ActionQueue actions |  | ||||||
|  |  | ||||||
| function queue:add_function(name, func) |  | ||||||
| 	queue.funcs[name] = func |  | ||||||
| end | end | ||||||
|  |  | ||||||
| -- If add_action with twice the same overwritecheck and same position are called, the first one is overwritten | -- If add_action with twice the same overwritecheck and same position are called, the first one is overwritten | ||||||
| -- use overwritecheck nil to never overwrite, but just add the event to the queue | -- use overwritecheck nil to never overwrite, but just add the event to the queue | ||||||
| -- priority specifies the order actions are executed within one globalstep, highest first | -- priority specifies the order actions are executed within one globalstep, highest first | ||||||
| -- should be between 0 and 1 | -- should be between 0 and 1 | ||||||
| function queue:add_action(pos, func, params, time, overwritecheck, priority) | function mesecon.queue:add_action(pos, func, params, time, overwritecheck, priority) | ||||||
| 	-- Create Action Table: | 	-- Create Action Table: | ||||||
| 	time = time or 0 -- time <= 0 --> execute, time > 0 --> wait time until execution | 	time = time or 0 -- time <= 0 --> execute, time > 0 --> wait time until execution | ||||||
| 	priority = priority or 1 | 	priority = priority or 1 | ||||||
| 	local action = { | 	local action = {	pos=mesecon.tablecopy(pos), | ||||||
| 		pos = mesecon.tablecopy(pos), | 				func=func, | ||||||
| 		func = func, | 				params=mesecon.tablecopy(params or {}), | ||||||
| 		params = mesecon.tablecopy(params or {}), | 				time=time, | ||||||
| 		time = time, | 				owcheck=(overwritecheck and mesecon.tablecopy(overwritecheck)) or nil, | ||||||
| 		owcheck = (overwritecheck and mesecon.tablecopy(overwritecheck)) or nil, | 				priority=priority} | ||||||
| 		priority = priority |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	 -- check if old action has to be overwritten / removed: | 	local toremove = nil | ||||||
| 	if overwritecheck then | 	-- Otherwise, add the action to the queue | ||||||
| 		for i, ac in ipairs(queue.actions) do | 	if overwritecheck then -- check if old action has to be overwritten / removed: | ||||||
| 			if vector.equals(pos, ac.pos) | 		for i, ac in ipairs(mesecon.queue.actions) do | ||||||
| 					and mesecon.cmpAny(overwritecheck, ac.owcheck) then | 			if(mesecon.cmpPos(pos, ac.pos) | ||||||
| 				-- remove the old action | 			and mesecon.cmpAny(overwritecheck, ac.owcheck)) then | ||||||
| 				table.remove(queue.actions, i) | 				toremove = i | ||||||
| 				break | 				break | ||||||
| 			end | 			end | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	table.insert(queue.actions, action) | 	if (toremove ~= nil) then | ||||||
|  | 		table.remove(mesecon.queue.actions, toremove) | ||||||
|  | 	end | ||||||
|  |  | ||||||
|  | 	table.insert(mesecon.queue.actions, action) | ||||||
| end | end | ||||||
|  |  | ||||||
| -- execute the stored functions on a globalstep | -- execute the stored functions on a globalstep | ||||||
| -- if however, the pos of a function is not loaded (get_node_or_nil == nil), do NOT execute the function | -- if however, the pos of a function is not loaded (get_node_or_nil == nil), do NOT execute the function | ||||||
| -- this makes sure that resuming mesecons circuits when restarting minetest works fine (hm, where do we do this?) | -- this makes sure that resuming mesecons circuits when restarting minetest works fine | ||||||
| -- However, even that does not work in some cases, that's why we delay the time the globalsteps | -- However, even that does not work in some cases, that's why we delay the time the globalsteps | ||||||
| -- start to be execute by 4 seconds | -- start to be execute by 5 seconds | ||||||
|  | local get_highest_priority = function (actions) | ||||||
|  | 	local highestp = -1 | ||||||
|  | 	local highesti | ||||||
|  | 	for i, ac in ipairs(actions) do | ||||||
|  | 		if ac.priority > highestp then | ||||||
|  | 			highestp = ac.priority | ||||||
|  | 			highesti = i | ||||||
|  | 		end | ||||||
|  | 	end | ||||||
|  |  | ||||||
| local function globalstep_func(dtime) | 	return highesti | ||||||
| 	local actions = queue.actions | end | ||||||
| 	-- split into two categories: |  | ||||||
| 	-- actions_now: actions to execute now |  | ||||||
| 	-- queue.actions: actions to execute later |  | ||||||
| 	local actions_now = {} |  | ||||||
| 	queue.actions = {} |  | ||||||
|  |  | ||||||
| 	for _, ac in ipairs(actions) do | local m_time = 0 | ||||||
|  | local resumetime = mesecon.setting("resumetime", 4) | ||||||
|  | minetest.register_globalstep(function (dtime) | ||||||
|  | 	m_time = m_time + dtime | ||||||
|  | 	-- don't even try if server has not been running for XY seconds; resumetime = time to wait | ||||||
|  | 	-- after starting the server before processing the ActionQueue, don't set this too low | ||||||
|  | 	if (m_time < resumetime) then return end | ||||||
|  | 	local actions = mesecon.tablecopy(mesecon.queue.actions) | ||||||
|  | 	local actions_now={} | ||||||
|  |  | ||||||
|  | 	mesecon.queue.actions = {} | ||||||
|  |  | ||||||
|  | 	-- sort actions into two categories: | ||||||
|  | 	-- those toexecute now (actions_now) and those to execute later (mesecon.queue.actions) | ||||||
|  | 	for i, ac in ipairs(actions) do | ||||||
| 		if ac.time > 0 then | 		if ac.time > 0 then | ||||||
| 			-- action ac is to be executed later | 			ac.time = ac.time - dtime -- executed later | ||||||
| 			-- ~> insert into queue.actions | 			table.insert(mesecon.queue.actions, ac) | ||||||
| 			ac.time = ac.time - dtime |  | ||||||
| 			table.insert(queue.actions, ac) |  | ||||||
| 		else | 		else | ||||||
| 			-- action ac is to be executed now |  | ||||||
| 			-- ~> insert into actions_now |  | ||||||
| 			table.insert(actions_now, ac) | 			table.insert(actions_now, ac) | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	-- stable-sort the executed actions after their priority | 	while(#actions_now > 0) do -- execute highest priorities first, until all are executed | ||||||
| 	-- some constructions might depend on the execution order, hence we first | 		local hp = get_highest_priority(actions_now) | ||||||
| 	-- execute the actions that had a lower index in actions_now | 		mesecon.queue:execute(actions_now[hp]) | ||||||
| 	local old_action_order = {} | 		table.remove(actions_now, hp) | ||||||
| 	for i, ac in ipairs(actions_now) do |  | ||||||
| 		old_action_order[ac] = i |  | ||||||
| 	end | 	end | ||||||
| 	table.sort(actions_now, function(ac1, ac2) | end) | ||||||
| 		if ac1.priority ~= ac2.priority then |  | ||||||
| 			return ac1.priority > ac2.priority |  | ||||||
| 		else |  | ||||||
| 			return old_action_order[ac1] < old_action_order[ac2] |  | ||||||
| 		end |  | ||||||
| 	end) |  | ||||||
|  |  | ||||||
| 	-- execute highest priorities first, until all are executed | function mesecon.queue:execute(action) | ||||||
| 	for _, ac in ipairs(actions_now) do | 	mesecon.queue.funcs[action.func](action.pos, unpack(action.params)) | ||||||
| 		queue:execute(ac) |  | ||||||
| 	end |  | ||||||
| end |  | ||||||
|  |  | ||||||
| -- delay the time the globalsteps start to be execute by 4 seconds |  | ||||||
| do |  | ||||||
| 	local m_time = 0 |  | ||||||
| 	local resumetime = mesecon.setting("resumetime", 4) |  | ||||||
| 	local globalstep_func_index = #minetest.registered_globalsteps + 1 |  | ||||||
|  |  | ||||||
| 	minetest.register_globalstep(function(dtime) |  | ||||||
| 		m_time = m_time + dtime |  | ||||||
| 		-- don't even try if server has not been running for XY seconds; resumetime = time to wait |  | ||||||
| 		-- after starting the server before processing the ActionQueue, don't set this too low |  | ||||||
| 		if m_time < resumetime then |  | ||||||
| 			return |  | ||||||
| 		end |  | ||||||
| 		-- replace this globalstep function |  | ||||||
| 		minetest.registered_globalsteps[globalstep_func_index] = globalstep_func |  | ||||||
| 	end) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| function queue:execute(action) |  | ||||||
| 	-- ignore if action queue function name doesn't exist, |  | ||||||
| 	-- (e.g. in case the action queue savegame was written by an old mesecons version) |  | ||||||
| 	if queue.funcs[action.func] then |  | ||||||
| 		queue.funcs[action.func](action.pos, unpack(action.params)) |  | ||||||
| 	end |  | ||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| -- Store and read the ActionQueue to / from a file | -- Store and read the ActionQueue to / from a file | ||||||
| -- so that upcoming actions are remembered when the game | -- so that upcoming actions are remembered when the game | ||||||
| -- is restarted | -- is restarted | ||||||
| queue.actions = mesecon.file2table("mesecon_actionqueue") |  | ||||||
|  | local wpath = minetest.get_worldpath() | ||||||
|  | local function file2table(filename) | ||||||
|  | 	local f = io.open(filename, "r") | ||||||
|  | 	if f==nil then return {} end | ||||||
|  | 	local t = f:read("*all") | ||||||
|  | 	f:close() | ||||||
|  | 	if t=="" or t==nil then return {} end | ||||||
|  | 	return minetest.deserialize(t) | ||||||
|  | end | ||||||
|  |  | ||||||
|  | local function table2file(filename, table) | ||||||
|  | 	local f = io.open(filename, "w") | ||||||
|  | 	f:write(minetest.serialize(table)) | ||||||
|  | 	f:close() | ||||||
|  | end | ||||||
|  |  | ||||||
|  | mesecon.queue.actions = file2table(wpath.."/mesecon_actionqueue") | ||||||
|  |  | ||||||
| minetest.register_on_shutdown(function() | minetest.register_on_shutdown(function() | ||||||
| 	mesecon.table2file("mesecon_actionqueue", queue.actions) | 	mesecon.queue.actions = table2file(wpath.."/mesecon_actionqueue", mesecon.queue.actions) | ||||||
| end) | end) | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								mesecons/depends.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | |||||||
|  | default | ||||||
| @@ -1,62 +0,0 @@ | |||||||
|  |  | ||||||
| -- a simple first-in-first-out queue |  | ||||||
| -- very similar to the one in https://github.com/minetest/minetest/pull/7683 |  | ||||||
|  |  | ||||||
| local fifo_queue = {} |  | ||||||
|  |  | ||||||
| local metatable = {__index = fifo_queue} |  | ||||||
|  |  | ||||||
| -- creates a new empty queue |  | ||||||
| function fifo_queue.new() |  | ||||||
| 	local q = {n_in = 0, n_out = 0, i_out = 1, buf_in = {}, buf_out = {}} |  | ||||||
| 	setmetatable(q, metatable) |  | ||||||
| 	return q |  | ||||||
| end |  | ||||||
|  |  | ||||||
| -- adds an element to the queue |  | ||||||
| function fifo_queue.add(self, v) |  | ||||||
| 	local n = self.n_in + 1 |  | ||||||
| 	self.n_in = n |  | ||||||
| 	self.buf_in[n] = v |  | ||||||
| end |  | ||||||
|  |  | ||||||
| -- removes and returns the next element, or nil of empty |  | ||||||
| function fifo_queue.take(self) |  | ||||||
| 	local i_out = self.i_out |  | ||||||
| 	if i_out <= self.n_out then |  | ||||||
| 		local v = self.buf_out[i_out] |  | ||||||
| 		self.i_out = i_out + 1 |  | ||||||
| 		self.buf_out[i_out] = true |  | ||||||
| 		return v |  | ||||||
| 	end |  | ||||||
|  |  | ||||||
| 	-- buf_out is empty, try to swap |  | ||||||
| 	self.i_out = 1 |  | ||||||
| 	self.n_out = 0 |  | ||||||
| 	if self.n_in == 0 then |  | ||||||
| 		return nil -- empty |  | ||||||
| 	end |  | ||||||
|  |  | ||||||
| 	-- swap |  | ||||||
| 	self.n_out = self.n_in |  | ||||||
| 	self.n_in = 0 |  | ||||||
| 	self.buf_out, self.buf_in = self.buf_in, self.buf_out |  | ||||||
|  |  | ||||||
| 	local v = self.buf_out[1] |  | ||||||
| 	self.i_out = 2 |  | ||||||
| 	self.buf_out[1] = true |  | ||||||
| 	return v |  | ||||||
| end |  | ||||||
|  |  | ||||||
| -- returns whether the queue is empty |  | ||||||
| function fifo_queue.is_empty(self) |  | ||||||
| 	return self.n_out == self.i_out + 1 and self.n_in == 0 |  | ||||||
| end |  | ||||||
|  |  | ||||||
| -- returns stuff for iteration in a for loop, like pairs |  | ||||||
| -- adding new elements while iterating is no problem |  | ||||||
| function fifo_queue.iter(self) |  | ||||||
| 	return fifo_queue.take, self, nil |  | ||||||
| end |  | ||||||
|  |  | ||||||
| return fifo_queue |  | ||||||
| @@ -3,7 +3,7 @@ | |||||||
| -- |  \/  | |___ ____  |___ |      |    | | \  | |____ | -- |  \/  | |___ ____  |___ |      |    | | \  | |____ | ||||||
| -- |      | |        | |    |      |    | |  \ |     | | -- |      | |        | |    |      |    | |  \ |     | | ||||||
| -- |      | |___ ____| |___ |____  |____| |   \| ____| | -- |      | |___ ____| |___ |____  |____| |   \| ____| | ||||||
| -- by Jeija, Uberi (Temperest), sfan5, VanessaE, Hawk777 and contributors | -- by Jeija, Uberi (Temperest), sfan5, VanessaE | ||||||
| -- | -- | ||||||
| -- | -- | ||||||
| -- | -- | ||||||
| @@ -11,7 +11,7 @@ | |||||||
| -- See the documentation on the forum for additional information, especially about crafting | -- See the documentation on the forum for additional information, especially about crafting | ||||||
| -- | -- | ||||||
| -- | -- | ||||||
| -- For basic development resources, see http://mesecons.net/developers.html | -- For developer documentation see the Developers' section on mesecons.TK | ||||||
| -- | -- | ||||||
| -- | -- | ||||||
| -- | -- | ||||||
| @@ -30,7 +30,7 @@ | |||||||
| --		action_change = function | --		action_change = function | ||||||
| --		rules = rules/get_rules | --		rules = rules/get_rules | ||||||
| --	}, | --	}, | ||||||
| --	conductor = | --	conductor =  | ||||||
| --	{ | --	{ | ||||||
| --		state = mesecon.state.on/off | --		state = mesecon.state.on/off | ||||||
| --		offstate = opposite state (for state = on only) | --		offstate = opposite state (for state = on only) | ||||||
| @@ -70,20 +70,26 @@ dofile(minetest.get_modpath("mesecons").."/internal.lua"); | |||||||
| -- these are the only functions you need to remember | -- these are the only functions you need to remember | ||||||
|  |  | ||||||
| mesecon.queue:add_function("receptor_on", function (pos, rules) | mesecon.queue:add_function("receptor_on", function (pos, rules) | ||||||
| 	mesecon.vm_begin() |  | ||||||
|  |  | ||||||
| 	rules = rules or mesecon.rules.default | 	rules = rules or mesecon.rules.default | ||||||
|  |  | ||||||
| 	-- Call turnon on all linking positions | 	-- if area (any of the rule targets) is not loaded, keep trying and call this again later | ||||||
| 	for _, rule in ipairs(mesecon.flattenrules(rules)) do | 	for _, rule in ipairs(mesecon.flattenrules(rules)) do | ||||||
| 		local np = vector.add(pos, rule) | 		local np = mesecon.addPosRule(pos, rule) | ||||||
|  | 		-- if area is not loaded, keep trying | ||||||
|  | 		if minetest.get_node_or_nil(np) == nil then | ||||||
|  | 			mesecon.queue:add_action(pos, "receptor_on", {rules}, nil, rules) | ||||||
|  | 			return | ||||||
|  | 		end | ||||||
|  | 	end | ||||||
|  |  | ||||||
|  | 	-- execute action | ||||||
|  | 	for _, rule in ipairs(mesecon.flattenrules(rules)) do | ||||||
|  | 		local np = mesecon.addPosRule(pos, rule) | ||||||
| 		local rulenames = mesecon.rules_link_rule_all(pos, rule) | 		local rulenames = mesecon.rules_link_rule_all(pos, rule) | ||||||
| 		for _, rulename in ipairs(rulenames) do | 		for _, rulename in ipairs(rulenames) do | ||||||
| 			mesecon.turnon(np, rulename) | 			mesecon.turnon(np, rulename) | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	mesecon.vm_commit() |  | ||||||
| end) | end) | ||||||
|  |  | ||||||
| function mesecon.receptor_on(pos, rules) | function mesecon.receptor_on(pos, rules) | ||||||
| @@ -93,21 +99,23 @@ end | |||||||
| mesecon.queue:add_function("receptor_off", function (pos, rules) | mesecon.queue:add_function("receptor_off", function (pos, rules) | ||||||
| 	rules = rules or mesecon.rules.default | 	rules = rules or mesecon.rules.default | ||||||
|  |  | ||||||
| 	-- Call turnoff on all linking positions | 	-- if area (any of the rule targets) is not loaded, keep trying and call this again later | ||||||
| 	for _, rule in ipairs(mesecon.flattenrules(rules)) do | 	for _, rule in ipairs(mesecon.flattenrules(rules)) do | ||||||
| 		local np = vector.add(pos, rule) | 		local np = mesecon.addPosRule(pos, rule) | ||||||
|  | 		if minetest.get_node_or_nil(np) == nil then | ||||||
|  | 			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) | 		local rulenames = mesecon.rules_link_rule_all(pos, rule) | ||||||
| 		for _, rulename in ipairs(rulenames) do | 		for _, rulename in ipairs(rulenames) do | ||||||
| 			mesecon.vm_begin() | 			if not mesecon.connected_to_receptor(np, mesecon.invertRule(rule)) then | ||||||
| 			mesecon.changesignal(np, minetest.get_node(np), rulename, mesecon.state.off, 2) | 				mesecon.turnoff(np, rulename) | ||||||
|  |  | ||||||
| 			-- Turnoff returns true if turnoff process was successful, no onstate receptor |  | ||||||
| 			-- was found along the way. Commit changes that were made in voxelmanip. If turnoff |  | ||||||
| 			-- returns true, an onstate receptor was found, abort voxelmanip transaction. |  | ||||||
| 			if (mesecon.turnoff(np, rulename)) then |  | ||||||
| 				mesecon.vm_commit() |  | ||||||
| 			else | 			else | ||||||
| 				mesecon.vm_abort() | 				mesecon.changesignal(np, minetest.get_node(np), rulename, mesecon.state.off, 2) | ||||||
| 			end | 			end | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
| @@ -124,5 +132,8 @@ print("[OK] Mesecons") | |||||||
| -- To be removed in future releases | -- To be removed in future releases | ||||||
| dofile(minetest.get_modpath("mesecons").."/legacy.lua"); | dofile(minetest.get_modpath("mesecons").."/legacy.lua"); | ||||||
|  |  | ||||||
|  | --The actual wires | ||||||
|  | dofile(minetest.get_modpath("mesecons").."/wires.lua"); | ||||||
|  |  | ||||||
| --Services like turnoff receptor on dignode and so on | --Services like turnoff receptor on dignode and so on | ||||||
| dofile(minetest.get_modpath("mesecons").."/services.lua"); | dofile(minetest.get_modpath("mesecons").."/services.lua"); | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ | |||||||
|  |  | ||||||
| -- 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) | ||||||
|  |  | ||||||
| @@ -37,6 +37,11 @@ | |||||||
| -- HIGH-LEVEL Internals | -- HIGH-LEVEL Internals | ||||||
| -- mesecon.is_power_on(pos)				--> Returns true if pos emits power in any way | -- mesecon.is_power_on(pos)				--> Returns true if pos emits power in any way | ||||||
| -- mesecon.is_power_off(pos)				--> Returns true if pos does not emit power in any way | -- mesecon.is_power_off(pos)				--> Returns true if pos does not emit power in any way | ||||||
|  | -- mesecon.turnon(pos, link) 				--> link is the input rule that caused calling turnon, turns on every connected node, iterative | ||||||
|  | -- mesecon.turnoff(pos, link)				--> link is the input rule that caused calling turnoff, turns off every connected node, iterative | ||||||
|  | -- mesecon.connected_to_receptor(pos, link)		--> Returns true if pos is connected to a receptor directly or via conductors, iterative | ||||||
|  | -- mesecon.rules_link(output, input, dug_outputrules)	--> Returns true if outputposition + outputrules = inputposition and inputposition + inputrules = outputposition (if the two positions connect) | ||||||
|  | -- mesecon.rules_link_anydir(outp., inp., d_outpr.)	--> Same as rules mesecon.rules_link but also returns true if output and input are swapped | ||||||
| -- mesecon.is_powered(pos)				--> Returns true if pos is powered by a receptor or a conductor | -- mesecon.is_powered(pos)				--> Returns true if pos is powered by a receptor or a conductor | ||||||
|  |  | ||||||
| -- RULES ROTATION helpers | -- RULES ROTATION helpers | ||||||
| @@ -46,8 +51,6 @@ | |||||||
| -- 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 | ||||||
|  |  | ||||||
| local fifo_queue = dofile(minetest.get_modpath("mesecons").."/fifo_queue.lua") |  | ||||||
|  |  | ||||||
| -- General | -- General | ||||||
| function mesecon.get_effector(nodename) | function mesecon.get_effector(nodename) | ||||||
| 	if  minetest.registered_nodes[nodename] | 	if  minetest.registered_nodes[nodename] | ||||||
| @@ -73,9 +76,7 @@ function mesecon.get_conductor(nodename) | |||||||
| 	end | 	end | ||||||
| end | end | ||||||
|  |  | ||||||
| function mesecon.get_any_outputrules(node) | function mesecon.get_any_outputrules (node) | ||||||
| 	if not node then return nil end |  | ||||||
|  |  | ||||||
| 	if mesecon.is_conductor(node.name) then | 	if mesecon.is_conductor(node.name) then | ||||||
| 		return mesecon.conductor_get_rules(node) | 		return mesecon.conductor_get_rules(node) | ||||||
| 	elseif mesecon.is_receptor(node.name) then | 	elseif mesecon.is_receptor(node.name) then | ||||||
| @@ -83,9 +84,7 @@ function mesecon.get_any_outputrules(node) | |||||||
| 	end | 	end | ||||||
| end | end | ||||||
|  |  | ||||||
| function mesecon.get_any_inputrules(node) | function mesecon.get_any_inputrules (node) | ||||||
| 	if not node then return nil end |  | ||||||
|  |  | ||||||
| 	if mesecon.is_conductor(node.name) then | 	if mesecon.is_conductor(node.name) then | ||||||
| 		return mesecon.conductor_get_rules(node) | 		return mesecon.conductor_get_rules(node) | ||||||
| 	elseif mesecon.is_effector(node.name) then | 	elseif mesecon.is_effector(node.name) then | ||||||
| @@ -93,9 +92,9 @@ function mesecon.get_any_inputrules(node) | |||||||
| 	end | 	end | ||||||
| end | end | ||||||
|  |  | ||||||
| function mesecon.get_any_rules(node) | function mesecon.get_any_rules (node) | ||||||
| 	return mesecon.merge_rule_sets(mesecon.get_any_inputrules(node), | 	return mesecon.mergetable(mesecon.get_any_inputrules(node) or {}, | ||||||
| 		mesecon.get_any_outputrules(node)) | 		mesecon.get_any_outputrules(node) or {}) | ||||||
| end | end | ||||||
|  |  | ||||||
| -- Receptors | -- Receptors | ||||||
| @@ -183,9 +182,7 @@ end | |||||||
|  |  | ||||||
| -- Activation: | -- Activation: | ||||||
| mesecon.queue:add_function("activate", function (pos, rulename) | mesecon.queue:add_function("activate", function (pos, rulename) | ||||||
| 	local node = mesecon.get_node_force(pos) | 	local node = minetest.get_node(pos) | ||||||
| 	if not node then return end |  | ||||||
|  |  | ||||||
| 	local effector = mesecon.get_effector(node.name) | 	local effector = mesecon.get_effector(node.name) | ||||||
|  |  | ||||||
| 	if effector and effector.action_on then | 	if effector and effector.action_on then | ||||||
| @@ -206,9 +203,7 @@ end | |||||||
|  |  | ||||||
| -- Deactivation | -- Deactivation | ||||||
| mesecon.queue:add_function("deactivate", function (pos, rulename) | mesecon.queue:add_function("deactivate", function (pos, rulename) | ||||||
| 	local node = mesecon.get_node_force(pos) | 	local node = minetest.get_node(pos) | ||||||
| 	if not node then return end |  | ||||||
|  |  | ||||||
| 	local effector = mesecon.get_effector(node.name) | 	local effector = mesecon.get_effector(node.name) | ||||||
|  |  | ||||||
| 	if effector and effector.action_off then | 	if effector and effector.action_off then | ||||||
| @@ -229,9 +224,7 @@ end | |||||||
|  |  | ||||||
| -- Change | -- Change | ||||||
| mesecon.queue:add_function("change", function (pos, rulename, changetype) | mesecon.queue:add_function("change", function (pos, rulename, changetype) | ||||||
| 	local node = mesecon.get_node_force(pos) | 	local node = minetest.get_node(pos) | ||||||
| 	if not node then return end |  | ||||||
|  |  | ||||||
| 	local effector = mesecon.get_effector(node.name) | 	local effector = mesecon.get_effector(node.name) | ||||||
|  |  | ||||||
| 	if effector and effector.action_change then | 	if effector and effector.action_change then | ||||||
| @@ -256,8 +249,6 @@ end | |||||||
| -- Conductors | -- Conductors | ||||||
|  |  | ||||||
| function mesecon.is_conductor_on(node, rulename) | function mesecon.is_conductor_on(node, rulename) | ||||||
| 	if not node then return false end |  | ||||||
|  |  | ||||||
| 	local conductor = mesecon.get_conductor(node.name) | 	local conductor = mesecon.get_conductor(node.name) | ||||||
| 	if conductor then | 	if conductor then | ||||||
| 		if conductor.state then | 		if conductor.state then | ||||||
| @@ -272,13 +263,10 @@ function mesecon.is_conductor_on(node, rulename) | |||||||
| 			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) | ||||||
| 	if not node then return false end |  | ||||||
|  |  | ||||||
| 	local conductor = mesecon.get_conductor(node.name) | 	local conductor = mesecon.get_conductor(node.name) | ||||||
| 	if conductor then | 	if conductor then | ||||||
| 		if conductor.state then | 		if conductor.state then | ||||||
| @@ -293,7 +281,6 @@ function mesecon.is_conductor_off(node, rulename) | |||||||
| 			return not mesecon.get_bit(binstate, bit) | 			return not mesecon.get_bit(binstate, bit) | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	return false | 	return false | ||||||
| end | end | ||||||
|  |  | ||||||
| @@ -353,182 +340,233 @@ 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 = mesecon.get_node_force(pos) | 	local node = minetest.get_node(pos) | ||||||
| 	if node and (mesecon.is_conductor_on(node, rulename) or mesecon.is_receptor_on(node.name)) then | 	if 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 = mesecon.get_node_force(pos) | 	local node = minetest.get_node(pos) | ||||||
| 	if node and (mesecon.is_conductor_off(node, rulename) or mesecon.is_receptor_off(node.name)) then | 	if 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 | ||||||
|  |  | ||||||
| -- Turn off an equipotential section starting at `pos`, which outputs in the direction of `link`. |  | ||||||
| -- Breadth-first search. Map is abstracted away in a voxelmanip. |  | ||||||
| -- Follow all all conductor paths replacing conductors that were already |  | ||||||
| -- looked at, activating / changing all effectors along the way. |  | ||||||
| function mesecon.turnon(pos, link) | function mesecon.turnon(pos, link) | ||||||
| 	local frontiers = fifo_queue.new() | 	local frontiers = {{pos = pos, link = link}} | ||||||
| 	frontiers:add({pos = pos, link = link}) |  | ||||||
| 	local pos_can_be_skipped = {} |  | ||||||
|  |  | ||||||
| 	local depth = 1 | 	local depth = 1 | ||||||
| 	for f in frontiers:iter() do | 	while frontiers[depth] do | ||||||
| 		local node = mesecon.get_node_force(f.pos) | 		local f = frontiers[depth] | ||||||
|  | 		local node = minetest.get_node_or_nil(f.pos) | ||||||
|  |  | ||||||
|  | 		-- area not loaded, postpone action | ||||||
| 		if not node then | 		if not node then | ||||||
| 			-- Area does not exist; do nothing | 			mesecon.queue:add_action(f.pos, "turnon", {link}, nil, true) | ||||||
| 			pos_can_be_skipped[minetest.hash_node_position(f.pos)] = true |  | ||||||
| 		elseif mesecon.is_conductor_off(node, f.link) then | 		elseif mesecon.is_conductor_off(node, f.link) then | ||||||
| 			local rules = mesecon.conductor_get_rules(node) | 			local rules = mesecon.conductor_get_rules(node) | ||||||
|  |  | ||||||
| 			-- Call turnon on neighbors | 			minetest.swap_node(f.pos, {name = mesecon.get_conductor_on(node, f.link), | ||||||
|  | 				param2 = node.param2}) | ||||||
|  |  | ||||||
|  | 			-- call turnon on neighbors: normal rules | ||||||
| 			for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do | 			for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do | ||||||
| 				local np = vector.add(f.pos, r) | 				local np = mesecon.addPosRule(f.pos, r) | ||||||
| 				if not pos_can_be_skipped[minetest.hash_node_position(np)] then |  | ||||||
| 					for _, l in ipairs(mesecon.rules_link_rule_all(f.pos, r)) do | 				-- area not loaded, postpone action | ||||||
| 						frontiers:add({pos = np, link = l}) | 				if not minetest.get_node_or_nil(np) then | ||||||
|  | 					mesecon.queue:add_action(np, "turnon", {rulename}, | ||||||
|  | 						nil, true) | ||||||
|  | 				else | ||||||
|  | 					local links = mesecon.rules_link_rule_all(f.pos, r) | ||||||
|  | 					for _, l in ipairs(links) do | ||||||
|  | 						table.insert(frontiers, {pos = np, link = l}) | ||||||
| 					end | 					end | ||||||
| 				end | 				end | ||||||
| 			end | 			end | ||||||
|  |  | ||||||
| 			mesecon.swap_node_force(f.pos, mesecon.get_conductor_on(node, f.link)) |  | ||||||
| 			pos_can_be_skipped[minetest.hash_node_position(f.pos)] = true |  | ||||||
| 		elseif mesecon.is_effector(node.name) then | 		elseif mesecon.is_effector(node.name) then | ||||||
| 			mesecon.changesignal(f.pos, node, f.link, mesecon.state.on, depth) | 			mesecon.changesignal(f.pos, node, f.link, mesecon.state.on, depth) | ||||||
| 			if mesecon.is_effector_off(node.name) then | 			if mesecon.is_effector_off(node.name) then | ||||||
| 				mesecon.activate(f.pos, node, f.link, depth) | 				mesecon.activate(f.pos, node, f.link, depth) | ||||||
| 			end | 			end | ||||||
| 		else |  | ||||||
| 			pos_can_be_skipped[minetest.hash_node_position(f.pos)] = true |  | ||||||
| 		end | 		end | ||||||
| 		depth = depth + 1 | 		depth = depth + 1 | ||||||
| 	end | 	end | ||||||
| end | end | ||||||
|  |  | ||||||
| -- Turn on an equipotential section starting at `pos`, which outputs in the direction of `link`. | mesecon.queue:add_function("turnon", function (pos, rulename, recdepth) | ||||||
| -- Breadth-first search. Map is abstracted away in a voxelmanip. | 	mesecon.turnon(pos, rulename, recdepth) | ||||||
| -- Follow all all conductor paths replacing conductors that were already | end) | ||||||
| -- looked at, deactivating / changing all effectors along the way. |  | ||||||
| -- In case an onstate receptor is discovered, abort the process by returning false, which will |  | ||||||
| -- cause `receptor_off` to discard all changes made in the voxelmanip. |  | ||||||
| -- Contrary to turnon, turnoff has to cache all change and deactivate signals so that they will only |  | ||||||
| -- be called in the very end when we can be sure that no conductor was found along the path. |  | ||||||
| -- |  | ||||||
| -- Signal table entry structure: |  | ||||||
| -- { |  | ||||||
| --	pos = position of effector, |  | ||||||
| --	node = node descriptor (name, param1 and param2), |  | ||||||
| --	link = link the effector is connected to, |  | ||||||
| --	depth = indicates order in which signals wire fired, higher is later |  | ||||||
| -- } |  | ||||||
| function mesecon.turnoff(pos, link) | function mesecon.turnoff(pos, link) | ||||||
| 	local frontiers = fifo_queue.new() | 	local frontiers = {{pos = pos, link = link}} | ||||||
| 	frontiers:add({pos = pos, link = link}) |  | ||||||
| 	local signals = {} |  | ||||||
| 	local pos_can_be_skipped = {} |  | ||||||
|  |  | ||||||
| 	local depth = 1 | 	local depth = 1 | ||||||
| 	for f in frontiers:iter() do | 	while frontiers[depth] do | ||||||
| 		local node = mesecon.get_node_force(f.pos) | 		local f = frontiers[depth] | ||||||
|  | 		local node = minetest.get_node_or_nil(f.pos) | ||||||
|  |  | ||||||
|  | 		-- area not loaded, postpone action | ||||||
| 		if not node then | 		if not node then | ||||||
| 			-- Area does not exist; do nothing | 			mesecon.queue:add_action(f.pos, "turnoff", {link}, nil, true) | ||||||
| 			pos_can_be_skipped[minetest.hash_node_position(f.pos)] = true |  | ||||||
| 		elseif mesecon.is_conductor_on(node, f.link) then | 		elseif mesecon.is_conductor_on(node, f.link) then | ||||||
| 			local rules = mesecon.conductor_get_rules(node) | 			local rules = mesecon.conductor_get_rules(node) | ||||||
|  |  | ||||||
|  | 			minetest.swap_node(f.pos, {name = mesecon.get_conductor_off(node, f.link), | ||||||
|  | 				param2 = node.param2}) | ||||||
|  |  | ||||||
|  | 			-- call turnoff on neighbors: normal rules | ||||||
| 			for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do | 			for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do | ||||||
| 				local np = vector.add(f.pos, r) | 				local np = mesecon.addPosRule(f.pos, r) | ||||||
|  |  | ||||||
| 				if not pos_can_be_skipped[minetest.hash_node_position(np)] then | 				-- area not loaded, postpone action | ||||||
| 					-- Check if an onstate receptor is connected. If that is the case, | 				if not minetest.get_node_or_nil(np) then | ||||||
| 					-- abort this turnoff process by returning false. `receptor_off` will | 					mesecon.queue:add_action(np, "turnoff", {rulename}, | ||||||
| 					-- discard all the changes that we made in the voxelmanip: | 						nil, true) | ||||||
| 					if mesecon.rules_link_rule_all_inverted(f.pos, r)[1] then | 				else | ||||||
| 						if mesecon.is_receptor_on(mesecon.get_node_force(np).name) then | 					local links = mesecon.rules_link_rule_all(f.pos, r) | ||||||
| 							return false | 					for _, l in ipairs(links) do | ||||||
| 						end | 						table.insert(frontiers, {pos = np, link = l}) | ||||||
| 					end |  | ||||||
|  |  | ||||||
| 					-- Call turnoff on neighbors |  | ||||||
| 					for _, l in ipairs(mesecon.rules_link_rule_all(f.pos, r)) do |  | ||||||
| 						frontiers:add({pos = np, link = l}) |  | ||||||
| 					end | 					end | ||||||
| 				end | 				end | ||||||
| 			end | 			end | ||||||
|  |  | ||||||
| 			mesecon.swap_node_force(f.pos, mesecon.get_conductor_off(node, f.link)) |  | ||||||
| 			pos_can_be_skipped[minetest.hash_node_position(f.pos)] = true |  | ||||||
| 		elseif mesecon.is_effector(node.name) then | 		elseif mesecon.is_effector(node.name) then | ||||||
| 			table.insert(signals, { | 			mesecon.changesignal(f.pos, node, f.link, mesecon.state.off, depth) | ||||||
| 				pos = f.pos, | 			if mesecon.is_effector_on(node.name) and not mesecon.is_powered(f.pos) then | ||||||
| 				node = node, | 				mesecon.deactivate(f.pos, node, f.link, depth) | ||||||
| 				link = f.link, | 			end | ||||||
| 				depth = depth |  | ||||||
| 			}) |  | ||||||
| 		else |  | ||||||
| 			pos_can_be_skipped[minetest.hash_node_position(f.pos)] = true |  | ||||||
| 		end | 		end | ||||||
| 		depth = depth + 1 | 		depth = depth + 1 | ||||||
| 	end | 	end | ||||||
|  | end | ||||||
|  |  | ||||||
| 	for _, sig in ipairs(signals) do | mesecon.queue:add_function("turnoff", function (pos, rulename, recdepth) | ||||||
| 		mesecon.changesignal(sig.pos, sig.node, sig.link, mesecon.state.off, sig.depth) | 	mesecon.turnoff(pos, rulename, recdepth) | ||||||
| 		if mesecon.is_effector_on(sig.node.name) and not mesecon.is_powered(sig.pos) then | end) | ||||||
| 			mesecon.deactivate(sig.pos, sig.node, sig.link, sig.depth) |  | ||||||
|  |  | ||||||
|  | function mesecon.connected_to_receptor(pos, link) | ||||||
|  | 	local node = 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(link, rules)) do | ||||||
|  | 		local links = mesecon.rules_link_rule_all_inverted(pos, rule) | ||||||
|  | 		for _, l in ipairs(links) do | ||||||
|  | 			local np = mesecon.addPosRule(pos, l) | ||||||
|  | 			if mesecon.find_receptor_on(np, mesecon.invertRule(l)) then | ||||||
|  | 				return true | ||||||
|  | 			end | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	return true | 	return false | ||||||
|  | end | ||||||
|  |  | ||||||
|  | function mesecon.find_receptor_on(pos, link) | ||||||
|  | 	local frontiers = {{pos = pos, link = link}} | ||||||
|  | 	local checked = {} | ||||||
|  |  | ||||||
|  | 	-- List of positions that have been searched for onstate receptors | ||||||
|  | 	local depth = 1 | ||||||
|  | 	while frontiers[depth] do | ||||||
|  | 		local f = frontiers[depth] | ||||||
|  | 		local node = minetest.get_node_or_nil(f.pos) | ||||||
|  |  | ||||||
|  | 		if not node then return false end | ||||||
|  | 		if mesecon.is_receptor_on(node.name) then return true end | ||||||
|  | 		if mesecon.is_conductor_on(node, f.link) then | ||||||
|  | 			local rules = mesecon.conductor_get_rules(node) | ||||||
|  |  | ||||||
|  | 			-- call turnoff on neighbors: normal rules | ||||||
|  | 			for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do | ||||||
|  | 				local np = mesecon.addPosRule(f.pos, r) | ||||||
|  |  | ||||||
|  | 				local links = mesecon.rules_link_rule_all_inverted(f.pos, r) | ||||||
|  | 				for _, l in ipairs(links) do | ||||||
|  | 					local checkedstring = np.x..np.y..np.z..l.x..l.y..l.z | ||||||
|  | 					if not checked[checkedstring] then | ||||||
|  | 						table.insert(frontiers, {pos = np, link = l}) | ||||||
|  | 						checked[checkedstring] = true | ||||||
|  | 					end | ||||||
|  | 				end | ||||||
|  | 			end | ||||||
|  | 			 | ||||||
|  | 		end | ||||||
|  | 		depth = depth + 1 | ||||||
|  | 	end | ||||||
|  | end | ||||||
|  |  | ||||||
|  | function mesecon.rules_link(output, input, dug_outputrules) --output/input are positions (outputrules optional, used if node has been dug), second return value: the name of the affected input rule | ||||||
|  | 	local outputnode = 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 | ||||||
|  | 					return true, inputrule | ||||||
|  | 				end | ||||||
|  | 			end | ||||||
|  | 		end | ||||||
|  | 	end | ||||||
|  | 	return false | ||||||
| end | end | ||||||
|  |  | ||||||
| -- Get all linking inputrules of inputnode (effector or conductor) that is connected to |  | ||||||
| -- outputnode (receptor or conductor) at position `output` and has an output in direction `rule` |  | ||||||
| function mesecon.rules_link_rule_all(output, rule) | function mesecon.rules_link_rule_all(output, rule) | ||||||
| 	local input = vector.add(output, rule) | 	local input = mesecon.addPosRule(output, rule) | ||||||
| 	local inputnode = mesecon.get_node_force(input) | 	local inputnode = minetest.get_node(input) | ||||||
| 	local inputrules = mesecon.get_any_inputrules(inputnode) | 	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  vector.equals(vector.add(input, inputrule), output) then | 		if  mesecon.cmpPos(mesecon.addPosRule(input, inputrule), output) then | ||||||
| 			table.insert(rules, inputrule) | 			table.insert(rules, inputrule) | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	return rules | 	return rules | ||||||
| end | end | ||||||
|  |  | ||||||
| -- Get all linking outputnodes of outputnode (receptor or conductor) that is connected to |  | ||||||
| -- inputnode (effector or conductor) at position `input` and has an input in direction `rule` |  | ||||||
| function mesecon.rules_link_rule_all_inverted(input, rule) | function mesecon.rules_link_rule_all_inverted(input, rule) | ||||||
| 	local output = vector.add(input, rule) | 	--local irule = mesecon.invertRule(rule) | ||||||
| 	local outputnode = mesecon.get_node_force(output) | 	local output = mesecon.addPosRule(input, rule) | ||||||
| 	local outputrules = mesecon.get_any_outputrules(outputnode) | 	local outputnode = minetest.get_node(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  vector.equals(vector.add(output, outputrule), input) then | 		if  mesecon.cmpPos(mesecon.addPosRule(output, outputrule), input) then | ||||||
| 			table.insert(rules, mesecon.invertRule(outputrule)) | 			table.insert(rules, mesecon.invertRule(outputrule)) | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
| 	return rules | 	return rules | ||||||
| end | end | ||||||
|  |  | ||||||
|  | function mesecon.rules_link_anydir(pos1, pos2) | ||||||
|  | 	return mesecon.rules_link(pos1, pos2) or mesecon.rules_link(pos2, pos1) | ||||||
|  | end | ||||||
|  |  | ||||||
| function mesecon.is_powered(pos, rule) | function mesecon.is_powered(pos, rule) | ||||||
| 	local node = mesecon.get_node_force(pos) | 	local node = minetest.get_node(pos) | ||||||
| 	local rules = mesecon.get_any_inputrules(node) | 	local rules = mesecon.get_any_inputrules(node) | ||||||
| 	if not rules then return false end | 	if not rules then return false end | ||||||
|  |  | ||||||
| @@ -539,11 +577,10 @@ function mesecon.is_powered(pos, rule) | |||||||
| 		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 = vector.add(pos, rname) | 				local np = mesecon.addPosRule(pos, rname) | ||||||
| 				local nn = mesecon.get_node_force(np) | 				local nn = minetest.get_node(np) | ||||||
|  | 				if (mesecon.is_conductor_on (nn, mesecon.invertRule(rname)) | ||||||
| 				if (mesecon.is_conductor_on(nn, mesecon.invertRule(rname)) | 				or mesecon.is_receptor_on (nn.name)) then | ||||||
| 				or mesecon.is_receptor_on(nn.name)) then |  | ||||||
| 					table.insert(sourcepos, np) | 					table.insert(sourcepos, np) | ||||||
| 				end | 				end | ||||||
| 			end | 			end | ||||||
| @@ -551,8 +588,8 @@ function mesecon.is_powered(pos, rule) | |||||||
| 	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 = vector.add(pos, rname) | 			local np = mesecon.addPosRule(pos, rname) | ||||||
| 			local nn = mesecon.get_node_force(np) | 			local nn = minetest.get_node(np) | ||||||
| 			if (mesecon.is_conductor_on (nn, mesecon.invertRule(rname)) | 			if (mesecon.is_conductor_on (nn, mesecon.invertRule(rname)) | ||||||
| 			or mesecon.is_receptor_on (nn.name)) then | 			or mesecon.is_receptor_on (nn.name)) then | ||||||
| 				table.insert(sourcepos, np) | 				table.insert(sourcepos, np) | ||||||
| @@ -564,3 +601,52 @@ function mesecon.is_powered(pos, rule) | |||||||
| 	if (#sourcepos == 0) then return false | 	if (#sourcepos == 0) then return false | ||||||
| 	else return sourcepos end | 	else return sourcepos end | ||||||
| end | end | ||||||
|  |  | ||||||
|  | --Rules rotation Functions: | ||||||
|  | function mesecon.rotate_rules_right(rules) | ||||||
|  | 	local nr = {} | ||||||
|  | 	for i, rule in ipairs(rules) do | ||||||
|  | 		table.insert(nr, { | ||||||
|  | 			x = -rule.z,  | ||||||
|  | 			y =  rule.y,  | ||||||
|  | 			z =  rule.x, | ||||||
|  | 			name = rule.name}) | ||||||
|  | 	end | ||||||
|  | 	return nr | ||||||
|  | end | ||||||
|  |  | ||||||
|  | function mesecon.rotate_rules_left(rules) | ||||||
|  | 	local nr = {} | ||||||
|  | 	for i, rule in ipairs(rules) do | ||||||
|  | 		table.insert(nr, { | ||||||
|  | 			x =  rule.z,  | ||||||
|  | 			y =  rule.y,  | ||||||
|  | 			z = -rule.x, | ||||||
|  | 			name = rule.name}) | ||||||
|  | 	end | ||||||
|  | 	return nr | ||||||
|  | end | ||||||
|  |  | ||||||
|  | function mesecon.rotate_rules_down(rules) | ||||||
|  | 	local nr = {} | ||||||
|  | 	for i, rule in ipairs(rules) do | ||||||
|  | 		table.insert(nr, { | ||||||
|  | 			x = -rule.y,  | ||||||
|  | 			y =  rule.x,  | ||||||
|  | 			z =  rule.z, | ||||||
|  | 			name = rule.name}) | ||||||
|  | 	end | ||||||
|  | 	return nr | ||||||
|  | end | ||||||
|  |  | ||||||
|  | function mesecon.rotate_rules_up(rules) | ||||||
|  | 	local nr = {} | ||||||
|  | 	for i, rule in ipairs(rules) do | ||||||
|  | 		table.insert(nr, { | ||||||
|  | 			x =  rule.y,  | ||||||
|  | 			y = -rule.x,  | ||||||
|  | 			z =  rule.z, | ||||||
|  | 			name = rule.name}) | ||||||
|  | 	end | ||||||
|  | 	return nr | ||||||
|  | end | ||||||
|   | |||||||
| @@ -1,14 +1,30 @@ | |||||||
| -- Un-forceload any forceloaded mapblocks from older versions of Mesecons which | -- Ugly hack to prevent breaking compatibility with other mods | ||||||
| -- used forceloading instead of VoxelManipulators. | -- Just remove the following two functions to delete the hack, to be done when other mods have updated | ||||||
| local BLOCKSIZE = 16 | function mesecon.receptor_on(self, pos, rules) | ||||||
|  | 	if (self.receptor_on) then | ||||||
| -- convert block hash --> node position | 		print("[Mesecons] Warning: A mod with mesecon support called mesecon:receptor_on.") | ||||||
| local function unhash_blockpos(hash) | 		print("[Mesecons]          If you are the programmer of this mod, please update it ") | ||||||
| 	return vector.multiply(minetest.get_position_from_hash(hash), BLOCKSIZE) | 		print("[Mesecons]          to use mesecon.receptor_on instead. mesecon:* is deprecated") | ||||||
|  | 		print("[Mesecons]          Otherwise, please make sure you're running the latest version") | ||||||
|  | 		print("[Mesecons]          of that mod and inform the mod creator.") | ||||||
|  | 	else | ||||||
|  | 		rules = pos | ||||||
|  | 		pos = self | ||||||
|  | 	end | ||||||
|  | 	mesecon.queue:add_action(pos, "receptor_on", {rules}, nil, rules) | ||||||
| end | end | ||||||
|  |  | ||||||
| local old_forceloaded_blocks = mesecon.file2table("mesecon_forceloaded") | function mesecon.receptor_off(self, pos, rules) | ||||||
| for hash, _ in pairs(old_forceloaded_blocks) do | 	if (self.receptor_off) then | ||||||
| 	minetest.forceload_free_block(unhash_blockpos(hash)) | 		print("[Mesecons] Warning: A mod with mesecon support called mesecon:receptor_off.") | ||||||
|  | 		print("[Mesecons]          If you are the programmer of this mod, please update it ") | ||||||
|  | 		print("[Mesecons]          to use mesecon.receptor_off instead. mesecon:* is deprecated") | ||||||
|  | 		print("[Mesecons]          Otherwise, please make sure you're running the latest version") | ||||||
|  | 		print("[Mesecons]          of that mod and inform the mod creator.") | ||||||
|  | 	else | ||||||
|  | 		rules = pos | ||||||
|  | 		pos = self | ||||||
|  | 	end | ||||||
|  | 	mesecon.queue:add_action(pos, "receptor_off", {rules}, nil, rules) | ||||||
| end | end | ||||||
| os.remove(minetest.get_worldpath()..DIR_DELIM.."mesecon_forceloaded") |  | ||||||
|   | |||||||
| @@ -1,2 +0,0 @@ | |||||||
| name = mesecons |  | ||||||
| depends = default |  | ||||||
| @@ -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 = false, | 	is_ground_content = true, | ||||||
| 	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 = false, | 	is_ground_content = true, | ||||||
| 	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 = minetest.LIGHT_MAX-11, | 	light_source = LIGHT_MAX-11, | ||||||
| 	mesecons = {conductor={ | 	mesecons = {conductor={ | ||||||
| 		state = mesecon.state.on, | 		state = mesecon.state.on, | ||||||
| 		offstate = "mesecons:mesecon_off" | 		offstate = "mesecons:mesecon_off" | ||||||
|   | |||||||
| @@ -1,85 +1,46 @@ | |||||||
| mesecon.rules = {} | mesecon.rules = {} | ||||||
| mesecon.state = {} | mesecon.state = {} | ||||||
|  |  | ||||||
| mesecon.rules.default = { | mesecon.rules.default = | ||||||
| 	{x =  0, y =  0, z = -1}, | {{x=0,  y=0,  z=-1}, | ||||||
| 	{x =  1, y =  0, z =  0}, |  {x=1,  y=0,  z=0}, | ||||||
| 	{x = -1, y =  0, z =  0}, |  {x=-1, y=0,  z=0}, | ||||||
| 	{x =  0, y =  0, z =  1}, |  {x=0,  y=0,  z=1}, | ||||||
| 	{x =  1, y =  1, z =  0}, |  {x=1,  y=1,  z=0}, | ||||||
| 	{x =  1, y = -1, z =  0}, |  {x=1,  y=-1, z=0}, | ||||||
| 	{x = -1, y =  1, z =  0}, |  {x=-1, y=1,  z=0}, | ||||||
| 	{x = -1, y = -1, z =  0}, |  {x=-1, y=-1, z=0}, | ||||||
| 	{x =  0, y =  1, z =  1}, |  {x=0,  y=1,  z=1}, | ||||||
| 	{x =  0, y = -1, z =  1}, |  {x=0,  y=-1, z=1}, | ||||||
| 	{x =  0, y =  1, z = -1}, |  {x=0,  y=1,  z=-1}, | ||||||
| 	{x =  0, y = -1, z = -1}, |  {x=0,  y=-1, z=-1}} | ||||||
| } |  | ||||||
|  |  | ||||||
| mesecon.rules.floor = mesecon.merge_rule_sets(mesecon.rules.default, {{x = 0, y = -1, z = 0}}) | mesecon.rules.pplate = mesecon.mergetable(mesecon.rules.default, {{x=0, y=-2, z=0}}) | ||||||
|  |  | ||||||
| mesecon.rules.pplate = mesecon.merge_rule_sets(mesecon.rules.floor, {{x = 0, y = -2, z = 0}}) | mesecon.rules.buttonlike = | ||||||
|  | {{x = 1,  y = 0, z = 0}, | ||||||
| mesecon.rules.buttonlike = { |  {x = 1,  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 =  0}, |  {x = 1,  y =-1, z =-1}, | ||||||
| 	{x = 1,  y = -1, z =  1}, |  {x = 2,  y = 0, z = 0}} | ||||||
| 	{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.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.buttonlike_get = function(node) | mesecon.rules.buttonlike_get = function(node) | ||||||
| 	local dir = minetest.facedir_to_dir(node.param2) | 	local rules = mesecon.rules.buttonlike | ||||||
| 	return rules_from_dir(rules_buttonlike, dir) | 	if node.param2 == 2 then | ||||||
|  | 		rules=mesecon.rotate_rules_left(rules) | ||||||
|  | 	elseif node.param2 == 3 then | ||||||
|  | 		rules=mesecon.rotate_rules_right(mesecon.rotate_rules_right(rules)) | ||||||
|  | 	elseif node.param2 == 0 then | ||||||
|  | 		rules=mesecon.rotate_rules_right(rules) | ||||||
|  | 	end | ||||||
|  | 	return rules | ||||||
| end | end | ||||||
|  |  | ||||||
| mesecon.state.on = "on" | mesecon.state.on = "on" | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| -- Dig and place services | -- Dig and place services | ||||||
|  |  | ||||||
| mesecon.on_placenode = function(pos, node) | mesecon.on_placenode = function (pos, node) | ||||||
| 	mesecon.execute_autoconnect_hooks_now(pos, node) | 	mesecon.update_autoconnect(pos, node) | ||||||
|  |  | ||||||
| 	-- Receptors: Send on signal when active | 	-- Receptors: Send on signal when active | ||||||
| 	if mesecon.is_receptor_on(node.name) then | 	if mesecon.is_receptor_on(node.name) then | ||||||
| @@ -16,26 +16,23 @@ mesecon.on_placenode = function(pos, node) | |||||||
| 			-- also call receptor_on if itself is powered already, so that neighboring | 			-- also call receptor_on if itself is powered already, so that neighboring | ||||||
| 			-- conductors will be activated (when pushing an on-conductor with a piston) | 			-- conductors will be activated (when pushing an on-conductor with a piston) | ||||||
| 			for _, s in ipairs(sources) do | 			for _, s in ipairs(sources) do | ||||||
| 				local rule = vector.subtract(pos, s) | 				local rule = {x = pos.x - s.x, y = pos.y - s.y, z = pos.z - s.z} | ||||||
| 				mesecon.turnon(pos, rule) | 				mesecon.turnon(pos, rule) | ||||||
| 			end | 			end | ||||||
| 			--mesecon.receptor_on (pos, mesecon.conductor_get_rules(node)) | 			--mesecon.receptor_on (pos, mesecon.conductor_get_rules(node)) | ||||||
| 		elseif mesecon.is_conductor_on(node) then | 		elseif mesecon.is_conductor_on(node) then | ||||||
| 			node.name = mesecon.get_conductor_off(node) | 			minetest.swap_node(pos, {name = mesecon.get_conductor_off(node)}) | ||||||
| 			minetest.swap_node(pos, node) |  | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	-- Effectors: Send changesignal and activate or deactivate | 	-- Effectors: Send changesignal and activate or deactivate | ||||||
| 	if mesecon.is_effector(node.name) then | 	if mesecon.is_effector(node.name) then | ||||||
| 		local powered_rules = {} | 		local powered_rules = {} | ||||||
| 		local unpowered_rules = {} |  | ||||||
|  |  | ||||||
| 		-- for each input rule, check if powered | 		-- for each input rule, check if powered | ||||||
| 		for _, r in ipairs(mesecon.effector_get_rules(node)) do | 		for _, r in ipairs(mesecon.effector_get_rules(node)) do | ||||||
| 			local powered = mesecon.is_powered(pos, r) | 			local powered = mesecon.is_powered(pos, r) | ||||||
| 			if powered then table.insert(powered_rules, r) | 			if powered then table.insert(powered_rules, r) end | ||||||
| 			else table.insert(unpowered_rules, r) end |  | ||||||
|  |  | ||||||
| 			local state = powered and mesecon.state.on or mesecon.state.off | 			local state = powered and mesecon.state.on or mesecon.state.off | ||||||
| 			mesecon.changesignal(pos, node, r, state, 1) | 			mesecon.changesignal(pos, node, r, state, 1) | ||||||
| @@ -45,92 +42,53 @@ mesecon.on_placenode = function(pos, node) | |||||||
| 			for _, r in ipairs(powered_rules) do | 			for _, r in ipairs(powered_rules) do | ||||||
| 				mesecon.activate(pos, node, r, 1) | 				mesecon.activate(pos, node, r, 1) | ||||||
| 			end | 			end | ||||||
| 		else |  | ||||||
| 			for _, r in ipairs(unpowered_rules) do |  | ||||||
| 				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.queue:add_action(pos, "update_autoconnect", {node}) | ||||||
| 	mesecon.execute_autoconnect_hooks_queue(pos, node) |  | ||||||
| end | end | ||||||
|  |  | ||||||
| function mesecon.on_blastnode(pos, intensity) | mesecon.queue:add_function("update_autoconnect", mesecon.update_autoconnect) | ||||||
| 	local node = minetest.get_node(pos) |  | ||||||
| 	minetest.remove_node(pos) |  | ||||||
| 	mesecon.on_dignode(pos, node) |  | ||||||
| 	return minetest.get_node_drops(node.name, "") |  | ||||||
| end |  | ||||||
|  |  | ||||||
| minetest.register_on_placenode(mesecon.on_placenode) | minetest.register_on_placenode(mesecon.on_placenode) | ||||||
| minetest.register_on_dignode(mesecon.on_dignode) | minetest.register_on_dignode(mesecon.on_dignode) | ||||||
|  |  | ||||||
| -- Overheating service for fast circuits | -- Overheating service for fast circuits | ||||||
| local OVERHEAT_MAX = mesecon.setting("overheat_max", 20) |  | ||||||
| local COOLDOWN_TIME = mesecon.setting("cooldown_time", 2.0) |  | ||||||
| local COOLDOWN_STEP = mesecon.setting("cooldown_granularity", 0.5) |  | ||||||
| local COOLDOWN_MULTIPLIER = OVERHEAT_MAX / COOLDOWN_TIME |  | ||||||
| local cooldown_timer = 0.0 |  | ||||||
| local object_heat = {} |  | ||||||
|  |  | ||||||
| -- returns true if heat is too high | -- returns true if heat is too high | ||||||
| function mesecon.do_overheat(pos) | mesecon.do_overheat = function(pos) | ||||||
| 	local id = minetest.hash_node_position(pos) | 	local meta = minetest.get_meta(pos) | ||||||
| 	local heat = (object_heat[id] or 0) + 1 | 	local heat = meta:get_int("heat") or 0 | ||||||
| 	object_heat[id] = heat |  | ||||||
| 	if heat >= OVERHEAT_MAX then | 	heat = heat + 1 | ||||||
| 		minetest.log("action", "Node overheats at " .. minetest.pos_to_string(pos)) | 	meta:set_int("heat", heat) | ||||||
| 		object_heat[id] = nil |  | ||||||
|  | 	if heat < mesecon.setting("overheat_max", 20) then | ||||||
|  | 		mesecon.queue:add_action(pos, "cooldown", {}, 1, nil, 0) | ||||||
|  | 	else | ||||||
| 		return true | 		return true | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	return false | 	return false | ||||||
| end | end | ||||||
|  |  | ||||||
| function mesecon.do_cooldown(pos) |  | ||||||
| 	local id = minetest.hash_node_position(pos) |  | ||||||
| 	object_heat[id] = nil |  | ||||||
| end |  | ||||||
|  |  | ||||||
| function mesecon.get_heat(pos) | mesecon.queue:add_function("cooldown", function (pos) | ||||||
| 	local id = minetest.hash_node_position(pos) | 	if minetest.get_item_group(minetest.get_node(pos).name, "overheat") == 0 then | ||||||
| 	return object_heat[id] or 0 | 		return -- node has been moved, this one does not use overheating - ignore | ||||||
| end | 	end | ||||||
|  |  | ||||||
| function mesecon.move_hot_nodes(moved_nodes) | 	local meta = minetest.get_meta(pos) | ||||||
| 	local new_heat = {} | 	local heat = meta:get_int("heat") | ||||||
| 	for _, n in ipairs(moved_nodes) do |  | ||||||
| 		local old_id = minetest.hash_node_position(n.oldpos) |  | ||||||
| 		local new_id = minetest.hash_node_position(n.pos) |  | ||||||
| 		new_heat[new_id] = object_heat[old_id] |  | ||||||
| 		object_heat[old_id] = nil |  | ||||||
| 	end |  | ||||||
| 	for id, heat in pairs(new_heat) do |  | ||||||
| 		object_heat[id] = heat |  | ||||||
| 	end |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function global_cooldown(dtime) | 	if (heat > 0) then | ||||||
| 	cooldown_timer = cooldown_timer + dtime | 		meta:set_int("heat", heat - 1) | ||||||
| 	if cooldown_timer < COOLDOWN_STEP then |  | ||||||
| 		return -- don't overload the CPU |  | ||||||
| 	end | 	end | ||||||
| 	local cooldown = COOLDOWN_MULTIPLIER * cooldown_timer | end) | ||||||
| 	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,15 +1,10 @@ | |||||||
| -- SETTINGS | -- SETTINGS | ||||||
| function mesecon.setting(setting, default) | function mesecon.setting(setting, default) | ||||||
| 	if type(default) == "boolean" then | 	if type(default) == "bool" then | ||||||
| 		local read = minetest.settings:get_bool("mesecon."..setting) | 		return minetest.setting_getbool("mesecon."..setting) or default | ||||||
| 		if read == nil then | 	elseif type(default) == "string" then | ||||||
| 			return default | 		return minetest.setting_get("mesecon."..setting) or default | ||||||
| 		else | 	elseif type(default) == "number" then | ||||||
| 			return read | 		return tonumber(minetest.setting_get("mesecon."..setting) or default) | ||||||
| 		end | 	end | ||||||
| 	elseif type(default) == "string" then | end | ||||||
| 		return minetest.settings:get("mesecon."..setting) or default |  | ||||||
| 	elseif type(default) == "number" then |  | ||||||
| 		return tonumber(minetest.settings:get("mesecon."..setting) or default) |  | ||||||
| 	end |  | ||||||
| end |  | ||||||
|   | |||||||
| Before Width: | Height: | Size: 191 B | 
							
								
								
									
										
											BIN
										
									
								
								mesecons/textures/jeija_fiber.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 592 B | 
							
								
								
									
										
											BIN
										
									
								
								mesecons/textures/jeija_glue.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 487 B | 
							
								
								
									
										
											BIN
										
									
								
								mesecons/textures/jeija_mesecon_switch_off.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 598 B | 
							
								
								
									
										
											BIN
										
									
								
								mesecons/textures/jeija_mesecon_switch_on.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 692 B | 
							
								
								
									
										
											BIN
										
									
								
								mesecons/textures/jeija_mesecon_switch_side.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 553 B | 
| Before Width: | Height: | Size: 844 B | 
| Before Width: | Height: | Size: 838 B | 
| Before Width: | Height: | Size: 851 B | 
| Before Width: | Height: | Size: 846 B | 
| Before Width: | Height: | Size: 222 B | 
| Before Width: | Height: | Size: 504 B | 
							
								
								
									
										
											BIN
										
									
								
								mesecons/textures/jeija_silicon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 867 B | 
| Before Width: | Height: | Size: 144 B After Width: | Height: | Size: 204 B | 
| Before Width: | Height: | Size: 377 B After Width: | Height: | Size: 465 B | 
| Before Width: | Height: | Size: 362 B After Width: | Height: | Size: 464 B | 
| @@ -2,60 +2,10 @@ function mesecon.move_node(pos, newpos) | |||||||
| 	local node = minetest.get_node(pos) | 	local node = minetest.get_node(pos) | ||||||
| 	local meta = minetest.get_meta(pos):to_table() | 	local meta = minetest.get_meta(pos):to_table() | ||||||
| 	minetest.remove_node(pos) | 	minetest.remove_node(pos) | ||||||
| 	minetest.set_node(newpos, node) | 	minetest.add_node(newpos, node) | ||||||
| 	minetest.get_meta(pos):from_table(meta) | 	minetest.get_meta(pos):from_table(meta) | ||||||
| end | end | ||||||
|  |  | ||||||
| -- Rules rotation Functions: |  | ||||||
| function mesecon.rotate_rules_right(rules) |  | ||||||
| 	local nr = {} |  | ||||||
| 	for i, rule in ipairs(rules) do |  | ||||||
| 		table.insert(nr, { |  | ||||||
| 			x = -rule.z, |  | ||||||
| 			y =  rule.y, |  | ||||||
| 			z =  rule.x, |  | ||||||
| 			name = rule.name}) |  | ||||||
| 	end |  | ||||||
| 	return nr |  | ||||||
| end |  | ||||||
|  |  | ||||||
| function mesecon.rotate_rules_left(rules) |  | ||||||
| 	local nr = {} |  | ||||||
| 	for i, rule in ipairs(rules) do |  | ||||||
| 		table.insert(nr, { |  | ||||||
| 			x =  rule.z, |  | ||||||
| 			y =  rule.y, |  | ||||||
| 			z = -rule.x, |  | ||||||
| 			name = rule.name}) |  | ||||||
| 	end |  | ||||||
| 	return nr |  | ||||||
| end |  | ||||||
|  |  | ||||||
| function mesecon.rotate_rules_down(rules) |  | ||||||
| 	local nr = {} |  | ||||||
| 	for i, rule in ipairs(rules) do |  | ||||||
| 		table.insert(nr, { |  | ||||||
| 			x = -rule.y, |  | ||||||
| 			y =  rule.x, |  | ||||||
| 			z =  rule.z, |  | ||||||
| 			name = rule.name}) |  | ||||||
| 	end |  | ||||||
| 	return nr |  | ||||||
| end |  | ||||||
|  |  | ||||||
| function mesecon.rotate_rules_up(rules) |  | ||||||
| 	local nr = {} |  | ||||||
| 	for i, rule in ipairs(rules) do |  | ||||||
| 		table.insert(nr, { |  | ||||||
| 			x =  rule.y, |  | ||||||
| 			y = -rule.x, |  | ||||||
| 			z =  rule.z, |  | ||||||
| 			name = rule.name}) |  | ||||||
| 	end |  | ||||||
| 	return nr |  | ||||||
| end |  | ||||||
| -- |  | ||||||
|  |  | ||||||
| function mesecon.flattenrules(allrules) | function mesecon.flattenrules(allrules) | ||||||
| --[[ | --[[ | ||||||
| 	{ | 	{ | ||||||
| @@ -100,7 +50,7 @@ function mesecon.rule2bit(findrule, allrules) | |||||||
| 	end | 	end | ||||||
| 	for m,metarule in ipairs( allrules) do | 	for m,metarule in ipairs( allrules) do | ||||||
| 	for _,    rule in ipairs(metarule ) do | 	for _,    rule in ipairs(metarule ) do | ||||||
| 		if vector.equals(findrule, rule) then | 		if mesecon.cmpPos(findrule, rule) then | ||||||
| 			return m | 			return m | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
| @@ -119,7 +69,7 @@ function mesecon.rule2metaindex(findrule, allrules) | |||||||
|  |  | ||||||
| 	for m, metarule in ipairs( allrules) do | 	for m, metarule in ipairs( allrules) do | ||||||
| 	for _,     rule in ipairs(metarule ) do | 	for _,     rule in ipairs(metarule ) do | ||||||
| 		if vector.equals(findrule, rule) then | 		if mesecon.cmpPos(findrule, rule) then | ||||||
| 			return m | 			return m | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
| @@ -179,43 +129,49 @@ function mesecon.set_bit(binary,bit,value) | |||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
| 	return binary | 	return binary | ||||||
|  | 	 | ||||||
| end | end | ||||||
|  |  | ||||||
| function mesecon.invertRule(r) | function mesecon.invertRule(r) | ||||||
| 	return vector.multiply(r, -1) | 	return {x = -r.x, y = -r.y, z = -r.z} | ||||||
| end | end | ||||||
|  |  | ||||||
| function mesecon.tablecopy(obj) -- deep copy | function mesecon.addPosRule(p, r) | ||||||
| 	if type(obj) == "table" then | 	return {x = p.x + r.x, y = p.y + r.y, z = p.z + r.z} | ||||||
| 		return table.copy(obj) | end | ||||||
|  |  | ||||||
|  | function mesecon.cmpPos(p1, p2) | ||||||
|  | 	return (p1.x == p2.x and p1.y == p2.y and p1.z == p2.z) | ||||||
|  | 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 | ||||||
|  |  | ||||||
| -- Returns whether two values are equal. |  | ||||||
| -- In tables, keys are compared for identity but values are compared recursively. |  | ||||||
| -- There is no protection from infinite recursion. |  | ||||||
| function mesecon.cmpAny(t1, t2) | function mesecon.cmpAny(t1, t2) | ||||||
| 	if type(t1) ~= type(t2) then return false end | 	if type(t1) ~= type(t2) then return false end | ||||||
| 	if type(t1) ~= "table" then return t1 == t2 end | 	if type(t1) ~= "table" and type(t2) ~= "table" then return t1 == t2 end | ||||||
|  |  | ||||||
| 	-- Check that for each key of `t1` both tables have the same value |  | ||||||
| 	for i, e in pairs(t1) do | 	for i, e in pairs(t1) do | ||||||
| 		if not mesecon.cmpAny(e, t2[i]) then return false end | 		if not mesecon.cmpAny(e, t2[i]) then return false end | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	-- Check that all keys of `t2` are also keys of `t1` so were checked in the previous loop |  | ||||||
| 	for i, _ in pairs(t2) do |  | ||||||
| 		if t1[i] == nil then return false end |  | ||||||
| 	end |  | ||||||
|  |  | ||||||
| 	return true | 	return true | ||||||
| end | end | ||||||
|  |  | ||||||
| -- Deprecated. Use `merge_tables` or `merge_rule_sets` as appropriate. | -- does not overwrite values; number keys (ipairs) are appended, not overwritten | ||||||
| function mesecon.mergetable(source, dest) | function mesecon.mergetable(source, dest) | ||||||
| 	minetest.log("warning", debug.traceback("Deprecated call to mesecon.mergetable")) |  | ||||||
| 	local rval = mesecon.tablecopy(dest) | 	local rval = mesecon.tablecopy(dest) | ||||||
|  |  | ||||||
| 	for k, v in pairs(source) do | 	for k, v in pairs(source) do | ||||||
| @@ -228,41 +184,14 @@ function mesecon.mergetable(source, dest) | |||||||
| 	return rval | 	return rval | ||||||
| end | end | ||||||
|  |  | ||||||
| -- Merges several rule sets in one. Order may not be preserved. Nil arguments |  | ||||||
| -- are ignored. |  | ||||||
| -- The rule sets must be of the same kind (either all single-level or all two-level). |  | ||||||
| -- The function may be changed to normalize the resulting set in some way. |  | ||||||
| function mesecon.merge_rule_sets(...) |  | ||||||
| 	local rval = {} |  | ||||||
| 	for _, t in pairs({...}) do -- ignores nils automatically |  | ||||||
| 		table.insert_all(rval, mesecon.tablecopy(t)) |  | ||||||
| 	end |  | ||||||
| 	return rval |  | ||||||
| end |  | ||||||
|  |  | ||||||
| -- Merges two tables, with entries from `replacements` taking precedence over |  | ||||||
| -- those from `base`. Returns the new table. |  | ||||||
| -- Values are deep-copied from either table, keys are referenced. |  | ||||||
| -- Numerical indices aren’t handled specially. |  | ||||||
| function mesecon.merge_tables(base, replacements) |  | ||||||
| 	local ret = mesecon.tablecopy(replacements) -- these are never overriden so have to be copied in any case |  | ||||||
| 	for k, v in pairs(base) do |  | ||||||
| 		if ret[k] == nil then -- it could be `false` |  | ||||||
| 			ret[k] = mesecon.tablecopy(v) |  | ||||||
| 		end |  | ||||||
| 	end |  | ||||||
| 	return ret |  | ||||||
| end |  | ||||||
|  |  | ||||||
| function mesecon.register_node(name, spec_common, spec_off, spec_on) | function mesecon.register_node(name, spec_common, spec_off, spec_on) | ||||||
| 	spec_common.drop = spec_common.drop or name .. "_off" | 	spec_common.drop = spec_common.drop or name .. "_off" | ||||||
| 	spec_common.on_blast = spec_common.on_blast or mesecon.on_blastnode |  | ||||||
| 	spec_common.__mesecon_basename = name | 	spec_common.__mesecon_basename = name | ||||||
| 	spec_on.__mesecon_state = "on" | 	spec_on.__mesecon_state = "on" | ||||||
| 	spec_off.__mesecon_state = "off" | 	spec_off.__mesecon_state = "off" | ||||||
|  |  | ||||||
| 	spec_on = mesecon.merge_tables(spec_common, spec_on); | 	spec_on = mesecon.mergetable(spec_common, spec_on); | ||||||
| 	spec_off = mesecon.merge_tables(spec_common, spec_off); | 	spec_off = mesecon.mergetable(spec_common, spec_off); | ||||||
|  |  | ||||||
| 	minetest.register_node(name .. "_on", spec_on) | 	minetest.register_node(name .. "_on", spec_on) | ||||||
| 	minetest.register_node(name .. "_off", spec_off) | 	minetest.register_node(name .. "_off", spec_off) | ||||||
| @@ -274,196 +203,9 @@ function mesecon.flipstate(pos, node) | |||||||
| 	local newstate | 	local newstate | ||||||
| 	if (nodedef.__mesecon_state == "on") then newstate = "off" end | 	if (nodedef.__mesecon_state == "on") then newstate = "off" end | ||||||
| 	if (nodedef.__mesecon_state == "off") then newstate = "on" end | 	if (nodedef.__mesecon_state == "off") then newstate = "on" end | ||||||
|  | 		 | ||||||
| 	minetest.swap_node(pos, {name = nodedef.__mesecon_basename .. "_" .. newstate, | 	minetest.swap_node(pos, {name = nodedef.__mesecon_basename .. "_" .. newstate, | ||||||
| 		param2 = node.param2}) | 		param2 = node.param2}) | ||||||
|  |  | ||||||
| 	return newstate | 	return newstate | ||||||
| end | 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 |  | ||||||
|   | |||||||
| @@ -22,7 +22,7 @@ local wire_getconnect = function (from_pos, self_pos) | |||||||
| 		end | 		end | ||||||
| 
 | 
 | ||||||
| 		for _, r in ipairs(mesecon.flattenrules(rules)) do | 		for _, r in ipairs(mesecon.flattenrules(rules)) do | ||||||
| 			if (vector.equals(vector.add(self_pos, r), from_pos)) then | 			if (mesecon.cmpPos(mesecon.addPosRule(self_pos, r), from_pos)) then | ||||||
| 				return true | 				return true | ||||||
| 			end | 			end | ||||||
| 		end | 		end | ||||||
| @@ -35,7 +35,7 @@ local wire_updateconnect = function (pos) | |||||||
| 	local connections = {} | 	local connections = {} | ||||||
| 
 | 
 | ||||||
| 	for _, r in ipairs(mesecon.rules.default) do | 	for _, r in ipairs(mesecon.rules.default) do | ||||||
| 		if wire_getconnect(pos, vector.add(pos, r)) then | 		if wire_getconnect(pos, mesecon.addPosRule(pos, r)) then | ||||||
| 			table.insert(connections, r) | 			table.insert(connections, r) | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
| @@ -83,7 +83,7 @@ local update_on_place_dig = function (pos, node) | |||||||
| 	if (not rules) then return end | 	if (not rules) then return end | ||||||
| 
 | 
 | ||||||
| 	for _, r in ipairs(mesecon.flattenrules(rules)) do | 	for _, r in ipairs(mesecon.flattenrules(rules)) do | ||||||
| 		local np = vector.add(pos, r) | 		local np = mesecon.addPosRule(pos, r) | ||||||
| 		if minetest.registered_nodes[minetest.get_node(np).name] | 		if minetest.registered_nodes[minetest.get_node(np).name] | ||||||
| 		and minetest.registered_nodes[minetest.get_node(np).name].mesecon_wire then | 		and minetest.registered_nodes[minetest.get_node(np).name].mesecon_wire then | ||||||
| 			wire_updateconnect(np) | 			wire_updateconnect(np) | ||||||
| @@ -91,7 +91,10 @@ local update_on_place_dig = function (pos, node) | |||||||
| 	end | 	end | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
| mesecon.register_autoconnect_hook("wire", update_on_place_dig) | function mesecon.update_autoconnect(pos, node) | ||||||
|  | 	if (not node) then node = minetest.get_node(pos) end | ||||||
|  | 	update_on_place_dig(pos, node) | ||||||
|  | end | ||||||
| 
 | 
 | ||||||
| -- ############################ | -- ############################ | ||||||
| -- ## Wire node registration ## | -- ## Wire node registration ## | ||||||
| @@ -132,7 +135,7 @@ nid_inc = function (nid) | |||||||
| 	end | 	end | ||||||
| 
 | 
 | ||||||
| 	-- BUT: Skip impossible nodeids: | 	-- BUT: Skip impossible nodeids: | ||||||
| 	if ((nid[0] == 0 and nid[4] == 1) or (nid[1] == 0 and nid[5] == 1) | 	if ((nid[0] == 0 and nid[4] == 1) or (nid[1] == 0 and nid[5] == 1)  | ||||||
| 	or (nid[2] == 0 and nid[6] == 1) or (nid[3] == 0 and nid[7] == 1)) then | 	or (nid[2] == 0 and nid[6] == 1) or (nid[3] == 0 and nid[7] == 1)) then | ||||||
| 		return nid_inc(nid) | 		return nid_inc(nid) | ||||||
| 	end | 	end | ||||||
| @@ -140,7 +143,7 @@ nid_inc = function (nid) | |||||||
| 	return i <= 8 | 	return i <= 8 | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
| local function register_wires() | register_wires = function() | ||||||
| 	local nid = {} | 	local nid = {} | ||||||
| 	while true do | 	while true do | ||||||
| 		-- Create group specifiction and nodeid string (see note above for details) | 		-- Create group specifiction and nodeid string (see note above for details) | ||||||
| @@ -195,29 +198,25 @@ local function register_wires() | |||||||
| 		}} | 		}} | ||||||
| 
 | 
 | ||||||
| 		local groups_on = {dig_immediate = 3, mesecon_conductor_craftable = 1, | 		local groups_on = {dig_immediate = 3, mesecon_conductor_craftable = 1, | ||||||
| 			not_in_creative_inventory = 1, not_in_craft_guide = 1} | 			not_in_creative_inventory = 1} | ||||||
| 		local groups_off = {dig_immediate = 3, mesecon_conductor_craftable = 1} | 		local groups_off = {dig_immediate = 3, mesecon_conductor_craftable = 1} | ||||||
| 		if nodeid ~= "00000000" then | 		if nodeid ~= "00000000" then | ||||||
| 			groups_off["not_in_creative_inventory"] = 1 | 			groups_off["not_in_creative_inventory"] = 1 | ||||||
| 			groups_off["not_in_craft_guide"] = 1 |  | ||||||
| 		end | 		end | ||||||
| 
 | 
 | ||||||
| 		mesecon.register_node(":mesecons:wire_"..nodeid, { | 		mesecon.register_node("mesecons:wire_"..nodeid, { | ||||||
| 			description = "Mesecon", | 			description = "Mesecon", | ||||||
| 			drawtype = "nodebox", | 			drawtype = "nodebox", | ||||||
| 			inventory_image = "mesecons_wire_inv.png", | 			inventory_image = "mesecons_wire_inv.png", | ||||||
| 			wield_image = "mesecons_wire_inv.png", | 			wield_image = "mesecons_wire_inv.png", | ||||||
| 			paramtype = "light", | 			paramtype = "light", | ||||||
| 			paramtype2 = "facedir", | 			paramtype2 = "facedir", | ||||||
| 			is_ground_content = false, |  | ||||||
| 			sunlight_propagates = true, | 			sunlight_propagates = true, | ||||||
| 			selection_box = selectionbox, | 			selection_box = selectionbox, | ||||||
| 			node_box = nodebox, | 			node_box = nodebox, | ||||||
| 			walkable = false, | 			walkable = false, | ||||||
| 			drop = "mesecons:wire_00000000_off", | 			drop = "mesecons:wire_00000000_off", | ||||||
| 			mesecon_wire = true, | 			mesecon_wire = true | ||||||
| 			sounds = default.node_sound_defaults(), |  | ||||||
| 			on_rotate = false, |  | ||||||
| 		}, {tiles = tiles_off, mesecons = meseconspec_off, groups = groups_off}, | 		}, {tiles = tiles_off, mesecons = meseconspec_off, groups = groups_off}, | ||||||
| 		{tiles = tiles_on, mesecons = meseconspec_on, groups = groups_on}) | 		{tiles = tiles_on, mesecons = meseconspec_on, groups = groups_on}) | ||||||
| 
 | 
 | ||||||
							
								
								
									
										1
									
								
								mesecons_alias/depends.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | |||||||
|  | mesecons | ||||||
| @@ -1,2 +0,0 @@ | |||||||
| name = mesecons_alias |  | ||||||
| depends = mesecons |  | ||||||
							
								
								
									
										1
									
								
								mesecons_blinkyplant/depends.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | |||||||
|  | mesecons | ||||||
| @@ -1,2 +0,0 @@ | |||||||
| The blinky plants toggles between on and off state every three seconds. Can be used to make clocks. Also works after having restarted the game. |  | ||||||
| It stops blinking in an inactive block, then starts again when the block becomes active. |  | ||||||
| Before Width: | Height: | Size: 54 KiB | 
| Before Width: | Height: | Size: 1.7 KiB | 
| @@ -24,7 +24,6 @@ mesecon.register_node("mesecons_blinkyplant:blinky_plant", { | |||||||
| 	drawtype = "plantlike", | 	drawtype = "plantlike", | ||||||
| 	inventory_image = "jeija_blinky_plant_off.png", | 	inventory_image = "jeija_blinky_plant_off.png", | ||||||
| 	paramtype = "light", | 	paramtype = "light", | ||||||
| 	is_ground_content = false, |  | ||||||
| 	walkable = false, | 	walkable = false, | ||||||
| 	sounds = default.node_sound_leaves_defaults(), | 	sounds = default.node_sound_leaves_defaults(), | ||||||
| 	selection_box = { | 	selection_box = { | ||||||
| @@ -32,13 +31,7 @@ mesecon.register_node("mesecons_blinkyplant:blinky_plant", { | |||||||
| 		fixed = {-0.3, -0.5, -0.3, 0.3, -0.5+0.7, 0.3}, | 		fixed = {-0.3, -0.5, -0.3, 0.3, -0.5+0.7, 0.3}, | ||||||
| 	}, | 	}, | ||||||
| 	on_timer = on_timer, | 	on_timer = on_timer, | ||||||
| 	on_rightclick = function(pos, node, clicker) | 	on_rightclick = toggle_timer, | ||||||
| 		if minetest.is_protected(pos, clicker and clicker:get_player_name() or "") then |  | ||||||
| 			return |  | ||||||
| 		end |  | ||||||
|  |  | ||||||
| 		toggle_timer(pos) |  | ||||||
| 	end, |  | ||||||
| 	on_construct = toggle_timer | 	on_construct = toggle_timer | ||||||
| },{ | },{ | ||||||
| 	tiles = {"jeija_blinky_plant_off.png"}, | 	tiles = {"jeija_blinky_plant_off.png"}, | ||||||
|   | |||||||
| @@ -1,2 +0,0 @@ | |||||||
| name = mesecons_blinkyplant |  | ||||||
| depends = mesecons |  | ||||||
| Before Width: | Height: | Size: 367 B After Width: | Height: | Size: 454 B | 
| Before Width: | Height: | Size: 394 B After Width: | Height: | Size: 463 B | 
							
								
								
									
										2
									
								
								mesecons_button/depends.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,2 @@ | |||||||
|  | mesecons | ||||||
|  | mesecons_receiver | ||||||
| @@ -1 +0,0 @@ | |||||||
| This receptor can be attached to walls. It turns on for 1 second if it's punched. |  | ||||||
| Before Width: | Height: | Size: 68 KiB | 
| Before Width: | Height: | Size: 4.3 KiB | 
| @@ -4,41 +4,35 @@ | |||||||
|  |  | ||||||
| mesecon.button_turnoff = function (pos) | mesecon.button_turnoff = function (pos) | ||||||
| 	local node = minetest.get_node(pos) | 	local node = minetest.get_node(pos) | ||||||
| 	if node.name ~= "mesecons_button:button_on" then -- has been dug | 	if node.name=="mesecons_button:button_on" then --has not been dug | ||||||
| 		return | 		minetest.swap_node(pos, {name = "mesecons_button:button_off", param2=node.param2}) | ||||||
|  | 		minetest.sound_play("mesecons_button_pop", {pos=pos}) | ||||||
|  | 		local rules = mesecon.rules.buttonlike_get(node) | ||||||
|  | 		mesecon.receptor_off(pos, rules) | ||||||
| 	end | 	end | ||||||
| 	minetest.swap_node(pos, {name = "mesecons_button:button_off", param2 = node.param2}) |  | ||||||
| 	minetest.sound_play("mesecons_button_pop", { pos = pos }, true) |  | ||||||
| 	local rules = mesecon.rules.buttonlike_get(node) |  | ||||||
| 	mesecon.receptor_off(pos, rules) |  | ||||||
| end | end | ||||||
|  |  | ||||||
| local use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or nil |  | ||||||
|  |  | ||||||
| minetest.register_node("mesecons_button:button_off", { | minetest.register_node("mesecons_button:button_off", { | ||||||
| 	drawtype = "nodebox", | 	drawtype = "nodebox", | ||||||
| 	tiles = { | 	tiles = { | ||||||
| 		"jeija_wall_button_sides.png", | 	"jeija_wall_button_sides.png",	 | ||||||
| 		"jeija_wall_button_sides.png", | 	"jeija_wall_button_sides.png", | ||||||
| 		"jeija_wall_button_sides.png", | 	"jeija_wall_button_sides.png", | ||||||
| 		"jeija_wall_button_sides.png", | 	"jeija_wall_button_sides.png", | ||||||
| 		"jeija_wall_button_sides.png", | 	"jeija_wall_button_sides.png", | ||||||
| 		"jeija_wall_button_off.png" | 	"jeija_wall_button_off.png" | ||||||
| 	}, | 	}, | ||||||
| 	use_texture_alpha = use_texture_alpha, |  | ||||||
| 	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", | ||||||
| 		fixed = { -6/16, -6/16, 5/16, 6/16, 6/16, 8/16 } | 		fixed = { -6/16, -6/16, 5/16, 6/16, 6/16, 8/16 } | ||||||
| 	}, | 	}, | ||||||
| 	node_box = { | 	node_box = { | ||||||
| 		type = "fixed", | 		type = "fixed",	 | ||||||
| 		fixed = { | 		fixed = { | ||||||
| 		{ -6/16, -6/16, 6/16, 6/16, 6/16, 8/16 },	-- the thin plate behind the button | 		{ -6/16, -6/16, 6/16, 6/16, 6/16, 8/16 },	-- the thin plate behind the button | ||||||
| 		{ -4/16, -2/16, 4/16, 4/16, 2/16, 6/16 }	-- the button itself | 		{ -4/16, -2/16, 4/16, 4/16, 2/16, 6/16 }	-- the button itself | ||||||
| @@ -46,18 +40,17 @@ minetest.register_node("mesecons_button:button_off", { | |||||||
| 	}, | 	}, | ||||||
| 	groups = {dig_immediate=2, mesecon_needs_receiver = 1}, | 	groups = {dig_immediate=2, mesecon_needs_receiver = 1}, | ||||||
| 	description = "Button", | 	description = "Button", | ||||||
| 	on_rightclick = function (pos, node) | 	on_punch = function (pos, node) | ||||||
| 		minetest.swap_node(pos, {name = "mesecons_button:button_on", param2=node.param2}) | 		minetest.swap_node(pos, {name = "mesecons_button:button_on", param2=node.param2}) | ||||||
| 		mesecon.receptor_on(pos, mesecon.rules.buttonlike_get(node)) | 		mesecon.receptor_on(pos, mesecon.rules.buttonlike_get(node)) | ||||||
| 		minetest.sound_play("mesecons_button_push", { pos = pos }, true) | 		minetest.sound_play("mesecons_button_push", {pos=pos}) | ||||||
| 		minetest.get_node_timer(pos):start(1) | 		minetest.after(1, mesecon.button_turnoff, pos) | ||||||
| 	end, | 	end, | ||||||
| 	sounds = default.node_sound_stone_defaults(), | 	sounds = default.node_sound_stone_defaults(), | ||||||
| 	mesecons = {receptor = { | 	mesecons = {receptor = { | ||||||
| 		state = mesecon.state.off, | 		state = mesecon.state.off, | ||||||
| 		rules = mesecon.rules.buttonlike_get | 		rules = mesecon.rules.buttonlike_get | ||||||
| 	}}, | 	}} | ||||||
| 	on_blast = mesecon.on_blastnode, |  | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_node("mesecons_button:button_on", { | minetest.register_node("mesecons_button:button_on", { | ||||||
| @@ -69,15 +62,12 @@ minetest.register_node("mesecons_button:button_on", { | |||||||
| 		"jeija_wall_button_sides.png", | 		"jeija_wall_button_sides.png", | ||||||
| 		"jeija_wall_button_sides.png", | 		"jeija_wall_button_sides.png", | ||||||
| 		"jeija_wall_button_on.png" | 		"jeija_wall_button_on.png" | ||||||
| 	}, | 		}, | ||||||
| 	use_texture_alpha = use_texture_alpha, |  | ||||||
| 	paramtype = "light", | 	paramtype = "light", | ||||||
| 	paramtype2 = "facedir", | 	paramtype2 = "facedir", | ||||||
| 	is_ground_content = false, |  | ||||||
| 	legacy_wallmounted = true, | 	legacy_wallmounted = true, | ||||||
| 	walkable = false, | 	walkable = false, | ||||||
| 	on_rotate = false, | 	light_source = LIGHT_MAX-7, | ||||||
| 	light_source = minetest.LIGHT_MAX-7, |  | ||||||
| 	sunlight_propagates = true, | 	sunlight_propagates = true, | ||||||
| 	selection_box = { | 	selection_box = { | ||||||
| 		type = "fixed", | 		type = "fixed", | ||||||
| @@ -97,9 +87,7 @@ minetest.register_node("mesecons_button:button_on", { | |||||||
| 	mesecons = {receptor = { | 	mesecons = {receptor = { | ||||||
| 		state = mesecon.state.on, | 		state = mesecon.state.on, | ||||||
| 		rules = mesecon.rules.buttonlike_get | 		rules = mesecon.rules.buttonlike_get | ||||||
| 	}}, | 	}} | ||||||
| 	on_timer = mesecon.button_turnoff, |  | ||||||
| 	on_blast = mesecon.on_blastnode, |  | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_craft({ | minetest.register_craft({ | ||||||
|   | |||||||
| @@ -1,2 +0,0 @@ | |||||||
| name = mesecons_button |  | ||||||
| depends = mesecons, mesecons_receiver |  | ||||||
| Before Width: | Height: | Size: 371 B After Width: | Height: | Size: 411 B | 
| Before Width: | Height: | Size: 409 B After Width: | Height: | Size: 449 B | 
| Before Width: | Height: | Size: 220 B After Width: | Height: | Size: 434 B | 
							
								
								
									
										1
									
								
								mesecons_commandblock/depends.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | |||||||
|  | mesecons | ||||||
| @@ -1,2 +0,0 @@ | |||||||
| There is no crafting recipe as this should only be available for server admins. Quite similar to the Minecraft counterpart. Executes server commands. |  | ||||||
| It works in inactive blocks. |  | ||||||
| Before Width: | Height: | Size: 33 KiB | 
| @@ -1,214 +1,195 @@ | |||||||
| minetest.register_chatcommand("say", { | minetest.register_chatcommand("say", { | ||||||
| 	params = "<text>", | 	params = "<text>", | ||||||
| 	description = "Say <text> as the server", | 	description = "Say <text> as the server", | ||||||
| 	privs = {server=true}, | 	privs = {server=true}, | ||||||
| 	func = function(name, param) | 	func = function(name, param) | ||||||
| 		minetest.chat_send_all(name .. ": " .. param) | 		minetest.chat_send_all(name .. ": " .. param) | ||||||
| 	end | 	end | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_chatcommand("tell", { | minetest.register_chatcommand("tell", { | ||||||
| 	params = "<name> <text>", | 	params = "<name> <text>", | ||||||
| 	description = "Say <text> to <name> privately", | 	description = "Say <text> to <name> privately", | ||||||
| 	privs = {shout=true}, | 	func = function(name, param) | ||||||
| 	func = function(name, param) | 		local found, _, target, message = param:find("^([^%s]+)%s+(.*)$") | ||||||
| 		local found, _, target, message = param:find("^([^%s]+)%s+(.*)$") | 		if found == nil then | ||||||
| 		if found == nil then | 			minetest.chat_send_player(name, "Invalid usage: " .. param) | ||||||
| 			minetest.chat_send_player(name, "Invalid usage: " .. param) | 			return | ||||||
| 			return | 		end | ||||||
| 		end | 		if not minetest.get_player_by_name(target) then | ||||||
| 		if not minetest.get_player_by_name(target) then | 			minetest.chat_send_player(name, "Invalid target: " .. target) | ||||||
| 			minetest.chat_send_player(name, "Invalid target: " .. target) | 		end | ||||||
| 		end | 		minetest.chat_send_player(target, name .. " whispers: " .. message, false) | ||||||
| 		minetest.chat_send_player(target, name .. " whispers: " .. message, false) | 	end | ||||||
| 	end | }) | ||||||
| }) |  | ||||||
|  | minetest.register_chatcommand("hp", { | ||||||
| minetest.register_chatcommand("hp", { | 	params = "<name> <value>", | ||||||
| 	params = "<name> <value>", | 	description = "Set health of <name> to <value> hitpoints", | ||||||
| 	description = "Set health of <name> to <value> hitpoints", | 	privs = {ban=true}, | ||||||
| 	privs = {ban=true}, | 	func = function(name, param) | ||||||
| 	func = function(name, param) | 		local found, _, target, value = param:find("^([^%s]+)%s+(%d+)$") | ||||||
| 		local found, _, target, value = param:find("^([^%s]+)%s+(%d+)$") | 		if found == nil then | ||||||
| 		if found == nil then | 			minetest.chat_send_player(name, "Invalid usage: " .. param) | ||||||
| 			minetest.chat_send_player(name, "Invalid usage: " .. param) | 			return | ||||||
| 			return | 		end | ||||||
| 		end | 		local player = minetest.get_player_by_name(target) | ||||||
| 		local player = minetest.get_player_by_name(target) | 		if player then | ||||||
| 		if player then | 			player:set_hp(value) | ||||||
| 			player:set_hp(value) | 		else | ||||||
| 		else | 			minetest.chat_send_player(name, "Invalid target: " .. target) | ||||||
| 			minetest.chat_send_player(name, "Invalid target: " .. target) | 		end | ||||||
| 		end | 	end | ||||||
| 	end | }) | ||||||
| }) |  | ||||||
|  | local function initialize_data(meta) | ||||||
| local function initialize_data(meta) | 	local commands = meta:get_string("commands") | ||||||
| 	local commands = minetest.formspec_escape(meta:get_string("commands")) | 	meta:set_string("formspec", | ||||||
| 	meta:set_string("formspec", | 		"invsize[9,5;]" .. | ||||||
| 		"invsize[9,5;]" .. | 		"textarea[0.5,0.5;8.5,4;commands;Commands;"..commands.."]" .. | ||||||
| 		"textarea[0.5,0.5;8.5,4;commands;Commands;"..commands.."]" .. | 		"label[1,3.8;@nearest, @farthest, and @random are replaced by the respective player names]" .. | ||||||
| 		"label[1,3.8;@nearest, @farthest, and @random are replaced by the respective player names]" .. | 		"button_exit[3.3,4.5;2,1;submit;Submit]") | ||||||
| 		"button_exit[3.3,4.5;2,1;submit;Submit]") | 	local owner = meta:get_string("owner") | ||||||
| 	local owner = meta:get_string("owner") | 	if owner == "" then | ||||||
| 	if owner == "" then | 		owner = "not owned" | ||||||
| 		owner = "not owned" | 	else | ||||||
| 	else | 		owner = "owned by " .. owner | ||||||
| 		owner = "owned by " .. owner | 	end | ||||||
| 	end | 	meta:set_string("infotext", "Command Block\n" .. | ||||||
| 	meta:set_string("infotext", "Command Block\n" .. | 		"(" .. owner .. ")\n" .. | ||||||
| 		"(" .. owner .. ")\n" .. | 		"Commands: "..commands) | ||||||
| 		"Commands: "..commands) | end | ||||||
| end |  | ||||||
|  | local function construct(pos) | ||||||
| local function construct(pos) | 	local meta = minetest.get_meta(pos) | ||||||
| 	local meta = minetest.get_meta(pos) |  | ||||||
|  | 	meta:set_string("commands", "tell @nearest Commandblock unconfigured") | ||||||
| 	meta:set_string("commands", "tell @nearest Commandblock unconfigured") |  | ||||||
|  | 	meta:set_string("owner", "") | ||||||
| 	meta:set_string("owner", "") |  | ||||||
|  | 	initialize_data(meta) | ||||||
| 	initialize_data(meta) | end | ||||||
| end |  | ||||||
|  | local function after_place(pos, placer) | ||||||
| local function after_place(pos, placer) | 	if placer then | ||||||
| 	if placer then | 		local meta = minetest.get_meta(pos) | ||||||
| 		local meta = minetest.get_meta(pos) | 		meta:set_string("owner", placer:get_player_name()) | ||||||
| 		meta:set_string("owner", placer:get_player_name()) | 		initialize_data(meta) | ||||||
| 		initialize_data(meta) | 	end | ||||||
| 	end | end | ||||||
| end |  | ||||||
|  | local function receive_fields(pos, formname, fields, sender) | ||||||
| local function receive_fields(pos, formname, fields, sender) | 	if not fields.submit then | ||||||
| 	if not fields.submit then | 		return | ||||||
| 		return | 	end | ||||||
| 	end | 	local meta = minetest.get_meta(pos) | ||||||
| 	local meta = minetest.get_meta(pos) | 	local owner = meta:get_string("owner") | ||||||
| 	local owner = meta:get_string("owner") | 	if owner ~= "" and sender:get_player_name() ~= owner then | ||||||
| 	if owner ~= "" and sender:get_player_name() ~= owner then | 		return | ||||||
| 		return | 	end | ||||||
| 	end | 	meta:set_string("commands", fields.commands) | ||||||
| 	meta:set_string("commands", fields.commands) |  | ||||||
|  | 	initialize_data(meta) | ||||||
| 	initialize_data(meta) | end | ||||||
| end |  | ||||||
|  | local function resolve_commands(commands, pos) | ||||||
| local function resolve_commands(commands, pos) | 	local nearest, farthest = nil, nil | ||||||
| 	local players = minetest.get_connected_players() | 	local min_distance, max_distance = math.huge, -1 | ||||||
|  | 	local players = minetest.get_connected_players() | ||||||
| 	-- No players online: remove all commands containing | 	for index, player in pairs(players) do | ||||||
| 	-- @nearest, @farthest and @random | 		local distance = vector.distance(pos, player:getpos()) | ||||||
| 	if #players == 0 then | 		if distance < min_distance then | ||||||
| 		commands = commands:gsub("[^\r\n]+", function (line) | 			min_distance = distance | ||||||
| 			if line:find("@nearest") then return "" end | 			nearest = player:get_player_name() | ||||||
| 			if line:find("@farthest") then return "" end | 		end | ||||||
| 			if line:find("@random") then return "" end | 		if distance > max_distance then | ||||||
| 			return line | 			max_distance = distance | ||||||
| 		end) | 			farthest = player:get_player_name() | ||||||
| 		return commands | 		end | ||||||
| 	end | 	end | ||||||
|  | 	local random = players[math.random(#players)]:get_player_name() | ||||||
| 	local nearest, farthest = nil, nil | 	commands = commands:gsub("@nearest", nearest) | ||||||
| 	local min_distance, max_distance = math.huge, -1 | 	commands = commands:gsub("@farthest", farthest) | ||||||
| 	for index, player in pairs(players) do | 	commands = commands:gsub("@random", random) | ||||||
| 		local distance = vector.distance(pos, player:get_pos()) | 	return commands | ||||||
| 		if distance < min_distance then | end | ||||||
| 			min_distance = distance |  | ||||||
| 			nearest = player:get_player_name() | local function commandblock_action_on(pos, node) | ||||||
| 		end | 	if node.name ~= "mesecons_commandblock:commandblock_off" then | ||||||
| 		if distance > max_distance then | 		return | ||||||
| 			max_distance = distance | 	end | ||||||
| 			farthest = player:get_player_name() |  | ||||||
| 		end | 	minetest.swap_node(pos, {name = "mesecons_commandblock:commandblock_on"}) | ||||||
| 	end |  | ||||||
| 	local random = players[math.random(#players)]:get_player_name() | 	local meta = minetest.get_meta(pos) | ||||||
| 	commands = commands:gsub("@nearest", nearest) | 	local owner = meta:get_string("owner") | ||||||
| 	commands = commands:gsub("@farthest", farthest) | 	if owner == "" then | ||||||
| 	commands = commands:gsub("@random", random) | 		return | ||||||
| 	return commands | 	end | ||||||
| end |  | ||||||
|  | 	local commands = resolve_commands(meta:get_string("commands"), pos) | ||||||
| local function commandblock_action_on(pos, node) | 	for _, command in pairs(commands:split("\n")) do | ||||||
| 	if node.name ~= "mesecons_commandblock:commandblock_off" then | 		local pos = command:find(" ") | ||||||
| 		return | 		local cmd, param = command, "" | ||||||
| 	end | 		if pos then | ||||||
|  | 			cmd = command:sub(1, pos - 1) | ||||||
| 	minetest.swap_node(pos, {name = "mesecons_commandblock:commandblock_on"}) | 			param = command:sub(pos + 1) | ||||||
|  | 		end | ||||||
| 	local meta = minetest.get_meta(pos) | 		local cmddef = minetest.chatcommands[cmd] | ||||||
| 	local owner = meta:get_string("owner") | 		if not cmddef then | ||||||
| 	if owner == "" then | 			minetest.chat_send_player(owner, "The command "..cmd.." does not exist") | ||||||
| 		return | 			return | ||||||
| 	end | 		end | ||||||
|  | 		local has_privs, missing_privs = minetest.check_player_privs(owner, cmddef.privs) | ||||||
| 	local commands = resolve_commands(meta:get_string("commands"), pos) | 		if not has_privs then | ||||||
| 	for _, command in pairs(commands:split("\n")) do | 			minetest.chat_send_player(owner, "You don't have permission " | ||||||
| 		local pos = command:find(" ") | 					.."to run "..cmd | ||||||
| 		local cmd, param = command, "" | 					.." (missing privileges: " | ||||||
| 		if pos then | 					..table.concat(missing_privs, ", ")..")") | ||||||
| 			cmd = command:sub(1, pos - 1) | 			return | ||||||
| 			param = command:sub(pos + 1) | 		end | ||||||
| 		end | 		cmddef.func(owner, param) | ||||||
| 		local cmddef = minetest.chatcommands[cmd] | 	end | ||||||
| 		if not cmddef then | end | ||||||
| 			minetest.chat_send_player(owner, "The command "..cmd.." does not exist") |  | ||||||
| 			return | local function commandblock_action_off(pos, node) | ||||||
| 		end | 	if node.name == "mesecons_commandblock:commandblock_on" then | ||||||
| 		local has_privs, missing_privs = minetest.check_player_privs(owner, cmddef.privs) | 		minetest.swap_node(pos, {name = "mesecons_commandblock:commandblock_off"}) | ||||||
| 		if not has_privs then | 	end | ||||||
| 			minetest.chat_send_player(owner, "You don't have permission " | end | ||||||
| 					.."to run "..cmd |  | ||||||
| 					.." (missing privileges: " | local function can_dig(pos, player) | ||||||
| 					..table.concat(missing_privs, ", ")..")") | 	local meta = minetest.get_meta(pos) | ||||||
| 			return | 	local owner = meta:get_string("owner") | ||||||
| 		end | 	return owner == "" or owner == player:get_player_name() | ||||||
| 		cmddef.func(owner, param) | end | ||||||
| 	end |  | ||||||
| end | minetest.register_node("mesecons_commandblock:commandblock_off", { | ||||||
|  | 	description = "Command Block", | ||||||
| local function commandblock_action_off(pos, node) | 	tiles = {"jeija_commandblock_off.png"}, | ||||||
| 	if node.name == "mesecons_commandblock:commandblock_on" then | 	inventory_image = minetest.inventorycube("jeija_commandblock_off.png"), | ||||||
| 		minetest.swap_node(pos, {name = "mesecons_commandblock:commandblock_off"}) | 	groups = {cracky=2, mesecon_effector_off=1}, | ||||||
| 	end | 	on_construct = construct, | ||||||
| end | 	after_place_node = after_place, | ||||||
|  | 	on_receive_fields = receive_fields, | ||||||
| local function can_dig(pos, player) | 	can_dig = can_dig, | ||||||
| 	local meta = minetest.get_meta(pos) | 	sounds = default.node_sound_stone_defaults(), | ||||||
| 	local owner = meta:get_string("owner") | 	mesecons = {effector = { | ||||||
| 	return owner == "" or owner == player:get_player_name() or | 		action_on = commandblock_action_on | ||||||
| 		minetest.check_player_privs(player, "protection_bypass") | 	}} | ||||||
| end | }) | ||||||
|  |  | ||||||
| minetest.register_node("mesecons_commandblock:commandblock_off", { | minetest.register_node("mesecons_commandblock:commandblock_on", { | ||||||
| 	description = "Command Block", | 	tiles = {"jeija_commandblock_on.png"}, | ||||||
| 	tiles = {"jeija_commandblock_off.png"}, | 	groups = {cracky=2, mesecon_effector_on=1, not_in_creative_inventory=1}, | ||||||
| 	inventory_image = minetest.inventorycube("jeija_commandblock_off.png"), | 	light_source = 10, | ||||||
| 	is_ground_content = false, | 	drop = "mesecons_commandblock:commandblock_off", | ||||||
| 	groups = {cracky=2, mesecon_effector_off=1}, | 	on_construct = construct, | ||||||
| 	on_construct = construct, | 	after_place_node = after_place, | ||||||
| 	after_place_node = after_place, | 	on_receive_fields = receive_fields, | ||||||
| 	on_receive_fields = receive_fields, | 	can_dig = can_dig, | ||||||
| 	can_dig = can_dig, | 	sounds = default.node_sound_stone_defaults(), | ||||||
| 	sounds = default.node_sound_stone_defaults(), | 	mesecons = {effector = { | ||||||
| 	mesecons = {effector = { | 		action_off = commandblock_action_off | ||||||
| 		action_on = commandblock_action_on | 	}} | ||||||
| 	}}, | }) | ||||||
| 	on_blast = mesecon.on_blastnode, |  | ||||||
| }) |  | ||||||
|  |  | ||||||
| minetest.register_node("mesecons_commandblock:commandblock_on", { |  | ||||||
| 	tiles = {"jeija_commandblock_on.png"}, |  | ||||||
| 	is_ground_content = false, |  | ||||||
| 	groups = {cracky=2, mesecon_effector_on=1, not_in_creative_inventory=1}, |  | ||||||
| 	light_source = 10, |  | ||||||
| 	drop = "mesecons_commandblock:commandblock_off", |  | ||||||
| 	on_construct = construct, |  | ||||||
| 	after_place_node = after_place, |  | ||||||
| 	on_receive_fields = receive_fields, |  | ||||||
| 	can_dig = can_dig, |  | ||||||
| 	sounds = default.node_sound_stone_defaults(), |  | ||||||
| 	mesecons = {effector = { |  | ||||||
| 		action_off = commandblock_action_off |  | ||||||
| 	}}, |  | ||||||
| 	on_blast = mesecon.on_blastnode, |  | ||||||
| }) |  | ||||||
|   | |||||||
| @@ -1,2 +0,0 @@ | |||||||
| name = mesecons_commandblock |  | ||||||
| depends = mesecons |  | ||||||
							
								
								
									
										
											BIN
										
									
								
								mesecons_commandblock/textures/jeija_close_window.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 323 B | 
| Before Width: | Height: | Size: 183 B After Width: | Height: | Size: 282 B | 
| Before Width: | Height: | Size: 183 B After Width: | Height: | Size: 278 B | 
							
								
								
									
										1
									
								
								mesecons_delayer/depends.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | |||||||
|  | mesecons | ||||||
| @@ -1 +0,0 @@ | |||||||
| The delayer delays the signal from the input for a determined time. The time can be set by punching the delayer. Possible delays are: 0.1 seconds, 0.3 seconds, 0.5 seconds and 1 second. You may try to use it for creating songs with the noteblock. It works in unloaded blocks. |  | ||||||
| Before Width: | Height: | Size: 50 KiB | 
| Before Width: | Height: | Size: 4.2 KiB | 
| @@ -33,12 +33,21 @@ end | |||||||
|  |  | ||||||
| -- Register the 2 (states) x 4 (delay times) delayers | -- Register the 2 (states) x 4 (delay times) delayers | ||||||
|  |  | ||||||
| local delaytime = { 0.1, 0.3, 0.5, 1.0 } |  | ||||||
|  |  | ||||||
| for i = 1, 4 do | for i = 1, 4 do | ||||||
|  | local groups = {} | ||||||
|  | if i == 1 then  | ||||||
|  | 	groups = {bendy=2,snappy=1,dig_immediate=2} | ||||||
|  | else | ||||||
|  | 	groups = {bendy=2,snappy=1,dig_immediate=2, not_in_creative_inventory=1} | ||||||
|  | end | ||||||
|  |  | ||||||
| local boxes = { | local delaytime | ||||||
| 	 { -6/16, -8/16, -6/16, 6/16, -7/16, 6/16 },		-- the main slab | if 		i == 1 then delaytime = 0.1 | ||||||
|  | elseif	i == 2 then delaytime = 0.3 | ||||||
|  | elseif	i == 3 then delaytime = 0.5 | ||||||
|  | elseif	i == 4 then delaytime = 1.0 end | ||||||
|  |  | ||||||
|  | boxes = {{ -6/16, -8/16, -6/16, 6/16, -7/16, 6/16 },		-- the main slab | ||||||
|  |  | ||||||
| 	 { -2/16, -7/16, -4/16, 2/16, -26/64, -3/16 },		-- the jeweled "on" indicator | 	 { -2/16, -7/16, -4/16, 2/16, -26/64, -3/16 },		-- the jeweled "on" indicator | ||||||
| 	 { -3/16, -7/16, -3/16, 3/16, -26/64, -2/16 }, | 	 { -3/16, -7/16, -3/16, 3/16, -26/64, -2/16 }, | ||||||
| @@ -48,13 +57,21 @@ local boxes = { | |||||||
|  |  | ||||||
| 	 { -6/16, -7/16, -6/16, -4/16, -27/64, -4/16 },		-- the timer indicator | 	 { -6/16, -7/16, -6/16, -4/16, -27/64, -4/16 },		-- the timer indicator | ||||||
| 	 { -8/16, -8/16, -1/16, -6/16, -7/16, 1/16 },		-- the two wire stubs | 	 { -8/16, -8/16, -1/16, -6/16, -7/16, 1/16 },		-- the two wire stubs | ||||||
| 	 { 6/16, -8/16, -1/16, 8/16, -7/16, 1/16 } | 	 { 6/16, -8/16, -1/16, 8/16, -7/16, 1/16 }} | ||||||
| } |  | ||||||
|  |  | ||||||
| -- Delayer definition defaults | minetest.register_node("mesecons_delayer:delayer_off_"..tostring(i), { | ||||||
| local def = { | 	description = "Delayer", | ||||||
| 	drawtype = "nodebox", | 	drawtype = "nodebox", | ||||||
| 	use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or nil, | 	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", | ||||||
| @@ -64,46 +81,26 @@ local def = { | |||||||
| 		type = "fixed", | 		type = "fixed", | ||||||
| 		fixed = boxes | 		fixed = boxes | ||||||
| 	}, | 	}, | ||||||
|  | 	groups = groups, | ||||||
| 	paramtype = "light", | 	paramtype = "light", | ||||||
| 	paramtype2 = "facedir", | 	paramtype2 = "facedir", | ||||||
| 	sunlight_propagates = true, | 	sunlight_propagates = true, | ||||||
| 	is_ground_content = false, | 	is_ground_content = true, | ||||||
| 	delayer_time = delaytime[i], | 	drop = 'mesecons_delayer:delayer_off_1', | ||||||
| 	sounds = default.node_sound_stone_defaults(), | 	on_punch = function (pos, node) | ||||||
| 	on_blast = mesecon.on_blastnode, | 		if node.name=="mesecons_delayer:delayer_off_1" then | ||||||
| 	drop = "mesecons_delayer:delayer_off_1", | 			minetest.swap_node(pos, {name = "mesecons_delayer:delayer_off_2", param2=node.param2}) | ||||||
| } | 		elseif node.name=="mesecons_delayer:delayer_off_2" then | ||||||
|  | 			minetest.swap_node(pos, {name = "mesecons_delayer:delayer_off_3", param2=node.param2}) | ||||||
| -- Deactivated delayer definition defaults | 		elseif node.name=="mesecons_delayer:delayer_off_3" then | ||||||
| local off_groups = {bendy=2,snappy=1,dig_immediate=2} | 			minetest.swap_node(pos, {name = "mesecons_delayer:delayer_off_4", param2=node.param2}) | ||||||
| if i > 1 then | 		elseif node.name=="mesecons_delayer:delayer_off_4" then | ||||||
| 	off_groups.not_in_creative_inventory = 1 | 			minetest.swap_node(pos, {name = "mesecons_delayer:delayer_off_1", param2=node.param2}) | ||||||
| end |  | ||||||
|  |  | ||||||
| local off_state = { |  | ||||||
| 	description = "Delayer", |  | ||||||
| 	tiles = { |  | ||||||
| 		"mesecons_delayer_off_"..tostring(i)..".png", |  | ||||||
| 		"mesecons_delayer_bottom.png", |  | ||||||
| 		"mesecons_delayer_ends_off.png", |  | ||||||
| 		"mesecons_delayer_ends_off.png", |  | ||||||
| 		"mesecons_delayer_sides_off.png", |  | ||||||
| 		"mesecons_delayer_sides_off.png" |  | ||||||
| 	}, |  | ||||||
| 	inventory_image = "mesecons_delayer_off_1.png", |  | ||||||
| 	wield_image = "mesecons_delayer_off_1.png", |  | ||||||
| 	groups = off_groups, |  | ||||||
| 	on_punch = function(pos, node, puncher) |  | ||||||
| 		if minetest.is_protected(pos, puncher and puncher:get_player_name() or "") then |  | ||||||
| 			return |  | ||||||
| 		end | 		end | ||||||
|  |  | ||||||
| 		minetest.swap_node(pos, { |  | ||||||
| 			name = "mesecons_delayer:delayer_off_"..tostring(i % 4 + 1), |  | ||||||
| 			param2 = node.param2 |  | ||||||
| 		}) |  | ||||||
| 	end, | 	end, | ||||||
|  | 	delayer_time = delaytime, | ||||||
| 	delayer_onstate = "mesecons_delayer:delayer_on_"..tostring(i), | 	delayer_onstate = "mesecons_delayer:delayer_on_"..tostring(i), | ||||||
|  | 	sounds = default.node_sound_stone_defaults(), | ||||||
| 	mesecons = { | 	mesecons = { | ||||||
| 		receptor = | 		receptor = | ||||||
| 		{ | 		{ | ||||||
| @@ -115,16 +112,13 @@ local off_state = { | |||||||
| 			rules = delayer_get_input_rules, | 			rules = delayer_get_input_rules, | ||||||
| 			action_on = delayer_activate | 			action_on = delayer_activate | ||||||
| 		} | 		} | ||||||
| 	}, | 	} | ||||||
| } | }) | ||||||
| for k, v in pairs(def) do |  | ||||||
| 	off_state[k] = off_state[k] or v |  | ||||||
| end |  | ||||||
| minetest.register_node("mesecons_delayer:delayer_off_"..tostring(i), off_state) |  | ||||||
|  |  | ||||||
| -- Activated delayer definition defaults |  | ||||||
| local on_state = { | minetest.register_node("mesecons_delayer:delayer_on_"..tostring(i), { | ||||||
| 	description = "You hacker you", | 	description = "You hacker you", | ||||||
|  | 	drawtype = "nodebox", | ||||||
| 	tiles = { | 	tiles = { | ||||||
| 		"mesecons_delayer_on_"..tostring(i)..".png", | 		"mesecons_delayer_on_"..tostring(i)..".png", | ||||||
| 		"mesecons_delayer_bottom.png", | 		"mesecons_delayer_bottom.png", | ||||||
| @@ -132,18 +126,34 @@ local on_state = { | |||||||
| 		"mesecons_delayer_ends_on.png", | 		"mesecons_delayer_ends_on.png", | ||||||
| 		"mesecons_delayer_sides_on.png", | 		"mesecons_delayer_sides_on.png", | ||||||
| 		"mesecons_delayer_sides_on.png" | 		"mesecons_delayer_sides_on.png" | ||||||
|  | 		}, | ||||||
|  | 	walkable = true, | ||||||
|  | 	selection_box = { | ||||||
|  | 		type = "fixed", | ||||||
|  | 		fixed = { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 }, | ||||||
|  | 	}, | ||||||
|  | 	node_box = { | ||||||
|  | 		type = "fixed", | ||||||
|  | 		fixed = boxes | ||||||
| 	}, | 	}, | ||||||
| 	groups = {bendy = 2, snappy = 1, dig_immediate = 2, not_in_creative_inventory = 1}, | 	groups = {bendy = 2, snappy = 1, dig_immediate = 2, not_in_creative_inventory = 1}, | ||||||
| 	on_punch = function(pos, node, puncher) | 	paramtype = "light", | ||||||
| 		if minetest.is_protected(pos, puncher and puncher:get_player_name() or "") then | 	paramtype2 = "facedir", | ||||||
| 			return | 	sunlight_propagates = true, | ||||||
|  | 	is_ground_content = true, | ||||||
|  | 	drop = 'mesecons_delayer:delayer_off_1', | ||||||
|  | 	on_punch = function (pos, node) | ||||||
|  | 		if node.name=="mesecons_delayer:delayer_on_1" then | ||||||
|  | 			minetest.swap_node(pos, {name = "mesecons_delayer:delayer_on_2", param2=node.param2}) | ||||||
|  | 		elseif node.name=="mesecons_delayer:delayer_on_2" then | ||||||
|  | 			minetest.swap_node(pos, {name = "mesecons_delayer:delayer_on_3", param2=node.param2}) | ||||||
|  | 		elseif node.name=="mesecons_delayer:delayer_on_3" then | ||||||
|  | 			minetest.swap_node(pos, {name = "mesecons_delayer:delayer_on_4", param2=node.param2}) | ||||||
|  | 		elseif node.name=="mesecons_delayer:delayer_on_4" then | ||||||
|  | 			minetest.swap_node(pos, {name = "mesecons_delayer:delayer_on_1", param2=node.param2}) | ||||||
| 		end | 		end | ||||||
|  |  | ||||||
| 		minetest.swap_node(pos, { |  | ||||||
| 			name = "mesecons_delayer:delayer_on_"..tostring(i % 4 + 1), |  | ||||||
| 			param2 = node.param2 |  | ||||||
| 		}) |  | ||||||
| 	end, | 	end, | ||||||
|  | 	delayer_time = delaytime, | ||||||
| 	delayer_offstate = "mesecons_delayer:delayer_off_"..tostring(i), | 	delayer_offstate = "mesecons_delayer:delayer_off_"..tostring(i), | ||||||
| 	mesecons = { | 	mesecons = { | ||||||
| 		receptor = | 		receptor = | ||||||
| @@ -156,13 +166,8 @@ local on_state = { | |||||||
| 			rules = delayer_get_input_rules, | 			rules = delayer_get_input_rules, | ||||||
| 			action_off = delayer_deactivate | 			action_off = delayer_deactivate | ||||||
| 		} | 		} | ||||||
| 	}, | 	} | ||||||
| } | }) | ||||||
| for k, v in pairs(def) do |  | ||||||
| 	on_state[k] = on_state[k] or v |  | ||||||
| end |  | ||||||
| minetest.register_node("mesecons_delayer:delayer_on_"..tostring(i), on_state) |  | ||||||
|  |  | ||||||
| end | end | ||||||
|  |  | ||||||
| minetest.register_craft({ | minetest.register_craft({ | ||||||
|   | |||||||
| @@ -1,2 +0,0 @@ | |||||||
| name = mesecons_delayer |  | ||||||
| depends = mesecons |  | ||||||
| Before Width: | Height: | Size: 221 B After Width: | Height: | Size: 438 B | 
| Before Width: | Height: | Size: 176 B After Width: | Height: | Size: 226 B | 
| Before Width: | Height: | Size: 187 B After Width: | Height: | Size: 228 B | 
| Before Width: | Height: | Size: 448 B After Width: | Height: | Size: 562 B | 
| Before Width: | Height: | Size: 449 B After Width: | Height: | Size: 558 B | 
| Before Width: | Height: | Size: 448 B After Width: | Height: | Size: 561 B | 
| Before Width: | Height: | Size: 446 B After Width: | Height: | Size: 556 B | 
| Before Width: | Height: | Size: 541 B After Width: | Height: | Size: 635 B | 
| Before Width: | Height: | Size: 541 B After Width: | Height: | Size: 632 B | 
| Before Width: | Height: | Size: 541 B After Width: | Height: | Size: 635 B | 
| Before Width: | Height: | Size: 538 B After Width: | Height: | Size: 630 B | 
| Before Width: | Height: | Size: 173 B After Width: | Height: | Size: 229 B | 
| Before Width: | Height: | Size: 181 B After Width: | Height: | Size: 234 B | 
							
								
								
									
										2
									
								
								mesecons_detector/depends.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,2 @@ | |||||||
|  | mesecons | ||||||
|  | mesecons_materials | ||||||
| @@ -1,11 +0,0 @@ | |||||||
| The node detector is a receptor. It changes its state when either any node |  | ||||||
| or a specific node is detected. Right-click it to set a nodename to scan for. |  | ||||||
| It can also receive digiline signals. For example, you can send |  | ||||||
| <code>{distance=4, scanname="default:dirt"}</code> |  | ||||||
| to set distance to 4 and scan for dirt. You can omit either parameter. |  | ||||||
| There is also a command parameter: <code>{command="get"}</code> will respond |  | ||||||
| with the detected nodename and <code>{command="scan"}</code> will respond with |  | ||||||
| a boolean using the distance and nodename of the detector. |  | ||||||
| Nodenames must include the mod they reside in, so for instance default:dirt, not just dirt. |  | ||||||
| The distance parameter specifies how many blocks are between the node detector and the node to detect. |  | ||||||
| Automatic scanning with Mesecons output only works when the detector is in an active block, but Digilines queries always work. |  | ||||||
| Before Width: | Height: | Size: 43 KiB | 
| Before Width: | Height: | Size: 7.3 KiB | 
| @@ -1,5 +0,0 @@ | |||||||
| The object detector is a receptor. It changes its state when a player approaches. |  | ||||||
| Right-click it to set a name to scan for. |  | ||||||
| You can also search for comma-separated lists of players where the detector gets activated if any of the names in the list are found. |  | ||||||
| It can also receive digiline signals which are the name to scan for on the specified channel in the right-click menu. |  | ||||||
| Automatic scanning with Mesecons output only works when the detector is in an active block, but Digilines queries always work. |  | ||||||
| Before Width: | Height: | Size: 78 KiB | 
| Before Width: | Height: | Size: 7.1 KiB | 
| @@ -4,7 +4,7 @@ local GET_COMMAND = "GET" | |||||||
| -- Detects players in a certain radius | -- Detects players in a certain radius | ||||||
| -- The radius can be specified in mesecons/settings.lua | -- The radius can be specified in mesecons/settings.lua | ||||||
|  |  | ||||||
| local function object_detector_make_formspec(pos) | local object_detector_make_formspec = function (pos) | ||||||
| 	local meta = minetest.get_meta(pos) | 	local meta = minetest.get_meta(pos) | ||||||
| 	meta:set_string("formspec", "size[9,2.5]" .. | 	meta:set_string("formspec", "size[9,2.5]" .. | ||||||
| 		"field[0.3,  0;9,2;scanname;Name of player to scan for (empty for any):;${scanname}]".. | 		"field[0.3,  0;9,2;scanname;Name of player to scan for (empty for any):;${scanname}]".. | ||||||
| @@ -12,10 +12,8 @@ local function object_detector_make_formspec(pos) | |||||||
| 		"button_exit[7,0.75;2,3;;Save]") | 		"button_exit[7,0.75;2,3;;Save]") | ||||||
| end | end | ||||||
|  |  | ||||||
| local function object_detector_on_receive_fields(pos, formname, fields, sender) | local object_detector_on_receive_fields = function(pos, formname, fields) | ||||||
| 	if not fields.scanname or not fields.digiline_channel then return end | 	if not fields.scanname or not fields.digiline_channel then return end; | ||||||
|  |  | ||||||
| 	if minetest.is_protected(pos, sender:get_player_name()) then return end |  | ||||||
|  |  | ||||||
| 	local meta = minetest.get_meta(pos) | 	local meta = minetest.get_meta(pos) | ||||||
| 	meta:set_string("scanname", fields.scanname) | 	meta:set_string("scanname", fields.scanname) | ||||||
| @@ -24,38 +22,25 @@ local function object_detector_on_receive_fields(pos, formname, fields, sender) | |||||||
| end | end | ||||||
|  |  | ||||||
| -- returns true if player was found, false if not | -- returns true if player was found, false if not | ||||||
| local function object_detector_scan(pos) | local object_detector_scan = function (pos) | ||||||
| 	local objs = minetest.get_objects_inside_radius(pos, mesecon.setting("detector_radius", 6)) | 	local objs = minetest.get_objects_inside_radius(pos, mesecon.setting("detector_radius", 6)) | ||||||
|  | 	for k, obj in pairs(objs) do | ||||||
| 	-- abort if no scan results were found | 		local isname = obj:get_player_name() -- "" is returned if it is not a player; "" ~= nil! | ||||||
| 	if next(objs) == nil then return false end | 		local scanname = minetest.get_meta(pos):get_string("scanname") | ||||||
|  | 		if (isname == scanname and isname ~= "") or (isname  ~= "" and scanname == "") then -- player with scanname found or not scanname specified | ||||||
| 	local scanname = minetest.get_meta(pos):get_string("scanname") | 			return true | ||||||
| 	local scan_for = {} |  | ||||||
| 	for _, str in pairs(string.split(scanname:gsub(" ", ""), ",")) do |  | ||||||
| 		scan_for[str] = true |  | ||||||
| 	end |  | ||||||
|  |  | ||||||
| 	local every_player = scanname == "" |  | ||||||
| 	for _, obj in pairs(objs) do |  | ||||||
| 		-- "" is returned if it is not a player; "" ~= nil; so only handle objects with foundname ~= "" |  | ||||||
| 		local foundname = obj:get_player_name() |  | ||||||
| 		if foundname ~= "" then |  | ||||||
| 			if every_player or scan_for[foundname] then |  | ||||||
| 				return true |  | ||||||
| 			end |  | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	return false | 	return false | ||||||
| end | end | ||||||
|  |  | ||||||
| -- set player name when receiving a digiline signal on a specific channel | -- set player name when receiving a digiline signal on a specific channel | ||||||
| local object_detector_digiline = { | local object_detector_digiline = { | ||||||
| 	effector = { | 	effector = { | ||||||
| 		action = function(pos, node, channel, msg) | 		action = function (pos, node, channel, msg) | ||||||
| 			local meta = minetest.get_meta(pos) | 			local meta = minetest.get_meta(pos) | ||||||
| 			if channel == meta:get_string("digiline_channel") then | 			local active_channel = meta:get_string("digiline_channel") | ||||||
|  | 			if channel == active_channel then | ||||||
| 				meta:set_string("scanname", msg) | 				meta:set_string("scanname", msg) | ||||||
| 				object_detector_make_formspec(pos) | 				object_detector_make_formspec(pos) | ||||||
| 			end | 			end | ||||||
| @@ -66,7 +51,6 @@ local object_detector_digiline = { | |||||||
| minetest.register_node("mesecons_detector:object_detector_off", { | minetest.register_node("mesecons_detector:object_detector_off", { | ||||||
| 	tiles = {"default_steel_block.png", "default_steel_block.png", "jeija_object_detector_off.png", "jeija_object_detector_off.png", "jeija_object_detector_off.png", "jeija_object_detector_off.png"}, | 	tiles = {"default_steel_block.png", "default_steel_block.png", "jeija_object_detector_off.png", "jeija_object_detector_off.png", "jeija_object_detector_off.png", "jeija_object_detector_off.png"}, | ||||||
| 	paramtype = "light", | 	paramtype = "light", | ||||||
| 	is_ground_content = false, |  | ||||||
| 	walkable = true, | 	walkable = true, | ||||||
| 	groups = {cracky=3}, | 	groups = {cracky=3}, | ||||||
| 	description="Player Detector", | 	description="Player Detector", | ||||||
| @@ -77,14 +61,12 @@ minetest.register_node("mesecons_detector:object_detector_off", { | |||||||
| 	on_construct = object_detector_make_formspec, | 	on_construct = object_detector_make_formspec, | ||||||
| 	on_receive_fields = object_detector_on_receive_fields, | 	on_receive_fields = object_detector_on_receive_fields, | ||||||
| 	sounds = default.node_sound_stone_defaults(), | 	sounds = default.node_sound_stone_defaults(), | ||||||
| 	digiline = object_detector_digiline, | 	digiline = object_detector_digiline | ||||||
| 	on_blast = mesecon.on_blastnode, |  | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_node("mesecons_detector:object_detector_on", { | minetest.register_node("mesecons_detector:object_detector_on", { | ||||||
| 	tiles = {"default_steel_block.png", "default_steel_block.png", "jeija_object_detector_on.png", "jeija_object_detector_on.png", "jeija_object_detector_on.png", "jeija_object_detector_on.png"}, | 	tiles = {"default_steel_block.png", "default_steel_block.png", "jeija_object_detector_on.png", "jeija_object_detector_on.png", "jeija_object_detector_on.png", "jeija_object_detector_on.png"}, | ||||||
| 	paramtype = "light", | 	paramtype = "light", | ||||||
| 	is_ground_content = false, |  | ||||||
| 	walkable = true, | 	walkable = true, | ||||||
| 	groups = {cracky=3,not_in_creative_inventory=1}, | 	groups = {cracky=3,not_in_creative_inventory=1}, | ||||||
| 	drop = 'mesecons_detector:object_detector_off', | 	drop = 'mesecons_detector:object_detector_off', | ||||||
| @@ -95,8 +77,7 @@ minetest.register_node("mesecons_detector:object_detector_on", { | |||||||
| 	on_construct = object_detector_make_formspec, | 	on_construct = object_detector_make_formspec, | ||||||
| 	on_receive_fields = object_detector_on_receive_fields, | 	on_receive_fields = object_detector_on_receive_fields, | ||||||
| 	sounds = default.node_sound_stone_defaults(), | 	sounds = default.node_sound_stone_defaults(), | ||||||
| 	digiline = object_detector_digiline, | 	digiline = object_detector_digiline | ||||||
| 	on_blast = mesecon.on_blastnode, |  | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_craft({ | minetest.register_craft({ | ||||||
| @@ -108,126 +89,71 @@ minetest.register_craft({ | |||||||
| 	} | 	} | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_craft({ | minetest.register_abm( | ||||||
| 	output = 'mesecons_detector:object_detector_off', | 	{nodenames = {"mesecons_detector:object_detector_off"}, | ||||||
| 	recipe = { | 	interval = 1.0, | ||||||
| 		{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"}, |  | ||||||
| 		{"default:steel_ingot", "mesecons_microcontroller:microcontroller0000", "default:steel_ingot"}, |  | ||||||
| 		{"default:steel_ingot", "group:mesecon_conductor_craftable", "default:steel_ingot"}, |  | ||||||
| 	} |  | ||||||
| }) |  | ||||||
|  |  | ||||||
| minetest.register_abm({ |  | ||||||
| 	nodenames = {"mesecons_detector:object_detector_off"}, |  | ||||||
| 	interval = 1, |  | ||||||
| 	chance = 1, | 	chance = 1, | ||||||
| 	action = function(pos, node) | 	action = function(pos) | ||||||
| 		if not object_detector_scan(pos) then return end | 		if object_detector_scan(pos) then | ||||||
|  | 			minetest.swap_node(pos, {name = "mesecons_detector:object_detector_on"}) | ||||||
| 		node.name = "mesecons_detector:object_detector_on" | 			mesecon.receptor_on(pos, mesecon.rules.pplate) | ||||||
| 		minetest.swap_node(pos, node) | 		end | ||||||
| 		mesecon.receptor_on(pos, mesecon.rules.pplate) |  | ||||||
| 	end, | 	end, | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_abm({ | minetest.register_abm( | ||||||
| 	nodenames = {"mesecons_detector:object_detector_on"}, | 	{nodenames = {"mesecons_detector:object_detector_on"}, | ||||||
| 	interval = 1, | 	interval = 1.0, | ||||||
| 	chance = 1, | 	chance = 1, | ||||||
| 	action = function(pos, node) | 	action = function(pos) | ||||||
| 		if object_detector_scan(pos) then return end | 		if not object_detector_scan(pos) then | ||||||
|  | 			minetest.swap_node(pos, {name = "mesecons_detector:object_detector_off"}) | ||||||
| 		node.name = "mesecons_detector:object_detector_off" | 			mesecon.receptor_off(pos, mesecon.rules.pplate) | ||||||
| 		minetest.swap_node(pos, node) | 		end | ||||||
| 		mesecon.receptor_off(pos, mesecon.rules.pplate) |  | ||||||
| 	end, | 	end, | ||||||
| }) | }) | ||||||
|  |  | ||||||
| -- Node detector | -- Node detector | ||||||
| -- Detects the node in front of it | -- Detects the node in front of it | ||||||
|  |  | ||||||
| local function node_detector_make_formspec(pos) | local node_detector_make_formspec = function (pos) | ||||||
| 	local meta = minetest.get_meta(pos) | 	local meta = minetest.get_meta(pos) | ||||||
| 	if meta:get_string("distance") == ""  then meta:set_string("distance", "0") end |  | ||||||
| 	meta:set_string("formspec", "size[9,2.5]" .. | 	meta:set_string("formspec", "size[9,2.5]" .. | ||||||
| 		"field[0.3,  0;9,2;scanname;Name of node to scan for (empty for any):;${scanname}]".. | 		"field[0.3,  0;9,2;scanname;Name of node to scan for (empty for any):;${scanname}]".. | ||||||
| 		"field[0.3,1.5;2.5,2;distance;Distance (0-"..mesecon.setting("node_detector_distance_max", 10).."):;${distance}]".. | 		"field[0.3,1.5;4,2;digiline_channel;Digiline Channel (optional):;${digiline_channel}]".. | ||||||
| 		"field[3,1.5;4,2;digiline_channel;Digiline Channel (optional):;${digiline_channel}]".. |  | ||||||
| 		"button_exit[7,0.75;2,3;;Save]") | 		"button_exit[7,0.75;2,3;;Save]") | ||||||
| end | end | ||||||
|  |  | ||||||
| local function node_detector_on_receive_fields(pos, fieldname, fields, sender) | local node_detector_on_receive_fields = function(pos, formname, fields) | ||||||
| 	if not fields.scanname or not fields.digiline_channel then return end | 	if not fields.scanname or not fields.digiline_channel then return end; | ||||||
|  |  | ||||||
| 	if minetest.is_protected(pos, sender:get_player_name()) then return end |  | ||||||
|  |  | ||||||
| 	local meta = minetest.get_meta(pos) | 	local meta = minetest.get_meta(pos) | ||||||
| 	meta:set_string("scanname", fields.scanname) | 	meta:set_string("scanname", fields.scanname) | ||||||
| 	meta:set_string("distance", fields.distance or "0") |  | ||||||
| 	meta:set_string("digiline_channel", fields.digiline_channel) | 	meta:set_string("digiline_channel", fields.digiline_channel) | ||||||
| 	node_detector_make_formspec(pos) | 	node_detector_make_formspec(pos) | ||||||
| end | end | ||||||
|  |  | ||||||
| -- returns true if node was found, false if not | -- returns true if player was found, false if not | ||||||
| local function node_detector_scan(pos) | local node_detector_scan = function (pos) | ||||||
| 	local node = minetest.get_node_or_nil(pos) | 	local node = minetest.get_node(pos) | ||||||
| 	if not node then return end | 	local frontpos = vector.subtract(pos, minetest.facedir_to_dir(node.param2)) | ||||||
|  | 	local frontnode = minetest.get_node(frontpos) | ||||||
| 	local meta = minetest.get_meta(pos) | 	local meta = minetest.get_meta(pos) | ||||||
|  | 	return (frontnode.name == meta:get_string("scanname")) or | ||||||
| 	local distance = meta:get_int("distance") | 		(frontnode.name ~= "air" and frontnode.name ~= "ignore" and meta:get_string("scanname") == "") | ||||||
| 	local distance_max = mesecon.setting("node_detector_distance_max", 10) |  | ||||||
| 	if distance < 0 then distance = 0 end |  | ||||||
| 	if distance > distance_max then distance = distance_max end |  | ||||||
|  |  | ||||||
| 	local frontname = minetest.get_node( |  | ||||||
| 		vector.subtract(pos, vector.multiply(minetest.facedir_to_dir(node.param2), distance + 1)) |  | ||||||
| 	).name |  | ||||||
| 	local scanname = meta:get_string("scanname") |  | ||||||
|  |  | ||||||
| 	return (frontname == scanname) or |  | ||||||
| 		(frontname ~= "air" and frontname ~= "ignore" and scanname == "") |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function node_detector_send_node_name(pos, node, channel, meta) |  | ||||||
| 	local distance = meta:get_int("distance") |  | ||||||
| 	local distance_max = mesecon.setting("node_detector_distance_max", 10) |  | ||||||
| 	if distance < 0 then distance = 0 end |  | ||||||
| 	if distance > distance_max then distance = distance_max end |  | ||||||
| 	local nodename = minetest.get_node( |  | ||||||
| 		vector.subtract(pos, vector.multiply(minetest.facedir_to_dir(node.param2), distance + 1)) |  | ||||||
| 	).name |  | ||||||
|  |  | ||||||
| 	digiline:receptor_send(pos, digiline.rules.default, channel, nodename) |  | ||||||
| end | end | ||||||
|  |  | ||||||
| -- set player name when receiving a digiline signal on a specific channel | -- set player name when receiving a digiline signal on a specific channel | ||||||
| local node_detector_digiline = { | local node_detector_digiline = { | ||||||
| 	effector = { | 	effector = { | ||||||
| 		action = function(pos, node, channel, msg) | 		action = function (pos, node, channel, msg) | ||||||
| 			local meta = minetest.get_meta(pos) | 			local meta = minetest.get_meta(pos) | ||||||
|  | 			local active_channel = meta:get_string("digiline_channel") | ||||||
| 			if channel ~= meta:get_string("digiline_channel") then return end | 			if channel == active_channel then | ||||||
|  |  | ||||||
| 			if type(msg) == "table" then |  | ||||||
| 				if msg.distance or msg.scanname then |  | ||||||
| 					if msg.distance then |  | ||||||
| 						meta:set_string("distance", msg.distance) |  | ||||||
| 					end |  | ||||||
| 					if msg.scanname then |  | ||||||
| 						meta:set_string("scanname", msg.scanname) |  | ||||||
| 					end |  | ||||||
| 					node_detector_make_formspec(pos) |  | ||||||
| 				end |  | ||||||
| 				if msg.command == "get" then |  | ||||||
| 					node_detector_send_node_name(pos, node, channel, meta) |  | ||||||
| 				elseif msg.command == "scan" then |  | ||||||
| 					local result = node_detector_scan(pos) |  | ||||||
| 					digiline:receptor_send(pos, digiline.rules.default, channel, result) |  | ||||||
| 				end |  | ||||||
| 			else |  | ||||||
| 				if msg == GET_COMMAND then | 				if msg == GET_COMMAND then | ||||||
| 					node_detector_send_node_name(pos, node, channel, meta) | 					local frontpos = vector.subtract(pos, minetest.facedir_to_dir(node.param2)) | ||||||
|  | 					local name = minetest.get_node(frontpos).name | ||||||
|  | 					digiline:receptor_send(pos, digiline.rules.default, channel, name) | ||||||
| 				else | 				else | ||||||
| 					meta:set_string("scanname", msg) | 					meta:set_string("scanname", msg) | ||||||
| 					node_detector_make_formspec(pos) | 					node_detector_make_formspec(pos) | ||||||
| @@ -238,28 +164,10 @@ local node_detector_digiline = { | |||||||
| 	receptor = {} | 	receptor = {} | ||||||
| } | } | ||||||
|  |  | ||||||
| local function after_place_node_detector(pos, placer) |  | ||||||
| 	local placer_pos = placer:get_pos() |  | ||||||
| 	if not placer_pos then |  | ||||||
| 		return |  | ||||||
| 	end |  | ||||||
|  |  | ||||||
| 	--correct for the player's height |  | ||||||
| 	if placer:is_player() then |  | ||||||
| 		placer_pos.y = placer_pos.y + 1.625 |  | ||||||
| 	end |  | ||||||
|  |  | ||||||
| 	--correct for 6d facedir |  | ||||||
| 	local node = minetest.get_node(pos) |  | ||||||
| 	node.param2 = minetest.dir_to_facedir(vector.subtract(pos, placer_pos), true) |  | ||||||
| 	minetest.set_node(pos, node) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| minetest.register_node("mesecons_detector:node_detector_off", { | minetest.register_node("mesecons_detector:node_detector_off", { | ||||||
| 	tiles = {"default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "jeija_node_detector_off.png"}, | 	tiles = {"default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "jeija_node_detector_off.png"}, | ||||||
| 	paramtype = "light", | 	paramtype = "light", | ||||||
| 	paramtype2 = "facedir", | 	paramtype2 = "facedir", | ||||||
| 	is_ground_content = false, |  | ||||||
| 	walkable = true, | 	walkable = true, | ||||||
| 	groups = {cracky=3}, | 	groups = {cracky=3}, | ||||||
| 	description="Node Detector", | 	description="Node Detector", | ||||||
| @@ -268,16 +176,33 @@ minetest.register_node("mesecons_detector:node_detector_off", { | |||||||
| 	}}, | 	}}, | ||||||
| 	on_construct = node_detector_make_formspec, | 	on_construct = node_detector_make_formspec, | ||||||
| 	on_receive_fields = node_detector_on_receive_fields, | 	on_receive_fields = node_detector_on_receive_fields, | ||||||
|  | 	after_place_node = function (pos, placer) | ||||||
|  | 		local placer_pos = placer:getpos() | ||||||
|  | 		 | ||||||
|  | 		--correct for the player's height | ||||||
|  | 		if placer:is_player() then placer_pos.y = placer_pos.y + 1.5 end | ||||||
|  | 		 | ||||||
|  | 		--correct for 6d facedir | ||||||
|  | 		if placer_pos then | ||||||
|  | 			local dir = { | ||||||
|  | 				x = pos.x - placer_pos.x, | ||||||
|  | 				y = pos.y - placer_pos.y, | ||||||
|  | 				z = pos.z - placer_pos.z | ||||||
|  | 			} | ||||||
|  | 			local node = minetest.get_node(pos) | ||||||
|  | 			node.param2 = minetest.dir_to_facedir(dir, true) | ||||||
|  | 			minetest.set_node(pos, node) | ||||||
|  | 			minetest.log("action", "real (6d) facedir: " .. node.param2) | ||||||
|  | 		end | ||||||
|  | 	end, | ||||||
| 	sounds = default.node_sound_stone_defaults(), | 	sounds = default.node_sound_stone_defaults(), | ||||||
| 	digiline = node_detector_digiline, | 	digiline = node_detector_digiline | ||||||
| 	on_blast = mesecon.on_blastnode, |  | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_node("mesecons_detector:node_detector_on", { | minetest.register_node("mesecons_detector:node_detector_on", { | ||||||
| 	tiles = {"default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "jeija_node_detector_on.png"}, | 	tiles = {"default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "jeija_node_detector_on.png"}, | ||||||
| 	paramtype = "light", | 	paramtype = "light", | ||||||
| 	paramtype2 = "facedir", | 	paramtype2 = "facedir", | ||||||
| 	is_ground_content = false, |  | ||||||
| 	walkable = true, | 	walkable = true, | ||||||
| 	groups = {cracky=3,not_in_creative_inventory=1}, | 	groups = {cracky=3,not_in_creative_inventory=1}, | ||||||
| 	drop = 'mesecons_detector:node_detector_off', | 	drop = 'mesecons_detector:node_detector_off', | ||||||
| @@ -286,9 +211,27 @@ minetest.register_node("mesecons_detector:node_detector_on", { | |||||||
| 	}}, | 	}}, | ||||||
| 	on_construct = node_detector_make_formspec, | 	on_construct = node_detector_make_formspec, | ||||||
| 	on_receive_fields = node_detector_on_receive_fields, | 	on_receive_fields = node_detector_on_receive_fields, | ||||||
|  | 	after_place_node = function (pos, placer) | ||||||
|  | 		local placer_pos = placer:getpos() | ||||||
|  | 		 | ||||||
|  | 		--correct for the player's height | ||||||
|  | 		if placer:is_player() then placer_pos.y = placer_pos.y + 1.5 end | ||||||
|  | 		 | ||||||
|  | 		--correct for 6d facedir | ||||||
|  | 		if placer_pos then | ||||||
|  | 			local dir = { | ||||||
|  | 				x = pos.x - placer_pos.x, | ||||||
|  | 				y = pos.y - placer_pos.y, | ||||||
|  | 				z = pos.z - placer_pos.z | ||||||
|  | 			} | ||||||
|  | 			local node = minetest.get_node(pos) | ||||||
|  | 			node.param2 = minetest.dir_to_facedir(dir, true) | ||||||
|  | 			minetest.set_node(pos, node) | ||||||
|  | 			minetest.log("action", "real (6d) facedir: " .. node.param2) | ||||||
|  | 		end | ||||||
|  | 	end, | ||||||
| 	sounds = default.node_sound_stone_defaults(), | 	sounds = default.node_sound_stone_defaults(), | ||||||
| 	digiline = node_detector_digiline, | 	digiline = node_detector_digiline | ||||||
| 	on_blast = mesecon.on_blastnode, |  | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_craft({ | minetest.register_craft({ | ||||||
| @@ -300,37 +243,26 @@ minetest.register_craft({ | |||||||
| 	} | 	} | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_craft({ | minetest.register_abm( | ||||||
| 	output = 'mesecons_detector:node_detector_off', | 	{nodenames = {"mesecons_detector:node_detector_off"}, | ||||||
| 	recipe = { | 	interval = 1.0, | ||||||
| 		{"default:steel_ingot", "group:mesecon_conductor_craftable", "default:steel_ingot"}, |  | ||||||
| 		{"default:steel_ingot", "mesecons_microcontroller:microcontroller0000", "default:steel_ingot"}, |  | ||||||
| 		{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"}, |  | ||||||
| 	} |  | ||||||
| }) |  | ||||||
|  |  | ||||||
| minetest.register_abm({ |  | ||||||
| 	nodenames = {"mesecons_detector:node_detector_off"}, |  | ||||||
| 	interval = 1, |  | ||||||
| 	chance = 1, | 	chance = 1, | ||||||
| 	action = function(pos, node) | 	action = function(pos, node) | ||||||
| 		if not node_detector_scan(pos) then return end | 		if node_detector_scan(pos) then | ||||||
|  | 			minetest.swap_node(pos, {name = "mesecons_detector:node_detector_on", param2 = node.param2}) | ||||||
| 		node.name = "mesecons_detector:node_detector_on" | 			mesecon.receptor_on(pos) | ||||||
| 		minetest.swap_node(pos, node) | 		end | ||||||
| 		mesecon.receptor_on(pos) |  | ||||||
| 	end, | 	end, | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_abm({ | minetest.register_abm( | ||||||
| 	nodenames = {"mesecons_detector:node_detector_on"}, | 	{nodenames = {"mesecons_detector:node_detector_on"}, | ||||||
| 	interval = 1, | 	interval = 1.0, | ||||||
| 	chance = 1, | 	chance = 1, | ||||||
| 	action = function(pos, node) | 	action = function(pos, node) | ||||||
| 		if node_detector_scan(pos) then return end | 		if not node_detector_scan(pos) then | ||||||
|  | 			minetest.swap_node(pos, {name = "mesecons_detector:node_detector_off", param2 = node.param2}) | ||||||
| 		node.name = "mesecons_detector:node_detector_off" | 			mesecon.receptor_off(pos) | ||||||
| 		minetest.swap_node(pos, node) | 		end | ||||||
| 		mesecon.receptor_off(pos) |  | ||||||
| 	end, | 	end, | ||||||
| }) | }) | ||||||
|   | |||||||
| @@ -1,2 +0,0 @@ | |||||||
| name = mesecons_detector |  | ||||||
| depends = mesecons, mesecons_materials |  | ||||||
| Before Width: | Height: | Size: 640 B After Width: | Height: | Size: 717 B | 
| Before Width: | Height: | Size: 687 B After Width: | Height: | Size: 727 B | 
| Before Width: | Height: | Size: 655 B After Width: | Height: | Size: 712 B | 
| Before Width: | Height: | Size: 693 B After Width: | Height: | Size: 735 B | 
							
								
								
									
										2
									
								
								mesecons_doors/depends.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,2 @@ | |||||||
|  | mesecons | ||||||
|  | doors | ||||||
| @@ -13,124 +13,68 @@ local function on_rightclick(pos, dir, check_name, replace, replace_dir, params) | |||||||
| 	minetest.swap_node(pos, {name = replace, param2 = p2}) | 	minetest.swap_node(pos, {name = replace, param2 = p2}) | ||||||
|  |  | ||||||
| 	if (minetest.get_meta(pos):get_int("right") ~= 0) == (params[1] ~= 3) then | 	if (minetest.get_meta(pos):get_int("right") ~= 0) == (params[1] ~= 3) then | ||||||
| 		minetest.sound_play("doors_door_close", { pos = pos, gain = 0.3, max_hear_distance = 10 }, true) | 		minetest.sound_play("door_close", {pos = pos, gain = 0.3, max_hear_distance = 10}) | ||||||
| 	else | 	else | ||||||
| 		minetest.sound_play("doors_door_open", { pos = pos, gain = 0.3, max_hear_distance = 10 }, true) | 		minetest.sound_play("door_open", {pos = pos, gain = 0.3, max_hear_distance = 10}) | ||||||
| 	end | 	end | ||||||
| end | end | ||||||
|  |  | ||||||
| local function meseconify_door(name) | local function meseconify_door(name) | ||||||
| 	if minetest.registered_items[name .. "_b_1"] then | 	local function toggle_state1 (pos, node) | ||||||
| 		-- old style double-node doors | 		on_rightclick(pos, 1, name.."_t_1", name.."_b_2", name.."_t_2", {1,2,3,0}) | ||||||
| 		local function toggle_state1 (pos, node) |  | ||||||
| 			on_rightclick(pos, 1, name.."_t_1", name.."_b_2", name.."_t_2", {1,2,3,0}) |  | ||||||
| 		end |  | ||||||
|  |  | ||||||
| 		local function toggle_state2 (pos, node) |  | ||||||
| 			on_rightclick(pos, 1, name.."_t_2", name.."_b_1", name.."_t_1", {3,0,1,2}) |  | ||||||
| 		end |  | ||||||
|  |  | ||||||
| 		minetest.override_item(name.."_b_1", { |  | ||||||
| 			mesecons = {effector = { |  | ||||||
| 				action_on = toggle_state1, |  | ||||||
| 				action_off = toggle_state1, |  | ||||||
| 				rules = mesecon.rules.pplate |  | ||||||
| 			}} |  | ||||||
| 		}) |  | ||||||
|  |  | ||||||
| 		minetest.override_item(name.."_b_2", { |  | ||||||
| 			mesecons = {effector = { |  | ||||||
| 				action_on = toggle_state2, |  | ||||||
| 				action_off = toggle_state2, |  | ||||||
| 				rules = mesecon.rules.pplate |  | ||||||
| 			}} |  | ||||||
| 		}) |  | ||||||
| 	elseif minetest.registered_items[name .. "_a"] then |  | ||||||
| 		-- new style mesh node based doors |  | ||||||
| 		local override = { |  | ||||||
| 			mesecons = {effector = { |  | ||||||
| 				action_on = function(pos, node) |  | ||||||
| 					local door = doors.get(pos) |  | ||||||
| 					if door then |  | ||||||
| 						door:open() |  | ||||||
| 					end |  | ||||||
| 				end, |  | ||||||
| 				action_off = function(pos, node) |  | ||||||
| 					local door = doors.get(pos) |  | ||||||
| 					if door then |  | ||||||
| 						door:close() |  | ||||||
| 					end |  | ||||||
| 				end, |  | ||||||
| 				rules = mesecon.rules.pplate |  | ||||||
| 			}} |  | ||||||
| 		} |  | ||||||
| 		minetest.override_item(name .. "_a", override) |  | ||||||
| 		minetest.override_item(name .. "_b", override) |  | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
|  | 	local function toggle_state2 (pos, node) | ||||||
|  | 		on_rightclick(pos, 1, name.."_t_2", name.."_b_1", name.."_t_1", {3,0,1,2}) | ||||||
|  | 	end | ||||||
|  |  | ||||||
|  | 	minetest.override_item(name.."_b_1", { | ||||||
|  | 		mesecons = {effector = { | ||||||
|  | 			action_on = toggle_state1, | ||||||
|  | 			action_off = toggle_state1, | ||||||
|  | 			rules = mesecon.rules.pplate | ||||||
|  | 		}}, | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	minetest.override_item(name.."_b_2", { | ||||||
|  | 		mesecons = {effector = { | ||||||
|  | 			action_on = toggle_state2, | ||||||
|  | 			action_off = toggle_state2, | ||||||
|  | 			rules = mesecon.rules.pplate | ||||||
|  | 		}}, | ||||||
|  | 	}) | ||||||
| end | end | ||||||
|  |  | ||||||
| meseconify_door("doors:door_wood") | meseconify_door("doors:door_wood") | ||||||
| meseconify_door("doors:door_steel") | meseconify_door("doors:door_steel") | ||||||
| meseconify_door("doors:door_glass") | meseconify_door("doors:door_glass") | ||||||
| meseconify_door("doors:door_obsidian_glass") | meseconify_door("doors:door_obsidian_glass") | ||||||
| meseconify_door("xpanes:door_steel_bar") |  | ||||||
|  |  | ||||||
| -- Trapdoor | -- Trapdoor | ||||||
| local function trapdoor_switch(pos, node) | local function trapdoor_switch(pos, node) | ||||||
| 	local state = minetest.get_meta(pos):get_int("state") | 	local state = minetest.get_meta(pos):get_int("state") | ||||||
|  |  | ||||||
| 	if state == 1 then | 	if state == 1 then | ||||||
| 		minetest.sound_play("doors_door_close", { pos = pos, gain = 0.3, max_hear_distance = 10 }, true) | 		minetest.sound_play("doors_door_close", {pos = pos, gain = 0.3, max_hear_distance = 10}) | ||||||
| 		minetest.set_node(pos, {name="doors:trapdoor", param2 = node.param2}) | 		minetest.set_node(pos, {name="doors:trapdoor", param2 = node.param2}) | ||||||
| 	else | 	else | ||||||
| 		minetest.sound_play("doors_door_open", { pos = pos, gain = 0.3, max_hear_distance = 10 }, true) | 		minetest.sound_play("doors_door_open", {pos = pos, gain = 0.3, max_hear_distance = 10}) | ||||||
| 		minetest.set_node(pos, {name="doors:trapdoor_open", param2 = node.param2}) | 		minetest.set_node(pos, {name="doors:trapdoor_open", param2 = node.param2}) | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	minetest.get_meta(pos):set_int("state", state == 1 and 0 or 1) | 	minetest.get_meta(pos):set_int("state", state == 1 and 0 or 1) | ||||||
| end | end | ||||||
|  |  | ||||||
| if doors and doors.get then | minetest.override_item("doors:trapdoor", { | ||||||
| 	local override = { | 	mesecons = {effector = { | ||||||
| 		mesecons = {effector = { | 		action_on = trapdoor_switch, | ||||||
| 			action_on = function(pos, node) | 		action_off = trapdoor_switch | ||||||
| 				local door = doors.get(pos) | 	}}, | ||||||
| 				if door then | }) | ||||||
| 					door:open() |  | ||||||
| 				end |  | ||||||
| 			end, |  | ||||||
| 			action_off = function(pos, node) |  | ||||||
| 				local door = doors.get(pos) |  | ||||||
| 				if door then |  | ||||||
| 					door:close() |  | ||||||
| 				end |  | ||||||
| 			end, |  | ||||||
| 		}}, |  | ||||||
| 	} |  | ||||||
| 	minetest.override_item("doors:trapdoor", override) |  | ||||||
| 	minetest.override_item("doors:trapdoor_open", override) |  | ||||||
| 	minetest.override_item("doors:trapdoor_steel", override) |  | ||||||
| 	minetest.override_item("doors:trapdoor_steel_open", override) |  | ||||||
|  |  | ||||||
| 	if minetest.registered_items["xpanes:trapdoor_steel_bar"] then | minetest.override_item("doors:trapdoor_open", { | ||||||
| 		minetest.override_item("xpanes:trapdoor_steel_bar", override) | 	mesecons = {effector = { | ||||||
| 		minetest.override_item("xpanes:trapdoor_steel_bar_open", override) | 		action_on = trapdoor_switch, | ||||||
| 	end | 		action_off = trapdoor_switch | ||||||
|  | 	}}, | ||||||
| else | }) | ||||||
| 	if minetest.registered_nodes["doors:trapdoor"] then |  | ||||||
| 		minetest.override_item("doors:trapdoor", { |  | ||||||
| 			mesecons = {effector = { |  | ||||||
| 				action_on = trapdoor_switch, |  | ||||||
| 				action_off = trapdoor_switch |  | ||||||
| 			}}, |  | ||||||
| 		}) |  | ||||||
|  |  | ||||||
| 		minetest.override_item("doors:trapdoor_open", { |  | ||||||
| 			mesecons = {effector = { |  | ||||||
| 				action_on = trapdoor_switch, |  | ||||||
| 				action_off = trapdoor_switch |  | ||||||
| 			}}, |  | ||||||
| 		}) |  | ||||||
| 	end |  | ||||||
| end |  | ||||||
|   | |||||||
| @@ -1,3 +0,0 @@ | |||||||
| name = mesecons_doors |  | ||||||
| depends = mesecons, doors |  | ||||||
| optional_depends = xpanes |  | ||||||
| @@ -1,12 +1,16 @@ | |||||||
| local screwdriver_exists = minetest.global_exists("screwdriver") | local corner_nodebox = { | ||||||
|  | 	type = "fixed", | ||||||
|  | 	fixed = {{ -16/32-0.001, -17/32, -3/32, 0, -13/32, 3/32 }, | ||||||
|  | 		   { -3/32, -17/32, -16/32+0.001, 3/32, -13/32, 3/32}} | ||||||
|  | } | ||||||
|  |  | ||||||
| local corner_selectionbox = { | local corner_selectionbox = { | ||||||
| 		type = "fixed", | 		type = "fixed", | ||||||
| 		fixed = { -16/32, -16/32, -16/32, 5/32, -12/32, 5/32 }, | 		fixed = { -16/32-0.001, -18/32, -16/32, 5/32, -12/32, 5/32 }, | ||||||
| } | } | ||||||
|  |  | ||||||
| local corner_get_rules = function (node) | local corner_get_rules = function (node) | ||||||
| 	local rules = | 	local rules =  | ||||||
| 	{{x = 1,  y = 0,  z =  0}, | 	{{x = 1,  y = 0,  z =  0}, | ||||||
| 	 {x = 0,  y = 0,  z = -1}} | 	 {x = 0,  y = 0,  z = -1}} | ||||||
|  |  | ||||||
| @@ -18,61 +22,62 @@ local corner_get_rules = function (node) | |||||||
| end | end | ||||||
|  |  | ||||||
| minetest.register_node("mesecons_extrawires:corner_on", { | minetest.register_node("mesecons_extrawires:corner_on", { | ||||||
| 	drawtype = "mesh", | 	drawtype = "nodebox", | ||||||
| 	mesh = "mesecons_extrawires_corner.obj", |  | ||||||
| 	tiles = { | 	tiles = { | ||||||
| 		{ name = "jeija_insulated_wire_sides_on.png", backface_culling = true }, | 		"jeija_insulated_wire_curved_tb_on.png", | ||||||
| 		{ name = "jeija_insulated_wire_ends_on.png", backface_culling = true }, | 		"jeija_insulated_wire_curved_tb_on.png^[transformR270", | ||||||
|  | 		"jeija_insulated_wire_sides_on.png", | ||||||
|  | 		"jeija_insulated_wire_ends_on.png", | ||||||
|  | 		"jeija_insulated_wire_sides_on.png", | ||||||
|  | 		"jeija_insulated_wire_ends_on.png" | ||||||
| 	}, | 	}, | ||||||
| 	paramtype = "light", | 	paramtype = "light", | ||||||
| 	paramtype2 = "facedir", | 	paramtype2 = "facedir", | ||||||
| 	is_ground_content = false, |  | ||||||
| 	walkable = false, | 	walkable = false, | ||||||
| 	sunlight_propagates = true, | 	sunlight_propagates = true, | ||||||
| 	selection_box = corner_selectionbox, | 	selection_box = corner_selectionbox, | ||||||
|  | 	node_box = corner_nodebox, | ||||||
| 	groups = {dig_immediate = 3, not_in_creative_inventory = 1}, | 	groups = {dig_immediate = 3, not_in_creative_inventory = 1}, | ||||||
| 	drop = "mesecons_extrawires:corner_off", | 	drop = "mesecons_extrawires:corner_off", | ||||||
| 	sounds = default.node_sound_defaults(), | 	mesecons = {conductor =  | ||||||
| 	mesecons = {conductor = |  | ||||||
| 	{ | 	{ | ||||||
| 		state = mesecon.state.on, | 		state = mesecon.state.on, | ||||||
| 		rules = corner_get_rules, | 		rules = corner_get_rules, | ||||||
| 		offstate = "mesecons_extrawires:corner_off" | 		offstate = "mesecons_extrawires:corner_off" | ||||||
| 	}}, | 	}} | ||||||
| 	on_blast = mesecon.on_blastnode, |  | ||||||
| 	on_rotate = screwdriver_exists and screwdriver.rotate_simple, |  | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_node("mesecons_extrawires:corner_off", { | minetest.register_node("mesecons_extrawires:corner_off", { | ||||||
| 	drawtype = "mesh", | 	drawtype = "nodebox", | ||||||
| 	description = "Insulated Mesecon Corner", | 	description = "Mesecon Corner", | ||||||
| 	mesh = "mesecons_extrawires_corner.obj", |  | ||||||
| 	tiles = { | 	tiles = { | ||||||
| 		{ name = "jeija_insulated_wire_sides_off.png", backface_culling = true }, | 		"jeija_insulated_wire_curved_tb_off.png", | ||||||
| 		{ name = "jeija_insulated_wire_ends_off.png", backface_culling = true }, | 		"jeija_insulated_wire_curved_tb_off.png^[transformR270", | ||||||
|  | 		"jeija_insulated_wire_sides_off.png", | ||||||
|  | 		"jeija_insulated_wire_ends_off.png", | ||||||
|  | 		"jeija_insulated_wire_sides_off.png", | ||||||
|  | 		"jeija_insulated_wire_ends_off.png" | ||||||
| 	}, | 	}, | ||||||
| 	paramtype = "light", | 	paramtype = "light", | ||||||
| 	paramtype2 = "facedir", | 	paramtype2 = "facedir", | ||||||
| 	is_ground_content = false, |  | ||||||
| 	walkable = false, | 	walkable = false, | ||||||
| 	sunlight_propagates = true, | 	sunlight_propagates = true, | ||||||
| 	selection_box = corner_selectionbox, | 	selection_box = corner_selectionbox, | ||||||
|  | 	node_box = corner_nodebox, | ||||||
| 	groups = {dig_immediate = 3}, | 	groups = {dig_immediate = 3}, | ||||||
| 	sounds = default.node_sound_defaults(), | 	mesecons = {conductor =  | ||||||
| 	mesecons = {conductor = |  | ||||||
| 	{ | 	{ | ||||||
| 		state = mesecon.state.off, | 		state = mesecon.state.off, | ||||||
| 		rules = corner_get_rules, | 		rules = corner_get_rules, | ||||||
| 		onstate = "mesecons_extrawires:corner_on" | 		onstate = "mesecons_extrawires:corner_on" | ||||||
| 	}}, | 	}} | ||||||
| 	on_blast = mesecon.on_blastnode, |  | ||||||
| 	on_rotate = screwdriver_exists and screwdriver.rotate_simple, |  | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_craft({ | minetest.register_craft({ | ||||||
| 	output = "mesecons_extrawires:corner_off 3", | 	output = "mesecons_extrawires:corner_off 3", | ||||||
| 	recipe = { | 	recipe = { | ||||||
| 		{"mesecons_insulated:insulated_off", "mesecons_insulated:insulated_off"}, | 		{"", "", ""}, | ||||||
| 		{"", "mesecons_insulated:insulated_off"}, | 		{"mesecons_insulated:insulated_off", "mesecons_insulated:insulated_off", ""}, | ||||||
|  | 		{"", "mesecons_insulated:insulated_off", ""}, | ||||||
| 	} | 	} | ||||||
| }) | }) | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| local function crossover_get_rules(node) | function crossover_get_rules(node) | ||||||
| 	return { | 	return { | ||||||
| 		{--first wire | 		{--first wire | ||||||
| 			{x=-1,y=0,z=0}, | 			{x=-1,y=0,z=0}, | ||||||
| @@ -19,110 +19,143 @@ local crossover_states = { | |||||||
| } | } | ||||||
|  |  | ||||||
| minetest.register_node("mesecons_extrawires:crossover_off", { | minetest.register_node("mesecons_extrawires:crossover_off", { | ||||||
| 	description = "Insulated Mesecon Crossover", | 	description = "Insulated Crossover", | ||||||
| 	drawtype = "mesh", | 	drawtype = "nodebox", | ||||||
| 	mesh = "mesecons_extrawires_crossover.b3d", |  | ||||||
| 	tiles = { | 	tiles = { | ||||||
| 		"jeija_insulated_wire_ends_off.png", | 		"jeija_insulated_wire_crossing_tb_off.png", | ||||||
| 		"jeija_insulated_wire_sides_off.png", | 		"jeija_insulated_wire_crossing_tb_off.png", | ||||||
| 		"jeija_insulated_wire_sides_off.png", |  | ||||||
| 		"jeija_insulated_wire_ends_off.png" | 		"jeija_insulated_wire_ends_off.png" | ||||||
| 	}, | 	}, | ||||||
| 	paramtype = "light", | 	paramtype = "light", | ||||||
| 	is_ground_content = false, |  | ||||||
| 	walkable = false, | 	walkable = false, | ||||||
| 	stack_max = 99, | 	stack_max = 99, | ||||||
| 	selection_box = {type="fixed", fixed={-16/32, -16/32, -16/32, 16/32, -5/32, 16/32}}, | 	selection_box = {type="fixed", fixed={-16/32-0.0001, -18/32, -16/32-0.001, 16/32+0.001, -5/32, 16/32+0.001}}, | ||||||
| 	groups = {dig_immediate=3, mesecon=3}, | 	node_box = { | ||||||
| 	sounds = default.node_sound_defaults(), | 		type = "fixed", | ||||||
|  | 		fixed = { | ||||||
|  | 			{ -16/32-0.001, -17/32, -3/32, 16/32+0.001, -13/32, 3/32 }, | ||||||
|  | 			{ -3/32, -17/32, -16/32-0.001, 3/32, -13/32, -6/32 }, | ||||||
|  | 			{ -3/32, -13/32, -9/32, 3/32, -6/32, -6/32 }, | ||||||
|  | 			{ -3/32, -9/32, -9/32, 3/32, -6/32, 9/32 }, | ||||||
|  | 			{ -3/32, -13/32, 6/32, 3/32, -6/32, 9/32 }, | ||||||
|  | 			{ -3/32, -17/32, 6/32, 3/32, -13/32, 16/32+0.001 }, | ||||||
|  | 		}, | ||||||
|  | 	}, | ||||||
|  | 	groups = {dig_immediate=3, mesecon=3, mesecon_conductor_craftable=1}, | ||||||
| 	mesecons = { | 	mesecons = { | ||||||
| 		conductor = { | 		conductor = { | ||||||
| 			states = crossover_states, | 			states = crossover_states, | ||||||
| 			rules = crossover_get_rules(), | 			rules = crossover_get_rules(), | ||||||
| 		} | 		} | ||||||
| 	}, | 	}, | ||||||
| 	on_blast = mesecon.on_blastnode, |  | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_node("mesecons_extrawires:crossover_01", { | minetest.register_node("mesecons_extrawires:crossover_01", { | ||||||
| 	description = "You hacker you!", | 	description = "You hacker you!", | ||||||
| 	drop = "mesecons_extrawires:crossover_off", | 	drop = "mesecons_extrawires:crossover_off", | ||||||
| 	drawtype = "mesh", | 	drawtype = "nodebox", | ||||||
| 	mesh = "mesecons_extrawires_crossover.b3d", |  | ||||||
| 	tiles = { | 	tiles = { | ||||||
| 		"jeija_insulated_wire_ends_on.png", | 		"jeija_insulated_wire_crossing_tb_01.png", | ||||||
| 		"jeija_insulated_wire_sides_on.png", | 		"jeija_insulated_wire_crossing_tb_01.png", | ||||||
| 		"jeija_insulated_wire_sides_off.png", | 		"jeija_insulated_wire_ends_01x.png", | ||||||
| 		"jeija_insulated_wire_ends_off.png" | 		"jeija_insulated_wire_ends_01x.png", | ||||||
|  | 		"jeija_insulated_wire_ends_01z.png", | ||||||
|  | 		"jeija_insulated_wire_ends_01z.png" | ||||||
| 	}, | 	}, | ||||||
| 	paramtype = "light", | 	paramtype = "light", | ||||||
| 	is_ground_content = false, |  | ||||||
| 	walkable = false, | 	walkable = false, | ||||||
| 	stack_max = 99, | 	stack_max = 99, | ||||||
| 	selection_box = {type="fixed", fixed={-16/32, -16/32, -16/32, 16/32, -5/32, 16/32}}, | 	selection_box = {type="fixed", fixed={-16/32-0.0001, -18/32, -16/32-0.001, 16/32+0.001, -5/32, 16/32+0.001}}, | ||||||
|  | 	node_box = { | ||||||
|  | 		type = "fixed", | ||||||
|  | 		fixed = { | ||||||
|  | 			{ -16/32-0.001, -17/32, -3/32, 16/32+0.001, -13/32, 3/32 }, | ||||||
|  | 			{ -3/32, -17/32, -16/32-0.001, 3/32, -13/32, -6/32 }, | ||||||
|  | 			{ -3/32, -13/32, -9/32, 3/32, -6/32, -6/32 }, | ||||||
|  | 			{ -3/32, -9/32, -9/32, 3/32, -6/32, 9/32 }, | ||||||
|  | 			{ -3/32, -13/32, 6/32, 3/32, -6/32, 9/32 }, | ||||||
|  | 			{ -3/32, -17/32, 6/32, 3/32, -13/32, 16/32+0.001 }, | ||||||
|  | 		}, | ||||||
|  | 	}, | ||||||
| 	groups = {dig_immediate=3, mesecon=3, not_in_creative_inventory=1}, | 	groups = {dig_immediate=3, mesecon=3, not_in_creative_inventory=1}, | ||||||
| 	sounds = default.node_sound_defaults(), |  | ||||||
| 	mesecons = { | 	mesecons = { | ||||||
| 		conductor = { | 		conductor = { | ||||||
| 			states = crossover_states, | 			states = crossover_states, | ||||||
| 			rules = crossover_get_rules(), | 			rules = crossover_get_rules(), | ||||||
| 		} | 		} | ||||||
| 	}, | 	}, | ||||||
| 	on_blast = mesecon.on_blastnode, |  | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_node("mesecons_extrawires:crossover_10", { | minetest.register_node("mesecons_extrawires:crossover_10", { | ||||||
| 	description = "You hacker you!", | 	description = "You hacker you!", | ||||||
| 	drop = "mesecons_extrawires:crossover_off", | 	drop = "mesecons_extrawires:crossover_off", | ||||||
| 	drawtype = "mesh", | 	drawtype = "nodebox", | ||||||
| 	mesh = "mesecons_extrawires_crossover.b3d", |  | ||||||
| 	tiles = { | 	tiles = { | ||||||
| 		"jeija_insulated_wire_ends_off.png", | 		"jeija_insulated_wire_crossing_tb_10.png", | ||||||
| 		"jeija_insulated_wire_sides_off.png", | 		"jeija_insulated_wire_crossing_tb_10.png", | ||||||
| 		"jeija_insulated_wire_sides_on.png", | 		"jeija_insulated_wire_ends_10x.png", | ||||||
| 		"jeija_insulated_wire_ends_on.png" | 		"jeija_insulated_wire_ends_10x.png", | ||||||
|  | 		"jeija_insulated_wire_ends_10z.png", | ||||||
|  | 		"jeija_insulated_wire_ends_10z.png" | ||||||
| 	}, | 	}, | ||||||
| 	paramtype = "light", | 	paramtype = "light", | ||||||
| 	is_ground_content = false, |  | ||||||
| 	walkable = false, | 	walkable = false, | ||||||
| 	stack_max = 99, | 	stack_max = 99, | ||||||
| 	selection_box = {type="fixed", fixed={-16/32, -16/32, -16/32, 16/32, -5/32, 16/32}}, | 	selection_box = {type="fixed", fixed={-16/32-0.0001, -18/32, -16/32-0.001, 16/32+0.001, -5/32, 16/32+0.001}}, | ||||||
|  | 	node_box = { | ||||||
|  | 		type = "fixed", | ||||||
|  | 		fixed = { | ||||||
|  | 			{ -16/32-0.001, -17/32, -3/32, 16/32+0.001, -13/32, 3/32 }, | ||||||
|  | 			{ -3/32, -17/32, -16/32-0.001, 3/32, -13/32, -6/32 }, | ||||||
|  | 			{ -3/32, -13/32, -9/32, 3/32, -6/32, -6/32 }, | ||||||
|  | 			{ -3/32, -9/32, -9/32, 3/32, -6/32, 9/32 }, | ||||||
|  | 			{ -3/32, -13/32, 6/32, 3/32, -6/32, 9/32 }, | ||||||
|  | 			{ -3/32, -17/32, 6/32, 3/32, -13/32, 16/32+0.001 }, | ||||||
|  | 		}, | ||||||
|  | 	}, | ||||||
| 	groups = {dig_immediate=3, mesecon=3, not_in_creative_inventory=1}, | 	groups = {dig_immediate=3, mesecon=3, not_in_creative_inventory=1}, | ||||||
| 	sounds = default.node_sound_defaults(), |  | ||||||
| 	mesecons = { | 	mesecons = { | ||||||
| 		conductor = { | 		conductor = { | ||||||
| 			states = crossover_states, | 			states = crossover_states, | ||||||
| 			rules = crossover_get_rules(), | 			rules = crossover_get_rules(), | ||||||
| 		} | 		} | ||||||
| 	}, | 	}, | ||||||
| 	on_blast = mesecon.on_blastnode, |  | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_node("mesecons_extrawires:crossover_on", { | minetest.register_node("mesecons_extrawires:crossover_on", { | ||||||
| 	description = "You hacker you!", | 	description = "You hacker you!", | ||||||
| 	drop = "mesecons_extrawires:crossover_off", | 	drop = "mesecons_extrawires:crossover_off", | ||||||
| 	drawtype = "mesh", | 	drawtype = "nodebox", | ||||||
| 	mesh = "mesecons_extrawires_crossover.b3d", |  | ||||||
| 	tiles = { | 	tiles = { | ||||||
|  | 		"jeija_insulated_wire_crossing_tb_on.png", | ||||||
|  | 		"jeija_insulated_wire_crossing_tb_on.png", | ||||||
|  | 		"jeija_insulated_wire_ends_on.png", | ||||||
|  | 		"jeija_insulated_wire_ends_on.png", | ||||||
| 		"jeija_insulated_wire_ends_on.png", | 		"jeija_insulated_wire_ends_on.png", | ||||||
| 		"jeija_insulated_wire_sides_on.png", |  | ||||||
| 		"jeija_insulated_wire_sides_on.png", |  | ||||||
| 		"jeija_insulated_wire_ends_on.png" | 		"jeija_insulated_wire_ends_on.png" | ||||||
| 	}, | 	}, | ||||||
| 	paramtype = "light", | 	paramtype = "light", | ||||||
| 	is_ground_content = false, |  | ||||||
| 	walkable = false, | 	walkable = false, | ||||||
| 	stack_max = 99, | 	stack_max = 99, | ||||||
| 	selection_box = {type="fixed", fixed={-16/32, -16/32, -16/32, 16/32, -5/32, 16/32}}, | 	selection_box = {type="fixed", fixed={-16/32-0.0001, -18/32, -16/32-0.001, 16/32+0.001, -5/32, 16/32+0.001}}, | ||||||
|  | 	node_box = { | ||||||
|  | 		type = "fixed", | ||||||
|  | 		fixed = { | ||||||
|  | 			{ -16/32-0.001, -17/32, -3/32, 16/32+0.001, -13/32, 3/32 }, | ||||||
|  | 			{ -3/32, -17/32, -16/32-0.001, 3/32, -13/32, -6/32 }, | ||||||
|  | 			{ -3/32, -13/32, -9/32, 3/32, -6/32, -6/32 }, | ||||||
|  | 			{ -3/32, -9/32, -9/32, 3/32, -6/32, 9/32 }, | ||||||
|  | 			{ -3/32, -13/32, 6/32, 3/32, -6/32, 9/32 }, | ||||||
|  | 			{ -3/32, -17/32, 6/32, 3/32, -13/32, 16/32+0.001 }, | ||||||
|  | 		}, | ||||||
|  | 	}, | ||||||
| 	groups = {dig_immediate=3, mesecon=3, not_in_creative_inventory=1}, | 	groups = {dig_immediate=3, mesecon=3, not_in_creative_inventory=1}, | ||||||
| 	sounds = default.node_sound_defaults(), |  | ||||||
| 	mesecons = { | 	mesecons = { | ||||||
| 		conductor = { | 		conductor = { | ||||||
| 			states = crossover_states, | 			states = crossover_states, | ||||||
| 			rules = crossover_get_rules(), | 			rules = crossover_get_rules(), | ||||||
| 		} | 		} | ||||||
| 	}, | 	}, | ||||||
| 	on_blast = mesecon.on_blastnode, |  | ||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_craft({ | minetest.register_craft({ | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								mesecons_extrawires/depends.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,2 @@ | |||||||
|  | default | ||||||
|  | mesecons | ||||||