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) | ||||
| 	mesecon.queue.funcs[name] = func | ||||
| The ActionQueue holds functions and actions. | ||||
| Functions are added on load time with a specified name. | ||||
| Actions are preserved over server restarts. | ||||
|  | ||||
| Each action consists of a position, the name of an added function to be called, | ||||
| the params that should be used in this function call (additionally to the pos), | ||||
| the time after which it should be executed, an optional overwritecheck and a | ||||
| priority. | ||||
|  | ||||
| If time = 0, the action will be executed in the next globalstep, otherwise the | ||||
| earliest globalstep when it will be executed is the after next globalstep. | ||||
|  | ||||
| It is guaranteed, that for two actions ac1, ac2 where ac1 ~= ac2, | ||||
| ac1.time == ac2.time, ac1.priority == ac2.priority and ac1 was added earlier | ||||
| than ac2, ac1 will be executed before ac2 (but in the same globalstep). | ||||
|  | ||||
| Note: Do not pass references in params, as they can not be preserved. | ||||
|  | ||||
| Also note: Some of the guarantees here might be dropped at some time. | ||||
| ]] | ||||
|  | ||||
|  | ||||
| -- localize for speed | ||||
| local queue = mesecon.queue | ||||
|  | ||||
| queue.actions = {} -- contains all ActionQueue actions | ||||
|  | ||||
| function queue:add_function(name, func) | ||||
| 	queue.funcs[name] = func | ||||
| end | ||||
|  | ||||
| -- If add_action with twice the same overwritecheck and same position are called, the first one is overwritten | ||||
| -- use overwritecheck nil to never overwrite, but just add the event to the queue | ||||
| -- priority specifies the order actions are executed within one globalstep, highest first | ||||
| -- should be between 0 and 1 | ||||
| function mesecon.queue:add_action(pos, func, params, time, overwritecheck, priority) | ||||
| function queue:add_action(pos, func, params, time, overwritecheck, priority) | ||||
| 	-- Create Action Table: | ||||
| 	time = time or 0 -- time <= 0 --> execute, time > 0 --> wait time until execution | ||||
| 	priority = priority or 1 | ||||
| 	local action = {	pos=mesecon.tablecopy(pos), | ||||
| 				func=func, | ||||
| 				params=mesecon.tablecopy(params or {}), | ||||
| 				time=time, | ||||
| 				owcheck=(overwritecheck and mesecon.tablecopy(overwritecheck)) or nil, | ||||
| 				priority=priority} | ||||
| 	local action = { | ||||
| 		pos = mesecon.tablecopy(pos), | ||||
| 		func = func, | ||||
| 		params = mesecon.tablecopy(params or {}), | ||||
| 		time = time, | ||||
| 		owcheck = (overwritecheck and mesecon.tablecopy(overwritecheck)) or nil, | ||||
| 		priority = priority | ||||
| 	} | ||||
|  | ||||
| 	local toremove = nil | ||||
| 	-- Otherwise, add the action to the queue | ||||
| 	if overwritecheck then -- check if old action has to be overwritten / removed: | ||||
| 		for i, ac in ipairs(mesecon.queue.actions) do | ||||
| 			if(vector.equals(pos, ac.pos) | ||||
| 			and mesecon.cmpAny(overwritecheck, ac.owcheck)) then | ||||
| 				toremove = i | ||||
| 	 -- check if old action has to be overwritten / removed: | ||||
| 	if overwritecheck then | ||||
| 		for i, ac in ipairs(queue.actions) do | ||||
| 			if vector.equals(pos, ac.pos) | ||||
| 					and mesecon.cmpAny(overwritecheck, ac.owcheck) then | ||||
| 				-- remove the old action | ||||
| 				table.remove(queue.actions, i) | ||||
| 				break | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	if (toremove ~= nil) then | ||||
| 		table.remove(mesecon.queue.actions, toremove) | ||||
| 	end | ||||
|  | ||||
| 	table.insert(mesecon.queue.actions, action) | ||||
| 	table.insert(queue.actions, action) | ||||
| end | ||||
|  | ||||
| -- execute the stored functions on a globalstep | ||||
| -- if however, the pos of a function is not loaded (get_node_or_nil == nil), do NOT execute the function | ||||
| -- this makes sure that resuming mesecons circuits when restarting minetest works fine | ||||
| -- this makes sure that resuming mesecons circuits when restarting minetest works fine (hm, where do we do this?) | ||||
| -- However, even that does not work in some cases, that's why we delay the time the globalsteps | ||||
| -- start to be execute by 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 | ||||
| -- start to be execute by 4 seconds | ||||
|  | ||||
| 	return highesti | ||||
| end | ||||
| local function globalstep_func(dtime) | ||||
| 	local actions = queue.actions | ||||
| 	-- split into two categories: | ||||
| 	-- actions_now: actions to execute now | ||||
| 	-- queue.actions: actions to execute later | ||||
| 	local actions_now = {} | ||||
| 	queue.actions = {} | ||||
|  | ||||
| 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 | ||||
| 	for _, ac in ipairs(actions) do | ||||
| 		if ac.time > 0 then | ||||
| 			ac.time = ac.time - dtime -- executed later | ||||
| 			table.insert(mesecon.queue.actions, ac) | ||||
| 			-- action ac is to be executed later | ||||
| 			-- ~> insert into queue.actions | ||||
| 			ac.time = ac.time - dtime | ||||
| 			table.insert(queue.actions, ac) | ||||
| 		else | ||||
| 			-- action ac is to be executed now | ||||
| 			-- ~> insert into actions_now | ||||
| 			table.insert(actions_now, ac) | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	while(#actions_now > 0) do -- execute highest priorities first, until all are executed | ||||
| 		local hp = get_highest_priority(actions_now) | ||||
| 		mesecon.queue:execute(actions_now[hp]) | ||||
| 		table.remove(actions_now, hp) | ||||
| 	-- stable-sort the executed actions after their priority | ||||
| 	-- some constructions might depend on the execution order, hence we first | ||||
| 	-- execute the actions that had a lower index in actions_now | ||||
| 	local old_action_order = {} | ||||
| 	for i, ac in ipairs(actions_now) do | ||||
| 		old_action_order[ac] = i | ||||
| 	end | ||||
| 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, | ||||
| 	-- (e.g. in case the action queue savegame was written by an old mesecons version) | ||||
| 	if mesecon.queue.funcs[action.func] then | ||||
| 		mesecon.queue.funcs[action.func](action.pos, unpack(action.params)) | ||||
| 	if queue.funcs[action.func] then | ||||
| 		queue.funcs[action.func](action.pos, unpack(action.params)) | ||||
| 	end | ||||
| end | ||||
|  | ||||
| @@ -98,8 +142,8 @@ end | ||||
| -- Store and read the ActionQueue to / from a file | ||||
| -- so that upcoming actions are remembered when the game | ||||
| -- is restarted | ||||
| mesecon.queue.actions = mesecon.file2table("mesecon_actionqueue") | ||||
| queue.actions = mesecon.file2table("mesecon_actionqueue") | ||||
|  | ||||
| minetest.register_on_shutdown(function() | ||||
| 	mesecon.table2file("mesecon_actionqueue", mesecon.queue.actions) | ||||
| 	mesecon.table2file("mesecon_actionqueue", queue.actions) | ||||
| 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 | ||||
| -- 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.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) | ||||
| -- These functions return rules that have been rotated in the specific direction | ||||
|  | ||||
| local fifo_queue = dofile(minetest.get_modpath("mesecons").."/fifo_queue.lua") | ||||
|  | ||||
| -- General | ||||
| function mesecon.get_effector(nodename) | ||||
| 	if  minetest.registered_nodes[nodename] | ||||
| @@ -92,8 +94,8 @@ function mesecon.get_any_inputrules(node) | ||||
| end | ||||
|  | ||||
| function mesecon.get_any_rules(node) | ||||
| 	return mesecon.mergetable(mesecon.get_any_inputrules(node) or {}, | ||||
| 		mesecon.get_any_outputrules(node) or {}) | ||||
| 	return mesecon.merge_rule_sets(mesecon.get_any_inputrules(node), | ||||
| 		mesecon.get_any_outputrules(node)) | ||||
| end | ||||
|  | ||||
| -- Receptors | ||||
| @@ -371,32 +373,39 @@ end | ||||
| -- Follow all all conductor paths replacing conductors that were already | ||||
| -- looked at, activating / changing all effectors along the way. | ||||
| function mesecon.turnon(pos, link) | ||||
| 	local frontiers = {{pos = pos, link = link}} | ||||
| 	local frontiers = fifo_queue.new() | ||||
| 	frontiers:add({pos = pos, link = link}) | ||||
| 	local pos_can_be_skipped = {} | ||||
|  | ||||
| 	local depth = 1 | ||||
| 	while frontiers[1] do | ||||
| 		local f = table.remove(frontiers, 1) | ||||
| 	for f in frontiers:iter() do | ||||
| 		local node = mesecon.get_node_force(f.pos) | ||||
|  | ||||
| 		if not node then | ||||
| 			-- 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 | ||||
| 			local rules = mesecon.conductor_get_rules(node) | ||||
|  | ||||
| 			-- Call turnon on neighbors | ||||
| 			for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do | ||||
| 				local np = vector.add(f.pos, r) | ||||
| 				for _, l in ipairs(mesecon.rules_link_rule_all(f.pos, r)) do | ||||
| 					table.insert(frontiers, {pos = np, link = l}) | ||||
| 				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 | ||||
| 						frontiers:add({pos = np, link = l}) | ||||
| 					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 | ||||
| 			mesecon.changesignal(f.pos, node, f.link, mesecon.state.on, depth) | ||||
| 			if mesecon.is_effector_off(node.name) then | ||||
| 				mesecon.activate(f.pos, node, f.link, depth) | ||||
| 			end | ||||
| 		else | ||||
| 			pos_can_be_skipped[minetest.hash_node_position(f.pos)] = true | ||||
| 		end | ||||
| 		depth = depth + 1 | ||||
| 	end | ||||
| @@ -419,37 +428,42 @@ end | ||||
| --	depth = indicates order in which signals wire fired, higher is later | ||||
| -- } | ||||
| 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 pos_can_be_skipped = {} | ||||
|  | ||||
| 	local depth = 1 | ||||
| 	while frontiers[1] do | ||||
| 		local f = table.remove(frontiers, 1) | ||||
| 	for f in frontiers:iter() do | ||||
| 		local node = mesecon.get_node_force(f.pos) | ||||
|  | ||||
| 		if not node then | ||||
| 			-- 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 | ||||
| 			local rules = mesecon.conductor_get_rules(node) | ||||
| 			for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do | ||||
| 				local np = vector.add(f.pos, r) | ||||
|  | ||||
| 				-- Check if an onstate receptor is connected. If that is the case, | ||||
| 				-- abort this turnoff process by returning false. `receptor_off` will | ||||
| 				-- discard all the changes that we made in the voxelmanip: | ||||
| 				for _, l in ipairs(mesecon.rules_link_rule_all_inverted(f.pos, r)) do | ||||
| 					if mesecon.is_receptor_on(mesecon.get_node_force(np).name) then | ||||
| 						return false | ||||
| 				if not pos_can_be_skipped[minetest.hash_node_position(np)] then | ||||
| 					-- Check if an onstate receptor is connected. If that is the case, | ||||
| 					-- abort this turnoff process by returning false. `receptor_off` will | ||||
| 					-- discard all the changes that we made in the voxelmanip: | ||||
| 					if mesecon.rules_link_rule_all_inverted(f.pos, r)[1] then | ||||
| 						if mesecon.is_receptor_on(mesecon.get_node_force(np).name) then | ||||
| 							return false | ||||
| 						end | ||||
| 					end | ||||
| 				end | ||||
|  | ||||
| 				-- Call turnoff on neighbors | ||||
| 				for _, l in ipairs(mesecon.rules_link_rule_all(f.pos, r)) do | ||||
| 					table.insert(frontiers, {pos = np, link = l}) | ||||
| 					-- 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 | ||||
|  | ||||
| 			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 | ||||
| 			table.insert(signals, { | ||||
| 				pos = f.pos, | ||||
| @@ -457,6 +471,8 @@ function mesecon.turnoff(pos, link) | ||||
| 				link = f.link, | ||||
| 				depth = depth | ||||
| 			}) | ||||
| 		else | ||||
| 			pos_can_be_skipped[minetest.hash_node_position(f.pos)] = true | ||||
| 		end | ||||
| 		depth = depth + 1 | ||||
| 	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}, | ||||
| } | ||||
|  | ||||
| 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 = { | ||||
| 	{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 | ||||
| 			-- conductors will be activated (when pushing an on-conductor with a piston) | ||||
| 			for _, s in ipairs(sources) do | ||||
| 				local rule = vector.subtract(pos, s) | ||||
| 				local rule = vector.subtract(s, pos) | ||||
| 				mesecon.turnon(pos, rule) | ||||
| 			end | ||||
| 			--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) | ||||
| 	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" | ||||
| end | ||||
|  | ||||
| @@ -186,34 +188,36 @@ function mesecon.invertRule(r) | ||||
| 	return vector.multiply(r, -1) | ||||
| 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 | ||||
| function mesecon.tablecopy(obj) -- deep copy | ||||
| 	if type(obj) == "table" then | ||||
| 		return table.copy(obj) | ||||
| 	end | ||||
|  | ||||
| 	return newtable | ||||
| 	return obj | ||||
| 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) | ||||
| 	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 | ||||
| 		if not mesecon.cmpAny(e, t2[i]) then return false end | ||||
| 	end | ||||
|  | ||||
| 	-- Check that all keys of `t2` are also keys of `t1` so were checked in the previous loop | ||||
| 	for i, _ in pairs(t2) do | ||||
| 		if t1[i] == nil then return false end | ||||
| 	end | ||||
|  | ||||
| 	return true | ||||
| end | ||||
|  | ||||
| -- 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) | ||||
| 	minetest.log("warning", debug.traceback("Deprecated call to mesecon.mergetable")) | ||||
| 	local rval = mesecon.tablecopy(dest) | ||||
|  | ||||
| 	for k, v in pairs(source) do | ||||
| @@ -226,6 +230,32 @@ function mesecon.mergetable(source, dest) | ||||
| 	return rval | ||||
| 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) | ||||
| 	spec_common.drop = spec_common.drop or name .. "_off" | ||||
| 	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_off.__mesecon_state = "off" | ||||
|  | ||||
| 	spec_on = mesecon.mergetable(spec_common, spec_on); | ||||
| 	spec_off = mesecon.mergetable(spec_common, spec_off); | ||||
| 	spec_on = mesecon.merge_tables(spec_common, spec_on); | ||||
| 	spec_off = mesecon.merge_tables(spec_common, spec_off); | ||||
|  | ||||
| 	minetest.register_node(name .. "_on", spec_on) | ||||
| 	minetest.register_node(name .. "_off", spec_off) | ||||
|   | ||||
| @@ -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}, | ||||
| 	}, | ||||
| 	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 | ||||
| },{ | ||||
| 	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 | ||||
| 	end | ||||
| 	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) | ||||
| 	mesecon.receptor_off(pos, rules) | ||||
| end | ||||
|  | ||||
| local use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or nil | ||||
|  | ||||
| minetest.register_node("mesecons_button:button_off", { | ||||
| 	drawtype = "nodebox", | ||||
| 	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_off.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" | ||||
| 	}, | ||||
| 	use_texture_alpha = use_texture_alpha, | ||||
| 	paramtype = "light", | ||||
| 	paramtype2 = "facedir", | ||||
| 	is_ground_content = false, | ||||
| @@ -46,7 +49,7 @@ minetest.register_node("mesecons_button:button_off", { | ||||
| 	on_rightclick = function (pos, node) | ||||
| 		minetest.swap_node(pos, {name = "mesecons_button:button_on", param2=node.param2}) | ||||
| 		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) | ||||
| 	end, | ||||
| 	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_on.png" | ||||
| 		}, | ||||
| 	}, | ||||
| 	use_texture_alpha = use_texture_alpha, | ||||
| 	paramtype = "light", | ||||
| 	paramtype2 = "facedir", | ||||
| 	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", { | ||||
| 	params = "<name> <text>", | ||||
| 	description = "Say <text> to <name> privately", | ||||
| 	privs = {shout=true}, | ||||
| 	func = function(name, param) | ||||
| 		local found, _, target, message = param:find("^([^%s]+)%s+(.*)$") | ||||
| 		if found == nil then | ||||
| @@ -110,7 +111,7 @@ local function resolve_commands(commands, pos) | ||||
| 	local nearest, farthest = nil, nil | ||||
| 	local min_distance, max_distance = math.huge, -1 | ||||
| 	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 | ||||
| 			min_distance = distance | ||||
| 			nearest = player:get_player_name() | ||||
| @@ -174,7 +175,8 @@ end | ||||
| local function can_dig(pos, player) | ||||
| 	local meta = minetest.get_meta(pos) | ||||
| 	local owner = meta:get_string("owner") | ||||
| 	return owner == "" or owner == player:get_player_name() | ||||
| 	return owner == "" or owner == player:get_player_name() or | ||||
| 		minetest.check_player_privs(player, "protection_bypass") | ||||
| end | ||||
|  | ||||
| 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 | ||||
|  | ||||
| for i = 1, 4 do | ||||
| local groups = {} | ||||
| if i == 1 then | ||||
| 	groups = {bendy=2,snappy=1,dig_immediate=2} | ||||
| else | ||||
| 	groups = {bendy=2,snappy=1,dig_immediate=2, not_in_creative_inventory=1} | ||||
| end | ||||
| local delaytime = { 0.1, 0.3, 0.5, 1.0 } | ||||
|  | ||||
| local delaytime | ||||
| 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 | ||||
| for i = 1, 4 do | ||||
|  | ||||
| local boxes = { | ||||
| 	 { -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 } | ||||
| } | ||||
|  | ||||
| minetest.register_node("mesecons_delayer:delayer_off_"..tostring(i), { | ||||
| 	description = "Delayer", | ||||
| -- Delayer definition defaults | ||||
| local def = { | ||||
| 	drawtype = "nodebox", | ||||
| 	tiles = { | ||||
| 		"mesecons_delayer_off_"..tostring(i)..".png", | ||||
| 		"mesecons_delayer_bottom.png", | ||||
| 		"mesecons_delayer_ends_off.png", | ||||
| 		"mesecons_delayer_ends_off.png", | ||||
| 		"mesecons_delayer_sides_off.png", | ||||
| 		"mesecons_delayer_sides_off.png" | ||||
| 		}, | ||||
| 	inventory_image = "mesecons_delayer_off_1.png", | ||||
| 	wield_image = "mesecons_delayer_off_1.png", | ||||
| 	use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or nil, | ||||
| 	walkable = true, | ||||
| 	selection_box = { | ||||
| 		type = "fixed", | ||||
| @@ -83,26 +64,46 @@ minetest.register_node("mesecons_delayer:delayer_off_"..tostring(i), { | ||||
| 		type = "fixed", | ||||
| 		fixed = boxes | ||||
| 	}, | ||||
| 	groups = groups, | ||||
| 	paramtype = "light", | ||||
| 	paramtype2 = "facedir", | ||||
| 	sunlight_propagates = true, | ||||
| 	is_ground_content = false, | ||||
| 	drop = 'mesecons_delayer:delayer_off_1', | ||||
| 	on_punch = function (pos, node) | ||||
| 		if node.name=="mesecons_delayer:delayer_off_1" then | ||||
| 			minetest.swap_node(pos, {name = "mesecons_delayer:delayer_off_2", param2=node.param2}) | ||||
| 		elseif node.name=="mesecons_delayer:delayer_off_2" then | ||||
| 			minetest.swap_node(pos, {name = "mesecons_delayer:delayer_off_3", param2=node.param2}) | ||||
| 		elseif node.name=="mesecons_delayer:delayer_off_3" then | ||||
| 			minetest.swap_node(pos, {name = "mesecons_delayer:delayer_off_4", param2=node.param2}) | ||||
| 		elseif node.name=="mesecons_delayer:delayer_off_4" then | ||||
| 			minetest.swap_node(pos, {name = "mesecons_delayer:delayer_off_1", param2=node.param2}) | ||||
| 		end | ||||
| 	end, | ||||
| 	delayer_time = delaytime, | ||||
| 	delayer_onstate = "mesecons_delayer:delayer_on_"..tostring(i), | ||||
| 	delayer_time = delaytime[i], | ||||
| 	sounds = default.node_sound_stone_defaults(), | ||||
| 	on_blast = mesecon.on_blastnode, | ||||
| 	drop = "mesecons_delayer:delayer_off_1", | ||||
| } | ||||
|  | ||||
| -- Deactivated delayer definition defaults | ||||
| local off_groups = {bendy=2,snappy=1,dig_immediate=2} | ||||
| if i > 1 then | ||||
| 	off_groups.not_in_creative_inventory = 1 | ||||
| end | ||||
|  | ||||
| local off_state = { | ||||
| 	description = "Delayer", | ||||
| 	tiles = { | ||||
| 		"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 = { | ||||
| 		receptor = | ||||
| 		{ | ||||
| @@ -115,13 +116,15 @@ minetest.register_node("mesecons_delayer:delayer_off_"..tostring(i), { | ||||
| 			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) | ||||
|  | ||||
|  | ||||
| minetest.register_node("mesecons_delayer:delayer_on_"..tostring(i), { | ||||
| -- Activated delayer definition defaults | ||||
| local on_state = { | ||||
| 	description = "You hacker you", | ||||
| 	drawtype = "nodebox", | ||||
| 	tiles = { | ||||
| 		"mesecons_delayer_on_"..tostring(i)..".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_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}, | ||||
| 	paramtype = "light", | ||||
| 	paramtype2 = "facedir", | ||||
| 	sunlight_propagates = true, | ||||
| 	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}) | ||||
| 	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_on_"..tostring(i % 4 + 1), | ||||
| 			param2 = node.param2 | ||||
| 		}) | ||||
| 	end, | ||||
| 	delayer_time = delaytime, | ||||
| 	delayer_offstate = "mesecons_delayer:delayer_off_"..tostring(i), | ||||
| 	sounds = default.node_sound_stone_defaults(), | ||||
| 	mesecons = { | ||||
| 		receptor = | ||||
| 		{ | ||||
| @@ -171,8 +157,12 @@ minetest.register_node("mesecons_delayer:delayer_on_"..tostring(i), { | ||||
| 			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 | ||||
|  | ||||
| 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 | ||||
| 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 | ||||
| respond with the detected nodename or you can send any other string and it will | ||||
| set this string as the node 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: 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 == "") | ||||
| end | ||||
|  | ||||
| local function node_detector_send_node_name(pos, node, channel, meta) | ||||
| 	local distance = meta:get_int("distance") | ||||
| 	local distance_max = mesecon.setting("node_detector_distance_max", 10) | ||||
| 	if distance < 0 then distance = 0 end | ||||
| 	if distance > distance_max then distance = distance_max end | ||||
| 	local nodename = minetest.get_node( | ||||
| 		vector.subtract(pos, vector.multiply(minetest.facedir_to_dir(node.param2), distance + 1)) | ||||
| 	).name | ||||
|  | ||||
| 	digiline:receptor_send(pos, digiline.rules.default, channel, nodename) | ||||
| end | ||||
|  | ||||
| -- set player name when receiving a digiline signal on a specific channel | ||||
| local node_detector_digiline = { | ||||
| 	effector = { | ||||
| 		action = function(pos, node, channel, msg) | ||||
| 			local meta = minetest.get_meta(pos) | ||||
|  | ||||
| 			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 msg == GET_COMMAND then | ||||
| 				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) | ||||
| 			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 | ||||
| 				meta:set_string("scanname", msg) | ||||
| 				node_detector_make_formspec(pos) | ||||
| 				if msg == GET_COMMAND then | ||||
| 					node_detector_send_node_name(pos, node, channel, meta) | ||||
| 				else | ||||
| 					meta:set_string("scanname", msg) | ||||
| 					node_detector_make_formspec(pos) | ||||
| 				end | ||||
| 			end | ||||
| 		end, | ||||
| 	}, | ||||
| @@ -218,7 +239,7 @@ local node_detector_digiline = { | ||||
| } | ||||
|  | ||||
| local function after_place_node_detector(pos, placer) | ||||
| 	local placer_pos = placer:getpos() | ||||
| 	local placer_pos = placer:get_pos() | ||||
| 	if not placer_pos then | ||||
| 		return | ||||
| 	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}) | ||||
|  | ||||
| 	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 | ||||
| 		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 | ||||
|  | ||||
| @@ -73,16 +73,17 @@ meseconify_door("doors:door_wood") | ||||
| meseconify_door("doors:door_steel") | ||||
| meseconify_door("doors:door_glass") | ||||
| meseconify_door("doors:door_obsidian_glass") | ||||
| meseconify_door("xpanes:door_steel_bar") | ||||
|  | ||||
| -- Trapdoor | ||||
| local function trapdoor_switch(pos, node) | ||||
| 	local state = minetest.get_meta(pos):get_int("state") | ||||
|  | ||||
| 	if state == 1 then | ||||
| 		minetest.sound_play("doors_door_close", {pos = pos, gain = 0.3, max_hear_distance = 10}) | ||||
| 		minetest.sound_play("doors_door_close", { pos = pos, gain = 0.3, max_hear_distance = 10 }, true) | ||||
| 		minetest.set_node(pos, {name="doors:trapdoor", param2 = node.param2}) | ||||
| 	else | ||||
| 		minetest.sound_play("doors_door_open", {pos = pos, gain = 0.3, max_hear_distance = 10}) | ||||
| 		minetest.sound_play("doors_door_open", { pos = pos, gain = 0.3, max_hear_distance = 10 }, true) | ||||
| 		minetest.set_node(pos, {name="doors:trapdoor_open", param2 = node.param2}) | ||||
| 	end | ||||
|  | ||||
| @@ -110,6 +111,12 @@ if doors and doors.get then | ||||
| 	minetest.override_item("doors:trapdoor_open", override) | ||||
| 	minetest.override_item("doors:trapdoor_steel", override) | ||||
| 	minetest.override_item("doors:trapdoor_steel_open", override) | ||||
|  | ||||
| 	if minetest.registered_items["xpanes:trapdoor_steel_bar"] then | ||||
| 		minetest.override_item("xpanes:trapdoor_steel_bar", override) | ||||
| 		minetest.override_item("xpanes:trapdoor_steel_bar_open", override) | ||||
| 	end | ||||
|  | ||||
| else | ||||
| 	if minetest.registered_nodes["doors:trapdoor"] then | ||||
| 		minetest.override_item("doors:trapdoor", { | ||||
|   | ||||
							
								
								
									
										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 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 = { | ||||
| 		type = "fixed", | ||||
| 		fixed = { -16/32, -16/32, -16/32, 5/32, -12/32, 5/32 }, | ||||
| @@ -25,14 +18,11 @@ local corner_get_rules = function (node) | ||||
| end | ||||
|  | ||||
| minetest.register_node("mesecons_extrawires:corner_on", { | ||||
| 	drawtype = "nodebox", | ||||
| 	drawtype = "mesh", | ||||
| 	mesh = "mesecons_extrawires_corner.obj", | ||||
| 	tiles = { | ||||
| 		"jeija_insulated_wire_curved_tb_on.png", | ||||
| 		"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" | ||||
| 		{ name = "jeija_insulated_wire_sides_on.png", backface_culling = true }, | ||||
| 		{ name = "jeija_insulated_wire_ends_on.png", backface_culling = true }, | ||||
| 	}, | ||||
| 	paramtype = "light", | ||||
| 	paramtype2 = "facedir", | ||||
| @@ -40,7 +30,6 @@ minetest.register_node("mesecons_extrawires:corner_on", { | ||||
| 	walkable = false, | ||||
| 	sunlight_propagates = true, | ||||
| 	selection_box = corner_selectionbox, | ||||
| 	node_box = corner_nodebox, | ||||
| 	groups = {dig_immediate = 3, not_in_creative_inventory = 1}, | ||||
| 	drop = "mesecons_extrawires:corner_off", | ||||
| 	sounds = default.node_sound_defaults(), | ||||
| @@ -55,15 +44,12 @@ minetest.register_node("mesecons_extrawires:corner_on", { | ||||
| }) | ||||
|  | ||||
| minetest.register_node("mesecons_extrawires:corner_off", { | ||||
| 	drawtype = "nodebox", | ||||
| 	drawtype = "mesh", | ||||
| 	description = "Insulated Mesecon Corner", | ||||
| 	mesh = "mesecons_extrawires_corner.obj", | ||||
| 	tiles = { | ||||
| 		"jeija_insulated_wire_curved_tb_off.png", | ||||
| 		"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" | ||||
| 		{ name = "jeija_insulated_wire_sides_off.png", backface_culling = true }, | ||||
| 		{ name = "jeija_insulated_wire_ends_off.png", backface_culling = true }, | ||||
| 	}, | ||||
| 	paramtype = "light", | ||||
| 	paramtype2 = "facedir", | ||||
| @@ -71,7 +57,6 @@ minetest.register_node("mesecons_extrawires:corner_off", { | ||||
| 	walkable = false, | ||||
| 	sunlight_propagates = true, | ||||
| 	selection_box = corner_selectionbox, | ||||
| 	node_box = corner_nodebox, | ||||
| 	groups = {dig_immediate = 3}, | ||||
| 	sounds = default.node_sound_defaults(), | ||||
| 	mesecons = {conductor = | ||||
| @@ -87,8 +72,7 @@ minetest.register_node("mesecons_extrawires:corner_off", { | ||||
| minetest.register_craft({ | ||||
| 	output = "mesecons_extrawires:corner_off 3", | ||||
| 	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").."/tjunction.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").."/mesewire.lua"); | ||||
|   | ||||
| @@ -18,7 +18,7 @@ minetest.override_item("default:mese", { | ||||
|  | ||||
| -- Copy node definition of powered mese from normal mese | ||||
| -- 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", | ||||
| 	light_source = 5, | ||||
| 	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({ | ||||
| 	output = "mesecons_extrawires:tjunction_off 3", | ||||
| 	recipe = { | ||||
| 		{"", "", ""}, | ||||
| 		{"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({ | ||||
| 	output = "mesecons_extrawires:vertical_off 3", | ||||
| 	recipe = { | ||||
| 		{"mesecons:wire_00000000_off"}, | ||||
| 		{"mesecons:wire_00000000_off"}, | ||||
| 		{"mesecons:wire_00000000_off"} | ||||
| 		{"group:mesecon_conductor_craftable"}, | ||||
| 		{"group:mesecon_conductor_craftable"}, | ||||
| 		{"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 |