Compare commits
	
		
			50 Commits
		
	
	
		
			v1.2.1
			...
			b91fe92d13
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| b91fe92d13 | |||
|  | e15c55c066 | ||
| 6a87290ead | |||
|  | db5879706d | ||
| 1963bfcc0d | |||
|  | 65793514fe | ||
| 6936c8c2e4 | |||
|  | f5c3f798be | ||
|  | 69d4a9584d | ||
|  | 3f75c06a3b | ||
| 2fc1682c04 | |||
|  | 93aa24dc42 | ||
|  | 93f155f604 | ||
| 9b835053c2 | |||
|  | 583d2c1441 | ||
|  | 397d449f1e | ||
|  | 29ec26a4c8 | ||
|  | 0d86f2c45e | ||
|  | d356f901a3 | ||
|  | 6921909100 | ||
|  | 3202bf6786 | ||
|  | fedbf49372 | ||
|  | 9fda51b650 | ||
|  | 4750925eab | ||
|  | 16836b16d6 | ||
|  | c1eccba247 | ||
|  | 01332a7ba1 | ||
|  | de4eeebd3b | ||
|  | 75bd1e8be6 | ||
|  | 95e6e2e4a5 | ||
|  | 168a923665 | ||
|  | 8dec053996 | ||
|  | e1cffdedbf | ||
|  | d3aedd2b98 | ||
|  | 68c1729990 | ||
|  | 9b58f8db29 | ||
|  | 7784b13da5 | ||
|  | 0dd530312b | ||
|  | e78bbd6f98 | ||
|  | bfd952b51a | ||
|  | b7873e8e02 | ||
|  | d6b2a39c99 | ||
|  | 1b54011b68 | ||
|  | 15e743629e | ||
|  | 1bf862f932 | ||
|  | 1a9704f184 | ||
|  | 8baa789eb1 | ||
|  | b0158f5674 | ||
|  | 073c92d487 | ||
|  | 737f366741 | 
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						| @@ -1 +1,3 @@ | |||||||
| *~ | *~ | ||||||
|  | *.patch | ||||||
|  | *.diff | ||||||
|   | |||||||
| @@ -1,96 +1,140 @@ | |||||||
| mesecon.queue.actions={} -- contains all ActionQueue actions | --[[ | ||||||
|  | Mesecons uses something it calls an ActionQueue. | ||||||
|  |  | ||||||
| function mesecon.queue:add_function(name, func) | The ActionQueue holds functions and actions. | ||||||
| 	mesecon.queue.funcs[name] = func | Functions are added on load time with a specified name. | ||||||
|  | Actions are preserved over server restarts. | ||||||
|  |  | ||||||
|  | Each action consists of a position, the name of an added function to be called, | ||||||
|  | the params that should be used in this function call (additionally to the pos), | ||||||
|  | the time after which it should be executed, an optional overwritecheck and a | ||||||
|  | priority. | ||||||
|  |  | ||||||
|  | If time = 0, the action will be executed in the next globalstep, otherwise the | ||||||
|  | earliest globalstep when it will be executed is the after next globalstep. | ||||||
|  |  | ||||||
|  | It is guaranteed, that for two actions ac1, ac2 where ac1 ~= ac2, | ||||||
|  | ac1.time == ac2.time, ac1.priority == ac2.priority and ac1 was added earlier | ||||||
|  | than ac2, ac1 will be executed before ac2 (but in the same globalstep). | ||||||
|  |  | ||||||
|  | Note: Do not pass references in params, as they can not be preserved. | ||||||
|  |  | ||||||
|  | Also note: Some of the guarantees here might be dropped at some time. | ||||||
|  | ]] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | -- localize for speed | ||||||
|  | local queue = mesecon.queue | ||||||
|  |  | ||||||
|  | queue.actions = {} -- contains all ActionQueue actions | ||||||
|  |  | ||||||
|  | function queue:add_function(name, func) | ||||||
|  | 	queue.funcs[name] = func | ||||||
| end | end | ||||||
|  |  | ||||||
| -- If add_action with twice the same overwritecheck and same position are called, the first one is overwritten | -- If add_action with twice the same overwritecheck and same position are called, the first one is overwritten | ||||||
| -- use overwritecheck nil to never overwrite, but just add the event to the queue | -- use overwritecheck nil to never overwrite, but just add the event to the queue | ||||||
| -- priority specifies the order actions are executed within one globalstep, highest first | -- priority specifies the order actions are executed within one globalstep, highest first | ||||||
| -- should be between 0 and 1 | -- should be between 0 and 1 | ||||||
| function mesecon.queue:add_action(pos, func, params, time, overwritecheck, priority) | function queue:add_action(pos, func, params, time, overwritecheck, priority) | ||||||
| 	-- Create Action Table: | 	-- Create Action Table: | ||||||
| 	time = time or 0 -- time <= 0 --> execute, time > 0 --> wait time until execution | 	time = time or 0 -- time <= 0 --> execute, time > 0 --> wait time until execution | ||||||
| 	priority = priority or 1 | 	priority = priority or 1 | ||||||
| 	local action = {	pos=mesecon.tablecopy(pos), | 	local action = { | ||||||
| 				func=func, | 		pos = mesecon.tablecopy(pos), | ||||||
| 				params=mesecon.tablecopy(params or {}), | 		func = func, | ||||||
| 				time=time, | 		params = mesecon.tablecopy(params or {}), | ||||||
| 				owcheck=(overwritecheck and mesecon.tablecopy(overwritecheck)) or nil, | 		time = time, | ||||||
| 				priority=priority} | 		owcheck = (overwritecheck and mesecon.tablecopy(overwritecheck)) or nil, | ||||||
|  | 		priority = priority | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	local toremove = nil | 	 -- check if old action has to be overwritten / removed: | ||||||
| 	-- Otherwise, add the action to the queue | 	if overwritecheck then | ||||||
| 	if overwritecheck then -- check if old action has to be overwritten / removed: | 		for i, ac in ipairs(queue.actions) do | ||||||
| 		for i, ac in ipairs(mesecon.queue.actions) do | 			if vector.equals(pos, ac.pos) | ||||||
| 			if(vector.equals(pos, ac.pos) | 					and mesecon.cmpAny(overwritecheck, ac.owcheck) then | ||||||
| 			and mesecon.cmpAny(overwritecheck, ac.owcheck)) then | 				-- remove the old action | ||||||
| 				toremove = i | 				table.remove(queue.actions, i) | ||||||
| 				break | 				break | ||||||
| 			end | 			end | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	if (toremove ~= nil) then | 	table.insert(queue.actions, action) | ||||||
| 		table.remove(mesecon.queue.actions, toremove) |  | ||||||
| 	end |  | ||||||
|  |  | ||||||
| 	table.insert(mesecon.queue.actions, action) |  | ||||||
| end | end | ||||||
|  |  | ||||||
| -- execute the stored functions on a globalstep | -- execute the stored functions on a globalstep | ||||||
| -- if however, the pos of a function is not loaded (get_node_or_nil == nil), do NOT execute the function | -- if however, the pos of a function is not loaded (get_node_or_nil == nil), do NOT execute the function | ||||||
| -- this makes sure that resuming mesecons circuits when restarting minetest works fine | -- this makes sure that resuming mesecons circuits when restarting minetest works fine (hm, where do we do this?) | ||||||
| -- However, even that does not work in some cases, that's why we delay the time the globalsteps | -- However, even that does not work in some cases, that's why we delay the time the globalsteps | ||||||
| -- start to be execute by 5 seconds | -- start to be execute by 4 seconds | ||||||
| local get_highest_priority = function (actions) |  | ||||||
| 	local highestp = -1 |  | ||||||
| 	local highesti |  | ||||||
| 	for i, ac in ipairs(actions) do |  | ||||||
| 		if ac.priority > highestp then |  | ||||||
| 			highestp = ac.priority |  | ||||||
| 			highesti = i |  | ||||||
| 		end |  | ||||||
| 	end |  | ||||||
|  |  | ||||||
| 	return highesti | local function globalstep_func(dtime) | ||||||
| end | 	local actions = queue.actions | ||||||
|  | 	-- split into two categories: | ||||||
|  | 	-- actions_now: actions to execute now | ||||||
|  | 	-- queue.actions: actions to execute later | ||||||
|  | 	local actions_now = {} | ||||||
|  | 	queue.actions = {} | ||||||
|  |  | ||||||
| local m_time = 0 | 	for _, ac in ipairs(actions) do | ||||||
| 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 | ||||||
| 			ac.time = ac.time - dtime -- executed later | 			-- action ac is to be executed later | ||||||
| 			table.insert(mesecon.queue.actions, ac) | 			-- ~> insert into queue.actions | ||||||
|  | 			ac.time = ac.time - dtime | ||||||
|  | 			table.insert(queue.actions, ac) | ||||||
| 		else | 		else | ||||||
|  | 			-- action ac is to be executed now | ||||||
|  | 			-- ~> insert into actions_now | ||||||
| 			table.insert(actions_now, ac) | 			table.insert(actions_now, ac) | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| 	while(#actions_now > 0) do -- execute highest priorities first, until all are executed | 	-- stable-sort the executed actions after their priority | ||||||
| 		local hp = get_highest_priority(actions_now) | 	-- some constructions might depend on the execution order, hence we first | ||||||
| 		mesecon.queue:execute(actions_now[hp]) | 	-- execute the actions that had a lower index in actions_now | ||||||
| 		table.remove(actions_now, hp) | 	local old_action_order = {} | ||||||
|  | 	for i, ac in ipairs(actions_now) do | ||||||
|  | 		old_action_order[ac] = i | ||||||
| 	end | 	end | ||||||
| end) | 	table.sort(actions_now, function(ac1, ac2) | ||||||
|  | 		if ac1.priority ~= ac2.priority then | ||||||
|  | 			return ac1.priority > ac2.priority | ||||||
|  | 		else | ||||||
|  | 			return old_action_order[ac1] < old_action_order[ac2] | ||||||
|  | 		end | ||||||
|  | 	end) | ||||||
|  |  | ||||||
| function mesecon.queue:execute(action) | 	-- execute highest priorities first, until all are executed | ||||||
|  | 	for _, ac in ipairs(actions_now) do | ||||||
|  | 		queue:execute(ac) | ||||||
|  | 	end | ||||||
|  | end | ||||||
|  |  | ||||||
|  | -- delay the time the globalsteps start to be execute by 4 seconds | ||||||
|  | do | ||||||
|  | 	local m_time = 0 | ||||||
|  | 	local resumetime = mesecon.setting("resumetime", 4) | ||||||
|  | 	local globalstep_func_index = #minetest.registered_globalsteps + 1 | ||||||
|  |  | ||||||
|  | 	minetest.register_globalstep(function(dtime) | ||||||
|  | 		m_time = m_time + dtime | ||||||
|  | 		-- don't even try if server has not been running for XY seconds; resumetime = time to wait | ||||||
|  | 		-- after starting the server before processing the ActionQueue, don't set this too low | ||||||
|  | 		if m_time < resumetime then | ||||||
|  | 			return | ||||||
|  | 		end | ||||||
|  | 		-- replace this globalstep function | ||||||
|  | 		minetest.registered_globalsteps[globalstep_func_index] = globalstep_func | ||||||
|  | 	end) | ||||||
|  | end | ||||||
|  |  | ||||||
|  | function queue:execute(action) | ||||||
| 	-- ignore if action queue function name doesn't exist, | 	-- ignore if action queue function name doesn't exist, | ||||||
| 	-- (e.g. in case the action queue savegame was written by an old mesecons version) | 	-- (e.g. in case the action queue savegame was written by an old mesecons version) | ||||||
| 	if mesecon.queue.funcs[action.func] then | 	if queue.funcs[action.func] then | ||||||
| 		mesecon.queue.funcs[action.func](action.pos, unpack(action.params)) | 		queue.funcs[action.func](action.pos, unpack(action.params)) | ||||||
| 	end | 	end | ||||||
| end | end | ||||||
|  |  | ||||||
| @@ -98,8 +142,8 @@ end | |||||||
| -- Store and read the ActionQueue to / from a file | -- Store and read the ActionQueue to / from a file | ||||||
| -- so that upcoming actions are remembered when the game | -- so that upcoming actions are remembered when the game | ||||||
| -- is restarted | -- is restarted | ||||||
| mesecon.queue.actions = mesecon.file2table("mesecon_actionqueue") | queue.actions = mesecon.file2table("mesecon_actionqueue") | ||||||
|  |  | ||||||
| minetest.register_on_shutdown(function() | minetest.register_on_shutdown(function() | ||||||
| 	mesecon.table2file("mesecon_actionqueue", mesecon.queue.actions) | 	mesecon.table2file("mesecon_actionqueue", queue.actions) | ||||||
| end) | end) | ||||||
|   | |||||||
| @@ -1 +0,0 @@ | |||||||
| default |  | ||||||
							
								
								
									
										62
									
								
								mesecons/fifo_queue.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,62 @@ | |||||||
|  |  | ||||||
|  | -- 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 | ||||||
| @@ -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) | ||||||
|  |  | ||||||
| @@ -46,6 +46,8 @@ | |||||||
| -- 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] | ||||||
| @@ -92,8 +94,8 @@ function mesecon.get_any_inputrules(node) | |||||||
| end | end | ||||||
|  |  | ||||||
| function mesecon.get_any_rules(node) | function mesecon.get_any_rules(node) | ||||||
| 	return mesecon.mergetable(mesecon.get_any_inputrules(node) or {}, | 	return mesecon.merge_rule_sets(mesecon.get_any_inputrules(node), | ||||||
| 		mesecon.get_any_outputrules(node) or {}) | 		mesecon.get_any_outputrules(node)) | ||||||
| end | end | ||||||
|  |  | ||||||
| -- Receptors | -- Receptors | ||||||
| @@ -371,32 +373,39 @@ end | |||||||
| -- Follow all all conductor paths replacing conductors that were already | -- Follow all all conductor paths replacing conductors that were already | ||||||
| -- looked at, activating / changing all effectors along the way. | -- looked at, activating / changing all effectors along the way. | ||||||
| function mesecon.turnon(pos, link) | function mesecon.turnon(pos, link) | ||||||
| 	local frontiers = {{pos = pos, link = link}} | 	local frontiers = fifo_queue.new() | ||||||
|  | 	frontiers:add({pos = pos, link = link}) | ||||||
|  | 	local pos_can_be_skipped = {} | ||||||
|  |  | ||||||
| 	local depth = 1 | 	local depth = 1 | ||||||
| 	while frontiers[1] do | 	for f in frontiers:iter() do | ||||||
| 		local f = table.remove(frontiers, 1) |  | ||||||
| 		local node = mesecon.get_node_force(f.pos) | 		local node = mesecon.get_node_force(f.pos) | ||||||
|  |  | ||||||
| 		if not node then | 		if not node then | ||||||
| 			-- Area does not exist; do nothing | 			-- Area does not exist; do nothing | ||||||
|  | 			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 | 			-- Call turnon on neighbors | ||||||
| 			for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do | 			for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do | ||||||
| 				local np = vector.add(f.pos, r) | 				local np = vector.add(f.pos, r) | ||||||
| 				for _, l in ipairs(mesecon.rules_link_rule_all(f.pos, r)) do | 				if not pos_can_be_skipped[minetest.hash_node_position(np)] then | ||||||
| 					table.insert(frontiers, {pos = np, link = l}) | 					for _, l in ipairs(mesecon.rules_link_rule_all(f.pos, r)) do | ||||||
|  | 						frontiers:add({pos = np, link = l}) | ||||||
|  | 					end | ||||||
| 				end | 				end | ||||||
| 			end | 			end | ||||||
|  |  | ||||||
| 			mesecon.swap_node_force(f.pos, mesecon.get_conductor_on(node, f.link)) | 			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 | ||||||
| @@ -419,37 +428,42 @@ end | |||||||
| --	depth = indicates order in which signals wire fired, higher is later | --	depth = indicates order in which signals wire fired, higher is later | ||||||
| -- } | -- } | ||||||
| function mesecon.turnoff(pos, link) | function mesecon.turnoff(pos, link) | ||||||
| 	local frontiers = {{pos = pos, link = link}} | 	local frontiers = fifo_queue.new() | ||||||
|  | 	frontiers:add({pos = pos, link = link}) | ||||||
| 	local signals = {} | 	local signals = {} | ||||||
|  | 	local pos_can_be_skipped = {} | ||||||
|  |  | ||||||
| 	local depth = 1 | 	local depth = 1 | ||||||
| 	while frontiers[1] do | 	for f in frontiers:iter() do | ||||||
| 		local f = table.remove(frontiers, 1) |  | ||||||
| 		local node = mesecon.get_node_force(f.pos) | 		local node = mesecon.get_node_force(f.pos) | ||||||
|  |  | ||||||
| 		if not node then | 		if not node then | ||||||
| 			-- Area does not exist; do nothing | 			-- Area does not exist; do nothing | ||||||
|  | 			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) | ||||||
| 			for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do | 			for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do | ||||||
| 				local np = vector.add(f.pos, r) | 				local np = vector.add(f.pos, r) | ||||||
|  |  | ||||||
| 				-- Check if an onstate receptor is connected. If that is the case, | 				if not pos_can_be_skipped[minetest.hash_node_position(np)] then | ||||||
| 				-- abort this turnoff process by returning false. `receptor_off` will | 					-- Check if an onstate receptor is connected. If that is the case, | ||||||
| 				-- discard all the changes that we made in the voxelmanip: | 					-- abort this turnoff process by returning false. `receptor_off` will | ||||||
| 				for _, l in ipairs(mesecon.rules_link_rule_all_inverted(f.pos, r)) do | 					-- discard all the changes that we made in the voxelmanip: | ||||||
| 					if mesecon.is_receptor_on(mesecon.get_node_force(np).name) then | 					if mesecon.rules_link_rule_all_inverted(f.pos, r)[1] then | ||||||
| 						return false | 						if mesecon.is_receptor_on(mesecon.get_node_force(np).name) then | ||||||
|  | 							return false | ||||||
|  | 						end | ||||||
| 					end | 					end | ||||||
| 				end |  | ||||||
|  |  | ||||||
| 				-- Call turnoff on neighbors | 					-- Call turnoff on neighbors | ||||||
| 				for _, l in ipairs(mesecon.rules_link_rule_all(f.pos, r)) do | 					for _, l in ipairs(mesecon.rules_link_rule_all(f.pos, r)) do | ||||||
| 					table.insert(frontiers, {pos = np, link = l}) | 						frontiers:add({pos = np, link = l}) | ||||||
|  | 					end | ||||||
| 				end | 				end | ||||||
| 			end | 			end | ||||||
|  |  | ||||||
| 			mesecon.swap_node_force(f.pos, mesecon.get_conductor_off(node, f.link)) | 			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, { | 			table.insert(signals, { | ||||||
| 				pos = f.pos, | 				pos = f.pos, | ||||||
| @@ -457,6 +471,8 @@ function mesecon.turnoff(pos, link) | |||||||
| 				link = f.link, | 				link = f.link, | ||||||
| 				depth = depth | 				depth = depth | ||||||
| 			}) | 			}) | ||||||
|  | 		else | ||||||
|  | 			pos_can_be_skipped[minetest.hash_node_position(f.pos)] = true | ||||||
| 		end | 		end | ||||||
| 		depth = depth + 1 | 		depth = depth + 1 | ||||||
| 	end | 	end | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								mesecons/mod.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,2 @@ | |||||||
|  | name = mesecons | ||||||
|  | depends = default | ||||||
| @@ -16,9 +16,9 @@ mesecon.rules.default = { | |||||||
| 	{x =  0, y = -1, z = -1}, | 	{x =  0, y = -1, z = -1}, | ||||||
| } | } | ||||||
|  |  | ||||||
| mesecon.rules.floor = mesecon.mergetable(mesecon.rules.default, {{x = 0, y = -1, z = 0}}) | mesecon.rules.floor = mesecon.merge_rule_sets(mesecon.rules.default, {{x = 0, y = -1, z = 0}}) | ||||||
|  |  | ||||||
| mesecon.rules.pplate = mesecon.mergetable(mesecon.rules.floor, {{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 = { | mesecon.rules.buttonlike = { | ||||||
| 	{x = 1,  y =  0, z =  0}, | 	{x = 1,  y =  0, z =  0}, | ||||||
|   | |||||||
| @@ -16,7 +16,7 @@ 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 = vector.subtract(s, pos) | ||||||
| 				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)) | ||||||
|   | |||||||
| Before Width: | Height: | Size: 323 B After Width: | Height: | Size: 191 B | 
| Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 844 B | 
| Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 838 B | 
| Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 851 B | 
| Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 846 B | 
| Before Width: | Height: | Size: 550 B After Width: | Height: | Size: 222 B | 
| Before Width: | Height: | Size: 613 B After Width: | Height: | Size: 504 B | 
| Before Width: | Height: | Size: 204 B After Width: | Height: | Size: 144 B | 
| Before Width: | Height: | Size: 465 B After Width: | Height: | Size: 377 B | 
| Before Width: | Height: | Size: 464 B After Width: | Height: | Size: 362 B | 
| @@ -164,7 +164,9 @@ end | |||||||
|  |  | ||||||
| function mesecon.get_bit(binary,bit) | function mesecon.get_bit(binary,bit) | ||||||
| 	bit = bit or 1 | 	bit = bit or 1 | ||||||
| 	local c = binary:len()-(bit-1) | 	local len = binary:len() | ||||||
|  | 	if bit > len then return false end | ||||||
|  | 	local c = len-(bit-1) | ||||||
| 	return binary:sub(c,c) == "1" | 	return binary:sub(c,c) == "1" | ||||||
| end | end | ||||||
|  |  | ||||||
| @@ -186,34 +188,36 @@ function mesecon.invertRule(r) | |||||||
| 	return vector.multiply(r, -1) | 	return vector.multiply(r, -1) | ||||||
| end | end | ||||||
|  |  | ||||||
| function mesecon.tablecopy(table) -- deep table copy | function mesecon.tablecopy(obj) -- deep copy | ||||||
| 	if type(table) ~= "table" then return table end -- no need to copy | 	if type(obj) == "table" then | ||||||
| 	local newtable = {} | 		return table.copy(obj) | ||||||
|  |  | ||||||
| 	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" and type(t2) ~= "table" then return t1 == t2 end | 	if type(t1) ~= "table" then return t1 == t2 end | ||||||
|  |  | ||||||
|  | 	-- Check that for each key of `t1` both tables have the same value | ||||||
| 	for i, e in pairs(t1) do | 	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 | ||||||
|  |  | ||||||
| -- does not overwrite values; number keys (ipairs) are appended, not overwritten | -- Deprecated. Use `merge_tables` or `merge_rule_sets` as appropriate. | ||||||
| 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 | ||||||
| @@ -226,6 +230,32 @@ 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.on_blast = spec_common.on_blast or mesecon.on_blastnode | ||||||
| @@ -233,8 +263,8 @@ function mesecon.register_node(name, spec_common, spec_off, spec_on) | |||||||
| 	spec_on.__mesecon_state = "on" | 	spec_on.__mesecon_state = "on" | ||||||
| 	spec_off.__mesecon_state = "off" | 	spec_off.__mesecon_state = "off" | ||||||
|  |  | ||||||
| 	spec_on = mesecon.mergetable(spec_common, spec_on); | 	spec_on = mesecon.merge_tables(spec_common, spec_on); | ||||||
| 	spec_off = mesecon.mergetable(spec_common, spec_off); | 	spec_off = mesecon.merge_tables(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) | ||||||
|   | |||||||
| @@ -1 +0,0 @@ | |||||||
| mesecons |  | ||||||
							
								
								
									
										2
									
								
								mesecons_alias/mod.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,2 @@ | |||||||
|  | name = mesecons_alias | ||||||
|  | depends = mesecons | ||||||
| @@ -1 +0,0 @@ | |||||||
| mesecons |  | ||||||
							
								
								
									
										
											BIN
										
									
								
								mesecons_blinkyplant/doc/blinkyplant/preview.png
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						| Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 54 KiB | 
| Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 1.7 KiB | 
| @@ -32,7 +32,13 @@ 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 = toggle_timer, | 	on_rightclick = function(pos, node, clicker) | ||||||
|  | 		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"}, | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								mesecons_blinkyplant/mod.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,2 @@ | |||||||
|  | name = mesecons_blinkyplant | ||||||
|  | depends = mesecons | ||||||
| Before Width: | Height: | Size: 454 B After Width: | Height: | Size: 367 B | 
| Before Width: | Height: | Size: 463 B After Width: | Height: | Size: 394 B | 
| @@ -1,2 +0,0 @@ | |||||||
| mesecons |  | ||||||
| mesecons_receiver |  | ||||||
| Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 68 KiB | 
| Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 4.3 KiB | 
| @@ -8,21 +8,24 @@ mesecon.button_turnoff = function (pos) | |||||||
| 		return | 		return | ||||||
| 	end | 	end | ||||||
| 	minetest.swap_node(pos, {name = "mesecons_button:button_off", param2 = node.param2}) | 	minetest.swap_node(pos, {name = "mesecons_button:button_off", param2 = node.param2}) | ||||||
| 	minetest.sound_play("mesecons_button_pop", {pos = pos}) | 	minetest.sound_play("mesecons_button_pop", { pos = pos }, true) | ||||||
| 	local rules = mesecon.rules.buttonlike_get(node) | 	local rules = mesecon.rules.buttonlike_get(node) | ||||||
| 	mesecon.receptor_off(pos, rules) | 	mesecon.receptor_off(pos, rules) | ||||||
| end | end | ||||||
|  |  | ||||||
|  | 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, | 	is_ground_content = false, | ||||||
| @@ -46,7 +49,7 @@ minetest.register_node("mesecons_button:button_off", { | |||||||
| 	on_rightclick = function (pos, node) | 	on_rightclick = function (pos, node) | ||||||
| 		minetest.swap_node(pos, {name = "mesecons_button:button_on", param2=node.param2}) | 		minetest.swap_node(pos, {name = "mesecons_button:button_on", param2=node.param2}) | ||||||
| 		mesecon.receptor_on(pos, mesecon.rules.buttonlike_get(node)) | 		mesecon.receptor_on(pos, mesecon.rules.buttonlike_get(node)) | ||||||
| 		minetest.sound_play("mesecons_button_push", {pos=pos}) | 		minetest.sound_play("mesecons_button_push", { pos = pos }, true) | ||||||
| 		minetest.get_node_timer(pos):start(1) | 		minetest.get_node_timer(pos):start(1) | ||||||
| 	end, | 	end, | ||||||
| 	sounds = default.node_sound_stone_defaults(), | 	sounds = default.node_sound_stone_defaults(), | ||||||
| @@ -66,7 +69,8 @@ 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, | 	is_ground_content = false, | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								mesecons_button/mod.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,2 @@ | |||||||
|  | name = mesecons_button | ||||||
|  | depends = mesecons, mesecons_receiver | ||||||
| Before Width: | Height: | Size: 411 B After Width: | Height: | Size: 371 B | 
| Before Width: | Height: | Size: 449 B After Width: | Height: | Size: 409 B | 
| Before Width: | Height: | Size: 434 B After Width: | Height: | Size: 220 B | 
| @@ -1 +0,0 @@ | |||||||
| mesecons |  | ||||||
| Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 33 KiB | 
| @@ -10,6 +10,7 @@ minetest.register_chatcommand("say", { | |||||||
| 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 | ||||||
| @@ -110,7 +111,7 @@ local function resolve_commands(commands, pos) | |||||||
| 	local nearest, farthest = nil, nil | 	local nearest, farthest = nil, nil | ||||||
| 	local min_distance, max_distance = math.huge, -1 | 	local min_distance, max_distance = math.huge, -1 | ||||||
| 	for index, player in pairs(players) do | 	for index, player in pairs(players) do | ||||||
| 		local distance = vector.distance(pos, player:getpos()) | 		local distance = vector.distance(pos, player:get_pos()) | ||||||
| 		if distance < min_distance then | 		if distance < min_distance then | ||||||
| 			min_distance = distance | 			min_distance = distance | ||||||
| 			nearest = player:get_player_name() | 			nearest = player:get_player_name() | ||||||
| @@ -174,7 +175,8 @@ end | |||||||
| local function can_dig(pos, player) | local function can_dig(pos, player) | ||||||
| 	local meta = minetest.get_meta(pos) | 	local meta = minetest.get_meta(pos) | ||||||
| 	local owner = meta:get_string("owner") | 	local owner = meta:get_string("owner") | ||||||
| 	return owner == "" or owner == player:get_player_name() | 	return owner == "" or owner == player:get_player_name() or | ||||||
|  | 		minetest.check_player_privs(player, "protection_bypass") | ||||||
| end | end | ||||||
|  |  | ||||||
| minetest.register_node("mesecons_commandblock:commandblock_off", { | minetest.register_node("mesecons_commandblock:commandblock_off", { | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								mesecons_commandblock/mod.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,2 @@ | |||||||
|  | name = mesecons_commandblock | ||||||
|  | depends = mesecons | ||||||
| Before Width: | Height: | Size: 282 B After Width: | Height: | Size: 183 B | 
| Before Width: | Height: | Size: 278 B After Width: | Height: | Size: 183 B | 
| @@ -1 +0,0 @@ | |||||||
| mesecons |  | ||||||
| Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 50 KiB | 
| Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 4.2 KiB | 
| @@ -33,19 +33,9 @@ end | |||||||
|  |  | ||||||
| -- Register the 2 (states) x 4 (delay times) delayers | -- Register the 2 (states) x 4 (delay times) delayers | ||||||
|  |  | ||||||
| for i = 1, 4 do | local delaytime = { 0.1, 0.3, 0.5, 1.0 } | ||||||
| local groups = {} |  | ||||||
| if i == 1 then |  | ||||||
| 	groups = {bendy=2,snappy=1,dig_immediate=2} |  | ||||||
| else |  | ||||||
| 	groups = {bendy=2,snappy=1,dig_immediate=2, not_in_creative_inventory=1} |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local delaytime | for i = 1, 4 do | ||||||
| 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 |  | ||||||
|  |  | ||||||
| local boxes = { | local boxes = { | ||||||
| 	 { -6/16, -8/16, -6/16, 6/16, -7/16, 6/16 },		-- the main slab | 	 { -6/16, -8/16, -6/16, 6/16, -7/16, 6/16 },		-- the main slab | ||||||
| @@ -61,19 +51,10 @@ local boxes = { | |||||||
| 	 { 6/16, -8/16, -1/16, 8/16, -7/16, 1/16 } | 	 { 6/16, -8/16, -1/16, 8/16, -7/16, 1/16 } | ||||||
| } | } | ||||||
|  |  | ||||||
| minetest.register_node("mesecons_delayer:delayer_off_"..tostring(i), { | -- Delayer definition defaults | ||||||
| 	description = "Delayer", | local def = { | ||||||
| 	drawtype = "nodebox", | 	drawtype = "nodebox", | ||||||
| 	tiles = { | 	use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or nil, | ||||||
| 		"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", | ||||||
| @@ -83,26 +64,46 @@ minetest.register_node("mesecons_delayer:delayer_off_"..tostring(i), { | |||||||
| 		type = "fixed", | 		type = "fixed", | ||||||
| 		fixed = boxes | 		fixed = boxes | ||||||
| 	}, | 	}, | ||||||
| 	groups = groups, |  | ||||||
| 	paramtype = "light", | 	paramtype = "light", | ||||||
| 	paramtype2 = "facedir", | 	paramtype2 = "facedir", | ||||||
| 	sunlight_propagates = true, | 	sunlight_propagates = true, | ||||||
| 	is_ground_content = false, | 	is_ground_content = false, | ||||||
| 	drop = 'mesecons_delayer:delayer_off_1', | 	delayer_time = delaytime[i], | ||||||
| 	on_punch = function (pos, node) |  | ||||||
| 		if node.name=="mesecons_delayer:delayer_off_1" then |  | ||||||
| 			minetest.swap_node(pos, {name = "mesecons_delayer:delayer_off_2", param2=node.param2}) |  | ||||||
| 		elseif node.name=="mesecons_delayer:delayer_off_2" then |  | ||||||
| 			minetest.swap_node(pos, {name = "mesecons_delayer:delayer_off_3", param2=node.param2}) |  | ||||||
| 		elseif node.name=="mesecons_delayer:delayer_off_3" then |  | ||||||
| 			minetest.swap_node(pos, {name = "mesecons_delayer:delayer_off_4", param2=node.param2}) |  | ||||||
| 		elseif node.name=="mesecons_delayer:delayer_off_4" then |  | ||||||
| 			minetest.swap_node(pos, {name = "mesecons_delayer:delayer_off_1", param2=node.param2}) |  | ||||||
| 		end |  | ||||||
| 	end, |  | ||||||
| 	delayer_time = delaytime, |  | ||||||
| 	delayer_onstate = "mesecons_delayer:delayer_on_"..tostring(i), |  | ||||||
| 	sounds = default.node_sound_stone_defaults(), | 	sounds = default.node_sound_stone_defaults(), | ||||||
|  | 	on_blast = mesecon.on_blastnode, | ||||||
|  | 	drop = "mesecons_delayer:delayer_off_1", | ||||||
|  | } | ||||||
|  |  | ||||||
|  | -- Deactivated delayer definition defaults | ||||||
|  | local off_groups = {bendy=2,snappy=1,dig_immediate=2} | ||||||
|  | if i > 1 then | ||||||
|  | 	off_groups.not_in_creative_inventory = 1 | ||||||
|  | end | ||||||
|  |  | ||||||
|  | local off_state = { | ||||||
|  | 	description = "Delayer", | ||||||
|  | 	tiles = { | ||||||
|  | 		"mesecons_delayer_off_"..tostring(i)..".png", | ||||||
|  | 		"mesecons_delayer_bottom.png", | ||||||
|  | 		"mesecons_delayer_ends_off.png", | ||||||
|  | 		"mesecons_delayer_ends_off.png", | ||||||
|  | 		"mesecons_delayer_sides_off.png", | ||||||
|  | 		"mesecons_delayer_sides_off.png" | ||||||
|  | 	}, | ||||||
|  | 	inventory_image = "mesecons_delayer_off_1.png", | ||||||
|  | 	wield_image = "mesecons_delayer_off_1.png", | ||||||
|  | 	groups = off_groups, | ||||||
|  | 	on_punch = function(pos, node, puncher) | ||||||
|  | 		if minetest.is_protected(pos, puncher and puncher:get_player_name() or "") then | ||||||
|  | 			return | ||||||
|  | 		end | ||||||
|  |  | ||||||
|  | 		minetest.swap_node(pos, { | ||||||
|  | 			name = "mesecons_delayer:delayer_off_"..tostring(i % 4 + 1), | ||||||
|  | 			param2 = node.param2 | ||||||
|  | 		}) | ||||||
|  | 	end, | ||||||
|  | 	delayer_onstate = "mesecons_delayer:delayer_on_"..tostring(i), | ||||||
| 	mesecons = { | 	mesecons = { | ||||||
| 		receptor = | 		receptor = | ||||||
| 		{ | 		{ | ||||||
| @@ -115,13 +116,15 @@ minetest.register_node("mesecons_delayer:delayer_off_"..tostring(i), { | |||||||
| 			action_on = delayer_activate | 			action_on = delayer_activate | ||||||
| 		} | 		} | ||||||
| 	}, | 	}, | ||||||
| 	on_blast = mesecon.on_blastnode, | } | ||||||
| }) | for k, v in pairs(def) do | ||||||
|  | 	off_state[k] = off_state[k] or v | ||||||
|  | end | ||||||
|  | minetest.register_node("mesecons_delayer:delayer_off_"..tostring(i), off_state) | ||||||
|  |  | ||||||
|  | -- Activated delayer definition defaults | ||||||
| minetest.register_node("mesecons_delayer:delayer_on_"..tostring(i), { | local on_state = { | ||||||
| 	description = "You hacker you", | 	description = "You hacker you", | ||||||
| 	drawtype = "nodebox", |  | ||||||
| 	tiles = { | 	tiles = { | ||||||
| 		"mesecons_delayer_on_"..tostring(i)..".png", | 		"mesecons_delayer_on_"..tostring(i)..".png", | ||||||
| 		"mesecons_delayer_bottom.png", | 		"mesecons_delayer_bottom.png", | ||||||
| @@ -129,36 +132,19 @@ minetest.register_node("mesecons_delayer:delayer_on_"..tostring(i), { | |||||||
| 		"mesecons_delayer_ends_on.png", | 		"mesecons_delayer_ends_on.png", | ||||||
| 		"mesecons_delayer_sides_on.png", | 		"mesecons_delayer_sides_on.png", | ||||||
| 		"mesecons_delayer_sides_on.png" | 		"mesecons_delayer_sides_on.png" | ||||||
| 		}, |  | ||||||
| 	walkable = true, |  | ||||||
| 	selection_box = { |  | ||||||
| 		type = "fixed", |  | ||||||
| 		fixed = { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 }, |  | ||||||
| 	}, |  | ||||||
| 	node_box = { |  | ||||||
| 		type = "fixed", |  | ||||||
| 		fixed = boxes |  | ||||||
| 	}, | 	}, | ||||||
| 	groups = {bendy = 2, snappy = 1, dig_immediate = 2, not_in_creative_inventory = 1}, | 	groups = {bendy = 2, snappy = 1, dig_immediate = 2, not_in_creative_inventory = 1}, | ||||||
| 	paramtype = "light", | 	on_punch = function(pos, node, puncher) | ||||||
| 	paramtype2 = "facedir", | 		if minetest.is_protected(pos, puncher and puncher:get_player_name() or "") then | ||||||
| 	sunlight_propagates = true, | 			return | ||||||
| 	is_ground_content = false, |  | ||||||
| 	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), | ||||||
| 	sounds = default.node_sound_stone_defaults(), |  | ||||||
| 	mesecons = { | 	mesecons = { | ||||||
| 		receptor = | 		receptor = | ||||||
| 		{ | 		{ | ||||||
| @@ -171,8 +157,12 @@ minetest.register_node("mesecons_delayer:delayer_on_"..tostring(i), { | |||||||
| 			action_off = delayer_deactivate | 			action_off = delayer_deactivate | ||||||
| 		} | 		} | ||||||
| 	}, | 	}, | ||||||
| 	on_blast = mesecon.on_blastnode, | } | ||||||
| }) | for k, v in pairs(def) do | ||||||
|  | 	on_state[k] = on_state[k] or v | ||||||
|  | end | ||||||
|  | minetest.register_node("mesecons_delayer:delayer_on_"..tostring(i), on_state) | ||||||
|  |  | ||||||
| end | end | ||||||
|  |  | ||||||
| minetest.register_craft({ | minetest.register_craft({ | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								mesecons_delayer/mod.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,2 @@ | |||||||
|  | name = mesecons_delayer | ||||||
|  | depends = mesecons | ||||||
| Before Width: | Height: | Size: 438 B After Width: | Height: | Size: 221 B | 
| Before Width: | Height: | Size: 226 B After Width: | Height: | Size: 176 B | 
| Before Width: | Height: | Size: 228 B After Width: | Height: | Size: 187 B | 
| Before Width: | Height: | Size: 562 B After Width: | Height: | Size: 448 B | 
| Before Width: | Height: | Size: 558 B After Width: | Height: | Size: 449 B | 
| Before Width: | Height: | Size: 561 B After Width: | Height: | Size: 448 B | 
| Before Width: | Height: | Size: 556 B After Width: | Height: | Size: 446 B | 
| Before Width: | Height: | Size: 635 B After Width: | Height: | Size: 541 B | 
| Before Width: | Height: | Size: 632 B After Width: | Height: | Size: 541 B | 
| Before Width: | Height: | Size: 635 B After Width: | Height: | Size: 541 B | 
| Before Width: | Height: | Size: 630 B After Width: | Height: | Size: 538 B | 
| Before Width: | Height: | Size: 229 B After Width: | Height: | Size: 173 B | 
| Before Width: | Height: | Size: 234 B After Width: | Height: | Size: 181 B | 
| @@ -1,2 +0,0 @@ | |||||||
| mesecons |  | ||||||
| mesecons_materials |  | ||||||
| @@ -1,8 +1,11 @@ | |||||||
| The node detector is a receptor. It changes its state when either any node | The node detector is a receptor. It changes its state when either any node | ||||||
| or a specific node is detected. Right-click it to set a nodename to scan for. | or a specific node is detected. Right-click it to set a nodename to scan for. | ||||||
| It can also receive digiline signals. You can either send "GET" and it will | It can also receive digiline signals. For example, you can send | ||||||
| respond with the detected nodename or you can send any other string and it will | <code>{distance=4, scanname="default:dirt"}</code> | ||||||
| set this string as the node to scan for. | 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. | 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. | 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. | Automatic scanning with Mesecons output only works when the detector is in an active block, but Digilines queries always work. | ||||||
|   | |||||||
| Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 43 KiB | 
| Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 7.3 KiB | 
| Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 78 KiB | 
| Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 7.1 KiB | 
| @@ -189,28 +189,49 @@ local function node_detector_scan(pos) | |||||||
| 		(frontname ~= "air" and frontname ~= "ignore" and scanname == "") | 		(frontname ~= "air" and frontname ~= "ignore" and scanname == "") | ||||||
| end | end | ||||||
|  |  | ||||||
|  | local function node_detector_send_node_name(pos, node, channel, meta) | ||||||
|  | 	local distance = meta:get_int("distance") | ||||||
|  | 	local distance_max = mesecon.setting("node_detector_distance_max", 10) | ||||||
|  | 	if distance < 0 then distance = 0 end | ||||||
|  | 	if distance > distance_max then distance = distance_max end | ||||||
|  | 	local nodename = minetest.get_node( | ||||||
|  | 		vector.subtract(pos, vector.multiply(minetest.facedir_to_dir(node.param2), distance + 1)) | ||||||
|  | 	).name | ||||||
|  |  | ||||||
|  | 	digiline:receptor_send(pos, digiline.rules.default, channel, nodename) | ||||||
|  | end | ||||||
|  |  | ||||||
| -- set player name when receiving a digiline signal on a specific channel | -- set player name when receiving a digiline signal on a specific channel | ||||||
| local node_detector_digiline = { | local node_detector_digiline = { | ||||||
| 	effector = { | 	effector = { | ||||||
| 		action = function(pos, node, channel, msg) | 		action = function(pos, node, channel, msg) | ||||||
| 			local meta = minetest.get_meta(pos) | 			local meta = minetest.get_meta(pos) | ||||||
|  |  | ||||||
| 			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 |  | ||||||
|  |  | ||||||
| 			if channel ~= meta:get_string("digiline_channel") then return end | 			if channel ~= meta:get_string("digiline_channel") then return end | ||||||
|  |  | ||||||
| 			if msg == GET_COMMAND then | 			if type(msg) == "table" then | ||||||
| 				local nodename = minetest.get_node( | 				if msg.distance or msg.scanname then | ||||||
| 					vector.subtract(pos, vector.multiply(minetest.facedir_to_dir(node.param2), distance + 1)) | 					if msg.distance then | ||||||
| 				).name | 						meta:set_string("distance", msg.distance) | ||||||
|  | 					end | ||||||
| 				digiline:receptor_send(pos, digiline.rules.default, channel, nodename) | 					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 | 			else | ||||||
| 				meta:set_string("scanname", msg) | 				if msg == GET_COMMAND then | ||||||
| 				node_detector_make_formspec(pos) | 					node_detector_send_node_name(pos, node, channel, meta) | ||||||
|  | 				else | ||||||
|  | 					meta:set_string("scanname", msg) | ||||||
|  | 					node_detector_make_formspec(pos) | ||||||
|  | 				end | ||||||
| 			end | 			end | ||||||
| 		end, | 		end, | ||||||
| 	}, | 	}, | ||||||
| @@ -218,7 +239,7 @@ local node_detector_digiline = { | |||||||
| } | } | ||||||
|  |  | ||||||
| local function after_place_node_detector(pos, placer) | local function after_place_node_detector(pos, placer) | ||||||
| 	local placer_pos = placer:getpos() | 	local placer_pos = placer:get_pos() | ||||||
| 	if not placer_pos then | 	if not placer_pos then | ||||||
| 		return | 		return | ||||||
| 	end | 	end | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								mesecons_detector/mod.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,2 @@ | |||||||
|  | name = mesecons_detector | ||||||
|  | depends = mesecons, mesecons_materials | ||||||
| Before Width: | Height: | Size: 717 B After Width: | Height: | Size: 640 B | 
| Before Width: | Height: | Size: 727 B After Width: | Height: | Size: 687 B | 
| Before Width: | Height: | Size: 712 B After Width: | Height: | Size: 655 B | 
| Before Width: | Height: | Size: 735 B After Width: | Height: | Size: 693 B | 
| @@ -1,2 +0,0 @@ | |||||||
| mesecons |  | ||||||
| doors |  | ||||||
| @@ -13,9 +13,9 @@ local function on_rightclick(pos, dir, check_name, replace, replace_dir, params) | |||||||
| 	minetest.swap_node(pos, {name = replace, param2 = p2}) | 	minetest.swap_node(pos, {name = replace, param2 = p2}) | ||||||
|  |  | ||||||
| 	if (minetest.get_meta(pos):get_int("right") ~= 0) == (params[1] ~= 3) then | 	if (minetest.get_meta(pos):get_int("right") ~= 0) == (params[1] ~= 3) then | ||||||
| 		minetest.sound_play("doors_door_close", {pos = pos, gain = 0.3, max_hear_distance = 10}) | 		minetest.sound_play("doors_door_close", { pos = pos, gain = 0.3, max_hear_distance = 10 }, true) | ||||||
| 	else | 	else | ||||||
| 		minetest.sound_play("doors_door_open", {pos = pos, gain = 0.3, max_hear_distance = 10}) | 		minetest.sound_play("doors_door_open", { pos = pos, gain = 0.3, max_hear_distance = 10 }, true) | ||||||
| 	end | 	end | ||||||
| end | end | ||||||
|  |  | ||||||
| @@ -73,16 +73,17 @@ 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}) | 		minetest.sound_play("doors_door_close", { pos = pos, gain = 0.3, max_hear_distance = 10 }, true) | ||||||
| 		minetest.set_node(pos, {name="doors:trapdoor", param2 = node.param2}) | 		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}) | 		minetest.sound_play("doors_door_open", { pos = pos, gain = 0.3, max_hear_distance = 10 }, true) | ||||||
| 		minetest.set_node(pos, {name="doors:trapdoor_open", param2 = node.param2}) | 		minetest.set_node(pos, {name="doors:trapdoor_open", param2 = node.param2}) | ||||||
| 	end | 	end | ||||||
|  |  | ||||||
| @@ -110,6 +111,12 @@ if doors and doors.get then | |||||||
| 	minetest.override_item("doors:trapdoor_open", override) | 	minetest.override_item("doors:trapdoor_open", override) | ||||||
| 	minetest.override_item("doors:trapdoor_steel", override) | 	minetest.override_item("doors:trapdoor_steel", override) | ||||||
| 	minetest.override_item("doors:trapdoor_steel_open", override) | 	minetest.override_item("doors:trapdoor_steel_open", override) | ||||||
|  |  | ||||||
|  | 	if minetest.registered_items["xpanes:trapdoor_steel_bar"] then | ||||||
|  | 		minetest.override_item("xpanes:trapdoor_steel_bar", override) | ||||||
|  | 		minetest.override_item("xpanes:trapdoor_steel_bar_open", override) | ||||||
|  | 	end | ||||||
|  |  | ||||||
| else | else | ||||||
| 	if minetest.registered_nodes["doors:trapdoor"] then | 	if minetest.registered_nodes["doors:trapdoor"] then | ||||||
| 		minetest.override_item("doors:trapdoor", { | 		minetest.override_item("doors:trapdoor", { | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								mesecons_doors/mod.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,3 @@ | |||||||
|  | name = mesecons_doors | ||||||
|  | depends = mesecons, doors | ||||||
|  | optional_depends = xpanes | ||||||
| @@ -1,12 +1,5 @@ | |||||||
| local screwdriver_exists = minetest.global_exists("screwdriver") | local screwdriver_exists = minetest.global_exists("screwdriver") | ||||||
|  |  | ||||||
| local corner_nodebox = { |  | ||||||
| 	type = "fixed", |  | ||||||
| 	-- ±0.001 is to prevent z-fighting |  | ||||||
| 	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, -16/32, -16/32, 5/32, -12/32, 5/32 }, | ||||||
| @@ -25,14 +18,11 @@ local corner_get_rules = function (node) | |||||||
| end | end | ||||||
|  |  | ||||||
| minetest.register_node("mesecons_extrawires:corner_on", { | minetest.register_node("mesecons_extrawires:corner_on", { | ||||||
| 	drawtype = "nodebox", | 	drawtype = "mesh", | ||||||
|  | 	mesh = "mesecons_extrawires_corner.obj", | ||||||
| 	tiles = { | 	tiles = { | ||||||
| 		"jeija_insulated_wire_curved_tb_on.png", | 		{ name = "jeija_insulated_wire_sides_on.png", backface_culling = true }, | ||||||
| 		"jeija_insulated_wire_curved_tb_on.png^[transformR270", | 		{ name = "jeija_insulated_wire_ends_on.png", backface_culling = true }, | ||||||
| 		"jeija_insulated_wire_sides_on.png", |  | ||||||
| 		"jeija_insulated_wire_ends_on.png", |  | ||||||
| 		"jeija_insulated_wire_sides_on.png", |  | ||||||
| 		"jeija_insulated_wire_ends_on.png" |  | ||||||
| 	}, | 	}, | ||||||
| 	paramtype = "light", | 	paramtype = "light", | ||||||
| 	paramtype2 = "facedir", | 	paramtype2 = "facedir", | ||||||
| @@ -40,7 +30,6 @@ minetest.register_node("mesecons_extrawires:corner_on", { | |||||||
| 	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(), | 	sounds = default.node_sound_defaults(), | ||||||
| @@ -55,15 +44,12 @@ minetest.register_node("mesecons_extrawires:corner_on", { | |||||||
| }) | }) | ||||||
|  |  | ||||||
| minetest.register_node("mesecons_extrawires:corner_off", { | minetest.register_node("mesecons_extrawires:corner_off", { | ||||||
| 	drawtype = "nodebox", | 	drawtype = "mesh", | ||||||
| 	description = "Insulated Mesecon Corner", | 	description = "Insulated Mesecon Corner", | ||||||
|  | 	mesh = "mesecons_extrawires_corner.obj", | ||||||
| 	tiles = { | 	tiles = { | ||||||
| 		"jeija_insulated_wire_curved_tb_off.png", | 		{ name = "jeija_insulated_wire_sides_off.png", backface_culling = true }, | ||||||
| 		"jeija_insulated_wire_curved_tb_off.png^[transformR270", | 		{ name = "jeija_insulated_wire_ends_off.png", backface_culling = true }, | ||||||
| 		"jeija_insulated_wire_sides_off.png", |  | ||||||
| 		"jeija_insulated_wire_ends_off.png", |  | ||||||
| 		"jeija_insulated_wire_sides_off.png", |  | ||||||
| 		"jeija_insulated_wire_ends_off.png" |  | ||||||
| 	}, | 	}, | ||||||
| 	paramtype = "light", | 	paramtype = "light", | ||||||
| 	paramtype2 = "facedir", | 	paramtype2 = "facedir", | ||||||
| @@ -71,7 +57,6 @@ minetest.register_node("mesecons_extrawires:corner_off", { | |||||||
| 	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(), | 	sounds = default.node_sound_defaults(), | ||||||
| 	mesecons = {conductor = | 	mesecons = {conductor = | ||||||
| @@ -87,8 +72,7 @@ minetest.register_node("mesecons_extrawires:corner_off", { | |||||||
| 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,3 +0,0 @@ | |||||||
| default |  | ||||||
| mesecons |  | ||||||
| screwdriver? |  | ||||||
| Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 36 KiB | 
| Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 1.9 KiB | 
| Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 58 KiB | 
| Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 1.7 KiB | 
| Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 28 KiB | 
| Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 2.5 KiB | 
| Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 47 KiB | 
| Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 1.9 KiB | 
| Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 11 KiB | 
| Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 1.9 KiB | 
							
								
								
									
										91
									
								
								mesecons_extrawires/doublecorner.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,91 @@ | |||||||
|  | local rotate | ||||||
|  | if minetest.global_exists("screwdriver") then rotate = screwdriver.rotate_simple end | ||||||
|  |  | ||||||
|  | local doublecorner_selectionbox = { | ||||||
|  | 	type = "fixed", | ||||||
|  | 	fixed = { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 }, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | local rules = { | ||||||
|  | 	{ | ||||||
|  | 		{ x = 1, y = 0, z = 0 }, | ||||||
|  | 		{ x = 0, y = 0, z = 1 }, | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		{ x = -1, y = 0, z = 0 }, | ||||||
|  | 		{ x = 0, y = 0, z = -1 }, | ||||||
|  | 	}, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | local doublecorner_rules = {} | ||||||
|  | for k = 1, 4 do | ||||||
|  | 	doublecorner_rules[k] = table.copy(rules) | ||||||
|  | 	for i, r in ipairs(rules) do | ||||||
|  | 		rules[i] = mesecon.rotate_rules_left(r) | ||||||
|  | 	end | ||||||
|  | end | ||||||
|  |  | ||||||
|  | local function doublecorner_get_rules(node) | ||||||
|  | 	return doublecorner_rules[node.param2 % 4 + 1] | ||||||
|  | end | ||||||
|  |  | ||||||
|  | local doublecorner_states = { | ||||||
|  | 	"mesecons_extrawires:doublecorner_00", | ||||||
|  | 	"mesecons_extrawires:doublecorner_01", | ||||||
|  | 	"mesecons_extrawires:doublecorner_10", | ||||||
|  | 	"mesecons_extrawires:doublecorner_11", | ||||||
|  | } | ||||||
|  | local wire1_states = { "off", "off", "on", "on" } | ||||||
|  | local wire2_states = { "off", "on", "off", "on" } | ||||||
|  |  | ||||||
|  | for k, state in ipairs(doublecorner_states) do | ||||||
|  | 	local w1 = wire1_states[k] | ||||||
|  | 	local w2 = wire2_states[k] | ||||||
|  | 	local groups =  { dig_immediate = 3 } | ||||||
|  | 	if k ~= 1 then groups.not_in_creative_inventory = 1 end | ||||||
|  | 	minetest.register_node(state, { | ||||||
|  | 		drawtype = "mesh", | ||||||
|  | 		mesh = "mesecons_extrawires_doublecorner.obj", | ||||||
|  | 		description = "Insulated Mesecon Double Corner", | ||||||
|  | 		tiles = { | ||||||
|  | 			{ name = "jeija_insulated_wire_sides_" .. w1 .. ".png", backface_culling = true }, | ||||||
|  | 			{ name = "jeija_insulated_wire_ends_" .. w1 .. ".png", backface_culling = true }, | ||||||
|  | 			{ name = "jeija_insulated_wire_sides_" .. w2 .. ".png", backface_culling = true }, | ||||||
|  | 			{ name = "jeija_insulated_wire_ends_" .. w2 .. ".png", backface_culling = true }, | ||||||
|  | 		}, | ||||||
|  | 		paramtype = "light", | ||||||
|  | 		paramtype2 = "facedir", | ||||||
|  | 		is_ground_content = false, | ||||||
|  | 		walkable = false, | ||||||
|  | 		sunlight_propagates = true, | ||||||
|  | 		selection_box = doublecorner_selectionbox, | ||||||
|  | 		groups = groups, | ||||||
|  | 		drop = doublecorner_states[1], | ||||||
|  | 		sounds = default.node_sound_defaults(), | ||||||
|  | 		mesecons = { | ||||||
|  | 			conductor = { | ||||||
|  | 				states = doublecorner_states, | ||||||
|  | 				rules = doublecorner_get_rules, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		on_blast = mesecon.on_blastnode, | ||||||
|  | 		on_rotate = rotate, | ||||||
|  | 	}) | ||||||
|  | end | ||||||
|  |  | ||||||
|  | minetest.register_craft({ | ||||||
|  | 	type = "shapeless", | ||||||
|  | 	output = "mesecons_extrawires:doublecorner_00", | ||||||
|  | 	recipe = { | ||||||
|  | 		"mesecons_extrawires:corner_off", | ||||||
|  | 		"mesecons_extrawires:corner_off", | ||||||
|  | 	}, | ||||||
|  | }) | ||||||
|  |  | ||||||
|  | minetest.register_craft({ | ||||||
|  | 	type = "shapeless", | ||||||
|  | 	output = "mesecons_extrawires:corner_off 2", | ||||||
|  | 	recipe = { | ||||||
|  | 		"mesecons_extrawires:doublecorner_00", | ||||||
|  | 	}, | ||||||
|  | }) | ||||||
| @@ -1,5 +1,6 @@ | |||||||
| dofile(minetest.get_modpath("mesecons_extrawires").."/crossover.lua"); | dofile(minetest.get_modpath("mesecons_extrawires").."/crossover.lua"); | ||||||
| dofile(minetest.get_modpath("mesecons_extrawires").."/tjunction.lua"); | dofile(minetest.get_modpath("mesecons_extrawires").."/tjunction.lua"); | ||||||
| dofile(minetest.get_modpath("mesecons_extrawires").."/corner.lua"); | dofile(minetest.get_modpath("mesecons_extrawires").."/corner.lua"); | ||||||
|  | dofile(minetest.get_modpath("mesecons_extrawires").."/doublecorner.lua"); | ||||||
| dofile(minetest.get_modpath("mesecons_extrawires").."/vertical.lua"); | dofile(minetest.get_modpath("mesecons_extrawires").."/vertical.lua"); | ||||||
| dofile(minetest.get_modpath("mesecons_extrawires").."/mesewire.lua"); | dofile(minetest.get_modpath("mesecons_extrawires").."/mesewire.lua"); | ||||||
|   | |||||||
| @@ -18,7 +18,7 @@ minetest.override_item("default:mese", { | |||||||
|  |  | ||||||
| -- Copy node definition of powered mese from normal mese | -- Copy node definition of powered mese from normal mese | ||||||
| -- and brighten texture tiles to indicate mese is powered | -- and brighten texture tiles to indicate mese is powered | ||||||
| local powered_def = mesecon.mergetable(minetest.registered_nodes["default:mese"], { | local powered_def = mesecon.merge_tables(minetest.registered_nodes["default:mese"], { | ||||||
| 	drop = "default:mese", | 	drop = "default:mese", | ||||||
| 	light_source = 5, | 	light_source = 5, | ||||||
| 	mesecons = {conductor = { | 	mesecons = {conductor = { | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								mesecons_extrawires/mod.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,3 @@ | |||||||
|  | name = mesecons_extrawires | ||||||
|  | depends = default, mesecons | ||||||
|  | optional_depends = screwdriver | ||||||
							
								
								
									
										125
									
								
								mesecons_extrawires/models/mesecons_extrawires_corner.obj
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,125 @@ | |||||||
|  | # Вершины | ||||||
|  | # Провод 1 | ||||||
|  | # 1 (ниж. внутр.) | ||||||
|  | v 0.093750 -0.531250 -0.501000 | ||||||
|  | v 0.093750 -0.531250 -0.331726 | ||||||
|  | v 0.331726 -0.531250 -0.093750 | ||||||
|  | v 0.501000 -0.531250 -0.093750 | ||||||
|  | # 5 (ниж. наруж.) | ||||||
|  | v -0.093750 -0.531250 -0.501000 | ||||||
|  | v -0.093750 -0.531250 -0.254061 | ||||||
|  | v 0.254061 -0.531250 0.093750 | ||||||
|  | v 0.501000 -0.531250 0.093750 | ||||||
|  | # 9 (верх. внутр.) | ||||||
|  | v 0.093750 -0.406250 -0.501000 | ||||||
|  | v 0.093750 -0.406250 -0.331726 | ||||||
|  | v 0.331726 -0.406250 -0.093750 | ||||||
|  | v 0.501000 -0.406250 -0.093750 | ||||||
|  | # 13 (верх. наруж.) | ||||||
|  | v -0.093750 -0.406250 -0.501000 | ||||||
|  | v -0.093750 -0.406250 -0.254061 | ||||||
|  | v 0.254061 -0.406250 0.093750 | ||||||
|  | v 0.501000 -0.406250 0.093750 | ||||||
|  | # Текстурные координаты | ||||||
|  | # 1 (ниж.) | ||||||
|  | vt 0.000000 0.406250 | ||||||
|  | vt 0.168274 0.406250 | ||||||
|  | vt 0.331726 0.406250 | ||||||
|  | vt 0.668274 0.406250 | ||||||
|  | vt 0.831726 0.406250 | ||||||
|  | vt 1.000000 0.406250 | ||||||
|  | vt 0.000000 0.593750 | ||||||
|  | vt 0.245939 0.593750 | ||||||
|  | vt 0.254061 0.593750 | ||||||
|  | vt 0.745939 0.593750 | ||||||
|  | vt 0.754061 0.593750 | ||||||
|  | vt 1.000000 0.593750 | ||||||
|  | # 13 (верх.) | ||||||
|  | vt 0.000000 0.406250 | ||||||
|  | vt 0.245939 0.406250 | ||||||
|  | vt 0.254061 0.406250 | ||||||
|  | vt 0.745939 0.406250 | ||||||
|  | vt 0.754061 0.406250 | ||||||
|  | vt 1.000000 0.406250 | ||||||
|  | vt 0.000000 0.593750 | ||||||
|  | vt 0.168274 0.593750 | ||||||
|  | vt 0.331726 0.593750 | ||||||
|  | vt 0.668274 0.593750 | ||||||
|  | vt 0.831726 0.593750 | ||||||
|  | vt 1.000000 0.593750 | ||||||
|  | # 25 (внутр.) | ||||||
|  | vt 1.000000 0.093750 | ||||||
|  | vt 0.831726 0.093750 | ||||||
|  | vt 0.668274 0.093750 | ||||||
|  | vt 0.331726 0.093750 | ||||||
|  | vt 0.168274 0.093750 | ||||||
|  | vt 0.000000 0.093750 | ||||||
|  | vt 1.000000 -0.031250 | ||||||
|  | vt 0.831726 -0.031250 | ||||||
|  | vt 0.668274 -0.031250 | ||||||
|  | vt 0.331726 -0.031250 | ||||||
|  | vt 0.168274 -0.031250 | ||||||
|  | vt 0.000000 -0.031250 | ||||||
|  | # 37 (внеш.) | ||||||
|  | vt 0.000000 -0.031250 | ||||||
|  | vt 0.245939 -0.031250 | ||||||
|  | vt 0.254061 -0.031250 | ||||||
|  | vt 0.745939 -0.031250 | ||||||
|  | vt 0.754061 -0.031250 | ||||||
|  | vt 1.000000 -0.031250 | ||||||
|  | vt 0.000000 0.093750 | ||||||
|  | vt 0.245939 0.093750 | ||||||
|  | vt 0.254061 0.093750 | ||||||
|  | vt 0.745939 0.093750 | ||||||
|  | vt 0.754061 0.093750 | ||||||
|  | vt 1.000000 0.093750 | ||||||
|  | # 49 (торец) | ||||||
|  | vt 0.406250 -0.031250 | ||||||
|  | vt 0.406250 0.093750 | ||||||
|  | vt 0.593750 -0.031250 | ||||||
|  | vt 0.593750 0.093750 | ||||||
|  | # Нормали | ||||||
|  | # 1 | ||||||
|  | vn 1.000000 0.000000 0.000000 | ||||||
|  | vn 0.000000 1.000000 0.000000 | ||||||
|  | vn 0.000000 0.000000 1.000000 | ||||||
|  | vn 0.707107 0.000000 0.707107 | ||||||
|  | # 5 | ||||||
|  | vn -1.000000 0.000000 0.000000 | ||||||
|  | vn 0.000000 -1.000000 0.000000 | ||||||
|  | vn 0.000000 0.000000 -1.000000 | ||||||
|  | vn -0.707107 0.000000 -0.707107 | ||||||
|  | # Грани | ||||||
|  | g Sides1 | ||||||
|  | # Часть 1 | ||||||
|  | f 5/37/1 6/38/1 14/44/1 | ||||||
|  | f 5/37/1 14/44/1 13/43/1 | ||||||
|  | f 13/13/2 14/14/2 10/20/2 | ||||||
|  | f 13/13/2 10/20/2 9/19/2 | ||||||
|  | f 9/25/5 10/26/5 2/32/5 | ||||||
|  | f 9/25/5 2/32/5 1/31/5 | ||||||
|  | f 1/1/6 2/2/6 6/8/6 | ||||||
|  | f 1/1/6 6/8/6 5/7/6 | ||||||
|  | # Часть 2 | ||||||
|  | f 6/39/4 7/40/4 15/46/4 | ||||||
|  | f 6/39/4 15/46/4 14/45/4 | ||||||
|  | f 14/15/2 15/16/2 11/22/2 | ||||||
|  | f 14/15/2 11/22/2 10/21/2 | ||||||
|  | f 10/27/8 11/28/8 3/34/8 | ||||||
|  | f 10/27/8 3/34/8 2/33/8 | ||||||
|  | f 2/3/6 3/4/6 7/10/6 | ||||||
|  | f 2/3/6 7/10/6 6/9/6 | ||||||
|  | # Часть 3 | ||||||
|  | f 7/41/3 8/42/3 16/48/3 | ||||||
|  | f 7/41/3 16/48/3 15/47/3 | ||||||
|  | f 15/17/2 16/18/2 12/24/2 | ||||||
|  | f 15/17/2 12/24/2 11/23/2 | ||||||
|  | f 11/29/7 12/30/7 4/36/7 | ||||||
|  | f 11/29/7 4/36/7 3/35/7 | ||||||
|  | f 3/5/6 4/6/6 8/12/6 | ||||||
|  | f 3/5/6 8/12/6 7/11/6 | ||||||
|  | g Ends1 | ||||||
|  | f 1/49/3 5/51/3 13/52/3 | ||||||
|  | f 1/49/3 13/52/3 9/50/3 | ||||||
|  | f 4/49/1 12/50/1 16/52/1 | ||||||
|  | f 4/49/1 16/52/1 8/51/1 | ||||||
							
								
								
									
										180
									
								
								mesecons_extrawires/models/mesecons_extrawires_doublecorner.obj
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,180 @@ | |||||||
|  | # Вершины | ||||||
|  | # Провод 1 | ||||||
|  | # 1 (ниж. внутр.) | ||||||
|  | v 0.093750 -0.531250 -0.501000 | ||||||
|  | v 0.093750 -0.531250 -0.331726 | ||||||
|  | v 0.331726 -0.531250 -0.093750 | ||||||
|  | v 0.501000 -0.531250 -0.093750 | ||||||
|  | # 5 (ниж. наруж.) | ||||||
|  | v -0.093750 -0.531250 -0.501000 | ||||||
|  | v -0.093750 -0.531250 -0.254061 | ||||||
|  | v 0.254061 -0.531250 0.093750 | ||||||
|  | v 0.501000 -0.531250 0.093750 | ||||||
|  | # 9 (верх. внутр.) | ||||||
|  | v 0.093750 -0.406250 -0.501000 | ||||||
|  | v 0.093750 -0.406250 -0.331726 | ||||||
|  | v 0.331726 -0.406250 -0.093750 | ||||||
|  | v 0.501000 -0.406250 -0.093750 | ||||||
|  | # 13 (верх. наруж.) | ||||||
|  | v -0.093750 -0.406250 -0.501000 | ||||||
|  | v -0.093750 -0.406250 -0.254061 | ||||||
|  | v 0.254061 -0.406250 0.093750 | ||||||
|  | v 0.501000 -0.406250 0.093750 | ||||||
|  | # Провод 2 | ||||||
|  | # 17 (ниж. внутр.) | ||||||
|  | v -0.093750 -0.531250 0.501000 | ||||||
|  | v -0.093750 -0.531250 0.331726 | ||||||
|  | v -0.331726 -0.531250 0.093750 | ||||||
|  | v -0.501000 -0.531250 0.093750 | ||||||
|  | # 21 (ниж. наруж.) | ||||||
|  | v 0.093750 -0.531250 0.501000 | ||||||
|  | v 0.093750 -0.531250 0.254061 | ||||||
|  | v -0.254061 -0.531250 -0.093750 | ||||||
|  | v -0.501000 -0.531250 -0.093750 | ||||||
|  | # 25 (верх. внутр.) | ||||||
|  | v -0.093750 -0.406250 0.501000 | ||||||
|  | v -0.093750 -0.406250 0.331726 | ||||||
|  | v -0.331726 -0.406250 0.093750 | ||||||
|  | v -0.501000 -0.406250 0.093750 | ||||||
|  | # 29 (верх. наруж.) | ||||||
|  | v 0.093750 -0.406250 0.501000 | ||||||
|  | v 0.093750 -0.406250 0.254061 | ||||||
|  | v -0.254061 -0.406250 -0.093750 | ||||||
|  | v -0.501000 -0.406250 -0.093750 | ||||||
|  | # Текстурные координаты | ||||||
|  | # 1 (ниж.) | ||||||
|  | vt 0.000000 0.406250 | ||||||
|  | vt 0.168274 0.406250 | ||||||
|  | vt 0.331726 0.406250 | ||||||
|  | vt 0.668274 0.406250 | ||||||
|  | vt 0.831726 0.406250 | ||||||
|  | vt 1.000000 0.406250 | ||||||
|  | vt 0.000000 0.593750 | ||||||
|  | vt 0.245939 0.593750 | ||||||
|  | vt 0.254061 0.593750 | ||||||
|  | vt 0.745939 0.593750 | ||||||
|  | vt 0.754061 0.593750 | ||||||
|  | vt 1.000000 0.593750 | ||||||
|  | # 13 (верх.) | ||||||
|  | vt 0.000000 0.406250 | ||||||
|  | vt 0.245939 0.406250 | ||||||
|  | vt 0.254061 0.406250 | ||||||
|  | vt 0.745939 0.406250 | ||||||
|  | vt 0.754061 0.406250 | ||||||
|  | vt 1.000000 0.406250 | ||||||
|  | vt 0.000000 0.593750 | ||||||
|  | vt 0.168274 0.593750 | ||||||
|  | vt 0.331726 0.593750 | ||||||
|  | vt 0.668274 0.593750 | ||||||
|  | vt 0.831726 0.593750 | ||||||
|  | vt 1.000000 0.593750 | ||||||
|  | # 25 (внутр.) | ||||||
|  | vt 1.000000 0.093750 | ||||||
|  | vt 0.831726 0.093750 | ||||||
|  | vt 0.668274 0.093750 | ||||||
|  | vt 0.331726 0.093750 | ||||||
|  | vt 0.168274 0.093750 | ||||||
|  | vt 0.000000 0.093750 | ||||||
|  | vt 1.000000 -0.031250 | ||||||
|  | vt 0.831726 -0.031250 | ||||||
|  | vt 0.668274 -0.031250 | ||||||
|  | vt 0.331726 -0.031250 | ||||||
|  | vt 0.168274 -0.031250 | ||||||
|  | vt 0.000000 -0.031250 | ||||||
|  | # 37 (внеш.) | ||||||
|  | vt 0.000000 -0.031250 | ||||||
|  | vt 0.245939 -0.031250 | ||||||
|  | vt 0.254061 -0.031250 | ||||||
|  | vt 0.745939 -0.031250 | ||||||
|  | vt 0.754061 -0.031250 | ||||||
|  | vt 1.000000 -0.031250 | ||||||
|  | vt 0.000000 0.093750 | ||||||
|  | vt 0.245939 0.093750 | ||||||
|  | vt 0.254061 0.093750 | ||||||
|  | vt 0.745939 0.093750 | ||||||
|  | vt 0.754061 0.093750 | ||||||
|  | vt 1.000000 0.093750 | ||||||
|  | # 49 (торец) | ||||||
|  | vt 0.406250 -0.031250 | ||||||
|  | vt 0.406250 0.093750 | ||||||
|  | vt 0.593750 -0.031250 | ||||||
|  | vt 0.593750 0.093750 | ||||||
|  | # Нормали | ||||||
|  | # 1 | ||||||
|  | vn 1.000000 0.000000 0.000000 | ||||||
|  | vn 0.000000 1.000000 0.000000 | ||||||
|  | vn 0.000000 0.000000 1.000000 | ||||||
|  | vn 0.707107 0.000000 0.707107 | ||||||
|  | # 5 | ||||||
|  | vn -1.000000 0.000000 0.000000 | ||||||
|  | vn 0.000000 -1.000000 0.000000 | ||||||
|  | vn 0.000000 0.000000 -1.000000 | ||||||
|  | vn -0.707107 0.000000 -0.707107 | ||||||
|  | # Грани | ||||||
|  | # Грани | ||||||
|  | g Sides1 | ||||||
|  | # Часть 1 | ||||||
|  | f 5/37/1 6/38/1 14/44/1 | ||||||
|  | f 5/37/1 14/44/1 13/43/1 | ||||||
|  | f 13/13/2 14/14/2 10/20/2 | ||||||
|  | f 13/13/2 10/20/2 9/19/2 | ||||||
|  | f 9/25/5 10/26/5 2/32/5 | ||||||
|  | f 9/25/5 2/32/5 1/31/5 | ||||||
|  | f 1/1/6 2/2/6 6/8/6 | ||||||
|  | f 1/1/6 6/8/6 5/7/6 | ||||||
|  | # Часть 2 | ||||||
|  | f 6/39/4 7/40/4 15/46/4 | ||||||
|  | f 6/39/4 15/46/4 14/45/4 | ||||||
|  | f 14/15/2 15/16/2 11/22/2 | ||||||
|  | f 14/15/2 11/22/2 10/21/2 | ||||||
|  | f 10/27/8 11/28/8 3/34/8 | ||||||
|  | f 10/27/8 3/34/8 2/33/8 | ||||||
|  | f 2/3/6 3/4/6 7/10/6 | ||||||
|  | f 2/3/6 7/10/6 6/9/6 | ||||||
|  | # Часть 3 | ||||||
|  | f 7/41/3 8/42/3 16/48/3 | ||||||
|  | f 7/41/3 16/48/3 15/47/3 | ||||||
|  | f 15/17/2 16/18/2 12/24/2 | ||||||
|  | f 15/17/2 12/24/2 11/23/2 | ||||||
|  | f 11/29/7 12/30/7 4/36/7 | ||||||
|  | f 11/29/7 4/36/7 3/35/7 | ||||||
|  | f 3/5/6 4/6/6 8/12/6 | ||||||
|  | f 3/5/6 8/12/6 7/11/6 | ||||||
|  | g Ends1 | ||||||
|  | f 1/49/3 5/51/3 13/52/3 | ||||||
|  | f 1/49/3 13/52/3 9/50/3 | ||||||
|  | f 4/49/1 12/50/1 16/52/1 | ||||||
|  | f 4/49/1 16/52/1 8/51/1 | ||||||
|  | g Sides2 | ||||||
|  | # Часть 1 | ||||||
|  | f 21/37/1 22/38/1 30/44/1 | ||||||
|  | f 21/37/1 30/44/1 29/43/1 | ||||||
|  | f 29/13/2 30/14/2 26/20/2 | ||||||
|  | f 29/13/2 26/20/2 25/19/2 | ||||||
|  | f 25/25/5 26/26/5 18/32/5 | ||||||
|  | f 25/25/5 18/32/5 17/31/5 | ||||||
|  | f 17/1/6 18/2/6 22/8/6 | ||||||
|  | f 17/1/6 22/8/6 21/7/6 | ||||||
|  | # Часть 2 | ||||||
|  | f 22/39/4 23/40/4 31/46/4 | ||||||
|  | f 22/39/4 31/46/4 30/45/4 | ||||||
|  | f 30/15/2 31/16/2 27/22/2 | ||||||
|  | f 30/15/2 27/22/2 26/21/2 | ||||||
|  | f 26/27/8 27/28/8 19/34/8 | ||||||
|  | f 26/27/8 19/34/8 18/33/8 | ||||||
|  | f 18/3/6 19/4/6 23/10/6 | ||||||
|  | f 18/3/6 23/10/6 22/9/6 | ||||||
|  | # Часть 3 | ||||||
|  | f 23/41/3 24/42/3 32/48/3 | ||||||
|  | f 23/41/3 32/48/3 31/47/3 | ||||||
|  | f 31/17/2 32/18/2 28/24/2 | ||||||
|  | f 31/17/2 28/24/2 27/23/2 | ||||||
|  | f 27/29/7 28/30/7 20/36/7 | ||||||
|  | f 27/29/7 20/36/7 19/35/7 | ||||||
|  | f 19/5/6 20/6/6 24/12/6 | ||||||
|  | f 19/5/6 24/12/6 23/11/6 | ||||||
|  | g Ends2 | ||||||
|  | f 17/49/3 21/51/3 29/52/3 | ||||||
|  | f 17/49/3 29/52/3 25/50/3 | ||||||
|  | f 20/49/1 28/50/1 32/52/1 | ||||||
|  | f 20/49/1 32/52/1 24/51/1 | ||||||
| @@ -88,7 +88,6 @@ minetest.register_node("mesecons_extrawires:tjunction_off", { | |||||||
| minetest.register_craft({ | minetest.register_craft({ | ||||||
| 	output = "mesecons_extrawires:tjunction_off 3", | 	output = "mesecons_extrawires:tjunction_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"}, | ||||||
| 		{"", "mesecons_insulated:insulated_off", ""}, | 		{"", "mesecons_insulated:insulated_off", ""}, | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -175,9 +175,9 @@ mesecon.register_node("mesecons_extrawires:vertical_bottom", { | |||||||
| minetest.register_craft({ | minetest.register_craft({ | ||||||
| 	output = "mesecons_extrawires:vertical_off 3", | 	output = "mesecons_extrawires:vertical_off 3", | ||||||
| 	recipe = { | 	recipe = { | ||||||
| 		{"mesecons:wire_00000000_off"}, | 		{"group:mesecon_conductor_craftable"}, | ||||||
| 		{"mesecons:wire_00000000_off"}, | 		{"group:mesecon_conductor_craftable"}, | ||||||
| 		{"mesecons:wire_00000000_off"} | 		{"group:mesecon_conductor_craftable"}, | ||||||
| 	} | 	} | ||||||
| }) | }) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,2 +0,0 @@ | |||||||
| mesecons |  | ||||||
| screwdriver? |  | ||||||
| Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 20 KiB | 
| Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 2.9 KiB | 
| Before Width: | Height: | Size: 598 B After Width: | Height: | Size: 519 B | 
| Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.7 KiB |