Tags support (#107)
Signed-off-by: Slava Zanko <slavazanko@gmail.com> Co-authored-by: Slava Zanko <slava.zanko@godel.shellenergy.co.uk> Co-authored-by: BuckarooBanzay <BuckarooBanzay@users.noreply.github.com> Co-authored-by: OgelGames <olliverdc28@gmail.com>
							
								
								
									
										20
									
								
								crafts.lua
									
									
									
									
									
								
							
							
						
						@@ -223,6 +223,26 @@ if pipeworks.enable_mese_tube then
 | 
			
		||||
	})
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
if pipeworks.enable_item_tags and pipeworks.enable_tag_tube then
 | 
			
		||||
	minetest.register_craft( {
 | 
			
		||||
		output = "pipeworks:tag_tube_000000 2",
 | 
			
		||||
		recipe = {
 | 
			
		||||
			{ "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" },
 | 
			
		||||
			{ materials.book, materials.mese_crystal, materials.book },
 | 
			
		||||
			{ "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" }
 | 
			
		||||
		},
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	minetest.register_craft( {
 | 
			
		||||
		type = "shapeless",
 | 
			
		||||
		output = "pipeworks:tag_tube_000000",
 | 
			
		||||
		recipe = {
 | 
			
		||||
			"pipeworks:mese_tube_000000",
 | 
			
		||||
			materials.book,
 | 
			
		||||
		},
 | 
			
		||||
	})
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
if pipeworks.enable_sand_tube then
 | 
			
		||||
	minetest.register_craft( {
 | 
			
		||||
		output = "pipeworks:sand_tube_1 2",
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,8 @@ local prefix = "pipeworks_"
 | 
			
		||||
 | 
			
		||||
local settings = {
 | 
			
		||||
	enable_pipes = true,
 | 
			
		||||
	enable_item_tags = true,
 | 
			
		||||
	enable_tag_tube = true,
 | 
			
		||||
	enable_lowpoly = false,
 | 
			
		||||
	enable_autocrafter = true,
 | 
			
		||||
	enable_deployer = true,
 | 
			
		||||
 
 | 
			
		||||
@@ -14,20 +14,29 @@ local function set_filter_formspec(data, meta)
 | 
			
		||||
 | 
			
		||||
	local formspec
 | 
			
		||||
	if data.digiline then
 | 
			
		||||
		local form_height = 3
 | 
			
		||||
		if pipeworks.enable_item_tags then
 | 
			
		||||
			form_height = 4
 | 
			
		||||
		end
 | 
			
		||||
		formspec =
 | 
			
		||||
			"size[8.5,3]"..
 | 
			
		||||
			("size[8.5,%f]"):format(form_height) ..
 | 
			
		||||
			"item_image[0.2,0;1,1;pipeworks:"..data.name.."]"..
 | 
			
		||||
			"label[1.2,0.2;"..minetest.formspec_escape(itemname).."]"..
 | 
			
		||||
			"field[0.5,1.6;4.6,1;channel;"..S("Channel")..";${channel}]"..
 | 
			
		||||
			"button[4.8,1.3;1.5,1;set_channel;"..S("Set").."]"..
 | 
			
		||||
			fs_helpers.cycling_button(meta, "button[0.2,2.3;4.05,1", "slotseq_mode",
 | 
			
		||||
			fs_helpers.cycling_button(meta, ("button[0.2,%f;4.05,1"):format(form_height - 0.7), "slotseq_mode",
 | 
			
		||||
				{S("Sequence slots by Priority"),
 | 
			
		||||
				 S("Sequence slots Randomly"),
 | 
			
		||||
				 S("Sequence slots by Rotation")})..
 | 
			
		||||
			fs_helpers.cycling_button(meta, "button[4.25,2.3;4.05,1", "exmatch_mode",
 | 
			
		||||
			fs_helpers.cycling_button(meta, ("button[4.25,%f;4.05,1"):format(form_height - 0.7), "exmatch_mode",
 | 
			
		||||
				{S("Exact match - off"),
 | 
			
		||||
				 S("Exact match - on")})..
 | 
			
		||||
			"button_exit[6.3,1.3;2,1;close;"..S("Close").."]"
 | 
			
		||||
			("button_exit[6.3,%f;2,1;close;" .. S("Close") .. "]"):format(form_height - 1.7)
 | 
			
		||||
		if pipeworks.enable_item_tags then
 | 
			
		||||
			formspec = formspec ..
 | 
			
		||||
				("field[0.5,%f;4.6,1;item_tags;"):format(form_height - 1.4) .. S("Item Tags") .. ";${item_tags}]" ..
 | 
			
		||||
				("button[4.8,%f;1.5,1;set_item_tags;"):format(form_height - 1.7) .. S("Set") .. "]"
 | 
			
		||||
		end
 | 
			
		||||
	else
 | 
			
		||||
		local exmatch_button = ""
 | 
			
		||||
		if data.stackwise then
 | 
			
		||||
@@ -62,6 +71,11 @@ local function set_filter_formspec(data, meta)
 | 
			
		||||
			exmatch_button..
 | 
			
		||||
			pipeworks.fs_helpers.get_inv(6)..
 | 
			
		||||
			"listring[]"
 | 
			
		||||
		if pipeworks.enable_item_tags then
 | 
			
		||||
			formspec = formspec ..
 | 
			
		||||
				"field[5.8,0.5;3,0.8;item_tags;" .. S("Item Tags") .. ";${item_tags}]" ..
 | 
			
		||||
				"button[9,0.3;1,1.1;set_item_tags;" .. S("Set") .. "]"
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	meta:set_string("formspec", formspec)
 | 
			
		||||
end
 | 
			
		||||
@@ -123,6 +137,7 @@ local function punch_filter(data, filtpos, filtnode, msg)
 | 
			
		||||
	local slotseq_mode
 | 
			
		||||
	local exmatch_mode
 | 
			
		||||
 | 
			
		||||
	local item_tags = pipeworks.sanitize_tags(filtmeta:get_string("item_tags"))
 | 
			
		||||
	local filters = {}
 | 
			
		||||
	if data.digiline then
 | 
			
		||||
		local function add_filter(name, group, count, wear, metadata)
 | 
			
		||||
@@ -186,6 +201,12 @@ local function punch_filter(data, filtpos, filtnode, msg)
 | 
			
		||||
				set_filter_formspec(data, filtmeta)
 | 
			
		||||
			end
 | 
			
		||||
 | 
			
		||||
			if type(msg.tags) == "table" then
 | 
			
		||||
				item_tags = pipeworks.sanitize_tags(msg.tags)
 | 
			
		||||
			elseif type(msg.tag) == "string" then
 | 
			
		||||
				item_tags = pipeworks.sanitize_tags({msg.tag})
 | 
			
		||||
			end
 | 
			
		||||
 | 
			
		||||
			if msg.nofire then
 | 
			
		||||
				return
 | 
			
		||||
			end
 | 
			
		||||
@@ -339,7 +360,7 @@ local function punch_filter(data, filtpos, filtnode, msg)
 | 
			
		||||
				local pos = vector.add(frompos, vector.multiply(dir, 1.4))
 | 
			
		||||
				local start_pos = vector.add(frompos, dir)
 | 
			
		||||
				pipeworks.tube_inject_item(pos, start_pos, dir, item,
 | 
			
		||||
					fakePlayer:get_player_name())
 | 
			
		||||
					fakePlayer:get_player_name(), item_tags)
 | 
			
		||||
				return true -- only fire one item, please
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
@@ -457,6 +478,10 @@ for _, data in ipairs({
 | 
			
		||||
			end
 | 
			
		||||
 | 
			
		||||
			local meta = minetest.get_meta(pos)
 | 
			
		||||
			if pipeworks.enable_item_tags and fields.item_tags and (fields.key_enter_field == "item_tags" or fields.set_item_tags) then
 | 
			
		||||
				local tags = pipeworks.sanitize_tags(fields.item_tags)
 | 
			
		||||
				meta:set_string("item_tags", table.concat(tags, ","))
 | 
			
		||||
			end
 | 
			
		||||
			--meta:set_int("slotseq_index", 1)
 | 
			
		||||
			set_filter_formspec(data, meta)
 | 
			
		||||
			set_filter_infotext(data, meta)
 | 
			
		||||
@@ -478,6 +503,10 @@ for _, data in ipairs({
 | 
			
		||||
			fs_helpers.on_receive_fields(pos, fields)
 | 
			
		||||
			local meta = minetest.get_meta(pos)
 | 
			
		||||
			meta:set_int("slotseq_index", 1)
 | 
			
		||||
			if pipeworks.enable_item_tags and fields.item_tags and (fields.key_enter_field == "item_tags" or fields.set_item_tags) then
 | 
			
		||||
				local tags = pipeworks.sanitize_tags(fields.item_tags)
 | 
			
		||||
				meta:set_string("item_tags", table.concat(tags, ","))
 | 
			
		||||
			end
 | 
			
		||||
			set_filter_formspec(data, meta)
 | 
			
		||||
			set_filter_infotext(data, meta)
 | 
			
		||||
		end
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								init.lua
									
									
									
									
									
								
							
							
						
						@@ -67,6 +67,7 @@ dofile(pipeworks.modpath.."/tubes/sorting.lua")
 | 
			
		||||
dofile(pipeworks.modpath.."/tubes/signal.lua")
 | 
			
		||||
dofile(pipeworks.modpath.."/tubes/embedded_tube.lua")
 | 
			
		||||
dofile(pipeworks.modpath.."/tubes/pane_embedded_tube.lua")
 | 
			
		||||
dofile(pipeworks.modpath.."/tubes/tags.lua")
 | 
			
		||||
 | 
			
		||||
if pipeworks.enable_teleport_tube then
 | 
			
		||||
	dofile(pipeworks.modpath.."/tubes/teleport.lua")
 | 
			
		||||
 
 | 
			
		||||
@@ -3,11 +3,36 @@ local enable_max_limit = minetest.settings:get_bool("pipeworks_enable_items_per_
 | 
			
		||||
local max_tube_limit = tonumber(minetest.settings:get("pipeworks_max_items_per_tube")) or 30
 | 
			
		||||
if enable_max_limit == nil then enable_max_limit = true end
 | 
			
		||||
 | 
			
		||||
if pipeworks.enable_item_tags then
 | 
			
		||||
	local max_tag_length = tonumber(minetest.settings:get("pipeworks_max_item_tag_length")) or 32
 | 
			
		||||
	local max_tags = tonumber(minetest.settings:get("pipeworks_max_item_tags")) or 16
 | 
			
		||||
 | 
			
		||||
	function pipeworks.sanitize_tags(tags)
 | 
			
		||||
		if type(tags) == "string" then
 | 
			
		||||
			tags = tags:split(",")
 | 
			
		||||
		end
 | 
			
		||||
		local sanitized = {}
 | 
			
		||||
		for i, tag in ipairs(tags) do
 | 
			
		||||
			if type(tag) == "string" then
 | 
			
		||||
				tag = tag:gsub("[%s,]", "")  -- Remove whitespace and commas
 | 
			
		||||
				tag = tag:gsub("%$%b%{%}", "")  -- Remove special ${key} values
 | 
			
		||||
				if tag ~= "" then
 | 
			
		||||
					table.insert(sanitized, tag:sub(1, max_tag_length))
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
			if #sanitized >= max_tags then
 | 
			
		||||
				break
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
		return sanitized
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function pipeworks.tube_item(pos, item)
 | 
			
		||||
	error("obsolete pipeworks.tube_item() called; change caller to use pipeworks.tube_inject_item() instead")
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function pipeworks.tube_inject_item(pos, start_pos, velocity, item, owner)
 | 
			
		||||
function pipeworks.tube_inject_item(pos, start_pos, velocity, item, owner, tags)
 | 
			
		||||
	-- Take item in any format
 | 
			
		||||
	local stack = ItemStack(item)
 | 
			
		||||
	local obj = luaentity.add_entity(pos, "pipeworks:tubed_item")
 | 
			
		||||
@@ -15,6 +40,7 @@ function pipeworks.tube_inject_item(pos, start_pos, velocity, item, owner)
 | 
			
		||||
	obj.start_pos = vector.new(start_pos)
 | 
			
		||||
	obj:set_velocity(velocity)
 | 
			
		||||
	obj.owner = owner
 | 
			
		||||
	obj.tags = tags
 | 
			
		||||
	--obj:set_color("red") -- todo: this is test-only code
 | 
			
		||||
	return obj
 | 
			
		||||
end
 | 
			
		||||
@@ -79,13 +105,14 @@ end
 | 
			
		||||
 | 
			
		||||
-- compatibility behaviour for the existing can_go() callbacks,
 | 
			
		||||
-- which can only specify a list of possible positions.
 | 
			
		||||
local function go_next_compat(pos, cnode, cmeta, cycledir, vel, stack, owner)
 | 
			
		||||
local function go_next_compat(pos, cnode, cmeta, cycledir, vel, stack, owner, tags)
 | 
			
		||||
	local next_positions = {}
 | 
			
		||||
	local max_priority = 0
 | 
			
		||||
	local can_go
 | 
			
		||||
 | 
			
		||||
	if minetest.registered_nodes[cnode.name] and minetest.registered_nodes[cnode.name].tube and minetest.registered_nodes[cnode.name].tube.can_go then
 | 
			
		||||
		can_go = minetest.registered_nodes[cnode.name].tube.can_go(pos, cnode, vel, stack)
 | 
			
		||||
	local def = minetest.registered_nodes[cnode.name]
 | 
			
		||||
	if def and def.tube and def.tube.can_go then
 | 
			
		||||
		can_go = def.tube.can_go(pos, cnode, vel, stack, tags)
 | 
			
		||||
	else
 | 
			
		||||
		local adjlist_string = minetest.get_meta(pos):get_string("adjlist")
 | 
			
		||||
		local adjlist = minetest.deserialize(adjlist_string) or default_adjlist -- backward compat: if not found, use old behavior: all directions
 | 
			
		||||
@@ -144,7 +171,7 @@ end
 | 
			
		||||
-- * a "multi-mode" data table (or nil if N/A) where a stack was split apart.
 | 
			
		||||
--	if this is not nil, the luaentity spawns new tubed items for each new fragment stack,
 | 
			
		||||
--	then deletes itself (i.e. the original item stack).
 | 
			
		||||
local function go_next(pos, velocity, stack, owner)
 | 
			
		||||
local function go_next(pos, velocity, stack, owner, tags)
 | 
			
		||||
	local cnode = minetest.get_node(pos)
 | 
			
		||||
	local cmeta = minetest.get_meta(pos)
 | 
			
		||||
	local speed = math.abs(velocity.x + velocity.y + velocity.z)
 | 
			
		||||
@@ -172,7 +199,7 @@ local function go_next(pos, velocity, stack, owner)
 | 
			
		||||
	-- n is the new value of the cycle counter.
 | 
			
		||||
	-- XXX: this probably needs cleaning up after being split out,
 | 
			
		||||
	-- seven args is a bit too many
 | 
			
		||||
	local n, found, new_velocity, multimode = go_next_compat(pos, cnode, cmeta, cycledir, vel, stack, owner)
 | 
			
		||||
	local n, found, new_velocity, multimode = go_next_compat(pos, cnode, cmeta, cycledir, vel, stack, owner, tags)
 | 
			
		||||
 | 
			
		||||
	-- if not using output cycling,
 | 
			
		||||
	-- don't update the field so it stays the same for the next item.
 | 
			
		||||
@@ -276,6 +303,7 @@ luaentity.register_entity("pipeworks:tubed_item", {
 | 
			
		||||
	color_entity = nil,
 | 
			
		||||
	color = nil,
 | 
			
		||||
	start_pos = nil,
 | 
			
		||||
	tags = nil,
 | 
			
		||||
 | 
			
		||||
	set_item = function(self, item)
 | 
			
		||||
		local itemstring = ItemStack(item):to_string() -- Accept any input format
 | 
			
		||||
@@ -337,8 +365,9 @@ luaentity.register_entity("pipeworks:tubed_item", {
 | 
			
		||||
		local node = minetest.get_node(self.start_pos)
 | 
			
		||||
		if minetest.get_item_group(node.name, "tubedevice_receiver") == 1 then
 | 
			
		||||
			local leftover
 | 
			
		||||
			if minetest.registered_nodes[node.name].tube and minetest.registered_nodes[node.name].tube.insert_object then
 | 
			
		||||
				leftover = minetest.registered_nodes[node.name].tube.insert_object(self.start_pos, node, stack, vel, self.owner)
 | 
			
		||||
			local def = minetest.registered_nodes[node.name]
 | 
			
		||||
			if def.tube and def.tube.insert_object then
 | 
			
		||||
				leftover = def.tube.insert_object(self.start_pos, node, stack, vel, self.owner)
 | 
			
		||||
			else
 | 
			
		||||
				leftover = stack
 | 
			
		||||
			end
 | 
			
		||||
@@ -353,7 +382,14 @@ luaentity.register_entity("pipeworks:tubed_item", {
 | 
			
		||||
			return
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		local found_next, new_velocity, multimode = go_next(self.start_pos, velocity, stack, self.owner) -- todo: color
 | 
			
		||||
		local tags
 | 
			
		||||
		if pipeworks.enable_item_tags then
 | 
			
		||||
			tags = self.tags or {}
 | 
			
		||||
		end
 | 
			
		||||
		local found_next, new_velocity, multimode = go_next(self.start_pos, velocity, stack, self.owner, tags) -- todo: color
 | 
			
		||||
		if pipeworks.enable_item_tags then
 | 
			
		||||
			self.tags = #tags > 0 and pipeworks.sanitize_tags(tags) or nil
 | 
			
		||||
		end
 | 
			
		||||
		local rev_vel = vector.multiply(velocity, -1)
 | 
			
		||||
		local rev_dir = vector.direction(self.start_pos,vector.add(self.start_pos,rev_vel))
 | 
			
		||||
		local rev_node = minetest.get_node(vector.round(vector.add(self.start_pos,rev_dir)))
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								textures/pipeworks_tag_tube_end.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 875 B  | 
							
								
								
									
										
											BIN
										
									
								
								textures/pipeworks_tag_tube_inv.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 496 B  | 
							
								
								
									
										
											BIN
										
									
								
								textures/pipeworks_tag_tube_noctr_1.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 768 B  | 
							
								
								
									
										
											BIN
										
									
								
								textures/pipeworks_tag_tube_noctr_2.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 744 B  | 
							
								
								
									
										
											BIN
										
									
								
								textures/pipeworks_tag_tube_noctr_3.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 743 B  | 
							
								
								
									
										
											BIN
										
									
								
								textures/pipeworks_tag_tube_noctr_4.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 747 B  | 
							
								
								
									
										
											BIN
										
									
								
								textures/pipeworks_tag_tube_noctr_5.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 769 B  | 
							
								
								
									
										
											BIN
										
									
								
								textures/pipeworks_tag_tube_noctr_6.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 753 B  | 
							
								
								
									
										
											BIN
										
									
								
								textures/pipeworks_tag_tube_plain_1.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 864 B  | 
							
								
								
									
										
											BIN
										
									
								
								textures/pipeworks_tag_tube_plain_2.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 865 B  | 
							
								
								
									
										
											BIN
										
									
								
								textures/pipeworks_tag_tube_plain_3.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 863 B  | 
							
								
								
									
										
											BIN
										
									
								
								textures/pipeworks_tag_tube_plain_4.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 864 B  | 
							
								
								
									
										
											BIN
										
									
								
								textures/pipeworks_tag_tube_plain_5.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 871 B  | 
							
								
								
									
										
											BIN
										
									
								
								textures/pipeworks_tag_tube_plain_6.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 860 B  | 
							
								
								
									
										
											BIN
										
									
								
								textures/pipeworks_tag_tube_short.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 457 B  | 
@@ -945,7 +945,7 @@ for white  = 0, 1 do
 | 
			
		||||
		tube = {
 | 
			
		||||
			connect_sides = {front = 1, back = 1, left = 1, right = 1, top = 1, bottom = 1},
 | 
			
		||||
			priority = 50,
 | 
			
		||||
			can_go = function(pos, node, velocity, stack)
 | 
			
		||||
			can_go = function(pos, node, velocity, stack, tags)
 | 
			
		||||
				local src = {name = nil}
 | 
			
		||||
				-- add color of the incoming tube explicitly; referring to rules, in case they change later
 | 
			
		||||
				for _, rule in pairs(rules) do
 | 
			
		||||
@@ -960,12 +960,33 @@ for white  = 0, 1 do
 | 
			
		||||
					itemstring = stack:to_string(),
 | 
			
		||||
					item = stack:to_table(),
 | 
			
		||||
					velocity = velocity,
 | 
			
		||||
					tags = table.copy(tags),
 | 
			
		||||
					side = src.name,
 | 
			
		||||
				})
 | 
			
		||||
				if not succ or type(msg) ~= "string" then
 | 
			
		||||
				if not succ then
 | 
			
		||||
					return go_back(velocity)
 | 
			
		||||
				end
 | 
			
		||||
				local r = rules[msg]
 | 
			
		||||
				return r and {r} or go_back(velocity)
 | 
			
		||||
				if type(msg) == "string" then
 | 
			
		||||
					local side = rules[msg]
 | 
			
		||||
					return side and {side} or go_back(velocity)
 | 
			
		||||
				elseif type(msg) == "table" then
 | 
			
		||||
					if pipeworks.enable_item_tags then
 | 
			
		||||
						local new_tags
 | 
			
		||||
						if type(msg.tags) == "table" then
 | 
			
		||||
							new_tags = msg.tags
 | 
			
		||||
						elseif type(msg.tag) == "string" then
 | 
			
		||||
							new_tags = {msg.tag}
 | 
			
		||||
						end
 | 
			
		||||
						if new_tags then
 | 
			
		||||
							for i=1, math.max(#tags, #new_tags) do
 | 
			
		||||
								tags[i] = new_tags[i]
 | 
			
		||||
							end
 | 
			
		||||
						end
 | 
			
		||||
					end
 | 
			
		||||
					local side = rules[msg.side]
 | 
			
		||||
					return side and {side} or go_back(velocity)
 | 
			
		||||
				end
 | 
			
		||||
				return go_back(velocity)
 | 
			
		||||
			end,
 | 
			
		||||
		},
 | 
			
		||||
		after_place_node = pipeworks.after_place,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										139
									
								
								tubes/tags.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,139 @@
 | 
			
		||||
local S = minetest.get_translator("pipeworks")
 | 
			
		||||
local fs_helpers = pipeworks.fs_helpers
 | 
			
		||||
 | 
			
		||||
if not pipeworks.enable_item_tags or not pipeworks.enable_tag_tube then return end
 | 
			
		||||
 | 
			
		||||
local help_text = minetest.formspec_escape(
 | 
			
		||||
	S("Separate multiple tags using commas.").."\n"..
 | 
			
		||||
	S("Use \"<none>\" to match items without tags.")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
local update_formspec = function(pos)
 | 
			
		||||
	local meta = minetest.get_meta(pos)
 | 
			
		||||
	local buttons_formspec = ""
 | 
			
		||||
	for i = 0, 5 do
 | 
			
		||||
		buttons_formspec = buttons_formspec .. fs_helpers.cycling_button(meta,
 | 
			
		||||
			"image_button[9," .. (i + (i * 0.25) + 0.5) .. ";1,0.6", "l" .. (i + 1) .. "s",
 | 
			
		||||
			{
 | 
			
		||||
				pipeworks.button_off,
 | 
			
		||||
				pipeworks.button_on
 | 
			
		||||
			}
 | 
			
		||||
		)
 | 
			
		||||
	end
 | 
			
		||||
	local size = "10.2,9"
 | 
			
		||||
	meta:set_string("formspec",
 | 
			
		||||
		"formspec_version[2]" ..
 | 
			
		||||
		"size[" .. size .. "]" ..
 | 
			
		||||
		pipeworks.fs_helpers.get_prepends(size) ..
 | 
			
		||||
		"field[1.5,0.25;7.25,1;tags1;;${tags1}]" ..
 | 
			
		||||
		"field[1.5,1.5;7.25,1;tags2;;${tags2}]" ..
 | 
			
		||||
		"field[1.5,2.75;7.25,1;tags3;;${tags3}]" ..
 | 
			
		||||
		"field[1.5,4.0;7.25,1;tags4;;${tags4}]" ..
 | 
			
		||||
		"field[1.5,5.25;7.25,1;tags5;;${tags5}]" ..
 | 
			
		||||
		"field[1.5,6.5;7.25,1;tags6;;${tags6}]" ..
 | 
			
		||||
 | 
			
		||||
		"image[0.22,0.25;1,1;pipeworks_white.png]" ..
 | 
			
		||||
		"image[0.22,1.50;1,1;pipeworks_black.png]" ..
 | 
			
		||||
		"image[0.22,2.75;1,1;pipeworks_green.png]" ..
 | 
			
		||||
		"image[0.22,4.00;1,1;pipeworks_yellow.png]" ..
 | 
			
		||||
		"image[0.22,5.25;1,1;pipeworks_blue.png]" ..
 | 
			
		||||
		"image[0.22,6.50;1,1;pipeworks_red.png]" ..
 | 
			
		||||
		buttons_formspec ..
 | 
			
		||||
		"label[0.22,7.9;"..help_text.."]"..
 | 
			
		||||
		"button[7.25,7.8;1.5,0.8;set_item_tags;" .. S("Set") .. "]"
 | 
			
		||||
	)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
pipeworks.register_tube("pipeworks:tag_tube", {
 | 
			
		||||
	description = S("Tag Sorting Pneumatic Tube Segment"),
 | 
			
		||||
	inventory_image = "pipeworks_tag_tube_inv.png",
 | 
			
		||||
	noctr = { "pipeworks_tag_tube_noctr_1.png", "pipeworks_tag_tube_noctr_2.png", "pipeworks_tag_tube_noctr_3.png",
 | 
			
		||||
		"pipeworks_tag_tube_noctr_4.png", "pipeworks_tag_tube_noctr_5.png", "pipeworks_tag_tube_noctr_6.png" },
 | 
			
		||||
	plain = { "pipeworks_tag_tube_plain_1.png", "pipeworks_tag_tube_plain_2.png", "pipeworks_tag_tube_plain_3.png",
 | 
			
		||||
		"pipeworks_tag_tube_plain_4.png", "pipeworks_tag_tube_plain_5.png", "pipeworks_tag_tube_plain_6.png" },
 | 
			
		||||
	ends = { "pipeworks_tag_tube_end.png" },
 | 
			
		||||
	short = "pipeworks_tag_tube_short.png",
 | 
			
		||||
	no_facedir = true, -- Must use old tubes, since the textures are rotated with 6d ones
 | 
			
		||||
	node_def = {
 | 
			
		||||
		tube = {
 | 
			
		||||
			can_go = function(pos, node, velocity, stack, tags)
 | 
			
		||||
				local tbl, tbln = {}, 0
 | 
			
		||||
				local found, foundn = {}, 0
 | 
			
		||||
				local meta = minetest.get_meta(pos)
 | 
			
		||||
				local tag_hash = {}
 | 
			
		||||
				if #tags > 0 then
 | 
			
		||||
					for _,tag in ipairs(tags) do
 | 
			
		||||
						tag_hash[tag] = true
 | 
			
		||||
					end
 | 
			
		||||
				else
 | 
			
		||||
					tag_hash["<none>"] = true  -- Matches items without tags
 | 
			
		||||
				end
 | 
			
		||||
				for i, vect in ipairs(pipeworks.meseadjlist) do
 | 
			
		||||
					local npos = vector.add(pos, vect)
 | 
			
		||||
					local node = minetest.get_node(npos)
 | 
			
		||||
					local reg_node = minetest.registered_nodes[node.name]
 | 
			
		||||
					if meta:get_int("l" .. i .. "s") == 1 and reg_node then
 | 
			
		||||
						local tube_def = reg_node.tube
 | 
			
		||||
						if not tube_def or not tube_def.can_insert or
 | 
			
		||||
							tube_def.can_insert(npos, node, stack, vect) then
 | 
			
		||||
							local side_tags = meta:get_string("tags" .. i)
 | 
			
		||||
							if side_tags ~= "" then
 | 
			
		||||
								side_tags = pipeworks.sanitize_tags(side_tags)
 | 
			
		||||
								for _,tag in ipairs(side_tags) do
 | 
			
		||||
									if tag_hash[tag] then
 | 
			
		||||
										foundn = foundn + 1
 | 
			
		||||
										found[foundn] = vect
 | 
			
		||||
										break
 | 
			
		||||
									end
 | 
			
		||||
								end
 | 
			
		||||
							else
 | 
			
		||||
								tbln = tbln + 1
 | 
			
		||||
								tbl[tbln] = vect
 | 
			
		||||
							end
 | 
			
		||||
						end
 | 
			
		||||
					end
 | 
			
		||||
				end
 | 
			
		||||
				return (foundn > 0) and found or tbl
 | 
			
		||||
			end
 | 
			
		||||
		},
 | 
			
		||||
		on_construct = function(pos)
 | 
			
		||||
			local meta = minetest.get_meta(pos)
 | 
			
		||||
			for i = 1, 6 do
 | 
			
		||||
				meta:set_int("l" .. tostring(i) .. "s", 1)
 | 
			
		||||
			end
 | 
			
		||||
			update_formspec(pos)
 | 
			
		||||
			meta:set_string("infotext", S("Tag sorting pneumatic tube"))
 | 
			
		||||
		end,
 | 
			
		||||
		after_place_node = function(pos, placer, itemstack, pointed_thing)
 | 
			
		||||
			if placer and placer:is_player() and placer:get_player_control().aux1 then
 | 
			
		||||
				local meta = minetest.get_meta(pos)
 | 
			
		||||
				for i = 1, 6 do
 | 
			
		||||
					meta:set_int("l" .. tostring(i) .. "s", 0)
 | 
			
		||||
				end
 | 
			
		||||
				update_formspec(pos)
 | 
			
		||||
			end
 | 
			
		||||
			return pipeworks.after_place(pos, placer, itemstack, pointed_thing)
 | 
			
		||||
		end,
 | 
			
		||||
		on_receive_fields = function(pos, formname, fields, sender)
 | 
			
		||||
			if (fields.quit and not fields.key_enter_field)
 | 
			
		||||
				or not pipeworks.may_configure(pos, sender) then
 | 
			
		||||
				return
 | 
			
		||||
			end
 | 
			
		||||
 | 
			
		||||
			local meta = minetest.get_meta(pos)
 | 
			
		||||
			for i = 1, 6 do
 | 
			
		||||
				local field_name = "tags" .. tostring(i)
 | 
			
		||||
				if fields[field_name] then
 | 
			
		||||
					local tags = pipeworks.sanitize_tags(fields[field_name])
 | 
			
		||||
					meta:set_string(field_name, table.concat(tags, ","))
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
 | 
			
		||||
			fs_helpers.on_receive_fields(pos, fields)
 | 
			
		||||
			update_formspec(pos)
 | 
			
		||||
		end,
 | 
			
		||||
		can_dig = function(pos, player)
 | 
			
		||||
			return true
 | 
			
		||||
		end,
 | 
			
		||||
	},
 | 
			
		||||
})
 | 
			
		||||